Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.coinvoyage.io/llms.txt

Use this file to discover all available pages before exploring further.

Use the CoinVoyage API when you need direct control over pay order creation, quote selection, standalone swaps, webhook management, refunds, fee claims, or backend reconciliation. Most React integrations should start with the PayKit SDK, then use the API directly for server-side workflows that should never run in the browser.
Endpoint-level schemas, request bodies, and response examples are available in the generated API Reference. This page explains the conventions that apply across the API.

Base URL

Production API requests use:
https://api.coinvoyage.io/v2
SDK integrations select the base URL through the environment option:
import { ApiClient } from "@coin-voyage/paykit/server";

const apiClient = new ApiClient({
  apiKey: process.env.COIN_VOYAGE_API_KEY!,
  environment: "production",
});
EnvironmentUse forNotes
productionLive payments and settlementUses production networks, routes, and dashboard configuration.

Authentication

CoinVoyage uses two credential types:
CredentialWhere to use itPurpose
API keyBrowser or serverIdentifies your organization. Safe to expose in client-side code.
API secretServer onlySigns privileged operations such as sales, refunds, PayOrder listing, KYC links, bank account management, withdrawals, webhooks, and fee claims.
Keep the API secret in a server-side environment variable or secrets manager. Never expose it through frontend bundles, mobile apps, public repositories, logs, analytics events, or client-side error reporting.

Public API key flows

DEPOSIT PayOrders can be created with the public API key because the destination address is supplied by the integration and no merchant settlement configuration is modified.
const { data, error } = await apiClient.createDepositPayOrder({
  intent: {
    asset: {
      chain_id: ChainId.SUI,
      address: null,
    },
    amount: {
      token_amount: 10,
    },
    receiving_address: "0xYourReceivingAddress",
  },
});

Signed server-side flows

SALE, REFUND, PayOrder listing, KYC links, bank account management, withdrawals, webhook management, and fee operations require your API secret. The SDK generates the authorization signature internally when you pass the raw secret to the relevant method.
const { data, error } = await apiClient.createSalePayOrder(
  {
    intent: {
      amount: {
        fiat: {
          amount: 49.99,
          unit: "USD",
        },
      },
    },
    metadata: {
      order_id: "order_123",
    },
  },
  process.env.COIN_VOYAGE_API_SECRET!
);
If you call the HTTP API manually, generate an HMAC-SHA256 authorization value from the HTTP method, request path, and timestamp. The SDK helper returns the header value in the required format:
const authorization = apiClient.generateAuthorizationSignature(
  process.env.COIN_VOYAGE_API_SECRET!,
  "POST",
  "/pay-orders"
);
APIKey=<apiKey>,signature=<signature>,timestamp=<timestamp>
Generate authorization signatures on your server only. A leaked API secret can create merchant sales, refunds, KYC links, bank account changes, withdrawals, webhooks, and fee claims for your organization.

Where payout APIs fit

KYC, bank accounts, and withdrawals are part of the optional fiat off-ramp flow. They do not replace PayOrders, and they are not required when you only want on-chain settlement to a wallet.
API areaWhen to use itCredential
KYCCreate a hosted verification link or check whether an organization is approved for fiat payout activity.API secret
Bank accountsAdd and retrieve linked payout destinations for a verified individual or business.API secret
WithdrawalsMove a supported on-chain settlement balance to a linked bank account.API secret, plus wallet execution when required
Withdrawals to bank accounts are optional. You can bring your own externally owned account (EOA), receive funds there, and move funds anywhere you want from that wallet. Use withdrawals only when your product needs a CoinVoyage-managed fiat payout to a linked bank account.
See Integration flows for the end-to-end KYC -> bank account -> withdrawal sequence.

Where swap APIs fit

Swap APIs are for standalone on-chain asset exchanges. They are separate from PayOrders: a PayOrder may use swaps internally while routing a payment, but swapQuote() and swapData() are useful when your product wants to quote and execute a swap as its own user action.
API areaWhen to use itCredential
Swap quotesShow the expected route, output amount, and fees before the user signs.API key
Swap execution dataRetrieve the transaction data the source wallet needs to sign and submit.API key, plus source-wallet signing
See Integration flows for the standalone swap sequence.

Request conventions

  • Send JSON request bodies with Content-Type: application/json.
  • Use ISO 8601 timestamps in UTC for stored times and event payloads.
  • Treat IDs as opaque strings. Do not parse structure out of payorder_id, webhook IDs, quote IDs, or transaction hashes.
  • Store token amounts exactly as returned by the API when reconciling payments. Prefer raw string amounts for accounting systems that require exact precision.
  • Attach your own order, user, or invoice identifiers in metadata so webhook handlers can reconcile events without a separate lookup.

Response shape

The SDK wraps every result in APIResponse<T>:
type APIResponse<T> = {
  data?: T
  error?: {
    path: string
    statusCode: number
    status: string
    message: string
  }
}
Check error before using data:
const { data, error } = await apiClient.getPayOrder("payorder_123");

if (error) {
  console.error(error.statusCode, error.message);
  return;
}

console.log(data.status);

Error handling

Handle API errors by status code category:
StatusMeaningRecommended action
400Invalid request body, parameters, or mode-specific constraintsShow a validation error and fix the request before retrying.
401Missing, invalid, or expired authorizationCheck API key, signature, timestamp, and server-side secret configuration.
403Credential is valid but not allowed to perform the actionConfirm organization permissions, environment, and feature access.
404Resource not foundConfirm the ID belongs to the same organization and environment.
409Request conflicts with current resource stateRefresh the PayOrder and decide whether the action is still valid.
422Semantically valid JSON that fails business validationSurface the message to the operator or correct the integration mapping.
429Too many requestsBack off and retry after the limit resets.
5xxTemporary platform or provider errorRetry with backoff for safe operations and alert if failures persist.
For payment fulfillment, prefer webhook-driven state changes over repeated polling. Polling is useful for dashboard-style views and recovery jobs, but webhooks are the source of real-time completion signals.

Rate limits

When a request exceeds a limit, CoinVoyage returns 429 Too Many Requests. Back off instead of retrying immediately, and use the Retry-After response header when it is present. See Rate limits for retry guidance and response headers.

Pagination and listing

List endpoints return paginated data when the result set can grow over time. Use pagination for reconciliation jobs, dashboards, exports, and backfills instead of assuming a single response contains every record. When consuming paginated endpoints:
  • Keep the original filter set stable while walking pages.
  • Store the last successful cursor, page, or timestamp checkpoint for long-running jobs.
  • Expect new records to appear while you paginate.
  • Reconcile by PayOrder ID rather than by page position.
See the generated API Reference for the exact pagination parameters supported by each endpoint.

Idempotency and retries

Network requests can time out after CoinVoyage receives them. Design your integration so retrying does not create duplicate business effects:
  • Store your internal order ID in PayOrder metadata.
  • Before creating a replacement PayOrder, check whether your order already has an active PayOrder.
  • Treat webhook event IDs as delivery IDs and PayOrder IDs as payment lifecycle IDs.
  • Make fulfillment idempotent by recording the PayOrder ID and terminal status before shipping goods, crediting balances, or updating inventory.
For server retries, use exponential backoff with jitter. Retry read operations freely. Retry create or mutation operations only when your application can detect duplicates by metadata, PayOrder ID, or its own internal state.

Webhook-first processing

Production integrations should use webhooks for payment state changes:
  1. Create a PayOrder from your server.
  2. Store the PayOrder ID against your internal order or account.
  3. Show the payment modal to the user.
  4. Verify webhook signatures before parsing the event.
  5. Update internal state from terminal events such as payorder_completed, payorder_refunded, payorder_expired, or payorder_error.
  6. Run a scheduled reconciliation job that compares your internal state with the CoinVoyage API.
See Webhooks overview and Webhook events for delivery setup and payload examples.

Go-live requirements

Before using production credentials, confirm that:
  • Your API secret is stored server-side only.
  • Webhook signature verification is enabled.
  • Fulfillment is idempotent.
  • Failed, expired, refunded, and partial-payment states are handled.
  • Your settlement currency and wallet address are configured in the dashboard.
  • You have tested a full payment, refund, and webhook flow in the development environment.
Use the Production checklist before launch.