Skip to content
VestiarionDocs

API reference

Add an invoice

POST/api/v1/invoices

Adds a payable or a receivable, checked by the rules of the console's invoice form, and recorded in the ledger as create_invoice with via: "api" and the key's id. It is added as the key's issuer's: if the agent holds it, the issuer cannot approve it, unless they are the workspace's only approver.

The agent decides a payable as one typed in, with every guardrail and the workspace's limits, usually within a minute. The API never approves or pays. A counterpartyId the workspace does not hold, including another workspace's, answers 400.

Send a workspace API key with read and write access as Authorization: Bearer …. A read-only key gets 403.

Parameters

  • Idempotency-Keystringoptionalin: header

    Makes a retry safe: up to 255 printable ASCII characters, unique to the record being added, such as its id in your own system. A repeat with the same key and the same body within 24 hours gets the first answer back, with Idempotent-Replayed: true, and adds nothing. The same key with a different body answers 409.

Request body

Example
application/json
{
  "counterpartyId": "6b361405-cfda-4400-a286-364b561911ce",
  "amount": "0.10",
  "dueDate": "2026-10-03",
  "poReference": "PO-API-1",
  "goodsReceived": true
}
Fields
  • directionstring · optional

    payable, a bill the business pays, which is the default, or receivable, one it is owed.

    One ofpayablereceivable

  • counterpartyIdstring

    The counterparty's id, from GET /api/v1/counterparties or from the answer that added it.

  • amountstring | number

    What it bills, in currency, with at most 6 decimal places. A decimal string such as "1250.50" keeps it exact; a number is read the same way.

  • currencystring · optional

    USDC, the default, or EURC.

    One ofUSDCEURC

  • dueDatestring

    The day it is due, as YYYY-MM-DD.

  • memostring · optional

    What it is for, up to 280 characters.

  • poReferencestring · optional

    The purchase order it bills against, up to 100 characters.

  • goodsReceivedboolean · optional

    Whether what it bills for has arrived. Defaults to false. Without it, or without poReference, the agent asks for the missing detail instead of paying.

  • earlyPayDiscountobject · optional

    A discount for paying by deadline. The agent weighs it against what the cash would earn in the reserve until dueDate.

    2 fields in earlyPayDiscount
    • percentstring | number

      The percent off, greater than 0 and less than 100, with at most 2 decimal places.

    • deadlinestring

      The last day it applies, as YYYY-MM-DD, on or before dueDate.

Try it

Try it is off for operations that add records: run the sample with your own key.

Code samples

cURL
curl "https://www.vestiarion.xyz/api/v1/invoices" \
  -X POST \
  -H "Authorization: Bearer $VESTIARION_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: billing-inv-2026-0042" \
  -d '{"counterpartyId":"6b361405-cfda-4400-a286-364b561911ce","amount":"0.10","dueDate":"2026-10-03","poReference":"PO-API-1","goodsReceived":true}'

Response

Example
201 · application/json
{
  "data": {
    "id": "1f96fd0b-71de-41bf-b088-779655ea6df4",
    "direction": "payable",
    "status": "pending",
    "amount": 0.1,
    "currency": "USDC",
    "memo": null,
    "poReference": "PO-API-1",
    "goodsReceived": true,
    "dueDate": "2026-10-03T12:00:00+00:00",
    "scheduledFor": null,
    "earlyPayDiscount": null,
    "decidedAt": null,
    "settledAt": null,
    "escalatedAt": null,
    "agentReasoning": null,
    "txHash": null,
    "paidAmount": null,
    "counterparty": {
      "id": "6b361405-cfda-4400-a286-364b561911ce",
      "name": "API Test Vendor",
      "riskLevel": "clear"
    },
    "createdAt": "2026-10-03T10:16:16.374931+00:00"
  }
}
Fields
  • dataobject

    An invoice in the payable or receivable book, with the agent's reasoning.

    19 fields in data
    • idstring
    • directionstring

      One ofpayablereceivable

    • statusstring
    • amountnumber
    • currencystring

      USDC or EURC: what amount is in, and what a payable is paid in. A EURC payable is checked against the counterparty's USDC limit at a quoted rate.

    • memostring · nullable
    • poReferencestring · nullable
    • goodsReceivedboolean
    • dueDatestring
    • scheduledForstring · nullable

      ISO timestamp the agent has committed to pay this on, once scheduled; else null.

    • earlyPayDiscountobject · nullable

      The early-payment discount this invoice carries, if any: the percent off and the deadline's ISO timestamp.

      2 fields in earlyPayDiscount
      • percentnumber
      • deadlinestring
    • decidedAtstring · nullable
    • settledAtstring · nullable
    • escalatedAtstring · nullable
    • agentReasoningstring · nullable

      Why the agent ruled as it did, verbatim from the decision.

    • txHashstring · nullable

      An on-chain hash once the payment settled, else null: on Arc testnet, or for a payout from a Gateway balance the mint on the payee's chain.

    • paidAmountnumber · nullable

      What actually left once this invoice was paid; null otherwise, even while a submitted transfer already carries an amount.

    • counterpartyobject · nullable
      3 fields in counterparty
      • idstring
      • namestring
      • riskLevelstring
    • createdAtstring

Errors

StatusCodeWhen
400invalid_requestAn invalid limit or cursor, a filter value outside its allowed values, or a request body that does not validate. The message names the parameter or the field, and lists the accepted values.
401unauthorizedNo key, or a malformed, unknown or revoked one: "A valid API key is required."
403forbiddenThe key's scopes do not cover this route: "This key cannot do that." Or, on a write, the person who created the key can no longer add records: "This key's issuer can no longer add records in this workspace."
409conflictThe Idempotency-Key was already used for a different request, or the first request with it is still being handled.
429rate_limitedToo many requests; wait as long as Retry-After says before trying again.
500internalAn unexpected server error. Implementation details are not exposed.