F
FromChain
API Reference

Invoices API

Create and manage payment invoices. Each invoice gets a unique deposit address for receiving USDT payments.

Create Invoice

POST/v1/invoices

Create a new payment invoice with a unique deposit address

Request

create-invoice.js
const response = await fetch('https://api.fromchain.io/v1/invoices', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer gw_live_your_api_key_here',
    'Content-Type': 'application/json',
    'Idempotency-Key': 'order_12345_payment'
  },
  body: JSON.stringify({
    amountExpected: '100.50',
    externalId: 'order_12345',
    description: 'Payment for Order #12345',
    expiresInMinutes: 30,
    metadata: {
      customerId: 'user_789',
      orderId: 'order_12345',
      plan: 'premium'
    }
  })
});

const invoice = await response.json();

Response

create-invoice-response.json
{
  "id": "inv_abc123",
  "externalId": "order_12345",
  "chain": "BSC",
  "token": "USDT",
  "depositAddress": "0x1234567890123456789012345678901234567890",
  "amountExpected": "100.50",
  "amountReceived": "0",
  "status": "PENDING",
  "confirmationsRequired": 5,
  "expiresAt": "2025-12-18T11:30:00.000Z",
  "description": "Payment for Order #12345",
  "metadata": {
    "customerId": "user_789",
    "orderId": "order_12345",
    "plan": "premium"
  },
  "createdAt": "2025-12-18T11:00:00.000Z",
  "updatedAt": "2025-12-18T11:00:00.000Z"
}

💡 Idempotency: Use the Idempotency-Key header to safely retry requests without creating duplicates.

List Invoices

GET/v1/invoices

Retrieve a paginated list of invoices with optional filters

Query Parameters

?status=PENDING,CONFIRMED

Filter by status (comma-separated)

?page=1&pageSize=20

Pagination (default: page=1, pageSize=20)

?externalId=order_12345

Find by your external reference ID

list-invoices.js
const response = await fetch(
  'https://api.fromchain.io/v1/invoices?status=CONFIRMED&page=1&pageSize=10',
  {
    headers: {
      'Authorization': 'Bearer gw_live_your_api_key_here'
    }
  }
);

const data = await response.json();
console.log(data);
// {
//   "items": [...],
//   "pagination": {
//     "total": 42,
//     "page": 1,
//     "pageSize": 10,
//     "totalPages": 5
//   }
// }

Get Single Invoice

GET/v1/invoices/:id

Retrieve detailed information about a specific invoice

get-invoice-response.json
{
  "id": "inv_abc123",
  "externalId": "order_12345",
  "chain": "BSC",
  "token": "USDT",
  "depositAddress": "0x1234567890123456789012345678901234567890",
  "amountExpected": "100.50",
  "amountReceived": "100.50",
  "status": "PAID_OUT",
  "confirmationsRequired": 5,
  "detectedBlockNumber": "45678901",
  "confirmedAt": "2025-12-18T11:15:00.000Z",
  "paidOutAt": "2025-12-18T11:20:00.000Z",
  "expiresAt": "2025-12-18T11:30:00.000Z",
  "description": "Payment for Order #12345",
  "metadata": {
    "customerId": "user_789",
    "orderId": "order_12345"
  },
  "transfers": [
    {
      "txHash": "0xabc...",
      "amount": "100.50",
      "confirmed": true
    }
  ],
  "payout": {
    "status": "COMPLETED",
    "feeTxHash": "0xfee...",
    "custodyTxHash": "0xcustody..."
  },
  "createdAt": "2025-12-18T11:00:00.000Z",
  "updatedAt": "2025-12-18T11:20:00.000Z"
}

Invoice Lifecycle & Statuses

An invoice goes through several states from creation to completion:

PENDING

Waiting for payment. Customer should send funds to the deposit address.

PAID_DETECTED

Exact payment detected, waiting for blockchain confirmations (0 of 5 confirmations).

PARTIALLY_PAID

Received less than expected amount. Customer needs to send the difference.

OVERPAID

Received more than expected. The extra amount will be included in the payout.

CONFIRMED

Payment confirmed with required blockchain confirmations (5 blocks on BSC).

PROCESSING_PAYOUT

Funds are being swept and split between fee wallet and custody wallet.

PAID_OUT

✅ Complete! Funds successfully transferred to fee and custody wallets.

EXPIRED

No payment received within the expiration window (default 30 minutes).

LATE_PAYMENT

Payment received after expiration. Will still be processed.

FAILED

Payout failed due to an error. Manual intervention may be required.

Best Practices

Use Idempotency Keys

Always include an Idempotency-Key header when creating invoices to prevent duplicates on retries.

fetch('https://api.fromchain.io/v1/invoices', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer gw_live_...',
    'Idempotency-Key': 'order_12345_payment', // ← Important!
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ ... })
})

Use Webhooks for Real-Time Updates

Don't poll the API repeatedly. Instead, configure webhooks to receive real-time notifications when invoice status changes.

Handle All Statuses

Your integration should handle all possible invoice statuses, including PARTIALLY_PAID, OVERPAID, and LATE_PAYMENT edge cases.

Store External IDs

Use the externalId field to link invoices to your internal order/transaction IDs for easy reconciliation.