Docs / Reference
Client libraries and examples
Each client is a single file with no external dependencies. Copy it into your project and you get request signing, invoice creation and retrieval, and webhook verification.
Node.js
Node 22+. Classes CoineticClient and CoineticError, plus the verifyWebhook function.
PHP
PHP 8.1+ with the curl and json extensions. \Cryptopay\Client, \Cryptopay\verify_webhook.
What's inside
| Function | Node.js | PHP | Python | Go |
|---|---|---|---|---|
| Sign a request | signRequest | sign_request | sign_request | SignRequest |
| Create an invoice | createInvoice | createInvoice | create_invoice | CreateInvoice |
| Retrieve an invoice | getInvoice | getInvoice | get_invoice | GetInvoice |
| Verify a webhook | verifyWebhook | verify_webhook | verify_webhook | VerifyWebhook |
| Statuses safe to fulfill | PAID_STATUSES | PAID_STATUSES | PAID_STATUSES | PaidStatuses |
The technical file and class names (cryptopay.*, CryptopayClient) are legacy and won't change; Node.js and Python also provide the aliases CoineticClient and CoineticError.
All four are tested against the same vectors
Request and webhook signatures from every client match the test vectors. Writing a client in another language? Get it to match them first: it's the fastest way to catch a signing bug.
Minimal flow
pseudocode
invoice = client.createInvoice({order_id, price_amount: "3.00", price_currency: "USD",
return_url: "https://shop.example/orders/42"},
idempotencyKey = "order-42")
redirect(invoice.checkout_url)
on POST /webhooks/coinetic (raw body!):
event = verifyWebhook(WEBHOOK_SECRET, headers, rawBody) # otherwise 400/401
if seen(event.id): return 200 # duplicate delivery
inv = client.getInvoice(event.data.invoice_id) # re-check
if inv.status in PAID_STATUSES: grantOnce(inv.order_id)
return 200What the clients don't do
- They don't store secrets: the key and secret are passed in from environment variables or a secrets manager.
- They don't store processed
X-Webhook-Idvalues; that's your database's job. - They don't convert amounts to numbers: every amount is a string.
- They don't retry requests on their own. Retry with the same
Idempotency-Keyon429,5xxand network errors. - They don't run in browsers or mobile apps, only on the server, where the secret lives.