easyway
Create account

Crypto payment API for developers

easyway is a crypto payment gateway you drive from your own code: create an invoice, send the customer to the hosted checkout, get a signed webhook when it is paid, and withdraw with a second call. 23 coins on 12 networks, one flat 0.5% fee per payment, and a sandbox that behaves like production.

The whole API on one screen

JSON over HTTPS at https://api.easyway.cash, authenticated with Authorization: Bearer sk_…. Each key carries only the scopes you tick when you create it.

EndpointScopeWhat it does
POST /v1/invoicesinvoices:writeCreate an invoice in USD or a coin; returns payment_url for the hosted checkout
GET /v1/invoicesinvoices:readList invoices, newest first; filter by order_id or a date range
GET /v1/invoices/{id}invoices:readOne invoice with its status, amounts and coin
POST /v1/invoices/{id}/cancelinvoices:writeCancel an invoice while it is still pending (no payment seen)
GET /v1/balancesbalances:readAvailable and locked balance per coin and network
POST /v1/payoutspayouts:writeWithdraw to an address on your whitelist
GET /v1/payoutspayouts:readList payouts; filter by status, coin or date range
GET /v1/payouts/{id}payouts:readOne payout with its status and transaction hash
GET /v1/assetsany keyCoins and networks open now, with confirmations, fees and minimums
GET /v1/ratesany keyCurrent USD price of every coin

The same contract is published as an OpenAPI 3.1 file at /openapi.json, so you can import it into Postman or Insomnia or generate a typed client. Field-by-field reference and samples are in the API docs.

Your first call

curl -X POST https://api.easyway.cash/v1/invoices \
  -H "Authorization: Bearer $EASYWAY_API_KEY" \
  -H "Idempotency-Key: order-1042" \
  -H "Content-Type: application/json" \
  -d '{"amount":"49.90","currency":"USD","order_id":"1042","success_url":"https://shop.example/thanks"}'

The same request from Node.js:

// A 49.90 USD invoice; the customer picks a coin on the hosted checkout
const res = await fetch("https://api.easyway.cash/v1/invoices", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.EASYWAY_API_KEY}`,
    "Idempotency-Key": "order-1042",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "amount": "49.90",
    "currency": "USD",
    "order_id": "1042",
    "success_url": "https://shop.example/thanks"
  }),
});
if (!res.ok) throw new Error(`easyway ${res.status}: ${(await res.json()).error}`);
const data = await res.json();

The answer has an id to save with your order and a payment_url to redirect to. The customer picks a coin and network there; the coin amount is fixed when they pick it. Leave out allowed_assets to offer every coin, or list asset ids to offer only those. The USDT TRC-20 guide walks through the full flow in Node.js, PHP and Python.

Conventions you can rely on

TopicHow it works
AmountsDecimal strings ("49.9"), never floats, in requests and responses
ValidationUnknown fields are rejected, not ignored: 400 validation_error with the names of the bad fields
ErrorsA stable machine-readable error code in every error body; match on it, not on the message
RetriesSend Idempotency-Key (8–128 characters) on POSTs; a repeat with the same body returns the first answer with Idempotent-Replayed: true, a different body under the same key gets 422, a repeat while the first is still running gets 409
Pagingpage and pageSize (up to 100), newest first, with total; from / to take whole UTC days
Rate limit300 requests per minute per key; 429 rate_limited with standard RateLimit headers
Test and livesk_test_ and sk_live_ keys hit the same URLs; the key decides the mode and a test key never sees live data

Webhooks

Subscribe an HTTPS endpoint to invoice.confirming, invoice.paid, invoice.underpaid, invoice.expired, invoice.cancelled, payout.sent and payout.failed. Each delivery is signed with HMAC-SHA256 over the timestamp and the raw body (X-Webhook-Signature: t=…,v1=…), times out after 10 seconds and is retried up to 8 times over about 45 hours; an endpoint that fails 25 times in a row is switched off until you turn it back on. Verify webhook signatures has working code for Node.js, PHP, Python and Next.js.

Running several shops on one account? Give each its own API key: invoice events of that key can go to the key's own webhook, and the checkout can show that shop's name and support e-mail instead of the account's.

Keys and funds

Keys are stored only as a keyed hash, can be limited to a list of IP addresses and can be revoked at any time. In live mode a payout can only go to an address you whitelisted in the dashboard with 2FA, so the API alone cannot send funds anywhere new. The server that answers the API holds only watch-only public keys; signing happens in a separate process. easyway holds your balance until you withdraw it — the security page explains how.

What the API does not do (yet)

So you can plan around it rather than find out later:

Not availableWhat to do instead
An SDK packageUse the cURL / Node.js / PHP / Python samples in the docs or generate a client from /openapi.json
Refund endpointSend a payout to the customer's address after adding it to your whitelist (see underpaid and late payments)
Cancelling a payout by APICancel a still-pending payout in the dashboard
Recurring billingCreate a new invoice per billing period from your own scheduler
Conversion to another coin or to fiatPayments stay in the coin the customer paid with; withdraw them as they are

Where to go next

Test crypto payments in the sandbox, send payouts from code, the guide index, and the pricing page for every coin's confirmations, withdrawal fee and minimum.

Create a merchant accountRead the API docs
Crypto payment API for developers | easyway