# CryptoSetype Payment API Base URL: `https://crypto.setype.com` ## Authentication All authenticated endpoints require the `X-API-Key` header. ``` X-API-Key: sk_<48 hex chars> ``` The API key is generated when you create a store. It is shown once — save it securely. Keys are bcrypt-hashed on the server and cannot be retrieved. --- ## Errors All errors return JSON: ```json { "error": "Human-readable message" } ``` | Code | Meaning | |------|---------| | 400 | Bad request — missing or invalid parameters | | 401 | Unauthorized — missing or invalid API key | | 404 | Not found | | 409 | Conflict — resource already processed | | 503 | No wallets available — retry shortly | --- ## Supported Currencies (13 payment methods) | Chain | Native | Tokens | Confirmations | |-------|--------|--------|---------------| | TRON | TRX | USDT (TRC-20) | 1 | | Bitcoin | BTC | — | 1 | | Ethereum | ETH | USDT (ERC-20), USDC (ERC-20) | 3 | | Solana | SOL | USDT (SPL), USDC (SPL) | 1 | | BNB Chain | BNB | USDT (BEP-20), USDC (BEP-20) | 3 | | Litecoin | LTC | — | 1 | Token payments use the same wallet address as native coins. When creating a payment, specify both `currency` and `chain` to select a token. --- ## POST /api/payments Create a payment invoice. **Requires `X-API-Key`.** ### Request ```json { "amount": 25.00, "currency": "USDT", "chain": "ethereum", "order_id": "your_order_123", "webhook_url": "https://yoursite.com/webhook", "success_url": "https://yoursite.com/success", "fail_url": "https://yoursite.com/fail", "metadata": { "user_id": 42 } } ``` | Field | Type | Required | Description | |-------|------|----------|-------------| | amount | number | yes | Amount (0.01–1,000,000) | | currency | string | yes | `USD` (multi-chain checkout), `TRX`, `USDT`, `USDC`, `BTC`, `ETH`, `SOL`, `BNB`, `LTC` | | chain | string | no | `tron`, `bitcoin`, `ethereum`, `solana`, `bnb`, `litecoin`. Required for token payments such as `USDT` or `USDC` on non-default chains. Default mapping: `TRX`→`tron`, `USDT`→`tron`, `BTC`→`bitcoin`, `ETH`→`ethereum`, `SOL`→`solana`, `BNB`→`bnb`, `LTC`→`litecoin`. | | order_id | string | no | Your internal order ID, returned in webhooks | | webhook_url | string | no | Override store's default webhook URL | | success_url | string | no | Redirect URL after confirmed payment | | fail_url | string | no | Redirect URL after expired/failed payment | | metadata | object | no | Arbitrary JSON, returned in webhooks | ### Response `201` ```json { "id": "pay_a1b2c3d4e5f6g7h8", "payment_url": "https://crypto.setype.com/pay/pay_a1b2c3d4e5f6g7h8", "address": "0x37aA2ECe891374eAbCd0b08b73E266926B111111", "amount": 25.00, "currency": "USDT", "chain": "ethereum", "status": "pending", "expires_at": 1712345678000 } ``` When `currency` is `USD`, `address` is `null` — the customer selects a coin on the hosted checkout page. ### Examples **Direct TRX payment:** ```bash curl -X POST https://crypto.setype.com/api/payments \ -H "Content-Type: application/json" \ -H "X-API-Key: sk_your_key" \ -d '{"amount": 50, "currency": "TRX", "order_id": "ord_trx_123"}' ``` **Direct USDT (TRC-20) payment:** ```bash curl -X POST https://crypto.setype.com/api/payments \ -H "Content-Type: application/json" \ -H "X-API-Key: sk_your_key" \ -d '{"amount": 25, "currency": "USDT", "order_id": "ord_123"}' ``` **USDT on Ethereum (ERC-20):** ```bash curl -X POST https://crypto.setype.com/api/payments \ -H "Content-Type: application/json" \ -H "X-API-Key: sk_your_key" \ -d '{"amount": 100, "currency": "USDT", "chain": "ethereum", "order_id": "ord_456"}' ``` **Multi-chain checkout (customer chooses coin):** ```bash curl -X POST https://crypto.setype.com/api/payments \ -H "Content-Type: application/json" \ -H "X-API-Key: sk_your_key" \ -d '{"amount": 50, "currency": "USD", "order_id": "ord_789", "success_url": "https://yoursite.com/success"}' ``` --- ## GET /api/payments/:id Get payment details. **Requires `X-API-Key`.** Only returns payments belonging to your store. ### Response `200` ```json { "id": "pay_a1b2c3d4e5f6g7h8", "order_id": "ord_123", "address": "TGGrCNwFuzrJbJPHx4pWm6jfgxz5xVVvvv", "expected_amount": 25.00, "expected_crypto": "USDT", "received_amount": 25.00, "tx_hash": "abc123def456...", "status": "confirmed", "expires_at": 1712345678000, "confirmed_at": 1712344000000, "created_at": 1712343000000 } ``` --- ## GET /api/payments List all payments for your store. **Requires `X-API-Key`.** | Query param | Type | Default | Description | |-------------|------|---------|-------------| | status | string | — | Filter: `pending`, `confirmed`, `expired`, `cancelled` | | limit | integer | 50 | Max results | | offset | integer | 0 | Pagination offset | ### Response `200` ```json [ { "id": "pay_a1b2c3d4e5f6g7h8", "order_id": "ord_123", "address": "TGGr...", "expected_amount": 25.00, "expected_crypto": "USDT", "received_amount": 25.00, "status": "confirmed", "created_at": 1712343000000 } ] ``` --- ## POST /api/payments/:id/cancel Cancel a pending payment. **Requires `X-API-Key`.** Only works if status is `pending`. Releases the wallet back to the pool. ### Response `200` ```json { "id": "pay_a1b2c3d4e5f6g7h8", "status": "cancelled" } ``` --- ## GET /api/payments/:id/status Public endpoint (no auth). Poll for payment status. Used by frontend. ### Response `200` ```json { "status": "pending", "expected_amount": 25.00, "expected_crypto": "USDT", "chain": "tron", "received_amount": null, "address": "TGGr...", "amount_usd": 25.00, "expires_at": 1712345678000, "success_url": "https://yoursite.com/success", "fail_url": "https://yoursite.com/fail" } ``` --- ## GET /api/chains Public endpoint. List all enabled currencies (native + tokens). ### Response `200` ```json [ { "chain": "tron", "ticker": "TRX", "label": "TRON", "isToken": false, "freeWallets": 5 }, { "chain": "tron", "ticker": "USDT", "label": "USDT (TRC-20)", "isToken": true, "freeWallets": 5 }, { "chain": "bitcoin", "ticker": "BTC", "label": "Bitcoin", "isToken": false, "freeWallets": 5 }, { "chain": "ethereum", "ticker": "ETH", "label": "Ethereum", "isToken": false, "freeWallets": 5 }, { "chain": "ethereum", "ticker": "USDT", "label": "USDT (ERC-20)", "isToken": true, "freeWallets": 5 }, { "chain": "ethereum", "ticker": "USDC", "label": "USDC (ERC-20)", "isToken": true, "freeWallets": 5 }, { "chain": "solana", "ticker": "SOL", "label": "Solana", "isToken": false, "freeWallets": 5 }, { "chain": "solana", "ticker": "USDT", "label": "USDT (Solana)", "isToken": true, "freeWallets": 5 }, { "chain": "solana", "ticker": "USDC", "label": "USDC (Solana)", "isToken": true, "freeWallets": 5 }, { "chain": "bnb", "ticker": "BNB", "label": "BNB", "isToken": false, "freeWallets": 5 }, { "chain": "bnb", "ticker": "USDT", "label": "USDT (BEP-20)", "isToken": true, "freeWallets": 5 }, { "chain": "bnb", "ticker": "USDC", "label": "USDC (BEP-20)", "isToken": true, "freeWallets": 5 }, { "chain": "litecoin", "ticker": "LTC", "label": "Litecoin", "isToken": false, "freeWallets": 5 } ] ``` --- ## GET /api/payments/:id/chains Public endpoint. For multi-chain (USD) payments, returns available currencies with real-time estimated crypto amounts. ### Response `200` ```json [ { "chain": "tron", "ticker": "TRX", "label": "TRON", "isToken": false, "estimatedAmount": 18.700000, "available": true, "freeWallets": 5 }, { "chain": "tron", "ticker": "USDT", "label": "USDT (TRC-20)", "isToken": true, "estimatedAmount": 50.00, "available": true, "freeWallets": 5 }, { "chain": "bitcoin", "ticker": "BTC", "label": "Bitcoin", "isToken": false, "estimatedAmount": 0.00058, "available": true, "freeWallets": 5 }, { "chain": "ethereum", "ticker": "USDT", "label": "USDT (ERC-20)", "isToken": true, "estimatedAmount": 50.00, "available": true, "freeWallets": 5 } ] ``` --- ## POST /api/payments/:id/select-chain Public endpoint. Select chain and currency for a multi-chain (USD) payment. Assigns wallet and converts USD to crypto at market rate. ### Request ```json { "chain": "ethereum", "ticker": "USDT" } ``` | Field | Type | Required | Description | |-------|------|----------|-------------| | chain | string | yes | `tron`, `bitcoin`, `ethereum`, `solana`, `bnb`, `litecoin` | | ticker | string | no | `USDT`, `USDC`, etc. Defaults to chain's native coin | ### Response `200` ```json { "address": "0x37aA2ECe891374eAbCd0b08b73E266926B111111", "amount": 50.00, "currency": "USDT", "chain": "ethereum", "expires_at": 1712345678000 } ``` --- ## Webhooks Webhooks notify your server when a payment is confirmed or expires. ### Events | Event | Trigger | |-------|---------| | `payment.confirmed` | On-chain payment received >= 99% of expected amount | | `payment.expired` | 30-minute expiration reached without payment | ### Payload ``` POST https://yoursite.com/webhook Content-Type: application/json X-Signature: ``` ```json { "event": "payment.confirmed", "payment_id": "pay_a1b2c3d4e5f6g7h8", "order_id": "ord_123", "expected_amount": 25.00, "received_amount": 25.00, "currency": "USDT", "tx_hash": "abc123def456...", "address": "TGGr...", "status": "confirmed", "metadata": { "user_id": 42 }, "timestamp": 1712344000 } ``` ### Signature Verification The `X-Signature` header contains an HMAC-SHA256 hex digest of the raw request body, using your `webhook_secret` as the key. **Node.js:** ```javascript const crypto = require('crypto'); function verifyWebhook(rawBody, signature, webhookSecret) { const expected = crypto.createHmac('sha256', webhookSecret).update(rawBody).digest('hex'); return crypto.timingSafeEqual(Buffer.from(signature, 'hex'), Buffer.from(expected, 'hex')); } app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => { if (!verifyWebhook(req.body, req.headers['x-signature'], 'whsec_your_secret')) { return res.status(401).send('Invalid signature'); } const event = JSON.parse(req.body); if (event.event === 'payment.confirmed') { // Fulfill the order } res.sendStatus(200); }); ``` **Python:** ```python import hmac, hashlib from flask import Flask, request def verify_webhook(raw_body, signature, secret): expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest() return hmac.compare_digest(signature, expected) @app.route('/webhook', methods=['POST']) def webhook(): sig = request.headers.get('X-Signature', '') if not verify_webhook(request.data, sig, 'whsec_your_secret'): return 'Invalid', 401 event = request.json if event['event'] == 'payment.confirmed': # Fulfill the order pass return 'OK', 200 ``` **PHP:** ```php $raw = file_get_contents('php://input'); $sig = $_SERVER['HTTP_X_SIGNATURE'] ?? ''; $expected = hash_hmac('sha256', $raw, 'whsec_your_secret'); if (!hash_equals($expected, $sig)) { http_response_code(401); die('Invalid'); } $event = json_decode($raw, true); if ($event['event'] === 'payment.confirmed') { /* fulfill */ } http_response_code(200); ``` ### Retry Policy 3 attempts: immediately, +60s, +300s. 10-second timeout per attempt. Return `2xx` to acknowledge. --- ## Payment Statuses | Status | Description | Webhook | |--------|-------------|---------| | `pending` | Awaiting on-chain payment | — | | `confirmed` | Payment received >= 99% of expected | `payment.confirmed` | | `expired` | 30-min window elapsed | `payment.expired` | | `cancelled` | Cancelled by merchant via API | — | | `underpaid` | Payment received < 99% of expected | — | Transitions: `pending` -> `confirmed` | `expired` | `cancelled` | `underpaid` --- ## Fees **GET /api/fees** (public, no auth): ```json { "payment_fee_rate": 0.004, "payment_fee_percent": "0.4%", "withdrawal_fees": { "USDT": 3.0, "USDC": 3.0, "TRX": 2.0, "BTC": 0.0001, "ETH": 0.002, "SOL": 0.01, "BNB": 0.001, "LTC": 0.001 }, "min_withdrawal": { "USDT": 10.0, "USDC": 10.0, "TRX": 20.0, "BTC": 0.0005, "ETH": 0.005, "SOL": 0.05, "BNB": 0.01, "LTC": 0.005 } } ``` - Payment processing: 0.4% of received amount (deducted from merchant balance) - Withdrawal fees depend on asset and chain - Use `GET /api/fees` and `GET /api/withdrawals/available/:store_id?crypto=...` to calculate the exact current amount --- ## Stores ### POST /api/stores (JWT auth) ```json { "name": "My Store", "domain": "example.com", "webhook_url": "https://example.com/webhook", "business_description": "Description for admin approval" } ``` Response `201`: ```json { "id": "str_a1b2c3d4e5f6g7h8", "name": "My Store", "api_key": "sk_<48 hex chars>", "webhook_secret": "whsec_<48 hex chars>", "message": "Store created. Save the API key and webhook secret - they cannot be retrieved later." } ``` Stores start in `pending` status and require admin approval before the API key works. ### PATCH /api/stores/:id (JWT auth) Update `name`, `domain`, `webhook_url`, `success_url`, `fail_url`. ### POST /api/stores/:id/regenerate-key (JWT auth) Returns a new `api_key`. Old key is immediately invalidated. --- ## Withdrawals ### GET /api/withdrawals/available/:store_id (JWT auth) ```json { "crypto": "ETH", "available": 95.50, "withdrawal_fee": 0.002, "you_receive": 95.498, "min_withdrawal": 0.005 } ``` `crypto` is passed as a query parameter: ```bash curl "https://crypto.setype.com/api/withdrawals/available/str_...?crypto=ETH" \ -H "Cookie: token=..." ``` ### POST /api/withdrawals (JWT auth) ```json { "store_id": "str_...", "to_address": "0xRecipientAddress...", "amount": 1.25, "crypto": "ETH", "chain": "ethereum" } ``` Response `201`: ```json { "id": "wd_a1b2c3d4e5f6g7h8", "status": "pending", "amount": 1.25, "crypto": "ETH", "chain": "ethereum", "withdrawal_fee": 0.002, "you_receive": 1.248 } ``` Notes: - `crypto` is required - `chain` is optional when it can be resolved from `crypto` - address validation is chain-specific - scheduled batch auto-processing currently applies to `TRON USDT` - other assets are approved through the admin flow --- ## Integration Examples ### Seamless (API-only, no redirects) ```javascript // 1. Create payment const res = await fetch('https://crypto.setype.com/api/payments', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-API-Key': 'sk_your_key' }, body: JSON.stringify({ amount: 25, currency: 'USDT', order_id: 'ord_123', webhook_url: 'https://yoursite.com/webhook' }) }); const payment = await res.json(); // 2. Display address + amount in your UI console.log(payment.address); // "TGGrCNw..." console.log(payment.amount); // 25.00 // 3. Poll for status OR wait for webhook const check = await fetch(`https://crypto.setype.com/api/payments/${payment.id}/status`).then(r => r.json()); if (check.status === 'confirmed') { /* fulfill order */ } ``` ### Hosted Checkout (redirect) ```javascript // 1. Create payment with redirect URLs const payment = await createPayment({ amount: 50, currency: 'USD', // multi-chain: customer picks coin order_id: 'ord_789', success_url: 'https://yoursite.com/success?order=789', fail_url: 'https://yoursite.com/checkout?order=789' }); // 2. Redirect to hosted checkout window.location.href = payment.payment_url; // 3. Verify payment via webhook (don't trust redirects alone) ``` **Best practice:** Always use webhooks as source of truth. The success_url redirect is for UX only.