Platform Invoices Guide

The Platform Invoice API lets you create, manage, and send invoices on behalf of businesses that have granted your platform access. Invoices are sent to recipients via email and can be paid through the Oncade payment flow.

Required scopes

invoice:create, invoice:read, invoice:update,invoice:send, invoice:cancel

All requests require the X-Target-Business-Id header and a grant from the target business.

Invoice lifecycle

Invoices move through a defined set of states. Understanding the lifecycle helps you integrate the correct API calls at the right time.

Loading diagram…
StatusMeaning
draftInvoice created but not yet delivered to the recipient. Not visible via the public invoice link.
sentInvoice delivered to the recipient via email. The recipient can now view and pay it.
processingAn ACH payment has been initiated and is awaiting settlement.
paidPayment received. Terminal state.
cancelledInvoice cancelled by the creator. Terminal state.
!

Draft invoices must be sent. When you create an invoice without setting status to "sent", it defaults to draft. Draft invoices are not visible to the recipient and no email is sent. You must explicitly send them via POST /v1/platform/invoices/{id}/send or create the invoice with "status": "sent" in the request body.

Creating invoices

Step 1: Create a draft invoice

Create an invoice in draft status to review it before delivering to the recipient. Omit the status field or set it to "draft".

curl -s -X POST \
  -H "Authorization: Bearer $PLATFORM_KEY" \
  -H "X-Target-Business-Id: $BIZ_ID" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "receiverName": "Acme Corp",
    "receiverEmail": "billing@acme.com",
    "date": "2026-04-12",
    "dueDate": "2026-05-12",
    "payToTarget": "BUSINESS",
    "items": [
      {
        "description": "Consulting — April 2026",
        "quantity": 1,
        "rate": 5000,
        "amount": 5000
      }
    ]
  }' \
  https://<host>/api/v1/platform/invoices

Required fields

FieldTypeDescription
receiverNamestringName of the invoice recipient
receiverEmailstringEmail address where the invoice will be delivered
datestringInvoice date (ISO 8601)
payToTargetstringBUSINESS — payment goes to the business payout wallet
itemsarrayAt least one line item with description, quantity, rate (dollars), amount (dollars)
i

Environment is derived from your API key. The invoice environment (test or live) is automatically determined by which API key you authenticate with. You do not need to pass environment in the request body. Currency defaults to USD and does not need to be specified.

Optional fields

FieldTypeDescription
invoiceNumberstringCustom invoice number. Auto-generated if omitted.
dueDatestringPayment due date (ISO 8601). Must be on or after date.
taxnumberTax amount in dollars. Added on top of the subtotal.
totalnumberExpected total for validation. Server rejects if it differs by more than $0.01.
notestringFree-text note displayed to the recipient.
metadataobjectArbitrary key-value data stored with the invoice.
statusstringSet to "sent" to create and immediately send. Defaults to "draft".
feesarrayPlatform fee line items (see Fees below).

Pay-to target

The payToTarget field determines where the invoice payment is routed.

i

Use BUSINESS for platform invoices. When creating invoices via the Platform API, payToTarget should be set to "BUSINESS". This routes payment to the business's configured payout wallet. The MY_ACCOUNT target is not supported for platform-created invoices.

The business must have a payout wallet configured before invoices can be created with the BUSINESS target. If the wallet is not set, the API returns a 400 error.

Step 2: Send the invoice

If you created the invoice as a draft, send it to the recipient with a separate call. This transitions the status to sent and triggers the delivery email.

curl -s -X POST \
  -H "Authorization: Bearer $PLATFORM_KEY" \
  -H "X-Target-Business-Id: $BIZ_ID" \
  https://<host>/api/v1/platform/invoices/$INVOICE_ID/send

Create and send in one step

To skip the draft phase, include "status": "sent" in the create request. The invoice is created and the email is sent immediately.

curl -s -X POST \
  -H "Authorization: Bearer $PLATFORM_KEY" \
  -H "X-Target-Business-Id: $BIZ_ID" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "receiverName": "Acme Corp",
    "receiverEmail": "billing@acme.com",
    "date": "2026-04-12",
    "payToTarget": "BUSINESS",
    "status": "sent",
    "items": [
      { "description": "Widget license", "quantity": 10, "rate": 25, "amount": 250 }
    ]
  }' \
  https://<host>/api/v1/platform/invoices

Invoice fees

Invoice fees work the same way as distribution fees. There are two categories applied on top of the invoice total:

Loading diagram…
TypeSourceWhen applied
Oncade service feeAuto-applied from the business's pricing configuration (or the global default)Always — cannot be opted out of
Platform feesPassed by your platform in the fees array at creation timeOnly when included in the request

The response includes a paymentSummary with the breakdown: invoiceAmount (the invoice total), payerFee (sum of all fees), and totalCharged (what the payer pays). Fees are charged to the payer, not the business.

Attaching platform fees

Pass a fees array in the create request. Each entry requires a recipientWallet — the wallet address that receives this fee payment.

curl -s -X POST \
  -H "Authorization: Bearer $PLATFORM_KEY" \
  -H "X-Target-Business-Id: $BIZ_ID" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "receiverName": "Acme Corp",
    "receiverEmail": "billing@acme.com",
    "date": "2026-04-12",
    "payToTarget": "BUSINESS",
    "items": [
      { "description": "Service agreement", "quantity": 1, "rate": 10000, "amount": 10000 }
    ],
    "fees": [
      {
        "label": "Platform Processing Fee",
        "percentage": 2.5,
        "flat": 50,
        "recipientWallet": "0xYourPlatformWallet"
      }
    ]
  }' \
  https://<host>/api/v1/platform/invoices
Fee fieldTypeDescription
labelstringDisplay name for this fee
percentagenumberPercentage of the invoice total (0–100). Defaults to 0.
flatnumberFlat fee in cents. Defaults to 0.
recipientWalletstringWallet address that receives this fee
!

Heads up: Fee amounts are calculated at creation time and stored on the invoice. The payer sees the full totalCharged (invoice amount + all fees) at payment time.

Managing invoices

Listing invoices

Retrieve invoices for a business with optional pagination and status filtering.

curl -s \
  -H "Authorization: Bearer $PLATFORM_KEY" \
  -H "X-Target-Business-Id: $BIZ_ID" \
  "https://<host>/api/v1/platform/invoices?page=1&limit=20&status=sent"

Supports page, limit (max 100), and status query parameters.

Getting a single invoice

curl -s \
  -H "Authorization: Bearer $PLATFORM_KEY" \
  -H "X-Target-Business-Id: $BIZ_ID" \
  https://<host>/api/v1/platform/invoices/$INVOICE_ID

Updating an invoice

Use PUT to update any non-terminal invoice (draft or sent). The full invoice body is required (this is a full replacement, not a partial update). Totals and payouts are recalculated server-side, but fee line items are determined at creation time and are not recalculated on update.

curl -s -X PUT \
  -H "Authorization: Bearer $PLATFORM_KEY" \
  -H "X-Target-Business-Id: $BIZ_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "receiverName": "Acme Corp",
    "receiverEmail": "billing@acme.com",
    "date": "2026-04-12",
    "payToTarget": "BUSINESS",
    "items": [
      { "description": "Consulting — April 2026", "quantity": 1, "rate": 7500, "amount": 7500 }
    ]
  }' \
  https://<host>/api/v1/platform/invoices/$INVOICE_ID
i

Terminal invoices cannot be modified. Once an invoice reaches paid or cancelled status, it cannot be updated.

Cancelling an invoice

Cancel a draft or sent invoice. Cancelled is a terminal state.

curl -s -X POST \
  -H "Authorization: Bearer $PLATFORM_KEY" \
  -H "X-Target-Business-Id: $BIZ_ID" \
  https://<host>/api/v1/platform/invoices/$INVOICE_ID/cancel

API Quick Reference

All invoice endpoints are under /v1/platform/invoices.

MethodPathScopePurpose
GET/invoicesinvoice:readList invoices (paginated, filterable by status)
POST/invoicesinvoice:createCreate invoice (draft or sent)
GET/invoices/{id}invoice:readGet invoice details
PUT/invoices/{id}invoice:updateUpdate a non-terminal invoice
POST/invoices/{id}/sendinvoice:sendSend a draft invoice (triggers email)
POST/invoices/{id}/cancelinvoice:cancelCancel a non-terminal invoice
GET/invoices/exportinvoice:readExport invoices as CSV

References