APIv3
Exit Documentation

Invoices

An invoice records billed products or services, taxes, payments, and the amount still due from a customer. API v3 can create, safely update, dispatch, cancel, and delete eligible invoices, retrieve existing invoices, record manual payments, and list payment history.


The invoice object

FieldTypeDescription
idstringUnique invoice UUID.
objectstringAlways invoice.
invoice_numberintegerAccount-assigned invoice number.
custom_invoice_numberstring or nullOptional custom invoice number.
namestring or nullInvoice name.
customer_idstringCustomer UUID.
customer_namestringCustomer display name stored with the invoice.
salesperson_idstringAssigned SalesBinder user UUID.
status_idintegerCurrent invoice status identifier.
statusstring or nullCurrent invoice status name.
issue_datestring or nullInvoice issue date in YYYY-MM-DD format.
expiry_datestring or nullStored invoice expiry date in YYYY-MM-DD format.
date_sentstring or nullDate sent in YYYY-MM-DD format.
date_fully_paidstring or nullDate fully paid in YYYY-MM-DD format.
purchase_order_numberstringCustomer purchase-order reference.
attentionstring or nullAttention line.
shipping_addressstring or nullShipping-address text stored on the invoice.
public_notestring or nullCustomer-facing invoice note.
payment_termsstring or nullPayment terms stored on the invoice.
subtotalstringSubtotal before shipping and taxes, as a four-decimal string.
shippingstringShipping charge as a four-decimal string.
taxstringPrimary tax amount as a four-decimal string.
tax_2stringSecondary tax amount as a four-decimal string.
totalstringInvoice total including shipping and taxes, as a four-decimal string.
amount_paidstringRecorded payments as a four-decimal string.
amount_duestringRemaining amount due as a four-decimal string.
shipped_percentinteger or nullPercentage shipped.
created_atstring or nullISO 8601 creation timestamp.
updated_atstring or nullISO 8601 modification timestamp.
linesarrayCurrent invoice line objects. Present only when retrieving one invoice.

Monetary values use the SalesBinder account's base currency. Cost and margin values are not included in invoice API responses.


The invoice line object

FieldTypeDescription
idstringUnique invoice-line UUID.
objectstringAlways invoice_line.
item_idstring or nullRelated inventory item UUID, when present.
namestring or nullLine-item name.
descriptionstring or nullLine-item description.
quantitynumberBilled quantity.
unit_idinteger or nullRelated unit identifier.
unit_pricestringOriginal unit price as a four-decimal string.
discount_percentstringDiscount percentage as a three-decimal string.
discounted_unit_pricestring or nullDiscounted unit price, or null when no discounted price is stored.
tax_ratestringPrimary tax percentage as a three-decimal string.
tax_2_ratestringSecondary tax percentage as a three-decimal string.
subtotalstringQuantity multiplied by the effective unit price, before tax, as a four-decimal string.

Line-item unit costs are intentionally omitted.


The payment object

FieldTypeDescription
idstringUnique payment or refund transaction UUID.
objectstringAlways payment.
invoice_idstringUUID of the related invoice.
amountstringSigned transaction amount as a four-decimal string. Refunds are negative.
typestringpayment for a non-negative amount or refund for a negative amount.
referencestring or nullManual or provider payment reference.
payment_datestring or nullTransaction date in YYYY-MM-DD format.
cardobject or nullLimited card summary when stored, otherwise null.
card.brandstring or nullCard brand when stored.
card.last4string or nullLast four card digits when stored.

The response includes only the payment fields listed above.


Create an invoice

POST/api/v3/invoices

Required scope: invoices:write

Creates an unpaid invoice assigned to the API key's current user. The response is the new invoice object with its calculated line items. Creating an invoice does not send it to the customer, record a payment, or mark anything as fulfilled.

Invoices can also be created from an existing open estimate through POST/api/v3/estimates/{estimate_id}/convert-to-invoice. That dedicated action preserves the estimate relationship and closes the estimate as part of the same operation.

Request fields

FieldTypeRequiredDescription
customer_idstringYesActive customer UUID in the current SalesBinder account.
linesarrayYesOne to 100 inventory or service line objects.
namestringNoOptional name for your own reference.
issue_datestringNoIssue date in YYYY-MM-DD format. Defaults using the account and user timezone.
custom_invoice_numberstringNoOptional custom reference, up to 24 characters.
purchase_order_numberstringNoCustomer purchase-order reference.
attentionstringNoAttention line.
shipping_addressstringNoShipping-address text.
public_notestringNoCustomer-facing note.
payment_termsstringNoPayment terms. Account defaults apply when omitted.
shippingnumberNoShipping charge. Defaults to 0.
discount_percentnumberNoInvoice-wide discount from 0 to 100.

Line fields

FieldTypeRequiredDescription
item_idstringInventory linesActive inventory item UUID. The API copies its name, description, cost, and permitted selling price.
item_variation_location_idintegerVariation itemsVariation-location identifier belonging to the selected item and account.
namestringService linesService line name. Ignored for inventory lines.
descriptionstringNoService line description. Inventory descriptions come from the item.
quantitynumberNoPositive quantity. Defaults to 1; unique items are always 1.
unit_pricenumberService linesRequired for service lines. Optional for inventory lines only when the current user may modify selling prices.
tax_ratenumberNoPrimary tax percentage from 0 to 100; defaults to the customer's rate.
tax_2_ratenumberNoSecondary tax percentage from 0 to 100; defaults to the customer's rate.

Invoice number, status, salesperson, account, source, totals, costs, payments, fulfillment state, and timestamps are controlled by SalesBinder. Supplying unsupported or protected fields returns 422 unsupported_invoice_field rather than silently accepting them.

Example request

bash
curl "https://yourbusiness.salesbinder.com/api/v3/invoices" \
  --request POST \
  --header "Authorization: Bearer YOUR_API_KEY" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: warehouse-invoice-1042" \
  --data '{
    "customer_id": "709d2a43-12a9-4d85-a9d9-cb16e66cef53",
    "issue_date": "2026-07-18",
    "shipping": 10,
    "discount_percent": 5,
    "lines": [
      {
        "item_id": "c420fb4b-e98e-4ed4-b2e9-7ad8cc970966",
        "quantity": 2
      },
      {
        "name": "Installation",
        "quantity": 1,
        "unit_price": 75,
        "tax_rate": 5
      }
    ]
  }'

The invoice and its number are saved together. A failed request does not consume an invoice number.


Update an invoice

PATCH/api/v3/invoices/{invoice_id}

Required scope: invoices:write

Updates supported fields on an unpaid invoice. Include only the top-level fields that should change. SalesBinder recalculates totals, taxes, discounts, inventory effects, and other protected values automatically.

The supported top-level fields are the same as invoice creation. customer_id may be changed only when a complete lines replacement is also supplied.

Replacing invoice lines

When lines is omitted, the current active lines are preserved. When lines is supplied, it is the complete replacement for all active non-discount lines:

  • Include an existing line's id to replace that line while preserving its identity.
  • Omit id to create a new line.
  • Any current active line omitted from the array is removed from the invoice.
  • Do not submit discount line IDs. Set the top-level discount_percent field to change or remove the invoice-wide discount.

Line IDs must belong to the invoice being updated. A deleted line, a line from another invoice, or a duplicated line ID is rejected.

Example request

bash
curl "https://yourbusiness.salesbinder.com/api/v3/invoices/c40e5d25-c573-48ec-aa46-9737eddf2513" \
  --request PATCH \
  --header "Authorization: Bearer YOUR_API_KEY" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: warehouse-invoice-1042-update-1" \
  --data '{
    "shipping": 12,
    "public_note": "Thank you for your business.",
    "discount_percent": 5,
    "lines": [
      {
        "id": "34ed0d15-8748-40b2-89d4-482466996234",
        "name": "Installation",
        "quantity": 2,
        "unit_price": 75,
        "tax_rate": 5
      },
      {
        "item_id": "c420fb4b-e98e-4ed4-b2e9-7ad8cc970966",
        "quantity": 1
      }
    ]
  }'

An Idempotency-Key is optional but recommended for update requests. SalesBinder temporarily replays the completed response for a quick retry with the same key and payload, while rejecting reuse of that key with different data.


List invoices

GET/api/v3/invoices

Required scope: invoices:read

Invoices linked to one sales order can also be listed through GET/api/v3/sales-orders/{sales_order_id}/invoices. That nested collection additionally requires sales_orders:read and applies both resources' visibility boundaries.

Returns visible active invoices ordered by invoice number, newest first. Line items are omitted from list responses.

Query parameters

ParameterTypeRequiredDescription
pageintegerNoPage number. Defaults to 1.
limitintegerNoRecords per page. Defaults to 20; maximum 100.
qstringNoSearches customer name, custom invoice number, and invoice name. A numeric value also matches an exact invoice number.
customer_idstringNoReturns invoices for the customer UUID.
status_idintegerNoReturns invoices with the status identifier.
issue_date_fromstringNoIncludes invoices issued on or after this YYYY-MM-DD date.
issue_date_tostringNoIncludes invoices issued on or before this YYYY-MM-DD date.

Example request

bash
curl "https://yourbusiness.salesbinder.com/api/v3/invoices?customer_id=709d2a43-12a9-4d85-a9d9-cb16e66cef53&limit=20" \
  --header "Authorization: Bearer YOUR_API_KEY"

Example response

json
{
  "object": "list",
  "url": "/api/v3/invoices",
  "has_more": false,
  "data": [
    {
      "id": "c40e5d25-c573-48ec-aa46-9737eddf2513",
      "object": "invoice",
      "invoice_number": 1042,
      "customer_id": "709d2a43-12a9-4d85-a9d9-cb16e66cef53",
      "customer_name": "Example Customer",
      "status_id": 9,
      "status": "Sent",
      "issue_date": "2026-07-18",
      "subtotal": "100.0000",
      "shipping": "10.0000",
      "tax": "5.5000",
      "tax_2": "2.2000",
      "total": "117.7000",
      "amount_paid": "50.0000",
      "amount_due": "67.7000"
    }
  ],
  "pagination": {
    "page": 1,
    "per_page": 20,
    "total_pages": 1,
    "total_records": 1
  }
}

Examples may omit unchanged fields for readability.


Retrieve an invoice

GET/api/v3/invoices/{invoice_id}

Required scope: invoices:read

Returns one visible active invoice. The response includes the lines array, ordered by the invoice's stored line order. Deleted lines are excluded.

Example request

bash
curl "https://yourbusiness.salesbinder.com/api/v3/invoices/c40e5d25-c573-48ec-aa46-9737eddf2513" \
  --header "Authorization: Bearer YOUR_API_KEY"

If the invoice is outside the current account or assigned-user boundary, is not an invoice, has been archived, or does not exist, the API returns 404 resource_missing.


Record an invoice payment

POST/api/v3/invoices/{invoice_id}/payments

Required scope: invoices:payments

Records a manual payment against one visible invoice and returns the created payment object with 201 Created. The API rechecks the invoice's current balance and prevents concurrent requests from applying against the same stale balance.

FieldTypeRequiredDescription
amountnumber or numeric stringYesPayment amount with up to four decimal places. Use a positive amount for an invoice balance or a negative amount when applying a credit note. The amount cannot exceed the remaining signed balance.
payment_datestringYesPayment date in YYYY-MM-DD format.
referencestringNoManual payment reference, up to 255 characters.

A zero payment is accepted only for a zero-balance invoice when the account has no active payment-provider connection or payment-sync subscription, matching the SalesBinder manual-payment workflow.

bash
curl "https://yourbusiness.salesbinder.com/api/v3/invoices/c40e5d25-c573-48ec-aa46-9737eddf2513/payments" \
  --request POST \
  --header "Authorization: Bearer YOUR_API_KEY" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: invoice-1042-payment-001" \
  --data '{
    "amount": "50.00",
    "payment_date": "2026-07-19",
    "reference": "Bank transfer 8472"
  }'
json
{
  "id": "2ce987a5-19a8-4bbe-ae2b-cff6da9fbfab",
  "object": "payment",
  "invoice_id": "c40e5d25-c573-48ec-aa46-9737eddf2513",
  "amount": "50.0000",
  "type": "payment",
  "reference": "Bank transfer 8472",
  "payment_date": "2026-07-19",
  "card": null
}

Use a unique Idempotency-Key for each intended payment. An identical retry during the short idempotency window returns the original 201 response with Idempotent-Replayed: true. Reusing the key with different request data returns 409 idempotency_key_reused. After the short window expires, the same request can create another payment when an eligible balance remains.

The endpoint records manual payments only. It does not charge a saved card, contact a payment provider, issue a refund against an earlier payment, or accept provider payment-method identifiers. Use the appropriate SalesBinder payment integration for provider-backed payments.

Payment access also requires the API key's user to retain the current invoice-list and apply-payments permissions. Account and assigned-user visibility are enforced before the write. A payment and the resulting invoice totals and status are committed together; if the invoice cannot be refreshed, no payment is retained.


Refund a manual payment

POST/api/v3/invoices/{invoice_id}/payments/{payment_id}/refunds

Required scope: invoices:refunds

Records a manual refund against one original manual payment and returns the linked refund object with 201 Created. The original payment remains in payment history, and the refund appears as a separate object with a negative amount and type set to refund.

FieldTypeRequiredDescription
amountnumber or numeric stringYesPositive refund amount with no more than two decimal places. It cannot exceed the original payment's remaining refundable amount.
refund_datestringYesRefund date in YYYY-MM-DD format.
referencestringNoManual refund reference, up to 255 characters.
bash
curl "https://yourbusiness.salesbinder.com/api/v3/invoices/c40e5d25-c573-48ec-aa46-9737eddf2513/payments/2ce987a5-19a8-4bbe-ae2b-cff6da9fbfab/refunds" \
  --request POST \
  --header "Authorization: Bearer YOUR_API_KEY" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: invoice-1042-refund-001" \
  --data '{
    "amount": "10.00",
    "refund_date": "2026-07-20",
    "reference": "Returned goods"
  }'
json
{
  "id": "fa81b6df-b21b-4546-a787-ea7d1089305d",
  "object": "payment",
  "invoice_id": "c40e5d25-c573-48ec-aa46-9737eddf2513",
  "amount": "-10.0000",
  "type": "refund",
  "reference": "Returned goods",
  "payment_date": "2026-07-20",
  "card": null
}

Each refund locks the invoice and original payment, then recalculates all linked refunds before saving. Concurrent requests therefore cannot both spend the same remaining refundable amount. The refund and resulting invoice totals and status are committed together.

Use a unique Idempotency-Key for each intended refund. An identical retry during the short idempotency window returns the original 201 response with Idempotent-Replayed: true instead of recording another refund.

This endpoint intentionally rejects provider-backed or card payments with 409 provider_refund_required. Refund those payments through the established SalesBinder payment integration so the external provider and local invoice remain coordinated. The API endpoint never calls a payment provider and never deletes or rewrites the original payment.

Refund access requires the current invoice-list and apply-payments permissions in addition to the dedicated API scope. The invoice and original payment must both belong to the current account, and the invoice must remain inside the user's assigned-invoice visibility boundary.


List invoice payments

GET/api/v3/invoices/{invoice_id}/payments

Required scope: invoices:read

Returns recorded payments and refunds for one visible invoice, ordered by payment date with the newest first. Positive amounts are payments and negative amounts are refunds.

ParameterTypeRequiredDescription
pageintegerNoPage number. Defaults to 1.
limitintegerNoRecords per page from 1 through 100. Defaults to 20.
bash
curl "https://yourbusiness.salesbinder.com/api/v3/invoices/c40e5d25-c573-48ec-aa46-9737eddf2513/payments?limit=20" \
  -H "Authorization: Bearer sb_live_your_api_key" \
  -H "Accept: application/json"
json
{
  "object": "list",
  "url": "/api/v3/invoices/c40e5d25-c573-48ec-aa46-9737eddf2513/payments",
  "has_more": false,
  "data": [
    {
      "id": "2ce987a5-19a8-4bbe-ae2b-cff6da9fbfab",
      "object": "payment",
      "invoice_id": "c40e5d25-c573-48ec-aa46-9737eddf2513",
      "amount": "50.0000",
      "type": "payment",
      "reference": "Card payment",
      "payment_date": "2026-07-18",
      "card": {
        "brand": "visa",
        "last4": "4242"
      }
    },
    {
      "id": "fa81b6df-b21b-4546-a787-ea7d1089305d",
      "object": "payment",
      "invoice_id": "c40e5d25-c573-48ec-aa46-9737eddf2513",
      "amount": "-10.0000",
      "type": "refund",
      "reference": "Partial refund",
      "payment_date": "2026-07-19",
      "card": null
    }
  ],
  "pagination": {
    "page": 1,
    "per_page": 20,
    "total_pages": 1,
    "total_records": 2
  }
}

The response includes only the payment fields documented above.

Payment history follows the invoice's account and assigned-user visibility. It does not require payment-application permission because this endpoint cannot create, change, refund, or delete a payment.


Dispatch an invoice

POST/api/v3/invoices/{invoice_id}/dispatch

Required scope: invoices:dispatch

Marks an active invoice as dispatched by setting its date_sent. This action does not email the invoice or contact the customer. It requires the current user's invoice-modify permission and accepts unpaid, partially paid, and paid-in-full invoices.

The optional date_sent field must use YYYY-MM-DD format. When omitted, SalesBinder uses the current date in the account and user's configured timezone. If the invoice already has a dispatch date, the original date is preserved so repeating the action is safe.

Example request

bash
curl "https://yourbusiness.salesbinder.com/api/v3/invoices/c40e5d25-c573-48ec-aa46-9737eddf2513/dispatch" \
  --request POST \
  --header "Authorization: Bearer YOUR_API_KEY" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: dispatch-invoice-c40e5d25" \
  --data '{
    "date_sent": "2026-07-20"
  }'

Example response

json
{
  "id": "c40e5d25-c573-48ec-aa46-9737eddf2513",
  "object": "invoice",
  "invoice_number": 1002,
  "status_id": 9,
  "status": "Unpaid",
  "date_sent": "2026-07-20",
  "amount_paid": "0.0000",
  "amount_due": "125.0000",
  "lines": [
    {
      "id": "4fe2627c-6bb7-480c-9f46-b4558416f82c",
      "object": "invoice_line",
      "item_id": "4bb16375-9674-4e38-bab0-bcb15b97b76d",
      "name": "Example Widget",
      "quantity": "1.0000"
    }
  ]
}

The response is the complete invoice detail object. A cancelled invoice returns 409 invoice_dispatch_not_allowed. Send an Idempotency-Key to replay the original response for quick network retries; this is separate from the repeat-safe preservation of the first dispatch date.


Cancel an invoice

POST/api/v3/invoices/{invoice_id}/cancel

Required scope: invoices:cancel

Cancels an unpaid invoice without deleting its financial record or line items. The invoice must have no payment transactions, packing lists, shipping shipments, shipped quantity, or drop-shipping activity. Cancellation also requires the current user's invoice-modify permission.

If the invoice was created from a sales order, cancellation removes that invoice association and refreshes the sales order's invoiced quantities. This differs from invoice deletion, which refuses to remove an associated invoice.

The request body must be an empty JSON object. Arbitrary status or invoice fields are rejected.

Example request

bash
curl "https://yourbusiness.salesbinder.com/api/v3/invoices/c40e5d25-c573-48ec-aa46-9737eddf2513/cancel" \
  --request POST \
  --header "Authorization: Bearer YOUR_API_KEY" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: cancel-invoice-c40e5d25" \
  --data '{}'

Example response

json
{
  "id": "c40e5d25-c573-48ec-aa46-9737eddf2513",
  "object": "invoice",
  "invoice_number": 1002,
  "status_id": 15,
  "status": "Cancelled",
  "amount_paid": "0.0000",
  "amount_due": "125.0000",
  "lines": [
    {
      "id": "4fe2627c-6bb7-480c-9f46-b4558416f82c",
      "object": "invoice_line",
      "item_id": "4bb16375-9674-4e38-bab0-bcb15b97b76d",
      "name": "Example Widget",
      "quantity": "1.0000"
    }
  ]
}

The response uses the complete invoice detail object with status 15. Repeating the action for an already-cancelled invoice returns its current cancelled representation. Send an Idempotency-Key to replay the original response for quick network retries.

Cancellation and sales-order unlinking are completed together. Inventory totals and unique-item sold status may update shortly after the response. SalesBinder returns 409 invoice_cancel_not_allowed when payment or fulfillment activity makes cancellation unsafe.


Delete an invoice

DELETE/api/v3/invoices/{invoice_id}

Required scope: invoices:delete

Deletes an eligible unpaid invoice and its lines. Deletion is limited to invoices with:

  • no applied payments or transaction records;
  • no sales-order or other document association;
  • no packing list or shipping shipment;
  • no shipped quantity; and
  • no drop-shipping activity.

SalesBinder returns 409 invoice_delete_not_allowed when the invoice exists within the key's visibility boundary but does not meet every deletion condition. Deleting an invoice never deletes related payments, sales orders, packing lists, or shipments.

Example request

bash
curl "https://yourbusiness.salesbinder.com/api/v3/invoices/c40e5d25-c573-48ec-aa46-9737eddf2513" \
  --request DELETE \
  --header "Authorization: Bearer YOUR_API_KEY"

Example response

json
{
  "id": "c40e5d25-c573-48ec-aa46-9737eddf2513",
  "object": "invoice",
  "deleted": true
}

The invoice and its lines are deleted together. For inventory lines, on-hand quantities may update shortly after the response. Service-only invoices do not change inventory.


Permissions and write behavior

API key scopes can reduce access but cannot exceed the current user's SalesBinder permissions. The user must currently be able to list invoices. Without the current view-all-invoices permission, list and retrieve operations are limited to invoices assigned to that user.

Creating, updating, dispatching, or cancelling an invoice also requires the current invoice-modify permission. Deletion requires the current invoice-delete permission. If that permission is not configured, SalesBinder may use the invoice-modify permission; an explicit denial is always respected. Inventory selling-price overrides require the current modify-selling-prices permission, and location-limited users can only select inventory in their permitted location.

Updating is limited to the explicitly documented fields on eligible unpaid invoices. Dispatch, manual payments, manual refunds, and cancellation use dedicated endpoints and independent scopes; they cannot email a customer, charge saved cards, or issue provider refunds. Deletion is limited to unpaid invoices without payment, document associations, packing, shipping, or drop-shipping activity. API v3 does not support invoice email delivery, archiving, restoring, setting an arbitrary status, or changing fulfillment state. Unsupported fields and actions are rejected.