Oxapher External API docs

A detailed guide for trusted systems that need to create customers, create paid invoices, read invoice responses, and send invoice messages in Oxapher.

Quick start

  1. Open Document Settings and create an External API credential.
  2. Copy the one-time API key and store it in your integration vault.
  3. Send the key as `Authorization: Bearer oxa_live_...`.
  4. Include an `Idempotency-Key` on every create or send request.
  5. Use HTTPS only in production.

What this API is for

Use the external API when another system already knows a customer or payment has happened and Oxapher should create the matching customer record, issue the invoice, post the payment, and return the number and print link.

This is the same business workflow the app uses internally. That means numbering, accounts posting, payment status, print/share generation, and delivery rules stay consistent.

What you can do

ActionEndpointScopeWhat you get back
Create or resolve a customer`POST /api/external/v1/customers``customers:write``customer`, `created`, and idempotent replay support
Create a paid invoice`POST /api/external/v1/invoices``invoices:write``invoice_id`, `invoice_number`, `print_url`, `payment_status`, and `delivery`
Read invoice details`GET /api/external/v1/invoices/{sales_document_id}``invoices:read`The normal invoice detail payload used by Oxapher
Send invoice by email or WhatsApp`POST /api/external/v1/invoices/{sales_document_id}/send``invoices:send``channel`, `status`, and `print_url`

Important rules

Authentication

Send the credential exactly as a bearer token in the request header:

If the credential does not include the required scope, Oxapher returns `403`.

Customer create: how to call it

`POST /api/external/v1/customers`

Use this when the upstream system already has the customer identity and you want Oxapher to create the matching customer, or return the existing one if `external_reference` is reused.

Important fields:

FieldRequiredNotes
`external_reference`NoStable upstream key that makes later calls resolve to the same Oxapher customer
`business`NoCompany name
`contact_name`NoPerson name
`mobile`NoPrimary mobile number
`email`NoEmail address
`country`NoDefaults to India in the app
`branch_id`NoUse when the customer belongs to a specific branch

If you send the same `external_reference` again, Oxapher resolves the same customer instead of creating a duplicate.

Customer response

FieldMeaning
`customer.customer_id`Oxapher customer id
`customer.business`Business name
`customer.contact_name`Contact person
`customer.mobile`Mobile number
`customer.email`Email address
`created``true` when a new customer was created, `false` when an existing customer was reused

Invoice create: how to call it

`POST /api/external/v1/invoices`

The invoice payload can either embed a `customer` object or send `customer_id` if the customer already exists.

You can create these invoice types:

Important invoice fields:

FieldRequiredNotes
`invoice_type`YesControls the invoice variant
`customer` or `customer_id`Yes for all except `cash_memo` / `pos`Embed a customer object or reference an existing one
`invoice.lines`YesEach line should include item, quantity, and rate data the app accepts
`paid`NoDefaults to paid for invoice creation through this API
`payment`NoPayment mode details used when the invoice is posted and paid
`deduct_stock`NoSet to `false` if you do not want stock to move
`send`NoOptional delivery instructions for email and WhatsApp

The create call does more than save a draft. It posts the invoice, records the payment when `paid` is true, and returns the print link the same way the app would.

Invoice response

FieldMeaning
`invoice_id`Oxapher sales document id
`sales_document_id`Same value as `invoice_id`
`invoice_number`Human-readable invoice number
`document_number`Same value as `invoice_number`
`invoice_type`The requested invoice variant
`status`Current invoice status
`payment_status`Current payment status
`grand_total`Final invoice amount
`customer_created`Whether the customer was created during this call
`account_voucher_id`Linked Accounts voucher id when posting created one
`print_url`Public share/print link for the invoice
`delivery`Email or WhatsApp delivery results when `send` was supplied

Read invoice details

`GET /api/external/v1/invoices/{sales_document_id}`

Use this when a caller already has the Oxapher invoice id and wants the current document data, status, totals, party details, and approval context.

The response is the standard Oxapher sales-document payload for that invoice. It includes the invoice identity, party details, line items, amounts, status, and any linked approval or accounting context.

Send invoice

`POST /api/external/v1/invoices/{sales_document_id}/send`

Use this when the invoice already exists and you want to trigger delivery after the fact.

ChannelNotes
`email`Sends to the invoice email recipient or the address you provide
`whatsapp`Sends to the invoice WhatsApp recipient or the mobile number you provide
`link`Returns a fresh print/share link

You can also send delivery instructions inside the invoice create call through `send`.

Trial call

There is no separate sandbox endpoint in the current API. The safest first test is a live call with a test customer and one invoice line.

Recommended trial flow:

  1. Create or resolve a customer with `external_reference` like `checkout-customer-42`.
  2. Create a single-line `retail_invoice` or `tax_invoice`.
  3. Keep `paid: true`.
  4. Set a unique `Idempotency-Key`.
  5. Save the returned `invoice_number`, `invoice_id`, and `print_url`.

If the same request runs again with the same idempotency key, Oxapher returns the same result instead of creating a duplicate.

Trial request and expected response

Use these tables as a copy checklist before wiring code:

Customer trial callValue
Method`POST`
URL`/api/external/v1/customers`
Required headers`Authorization`, `Content-Type`, `Idempotency-Key`
Minimum body`external_reference`, plus at least one of `business`, `contact_name`, `mobile`, or `email`
Success response`customer.customer_id` and `created`
Invoice trial callValue
Method`POST`
URL`/api/external/v1/invoices`
Required headers`Authorization`, `Content-Type`, `Idempotency-Key`
Minimum body`invoice_type`, `customer` or `customer_id`, and `invoice.lines`
Default payment behavior`paid` is true unless you explicitly send false
Success response`invoice_id`, `invoice_number`, `payment_status`, `grand_total`, `print_url`, and optional `delivery`
Common response fieldDeveloper use
`invoice_id`Store this id for later read/send calls
`invoice_number`Show this number to the customer or upstream system
`payment_status`Confirm whether the invoice was posted as paid
`print_url`Open this URL to print or share the invoice
`delivery.status`Check whether email or WhatsApp sending was triggered

Error handling

StatusMeaning
`400`Missing or invalid fields
`401`Missing or invalid bearer token
`403`Credential does not have the needed scope
`404`Invoice or customer could not be found
`409`The idempotency key was reused incorrectly or a request is still processing
`429`Rate limit reached

Example customer payload

Use this shape when a checkout or ERP companion app creates a customer first:

FieldExample
`external_reference``stripe-cus_1024`
`business``Example Stores`
`contact_name``Asha Patel`
`mobile``9876543210`
`email``accounts@example.test`
`country``India`

Example invoice payload

This is the simple billing pattern:

FieldExample
`invoice_type``retail_invoice`
`customer.external_reference``stripe-cus_1024`
`paid``true`
`payment.mode``cash`
`invoice.lines[0].item_id``API-SERVICE-1`
`invoice.lines[0].quantity``1`
`invoice.lines[0].unit_rate``500`
`invoice.lines[0].gst_rate``0`
`invoice.billing_address``12 Test Road, Ahmedabad, Gujarat, 380015, India`
`invoice.shipping_address``12 Test Road, Ahmedabad, Gujarat, 380015, India`
`send.email.recipient``buyer@example.test`
`send.whatsapp.recipient``9876543210`

Related pages