# Authentication Source: https://docs.tender.cash/api-reference/authentication How Tender signs and authenticates API requests. All requests require authentication. You can get your API credentials (Access ID and Access Secret) from the Tender dashboard. Tender uses two authentication methods, depending on the endpoint: | Method | Headers required | Used by | | --------------------- | ------------------------------------------------------------------------------ | ---------------------------------------------------------- | | **Signed (HMAC)** | `x-access-id`, `x-request-id`, `x-timestamp`, `authorization` (HMAC signature) | Agents, Conversions, Onramp, Payouts, Subwallets, Webhooks | | **Basic (Access ID)** | `x-access-id` only | Payments, System (chains, currencies, rates) | Each endpoint page shows which method it uses in a note at the top. *** ## Basic (Access ID) Authentication Payment and System endpoints (`/v1/api/payment/*` and `/v1/api/system/*`) only require your public access ID: ```http theme={null} x-access-id: Content-Type: application/json ``` No request signing is needed for these endpoints. Your Access Secret is never sent. *** ## Signed (HMAC) Authentication All other endpoints require HMAC signature-based authentication. Each request must include these headers: ```http theme={null} x-access-id: x-request-id: x-timestamp: authorization: Content-Type: application/json ``` ### Request Signing To protect the integrity of your API requests, Tender uses HMAC-SHA256 signature authentication. This ensures that each request is securely verified and that the data hasn't been altered in transit. Each request's headers must include: 1. **x-access-id**: Your public API access ID 2. **x-request-id**: A unique UUID v4 for each request 3. **x-timestamp**: Current timestamp in ISO 8601 format 4. **authorization**: Base64-encoded HMAC-SHA256 signature #### How Signatures Are Generated An **authorization** signature is generated using: 1. A JSON payload containing the timestamp, request ID, and access ID 2. Your API secret key 3. HMAC-SHA256 algorithm 4. Base64 encoding of the resulting hash The signed payload structure: ```json theme={null} { "timeStamp": "", "requestId": "", "accessId": "" } ``` #### Signature Algorithm ```text theme={null} hash = Base64(HMAC_SHA256(JSON.stringify(payload), accessSecret)) ``` *** ### Signed Request Example ```javascript Node.js theme={null} import crypto from 'crypto'; import { v4 as uuidv4 } from 'uuid'; function generateSignature(accessId, accessSecret) { // Generate request ID and timestamp const requestId = uuidv4(); const timeStamp = new Date().toISOString(); // Create the payload to sign const payload = { timeStamp: timeStamp, requestId: requestId, accessId: accessId }; // Generate HMAC-SHA256 signature const hmac = crypto.createHmac('sha256', accessSecret); hmac.update(JSON.stringify(payload)); const signature = hmac.digest('base64'); return { 'x-access-id': accessId, 'x-request-id': requestId, 'x-timestamp': timeStamp, 'authorization': signature, 'Content-Type': 'application/json' }; } // Usage const accessId = 'YOUR_ACCESS_ID'; const accessSecret = 'YOUR_ACCESS_SECRET'; const headers = generateSignature(accessId, accessSecret); console.log('Headers:', headers); // Make API request const response = await fetch('https://secureapi.tender.cash/v1/api/agent/create', { method: 'POST', headers: headers, body: JSON.stringify({ firstName: 'John', lastName: 'Doe', email: 'john@example.com', phoneNumber: '1234567890', location: 'Lagos', address: '123 Main Street', country: 'Nigeria' }) }); const data = await response.json(); console.log('Response:', data); ``` ```python Python theme={null} import hmac import hashlib import base64 import json import uuid from datetime import datetime import requests def generate_signature(access_id, access_secret): # Generate request ID and timestamp request_id = str(uuid.uuid4()) timestamp = datetime.utcnow().isoformat() + 'Z' # Create the payload to sign payload = { "timeStamp": timestamp, "requestId": request_id, "accessId": access_id } # Generate HMAC-SHA256 signature message = json.dumps(payload) signature = base64.b64encode( hmac.new( access_secret.encode('utf-8'), message.encode('utf-8'), hashlib.sha256 ).digest() ).decode('utf-8') return { 'x-access-id': access_id, 'x-request-id': request_id, 'x-timestamp': timestamp, 'authorization': signature, 'Content-Type': 'application/json' } # Usage access_id = 'YOUR_ACCESS_ID' access_secret = 'YOUR_ACCESS_SECRET' headers = generate_signature(access_id, access_secret) print('Headers:', headers) # Make API request response = requests.post( 'https://secureapi.tender.cash/v1/api/agent/create', headers=headers, json={ 'firstName': 'John', 'lastName': 'Doe', 'email': 'john@example.com', 'phoneNumber': '1234567890', 'location': 'Lagos', 'address': '123 Main Street', 'country': 'Nigeria' } ) data = response.json() print('Response:', data) ``` ```php PHP theme={null} $timeStamp, 'requestId' => $requestId, 'accessId' => $accessId ]; // Generate HMAC-SHA256 signature $message = json_encode($payload); $signature = base64_encode(hash_hmac('sha256', $message, $accessSecret, true)); return [ 'x-access-id' => $accessId, 'x-request-id' => $requestId, 'x-timestamp' => $timeStamp, 'authorization' => $signature, 'Content-Type' => 'application/json' ]; } // Usage $accessId = 'YOUR_ACCESS_ID'; $accessSecret = 'YOUR_ACCESS_SECRET'; $headers = generateSignature($accessId, $accessSecret); print_r($headers); // Make API request $ch = curl_init('https://secureapi.tender.cash/v1/api/agent/create'); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([ 'firstName' => 'John', 'lastName' => 'Doe', 'email' => 'john@example.com', 'phoneNumber' => '1234567890', 'location' => 'Lagos', 'address' => '123 Main Street', 'country' => 'Nigeria' ])); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'x-access-id: ' . $headers['x-access-id'], 'x-request-id: ' . $headers['x-request-id'], 'x-timestamp: ' . $headers['x-timestamp'], 'authorization: ' . $headers['authorization'], 'Content-Type: application/json' ]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); curl_close($ch); echo 'Response: ' . $response; ?> ``` *** ## Important Notes * **Keep your Access Secret secure**: Never expose it in client-side code or public repositories * **Generate a new request ID** for each request using UUID v4 * **Use ISO 8601 format** for timestamps (e.g., `2025-03-15T09:45:53.000Z`) * **Invalid signatures** will result in a 401 Unauthorized error For troubleshooting authentication errors, see the [Errors](/api-reference/errors) section. # Add Webhook Source: https://docs.tender.cash/api-reference/endpoint/add-webhook POST /v1/api/webhook Register a new webhook endpoint for transaction events **Auth method: Signed (HMAC)** — this endpoint requires the full set of signed headers: `x-access-id`, `x-request-id`, `x-timestamp`, and an HMAC-SHA256 `authorization` signature. See [Authentication](/api-reference/authentication#signed-hmac-authentication). ## Headers Base64-encoded HMAC-SHA256 signature of the request payload using the API secret **Minimum string length:** `1` **Example:** `"5e73d044c44d733fcf819ad3409aaaddca840d421b69cb0b04e2c750fc62e-ce7526d36296237663ad1f06f62a730c0466516507196b3ce6567493c-c52a7cf63d"` Current timestamp in ISO 8601 format **Example:** `"2025-03-15T09:45:53.000Z"` Unique identifier for the request (UUID v4) **Example:** `"550e8400-e29b-41d4-a716-446655440000"` Your API access ID provided by Tender **Example:** `"your-access-id-here"` Media type of the request body **Example:** `"application/json"` ## Body Webhook endpoint URL to receive event notifications **Example:** `"https://example.com/webhook"` Description of the webhook purpose **Example:** `"Transaction notifications"` Array of event types to subscribe to **Example:** `["transaction_completed"]` Custom headers to include in webhook requests (optional) **Example:** `{ "api-key": "your-api-key" }` ## Response Status of the API request **Example:** `"success"` Human-readable message describing the result **Example:** `"success"` The created webhook configuration Unique MongoDB identifier for the webhook **Example:** `"691069ff947a702cfad9e861"` Merchant ID associated with the webhook **Example:** `"6538e8f9bdec6d1a21978a64"` Description of the webhook **Example:** `"new example webhooks"` Webhook endpoint URL **Example:** `"https://exampleiop.com"` Array of subscribed event types **Example:** `["transaction_completed"]` Custom headers for webhook requests **Example:** `{ "api-key": "allow-requior" }` Whether the webhook is currently active **Example:** `true` Whether the webhook has been deleted **Example:** `false` ISO 8601 timestamp when the webhook was created **Example:** `"2025-11-09T10:16:31.594Z"` ISO 8601 timestamp when the webhook was last updated **Example:** `"2025-11-09T10:18:35.286Z"` Version key for MongoDB document **Example:** `0` # Create Conversion Source: https://docs.tender.cash/api-reference/endpoint/conversions/create POST /v1/api/conversions Directly create a crypto-to-crypto swap or a fiat payout conversion — no OTP required **Auth method: Signed (HMAC)** — this endpoint requires the full set of signed headers: `x-access-id`, `x-request-id`, `x-timestamp`, and an HMAC-SHA256 `authorization` signature. See [Authentication](/api-reference/authentication#signed-hmac-authentication). ## Headers Base64-encoded HMAC-SHA256 signature of the request payload **Example:** `"5e73d044c44d733fcf819ad3409aaad..."` Current timestamp in ISO 8601 format **Example:** `"2025-03-15T09:45:53.000Z"` Unique UUID v4 for the request **Example:** `"550e8400-e29b-41d4-a716-446655440000"` Your API access ID provided by Tender **Example:** `"your-access-id-here"` **Example:** `"application/json"` ## Body Conversion type. Use `crypto` to swap to another coin/chain, or `fiat` to convert to a payout account. **Allowed values:** `crypto`, `fiat` **Example:** `"crypto"` Source blockchain chain ID **Example:** `"ethereum"` Source coin ID **Example:** `"usdt"` Amount to convert **Example:** `"100"` Destination chain. **Required when `type` is `crypto`.** **Example:** `"solana"` Destination coin. **Required when `type` is `crypto`.** **Example:** `"sol"` Payout account to receive funds. **Required when `type` is `fiat`.** **Example:** `"66aec7de809b7f45c42a49f9"` ## Response **Example:** `"success"` **Example:** `"Conversion created successfully"` The newly created conversion record **Example:** `"66aec7de809b7f45c42a49f9"` **Example:** `"crypto"` Initial status after creation **Example:** `"pending"` **Example:** `"100"` **Example:** `"usdt"` **Example:** `"ethereum"` Present for crypto swaps **Example:** `"solana"` Present for crypto swaps **Example:** `"sol"` All stages initialised to `pending` **Example:** `{ "sendForConversion": { "status": "pending" }, "conversionState": { "status": "pending" }, "settleCrypto": { "status": "pending" } }` **Example:** `"2024-09-24T22:20:15.650Z"` # Calculate Conversion Fee Source: https://docs.tender.cash/api-reference/endpoint/conversions/fee GET /v1/api/conversions/fee/{chain}/{coin}/{amount} Get a fee quote for converting a given coin/chain amount, with optional destination for crypto swaps **Auth method: Signed (HMAC)** — this endpoint requires the full set of signed headers: `x-access-id`, `x-request-id`, `x-timestamp`, and an HMAC-SHA256 `authorization` signature. See [Authentication](/api-reference/authentication#signed-hmac-authentication). ## Headers Your API access ID provided by Tender **Example:** `"your-access-id-here"` ## Path Parameters Source chain identifier **Example:** `"ethereum"` Source coin identifier **Example:** `"usdt"` Amount to convert **Example:** `"100"` ## Query Parameters Destination chain for a crypto swap quote **Example:** `"solana"` Destination coin for a crypto swap quote **Example:** `"sol"` ## Response **Example:** `"success"` **Example:** `"success"` Conversion fee quote Source amount **Example:** `100` Source amount in USD **Example:** `100.00` Conversion fee in source coin **Example:** `0.5` Conversion fee in USD **Example:** `0.50` Amount you will convert after fees are deducted **Example:** `99.5` Estimated destination amount (crypto swaps only) **Example:** `1.24` Exchange rate applied **Example:** `0.0125` # Get Conversion Source: https://docs.tender.cash/api-reference/endpoint/conversions/get-one GET /v1/api/conversions/{id} Retrieve a single conversion record by ID **Auth method: Signed (HMAC)** — this endpoint requires the full set of signed headers: `x-access-id`, `x-request-id`, `x-timestamp`, and an HMAC-SHA256 `authorization` signature. See [Authentication](/api-reference/authentication#signed-hmac-authentication). ## Headers Your API access ID provided by Tender **Example:** `"your-access-id-here"` ## Path Parameters The unique conversion ID **Example:** `"66aec7de809b7f45c42a49f9"` ## Response **Example:** `"success"` **Example:** `"success"` The conversion record Unique identifier **Example:** `"66aec7de809b7f45c42a49f9"` **Example:** `"6538e8f9bdec6d1a21978a64"` `crypto` or `fiat` **Example:** `"crypto"` **Example:** `"completed"` **Example:** `"10.5"` **Example:** `"usdt"` **Example:** `"ethereum"` Destination chain (crypto swaps only) **Example:** `"solana"` Destination coin (crypto swaps only) **Example:** `"sol"` **Example:** `{ "status": "completed" }` **Example:** `{ "status": "completed" }` **Example:** `{ "status": "completed" }` Present only for fiat conversions. **Example:** `{ "status": "completed" }` **Example:** `"2024-09-24T22:20:15.650Z"` **Example:** `"2024-09-24T22:25:00.000Z"` # List Conversions Source: https://docs.tender.cash/api-reference/endpoint/conversions/list GET /v1/api/conversions Retrieve all conversions for your merchant account with optional filters and pagination **Auth method: Signed (HMAC)** — this endpoint requires the full set of signed headers: `x-access-id`, `x-request-id`, `x-timestamp`, and an HMAC-SHA256 `authorization` signature. See [Authentication](/api-reference/authentication#signed-hmac-authentication). ## Headers Your API access ID provided by Tender **Example:** `"your-access-id-here"` ## Query Parameters Page number for pagination **Example:** `1` Number of records per page **Example:** `10` Filter by conversion status. Passing `pending` returns both `pending` and `processing` records. **Allowed values:** `pending`, `processing`, `completed` **Example:** `"completed"` ## Response Status of the API request **Example:** `"success"` Human-readable message describing the result **Example:** `"success"` Conversions list and aggregate history Paginated list of conversion records Array of conversion objects Unique identifier for the conversion **Example:** `"66aec7de809b7f45c42a49f9"` Merchant associated with the conversion **Example:** `"6538e8f9bdec6d1a21978a64"` Conversion type: `crypto` (swap) or `fiat` (payout account) **Example:** `"crypto"` Current status of the conversion **Example:** `"completed"` Source amount **Example:** `"10.5"` Source coin identifier **Example:** `"usdt"` Source chain identifier **Example:** `"ethereum"` Destination chain (crypto swaps only) **Example:** `"solana"` Destination coin (crypto swaps only) **Example:** `"sol"` Lifecycle stages of the conversion **Example:** `{ "status": "completed" }` **Example:** `{ "status": "completed" }` **Example:** `{ "status": "completed" }` Present only for fiat conversions. **Example:** `{ "status": "completed" }` ISO 8601 timestamp **Example:** `"2024-09-24T22:20:15.650Z"` Total number of pages **Example:** `3` Current page **Example:** `1` Items per page **Example:** `10` Aggregate totals for all conversion statuses **Example:** `{ "total": 25, "completed": 20, "pending": 5 }` # Swap-Enabled Chains Source: https://docs.tender.cash/api-reference/endpoint/conversions/swap-chains GET /v1/api/conversions/swap/chains List all blockchain networks that support crypto-to-crypto swaps, optionally filtered by coin **Auth method: Signed (HMAC)** — this endpoint requires the full set of signed headers: `x-access-id`, `x-request-id`, `x-timestamp`, and an HMAC-SHA256 `authorization` signature. See [Authentication](/api-reference/authentication#signed-hmac-authentication). ## Headers Your API access ID provided by Tender **Example:** `"your-access-id-here"` ## Query Parameters Filter chains that support a specific coin **Example:** `"usdt"` ## Response **Example:** `"success"` **Example:** `"success"` Array of chains that have swap enabled Chain identifier **Example:** `"ethereum"` Display name **Example:** `"Ethereum"` Chain icon URL **Example:** `"https://tender-store.s3.amazonaws.com/icons/ethereum.png"` Native coin symbol **Example:** `"ETH"` Blockchain type (e.g. `evm`, `sol`, `tron`) **Example:** `"evm"` **Example:** `"active"` # Swap-Enabled Coins Source: https://docs.tender.cash/api-reference/endpoint/conversions/swap-coins GET /v1/api/conversions/swap/coins List all coins available for crypto-to-crypto swaps, optionally filtered by chain **Auth method: Signed (HMAC)** — this endpoint requires the full set of signed headers: `x-access-id`, `x-request-id`, `x-timestamp`, and an HMAC-SHA256 `authorization` signature. See [Authentication](/api-reference/authentication#signed-hmac-authentication). ## Headers Your API access ID provided by Tender **Example:** `"your-access-id-here"` ## Query Parameters Comma-separated list of chain IDs to filter by. Returns coins available on those chains. **Example:** `"ethereum,solana"` ## Response **Example:** `"success"` **Example:** `"success"` Array of coins with swap enabled Coin identifier **Example:** `"usdt"` Display name **Example:** `"Tether USD"` Ticker symbol **Example:** `"USDT"` Coin icon URL **Example:** `"https://tender-store.s3.amazonaws.com/icons/usdt.png"` Chain IDs this coin is available on **Example:** `["ethereum", "tron", "solana"]` **Example:** `"active"` # Delete Webhook Source: https://docs.tender.cash/api-reference/endpoint/delete-webhook DELETE /v1/api/webhook/{id} Remove an existing webhook endpoint **Auth method: Signed (HMAC)** — this endpoint requires the full set of signed headers: `x-access-id`, `x-request-id`, `x-timestamp`, and an HMAC-SHA256 `authorization` signature. See [Authentication](/api-reference/authentication#signed-hmac-authentication). ## Path Parameters Webhook ID to delete **Example:** `"691069ff947a702cfad9e861"` ## Headers Base64-encoded HMAC-SHA256 signature of the request payload using the API secret **Minimum string length:** `1` **Example:** `"5e73d044c44d733fcf819ad3409aaaddca840d421b69cb0b04e2c750fc62e-ce7526d36296237663ad1f06f62a730c0466516507196b3ce6567493c-c52a7cf63d"` Current timestamp in ISO 8601 format **Example:** `"2025-03-15T09:45:53.000Z"` Unique identifier for the request (UUID v4) **Example:** `"550e8400-e29b-41d4-a716-446655440000"` Your API access ID provided by Tender **Example:** `"your-access-id-here"` ## Response Status of the API request **Example:** `"success"` Human-readable message describing the result **Example:** `"success"` Deletion confirmation Confirmation that the webhook was deleted **Example:** `true` # Fetch Chain Currencies Source: https://docs.tender.cash/api-reference/endpoint/fetch-chain-currencies GET /v1/api/system/chains/{id}/currency Retrieve currencies supported on a specific blockchain **Auth method: Basic (Access ID)** — this endpoint only requires your `x-access-id` header. No request signing is needed. See [Authentication](/api-reference/authentication#basic-access-id-authentication). ## Path Parameters Chain identifier **Example:** `"avalanche"` ## Headers Your API access ID provided by Tender **Example:** `"your-access-id-here"` ## Response Status of the API request **Example:** `"success"` Human-readable message describing the result **Example:** `"success"` Array of currencies supported on the specified chain Unique identifier for the currency **Example:** `"avalanche"` Display name of the currency **Example:** `"Avax"` URL to the currency's icon image **Example:** `"https://tender-store.s3.amazonaws.com/icons/avax.png"` Currency symbol **Example:** `"AVAX"` Current status of the currency **Example:** `"active"` Whether this is a smart contract token **Example:** `false` Array of chain identifiers where this currency is available **Example:** `["avalanche"]` Price identifier for market data **Example:** `"avalanche-2"` Fee configuration per chain (chain id to fee string) **Example:** `{ "avalanche": "5" }` Smart contract addresses per chain when isContract is true (chain id to address) **Example:** `{ "avalanche": "0x5425890298aed601595a70AB815c96711a31Bc65", "ethereum": "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238" }` ## Example response ```json theme={null} { "status": "success", "message": "success", "data": [ { "id": "avalanche", "name": "Avax", "icon": "https://tender-store.s3.amazonaws.com/icons/avax.png", "symbol": "AVAX", "status": "active", "isContract": false, "chains": ["avalanche"], "priceTag": "avalanche-2", "fee": { "avalanche": "5" } }, { "id": "usdc", "name": "USDC", "icon": "https://tender-store.s3.amazonaws.com/icons/usdc.png", "symbol": "USDC", "status": "active", "isContract": true, "chains": ["avalanche", "ethereum", "optimism", "aurora", "near", "polygon", "solana", "base", "beam", "stellar", "tron", "8453"], "priceTag": "usd-coin", "fee": { "ethereum": "25", "optimism": "3", "avalanche": "3", "polygon": "3", "solana": "3", "stellar": "3", "base": "5", "beam": "5", "tron": "3" }, "contractAddress": { "avalanche": "0x5425890298aed601595a70AB815c96711a31Bc65", "ethereum": "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238", "optimism": "0xA6d3287496f7d3f1F20521141161448D15393b67", "polygon": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", "solana": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", "stellar": "GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5", "tron": "TEkxiTehnzSmSe2XqrBj4w32RUN966rdz8", "base": "0x53D85F1925fCE8BB93732ed969800Df0b062258A" } }, { "id": "usdt", "name": "USDT", "icon": "https://tender-store.s3.amazonaws.com/icons/usdt.png", "symbol": "USDT", "status": "active", "isContract": true, "chains": ["avalanche", "ethereum", "optimism", "aurora", "near", "polygon", "solana", "tron", "pego"], "priceTag": "tether", "fee": { "ethereum": "25", "optimism": "3", "avalanche": "3", "polygon": "3", "solana": "3", "tron": "3", "pego": "3" }, "contractAddress": { "avalanche": "0xa1Ef10416440A13D555B9Dc78F81153D13340588", "ethereum": "0xFcF3950CFB1aCA9a7733839967126799A4D10fdF", "optimism": "0x94b008aA00579c1307B0EF2c499aD98a8ce58e58", "polygon": "0xc2132D05D31c914a87C6611C10748AEb04B58e8F", "solana": "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB", "tron": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", "pego": "0x02F9Bebf5E54968D8Cc2562356C91ECDE135801B" } } ] } ``` # Fetch Allowed Chains Source: https://docs.tender.cash/api-reference/endpoint/fetch-chains GET /v1/api/system/chains Retrieve all supported blockchain networks and their configuration **Auth method: Basic (Access ID)** — this endpoint only requires your `x-access-id` header. No request signing is needed. See [Authentication](/api-reference/authentication#basic-access-id-authentication). ## Headers Your API access ID provided by Tender **Example:** `"your-access-id-here"` ## Response Status of the API request **Example:** `"success"` Human-readable message describing the result **Example:** `"success"` Container object for chains list and pagination data Array of supported blockchain networks Unique identifier for the chain **Example:** `"8453"` Display name of the blockchain **Example:** `"Base"` URL of the chain icon image (optional) **Example:** `"https://tender-store.s3.amazonaws.com/icons/ethereum.png"` Native coin symbol **Example:** `"ETH"` Type of blockchain (e.g., evm, aptos, btc, sol, ton, tron, xrpl, stellar, move) **Example:** `"evm"` Current status of the chain **Example:** `"active"` Block explorer URL (may be empty string) **Example:** `"https://basescan.org"` Total number of pages available **Example:** `1` Current page number **Example:** `1` Number of items per page **Example:** `40` ## Example response ```json theme={null} { "status": "success", "message": "success", "data": { "data": [ { "id": "", "name": "", "icon": "", "coin": "", "chainType": "", "status": "", "explorer": "" } ], "pages": 1, "page": 1, "limit": 40 } } ``` # Fetch All Currencies Source: https://docs.tender.cash/api-reference/endpoint/fetch-currencies GET /v1/api/system/currency Retrieve all supported currencies with their chain mappings **Auth method: Basic (Access ID)** — this endpoint only requires your `x-access-id` header. No request signing is needed. See [Authentication](/api-reference/authentication#basic-access-id-authentication). ## Headers Your API access ID provided by Tender **Example:** `"your-access-id-here"` ## Response Status of the API request **Example:** `"success"` Human-readable message describing the result **Example:** `"success"` Array of all supported currencies across all chains Unique MongoDB identifier for the currency **Example:** `"64fc4cda43812c15552311d7"` Unique identifier for the currency **Example:** `"usdc"` Display name of the currency **Example:** `"USDC"` URL to the currency's icon image **Example:** `"https://secureapi.tender.cash/icons/usdc.png"` Whether this is a smart contract token **Example:** `true` Array of chains where this currency is available **Example:** `["avalanche", "ethereum", "polygon", "solana"]` Price identifier for market data **Example:** `"usd-coin"` Fee configuration per chain **Example:** `{ "ethereum": "25", "polygon": "3" }` Currency symbol **Example:** `"USDC"` Current status of the currency **Example:** `"active"` Smart contract addresses per chain Contract address on Ethereum **Example:** `"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"` Contract address on Polygon **Example:** `"0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174"` Contract address on Avalanche **Example:** `"0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E"` Activation fees per chain (if applicable) **Example:** `{ "stellar": "1.1" }` Compatible wallet applications **Example:** `["beam"]` ISO 8601 timestamp when the currency was added **Example:** `"2023-09-05T19:29:57.194Z"` ISO 8601 timestamp when the currency was last updated **Example:** `"2024-08-03T23:02:51.067Z"` # Fetch Exchange Rates Source: https://docs.tender.cash/api-reference/endpoint/fetch-exchange-rates GET /v1/api/system/rates/{coin} Get current exchange rate for a cryptocurrency **Auth method: Basic (Access ID)** — this endpoint only requires your `x-access-id` header. No request signing is needed. See [Authentication](/api-reference/authentication#basic-access-id-authentication). ## Path Parameters Coin identifier **Example:** `"bitcoin"` ## Query Parameters Target fiat currency code (optional) **Example:** `"ngn"` ## Headers Your API access ID provided by Tender **Example:** `"your-access-id-here"` ## Response Status of the API request **Example:** `"success"` Human-readable message describing the result **Example:** `"success"` Exchange rate information for the requested coin Coin identifier **Example:** `"bitcoin"` Current price in USD **Example:** `82752` Exchange rate to the target currency **Example:** `127843151.04` Target fiat currency code **Example:** `"ngn"` # Fetch Webhook Source: https://docs.tender.cash/api-reference/endpoint/fetch-webhook GET /v1/api/webhook Get active webhook configuration for the merchant **Auth method: Signed (HMAC)** — this endpoint requires the full set of signed headers: `x-access-id`, `x-request-id`, `x-timestamp`, and an HMAC-SHA256 `authorization` signature. See [Authentication](/api-reference/authentication#signed-hmac-authentication). ## Headers Base64-encoded HMAC-SHA256 signature of the request payload using the API secret **Minimum string length:** `1` **Example:** `"5e73d044c44d733fcf819ad3409aaaddca840d421b69cb0b04e2c750fc62e-ce7526d36296237663ad1f06f62a730c0466516507196b3ce6567493c-c52a7cf63d"` Current timestamp in ISO 8601 format **Example:** `"2025-03-15T09:45:53.000Z"` Unique identifier for the request (UUID v4) **Example:** `"550e8400-e29b-41d4-a716-446655440000"` Your API access ID provided by Tender **Example:** `"your-access-id-here"` ## Response Status of the API request **Example:** `"success"` Human-readable message describing the result **Example:** `"Webhooks fetched"` The active webhook configuration Unique MongoDB identifier for the webhook **Example:** `"69105ed34b9f23d52d1be957"` Merchant ID associated with the webhook **Example:** `"6538e8f9bdec6d1a21978a64"` Description of the webhook **Example:** `"example requests"` Webhook endpoint URL **Example:** `"https://example.com"` Array of subscribed event types **Example:** `["transaction_completed"]` Custom headers for webhook requests **Example:** `{ "api-key": "allow-requior" }` Whether the webhook is currently active **Example:** `true` Whether the webhook has been deleted **Example:** `false` ISO 8601 timestamp when the webhook was created **Example:** `"2025-11-09T09:28:51.401Z"` ISO 8601 timestamp when the webhook was last updated **Example:** `"2025-11-09T09:28:51.401Z"` Version key for MongoDB document **Example:** `0` # Initiate Payment Source: https://docs.tender.cash/api-reference/endpoint/initiate-payment POST /v1/api/payment/initiate Create a new cryptocurrency payment transaction **Auth method: Basic (Access ID)** — this endpoint only requires your `x-access-id` header. No request signing is needed. See [Authentication](/api-reference/authentication#basic-access-id-authentication). ## Headers Your API access ID provided by Tender **Example:** `"your-access-id-here"` Media type of the request body **Example:** `"application/json"` ## Body Payment amount in the specified currency **Example:** `"1.023"` Blockchain network to use for the transaction **Example:** `"avalanche"` Cryptocurrency coin for the payment **Example:** `"avalanche"` Optional reference or transaction ID for your own tracking purposes **Example:** `"ORDER-12345"` Optional metadata attached to the payment The customer's email address **Example:** `"customer@example.com"` ## Response Status of the API request **Example:** `"success"` Human-readable message describing the result **Example:** `"success"` The initiated payment transaction details (uses formatTransactionResponse structure) Unique MongoDB identifier for the transaction **Example:** `"66aec7de809b7f45c42a49f9"` Transaction type **Example:** `"receive"` Blockchain network used **Example:** `"avalanche"` Detailed blockchain network information Chain MongoDB ID **Example:** `"64f782bb4278fc475eb30e29"` Chain display name **Example:** `"Avalanche"` Chain icon URL **Example:** `"https://example.com/avalanche.png"` Chain identifier **Example:** `"avalanche"` Native coin symbol **Example:** `"AVAX"` Chain status **Example:** `"active"` Blockchain explorer URL **Example:** `"https://snowtrace.io"` Type of blockchain **Example:** `"evm"` Whether pre-funded wallets are allowed **Example:** `false` Whether this supports multiple chains **Example:** `false` RPC endpoint URL **Example:** `"https://api.avax.network/ext/bc/C/rpc"` Chain category type **Example:** `"blockchain"` ISO 8601 timestamp **Example:** `"2023-05-29T21:07:27.509Z"` ISO 8601 timestamp **Example:** `"2023-05-29T21:07:27.509Z"` Detailed currency information Currency MongoDB ID **Example:** `"64fc4cda43812c15552311d7"` Currency identifier **Example:** `"avalanche"` Currency full name **Example:** `"Avalanche"` Currency icon URL **Example:** `"https://example.com/avax.png"` Whether this is a smart contract token **Example:** `false` Supported blockchain networks **Example:** `["avalanche"]` Currency symbol **Example:** `"AVAX"` Price tracking identifier **Example:** `"avalanche-2"` Transaction fee **Example:** `"0.001"` Currency status **Example:** `"active"` Currency type **Example:** `"native"` ISO 8601 timestamp **Example:** `"2023-05-29T21:07:27.509Z"` ISO 8601 timestamp **Example:** `"2023-05-29T21:07:27.509Z"` Destination wallet address for payment **Example:** `"0x40b95eddeeac0776ebefc3963bb9ba7d22cbd065"` Index of the wallet address **Example:** `"7"` Amount in cryptocurrency **Example:** `"0.023741"` Equivalent amount in USD **Example:** `"1.02"` Amount in the specified cryptocurrency **Example:** `"0.023741"` Transaction fee in cryptocurrency **Example:** `"0.00023741"` Transaction fee in USD **Example:** `"0.0102"` Whether the fee has been sent **Example:** `false` Wallet activation fee if applicable **Example:** `"0"` Wallet activation fee in USD **Example:** `"0"` Exchange rate used for conversion **Example:** `"43.09"` Agent details receiving the payment Agent MongoDB ID **Example:** `"6538eaaebdec6d1a21978e6a"` Agent first name **Example:** `"John"` Agent last name **Example:** `"Doe"` Agent email address **Example:** `"john@example.com"` Agent avatar URL **Example:** `"https://example.com/avatar.jpg"` Agent phone number **Example:** `"+1234567890"` Agent location **Example:** `"New York, USA"` Total sales amount **Example:** `"1500.50"` Agent country **Example:** `"USA"` Agent address **Example:** `"123 Main St"` Whether agent is active **Example:** `true` Agent unique identifier **Example:** `"AGT-001"` Agent wallet balance **Example:** `"500.00"` Associated merchant ID **Example:** `"6538e8f9bdec6d1a21978a64"` Agent's default fiat currency settings Currency code **Example:** `"USD"` Conversion rate **Example:** `"1"` Whether to use system rate **Example:** `true` Merchant details associated with the transaction Merchant MongoDB ID **Example:** `"6538e8f9bdec6d1a21978a64"` Merchant first name **Example:** `"Jane"` Merchant last name **Example:** `"Smith"` Merchant email address **Example:** `"jane@example.com"` Merchant avatar URL **Example:** `"https://example.com/merchant-avatar.jpg"` Merchant phone number **Example:** `"+1234567890"` Whether merchant is active **Example:** `true` Merchant logo URL **Example:** `"https://example.com/logo.png"` Merchant business name **Example:** `"Example Store"` Merchant description **Example:** `"Online retail store"` Two-factor authentication status **Example:** `false` KYC verification status **Example:** `false` KYC submission status **Example:** `false` Instant conversion enabled **Example:** `false` Default currency **Example:** `"USD"` Merchant wallet balance **Example:** `"1000.00"` Whether merchant is deleted **Example:** `false` Whether wallet was regenerated **Example:** `false` Whether funds have been transferred **Example:** `false` Smart contract address (empty for native tokens) **Example:** `""` Current status of the transaction **Example:** `"pending"` Whether payment is blacklisted **Example:** `false` Actual amount received **Example:** `"0"` Amount received in USD **Example:** `"0"` Balance still required **Example:** `"0.023741"` Balance required in USD **Example:** `"1.02"` Whether this is a partial payment **Example:** `false` Amount in agent's local currency **Example:** `"1.023"` Amount received in agent's currency **Example:** `"0"` Balance required in agent's currency **Example:** `"1.023"` Unique transaction identifier **Example:** `"66aec7de809b7f45c42a49f9"` ISO 8601 timestamp when the transaction was created **Example:** `"2023-05-29T21:07:27.509Z"` ISO 8601 timestamp when the transaction was last updated **Example:** `"2023-05-29T21:07:27.509Z"` # Initiate Payment By Fiat Currency Source: https://docs.tender.cash/api-reference/endpoint/initiate-payment-currency POST /v1/api/payment/initiate/{currency} Create a payment transaction for a specific fiat currency **Auth method: Basic (Access ID)** — this endpoint only requires your `x-access-id` header. No request signing is needed. See [Authentication](/api-reference/authentication#basic-access-id-authentication). ## Path Parameters Currency code for the payment **Example:** `"ngn"` ## Headers Your API access ID provided by Tender **Example:** `"your-access-id-here"` Media type of the request body **Example:** `"application/json"` ## Body Payment amount in the specified currency **Example:** `"1.023"` Blockchain network to use for the transaction **Example:** `"avalanche"` Cryptocurrency for the payment **Example:** `"avalanche"` Optional reference or transaction ID for your own tracking purposes **Example:** `"ORDER-12345"` Optional metadata attached to the payment The customer's email address **Example:** `"customer@example.com"` ## Response Status of the API request **Example:** `"success"` Human-readable message describing the result **Example:** `"success"` The initiated payment transaction details Transaction type **Example:** `"receive"` Blockchain network used **Example:** `"avalanche"` Internal chain identifier **Example:** `"64f782bb4278fc475eb30e29"` Destination wallet address for payment **Example:** `"0x40b95eddeeac0776ebefc3963bb9ba7d22cbd065"` Amount in cryptocurrency **Example:** `"0.023741"` Equivalent amount in USD **Example:** `"1.02"` Amount in the specified cryptocurrency **Example:** `"0.023741"` Transaction fee in cryptocurrency **Example:** `0.00023741007194244602` Transaction fee in USD **Example:** `0.0102` Whether the fee has been sent **Example:** `false` Exchange rate used for conversion **Example:** `43.09` Agent receiving the payment **Example:** `"6538eaaebdec6d1a21978e6a"` Merchant ID associated with the transaction **Example:** `"6538e8f9bdec6d1a21978a64"` Currency identifier **Example:** `"64fc4cda43812c15552311d7"` Amount in agent's local currency **Example:** `"1.023"` Exchange rate for agent's currency **Example:** `"1"` Agent's local currency code **Example:** `"usd"` Unique transaction identifier **Example:** `"66aec7de809b7f45c42a49f9"` # Fetch On-ramp Chains Source: https://docs.tender.cash/api-reference/endpoint/onramp/chains GET /v1/api/onramp/chains List blockchain networks available for on-ramp delivery **Auth method: Signed (HMAC)** — this endpoint requires the full set of signed headers: `x-access-id`, `x-request-id`, `x-timestamp`, and an HMAC-SHA256 `authorization` signature. See [Authentication](/api-reference/authentication#signed-hmac-authentication). ## Headers Base64-encoded HMAC-SHA256 signature using your API secret **Example:** `"2025-03-15T09:45:53.000Z"` **Example:** `"550e8400-e29b-41d4-a716-446655440000"` **Example:** `"your-access-id-here"` ## Response **Example:** `"success"` **Example:** `"success"` Array of supported chains Chain identifier — use as `targetChain` in Initiate On-ramp **Example:** `"tron"` **Example:** `"Tron"` **Example:** `"https://cdn.tender.cash/chains/tron.png"` **Example:** `"tron"` **Example:** `"https://tronscan.org"` **Example:** `"active"` # Fetch On-ramp Coins Source: https://docs.tender.cash/api-reference/endpoint/onramp/coins GET /v1/api/onramp/coins List cryptocurrencies available for on-ramp delivery, optionally filtered by chain **Auth method: Signed (HMAC)** — this endpoint requires the full set of signed headers: `x-access-id`, `x-request-id`, `x-timestamp`, and an HMAC-SHA256 `authorization` signature. See [Authentication](/api-reference/authentication#signed-hmac-authentication). ## Headers Base64-encoded HMAC-SHA256 signature using your API secret **Example:** `"2025-03-15T09:45:53.000Z"` **Example:** `"550e8400-e29b-41d4-a716-446655440000"` **Example:** `"your-access-id-here"` ## Query Parameters Filter coins to those supported on a specific chain. Must match a chain `id` from [Fetch On-ramp Chains](/api-reference/endpoint/onramp/chains). **Example:** `"tron"` ## Response **Example:** `"success"` **Example:** `"success"` Array of supported coins Coin identifier — use as `targetCurrency` in Initiate On-ramp **Example:** `"usdt"` **Example:** `"Tether USD"` **Example:** `"USDT"` **Example:** `"https://cdn.tender.cash/coins/usdt.png"` Chain IDs this coin is available on **Example:** `["tron", "ethereum"]` Whether this is an ERC-20 / TRC-20 token **Example:** `true` **Example:** `true` # Initiate On-ramp Source: https://docs.tender.cash/api-reference/endpoint/onramp/initiate POST /v1/api/onramp/initiate Create an on-ramp request using a valid quote **Auth method: Signed (HMAC)** — this endpoint requires the full set of signed headers: `x-access-id`, `x-request-id`, `x-timestamp`, and an HMAC-SHA256 `authorization` signature. See [Authentication](/api-reference/authentication#signed-hmac-authentication). ## Headers Base64-encoded HMAC-SHA256 signature of the request payload using your API secret **Example:** `"5e73d044c44d733fcf819ad3409aaa..."` **Example:** `"2025-03-15T09:45:53.000Z"` **Example:** `"550e8400-e29b-41d4-a716-446655440000"` **Example:** `"your-access-id-here"` **Example:** `"application/json"` ## Body The `quoteId` returned by [Get On-ramp Quote](/api-reference/endpoint/onramp/quote). Must not be expired or already used. Each quote is single-use. **Example:** `"b7f2a1c3-9d4e-4b2f-a8c0-1e2d3f4a5b6c"` Wallet address that will receive the crypto. Must be valid for the chain specified in the quote. **Example:** `"TRDFGhjkytywooiueonuoo"` Details of the customer making the fiat payment Customer email address **Example:** `"customer@example.com"` Customer full name **Example:** `"Ada Obi"` Optional key-value pairs for your own reference. Values must be strings or numbers. **Example:** `{ "orderId": "ORD-9821", "userId": "usr_42" }` ## Error cases | Condition | Message | | ----------------------------------- | ----------------------------------- | | `quoteId` not found or already used | `"Quote not found or already used"` | | Quote past its `expiresAt` | `"Quote has expired"` | | Missing `quoteId` field | Joi 400 validation error | ## Response **Example:** `"success"` **Example:** `"Onramp initiated"` Unique reference for this on-ramp request. Use this to poll status. **Example:** `"a3f1c2d4-8e7b-4f0a-9c1d-2e3f4a5b6c7d"` Initial status — always `pending_payment` **Example:** `"pending_payment"` Virtual bank account the customer must pay into **Example:** `"0123456789"` **Example:** `"Tender / Ada Obi"` **Example:** `"Wema Bank"` ISO 8601 timestamp after which the virtual bank account expires (1 hour) **Example:** `"2025-06-10T11:00:00.000Z"` Fiat amount the customer must pay (from the quote) **Example:** `50000` Fiat currency (from the quote) **Example:** `"NGN"` **Example:** `"tron"` **Example:** `"TRDFGhjkytywooiueonuoo"` **Example:** `"USDT"` # Get On-ramp Quote Source: https://docs.tender.cash/api-reference/endpoint/onramp/quote POST /v1/api/onramp/quote Fetch a live exchange rate estimate before initiating an on-ramp **Auth method: Signed (HMAC)** — this endpoint requires the full set of signed headers: `x-access-id`, `x-request-id`, `x-timestamp`, and an HMAC-SHA256 `authorization` signature. See [Authentication](/api-reference/authentication#signed-hmac-authentication). ## Headers Base64-encoded HMAC-SHA256 signature of the request payload using your API secret **Example:** `"5e73d044c44d733fcf819ad3409aaa..."` **Example:** `"2025-03-15T09:45:53.000Z"` **Example:** `"550e8400-e29b-41d4-a716-446655440000"` **Example:** `"your-access-id-here"` **Example:** `"application/json"` ## Body Amount the customer will pay in `fiatCurrency`, in whole units (e.g. NGN — not kobo) **Example:** `50000` ISO 4217 fiat currency code. Defaults to `NGN` **Example:** `"NGN"` Symbol of the cryptocurrency to deliver **Example:** `"USDT"` Blockchain network to deliver the crypto on. Use a chain `id` from [Fetch On-ramp Chains](/api-reference/endpoint/onramp/chains). **Example:** `"tron"` ## Response **Example:** `"success"` **Example:** `"Quote generated"` UUID that identifies this quote. Pass this to [Initiate On-ramp](/api-reference/endpoint/onramp/initiate). **Example:** `"b7f2a1c3-9d4e-4b2f-a8c0-1e2d3f4a5b6c"` **Example:** `"NGN"` **Example:** `50000` **Example:** `"USDT"` **Example:** `"tron"` Intermediate currency used during the swap leg (for informational purposes) **Example:** `"usdt"` Intermediate chain used during the swap leg **Example:** `"tron"` Exchange rate: how many `swapCurrency` units per 1 `fiatCurrency` **Example:** `0.000597` Estimated amount of `targetCurrency` the customer will receive, based on `fiatAmount × rate` **Example:** `"29.850000"` ISO 8601 timestamp after which this quote is no longer valid. Initiate before this time. **Example:** `"2025-06-10T10:05:00.000Z"` # Get On-ramp Status Source: https://docs.tender.cash/api-reference/endpoint/onramp/status GET /v1/api/onramp/{reference} Retrieve the current status and stage progress of an on-ramp request **Auth method: Signed (HMAC)** — this endpoint requires the full set of signed headers: `x-access-id`, `x-request-id`, `x-timestamp`, and an HMAC-SHA256 `authorization` signature. See [Authentication](/api-reference/authentication#signed-hmac-authentication). ## Overview Returns the full on-ramp record for a given `reference`. Poll this endpoint after initiating an on-ramp to track which stage the pipeline is on. ### Status values | Status | Meaning | | ----------------- | ---------------------------------------------------------------- | | `pending_payment` | Waiting for the customer's fiat bank transfer | | `processing` | Payment confirmed; pipeline is running | | `crypto_sent` | Crypto dispatched to `targetAddress` | | `completed` | Fully settled | | `failed` | Terminal failure — see `failureReason` and `stages[*].lastError` | ### Stage pipeline Each on-ramp progresses through the following stages in order: | Stage | Description | | -------------- | ------------------------------------------------------------------------------------- | | `payment` | Fiat payment confirmed by the provider | | `payout` | Fiat forwarded to JuicyWay for conversion | | `swap` | JuicyWay swaps fiat → intermediate crypto (e.g. USDT on Tron) | | `swapWithdraw` | Swapped crypto withdrawn from JuicyWay to merchant swap wallet *(skipped by default)* | | `cryptoSend` | Crypto sent from swap wallet to `targetAddress` (direct or via NEAR Intents bridge) | Each stage has its own `status`: `pending` · `in_progress` · `completed` · `failed` · `skipped`. ## Headers Base64-encoded HMAC-SHA256 signature using your API secret **Example:** `"5e73d044c44d733fcf819ad3409aaa..."` **Example:** `"2025-03-15T09:45:53.000Z"` **Example:** `"550e8400-e29b-41d4-a716-446655440000"` **Example:** `"your-access-id-here"` ## Path Parameters The `reference` returned by [Initiate On-ramp](/api-reference/endpoint/onramp/initiate) **Example:** `"a3f1c2d4-8e7b-4f0a-9c1d-2e3f4a5b6c7d"` ## Response **Example:** `"success"` **Example:** `"success"` **Example:** `"a3f1c2d4-8e7b-4f0a-9c1d-2e3f4a5b6c7d"` The quote ID that was used to initiate this request **Example:** `"b7f2a1c3-9d4e-4b2f-a8c0-1e2d3f4a5b6c"` Overall pipeline status **Example:** `"processing"` **Example:** `"tron"` **Example:** `"TRDFGhjkytywooiueonuoo"` **Example:** `"USDT"` **Example:** `"NGN"` **Example:** `"50000"` Fiat amount confirmed by the payment provider **Example:** `"50000"` Amount of `targetCurrency` credited after the swap **Example:** `"29.87"` Bank account details presented to the customer **Example:** `"0123456789"` **Example:** `"Tender / Ada Obi"` **Example:** `"Wema Bank"` **Example:** `"2025-06-09T11:00:00.000Z"` Per-stage progress. Each stage has the same shape. `pending` · `in_progress` · `completed` · `failed` · `skipped` **Example:** `1` **Example:** `"2025-06-09T10:01:00.000Z"` **Example:** `"2025-06-09T10:02:30.000Z"` Set only when status is `failed` Error message from the last failed attempt Stage-specific data (e.g. `swapId`, `withdrawId`, `txRef`) Same shape as `payment` Same shape as `payment` Same shape as `payment`. Status is `skipped` by default. Same shape as `payment` Human-readable reason for terminal failure. Present only when `status` is `failed`. **Example:** `"Swap wallet balance too low: 12 USDT < minimum 100"` **Example:** `"2025-06-09T10:00:00.000Z"` **Example:** `"2025-06-09T10:05:00.000Z"` # Payout Crypto Source: https://docs.tender.cash/api-reference/endpoint/payouts/crypto POST /v1/api/payout/crypto Send a crypto payout directly to a wallet address or saved payout account — no OTP required **Auth method: Signed (HMAC)** — this endpoint requires the full set of signed headers: `x-access-id`, `x-request-id`, `x-timestamp`, and an HMAC-SHA256 `authorization` signature. See [Authentication](/api-reference/authentication#signed-hmac-authentication). ## Headers Base64-encoded HMAC-SHA256 signature of the request payload **Example:** `"5e73d044c44d733fcf819ad3409aaad..."` **Example:** `"2025-03-15T09:45:53.000Z"` Unique UUID v4 **Example:** `"550e8400-e29b-41d4-a716-446655440000"` **Example:** `"your-access-id-here"` **Example:** `"application/json"` ## Body Coin to pay out **Example:** `"usdt"` Chain to send on **Example:** `"tron"` Amount to pay out **Example:** `"50"` Destination wallet address. **Required if `payoutAccountId` is not provided.** **Example:** `"TQn9Y2khDD9JHTfVE5oB2h8BKWWM4LxKLT"` Saved payout account ID. **Required if `address` is not provided.** **Example:** `"66aec7de809b7f45c42a49f9"` ## Response **Example:** `"success"` **Example:** `"success"` The created payout record **Example:** `"66aec7de809b7f45c42a49f9"` **Example:** `"pending"` **Example:** `"50"` **Example:** `"usdt"` **Example:** `"tron"` **Example:** `"TQn9Y2khDD9JHTfVE5oB2h8BKWWM4LxKLT"` **Example:** `"0.5"` **Example:** `"2024-09-24T22:20:15.650Z"` # Calculate Payout Fee Source: https://docs.tender.cash/api-reference/endpoint/payouts/fee GET /v1/api/payout/fee/{chain}/{coin}/{amount} Get a fee estimate for a payout of a given coin/chain amount **Auth method: Signed (HMAC)** — this endpoint requires the full set of signed headers: `x-access-id`, `x-request-id`, `x-timestamp`, and an HMAC-SHA256 `authorization` signature. See [Authentication](/api-reference/authentication#signed-hmac-authentication). ## Headers Your API access ID provided by Tender **Example:** `"your-access-id-here"` ## Path Parameters Chain identifier **Example:** `"tron"` Coin identifier **Example:** `"usdt"` Amount to pay out **Example:** `"50"` ## Response **Example:** `"success"` **Example:** `"success"` Requested payout amount **Example:** `50` Equivalent amount in USD **Example:** `50.00` Payout fee in the coin **Example:** `0.5` Payout fee in USD **Example:** `0.50` Amount delivered after fees are deducted **Example:** `49.5` Normalised coin identifier **Example:** `"usdt"` Chain identifier **Example:** `"tron"` Estimated time for funds to arrive on-chain **Example:** `"1-3 minutes"` # Payout Fiat Source: https://docs.tender.cash/api-reference/endpoint/payouts/fiat POST /v1/api/payout/fiat Convert USDC wallet balance to NGN via a direct bank transfer or an anchor **Auth method: Signed (HMAC)** — this endpoint requires the full set of signed headers: `x-access-id`, `x-request-id`, `x-timestamp`, and an HMAC-SHA256 `authorization` signature. See [Authentication](/api-reference/authentication#signed-hmac-authentication). # Get Payout Source: https://docs.tender.cash/api-reference/endpoint/payouts/get-one GET /v1/api/payout/{id} Retrieve a single payout record by ID **Auth method: Signed (HMAC)** — this endpoint requires the full set of signed headers: `x-access-id`, `x-request-id`, `x-timestamp`, and an HMAC-SHA256 `authorization` signature. See [Authentication](/api-reference/authentication#signed-hmac-authentication). ## Headers Your API access ID provided by Tender **Example:** `"your-access-id-here"` ## Path Parameters The unique payout ID **Example:** `"66aec7de809b7f45c42a49f9"` ## Response **Example:** `"success"` **Example:** `"success"` The payout record **Example:** `"66aec7de809b7f45c42a49f9"` **Example:** `"6538e8f9bdec6d1a21978a64"` **Example:** `"crypto"` **Example:** `"completed"` **Example:** `"50"` **Example:** `"usdt"` **Example:** `"tron"` **Example:** `"TQn9Y2khDD9JHTfVE5oB2h8BKWWM4LxKLT"` **Example:** `"0.5"` **Example:** `"0.50"` **Example:** `"0xabc123..."` **Example:** `"2024-09-24T22:20:15.650Z"` **Example:** `"2024-09-24T22:25:00.000Z"` # List Payouts Source: https://docs.tender.cash/api-reference/endpoint/payouts/list GET /v1/api/payout Retrieve all payouts for your merchant account with pagination **Auth method: Signed (HMAC)** — this endpoint requires the full set of signed headers: `x-access-id`, `x-request-id`, `x-timestamp`, and an HMAC-SHA256 `authorization` signature. See [Authentication](/api-reference/authentication#signed-hmac-authentication). ## Headers Your API access ID provided by Tender **Example:** `"your-access-id-here"` ## Query Parameters Page number for pagination **Example:** `1` Number of records per page **Example:** `10` ## Response **Example:** `"success"` **Example:** `"success"` Paginated payout records Array of payout objects **Example:** `"66aec7de809b7f45c42a49f9"` **Example:** `"6538e8f9bdec6d1a21978a64"` `crypto` or `fiat` **Example:** `"crypto"` **Example:** `"completed"` **Example:** `"50"` **Example:** `"usdt"` **Example:** `"tron"` Destination wallet address (crypto payouts) **Example:** `"TQn9Y2khDD9JHTfVE5oB2h8BKWWM4LxKLT"` **Example:** `"0.5"` On-chain transaction hash (after broadcast) **Example:** `"0xabc123..."` **Example:** `"2024-09-24T22:20:15.650Z"` **Example:** `2` **Example:** `1` **Example:** `10` # Add Deposit Filter Source: https://docs.tender.cash/api-reference/endpoint/subwallets/add-filter POST /v1/api/wallet/filter Register a blockchain address to be monitored for incoming deposits **Auth method: Signed (HMAC)** — this endpoint requires the full set of signed headers: `x-access-id`, `x-request-id`, `x-timestamp`, and an HMAC-SHA256 `authorization` signature. See [Authentication](/api-reference/authentication#signed-hmac-authentication). Registers an address with Tender's deposit monitor. Once registered, any deposit detected on this address triggers a `SUB_USER_WALLET_TRANSACTION_DETECTED` webhook to your server. ## Example ```javascript Node.js theme={null} const res = await fetch(`${BASE}/wallet/filter`, { method: 'POST', headers: makeHeaders(), body: JSON.stringify({ address: '0xabc123...', chains: ['ethereum', 'polygon'], }), }); const { data } = await res.json(); // data.watched → true // data.chains → ['ethereum', 'polygon'] ``` ```python Python theme={null} res = requests.post( f"{BASE}/wallet/filter", headers=make_headers(), json={"address": "0xabc123...", "chains": ["ethereum", "polygon"]}, ) data = res.json()["data"] ``` ## Headers Base64-encoded HMAC-SHA256 signature of the request payload using the API secret **Example:** `"5e73d044c44d733fcf819ad3409aaad..."` Current timestamp in ISO 8601 format **Example:** `"2025-03-15T09:45:53.000Z"` Unique identifier for the request (UUID v4) **Example:** `"550e8400-e29b-41d4-a716-446655440000"` Your API access ID provided by Tender **Example:** `"your-access-id-here"` **Example:** `"application/json"` ## Body The blockchain address to watch. **Example:** `"0xabc123..."` List of chain identifiers on which to watch this address for deposits. **Example:** `["ethereum", "polygon"]` ## Response **Example:** `"success"` **Example:** `"success"` The address that was registered. **Example:** `"0xabc123..."` Confirmation that the address is now being watched. **Example:** `true` The chains on which the address is being monitored. **Example:** `["ethereum", "polygon"]` # Check Watched Address Source: https://docs.tender.cash/api-reference/endpoint/subwallets/check-watched GET /v1/api/wallet/watch/{address} Check whether a blockchain address is currently registered with Tender's deposit monitor **Auth method: Signed (HMAC)** — this endpoint requires the full set of signed headers: `x-access-id`, `x-request-id`, `x-timestamp`, and an HMAC-SHA256 `authorization` signature. See [Authentication](/api-reference/authentication#signed-hmac-authentication). ## Example ```javascript Node.js theme={null} const res = await fetch(`${BASE}/wallet/watch/0xabc123...`, { headers: makeHeaders(), }); const { data } = await res.json(); // data.watched → true | false ``` ```python Python theme={null} res = requests.get( f"{BASE}/wallet/watch/0xabc123...", headers=make_headers(), ) watched = res.json()["data"]["watched"] ``` ## Headers Base64-encoded HMAC-SHA256 signature of the request payload using the API secret **Example:** `"5e73d044c44d733fcf819ad3409aaad..."` Current timestamp in ISO 8601 format **Example:** `"2025-03-15T09:45:53.000Z"` Unique identifier for the request (UUID v4) **Example:** `"550e8400-e29b-41d4-a716-446655440000"` Your API access ID provided by Tender **Example:** `"your-access-id-here"` ## Path Parameters The blockchain address to check. **Example:** `"0xabc123..."` ## Response **Example:** `"success"` **Example:** `"success"` `true` if the address is registered with the deposit monitor. **Example:** `true` # Create Address Source: https://docs.tender.cash/api-reference/endpoint/subwallets/create-address POST /v1/api/wallet/address Generate additional blockchain addresses on specific networks for an existing subwallet **Auth method: Signed (HMAC)** — this endpoint requires the full set of signed headers: `x-access-id`, `x-request-id`, `x-timestamp`, and an HMAC-SHA256 `authorization` signature. See [Authentication](/api-reference/authentication#signed-hmac-authentication). ## Example ```javascript Node.js theme={null} const res = await fetch(`${BASE}/wallet/address`, { method: 'POST', headers: makeHeaders(), body: JSON.stringify({ wallet_reference: 'user-8821', address_reference: 'slot-2', networks: ['ethereum', 'polygon'], }), }); const { data } = await res.json(); /* { wallet_reference: 'user-8821', address_reference: 'slot-2', addresses: [ { network: 'ethereum', address: '0x111...', address_reference: 'slot-2' }, { network: 'polygon', address: '0x222...', address_reference: 'slot-2' } ] } */ ``` ```python Python theme={null} res = requests.post( f"{BASE}/wallet/address", headers=make_headers(), json={ "wallet_reference": "user-8821", "address_reference": "slot-2", "networks": ["ethereum", "polygon"], }, ) data = res.json()["data"] ``` ## Headers Base64-encoded HMAC-SHA256 signature of the request payload using the API secret **Example:** `"5e73d044c44d733fcf819ad3409aaad..."` Current timestamp in ISO 8601 format **Example:** `"2025-03-15T09:45:53.000Z"` Unique identifier for the request (UUID v4) **Example:** `"550e8400-e29b-41d4-a716-446655440000"` Your API access ID provided by Tender **Example:** `"your-access-id-here"` **Example:** `"application/json"` ## Body The reference of the wallet to add addresses to. **Example:** `"user-8821"` A label for this batch of addresses — useful for grouping addresses by deposit slot or asset type. **Example:** `"slot-2"` List of network identifiers to create addresses on. **Example:** `["ethereum", "polygon"]` ## Response **Example:** `"success"` **Example:** `"success"` **Example:** `"user-8821"` **Example:** `"slot-2"` Newly created addresses. **Example:** `"ethereum"` **Example:** `"0xabc123..."` **Example:** `"slot-2"` # Create Wallet Source: https://docs.tender.cash/api-reference/endpoint/subwallets/create-wallet POST /v1/api/wallet Provision a new subwallet for an end-user under your merchant account **Auth method: Signed (HMAC)** — this endpoint requires the full set of signed headers: `x-access-id`, `x-request-id`, `x-timestamp`, and an HMAC-SHA256 `authorization` signature. See [Authentication](/api-reference/authentication#signed-hmac-authentication). ## Example ```javascript Node.js theme={null} const res = await fetch(`${BASE}/wallet`, { method: 'POST', headers: makeHeaders(), body: JSON.stringify({ reference: 'user-8821', }), }); const { data } = await res.json(); /* { reference: 'user-8821', addresses: [ { network: 'ethereum', address: '0xabc...', address_reference: 'ref-1' }, { network: 'polygon', address: '0xdef...', address_reference: 'ref-1' } ] } */ ``` ```python Python theme={null} res = requests.post( f"{BASE}/wallet", headers=make_headers(), json={"reference": "user-8821"}, ) data = res.json()["data"] # data["reference"] → "user-8821" # data["addresses"] → list of address objects ``` ## Headers Base64-encoded HMAC-SHA256 signature of the request payload using the API secret **Example:** `"5e73d044c44d733fcf819ad3409aaad..."` Current timestamp in ISO 8601 format **Example:** `"2025-03-15T09:45:53.000Z"` Unique identifier for the request (UUID v4) **Example:** `"550e8400-e29b-41d4-a716-446655440000"` Your API access ID provided by Tender **Example:** `"your-access-id-here"` **Example:** `"application/json"` ## Body A unique identifier for this wallet within your merchant account. Use your own user ID or any stable string — it must be unique across all wallets you create. **Example:** `"user-8821"` ## Response **Example:** `"success"` **Example:** `"success"` The wallet reference you provided. **Example:** `"user-8821"` Blockchain addresses provisioned for this wallet. The blockchain network. **Example:** `"ethereum"` The blockchain address. **Example:** `"0xabc123..."` An internal reference for this address slot. **Example:** `"ref-1"` # Get Address Balance Source: https://docs.tender.cash/api-reference/endpoint/subwallets/get-balance GET /v1/api/wallet/balance/{address} Fetch the balance of a subwallet blockchain address for a specific chain and currency **Auth method: Signed (HMAC)** — this endpoint requires the full set of signed headers: `x-access-id`, `x-request-id`, `x-timestamp`, and an HMAC-SHA256 `authorization` signature. See [Authentication](/api-reference/authentication#signed-hmac-authentication). ## Example ```javascript Node.js theme={null} const res = await fetch(`${BASE}/wallet/balance/0xabc123...?chain=ethereum¤cy=USDT`, { headers: makeHeaders(), }); const { data } = await res.json(); // data.balance → 8.0 ``` ```python Python theme={null} res = requests.get( f"{BASE}/wallet/balance/0xabc123...", params={"chain": "ethereum", "currency": "USDT"}, headers=make_headers(), ) balance = res.json()["data"]["balance"] # balance → 8.0 ``` ## Headers Base64-encoded HMAC-SHA256 signature of the request payload using the API secret **Example:** `"5e73d044c44d733fcf819ad3409aaad..."` Current timestamp in ISO 8601 format **Example:** `"2025-03-15T09:45:53.000Z"` Unique identifier for the request (UUID v4) **Example:** `"550e8400-e29b-41d4-a716-446655440000"` Your API access ID provided by Tender **Example:** `"your-access-id-here"` ## Path Parameters The blockchain address to query. **Example:** `"0xabc123..."` ## Query Parameters Chain to query. Supported values: `ethereum`, `tron`, `bitcoin`. **Example:** `"ethereum"` Currency symbol to query (e.g. `USDT`, `USDC`, `ETH`). **Example:** `"USDT"` ## Response **Example:** `"success"` **Example:** `"success"` The balance for the specified currency on the specified chain. **Example:** `8.00` ## Error Responses | Condition | Status | Message | | ------------------------------------ | ------ | ---------------------------------------- | | `chain` param missing | 400 | `chain query param is required` | | `currency` param missing | 400 | `currency query param is required` | | Chain not recognised | 400 | `invalid chain: ` | | Chain not supported for subwallets | 400 | `Unsupported chain for subwallets` | | Currency not supported on that chain | 400 | `Unsupported currency for chain ` | # List Addresses Source: https://docs.tender.cash/api-reference/endpoint/subwallets/list-addresses GET /v1/api/wallet/{walletReference}/addresses Retrieve all blockchain addresses for a specific subwallet **Auth method: Signed (HMAC)** — this endpoint requires the full set of signed headers: `x-access-id`, `x-request-id`, `x-timestamp`, and an HMAC-SHA256 `authorization` signature. See [Authentication](/api-reference/authentication#signed-hmac-authentication). ## Example ```javascript Node.js theme={null} const res = await fetch(`${BASE}/wallet/user-8821/addresses?page=1&limit=20`, { headers: makeHeaders(), }); const { data } = await res.json(); /* [ { network: 'ethereum', address: '0xabc...', address_reference: 'ref-1' }, { network: 'polygon', address: '0xdef...', address_reference: 'ref-1' } ] */ ``` ```python Python theme={null} res = requests.get( f"{BASE}/wallet/user-8821/addresses", headers=make_headers(), params={"page": 1, "limit": 20}, ) addresses = res.json()["data"] ``` ## Headers Base64-encoded HMAC-SHA256 signature of the request payload using the API secret **Example:** `"5e73d044c44d733fcf819ad3409aaad..."` Current timestamp in ISO 8601 format **Example:** `"2025-03-15T09:45:53.000Z"` Unique identifier for the request (UUID v4) **Example:** `"550e8400-e29b-41d4-a716-446655440000"` Your API access ID provided by Tender **Example:** `"your-access-id-here"` ## Path Parameters The reference of the wallet whose addresses you want to list. **Example:** `"user-8821"` ## Query Parameters Page number for pagination. Defaults to `1`. **Example:** `1` Number of addresses per page. Defaults to `20`. **Example:** `20` ## Response **Example:** `"success"` **Example:** `"success"` List of address objects. The blockchain network. **Example:** `"ethereum"` The blockchain address. **Example:** `"0xabc123..."` The label assigned to this address slot. **Example:** `"ref-1"` # List Wallets Source: https://docs.tender.cash/api-reference/endpoint/subwallets/list-wallets GET /v1/api/wallet Retrieve all subwallets created under your merchant account **Auth method: Signed (HMAC)** — this endpoint requires the full set of signed headers: `x-access-id`, `x-request-id`, `x-timestamp`, and an HMAC-SHA256 `authorization` signature. See [Authentication](/api-reference/authentication#signed-hmac-authentication). ## Example ```javascript Node.js theme={null} const res = await fetch(`${BASE}/wallet?page=1&limit=20`, { headers: makeHeaders(), }); const { data, total, pages, page, limit } = await res.json(); /* data: [ { wallet_reference: 'user-8821', addresses: [ { network: 'ethereum', address: '0xabc...', address_reference: 'ref-1' } ] } ], total: 42, pages: 3, page: 1, limit: 20 */ ``` ```python Python theme={null} res = requests.get( f"{BASE}/wallet", headers=make_headers(), params={"page": 1, "limit": 20}, ) body = res.json() wallets = body["data"] total = body["total"] ``` ## Headers Base64-encoded HMAC-SHA256 signature of the request payload using the API secret **Example:** `"5e73d044c44d733fcf819ad3409aaad..."` Current timestamp in ISO 8601 format **Example:** `"2025-03-15T09:45:53.000Z"` Unique identifier for the request (UUID v4) **Example:** `"550e8400-e29b-41d4-a716-446655440000"` Your API access ID provided by Tender **Example:** `"your-access-id-here"` ## Query Parameters Page number for pagination. Defaults to `1`. **Example:** `1` Number of wallets per page. Defaults to `20`. **Example:** `20` ## Response **Example:** `"success"` **Example:** `"success"` List of wallet objects. The wallet's unique reference. **Example:** `"user-8821"` All addresses belonging to this wallet. **Example:** `"ethereum"` **Example:** `"0xabc123..."` **Example:** `"ref-1"` Total number of wallets across all pages. **Example:** `42` Total number of pages. **Example:** `3` Current page number. **Example:** `1` Number of results per page. **Example:** `20` # Transfer Funds Source: https://docs.tender.cash/api-reference/endpoint/subwallets/transfer POST /v1/api/wallet/transfer Send native coins or token assets from a subwallet address using a unified endpoint **Auth method: Signed (HMAC)** — this endpoint requires the full set of signed headers: `x-access-id`, `x-request-id`, `x-timestamp`, and an HMAC-SHA256 `authorization` signature. See [Authentication](/api-reference/authentication#signed-hmac-authentication). This endpoint handles both native coin transfers (ETH, TRX, BTC) and token transfers (USDT, USDC) in a single call. Pass `chain` and `currency`. The transfer is submitted on-chain asynchronously. When the transaction confirms, Tender fires a `SUB_USER_WALLET_TRANSFER_CONFIRMED` webhook to your server. **Supported chains:** `ethereum`, `tron`, `bitcoin` ## Example ```javascript Node.js theme={null} // Native coin transfer (e.g. ETH on Ethereum) const res = await fetch(`${BASE}/wallet/transfer`, { method: 'POST', headers: makeHeaders(), body: JSON.stringify({ chain: 'ethereum', currency: 'ethereum', sender: '0xabc123...', receiver: '0x999fff...', amount: 0.01, merchant_reference: 'payout-9921', address_reference: 'slot-2', }), }); const { data } = await res.json(); // data.tx_id → "0xabc123def456..." // Token transfer (e.g. USDT on Tron) const res2 = await fetch(`${BASE}/wallet/transfer`, { method: 'POST', headers: makeHeaders(), body: JSON.stringify({ chain: 'tron', currency: 'usdt', sender: 'TXYZop...', receiver: 'TABCef...', amount: 50, merchant_reference: 'payout-9922', address_reference: 'slot-2', }), }); const { data: data2 } = await res2.json(); // data2.tx_id → "abc123def456..." ``` ```python Python theme={null} import requests, json # Native coin transfer (e.g. ETH on Ethereum) res = requests.post( f"{BASE}/wallet/transfer", headers=make_headers(), json={ "chain": "ethereum", "currency": "ethereum", "sender": "0xabc123...", "receiver": "0x999fff...", "amount": 0.01, "merchant_reference": "payout-9921", "address_reference": "slot-2", }, ) tx_id = res.json()["data"]["tx_id"] # Token transfer (e.g. USDT on Tron) res2 = requests.post( f"{BASE}/wallet/transfer", headers=make_headers(), json={ "chain": "tron", "currency": "usdt", "sender": "TXYZop...", "receiver": "TABCef...", "amount": 50, "merchant_reference": "payout-9922", "address_reference": "slot-2", }, ) tx_id2 = res2.json()["data"]["tx_id"] ``` ## Headers Base64-encoded HMAC-SHA256 signature of the request payload using the API secret **Example:** `"5e73d044c44d733fcf819ad3409aaad..."` Current timestamp in ISO 8601 format **Example:** `"2025-03-15T09:45:53.000Z"` Unique identifier for the request (UUID v4) **Example:** `"550e8400-e29b-41d4-a716-446655440000"` Your API access ID provided by Tender **Example:** `"your-access-id-here"` **Example:** `"application/json"` ## Body The chain to use for the transfer. Supported values: `ethereum`, `tron`, `bitcoin`. **Example:** `"ethereum"` The currency to transfer (e.g. `ethereum`, `usdt`, `usdc`, `bitcoin`). Must be supported on the specified chain. **Example:** `"usdt"` The subwallet address to send from. **Example:** `"0xabc123..."` The destination address. **Example:** `"0x999fff..."` Amount to transfer in human-readable units (e.g. `0.01` ETH, `50` USDT). **Example:** `10.5` Your own reference for this transfer, for idempotency and reconciliation. **Example:** `"payout-9921"` The address reference label of the sender address. **Example:** `"slot-2"` ## Response **Example:** `"success"` **Example:** `"success"` The on-chain transaction hash. **Example:** `"0xabc123def456..."` ## Error Responses | Condition | Status | Message | | -------------------------------------- | ------ | ----------------------------------------------- | | Invalid chain | 400 | `invalid chain: ` | | Invalid currency | 400 | `invalid currency: ` | | Chain not supported for subwallets | 400 | `Unsupported chain for subwallets` | | Currency not valid on that chain | 400 | `Unsupported currency for chain ` | | No contract address for token on chain | 400 | `no contract address for on ` | # Validate Address Source: https://docs.tender.cash/api-reference/endpoint/subwallets/validate-address POST /v1/api/wallet/validate Check whether a blockchain address is valid on one or more networks **Auth method: Signed (HMAC)** — this endpoint requires the full set of signed headers: `x-access-id`, `x-request-id`, `x-timestamp`, and an HMAC-SHA256 `authorization` signature. See [Authentication](/api-reference/authentication#signed-hmac-authentication). ## Example ```javascript Node.js theme={null} const res = await fetch(`${BASE}/wallet/validate`, { method: 'POST', headers: makeHeaders(), body: JSON.stringify({ address: '0xabc123...', networks: ['ethereum'], }), }); const { data } = await res.json(); // data.valid → true ``` ```python Python theme={null} res = requests.post( f"{BASE}/wallet/validate", headers=make_headers(), json={"address": "0xabc123...", "networks": ["ethereum"]}, ) valid = res.json()["data"]["valid"] ``` ## Headers Base64-encoded HMAC-SHA256 signature of the request payload using the API secret **Example:** `"5e73d044c44d733fcf819ad3409aaad..."` Current timestamp in ISO 8601 format **Example:** `"2025-03-15T09:45:53.000Z"` Unique identifier for the request (UUID v4) **Example:** `"550e8400-e29b-41d4-a716-446655440000"` Your API access ID provided by Tender **Example:** `"your-access-id-here"` **Example:** `"application/json"` ## Body The blockchain address to validate. **Example:** `"0xabc123..."` List of network identifiers to validate the address against. **Example:** `["ethereum"]` ## Response **Example:** `"success"` **Example:** `"success"` `true` if the address is valid on all specified networks, `false` otherwise. **Example:** `true` # Validate Payment Source: https://docs.tender.cash/api-reference/endpoint/validate-payment POST /v1/api/payment/validate/{id} Validate a payment transaction by ID **Auth method: Basic (Access ID)** — this endpoint only requires your `x-access-id` header. No request signing is needed. See [Authentication](/api-reference/authentication#basic-access-id-authentication). ## Path Parameters Transaction ID to validate **Example:** `"6475140f90e4c515f231fcea"` ## Headers Your API access ID provided by Tender **Example:** `"your-access-id-here"` ## Response Status of the API request **Example:** `"success"` Human-readable message describing the result **Example:** `"payment received"` The validated payment transaction details Unique MongoDB identifier for the transaction **Example:** `"6475140f90e4c515f231fcea"` Transaction type **Example:** `"receive"` Blockchain network used **Example:** `"ethereum"` Detailed blockchain network information Chain MongoDB ID **Example:** `"64f782bb4278fc475eb30e29"` Chain display name **Example:** `"Ethereum"` Chain icon URL **Example:** `"https://example.com/ethereum.png"` Chain identifier **Example:** `"ethereum"` Native coin symbol **Example:** `"ETH"` Chain status **Example:** `"active"` Blockchain explorer URL **Example:** `"https://etherscan.io"` Type of blockchain **Example:** `"evm"` Whether pre-funded wallets are allowed **Example:** `false` Whether this supports multiple chains **Example:** `false` RPC endpoint URL **Example:** `"https://eth-mainnet.g.alchemy.com/v2/..."` Chain category type **Example:** `"blockchain"` ISO 8601 timestamp **Example:** `"2023-05-29T21:07:27.509Z"` ISO 8601 timestamp **Example:** `"2023-05-29T21:07:27.509Z"` Detailed currency information Currency MongoDB ID **Example:** `"6454b021cf6b3b771926792e"` Currency identifier **Example:** `"usdt"` Currency full name **Example:** `"Tether USD"` Currency icon URL **Example:** `"https://example.com/usdt.png"` Whether this is a smart contract token **Example:** `true` Supported blockchain networks **Example:** `["ethereum", "bsc", "polygon"]` Currency symbol **Example:** `"USDT"` Price tracking identifier **Example:** `"tether"` Transaction fee **Example:** `"0.001"` Currency status **Example:** `"active"` Currency type **Example:** `"token"` ISO 8601 timestamp **Example:** `"2023-05-29T21:07:27.509Z"` ISO 8601 timestamp **Example:** `"2023-05-29T21:07:27.509Z"` Wallet address involved in the transaction **Example:** `"0xC6FF2283472C0403a178D8E565D50588DefAc85B"` Wallet address index **Example:** `"0"` Transaction amount in cryptocurrency **Example:** `"0.0001"` Transaction amount in USD **Example:** `"0.1893"` Amount in coin denomination **Example:** `"0.0001"` Transaction fee **Example:** `"0"` Transaction fee in USD **Example:** `"0"` Whether the fee has been sent **Example:** `false` Wallet activation fee **Example:** `"0"` Wallet activation fee in USD **Example:** `"0"` Exchange rate used **Example:** `"1893"` Agent details associated with the transaction Agent MongoDB ID **Example:** `"6473034c48441d031ed5f299"` Agent first name **Example:** `"John"` Agent last name **Example:** `"Doe"` Agent email address **Example:** `"john@example.com"` Agent avatar URL **Example:** `"https://example.com/avatar.jpg"` Agent phone number **Example:** `"+1234567890"` Agent location **Example:** `"New York, USA"` Total sales amount **Example:** `"1500.50"` Agent country **Example:** `"USA"` Agent address **Example:** `"123 Main St"` Whether agent is active **Example:** `true` Agent unique identifier **Example:** `"AGT-001"` Agent wallet balance **Example:** `"500.00"` Associated merchant ID **Example:** `"647302dea2f273c67b878a66"` Agent's default fiat currency settings Currency code **Example:** `"USD"` Conversion rate **Example:** `"1"` Whether to use system rate **Example:** `true` Merchant details associated with the transaction Merchant MongoDB ID **Example:** `"647302dea2f273c67b878a66"` Merchant first name **Example:** `"Jane"` Merchant last name **Example:** `"Smith"` Merchant email address **Example:** `"jane@example.com"` Merchant avatar URL **Example:** `"https://example.com/merchant-avatar.jpg"` Merchant phone number **Example:** `"+1234567890"` Whether merchant is active **Example:** `true` Merchant logo URL **Example:** `"https://example.com/logo.png"` Merchant business name **Example:** `"Example Store"` Merchant description **Example:** `"Online retail store"` Two-factor authentication status **Example:** `false` KYC verification status **Example:** `false` KYC submission status **Example:** `false` Instant conversion enabled **Example:** `false` Default currency **Example:** `"USD"` Merchant wallet balance **Example:** `"1000.00"` Whether merchant is deleted **Example:** `false` Whether wallet was regenerated **Example:** `false` Whether funds have been transferred **Example:** `false` Smart contract address (for token transactions) **Example:** `""` Current status of the transaction **Example:** `"completed"` Whether payment is blacklisted **Example:** `false` Actual amount received **Example:** `"0.0001"` Amount received in USD **Example:** `"0.1893"` Balance still required **Example:** `"0"` Balance required in USD **Example:** `"0"` Whether this is a partial payment **Example:** `false` Amount in agent's currency **Example:** `"0.1893"` Amount received in agent's currency **Example:** `"0.1893"` Balance required in agent's currency **Example:** `"0"` Unique transaction identifier **Example:** `"6475140f90e4c515f231fcea"` ISO 8601 timestamp when the transaction was created **Example:** `"2023-05-29T21:07:27.509Z"` ISO 8601 timestamp when the transaction was last updated **Example:** `"2023-05-29T21:07:27.509Z"` # Get Webhook Logs Source: https://docs.tender.cash/api-reference/endpoint/webhook-logs GET /v1/api/webhook/logs Retrieve paginated webhook delivery logs **Auth method: Signed (HMAC)** — this endpoint requires the full set of signed headers: `x-access-id`, `x-request-id`, `x-timestamp`, and an HMAC-SHA256 `authorization` signature. See [Authentication](/api-reference/authentication#signed-hmac-authentication). ## Headers Base64-encoded HMAC-SHA256 signature of the request payload using the API secret **Minimum string length:** `1` **Example:** `"5e73d044c44d733fcf819ad3409aaaddca840d421b69cb0b04e2c750fc62e-ce7526d36296237663ad1f06f62a730c0466516507196b3ce6567493c-c52a7cf63d"` Current timestamp in ISO 8601 format **Example:** `"2025-03-15T09:45:53.000Z"` Unique identifier for the request (UUID v4) **Example:** `"550e8400-e29b-41d4-a716-446655440000"` Your API access ID provided by Tender **Example:** `"your-access-id-here"` ## Response Status of the API request **Example:** `"success"` Human-readable message describing the result **Example:** `"Webhook logs fetched"` Webhook delivery logs and pagination data Array of webhook delivery log entries Unique identifier for the log entry **Example:** `"691069ff947a702cfad9e862"` ID of the webhook that was triggered **Example:** `"691069ff947a702cfad9e861"` Type of event that triggered the webhook **Example:** `"transaction_completed"` Delivery status (success, failed, pending) **Example:** `"success"` HTTP status code from webhook endpoint **Example:** `200` Data sent to the webhook endpoint Response received from the webhook endpoint Number of delivery attempts **Example:** `1` ISO 8601 timestamp when the log entry was created **Example:** `"2025-11-09T10:20:00.000Z"` Total number of log entries **Example:** `0` Total number of pages available **Example:** `0` # Errors Source: https://docs.tender.cash/api-reference/errors Tender follows follows the conventional HTTP status codes. Code in the range of 2xx indicate success, while codes in the range of 4xx indicates that the request failed as a result of the something provided in the request data. And codes in the range 5xx are unexpected server errors. ## Error envelope On error, responses are wrapped in the same envelope shape as successful responses: ```json theme={null} { "status": "error", "message": "human readable description", "data": null } ``` Some endpoints may include additional fields in `data` with more context about the failure. ## HTTP status codes | Code | Name | Description | | ---- | -------------------- | ---------------------------------------------------------------------------------- | | 200 | OK | Request succeeded. | | 201 | Created | Request succeeded and a new resource was created. | | 202 | Accepted | Request accepted for processing (e.g. webhook fetch / logs). | | 400 | Bad Request | The request is malformed or missing required parameters. | | 401 | Unauthorized | Authentication failed – missing, invalid, or expired credentials / signature. | | 403 | Forbidden | Authenticated, but not allowed to access this resource. | | 404 | Not Found | Resource does not exist or is not visible to this merchant. | | 409 | Conflict | Conflicting request (for example, duplicate action on the same resource). | | 422 | Unprocessable Entity | Payload validation error – fields are present but invalid. | | 429 | Too Many Requests | Rate limit exceeded; back off and retry later. | | 5xx | Server Error | Unexpected error while processing the request – retry with backoff if appropriate. | ## Working with validation errors When you receive a `400` or `422` response, check: * The request body matches the documented schema (field names and types). * Path parameters (for example, `:id`, `:currency`, `:coin`) are present and valid. * Authentication headers from the **Authentication** section are correctly set. Fix the offending fields and retry the request. If errors persist with a seemingly correct payload, capture the full response body and contact support.\*\*\* End Patch # Getting API Credentials Source: https://docs.tender.cash/get-started/api-credentials Generate and manage your Tender API credentials for authentication ## Overview Tender secures API requests with two authentication methods — Signed (HMAC) for most endpoints, and Basic (Access ID) for Payment and System endpoints (see [Authentication](/api-reference/authentication)). You'll need two credentials: 1. **Access ID** - Your public API identifier, sent with every request 2. **Access Secret** - Your private key for signing requests to Signed (HMAC) endpoints Never share your Access Secret or commit it to version control. Treat it like a password. *** ## Generating API Credentials Navigate to [sandbox-merchant.tender.cash](https://sandbox-merchant.tender.cash) (sandbox) or [merchant.tender.cash](https://merchant.tender.cash) (live) and log in to your account. * Click on **Settings** in the sidebar * Select **API Credentials** * Click **Generate New Credentials** * Give your credentials a descriptive name (e.g., "Production API", "Dev Server") **Important**: Copy and securely store both credentials immediately. The Access Secret will only be shown once. * **Access ID**: Copy this value * **Access Secret**: Copy this value (shown only once) * Store them in a secure location (password manager, environment variables, secrets manager) *** ## Test vs Production Credentials **Test Credentials** are for: * Development and integration * Testing payment flows * Webhook testing * Uses testnet cryptocurrencies ```text theme={null} Base URL: https://sandbox-api.tender.cash ``` **Production Credentials** are for: * Live transactions * Real cryptocurrency payments * Production webhooks * Uses mainnet cryptocurrencies ```text theme={null} Base URL: https://secureapi.tender.cash ``` Only use production credentials after thorough testing in the test environment. *** ## Managing Credentials ### Viewing Active Credentials In the dashboard, you can: * View all active API credentials * See last used date * Check usage statistics * View credential names and environments ### Revoking Credentials If credentials are compromised: Create replacement credentials immediately Deploy new credentials to all systems Delete compromised credentials from dashboard Check that all systems are working with new credentials *** ## Next Steps Learn how to sign API requests with your credentials Make your first API call *** ## Troubleshooting **Possible causes:** * Incorrect Access ID or Secret * Invalid HMAC signature * Using test credentials on production endpoint (or vice versa) **Solution:** Verify your credentials and signature generation **Check:** * Are you using the correct environment (test vs production)? * Have the credentials been revoked? * Is the timestamp in the correct format? * Is the signature generated correctly? # OpenAPI Specification Source: https://docs.tender.cash/get-started/api-specification ## Tender API Specification (1.0.0) Prefer to use OpenAPI tooling? You can access our full OpenAPI spec directly or import it to Postman, Insomnia, or other API clients: Get the complete OpenAPI 3.1.0 specification for Tender API ### What You Can Do With the OpenAPI Spec * **Import to Postman or Insomnia** - Generate a complete API collection with all endpoints * **Generate API Clients** - Use tools like OpenAPI Generator to create SDK code * **API Testing** - Automate testing with tools that support OpenAPI specs * **Documentation** - Generate custom documentation using Swagger UI or similar tools * **Validation** - Validate request/response payloads against the schema ### Using with Postman 1. Open Postman 2. Click **Import** in the top left 3. Choose **Link** and paste: `https://docs.tender.cash/api-reference/openapi.json` 4. Click **Continue** and then **Import** 5. Your Tender API collection is ready to use! ### Using with OpenAPI Generator Generate client libraries in your preferred language: ```bash theme={null} # Install OpenAPI Generator npm install @openapitools/openapi-generator-cli -g # Generate a Node.js client openapi-generator-cli generate \ -i https://docs.tender.cash/api-reference/openapi.json \ -g javascript \ -o ./tender-client ``` # Create Account Source: https://docs.tender.cash/get-started/create-account Sign up for a Tender account to start accepting cryptocurrency payments ## Getting Started with Tender To start accepting cryptocurrency payments with Tender, you'll need to create a merchant account. Follow these steps to get started: *** ## Step 1: Sign Up Visit the Tender website and click on the "Sign Up" or "Get Started" button. Go to [https://tender.cash](https://tender.cash) and click "Sign Up" Fill in your business details: * Business name * Business email * Country * Business type Set up your account credentials: * Create a secure password * Verify your email address *** ## Step 2: Complete KYC Verification To comply with regulatory requirements, you'll need to complete Know Your Customer (KYC) verification: **Required Documents:** * Government-issued ID (passport, driver's license, or national ID) * Proof of address (utility bill or bank statement) * Selfie for identity verification **Required Documents:** * Business registration documents * Tax identification number * Director/owner identification * Proof of business address * Bank account information KYC verification typically takes 1-3 business days. You'll receive an email notification once your account is approved. *** ## Step 3: Access Your Dashboard Once your account is verified, you can access the Tender Dashboard: * View transaction history * Monitor wallet balances * Manage agents and sub-businesses * Generate API credentials * Configure webhooks * View analytics and reports *** ## Step 4: Configure Your Account Before going live, configure your account settings: Use the test environment to: * Test API integration * Simulate transactions * Verify webhook delivery * Test payment flows Test environment uses testnet cryptocurrencies with no real value. Production environment for: * Real cryptocurrency transactions * Live customer payments * Actual fund settlements Ensure thorough testing before switching to production. *** ## Next Steps Generate your API keys to start integration Make your first API call *** ## Need Help? For assistance with account creation, reach out to our support team: * **Email**: [support@tender.cash](mailto:support@tender.cash) * **Documentation**: [docs.tender.cash](https://docs.tender.cash) * **Support Portal**: [support.tender.cash](https://support.tender.cash) # Definitions Source: https://docs.tender.cash/get-started/definitions Below are essential terms you'll encounter while integrating Tender. Understanding these will help ensure smooth implementation, testing, and reconciliation of transactions. ## Authentication & Security #### Access ID A public credential used to identify your account when making API requests. This identifier is passed in the `x-access-id` header with every request. #### Access Secret A private credential used for signing and verifying API requests. You must use your secret to generate HMAC signatures for authentication. Never share this key or commit it to version control. #### Signing Requests Most Tender API endpoints require requests to be signed using HMAC-SHA256 with your Access Secret. This ensures that requests are legitimate and have not been tampered with during transmission. Payment and System endpoints use Basic (Access ID) authentication instead and don't require a signature — see [Authentication](/api-reference/authentication) for which method each endpoint group uses. *** ## Environments We have two environments in Tender: | Environment | Details | | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Test** | A sandbox environment used during development and testing. It allows developers to simulate payment flows and API interactions using testnet cryptocurrencies. No actual funds are processed. | | **Production** | The live environment where real cryptocurrency transactions occur. It processes actual payments on mainnet blockchains and should only be accessed with secure, verified credentials. | *** ## Payments #### Agent A sub-business or merchant account that can receive cryptocurrency payments independently. Agents have their own wallet addresses and can be managed through the Tender API. #### Payment Initiation The process of creating a new cryptocurrency payment request. Returns a wallet address where the customer can send funds on their chosen blockchain. #### Chain A blockchain network (e.g., Ethereum, Polygon, BSC) where cryptocurrency transactions are processed. Tender supports multiple chains for flexibility. #### Coin/Currency The specific cryptocurrency used for payment (e.g., USDT, USDC, ETH). Each chain may support multiple currencies. #### Fiat Currency Traditional government-issued currency that is not backed by a physical commodity but by the government that issued it (e.g., USD, EUR, NGN, GBP). In Tender's context, fiat currencies are used as the base currency for pricing and conversions. When initiating a payment by fiat currency, you specify the amount in fiat (e.g., \$100 USD), and Tender calculates the equivalent cryptocurrency amount based on current exchange rates. #### Transaction Validation The confirmation of a cryptocurrency payment after it has been broadcast and confirmed on the blockchain. Returns the transaction status and details. *** ## Integration Terms #### Webhook A real-time notification sent to your server when certain events occur (e.g., transaction completed, payment failed). Webhooks are configured with a callback URL and optional custom headers. #### Callback URL The endpoint on your system where Tender sends webhook events. It must be accessible over HTTPS and respond with a 2xx status code. #### Exchange Rate The conversion rate between cryptocurrencies and fiat currencies (e.g., USDT to USD). Tender provides real-time exchange rate data through the API. #### Request ID A unique identifier (UUID) for each API request, passed in the `x-request-id` header. Used for request tracking and idempotency. #### Timestamp The Unix timestamp (in milliseconds) when a request is made, passed in the `x-timestamp` header. Used as part of the HMAC signature generation. *** ## Blockchain Terms #### Wallet Address A unique cryptographic address on a blockchain where cryptocurrency can be received. Each agent has wallet addresses for supported chains. #### Confirmation The number of blocks added to the blockchain after a transaction is included. More confirmations mean higher security and finality. #### Gas Fee The transaction fee paid to blockchain validators/miners for processing a transaction. Gas fees vary by network and congestion. #### Testnet A parallel blockchain network used for testing without using real cryptocurrency. Useful for development and integration testing. #### Mainnet The primary blockchain network where real transactions with actual value occur. Used in production environments. # Use Cases Source: https://docs.tender.cash/get-started/use-cases #### Multi-Location Businesses with Cryptocurrency Payments Businesses with multiple locations or franchises can create separate agents for each location, enabling independent cryptocurrency payment tracking and reconciliation per branch. #### E-commerce Platforms Accepting Crypto Online stores can integrate Tender to accept cryptocurrency payments across multiple blockchains, giving customers flexibility to pay with their preferred chain and stablecoin. #### Marketplace Platforms with Multiple Merchants Marketplaces can assign each seller their own agent account with unique wallet addresses, simplifying payment routing and settlement for multi-vendor platforms. #### Cross-Border Payment Solutions Businesses serving international customers can leverage cryptocurrency payments to avoid traditional banking fees, currency conversion costs, and lengthy settlement times. #### Payment Links for Social Commerce Generate cryptocurrency payment requests that can be shared via WhatsApp, Telegram, or social media to collect payments remotely without building a full checkout page. #### White-Label Payment Infrastructure Fintech platforms and payment service providers can build on Tender's infrastructure to offer cryptocurrency payment capabilities to their merchants with custom branding. # Webhook Events Source: https://docs.tender.cash/get-started/webhook-events ## Supported Events We'll keep expanding this list as we add more webhooks. | Event Type | Description | | ---------------------------- | ---------------------------------------------------------------------------- | | transaction\_completed | A payment transaction was successfully completed and confirmed on blockchain | | transaction\_overpayment | A transaction received more than the expected amount | | transaction\_partially\_paid | A transaction received partial payment, less than the expected amount | | transaction\_requested | A new payment transaction has been initiated | | transaction\_reserved | A transaction has been reserved and is awaiting payment | | transaction\_cancelled | A transaction was cancelled before completion | # Webhooks Source: https://docs.tender.cash/get-started/webhooks Receive real-time notifications about events in your Tender account Webhooks (or callbacks) let you automatically receive asynchronous events from Tender when important events happen — like when a payment status changes or a transaction gets completed. ## Register your webhook URLs Webhooks are currently registered when you call APIs via the `callbackUrl` field. *** ## Webhook Structure All webhooks have the same payload structure. * `event`: the name of the event * `data`: event data specific to the event being sent Example webhook payload: ```json theme={null} { "event": "transaction_completed", "data": { "txId": "66aec7de809b7f45c42a49f9", "type": "receive", "chain": "ethereum", "amount": "0.001", "usdAmount": "2.50", "walletAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", "agentId": "6538eaaebdec6d1a21978e6a", "merchantId": "6538e8f9bdec6d1a21978a64", "status": "completed", "createdAt": "2025-01-21T12:30:00.000Z", "completedAt": "2025-01-21T12:34:56.789Z" } } ``` *** ## Webhook Retries Always acknowledge a webhook instantly by responding with `2xx`, else it will be considered as failed. Failed webhooks are retried with constant backoff for a maximum of 3 times with a delay of 1 minute. *** ## Webhook Security To ensure you are receiving webhooks from Tender, you can define custom headers that will be included with every webhook request. These headers allow you to verify that the webhook is originating from Tender and not from a malicious source. ### Setting Custom Headers When registering a webhook via the API, you can specify custom headers that Tender will include in all webhook requests: ```javascript theme={null} const response = await fetch('https://secureapi.tender.cash/v1/api/webhook', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-access-id': accessId, 'x-request-id': requestId, 'x-timestamp': timestamp, 'authorization': signature }, body: JSON.stringify({ url: 'https://your-domain.com/webhooks/tender', description: 'Production webhook', eventTypes: ['transaction_completed', 'transaction_failed'], headers: { 'X-Webhook-Secret': 'your-secret-key-here', 'X-Api-Version': 'v1' } }) }); ``` ### Verifying Custom Headers On your webhook endpoint, verify the custom headers to ensure the request is from Tender: ```javascript theme={null} const express = require('express'); const app = express(); const WEBHOOK_SECRET = 'your-secret-key-here'; // Same as defined in webhook registration app.post('/webhooks/tender', express.json(), (req, res) => { // Verify the custom header const webhookSecret = req.headers['x-webhook-secret']; if (webhookSecret !== WEBHOOK_SECRET) { return res.status(401).json({ error: 'Unauthorized' }); } // Process the webhook const { event, data } = req.body; console.log('Verified webhook:', event); // Acknowledge receipt res.status(200).json({ received: true }); }); app.listen(3000); ``` ### Best Practices * Use strong, randomly generated values for your custom headers * Keep your custom header values secret and secure * Rotate your webhook secrets periodically * Always validate the custom headers before processing webhook data * Consider using multiple headers for additional security layers # Conversions Source: https://docs.tender.cash/guides/conversions Swap crypto to another coin/chain or convert to a fiat payout account A conversion moves funds from one form to another without requiring the customer to make a new payment. There are two types: | Type | What it does | | -------- | ---------------------------------------------------------------------------------------- | | `crypto` | Swaps a coin on one chain to a different coin or chain (e.g. USDT/Ethereum → SOL/Solana) | | `fiat` | Converts crypto balance to fiat and sends it to a saved payout account | *** ## How it works Call `GET /conversions/swap-chains` and `GET /conversions/swap-coins` to find what source/destination pairs are available. Call `GET /conversions/fee/{chain}/{coin}/{amount}` to get a fee quote and estimated output before committing. For crypto swaps, pass `toChain` and `toCoin` as query params to get a destination-specific estimate. Call `POST /conversions` with the source coin, chain, amount, and destination. The conversion is queued immediately and processed asynchronously. Call `GET /conversions/{id}` to track `processingStages` until the conversion settles. *** ## Prerequisites These endpoints use Signed (HMAC) authentication — an HMAC-SHA256 signature is required on every request. See the authentication guide for code examples. ```javascript theme={null} const BASE = 'https://sandbox-api.tender.cash/v1/api'; // makeHeaders() → { 'x-access-id', 'x-request-id', 'x-timestamp', 'authorization', ... } ``` *** ## Step 1 — Check the fee Always fetch a fee quote before creating a conversion so you can show the cost to the user. ```javascript Node.js theme={null} // Crypto swap fee quote const feeRes = await fetch( `${BASE}/conversions/fee/ethereum/usdt/100?toChain=solana&toCoin=sol`, { headers: makeHeaders() } ); const { data: fee } = await feeRes.json(); /* { amount: 100, amountUSD: 100.00, fee: 0.5, feeUSD: 0.50, amountAfterFee: 99.5, estimatedOutput: 1.24, rate: 0.0125 } */ ``` ```python Python theme={null} fee_res = requests.get( f"{BASE}/conversions/fee/ethereum/usdt/100", params={ "toChain": "solana", "toCoin": "sol" }, headers=make_headers(), ) fee = fee_res.json()["data"] ``` *** ## Step 2 — Create a crypto swap ```javascript Node.js theme={null} const convRes = await fetch(`${BASE}/conversions`, { method: 'POST', headers: makeHeaders(), body: JSON.stringify({ type: 'crypto', chain: 'ethereum', coin: 'usdt', amount: '100', toChain: 'solana', toCoin: 'sol', }), }); const { data } = await convRes.json(); const conversionId = data.conversion._id; console.log('Status:', data.conversion.status); // "pending" ``` ```python Python theme={null} conv_res = requests.post( f"{BASE}/conversions", headers=make_headers(), json={ "type": "crypto", "chain": "ethereum", "coin": "usdt", "amount": "100", "toChain": "solana", "toCoin": "sol", }, ) conversion = conv_res.json()["data"]["conversion"] conversion_id = conversion["_id"] ``` *** ## Step 2 (alt) — Create a fiat conversion To convert to fiat, supply a `payoutAccountId` instead of `toChain`/`toCoin`. ```javascript Node.js theme={null} const convRes = await fetch(`${BASE}/conversions`, { method: 'POST', headers: makeHeaders(), body: JSON.stringify({ type: 'fiat', chain: 'ethereum', coin: 'usdt', amount: '100', payoutAccountId: '66aec7de809b7f45c42a49f9', }), }); ``` ```python Python theme={null} conv_res = requests.post( f"{BASE}/conversions", headers=make_headers(), json={ "type": "fiat", "chain": "ethereum", "coin": "usdt", "amount": "100", "payoutAccountId": "66aec7de809b7f45c42a49f9", }, ) ``` *** ## Step 3 — Poll for completion ```javascript Node.js theme={null} async function pollConversion(id, intervalMs = 8000) { while (true) { const res = await fetch(`${BASE}/conversions/${id}`, { headers: makeHeaders() }); const { data } = await res.json(); const stages = data.processingStages; console.log('Stages:', stages); const allDone = Object.values(stages).every(s => s.status === 'completed'); if (allDone) return data; const failed = Object.values(stages).find(s => s.status === 'failed'); if (failed) throw new Error('Conversion failed'); await new Promise(r => setTimeout(r, intervalMs)); } } ``` ```python Python theme={null} import time def poll_conversion(conversion_id, interval_s=8): while True: res = requests.get(f"{BASE}/conversions/{conversion_id}", headers=make_headers()) data = res.json()["data"] stages = data["processingStages"] if all(s["status"] == "completed" for s in stages.values()): return data if any(s["status"] == "failed" for s in stages.values()): raise RuntimeError("Conversion failed") time.sleep(interval_s) ``` *** ## Processing stages | Stage | What happens | | ------------------- | ---------------------------------------- | | `sendForConversion` | Funds sent to the conversion provider | | `conversionState` | Provider executes the swap | | `settleCrypto` | Converted funds delivered to destination | *** ## Error handling | Scenario | Action | | ------------------------ | ------------------------------------------------------------------------------- | | Amount below minimum | Check `fee.amountAfterFee > 0` before creating | | Unsupported swap pair | Verify pair exists via `/conversions/swap-chains` and `/conversions/swap-coins` | | Stage `status: "failed"` | Read the stage's `lastError` field; retry or contact support | # Bulk Disbursements Source: https://docs.tender.cash/guides/disbursements Pay multiple recipients at once using USDC or XLM on the Stellar network Tender's disbursement feature lets you send funds to many recipients in a single action. Each recipient receives an invitation to claim their payment directly into their Tender loyalty wallet. Disbursement flow demo *** ## How it works Collect each recipient's contact (email or phone), a unique ID, the amount, and their date of birth for verification. Go to **Wallet → Actions → Disburse** in your merchant dashboard, fill in the details, and upload a CSV or enter recipients manually. Tender debits your Stellar platform balance and transfers the total to the Stellar Disbursement Platform distribution account on-chain. Each recipient receives an invitation via email or SMS. They click the link, verify their identity, and funds are credited to their Tender loyalty wallet. *** ## Prerequisites Your merchant account must be fully KYC verified before you can disburse. You must hold the asset you want to disburse (USDC or XLM) in your Tender platform wallet. The full total is debited at submission time. *** ## Supported assets | Asset | Network | Notes | | ----- | ------- | ----------------------------------------------------------- | | USDC | Stellar | Settled to recipient's Tender loyalty wallet | | XLM | Stellar | Native asset — settled to recipient's Tender loyalty wallet | *** ## CSV format Upload a `.csv` file with the following columns: ```csv theme={null} contact,id,amount,verification alice@example.com,cust-001,10.00,1990-05-20 bob@example.com,cust-002,25.50,1985-11-03 +2348012345678,cust-003,5.00,1992-08-14 ``` | Column | Type | Description | | -------------- | ------ | ---------------------------------------------------------------------------- | | `contact` | string | Recipient email address or phone number (E.164 format for phone) | | `id` | string | Your internal ID for this recipient — must be unique within the disbursement | | `amount` | number | Amount to send (e.g. `10.00`) | | `verification` | string | Recipient's date of birth in `YYYY-MM-DD` — must match exactly at claim time | The `verification` date of birth must match exactly what the recipient enters when they claim their funds. A mismatch will block the payment. ### Rules * Each `id` must be unique within the disbursement * Minimum amount: `0.0000001` (Stellar precision) * Maximum recipients per disbursement: **10,000** * Disbursement `name` must be globally unique — plan a naming convention such as `payroll-2026-06` *** ## Disbursement statuses ### Disbursement-level | Status | Meaning | | ------------- | ------------------------------------ | | `STARTED` | Accepted — payments are being queued | | `IN_PROGRESS` | Some recipients paid, others pending | | `COMPLETED` | All recipients paid | | `PAUSED` | Manually paused | ### Per-recipient payment status | Status | Meaning | | --------- | ---------------------------------------------------- | | `READY` | Queued, waiting for recipient to register and verify | | `PENDING` | Submitted to the Stellar network | | `SUCCESS` | Funds landed in recipient's Tender loyalty wallet | | `FAILED` | Payment failed — will retry automatically | *** ## Troubleshooting Your Stellar platform balance is below the disbursement total. Top up via your wallet page and retry. A disbursement with that exact name was already submitted. Use a different, unique name. The date of birth in your CSV doesn't match what the recipient entered at registration. Confirm the correct date and resubmit with an updated record. Check whether they completed registration — they need to click the link in their email or SMS invitation. Unregistered recipients stay in `READY` state until they do. Your platform wallet has no Stellar USDC. Either switch to XLM or deposit USDC to your Tender Stellar wallet first. *** ## FAQ Funds are credited to the recipient's Tender loyalty wallet. Recipients without an account will be guided through a short setup flow when they click their invitation link. Disbursements can be paused before all payments are processed. Already-sent payments cannot be reversed — Stellar transactions are final. Up to 10,000 recipients per disbursement. For larger campaigns, split across multiple disbursements. The payment stays in `READY` state indefinitely until the recipient completes their registration and identity verification via the invitation link. # Fiat Payouts Source: https://docs.tender.cash/guides/fiat-payouts Convert USDC from your merchant balance to a supported fiat currency via a direct bank transfer or an anchor A fiat payout debits USDC from your Tender merchant balance and delivers supported fiat currencies to a recipient. There are two methods: **Internal** — sends funds directly to a Nigerian bank account using the recipient's bank code and account number. **Anchor** — routes funds through a third-party anchor integrated with Tender. You pass the anchor's name as the `method` value. Tender currently supports **MoneyGram** as an anchor, with more to be added over time. Both methods use the same endpoint: `POST /v1/api/payout/fiat`. *** ## Prerequisites These endpoints use Signed (HMAC) authentication — an HMAC-SHA256 signature is required on every request. See the authentication guide for code examples. *** ## Internal bank transfer Call `POST /payout/fiat` with `method: "internal"`, the asset, amount, and the recipient's bank details. A successful response returns the payout record with `status: "pending"`. Call `GET /payout/{id}` until `status` is `completed` or `failed`. Full parameter list and interactive playground for both internal and anchor methods. *** ## Anchor payout Anchor payouts route funds through a Tender-integrated third-party provider. To initiate one, set `method` to the name of the anchor you want to use. The recipient's required details vary by anchor. MoneyGram is the only anchor currently available. Additional anchors will be listed here as they are integrated. ### Available anchors | Anchor | `method` value | Recipient details required | | --------- | -------------- | ------------------------------------------- | | MoneyGram | `"moneygram"` | Name, date of birth, mobile number, address | Call `POST /payout/fiat` with `method` set to the anchor name and the recipient's required details. The response includes a `url`. Direct your recipient to this URL to complete collection via the anchor. ### Identifying the end user with `reference` Anchor payouts accept an optional `reference` field — a stable identifier for the end user the payout is for. It is echoed back to the anchor as the payout's `merchant_reference` for reconciliation, and for **MoneyGram** it also determines which MoneyGram consumer the payout is attributed to. When you serve many end users through one Tender merchant account, pass a `reference` so each user maps to a **distinct MoneyGram consumer** — each with its own KYC record and its own transaction-limit window. Without a `reference`, every payout collapses into a single consumer for your merchant account, so all your users share one KYC identity and one aggregate limit. The value must be **stable per end user**: reuse the same `reference` for the same person on every payout, and use a different `reference` for a different person. A per-transaction value (a new order or invoice id each time) would create a new MoneyGram consumer on every payout — re-triggering KYC and fragmenting limits. Omit `reference` (or set it to your own merchant id) to attribute the payout to your merchant account itself. Full parameter list and interactive playground for anchor-based payouts. *** ## Payout status values | Status | Meaning | | ------------ | ----------------------------------------------------- | | `pending` | Queued, not yet processed | | `processing` | Being handled by the payment network | | `completed` | Successfully delivered | | `failed` | Rejected — check `failureReason` on the payout record | *** ## Error handling | Scenario | Action | | ---------------------- | ------------------------------------------------------------------------ | | Insufficient balance | Ensure your USDC wallet balance covers the amount before submitting | | Invalid bank code | Verify the bank code against your local bank list | | Missing required field | All fields for the chosen `method` are required — see the API reference | | `status: "failed"` | Read `failureReason` on the payout record returned by `GET /payout/{id}` | # Payments Source: https://docs.tender.cash/guides/payments Accept cryptocurrency payments from customers on any supported chain Tender generates a unique wallet address for each payment request. Your customer sends the exact crypto amount to that address, Tender detects the on-chain transfer, and marks the transaction complete. No custodial account or key management is required on your side. *** ## How it works Call `POST /payment/initiate` with the amount, chain, and coin. Tender returns a `walletAddress` and a `txId` to track the transaction. Display the `walletAddress` and exact `amount` to your customer. They send from their own wallet — any compatible wallet on that chain works. Tender monitors the address on-chain. When the payment arrives, the transaction status updates automatically. You can poll or listen via webhook. Call `POST /payment/validate/{id}` to confirm the payment is received and the transaction is complete on your end. *** ## Prerequisites Payment endpoints use Basic (Access ID) authentication — only your `x-access-id` header is required. See the authentication guide for details on both auth methods. ```javascript theme={null} const BASE = 'https://sandbox-api.tender.cash/v1/api'; // makeHeaders() → { 'x-access-id': ACCESS_ID, 'Content-Type': 'application/json' } ``` *** ## Step 1 — Initiate a payment ```javascript Node.js theme={null} const res = await fetch(`${BASE}/payment/initiate`, { method: 'POST', headers: makeHeaders(), body: JSON.stringify({ amount: '10.00', chain: 'tron', coin: 'usdt', reference: 'ORDER-9821', // your own order ID, optional meta: { customerEmail: 'customer@example.com' }, // optional metadata }), }); const { data: payment } = await res.json(); console.log(payment); /* { txId: "66aec7de809b7f45c42a49f9", walletAddress: "TQn9Y2khDD9JHTfVE5oB2h8BKWWM4LxKLT", amount: "10.00", coin: "usdt", chain: "tron", status: "pending", expiresAt: "2025-06-10T11:00:00.000Z" } */ const { txId, walletAddress, amount } = payment; ``` ```python Python theme={null} res = requests.post( f"{BASE}/payment/initiate", headers=make_headers(), json={ "amount": "10.00", "chain": "tron", "coin": "usdt", "reference": "ORDER-9821", "meta": {"customerEmail": "customer@example.com"}, # optional metadata }, ) payment = res.json()["data"] tx_id = payment["txId"] wallet_address = payment["walletAddress"] ``` *** ## Step 2 — Show payment details to your customer Display the wallet address and exact amount. The customer must send **exactly** the specified amount — partial sends are tracked as partial payments. ``` Please send: 10.00 USDT Network: Tron (TRC-20) To: TQn9Y2khDD9JHTfVE5oB2h8BKWWM4LxKLT Do not send from an exchange. Use a self-custody wallet. Payment expires in 1 hour. ``` The `walletAddress` is unique to this transaction. Never reuse addresses across payments. *** ## Step 3 — Poll for payment status ```javascript Node.js theme={null} async function pollPayment(txId, intervalMs = 8000) { while (true) { const res = await fetch(`${BASE}/payment/validate/${txId}`, { method: 'POST', headers: makeHeaders(), }); const { data } = await res.json(); console.log('Status:', data.status, '| Received:', data.amountReceived); if (data.status === 'completed') return data; if (data.status === 'failed') throw new Error('Payment failed'); await new Promise(r => setTimeout(r, intervalMs)); } } const result = await pollPayment(txId); ``` ```python Python theme={null} import time def poll_payment(tx_id, interval_s=8): while True: res = requests.post(f"{BASE}/payment/validate/{tx_id}", headers=make_headers()) data = res.json()["data"] print(f"Status: {data['status']} | Received: {data['amountReceived']}") if data["status"] == "completed": return data if data["status"] == "failed": raise RuntimeError("Payment failed") time.sleep(interval_s) ``` Use webhooks instead of polling for production. Configure your webhook URL and Tender will push a notification the moment the payment status changes. See [Webhooks](/get-started/webhooks). *** ## Payment status values | Status | Meaning | | ----------- | --------------------------------------------- | | `pending` | Address generated; awaiting customer transfer | | `partial` | Some funds received but not the full amount | | `completed` | Full amount received and confirmed on-chain | | `failed` | Payment expired or rejected | *** ## Partial payments If the customer sends less than the required `amount`, the transaction moves to `partial` status. The `balanceRequired` field shows what is still owed. You can: * Ask the customer to send the remaining balance to the same address * Mark the order as underpaid and handle it in your own logic *** ## Error handling | Scenario | Action | | --------------------------- | ---------------------------------------------------------------------------------------------------- | | Customer sends wrong amount | Check `amountReceived` vs `amount`; handle partial if needed | | Payment expires | Initiate a new payment; do not reuse the old address | | Wrong network | Funds sent on the wrong chain cannot be recovered automatically — always display the network clearly | | `status: "failed"` | Initiate a fresh payment request | # Payouts Source: https://docs.tender.cash/guides/payouts Send crypto from your merchant balance to a wallet address or saved payout account A payout sends crypto from your Tender merchant balance to an external destination — either a raw wallet address or a saved payout account. Payouts are processed asynchronously and do not require an OTP. *** ## How it works Call `GET /payout/fee/{chain}/{coin}/{amount}` to see the fee and net amount before committing. Call `POST /payout/crypto` with the coin, chain, amount, and either a wallet `address` or a saved `payoutAccountId`. Call `GET /payout/{id}` until `status` is `completed` or `failed`. *** ## Prerequisites These endpoints use Signed (HMAC) authentication — an HMAC-SHA256 signature is required on every request. See the authentication guide for code examples. ```javascript theme={null} const BASE = 'https://sandbox-api.tender.cash/v1/api'; // makeHeaders() → { 'x-access-id', 'x-request-id', 'x-timestamp', 'authorization', ... } ``` *** ## Step 1 — Check the fee ```javascript Node.js theme={null} const feeRes = await fetch( `${BASE}/payout/fee/tron/usdt/50`, { headers: makeHeaders() } ); const { data: fee } = await feeRes.json(); /* { amount: 50, amountUSD: 50.00, fee: 0.5, feeUSD: 0.50, amountAfterFee: 49.5, currency: "usdt", chain: "tron" } */ ``` ```python Python theme={null} fee_res = requests.get( f"{BASE}/payout/fee/tron/usdt/50", headers=make_headers(), ) fee = fee_res.json()["data"] ``` *** ## Step 2 — Submit a payout to a wallet address ```javascript Node.js theme={null} const payoutRes = await fetch(`${BASE}/payout/crypto`, { method: 'POST', headers: makeHeaders(), body: JSON.stringify({ coin: 'usdt', chain: 'tron', amount: '50', address: 'TQn9Y2khDD9JHTfVE5oB2h8BKWWM4LxKLT', }), }); const { data: payout } = await payoutRes.json(); const payoutId = payout._id; console.log('Status:', payout.status); // "pending" ``` ```python Python theme={null} payout_res = requests.post( f"{BASE}/payout/crypto", headers=make_headers(), json={ "coin": "usdt", "chain": "tron", "amount": "50", "address": "TQn9Y2khDD9JHTfVE5oB2h8BKWWM4LxKLT", }, ) payout = payout_res.json()["data"] payout_id = payout["_id"] ``` *** ## Step 2 (alt) — Payout to a saved payout account ```javascript Node.js theme={null} const payoutRes = await fetch(`${BASE}/payout/crypto`, { method: 'POST', headers: makeHeaders(), body: JSON.stringify({ coin: 'usdt', chain: 'tron', amount: '50', payoutAccountId: '66aec7de809b7f45c42a49f9', }), }); ``` ```python Python theme={null} payout_res = requests.post( f"{BASE}/payout/crypto", headers=make_headers(), json={ "coin": "usdt", "chain": "tron", "amount": "50", "payoutAccountId": "66aec7de809b7f45c42a49f9", }, ) ``` *** ## Step 3 — Poll for completion ```javascript Node.js theme={null} async function pollPayout(id, intervalMs = 8000) { while (true) { const res = await fetch(`${BASE}/payout/${id}`, { headers: makeHeaders() }); const { data } = await res.json(); console.log('Status:', data.status); if (data.status === 'completed') return data; if (data.status === 'failed') throw new Error('Payout failed'); await new Promise(r => setTimeout(r, intervalMs)); } } const result = await pollPayout(payoutId); ``` ```python Python theme={null} import time def poll_payout(payout_id, interval_s=8): while True: res = requests.get(f"{BASE}/payout/{payout_id}", headers=make_headers()) data = res.json()["data"] print(f"Status: {data['status']}") if data["status"] == "completed": return data if data["status"] == "failed": raise RuntimeError("Payout failed") time.sleep(interval_s) ``` Configure a webhook to be notified when a payout completes instead of polling. See [Webhooks](/get-started/webhooks) for setup instructions. *** ## Payout status values | Status | Meaning | | ------------ | ------------------------------ | | `pending` | Queued, not yet sent on-chain | | `processing` | Broadcast to the network | | `completed` | Confirmed on-chain | | `failed` | Rejected — see `failureReason` | *** ## Error handling | Scenario | Action | | ------------------------------------------------ | -------------------------------------------------------- | | Insufficient balance | Check merchant balance before submitting | | Amount below minimum | Call the fee endpoint first; verify `amountAfterFee > 0` | | `status: "failed"` | Read `failureReason` on the payout record | | Neither `address` nor `payoutAccountId` provided | Exactly one must be supplied; omitting both returns 400 | # Subwallets Source: https://docs.tender.cash/guides/subwallets Create and manage crypto wallets for your end-users — deposits, addresses, and transfers, all under your merchant account This feature is currently only available in the sandbox environment. Tender's subwallet offering lets you provision and manage a full wallet infrastructure for each of your end-users. You create a wallet per user, assign blockchain addresses, watch those addresses for incoming deposits, and initiate outbound transfers — all via your merchant API credentials, without your users ever touching Tender directly. *** ## How it works Provision a wallet tied to a unique reference you supply — typically your own user ID. Tender returns the wallet's initial set of blockchain addresses. Create additional addresses on specific networks for an existing wallet. You can group addresses under a named reference to represent separate deposit slots or assets. Register each address with Tender's deposit monitor. When a deposit arrives, Tender fires a `SUB_USER_WALLET_TRANSACTION_DETECTED` webhook to your server with the full transaction details. Send funds from a subwallet address to any destination. Pass `chain` and `currency` — Tender resolves whether to use a native coin or token transfer internally. Tender confirms the on-chain transaction and fires a `SUB_USER_WALLET_TRANSFER_CONFIRMED` webhook when it settles. *** ## Prerequisites These endpoints use Signed (HMAC) authentication — an HMAC-SHA256 signature is required on every request. See the authentication guide for code examples. *** ## Step 1 — Create a wallet Call `POST /wallet` with a `reference` that uniquely identifies the end-user within your merchant account. Tender provisions a wallet and returns its blockchain addresses immediately. Store the `reference` — you will use it in every subsequent call for that user. Full parameters and response schema for `POST /wallet` *** ## Step 2 — Add addresses to the wallet Call `POST /wallet/address` with the `wallet_reference`, an `address_reference` label of your choice, and the list of `networks` you want addresses on. The new addresses are merged into the wallet alongside any existing ones. Full parameters and response schema for `POST /wallet/address` *** ## Step 3 — Watch for deposits Call `POST /wallet/filter` with the address and the chains to monitor. Once registered, Tender watches that address on-chain and fires a `SUB_USER_WALLET_TRANSACTION_DETECTED` webhook to your server whenever a deposit is detected. **Webhook payload fields:** | Field | Description | | ----------------------- | ------------------------------------------------------------------------ | | `depositKey` | Unique key for the deposit event (`chain:txHash:index`) | | `transactionId` | Tender's internal transaction ID | | `walletReference` | The wallet this deposit belongs to | | `addressReference` | The address slot label | | `chainId` | The network the deposit arrived on | | `symbol` | Token symbol (e.g. `ETH`, `USDT`) | | `address` | The receiving address | | `txHash` | On-chain transaction hash | | `amount` | Amount in the token's smallest unit (e.g. wei for ETH) | | `decimals` | Decimal places — divide `amount` by `10 ** decimals` for the human value | | `confirmed` | `false` on first detection; `true` once fully confirmed | | `confirmations` | Current confirmation count | | `confirmationsRequired` | Confirmations needed to consider the deposit settled | | `occurredAt` | ISO 8601 timestamp of the event | Treat a deposit as settled only when `confirmed` is `true` or `confirmations >= confirmationsRequired`. Full parameters and response schema for `POST /wallet/filter` *** ## Step 4 — Initiate a transfer Call `POST /wallet/transfer` with `chain`, `currency`, `sender`, `receiver`, `amount`, and your own `merchant_reference`. Tender automatically routes to a native coin or token transfer based on the currency. The response returns a `tx_id` immediately; the transfer settles asynchronously. **Supported chains:** `ethereum`, `tron`, `bitcoin` Full parameters and response schema for `POST /wallet/transfer` When the transfer confirms on-chain, Tender fires a `SUB_USER_WALLET_TRANSFER_CONFIRMED` webhook to your server. *** ## Utility operations | Operation | Endpoint | What it does | | ---------------- | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | | List wallets | [`GET /wallet`](/api-reference/endpoint/subwallets/list-wallets) | Paginated list of all wallets under your merchant account | | List addresses | [`GET /wallet/:walletReference/addresses`](/api-reference/endpoint/subwallets/list-addresses) | All addresses belonging to a specific wallet | | Get balance | [`GET /wallet/balance/:address`](/api-reference/endpoint/subwallets/get-balance) | Native, USDC, and USDT balances for an address on a specific chain | | Validate address | [`POST /wallet/validate`](/api-reference/endpoint/subwallets/validate-address) | Check whether an address is valid on a given set of networks | | Check watched | [`GET /wallet/watch/:address`](/api-reference/endpoint/subwallets/check-watched) | Check whether an address is currently registered with the deposit monitor | *** ## Webhook events | Event | Fired when | | -------------------------------------- | -------------------------------------- | | `SUB_USER_WALLET_TRANSACTION_DETECTED` | A deposit arrives on a watched address | | `SUB_USER_WALLET_TRANSFER_CONFIRMED` | An outbound transfer confirms on-chain | See [Webhooks](/get-started/webhooks) for how to configure your endpoint and verify payloads. # Home Source: https://docs.tender.cash/index Start accepting cryptocurrency payments and managing agents on your platform **Prerequisites**: Before you begin, make sure to create an account and complete onboarding. Start accepting cryptocurrency payments online through multiple blockchain networks with Tender's robust payment infrastructure. Accept cryptocurrency payments on your website, app, or digital platform Create and manage agents (sub-businesses) under your merchant account *** ## Quick Links Sign up for a Tender account and get started Obtain your API keys from the dashboard Learn how to authenticate API requests with HMAC signatures Configure webhooks for real-time event notifications *** ## API Reference Explore our comprehensive API documentation: Initiate and validate cryptocurrency payments Create and manage agent accounts Get supported chains, currencies, and exchange rates Configure and manage webhook endpoints # On-ramp Source: https://docs.tender.cash/onramp/overview Let customers pay with local fiat and receive cryptocurrency directly to their wallet The Tender on-ramp converts a fiat bank payment (e.g. NGN transfer) into cryptocurrency and delivers it to a wallet address on the customer's chosen blockchain — all in a single integration. ## How it works Call `POST /onramp/quote` with the fiat amount and target cryptocurrency. Tender returns a live exchange rate, an estimated crypto output, and a `quoteId` that is valid for a short window (typically 60 seconds). Call `POST /onramp/initiate` with the `quoteId`, the customer's wallet address, and their contact details. Tender creates a virtual bank account and returns the transfer details to show your customer. Customer makes a local bank transfer to the virtual account. No crypto wallet or exchange account is needed on their side — just a standard bank transfer. Once payment is confirmed, Tender runs the pipeline automatically: * Forwards the fiat to the swap provider * Swaps fiat → intermediate crypto (USDT on Tron) * Delivers the final crypto to the `targetAddress` on the `targetChain` Call `GET /onramp/{reference}` to track progress. The `stages` object shows exactly where the pipeline is at any moment. *** ## Pipeline stages After payment is confirmed, the on-ramp moves through these stages in order: | Stage | What happens | | -------------- | ----------------------------------------------------------------------- | | `payment` | Fiat payment confirmed by the payment provider | | `payout` | Fiat forwarded to the swap provider's account | | `swap` | Fiat swapped to intermediate crypto (e.g. USDT on Tron) | | `swapWithdraw` | Swapped crypto withdrawn to Tender's swap wallet *(skipped by default)* | | `cryptoSend` | Crypto sent from Tender's swap wallet to the customer's `targetAddress` | Each stage has a `status` of `pending`, `in_progress`, `completed`, `failed`, or `skipped`. *** ## Overall status values | Status | Meaning | | ----------------- | ---------------------------------------------------------------- | | `pending_payment` | Waiting for the customer's bank transfer | | `processing` | Payment confirmed; pipeline is running | | `crypto_sent` | Crypto dispatched to `targetAddress` | | `completed` | Fully settled | | `failed` | Terminal failure — see `failureReason` and `stages[*].lastError` | *** ## Key concepts ### Quotes are required and single-use Before initiating, you must call `/onramp/quote` to lock in a rate. The returned `quoteId` is: * **Time-limited** — expires after `time_to_lock` seconds (shown as `expiresAt`) * **Single-use** — consumed the moment it is passed to `/onramp/initiate` Attempting to initiate with an expired or already-used quote returns a `400` error. ### Virtual bank accounts expire The virtual bank account returned by `/onramp/initiate` expires after **1 hour**. If the customer does not pay within that window, the on-ramp request moves to `failed` status. ### Supported chains and currencies Use the discovery endpoints to present your customers with what is available: * `GET /onramp/chains` — chains that support on-ramp delivery * `GET /onramp/coins` — cryptocurrencies available, optionally filtered by chain *** ## Integration This section walks through every step of a real on-ramp integration, from discovery to polling for completion. All examples use the sandbox environment. ### Prerequisites * A Tender merchant account with API credentials * Your `TENDER_ACCESS_ID` and `TENDER_ACCESS_SECRET` set as environment variables Onramp endpoints use Signed (HMAC) authentication — an HMAC-SHA256 signature is required on every request. Follow the authentication guide for full details and code examples in Node.js, Python, and PHP before continuing. The examples below assume you have a `makeHeaders()` helper and a `BASE` constant as described in that guide: ```javascript theme={null} const BASE = 'https://sandbox-api.tender.cash/v1/api'; // makeHeaders() → { 'x-access-id', 'x-request-id', 'x-timestamp', 'authorization', ... } ``` *** ### Step 1 — Discover available chains and coins Show your customers which blockchains and currencies they can receive. ```javascript Node.js theme={null} // Fetch supported chains const chainsRes = await fetch(`${BASE}/onramp/chains`, { headers: makeHeaders(), }); const { data: chains } = await chainsRes.json(); // chains = [{ id: "tron", name: "Tron", icon: "...", ... }] // Fetch supported coins (optionally filter by chain) const coinsRes = await fetch(`${BASE}/onramp/coins?chain=tron`, { headers: makeHeaders(), }); const { data: coins } = await coinsRes.json(); // coins = [{ id: "usdt", name: "Tether USD", symbol: "USDT", ... }] ``` ```python Python theme={null} import requests chains_res = requests.get(f"{BASE}/onramp/chains", headers=make_headers()) chains = chains_res.json()["data"] coins_res = requests.get(f"{BASE}/onramp/coins?chain=tron", headers=make_headers()) coins = coins_res.json()["data"] ``` *** ### Step 2 — Get a quote Once the customer has chosen a target currency and entered their fiat amount, fetch a live quote. ```javascript Node.js theme={null} const quoteRes = await fetch(`${BASE}/onramp/quote`, { method: 'POST', headers: makeHeaders(), body: JSON.stringify({ fiatAmount: 50000, // NGN, in whole units (not kobo) fiatCurrency: 'NGN', // defaults to NGN if omitted targetCurrency: 'USDT', targetChain: 'tron', }), }); const { data: quote } = await quoteRes.json(); console.log(quote); /* { quoteId: "b7f2a1c3-9d4e-4b2f-a8c0-1e2d3f4a5b6c", fiatCurrency: "NGN", fiatAmount: 50000, targetCurrency: "USDT", targetChain: "tron", rate: 0.000597, estimatedCryptoAmount: "29.850000", expiresAt: "2025-06-10T10:05:00.000Z" } */ ``` ```python Python theme={null} quote_res = requests.post( f"{BASE}/onramp/quote", headers=make_headers(), json={ "fiatAmount": 50000, "fiatCurrency": "NGN", "targetCurrency": "USDT", "targetChain": "tron", }, ) quote = quote_res.json()["data"] ``` Quotes expire at `expiresAt`. Display a countdown and call `/onramp/quote` again if the customer lets it lapse before confirming. *** ### Step 3 — Show the quote to your customer Display the estimated output and ask for confirmation before initiating. ``` You pay: ₦50,000 NGN You receive: ≈ 29.85 USDT Network: Tron (TRC-20) Rate expires: in 58 seconds ``` The estimated amount is based on the rate at quote time. The actual amount delivered may differ slightly if the quote expires and a fresh rate is applied internally. *** ### Step 4 — Initiate the on-ramp After the customer confirms, call `/onramp/initiate` with the `quoteId` and their wallet address. ```javascript Node.js theme={null} const initiateRes = await fetch(`${BASE}/onramp/initiate`, { method: 'POST', headers: makeHeaders(), body: JSON.stringify({ quoteId: quote.quoteId, targetAddress: 'TRDFGhjkytywooiueonuoo', // customer's USDT/Tron address customer: { email: 'customer@example.com', name: 'Ada Obi', }, metadata: { orderId: 'ORD-9821' }, // your own reference, optional }), }); const { data: onramp } = await initiateRes.json(); console.log(onramp); /* { reference: "a3f1c2d4-8e7b-4f0a-9c1d-2e3f4a5b6c7d", status: "pending_payment", bankTransfer: { accountNumber: "0123456789", accountName: "Tender / Ada Obi", bankName: "Wema Bank" }, expiresAt: "2025-06-10T11:00:00.000Z", amount: { value: 50000, currency: "NGN" } } */ ``` ```python Python theme={null} initiate_res = requests.post( f"{BASE}/onramp/initiate", headers=make_headers(), json={ "quoteId": quote["quoteId"], "targetAddress": "TRDFGhjkytywooiueonuoo", "customer": { "email": "customer@example.com", "name": "Ada Obi", }, }, ) onramp = initiate_res.json()["data"] reference = onramp["reference"] ``` **Error cases to handle:** | Error message | Cause | Fix | | ----------------------------------- | ------------------------------------------------------- | -------------------- | | `"Quote not found or already used"` | `quoteId` was already consumed or never existed | Fetch a fresh quote | | `"Quote has expired"` | `expiresAt` passed before `/initiate` was called | Fetch a fresh quote | | Joi validation error | `quoteId` missing, not a UUID, or `targetAddress` empty | Fix the request body | *** ### Step 5 — Display bank transfer details Show the returned `bankTransfer` details so the customer knows where to send money. ``` Please transfer ₦50,000 to: Bank: Wema Bank Account name: Tender / Ada Obi Account number: 0123456789 This account expires at 11:00 AM UTC. Do not send a different amount. ``` Store the `reference` — you will use it to poll for status. *** ### Step 6 — Poll for completion Poll `GET /onramp/{reference}` until `status` is `crypto_sent` or `completed`. ```javascript Node.js theme={null} async function pollOnramp(reference, intervalMs = 10000) { while (true) { const res = await fetch(`${BASE}/onramp/${reference}`, { headers: makeHeaders() }); const { data } = await res.json(); console.log(`Status: ${data.status}`, data.stages); if (data.status === 'crypto_sent' || data.status === 'completed') { console.log('On-ramp complete!'); return data; } if (data.status === 'failed') { throw new Error(`On-ramp failed: ${data.failureReason}`); } await new Promise(r => setTimeout(r, intervalMs)); } } const result = await pollOnramp(onramp.reference); ``` ```python Python theme={null} import time def poll_onramp(reference, interval_s=10): while True: res = requests.get(f"{BASE}/onramp/{reference}", headers=make_headers()) data = res.json()["data"] print(f"Status: {data['status']}") if data["status"] in ("crypto_sent", "completed"): print("On-ramp complete!") return data if data["status"] == "failed": raise RuntimeError(f"On-ramp failed: {data.get('failureReason')}") time.sleep(interval_s) result = poll_onramp(reference) ``` Rather than polling, configure a webhook to receive a notification when the status changes. See [Webhooks](/get-started/webhooks) for setup instructions. *** ### Inspecting stage progress The `stages` object in the status response shows the exact state of each pipeline step. ```json theme={null} { "stages": { "payment": { "status": "completed", "completedAt": "2025-06-10T10:02:30Z" }, "payout": { "status": "completed", "completedAt": "2025-06-10T10:03:10Z" }, "swap": { "status": "in_progress", "startedAt": "2025-06-10T10:03:15Z", "attempts": 1 }, "swapWithdraw": { "status": "skipped" }, "cryptoSend": { "status": "pending" } } } ``` *** ### Error handling | Scenario | Recommended action | | ---------------------------------------- | ------------------------------------------------------------------- | | `status: "failed"` | Read `failureReason` and display it; offer the customer a retry | | `status: "pending_payment"` after 1 hour | The virtual account expired; start a new on-ramp | | Stage `status: "failed"` | Read `stages[*].lastError` for the provider-level reason | | Network error polling | Retry with exponential backoff; the on-ramp reference is idempotent | # Quick Start Source: https://docs.tender.cash/quickstart Make your first cryptocurrency payment in minutes ## Get Started in Three Steps Get up and running with Tender's API and accept your first cryptocurrency payment. *** ### Step 1: Get Your API Credentials 1. Log in to your [Tender Merchant Dashboard](https://sandbox-merchant.tender.cash) (sandbox) or [merchant.tender.cash](https://merchant.tender.cash) (live) 2. Navigate to **Settings** → **API Credentials** 3. Click **Generate New Credentials** 4. Select **Test Environment** for development 5. Save your **Access ID** and **Access Secret** securely Use the test environment while integrating. It uses testnet cryptocurrencies with no real value. Never hardcode credentials. Use environment variables: ```bash .env theme={null} TENDER_ACCESS_ID=your_access_id_here TENDER_ACCESS_SECRET=your_access_secret_here TENDER_BASE_URL=https://sandbox-api.tender.cash ``` *** ### Step 2: Make Your First API Call Choose your preferred language and make a request to create an agent: ```javascript Node.js theme={null} import crypto from 'crypto'; import { v4 as uuidv4 } from 'uuid'; // Your credentials const accessId = process.env.TENDER_ACCESS_ID; const accessSecret = process.env.TENDER_ACCESS_SECRET; // Generate signature const requestId = uuidv4(); const timeStamp = new Date().toISOString(); const payload = { timeStamp, requestId, accessId }; const signature = crypto .createHmac('sha256', accessSecret) .update(JSON.stringify(payload)) .digest('base64'); // Make API request const response = await fetch('https://sandbox-api.tender.cash/v1/api/agent/create', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-access-id': accessId, 'x-request-id': requestId, 'x-timestamp': timeStamp, 'authorization': signature }, body: JSON.stringify({ type: 'online', name: 'Lagos Fashion Store', email: 'lagosfashion@store.com', phoneNumber: '0123246784824', location: 'Lagos', country: 'Nigeria', avatar: 'https:///imagesamp.lo.co', currency: 'NGN', password: '12345678' }) }); const data = await response.json(); console.log('Agent created:', data); ``` ```python Python theme={null} import hmac import hashlib import base64 import json import uuid from datetime import datetime import requests import os # Your credentials access_id = os.getenv('TENDER_ACCESS_ID') access_secret = os.getenv('TENDER_ACCESS_SECRET') # Generate signature request_id = str(uuid.uuid4()) timestamp = datetime.utcnow().isoformat() + 'Z' payload = { "timeStamp": timestamp, "requestId": request_id, "accessId": access_id } message = json.dumps(payload) signature = base64.b64encode( hmac.new( access_secret.encode('utf-8'), message.encode('utf-8'), hashlib.sha256 ).digest() ).decode('utf-8') # Make API request response = requests.post( 'https://sandbox-api.tender.cash/v1/api/agent/create', headers={ 'Content-Type': 'application/json', 'x-access-id': access_id, 'x-request-id': request_id, 'x-timestamp': timestamp, 'authorization': signature }, json={ 'type': 'online', 'name': 'Lagos Fashion Store', 'email': 'lagosfashion@store.com', 'phoneNumber': '0123246784824', 'location': 'Lagos', 'country': 'Nigeria', 'avatar': 'https:///imagesamp.lo.co', 'currency': 'NGN', 'password': '12345678' } ) data = response.json() print('Agent created:', data) ``` ```php PHP theme={null} $timeStamp, 'requestId' => $requestId, 'accessId' => $accessId ]; $message = json_encode($payload); $signature = base64_encode(hash_hmac('sha256', $message, $accessSecret, true)); // Make API request $ch = curl_init('https://sandbox-api.tender.cash/v1/api/agent/create'); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([ 'type' => 'online', 'name' => 'Lagos Fashion Store', 'email' => 'lagosfashion@store.com', 'phoneNumber' => '0123246784824', 'location' => 'Lagos', 'country' => 'Nigeria', 'avatar' => 'https:///imagesamp.lo.co', 'currency' => 'NGN', 'password' => '12345678' ])); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Content-Type: application/json', 'x-access-id: ' . $accessId, 'x-request-id: ' . $requestId, 'x-timestamp: ' . $timeStamp, 'authorization: ' . $signature ]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); curl_close($ch); $data = json_decode($response, true); echo 'Agent created: ' . print_r($data, true); ?> ``` **Expected Response:** ```json theme={null} { "status": "success", "message": "success", "data": { "id": "66f33b1fa9446a6b6b8f32cd", "name": "Lagos Fashion Store", "email": "jsmith@example.com", "phoneNumber": "0123246784824", "location": "Lagos", "country": "Nigeria", "active": true, "agentId": "vbibtucm9yn", "merchantId": "6538e8f9bdec6d1a21978a64", "currency": "NGN", "totalSales": "0.00 NGN", "defaultFiatCurrency": { "currency": "NGN", "useSystemRate": true, "rate": "0" }, "createdAt": "2023-11-07T05:31:56Z" } } ``` *** ### Step 3: Initiate Your First Payment Now let's create a cryptocurrency payment. Payment endpoints use [Basic (Access ID) authentication](/api-reference/authentication#basic-access-id-authentication), so only your `x-access-id` header is required — no signature: ```javascript theme={null} const paymentResponse = await fetch('https://sandbox-api.tender.cash/v1/api/payment/initiate', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-access-id': accessId }, body: JSON.stringify({ amount: "10.00", chain: "ethereum", coin: "usdc" }) }); const payment = await paymentResponse.json(); console.log('Payment initiated:', payment); ``` **Expected Response:** ```json theme={null} { "status": "success", "message": "success", "data": { "txId": "66aec7de809b7f45c42a49f9", "type": "receive", "chain": "ethereum", "amount": "10.00", "usdAmount": "10.00", "walletAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", "status": "pending", "agentId": "abc123xyz" } } ``` The `walletAddress` is where your customer should send the cryptocurrency. Monitor the transaction status using webhooks or the validation endpoint. *** ## Next Steps Now that you've made your first requests, explore more features: Deep dive into HMAC signature authentication Explore all payment endpoints and options Set up real-time event notifications View all supported blockchains and currencies *** ## Testing Your Integration Before going to production: Test with different blockchains and currencies in the test environment Configure and test webhook delivery for transaction events Implement proper error handling for failed transactions Ensure API credentials are stored securely and never exposed Switch to production credentials and base URL *** ## Need Help? * **Email**: [support@tender.cash](mailto:support@tender.cash) * **Documentation**: [docs.tender.cash](https://docs.tender.cash) * **API Reference**: Browse complete API documentation # JavaScript SDK Source: https://docs.tender.cash/sdk/javascript Integrate Tender cryptocurrency payments in your JavaScript and React applications ## Overview This page contains full documentation for both JavaScript SDK tracks: * **Latest SDK**: `@tender-cash/js-sdk` * **Legacy SDK (Old Version)**: `@tender-cash/agent-sdk-react` ## Package Current JavaScript SDK package *** ## Installation ```bash npm theme={null} npm install @tender-cash/js-sdk ``` ```bash yarn theme={null} yarn add @tender-cash/js-sdk ``` ```bash pnpm theme={null} pnpm add @tender-cash/js-sdk ``` *** ## Usage in React Use `TenderSdk` as the primary component. `TenderAgentSdk` is still exported as a backward-compatible alias. ```tsx theme={null} import { TenderSdk, onFinishResponse } from '@tender-cash/js-sdk'; function PaymentComponent() { const handleEventResponse = (response: onFinishResponse) => { console.log('SDK Response:', response); }; return ( ); } ``` When `referenceId` and `amount` are provided, the modal auto-opens on component mount. *** ## API Reference ### Component Props (`TenderAgentProps`) Applies to both `TenderSdk` and `TenderAgentSdk`. #### Required Props | Prop | Type | Description | | -------------- | --------------------------------- | ------------------------------------------ | | `accessId` | `string` | Your Tender merchant Access ID. | | `fiatCurrency` | `string` | Fiat code, e.g. `"USD"`, `"EUR"`, `"NGN"`. | | `env` | `"test"` \| `"live"` \| `"local"` | Target environment. | #### Optional Props | Prop | Type | Description | | ---------------------- | ---------------------------------- | ---------------------------------------------------- | | `onEventResponse` | `(data: onFinishResponse) => void` | Called when payment state changes. | | `referenceId` | `string` | Payment reference. Required for auto-open mode. | | `amount` | `number` | Payment amount in fiat. Required for auto-open mode. | | `paymentExpirySeconds` | `number` | Payment expiration in seconds. | | `theme` | `"light"` \| `"dark"` | Modal theme. | | `closeModal` | `() => void` | Callback fired when modal closes. | *** ## Ref Usage ```tsx theme={null} import { useRef } from 'react'; import { TenderSdk, TenderRef } from '@tender-cash/js-sdk'; function PaymentComponent() { const tenderRef = useRef(null); const openPayment = () => { tenderRef.current?.initiatePayment({ amount: 150, referenceId: `order-${Date.now()}`, paymentExpirySeconds: 1800 }); }; const closePayment = () => { tenderRef.current?.dismiss(); }; return ( <> ); } ``` ### Ref Methods (`TenderRef`) | Method | Description | | ----------------- | -------------------------------------------------------- | | `initiatePayment` | Opens modal and starts payment with provided parameters. | | `dismiss` | Closes the modal. | *** ## Callback Data (`onFinishResponse`) ```typescript theme={null} interface onFinishResponse { status: "partial-payment" | "completed" | "overpayment" | "pending" | "error" | "cancelled"; message: string; data: IPaymentData | undefined; } ``` *** ## Features * Shadow DOM style isolation * Auto-open mode from props * Programmatic control with refs * TypeScript support * Works across desktop and mobile This is the old SDK version. New integrations should use `@tender-cash/js-sdk`. ## Package Legacy package (previous SDK version) *** ## Installation ```bash npm theme={null} npm install @tender-cash/agent-sdk-react ``` ```bash yarn theme={null} yarn add @tender-cash/agent-sdk-react ``` ```bash pnpm theme={null} pnpm add @tender-cash/agent-sdk-react ``` *** ## Usage in React ```jsx theme={null} import { TenderAgentSdk, onFinishResponse } from '@tender-cash/agent-sdk-react'; function PaymentComponent() { const handleEventResponse = (response: onFinishResponse) => { console.log('SDK Response:', response); }; return ( ); } ``` *** ## API Reference ### Component Props (`TenderAgentProps`) #### Required Props | Prop | Type | Description | | -------------- | --------------------------------- | -------------------------------------------- | | `fiatCurrency` | `string` | Fiat currency code, e.g. `"USD"` or `"EUR"`. | | `accessId` | `string` | Your Tender merchant Access ID. | | `env` | `"test"` \| `"live"` \| `"local"` | Target environment. | #### Optional Props | Prop | Type | Description | | ---------------------- | ---------------------------------- | ---------------------------------------------------- | | `onEventResponse` | `(data: onFinishResponse) => void` | Called when payment status updates. | | `referenceId` | `string` | Payment reference. Required for auto-open mode. | | `amount` | `number` | Payment amount in fiat. Required for auto-open mode. | | `paymentExpirySeconds` | `number` | Payment expiration in seconds. | | `theme` | `"light"` \| `"dark"` | Modal theme. | *** ## Ref Usage ```jsx theme={null} import { useRef } from 'react'; import { TenderAgentSdk, TenderAgentRef } from '@tender-cash/agent-sdk-react'; function PaymentComponent() { const tenderRef = useRef(null); const handleOpenPayment = () => { tenderRef.current?.initiatePayment({ amount: 150.00, referenceId: "unique-payment-reference-123", paymentExpirySeconds: 1800 }); }; const handleCloseModal = () => { tenderRef.current?.closeModal(); }; return ( <> ); } ``` ### Ref Methods (`TenderAgentRef`) | Method | Description | | ----------------- | -------------------------------------------------------- | | `initiatePayment` | Opens modal and starts payment with provided parameters. | | `dismiss` | Closes the modal. | | `closeModal` | Closes the modal from outside the widget. | *** ## Callback Data (`onFinishResponse`) ```typescript theme={null} interface onFinishResponse { status: "partial-payment" | "completed" | "overpayment" | "pending" | "error" | "cancelled"; message: string; data: IPaymentData | undefined; } ``` *** ## Features * Shadow DOM style isolation * Auto-open modal flow * TypeScript support * Responsive payment UI *** ## Next Steps Explore the full API documentation Set up webhook notifications View source repositories Contact our support team # Introduction Source: https://docs.tender.cash/sdk/overview Official Tender SDK for JavaScript applications ## Overview Tender provides an official JavaScript SDK to help you integrate cryptocurrency payments into your applications quickly and easily. *** ## Available SDK `@tender-cash/js-sdk` for JavaScript and React applications Legacy package: `@tender-cash/agent-sdk-react` *** ## Features The Tender JavaScript SDK includes: * **Shadow DOM Isolation** - Prevents CSS conflicts with your application styles * **TypeScript Support** - Full TypeScript definitions for type safety * **Error Handling** - Comprehensive error handling with detailed messages * **Loading States** - Built-in loading state management * **Theme Customization** - Support for light and dark themes * **Auto-Open Modal** - Streamlined payment flow with automatic modal opening * **Framework Agnostic** - Works with React, Vue, Angular, or vanilla JavaScript * **Responsive Design** - Optimized for both desktop and mobile devices *** ## Key Features | Feature | JavaScript SDK | | -------------------- | -------------- | | TypeScript Support | ✅ | | Payment Initiation | ✅ | | Payment Validation | ✅ | | Blockchain Selection | ✅ | | Loading States | ✅ | | Error Handling | ✅ | | Theme Support | ✅ | | Shadow DOM | ✅ | | Mobile Responsive | ✅ | | React Integration | ✅ | | Vanilla JS Support | ✅ | *** ## Installation ```bash npm theme={null} npm install @tender-cash/js-sdk ``` ```bash yarn theme={null} yarn add @tender-cash/js-sdk ``` ```bash pnpm theme={null} pnpm add @tender-cash/js-sdk ``` *** ## Need Help? View the full API documentation Get started with Tender API View source code and contribute Contact our support team # WordPress (WooCommerce) Plugin Source: https://docs.tender.cash/sdk/wordpress Accept Tender cryptocurrency payments in WooCommerce using the official Tender JavaScript SDK. ## Overview The Tender WooCommerce plugin is a WordPress payment gateway that embeds the **Tender JavaScript/React SDK** directly into your WooCommerce checkout flow. Instead of custom HTML forms, the plugin uses the `@tender-cash/agent-sdk-react` package to render the Tender payment experience, including support for: * **Crypto payments** in your WooCommerce store * **Completed, partial, and overpayment** handling * **Test and live environments** * **WooCommerce Blocks** checkout compatibility * **Automatic WooCommerce order status updates** You can install the plugin from the provided ZIP file: * **Download**: [`woo-tender-sdk.zip`](https://tender-store.s3.us-east-1.amazonaws.com/woo-tender-sdk.zip) *** ## Installation Follow these steps to install the Tender WooCommerce plugin: 1. **Download** the plugin ZIP: [`woo-tender-sdk.zip`](https://tender-store.s3.us-east-1.amazonaws.com/woo-tender-sdk.zip) 2. In your WordPress admin, go to **Plugins → Add New → Upload Plugin** 3. Upload the ZIP file and click **Install Now** 4. Click **Activate** to enable the plugin 5. Go to **WooCommerce → Settings → Payments** 6. Enable **"Tender SDK Payment"** and click **Manage** to configure it Alternatively, you can upload it manually: 1. Extract the ZIP 2. Upload the `woocommerce-payment-sdk-gateway` folder to `/wp-content/plugins/` 3. Activate the plugin in **Plugins** *** ## Configuration In **WooCommerce → Settings → Payments → Tender SDK Payment**, configure the gateway with your Tender credentials. ### Required settings * **Access ID**: Your Tender merchant Access ID (from the Tender dashboard) * **Access Secret**: Your Tender merchant Access Secret * **Agent ID**: Your Tender Agent ID * **Environment**: `Test` (staging) or `Live` (production) ### Optional settings * **Title**: Name shown to customers at checkout (default: "Pay with Crypto") * **Description**: Description shown on the checkout page Make sure the credentials you use match the selected environment (test vs live). *** ## How It Works The WooCommerce gateway wraps the Tender React SDK and handles order status updates for you. 1. Customer selects **Tender SDK Payment** at checkout 2. After placing the order, they are redirected to the **Tender payment page** 3. The Tender React SDK loads and renders the payment UI 4. Customer chooses a cryptocurrency and completes payment 5. The SDK sends the payment status back to WordPress via secure AJAX 6. WooCommerce order status is updated automatically: * **Completed** – Order marked as paid * **Overpayment** – Order completed with a note about the excess amount * **Partial payment** – Order placed **on hold** pending full payment * **Error / Cancelled** – Customer is redirected back to checkout *** ## SDK Integration Details Under the hood, the plugin uses the **Tender Agent SDK React** library: * **Package**: `@tender-cash/agent-sdk-react` * **Load method**: ES module from CDN (`unpkg.com`) Example of the SDK props used by the plugin: ```jsx theme={null} ``` The `onEventResponse` callback is responsible for sending the payment result back to WordPress, which then updates the WooCommerce order. For a deeper dive into the SDK itself, see the **JavaScript SDK** docs at `/sdk/javascript`. *** ## File Structure (Plugin) The main plugin files are organized as follows: ```text theme={null} woocommerce-payment-sdk-gateway/ ├── woocommerce-tender-sdk-gateway.php # Main plugin bootstrap file ├── class-woocommerce-tender-sdk-gateway.php # WooCommerce gateway implementation ├── templates/ │ └── tender-sdk-payment.php # Payment page template that mounts the SDK ├── blocks/ │ ├── class-tender-sdk-payment-block.php # WooCommerce Blocks integration │ └── build/ │ ├── index.js # Block script │ └── index.asset.php # Asset dependencies ├── languages/ # Translation files └── README.md # Plugin README ``` Key WordPress/WooCommerce integration points: * `woocommerce_payment_gateways` – registers the gateway * `woocommerce_blocks_payment_method_type_registration` – registers the checkout block * `wp_ajax_tender_sdk_update_order_status` – handles payment status updates *** ## Requirements To use the plugin in production, you need: * **WordPress** 5.0 or higher * **WooCommerce** 3.0 or higher * **PHP** 7.4 or higher * A modern browser with JavaScript enabled * Valid Tender **Access ID**, **Access Secret**, and **Agent ID** *** ## Security Considerations The WooCommerce plugin follows WordPress security best practices: * All AJAX requests use **WordPress nonces** * Tender access credentials are stored securely in **WordPress options** * Order IDs and payment data are validated before processing * Payment details are sanitized before being stored For additional security recommendations, see the **Best Practices** section in the JavaScript SDK docs. *** ## Support & Next Steps If you encounter issues: * **WooCommerce / WordPress integration**: Contact your internal development team * **Tender SDK behavior**: Refer to the **JavaScript SDK** docs or Tender support You can continue exploring: Learn more about the underlying Tender React SDK. Explore the full Tender API.