Skip to main content

Setup & Installation

Get Sandbox Credentials

Contact your Ealyx account manager or email info@ealyx.com with:

  • Company name and technical contact
  • Webhook base URL (staging/production)
  • Integration timeline

You'll receive:

  • Sandbox environment URL
  • ClientId and ClientSecret
  • Username and Password

Keep your credentials secure and do not expose them to the public. Once you have completed the integration, you can request production credentials from your Ealyx account manager.

Store Configuration Values

You'll need to store the credentials and configuration values you received. How you store them is entirely up to you—environment variables, .env file, configuration database, encrypted storage, or any other secure method. The important part is that you keep them secure and accessible for use in the API calls that follow.

Configuration values to save

  • {CLIENT_ID} - Your platform's unique identifier
  • {CLIENT_SECRET} - Your secure key for authentication
  • {USERNAME} - Admin account username
  • {PASSWORD} - Admin account password
  • {API_BASE_URL} - API base URL (Sandbox: https://api.stg.ealyx.tech or Production: https://api.ealyx.tech)
  • {ASSETS_URL} - CDN base URL (Sandbox: https://cdn.stg.ealyx.tech or Production: https://cdn.ealyx.tech)

Example storage options

Environment Variables (if using .env file or system variables)

EALYX_CLIENT_ID="your_client_id"
EALYX_CLIENT_SECRET="your_client_secret"
EALYX_USERNAME="your_username"
EALYX_PASSWORD="your_password"
EALYX_API_BASE_URL="https://api.stg.ealyx.tech"
EALYX_ASSETS_URL="https://cdn.stg.ealyx.tech"

Configuration File (JSON, YAML, etc.)

{
"ealyx": {
"clientId": "your_client_id",
"clientSecret": "your_client_secret",
"username": "your_username",
"password": "your_password",
"apiBaseUrl": "https://api.stg.ealyx.tech",
"assetsUrl": "https://cdn.stg.ealyx.tech"
}
}

Secure Storage (secrets management, encrypted database, etc.)

Choose your preferred secure storage method and load the values at runtime.

Frontend Installation

Add this to your base template before </body>:

<script>
window.ealyxConfiguration = {
merchantId: '{MERCHANT_ID}',
browserCallbackBase: '{MERCHANT_CALLBACKS_BASE}',
confirmUrl: '{MERCHANT_SUCCESS_URL}',
products: 'valuations+ep1' // Default is just 'valuations'
};
import('{ASSETS_URL}/v1/main.js')
.then(module => { window.Ealyx = module.Ealyx; })
.catch(err => console.error('Error loading Ealyx:', err));
</script>

Note: For production, replace {ASSETS_URL} with https://cdn.ealyx.tech

The frontend SDK will automatically:

  • Load trade-in teasers on your pages
  • Handle the valuation modal
  • Manage the Ealyx Pay modal
  • Emit events for your backend to listen to (see Available SDK Events for complete reference)

Authentication

Overview

Ealyx uses two layers of authentication to secure API access. Understanding the difference is crucial for proper integration.

Layer 1: Credentials (Client ID + Secret + Username + Password)

What are credentials?

These are your permanent, master credentials that identify your application and account:

CredentialPurpose
CLIENT_IDUniquely identifies your application/merchant account
CLIENT_SECRETSecret key paired with CLIENT_ID for secure identification
USERNAMEYour administrative user account in Ealyx
PASSWORDYour administrative user password

When are credentials used?

Only during the initial authentication step to obtain temporary tokens. You send credentials to Ealyx's OAuth server exactly twice:

  1. Initial login - To get access_token and refresh_token
  2. Token refresh - To get a new access_token when it expires

Security considerations:

  • Never hardcode credentials in your application
  • Never expose in API calls (except the initial OAuth request)
  • Store securely in environment variables or secrets management system
  • Rotate regularly as a security best practice

Layer 2: OAuth 2.0 Tokens (Access Token + Refresh Token)

What are tokens?

Tokens are temporary credentials issued by Ealyx after you successfully authenticate with your credentials:

TokenDurationPurpose
access_token1 hourUsed to authenticate all API requests
refresh_tokenLong-livedUsed to obtain new access tokens without re-authenticating
expires_in3600 secondsTime until access_token expires

When are tokens used?

Every API call to Ealyx (after initial authentication) uses the access_token:

curl -X GET '{API_BASE_URL}/core/merchants/' \
-H 'Authorization: Bearer {ACCESS_TOKEN}' \
-H 'Content-Type: application/json'

Token Lifecycle:

  1. Initial login → Obtain access_token + refresh_token
  2. Store tokens → Save in your database
  3. Make API calls → Use access_token in Authorization header
  4. Token expires → etect expiration using expires_in and the timestamp when the token was obtained, use refresh_token to get new access_token
  5. Continue → Use new access_token for subsequent calls and replace the new refresh_token
  6. Refresh fails → Re-authenticate using credentials again

Security benefits:

  • Time-limited - Tokens expire after 1 hour, limiting damage if compromised
  • Revocable - Tokens automatically become invalid after expiration
  • Renewable - Get new tokens without exposing credentials repeatedly
  • Separable - Credentials stay secure; only temporary tokens are transmitted

Why This Two-Layer Approach?

Credentials alone would be unsafe:

  • Sending username/password with every API call = huge security risk
  • If credentials leak, attacker has permanent access

Tokens provide security:

  • Only credentials are sent once (in OAuth request)
  • Tokens are sent in every API call, but they expire automatically
  • If a token leaks, it's only valid for 1 hour

Analogy:

Credentials = Master key to your house (stored safely at home)
Access Token = Day pass valid for 1 hour (carried with you)

You use the master key once to get the day pass (setup).
You use the day pass all day long (every API call).
At the end of the day, the pass expires and becomes useless.
Tomorrow, you use the master key to get a new day pass.

Token Management

Since you're making HTTP API calls directly, you need to manage OAuth 2.0 tokens programmatically. This involves storing tokens, handling authentication, and managing token lifecycle.

Token Storage

You need to store OAuth tokens persistently between requests. The storage mechanism is flexible and depends on your infrastructure:

  • Relational Database (MySQL, PostgreSQL, etc.)
  • NoSQL Database (MongoDB, DynamoDB, etc.)
  • Key-Value Store (Redis, Memcached)
  • File System (with proper locking mechanisms)
  • Any other persistent storage you already use

The key requirements are:

  1. Persistence: Tokens must survive server restarts
  2. Atomic Updates: Concurrent requests must not corrupt token data
  3. Security: Tokens must be protected at rest (encryption recommended)
  4. Access Speed: Lookups should be fast (tokens are checked on every API call)

Option A: MySQL

CREATE TABLE ealyx_tokens (
id INT PRIMARY KEY AUTO_INCREMENT,
access_token VARCHAR(2048) NOT NULL,
refresh_token VARCHAR(2048) NOT NULL,
token_type VARCHAR(50) NOT NULL DEFAULT 'Bearer',
expires_at DATETIME NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY unique_latest (id)
);

To retrieve the latest token:

SELECT * FROM ealyx_tokens ORDER BY id DESC LIMIT 1;

To update (refresh) the token:

INSERT INTO ealyx_tokens (access_token, refresh_token, token_type, expires_at)
VALUES (?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
access_token = VALUES(access_token),
refresh_token = VALUES(refresh_token),
expires_at = VALUES(expires_at),
updated_at = NOW();

Option B: PostgreSQL

CREATE TABLE ealyx_tokens (
id SERIAL PRIMARY KEY,
access_token VARCHAR(2048) NOT NULL,
refresh_token VARCHAR(2048) NOT NULL,
token_type VARCHAR(50) NOT NULL DEFAULT 'Bearer',
expires_at TIMESTAMP NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE UNIQUE INDEX idx_latest_token ON ealyx_tokens (id DESC);

To retrieve the latest token:

SELECT * FROM ealyx_tokens ORDER BY id DESC LIMIT 1;

To update (refresh) the token (using INSERT with conflict handling):

INSERT INTO ealyx_tokens (access_token, refresh_token, token_type, expires_at)
VALUES (?, ?, ?, ?)
ON CONFLICT (id) DO UPDATE SET
access_token = EXCLUDED.access_token,
refresh_token = EXCLUDED.refresh_token,
expires_at = EXCLUDED.expires_at,
updated_at = CURRENT_TIMESTAMP;

Or simply insert new records and always query the latest:

INSERT INTO ealyx_tokens (access_token, refresh_token, token_type, expires_at)
VALUES (?, ?, ?, ?);

SELECT * FROM ealyx_tokens ORDER BY id DESC LIMIT 1;

Token Lifecycle

  1. Initial Login: Obtain access_token and refresh_token using your credentials
  2. Store Tokens: Save them in your persistent storage
  3. Use Access Token: Include it in all API requests
  4. Check Expiration: Before each request, verify if token is still valid
  5. Refresh if Needed: When expired, use refresh_token to get a new access_token
  6. Re-authenticate if Refresh Fails: If refresh fails, perform login again

Initial Login

Perform a one-time authentication to obtain initial tokens:

# 1. Set your credentials and API base URL
# For staging: API_BASE_URL="https://api.stg.ealyx.tech"
# For production: API_BASE_URL="https://api.ealyx.tech"
CLIENT_ID="your_client_id"
CLIENT_SECRET="your_client_secret"
USERNAME="your_username"
PASSWORD="your_password"
API_BASE_URL="{API_BASE_URL}"

# 2. Authenticate
curl -X POST "$API_BASE_URL/oauth2/token/" \
-H "Authorization: Basic $(echo -n "$CLIENT_ID:$CLIENT_SECRET" | base64)" \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=password' \
-d "username=$USERNAME" \
-d "password=$PASSWORD" \
-d 'scope=core payments valuations'
✓ Verification

Expected response:

{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"expires_in": 3600,
"token_type": "Bearer",
"refresh_token": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"merchant_id": "merchant_67890",
"user_id": "user_12345"
}
CheckExpectedIf it fails
access_tokenNot nullCheck CLIENT_ID/SECRET are correct
user_idNot nullCheck USERNAME/PASSWORD are correct
merchant_idNot nullContact Ealyx - credentials may not be activated

Store in your database: access_token, refresh_token, expires_at (now + expires_in), merchant_id, user_id

Save user_id and merchant_id - needed later for webhook signature validation.

Important:

  • Perform this initial login only once during setup, not on every request
  • Keep CLIENT_SECRET secure and never expose it to the frontend
  • The access_token expires after expires_in seconds (typically 3600 seconds = 1 hour)
  • Use the refresh_token to obtain new access tokens without re-authenticating

Token Refresh

When the access_token is about to expire (or has expired), use the refresh_token:

# Use the stored refresh_token from initial login
CLIENT_ID="your_client_id"
CLIENT_SECRET="your_client_secret"
REFRESH_TOKEN="your_stored_refresh_token"
API_BASE_URL="{API_BASE_URL}"

# Request a new token
curl -X POST "$API_BASE_URL/oauth2/token/" \
-H "Authorization: Basic $(echo -n "$CLIENT_ID:$CLIENT_SECRET" | base64)" \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=refresh_token' \
-d "refresh_token=$REFRESH_TOKEN"
✓ Verification

Expected response (same format as initial login):

{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"expires_in": 3600,
"token_type": "Bearer",
"refresh_token": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"merchant_id": "merchant_67890",
"user_id": "user_12345"
}
CheckExpectedIf it fails
New access_tokenNot nullRefresh token may be expired - re-authenticate
New refresh_tokenNot nullStore this new refresh token immediately

Update your database with the new tokens and recalculate expires_at.

Using Bearer Tokens in API Requests

Include the access_token in the Authorization header for all API calls:

ACCESS_TOKEN="your_valid_access_token"
API_BASE_URL="{API_BASE_URL}"

curl -X GET "$API_BASE_URL/core/merchants/" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H 'Content-Type: application/json'
✓ Verification
CheckExpectedIf it fails
HTTP status200 OKToken may be expired - refresh it
ResponseMerchant JSON objectCheck Authorization: Bearer header format
HTTP 401-Token expired - use Token Refresh above

Token Management Bash Scripts

For production use, implement these bash functions to automatically manage token lifecycle. These scripts handle authentication, expiration checking, and token refresh:

ealyx-token-manager.sh - Complete token management script:

#!/bin/bash

# Token Management for Ealyx API
# Source this file in your scripts: source ealyx-token-manager.sh

set -e

# Configuration (customize these)
EALYX_CONFIG_FILE="${EALYX_CONFIG_FILE:-.ealyx-config}"
EALYX_TOKEN_FILE="${EALYX_TOKEN_FILE:-.ealyx-tokens}"
API_BASE_URL="${API_BASE_URL:-{API_BASE_URL}}"

# Load credentials from config file if it exists
if [ -f "$EALYX_CONFIG_FILE" ]; then
source "$EALYX_CONFIG_FILE"
fi

# Function: Authenticate and get initial tokens
ealyx_authenticate() {
local client_id="$1"
local client_secret="$2"
local username="$3"
local password="$4"

if [ -z "$client_id" ] || [ -z "$client_secret" ] || [ -z "$username" ] || [ -z "$password" ]; then
echo "Usage: ealyx_authenticate <CLIENT_ID> <CLIENT_SECRET> <USERNAME> <PASSWORD>"
return 1
fi

local basic_auth=$(echo -n "$client_id:$client_secret" | base64 | tr -d '\n')
local response=$(curl -s -X POST "$API_BASE_URL/oauth2/token/" \
-H "Authorization: Basic $basic_auth" \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=password' \
-d "username=$username" \
-d "password=$password" \
-d 'scope=core payments valuations')

# Check for errors
if echo "$response" | grep -q '"error"'; then
echo "❌ Authentication failed:"
echo "$response" | jq .
return 1
fi

# Calculate and add expires_at timestamp (as epoch seconds)
# Using epoch timestamp is portable across all platforms (no date -d needed)
local expires_in=$(echo "$response" | jq -r '.expires_in')
local now=$(date +%s)
local expires_at=$((now + expires_in))

# Add expires_at to JSON and save
echo "$response" | jq --argjson expires_at "$expires_at" '. + {expires_at: $expires_at}' > "$EALYX_TOKEN_FILE"
echo "✓ Authentication successful. Tokens saved to $EALYX_TOKEN_FILE"

return 0
}

# Function: Get a valid access token (refreshes if expired)
ealyx_get_token() {
local scope="${1:-core payments valuations}"

# Check if token file exists
if [ ! -f "$EALYX_TOKEN_FILE" ]; then
echo "❌ Token file not found: $EALYX_TOKEN_FILE"
echo "Run: ealyx_authenticate <CLIENT_ID> <CLIENT_SECRET> <USERNAME> <PASSWORD>"
return 1
fi

# Read token data
local access_token=$(jq -r '.access_token' "$EALYX_TOKEN_FILE")
local refresh_token=$(jq -r '.refresh_token' "$EALYX_TOKEN_FILE")
local expires_at=$(jq -r '.expires_at' "$EALYX_TOKEN_FILE")

# Check if token is expired (with 5-minute buffer)
# Note: expires_at should be stored as epoch timestamp (seconds since 1970)
# This avoids date -d which is GNU-specific and fails on macOS
local now=$(date +%s)
local expires_timestamp="${expires_at:-$((now + 3600))}" # Default to 1 hour if not set
local buffer=$((5 * 60)) # 5 minute buffer

if [ $now -gt $((expires_timestamp - buffer)) ]; then
echo "⟳ Token expired, refreshing..." >&2
ealyx_refresh_token "$scope" || return 1
access_token=$(jq -r '.access_token' "$EALYX_TOKEN_FILE")
fi

echo "$access_token"
return 0
}

# Function: Refresh the access token
ealyx_refresh_token() {
local scope="${1:-core payments valuations}"
local client_id="${CLIENT_ID:-}"
local client_secret="${CLIENT_SECRET:-}"

if [ -z "$client_id" ] || [ -z "$client_secret" ]; then
echo "❌ CLIENT_ID and CLIENT_SECRET must be set"
return 1
fi

# Read refresh token from file
if [ ! -f "$EALYX_TOKEN_FILE" ]; then
echo "❌ Token file not found: $EALYX_TOKEN_FILE"
return 1
fi

local refresh_token=$(jq -r '.refresh_token' "$EALYX_TOKEN_FILE")

# Request new token
local response=$(curl -s -X POST "$API_BASE_URL/oauth2/token/" \
-H "Authorization: Basic $(echo -n "$client_id:$client_secret" | base64)" \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=refresh_token' \
-d "refresh_token=$refresh_token" \
-d "scope=$scope")

# Check for errors
if echo "$response" | grep -q '"error"'; then
echo "❌ Token refresh failed:"
echo "$response" | jq .
return 1
fi

# Calculate and add expires_at timestamp (as epoch seconds)
# Using epoch timestamp is portable across all platforms (no date -d needed)
local expires_in=$(echo "$response" | jq -r '.expires_in')
local now=$(date +%s)
local expires_at=$((now + expires_in))

# Save updated tokens with expires_at as epoch timestamp
echo "$response" | jq --arg exp "$expires_at" '. + {expires_at: $exp | tonumber}' > "$EALYX_TOKEN_FILE"
echo "✓ Token refreshed successfully" >&2

return 0
}

# Function: Make an authenticated API call
ealyx_api() {
local method="$1"
local endpoint="$2"
shift 2
local curl_args=("$@")

if [ -z "$method" ] || [ -z "$endpoint" ]; then
echo "Usage: ealyx_api <METHOD> <ENDPOINT> [CURL_ARGS...]"
echo "Example: ealyx_api GET /core/merchants/"
return 1
fi

# Get valid token
local access_token=$(ealyx_get_token) || return 1

# Build URL
local url="$API_BASE_URL$endpoint"

# Make request with token
curl -s -X "$method" "$url" \
-H "Authorization: Bearer $access_token" \
"${curl_args[@]}"

return 0
}

# Export functions for use in other scripts
export -f ealyx_authenticate
export -f ealyx_get_token
export -f ealyx_refresh_token
export -f ealyx_api

Important: Token Storage Format

The token manager stores expires_at as an epoch timestamp (seconds since January 1, 1970). This approach:

  • ✅ Works on macOS, Linux, and all Unix-like systems (no date -d needed)
  • ✅ Simple arithmetic comparison: if [ $now -gt $expires_timestamp ]
  • ✅ No string parsing or date format conversion needed

When you run ealyx_authenticate or ealyx_refresh_token, the token file looks like:

{
"access_token": "...",
"refresh_token": "...",
"expires_in": 3600,
"token_type": "Bearer",
"merchant_id": "merchant_123",
"user_id": "user_456",
"expires_at": 1734896400
}

The expires_at field is a number (epoch timestamp), not a string. This makes expiration checks trivial:

current=$(date +%s)
if [ $current -gt $expires_at ]; then
echo "Token expired"
fi

Usage Example:

These functions are included in the ealyx-token-manager.sh:

# Source the token manager in your scripts
source ealyx-token-manager.sh

# Initial authentication
ealyx_authenticate "your_client_id" "your_client_secret" "username" "password"

# Get a valid token (automatically refreshes if needed)
TOKEN=$(ealyx_get_token) || exit 1

# Make API calls
ealyx_api GET "/core/merchants/" \
-H "Content-Type: application/json"

# For order updates, get token with 'updates' scope
TOKEN=$(ealyx_get_token "updates") || exit 1

Here are additional utility functions to append into ealyx-token-manager.sh:

# Function: Validate webhook signature
ealyx_validate_signature() {
local received_signature="$1"
local request_body="$2"
local user_id="${USER_ID:-}"
local merchant_id="${MERCHANT_ID:-}"

if [ -z "$user_id" ] || [ -z "$merchant_id" ]; then
echo "❌ USER_ID and MERCHANT_ID must be set"
return 1
fi

if [ -z "$received_signature" ] || [ -z "$request_body" ]; then
echo "Usage: ealyx_validate_signature <SIGNATURE> <REQUEST_BODY>"
return 1
fi

local secret="$user_id-$merchant_id"
local expected_signature=$(echo -n "$request_body" | openssl dgst -sha256 -hmac "$secret" | cut -d' ' -f2)

if [ "$received_signature" = "$expected_signature" ]; then
echo "✓ Signature valid"
return 0
else
echo "❌ Signature invalid"
echo "Received: $received_signature"
echo "Expected: $expected_signature"
return 1
fi
}

# Export functions for use in other scripts
export -f ealyx_validate_signature

Usage Examples:

# 1. Source the script
source ealyx-token-manager.sh

# 2. Set credentials (or load from ealyx-config)
export CLIENT_ID="your_client_id"
export CLIENT_SECRET="your_client_secret"
export USERNAME="your_username"
export PASSWORD="your_password"
export USER_ID="from_initial_auth_response"
export MERCHANT_ID="from_initial_auth_response"

# 3. Authenticate once
ealyx_authenticate "$CLIENT_ID" "$CLIENT_SECRET" "$USERNAME" "$PASSWORD"

# 4. Make API calls (tokens handled automatically)
ealyx_api GET "/core/merchants/" -H 'Content-Type: application/json' | jq .

# 5. For POST requests with data
ealyx_api POST "/payments/orders/update" \
-H 'Content-Type: application/json' \
-d '{"order_id":"ORD-123","update_type":"shipped"}' | jq .

# 6. Validate webhook signatures
request_body='{"data":{"cart_id":"cart_123","status":"pending"}}'
received_sig="from_header: X-Ealyx-Signature"
ealyx_validate_signature "$received_sig" "$request_body"

✓ Benefits of using these scripts:

  • Automatic token expiration detection
  • Transparent token refresh on first request
  • Consistent error handling
  • Webhook signature validation helper
  • Reusable across multiple scripts

Token Scope Management

Different Ealyx API operations require different OAuth scopes. The Ealyx OAuth server validates that your token has the required scope for each endpoint:

OperationRequired ScopeEndpoint
Valuation, Trade-in queries, Merchant infocore payments valuations/core/merchants/, /core/sessions/, /core/tradeinitems/
Order status updatesupdatesPOST /payments/orders/update

Important: Scopes Cannot Be Combined

You cannot request multiple scopes in a single token request like scope=core payments valuations updates. The Ealyx OAuth server validates scopes strictly - you must request tokens with the exact scopes needed:

  • Initial login scope: core payments valuations (for all standard operations)
  • Order update scope: updates (explicitly, for order updates only)

If you try to use a token with the wrong scope on an endpoint, you'll get a 403 Forbidden error.

Recommended Strategy: Single Token + Refresh for Updates

Store one primary token and refresh it with the updates scope only when needed:

# Initial login - store this token and its refresh_token
curl -X POST '{API_BASE_URL}/oauth2/token/' \
-H 'Authorization: Basic '$(echo -n "{CLIENT_ID}:{CLIENT_SECRET}" | base64) \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=password' \
-d 'username={USERNAME}' \
-d 'password={PASSWORD}' \
-d 'scope=core payments valuations'

# Response includes:
# {
# "access_token": "primary_token_abc123...",
# "refresh_token": "refresh_abc123...",
# "expires_in": 3600
# }

# Later, when you need to update an order, obtain a NEW token with updates scope
curl -X POST '{API_BASE_URL}/oauth2/token/' \
-H 'Authorization: Basic '$(echo -n "{CLIENT_ID}:{CLIENT_SECRET}" | base64) \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=refresh_token' \
-d 'refresh_token={REFRESH_TOKEN}' \
-d 'scope=updates'

# Response includes update_token with limited scope:
# {
# "access_token": "update_token_xyz789...",
# "refresh_token": "refresh_xyz789...",
# "expires_in": 3600
# }

# Use this update_token ONLY for POST /payments/orders/update
curl -X POST '{API_BASE_URL}/payments/orders/update' \
-H 'Authorization: Bearer update_token_xyz789...' \
-H 'Content-Type: application/json' \
-d '{"order_id":"ORD-123","update_type":"shipped"}'

# After update completes, return to using your primary_token for other operations with other refresh token and scope `core payments valuations`

Why Separate Scopes?

Security isolation - each token type has minimal permissions. If a token leaks:

  • Leaked core payments valuations token: Attacker can query valuations, read merchant data (not payment-related)
  • Leaked updates token: Attacker can only update order status (cannot read customer data)

How the Token Manager Handles This

The ealyx_get_token function supports this pattern:

# Default: Get token with standard scope
TOKEN=$(ealyx_get_token)

# For order updates: Explicitly request updates scope
UPDATE_TOKEN=$(ealyx_get_token "updates")

# Use the right token for each operation
curl -X GET '{API_BASE_URL}/core/merchants/' \
-H "Authorization: Bearer $TOKEN"

curl -X POST '{API_BASE_URL}/payments/orders/update' \
-H "Authorization: Bearer $UPDATE_TOKEN" \
-d '{"order_id":"ORD-123","update_type":"shipped"}'

Note: The PHP SDK uses this pattern - it obtains a fresh token with updates scope for each order update call, using the refresh_token from the primary login. This is the recommended approach for security and clarity.