Developer Documentation

Build against the live CoinDirectly merchant API.

Current API reference below is generated from the deployed backend. Edit the short introduction here via Admin Content Editor; endpoint details remain visible.

Production API · USDT on TRON (TRC20)

Integrate real USDT payments

CoinDirectly creates exact-amount invoices, displays a hosted checkout, verifies real transfers on the TRON blockchain, and sends signed payment notifications. Each customer pays directly to the approved merchant's registered wallet. CoinDirectly does not sweep customer USDT.

Register & verify email→Admin approval→Pay 30.00 USDT / 30 days→Create API key→Create invoice
The subscription price displayed here is read from the live plan configuration when available. The subscription invoice includes its own unique amount adjustment under 1 USDT. Your customer's invoice uses your merchant wallet, not CoinDirectly's subscription wallet.

Open Merchant Dashboard ↗ View plan & eligibility

01. Server-to-server authentication

Base URL: https://coindirectly.org/gateway/v1. Add the header X-API-Key: YOUR_SECRET_MERCHANT_KEY to merchant requests. Create/rotate your key in Merchant Dashboard → API & Webhooks after admin approval and an active subscription. Never embed the key in HTML, browser JavaScript, mobile source code or a public Telegram bot command.

curl -sS https://coindirectly.org/gateway/v1/readiness \
  -H 'X-API-Key: YOUR_SECRET_MERCHANT_KEY'

node_and_scanner_ready: true plus a registered receiving wallet means the chain verifier is currently ready. Availability may change.

02. Merchant API reference

PUT/services/{service_id}

Configure a reusable package price

Service ID: letters, numbers, underscore, dot, dash (maximum 100 characters). Amount is a string with up to six decimals; accepted range is 0.01–10,000,000 USDT.

curl -X PUT 'https://coindirectly.org/gateway/v1/services/basic-plan' \
  -H 'X-API-Key: YOUR_SECRET_MERCHANT_KEY' \
  -H 'Content-Type: application/json' \
  --data '{"amount_usdt":"10.00","enabled":true}'

List: GET /services (same API key). Disabled services cannot be used for new invoices.

POST/invoices

Create a hosted checkout invoice

Choose either amount_usdt (any valid package price) or an enabled service_id. Supply a unique reference from your store/bot. Expiry: 10–30 minutes. Repeating the same merchant reference with identical parameters returns the existing invoice; conflicting parameters return 409.

curl -X POST 'https://coindirectly.org/gateway/v1/invoices' \
  -H 'X-API-Key: YOUR_SECRET_MERCHANT_KEY' \
  -H 'Content-Type: application/json' \
  --data '{"merchant_reference":"order-1001", "amount_usdt":"50.00", "expires_minutes":30}'

Response fields: invoice_id, merchant_reference, deposit_address, package_usdt, amount_usdt (the exact amount), unique_addition_usdt, status, expires_at, checkout_url.

{
 "invoice_id": "INVOICE_ID_FROM_API",
 "merchant_reference": "order-1001",
 "deposit_address": "YOUR_APPROVED_TRON_WALLET",
 "package_usdt": "50",
 "amount_usdt": "50.27",
 "unique_addition_usdt": "0.27",
 "status": "PENDING",
 "checkout_url": "https://coindirectly.org/gateway/v1/checkout/INVOICE_ID?token=CHECKOUT_TOKEN"
}

Illustrative response values only; actual amounts, invoice IDs and tokens are generated by the API. The unique payable amount is reserved across previous invoices to avoid unsafe duplicate matching; for extremely high invoice volumes the API can use more decimal places or return 409 when the amount space is exhausted.

GET/invoices/{invoice_id}

Check payment status

Requires merchant API key. Lookup by your own order ID: GET /invoices/by-reference/{merchant_reference}. Get matched blockchain transfers: GET /invoices/{invoice_id}/events.

curl 'https://coindirectly.org/gateway/v1/invoices/INVOICE_ID' \
  -H 'X-API-Key: YOUR_SECRET_MERCHANT_KEY'

Relevant values: status, confirmed_usdt, remaining_usdt, deposit_address, and expires_at. Only deliver automatically after the server-to-server result says PAID.

GET/public/invoices/{invoice_id}?token=...

Customer-facing status and payment claims

This scoped token is embedded in the checkout URL. It is a bearer credential for that invoice; do not publish it widely. The hosted checkout polls the scoped status endpoint. Customers who have already paid can claim a specific blockchain TXID:

POST /public/invoices/INVOICE_ID/claims?token=CHECKOUT_TOKEN
Content-Type: application/json

{"txid":"64_character_TRON_transaction_hash"}

The TXID must refer to a successful, finalized transfer of the genuine TRON USDT contract to the invoice's receiving wallet. An exchange withdrawal order number is not a TXID. The claim may return VERIFIED or REVIEW_REQUIRED; a public TXID alone does not prove who owns the payment. Manual review is used for ambiguous amounts, late claims and underpayments.

03. Signed payment webhooks

In Merchant Dashboard → API & Webhooks, configure a publicly reachable HTTPS URL on port 443. Save the generated webhook secret securely (it is shown only once). Webhooks are retried after non-2xx responses.

Webhook body includes event_id, event_type (such as invoice.paid or invoice.partial), and invoice with the actual payment status. Verify these headers before processing:

X-CoinDirectly-Timestamp: UNIX_SECONDS
X-CoinDirectly-Signature: sha256=HEX_HMAC_SHA256
X-CoinDirectly-Event-ID: DELIVERY_ID

Signature algorithm: HMAC_SHA256(webhook_secret, timestamp + "." + raw_request_body). Compare in constant time; reject stale timestamps; deduplicate by event_id in the signed JSON body. Reply with HTTP 2xx only after safely storing the event. Webhooks may arrive more than once and must be idempotent. Before delivering goods, re-query the invoice with your server-side merchant API key.

import hmac, hashlib
expected = 'sha256=' + hmac.new(
    WEBHOOK_SECRET.encode(),
    (timestamp + '.').encode() + raw_body,
    hashlib.sha256
).hexdigest()
verified = hmac.compare_digest(expected, received_signature)

04. Statuses, errors & safe fulfillment

Invoice status

PENDING waiting. PARTIAL credited underpayment after review. PAID confirmed. EXPIRED/EXPIRED_PARTIAL outside payment window. MANUAL_REVIEW requires human action.

HTTP errors

401 missing/invalid API key; 403 inactive subscription, suspended account or unregistered wallet; 404 unknown service/invoice; 409 reference conflict or uncertain payment; 422 invalid input; 429 claim/rate limits; 503 chain/scanner unavailable.

Do not mark an order paid because a customer submits a screenshot, public TXID, or clicks “I Paid”. Trust a verified PAID result and your own merchant reference. If the chain scanner is unavailable, payment approval must fail closed.

05. Telegram bot / Python / PHP integration

Your Telegram bot's backend can call the Merchant API over HTTPS. Never send a Merchant API Key to Telegram users and never place it in client-side scripts. Use the existing owner's merchant key only for the platform's own subscription/approved services; another merchant's customer payments must always use that merchant's separate key and receiving wallet.

Owner usage: sign in at Admin Dashboard to approve applications, set the 30-day plan and edit website pages. The Admin dashboard does not use the public merchant API key. For your own Telegram bot payment flow, use a server-side merchant API key linked to the correct receiving wallet and follow the sample client included in the upgrade ZIP.

# Run from your private server, never public browser
export COINDIRECTLY_API_KEY='YOUR_MERCHANT_API_KEY'
python3 coindirectly_bot_client.py create order-telegram-001 10.00
python3 coindirectly_bot_client.py status INVOICE_ID

For PHP websites or bots, send the same request using cURL with X-API-Key. Use returned checkout_url as a Telegram button. Check status using your server and grant service access only after PAID. See the examples supplied in the package.

Support and responsible operation

Contact Telegram Support if a customer paid the wrong amount, used a different TRON address or has a confirmed TXID requiring manual review. Payment verification and automated webhooks require production tests and continuous monitoring; an API-ready status alone does not guarantee uninterrupted processing.