Skip to main content

Merchant API contract — v0 proposal

Status: Contract proposal, not implemented. All responses are illustrative. A published OpenAPI specification should be generated and reviewed before implementation.

Authentication and headers​

  • HTTPS only; scoped merchant API credentials with rotation and revocation.
  • Authorization: Bearer <token> (placeholder syntax; never commit actual credentials).
  • Idempotency-Key required for create, cancel and other financial mutations.
  • X-Request-Id accepted for traceability.
  • API returns stable machine-readable error codes and a server correlation ID.

Create a bill​

POST /v1/bills

{
"externalBillId": "INV-10042",
"merchantCustomerId": "cust_123",
"amountMinor": 12000,
"currency": "AUD",
"dueAt": "2026-11-20T23:59:00+11:00",
"description": "Monthly service",
"metadata": {"plan": "standard"}
}

Expected: 202 Accepted or 201 Created after durable validation; response includes internal bill ID, status, version and request ID. A repeated idempotency key with identical payload returns the original response. Same key with different payload returns a conflict.

Read a bill​

GET /v1/bills/{billId} returns bill state plus separate collection and payout status, if present. Avoid leaking consumer payment-method details to merchants.

Cancel a bill​

POST /v1/bills/{billId}/cancel requires a reason and idempotency key. Cancellation is not guaranteed once a provider attempt is in flight; return a pending/exception state rather than falsely confirming cancellation.

Webhook example​

{
"id": "evt_123",
"type": "collection.succeeded",
"schemaVersion": "2026-10-01",
"occurredAt": "2026-11-18T03:12:00Z",
"merchantId": "merch_123",
"data": {
"billId": "bill_123",
"externalBillId": "INV-10042",
"collectionId": "col_123",
"amountMinor": 12000,
"currency": "AUD"
}
}

Sign payloads with a rotating secret and timestamp; verify raw body, signature and freshness. Retries may arrive out of order. Provide webhook replay and a dead-letter recovery process.

Error categories​

INVALID_REQUEST, UNAUTHENTICATED, FORBIDDEN, MANDATE_INACTIVE, BILL_CONFLICT, IDEMPOTENCY_CONFLICT, RATE_LIMITED, TEMPORARILY_UNAVAILABLE, PROVIDER_OUTCOME_UNKNOWN. Financial ambiguity must not be presented as a definite failure.