Getting Started with the Weenx Integration API
Server-to-server contract for workspace-scoped crypto payments — invoices, hosted checkout, charges, payouts, refunds, on/off-ramp, auto-convert, settlement, balances, subscriptions, reporting, and signed webhooks.
Build a secure backend-to-backend integration between your platform and Weenx.
The Weenx Integration API is designed for trusted server-side systems. It gives your backend direct access to workspace-scoped invoicing and hosted checkout, incoming-payment reconciliation, authorize/capture charges, receive-address management, crypto payouts, invoice refunds and reversals, internal balance transfers, fiat on-ramp and off-ramp, auto-convert rules, hot/cold settlement configuration, wallet balances, recurring subscriptions, reporting, and signed outbound webhooks.
Overview
The Integration API allows a merchant backend to:
- authenticate with a workspace API key
- confirm which workspace the key resolves to, and inspect the scopes and plan it carries
- read the asset catalog — the currencies, networks, and
currencyNetworkIdvalues enabled for the workspace - read wallet balances for funding and reconciliation
- create invoices, build a hosted-checkout descriptor, and issue signed payment links
- run an authorize/capture flow on top of an invoice with the charges API
- assign a fixed per-customer receive address, or allocate a one-time per-invoice address
- reconcile incoming payments, deposits, and settlement batches
- queue crypto payouts, estimate their fees, cancel them while pending, and manage the payout destination whitelist
- queue invoice refunds and reversals back to a destination address
- move balance between your own workspace environments with internal transfers
- buy crypto with fiat (on-ramp) and sell crypto for fiat to a bank beneficiary (off-ramp)
- define auto-convert rules that swap a received asset into a target asset
- configure on-chain hot/cold settlement and USD hot-float threshold policies
- run recurring billing with subscription plans and subscriptions
- read plan, quota, and usage information
- pull reporting as JSON or CSV
- manage webhook endpoints and consume signed outbound events
The API is workspace-scoped. The workspace is resolved from the X-Api-Key header. Do not send a workspace identifier in a route, query string, or request body — the API ignores it and always acts on the workspace the key belongs to.
How the money moves
Three balances matter, and they move at different moments.
The workspace balance is your settled crypto held with Weenx, tracked per asset (currencyNetworkId). It is credited when an incoming payment confirms on-chain and is settled, and it is debited when you queue a payout, a refund, or an outgoing internal transfer.
An invoice is a request for payment. You create it for an amount in a specific asset; Weenx watches the receive address and records incoming on-chain payments against it. An invoice moves through Created, Waiting, Partial, Confirming, Paid, Expired, Failed, Cancelled, and ManualReview. Nothing is credited until the underlying on-chain payment reaches the required number of confirmations.
The card / customer-facing balances are out of scope for this money model: this API settles crypto to your workspace, and pays crypto out from it.
Two rules follow from this:
- The chain is the source of truth. An incoming payment is only credited — and only announced to your webhook endpoint, dashboard, and ledger — after it reaches finality. Build for the confirmation delay; do not treat a detected-but-unconfirmed payment as money you hold.
- Your platform settlement fee is deducted from your proceeds when an invoice is paid, not billed separately per transaction. The remainder is your net credit. See Security and Authentication and your plan for the exact percentage.
Practically: read GET /v1/balances before you queue a payout, watch for the PaymentConfirmed webhook (or poll GET /v1/invoices/{invoiceId}/status) to know an invoice is paid, and reconcile with GET /v1/payments when you need the on-chain detail.
Base URL
Weenx issues your Integration API host together with your API key. Every example on these pages uses the placeholder below; substitute the host you were given.
https://api.weenx.com
Every endpoint is served under the v1/ path prefix, for example https://api.weenx.com/v1/me.
Authentication
Every endpoint except the unauthenticated root (/), health (/health), and the OpenAPI document (/openapi/v1.json) requires the X-Api-Key header:
X-Api-Key: YOUR_WORKSPACE_API_KEYExample:
curl --request GET \
--url https://api.weenx.com/v1/me \
--header 'X-Api-Key: YOUR_WORKSPACE_API_KEY'An API key is workspace-scoped and carries a set of granted scopes. A request is rejected when the key is missing, empty, malformed, inactive, expired, or cannot resolve to an active workspace. Store API keys only in trusted backend infrastructure. Never expose them in browser code, mobile apps, public JavaScript bundles, public repositories, or customer-facing clients.
Scopes follow a resource:action shape — invoices:read, payouts:write, and so on — and a key that holds the wildcard * satisfies every endpoint. The full scope-to-endpoint mapping is in Security and Authentication.
The response envelope
Every response, success or failure, is the same envelope. The three keys are always present.
Successful responses:
{
"success": true,
"message": "Invoice created.",
"data": { }
}On success, message is a short human-readable string and the payload you want is in data. Drive your integration from data, not from the exact wording of message.
Failure responses carry success: false and a display-safe message. Typed domain errors also carry a stable machine-readable code:
{
"success": false,
"message": "Your plan does not include this capability.",
"code": "plan.capability_denied"
}Not every failure carries a code — some checks (for example a missing scope) return just success and message. When a request fails input validation on individual fields, the envelope also carries an errors object keyed by field name. Drive your control flow from the HTTP status code and, where present, the code; treat message as display text whose exact wording can change.
Idempotency
State-changing writes can be made safe to retry with an idempotency key. There are two placements, and which one an endpoint uses is fixed:
Idempotency-Keyheader —POST /v1/invoicesaccepts an optionalIdempotency-Keyheader. A retry with the same key and the same payload replays the stored response; the same key with a different payload is rejected with409 Conflict.idempotencyKeybody field — payouts (POST /v1/payouts), internal transfers (POST /v1/transfers), and ramp order creation carry the idempotency key inside the request body. For internal transfers the field is required; the service deduplicates on it so a retry returns the original transfer instead of moving funds twice.
An idempotency key may be up to 128 characters and is retained for 24 hours. Reuse the same key only for the same logical business action with the same payload; do not mint a new key for a write whose outcome is unknown — retry with the same key, or reconcile through the read endpoints and webhooks.
Amounts and currencies
Every money value is a JSON number. Parse it into a decimal type; never compare the serialized text, and do not assume a fixed number of fraction digits — the transport form carries the scale of the value, which varies by asset and by endpoint. Round for display to the asset's own minor unit.
Assets are identified by an integer currencyNetworkId, which pins both the currency and the network it settles on (for example USDT on TRC-20 is a different currencyNetworkId from USDT on ERC-20). Resolve the valid values for your workspace from the catalog:
GET /v1/catalog/currencies— the currencies (code, symbol, decimals,isFiat,isStable)GET /v1/catalog/networks— the networks (family, chain id, default confirmations, address-tag rules)GET /v1/catalog/currency-networks— the enabledcurrencyNetworkIdvalues, each with its token standard and contract address
Store the currencyNetworkId values your integration uses; do not hard-code them, because the set is scoped to the assets enabled for your workspace and plan.
Timestamps
Every timestamp in every response and webhook payload is a UTC instant in ISO-8601 format with a trailing Z, for example 2026-08-14T10:30:00Z. Field names carry the ...AtUtc suffix to make this explicit. Parse timestamps with a library that honours the offset and convert to your users' local zone only at display time; do not assume a value is already in your server's local zone.
Pagination
List endpoints paginate in one of two styles, depending on the resource:
page/pageSize— invoices, payouts, incoming payments, deposits, settlement batches, and webhook deliveries.pagestarts at 1;pageSizeis clamped to a per-endpoint maximum. These responses carrypage,pageSize, andtotal.skip/take— quick links, no-code buttons, subscriptions, and subscription plans.
One transport detail to plan for: on the paged list endpoints, a row's status is serialized as an integer code, while the corresponding detail/getter endpoint returns the string enum name for the same field. Read a list row's status as a number and a detail view's status as a string.
Recommended first calls
Run these once, in this order, when you connect a new API key:
GET /v1/meGET /v1/billing/planGET /v1/catalog/currency-networksGET /v1/balancesPOST /v1/invoicesGET /v1/invoices/{invoiceId}/statusPOST /v1/webhooks
This confirms credentials and workspace identity, the plan and its capabilities, the assets you can transact in, your balances, and the invoice and webhook behaviour, before you put real traffic through.
Step 1: Confirm the key context
curl --request GET \
--url https://api.weenx.com/v1/me \
--header 'X-Api-Key: YOUR_WORKSPACE_API_KEY'GET /v1/me needs only a valid key — no scope. It returns:
workspaceEnvironmentId— the workspace this key acts onapiKeyId— the id of the authenticating keygrantedScopes— the scopes the key carriesplan— the effective plan and its capabilities, ornullplanUnavailableReason— set whenplanisnull
Store the expected workspaceEnvironmentId in your backend configuration and fail your health check if the value returned does not match.
Step 2: Read the plan
curl --request GET \
--url https://api.weenx.com/v1/billing/plan \
--header 'X-Api-Key: YOUR_WORKSPACE_API_KEY'GET /v1/billing/plan returns your plan code and name, the monthly and setup fees, the settlement fee percentage, per-asset limits, and the capability flags that gate several endpoints — hostedCheckout, customPaymentPage, staticAddresses, autoConvert, webhooks, makerCheckerPayouts, dedicatedWallets, and customSettlementSchedules. A call to a capability your plan does not grant is rejected with 403 and the machine code plan.capability_denied, so check the flags before you enable a flow. The capacity and usage endpoints under GET /v1/billing/capacity/... and GET /v1/billing/usage/monthly-volume report how much of each quota you have consumed.
Step 3: Read the catalog and balances
curl --request GET \
--url https://api.weenx.com/v1/catalog/currency-networks \
--header 'X-Api-Key: YOUR_WORKSPACE_API_KEY'
curl --request GET \
--url https://api.weenx.com/v1/balances \
--header 'X-Api-Key: YOUR_WORKSPACE_API_KEY'The catalog gives you the valid currencyNetworkId values. GET /v1/balances returns one row per wallet with availableBalance, lockedBalance, and totalBalance in the wallet's asset. Read availableBalance before any billable operation such as a payout.
Step 4: Create an invoice
curl --request POST \
--url https://api.weenx.com/v1/invoices \
--header 'Content-Type: application/json' \
--header 'X-Api-Key: YOUR_WORKSPACE_API_KEY' \
--header 'Idempotency-Key: order-1234' \
--data '{
"currencyNetworkId": 1001,
"amount": 49.99,
"orderId": "order-1234",
"title": "Order #1234",
"expiresInSeconds": 3600,
"redirectUrl": "https://example.com/return"
}'Only currencyNetworkId (a positive integer) and amount (a positive number) are required. A successful response returns:
invoiceIdstatus— the invoice status as a string name (oftenWaitingon a fresh invoice)expectedAmountexpiresAtUtc— nullable
Store the returned invoiceId. Use it to read detail (GET /v1/invoices/{invoiceId}), poll status (GET /v1/invoices/{invoiceId}/status), build a hosted-checkout descriptor (GET /v1/invoices/{invoiceId}/hosted-checkout), issue a signed payment link (POST /v1/invoices/{invoiceId}/links), or allocate a one-time receive address (POST /v1/invoices/{invoiceId}/address).
Step 5: Get paid, and know when
A cardholder — here, a payer — sends crypto to the invoice's receive address. Weenx detects the transaction, waits for the required confirmations, and settles it to your workspace balance. There are two ways to observe this, and you should use both:
- Webhooks (push). Subscribe an endpoint and handle
PaymentDetected(pre-confirmation) andPaymentConfirmed(final). See Webhooks. - Reads (pull). Poll
GET /v1/invoices/{invoiceId}/statusfor the invoice, or reconcile the on-chain detail withGET /v1/payments,GET /v1/payments/deposits, andGET /v1/payments/settlement-batches.
Use webhooks for fast notification and the read endpoints for authoritative current state.
Step 6: Pay out
curl --request POST \
--url https://api.weenx.com/v1/payouts \
--header 'Content-Type: application/json' \
--header 'X-Api-Key: YOUR_WORKSPACE_API_KEY' \
--data '{
"currencyNetworkId": 1001,
"amount": 25.00,
"destinationAddress": "TXk...destination",
"idempotencyKey": "payout-order-1234"
}'Creating a payout over the Integration API queues the request. The destination is checked against your payout whitelist at create time, and approval and on-chain sending remain operator-gated in the Weenx console. This is deliberate: a leaked API key cannot move funds out on its own. Read the payout back with GET /v1/payouts/{payoutRequestId}, estimate fees beforehand with GET /v1/payouts/fee-estimate, and follow completion through the PayoutSent, PayoutConfirming, and PayoutCompleted webhooks. The money-movement model is covered in full in Payouts and Money Movement.
Main endpoint groups
Context and catalog
GET /v1/meGET /v1/catalog/currenciesGET /v1/catalog/networksGET /v1/catalog/currency-networksGET /v1/balances
Invoices, charges, and links
GET /v1/invoicesPOST /v1/invoicesGET /v1/invoices/{invoiceId}GET /v1/invoices/{invoiceId}/statusPOST /v1/invoices/{invoiceId}/cancelGET /v1/invoices/{invoiceId}/hosted-checkoutPOST /v1/invoices/{invoiceId}/linksGET /v1/invoices/{invoiceId}/linksPOST /v1/chargesGET /v1/charges/{chargeId}POST /v1/charges/{chargeId}/refreshPOST /v1/charges/{chargeId}/pricing/selectPOST /v1/charges/{chargeId}/authorizePOST /v1/charges/{chargeId}/capturePOST /v1/charges/{chargeId}/cancelGET /v1/charges/{chargeId}/capturesGET /v1/charges/{chargeId}/eventsPOST /v1/links/quicklinksGET /v1/links/quicklinksPOST /v1/links/quicklinks/{id}/disableGET /v1/links/{paymentLinkId}POST /v1/links/{paymentLinkId}/disablePOST /v1/buttonsPUT /v1/buttons/{id}GET /v1/buttonsPOST /v1/buttons/address-only/provision
Addresses and customers
POST /v1/addresses/staticPOST /v1/addresses/static/bulkGET /v1/addresses/staticGET /v1/addresses/static/{id}/historyPOST /v1/addresses/static/{id}/statePOST /v1/addresses/static/{id}/retirePOST /v1/addresses/static/{id}/rotatePOST /v1/invoices/{invoiceId}/addressGET /v1/invoices/{invoiceId}/addressesPOST /v1/customersGET /v1/customersGET /v1/customers/{id}PUT /v1/customers/{id}POST /v1/customers/{id}/archivePOST /v1/customers/{id}/restoreDELETE /v1/customers/{id}
Payments, payouts, refunds, and transfers
GET /v1/paymentsGET /v1/payments/{id}GET /v1/payments/depositsGET /v1/payments/settlement-batchesPOST /v1/payoutsGET /v1/payoutsGET /v1/payouts/{payoutRequestId}GET /v1/payouts/fee-estimatePOST /v1/payouts/{payoutRequestId}/cancelGET /v1/payout-whitelistPOST /v1/payout-whitelistPOST /v1/payout-whitelist/{id}/activatePOST /v1/payout-whitelist/{id}/deactivateGET /v1/invoices/{invoiceId}/refundsPOST /v1/invoices/{invoiceId}/refunds/quotePOST /v1/invoices/{invoiceId}/refundsGET /v1/invoices/{invoiceId}/reversalsPOST /v1/invoices/{invoiceId}/reversals/quotePOST /v1/invoices/{invoiceId}/reversalsPOST /v1/transfersGET /v1/transfers
Ramp, auto-convert, and settlement
POST /v1/onramp/quotesPOST /v1/onramp/ordersGET /v1/onramp/ordersGET /v1/onramp/orders/{orderId}POST /v1/offramp/beneficiariesPOST /v1/offramp/beneficiaries/{id}/verifyGET /v1/offramp/beneficiariesPOST /v1/offramp/quotesPOST /v1/offramp/ordersGET /v1/offramp/ordersGET /v1/offramp/orders/{orderId}GET /v1/auto-convert/rulesPOST /v1/auto-convert/rulesDELETE /v1/auto-convert/rules/{id}GET /v1/settlement/policiesPOST /v1/settlement/policiesPOST /v1/settlement/policies/applyPOST /v1/settlement/configPOST /v1/settlement/config/preview-splitPUT /v1/settlement/coin-acceptance/policyGET /v1/settlement/coin-acceptanceGET /v1/settlement/coin-acceptance/effective/{currencyNetworkId}
Subscriptions, billing, reports, and webhooks
POST /v1/subscription-plansPUT /v1/subscription-plans/{id}GET /v1/subscription-plansDELETE /v1/subscription-plans/{id}POST /v1/subscriptionsGET /v1/subscriptionsPOST /v1/subscriptions/{id}/pausePOST /v1/subscriptions/{id}/resumePOST /v1/subscriptions/{id}/cancelPOST /v1/subscriptions/{id}/change-plan/previewPOST /v1/subscriptions/{id}/change-planGET /v1/billing/planGET /v1/billing/capacity/static-addressesGET /v1/billing/capacity/team-membersGET /v1/billing/capacity/assetsGET /v1/billing/usage/monthly-volumeGET /v1/reports/snapshotGET /v1/reports/dailyGET /v1/reports/fee-breakdownGET /v1/reports/treasury-balancesGET /v1/reports/settlementsGET /v1/reports/product/...(ramp volume, card spend, subscriptions, affiliate, profit-and-loss, invoice conversion)POST /v1/webhooksGET /v1/webhooksGET /v1/webhooks/{id}/deliveriesPOST /v1/webhooks/{id}/rotate-secretPOST /v1/webhooks/{id}/testPOST /v1/webhooks/{id}/disableGET /v1/webhooks/events
Most reporting endpoints also expose a CSV variant at .../export.csv.
Production rules
- Store API keys only in backend secret storage; never expose them in browser, mobile, public JavaScript, or public repositories.
- Use HTTPS for all production traffic.
- Resolve
currencyNetworkIdvalues from the catalog; do not hard-code them. - Send the same idempotency key when retrying the same write, and never mint a new key for a write whose final state is unknown.
- Treat a detected-but-unconfirmed payment as not-yet-money; wait for
PaymentConfirmedor aPaidinvoice status. - Store returned
invoiceId,payoutRequestId, and operation ids for reconciliation. - Verify every webhook signature against the raw request body before you act on it.
- Check plan capability flags before enabling gated flows, and handle the
plan.capability_denied403. - Reconcile uncertain outcomes with invoice status, payment reads, payout reads, deposits, settlement batches, and webhooks.
- Build only on the documented fields in the responses you consume; ignore any field you do not recognise.
Updated 6 days ago