GuideReference
v1.1.0
OAS 3.0.3

orda API

API for managing quotes, transactions and recipients in a cross-chain payment system.

Authentication

This API uses HMAC-SHA256 authentication to ensure request integrity and authenticity. All requests must include proper authentication headers.

Required Headers

Header Description Example
x-client-id Your project client ID from orda dashboard prj_abc123...
x-signature HMAC-SHA256 signature of the canonical request body a1b2c3d4...
x-timestamp Request timestamp in milliseconds (for replay protection - Optional) 1704067200000

Signature Generation

The HMAC signature is generated using the following process:

1. Canonical JSON Serialization

The request body is canonicalized to ensure consistent signatures regardless of JSON key ordering:

  • Object keys are sorted alphabetically
  • No whitespace between elements
  • Consistent string escaping
  • Handles nested objects and arrays recursively

Example:

// Original JSON (key order may vary)
{"name": "John", "age": 30, "city": "New York"}

// Canonical JSON (always same output)
{"age":30,"city":"New York","name":"John"}

2. HMAC-SHA256 Calculation

signature = HMAC-SHA256(canonical_body, client_secret)

Where:

  • canonical_body is the canonicalized JSON string (or empty string for no body)
  • client_secret is your API client secret
  • Output is hexadecimal string

Authentication Flow

  1. Canonicalize the request body JSON (if present)
  2. Generate HMAC-SHA256 signature using your client secret
  3. Add headers to your request:
    • x-client-id: Your project client ID
    • x-signature: The generated signature
    • x-timestamp: Current timestamp in milliseconds - Optional
  4. Send the request

Error Responses

Status Code Error Description
401 INVALID_SIGNATURE Signature verification failed
401 MISSING_SIGNATURE Required x-signature header missing
401 MISSING_CLIENT_ID Required x-client-id header missing
401 TIMESTAMP_TOO_OLD Request timestamp is too old (replay protection)
403 INVALID_CLIENT Client credentials are invalid

Code Examples

JavaScript (Node.js)

const crypto = require('crypto');

function canonicalizeJSON(obj, seenObjects = new WeakSet()) {
    if (obj === null) return 'null';
    if (typeof obj === 'undefined') return 'undefined';
    if (typeof obj === 'boolean' || typeof obj === 'number') return String(obj);
    if (typeof obj === 'string') return JSON.stringify(obj);
    if (obj instanceof Date) return JSON.stringify(obj.toISOString());
    
    if (Array.isArray(obj)) {
        if (seenObjects.has(obj)) return '[Circular]';
        seenObjects.add(obj);
        const items = obj.map(item => canonicalizeJSON(item, seenObjects));
        seenObjects.delete(obj);
        return `[${items.join(',')}]`;
    }
    
    if (typeof obj === 'object') {
        if (seenObjects.has(obj)) return '{Circular}';
        seenObjects.add(obj);
        const sortedKeys = Object.keys(obj).sort();
        const pairs = sortedKeys.map(key => {
            const value = canonicalizeJSON(obj[key], seenObjects);
            return `${JSON.stringify(key)}:${value}`;
        });
        seenObjects.delete(obj);
        return `{${pairs.join(',')}}`;
    }
    
    return JSON.stringify(obj);
}

function generateSignature(body, clientSecret) {
    const canonicalBody = body ? canonicalizeJSON(body) : '';
    return crypto
        .createHmac('sha256', clientSecret)
        .update(canonicalBody)
        .digest('hex');
}

// Add to request headers
const headers = {
    'x-client-id': clientId,
    'x-signature': generateSignature(requestBody, clientSecret),
    'x-timestamp': Date.now().toString(),
    'Content-Type': 'application/json'
};

Python

import hashlib
import hmac
import json
import time
from typing import Any, Set

def canonicalize_json(obj: Any, seen_objects: Set[int] = None) -> str:
    if seen_objects is None:
        seen_objects = set()
        
    if obj is None:
        return 'null'
    elif isinstance(obj, bool):
        return 'true' if obj else 'false'
    elif isinstance(obj, (int, float)):
        return str(obj)
    elif isinstance(obj, str):
        return json.dumps(obj)
    elif isinstance(obj, list):
        obj_id = id(obj)
        if obj_id in seen_objects:
            return '[Circular]'
        seen_objects.add(obj_id)
        items = [canonicalize_json(item, seen_objects) for item in obj]
        seen_objects.remove(obj_id)
        return f"[{','.join(items)}]"
    elif isinstance(obj, dict):
        obj_id = id(obj)
        if obj_id in seen_objects:
            return '{Circular}'
        seen_objects.add(obj_id)
        sorted_keys = sorted(obj.keys())
        pairs = [f'"{key}":{canonicalize_json(obj[key], seen_objects)}' for key in sorted_keys]
        seen_objects.remove(obj_id)
        return f"{{{','.join(pairs)}}}"
    else:
        return json.dumps(obj)

def generate_signature(body: dict, client_secret: str) -> str:
    canonical_body = canonicalize_json(body) if body else ''
    signature = hmac.new(
        client_secret.encode('utf-8'),
        canonical_body.encode('utf-8'),
        hashlib.sha256
    ).hexdigest()
    return signature

# Add to request headers
headers = {
    'x-client-id': client_id,
    'x-signature': generate_signature(request_body, client_secret),
    'x-timestamp': str(int(time.time() * 1000)),
    'Content-Type': 'application/json'
}

cURL

# You'll need to implement canonical JSON serialization
# and HMAC generation in your preferred scripting language

SIGNATURE=$(echo -n "$CANONICAL_BODY" | openssl dgst -sha256 -hmac "$CLIENT_SECRET" -hex | cut -d' ' -f2)
TIMESTAMP=$(date +%s)000

curl -X POST "https://api.orda.network/v1/endpoint" \
  -H "Content-Type: application/json" \
  -H "x-client-id: $CLIENT_ID" \
  -H "x-signature: $SIGNATURE" \
  -H "x-timestamp: $TIMESTAMP" \
  -d "$REQUEST_BODY"

Important Notes

  • Empty bodies: For requests with no body, use an empty string "" for signature generation
  • Key ordering: The canonical JSON ensures consistent signatures regardless of object key order
  • Environment variables: When using Postman, environment variables in the format {{variable_name}} are automatically resolved
  • Replay protection: Timestamps prevent replay attacks; ensure your system clock is synchronized
  • Secret security: Keep your client secret secure and never expose it in client-side code

Testing Your Implementation

To verify your HMAC implementation is working correctly:

  1. Test with the same JSON object but different key orders
  2. Ensure both generate identical signatures
  3. Verify empty body requests work correctly
  4. Test with nested objects and arrays
Server: https://api.orda.network/v1

Default API path

Client Libraries

Crypto-to-crypto (Collapsed)

Operations for handling direct and cross-chain transactions

Crypto-to-fiat (Collapsed)

Operations for crypto to fiat conversions (off-ramp)

Crypto-to-fiat Operations

Models