Help centerIntegrations

Create and publish invoices with a hub key

Create an invoice on a case, add its line items, publish it to the client, and mark it paid, void or another status from your billing system.

In this article8 sections

This page covers creating, publishing and updating a case's invoices with a hub key. Paths are under https://prd-api-app.caseactive.com/v1/<hub id>/<case id>.

Calls

CallWhat it does
POST /invoicesCreates an invoice, unpublished
PUT /invoices/<invoice_id>/transactionsSets its line items, tax and discount
PUT /invoices/<invoice_id>Changes it, before publishing
DELETE /invoices/<invoice_id>Deletes it, before publishing
PUT /invoices/<invoice_id>/publishPublishes it, which sends it to its recipients
PUT /invoices/<invoice_id>/statusMarks it paid, void, processing, uncollectible or open
GET /invoices?filter=allLists the case's invoices
GET /invoices/<invoice_id>Reads one invoice

An invoice goes out in three steps: create it, add its lines, then publish it. Until it's published, its recipients don't see it and nobody is told. Once it's published, only its status can change.

Creating an invoice

FieldWhat it doesRequiredDefault
nameThe invoice's title. Letters, numbers, spaces and & ' - _ ( ) . /; no commas, colons or #.Yes—
duration{"due_date": "2026-10-15T17:00:00-04:00"}, with its time zone offset. Invoices don't repeat: a repeat rule is refused.Yes—
statusAlways "open"Yes—
participants_idsWho it's billed to: user IDs of people on the case, from GET /teamNo, but needed to publishNobody
descriptionWhat it's forNoNone
invoice_number, po_numberYour invoice and purchase order numbers, in letters, numbers and dashesNoNone
host_ref_idYour system's reference for it, in letters, numbers and dashes. No two invoices in your hub can share one, and it can't be changed once set.NoNone
terms, notesPayment terms and a note, shown on the invoiceNoNone
notificationsReminders: {"names": ["days", "hours"], "values": [-1440, -60]}, each value in minutes before the due dateNoNone
instant_notifyfalse to send no request at publishing, only the remindersNotrue
curl -X POST https://prd-api-app.caseactive.com/v1/ca-7e6d5c4b3a2f10/cc-1a2b3c4d5e6f70/invoices \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "September legal services", "duration": {"due_date": "2026-10-15T17:00:00-04:00"}, "status": "open", "participants_ids": ["cu-4f1c2a9e8b7d60"], "invoice_number": "INV-1042", "host_ref_id": "acct-1042", "terms": "Net 15"}'

It answers 201 with the invoice_id, such as invoice::20261002143000_ab12cd34ef5678. Use it in paths as it is.

Line items

PUT /invoices/<invoice_id>/transactions sets every line, the tax and the discount at once:

{
  "transactions": {
    "transactions": [
      {"transaction_type": "charge", "description": "Consultation (hours)", "value": 35000, "quantity": 2},
      {"transaction_type": "charge", "description": "Court filing fee", "value": 30000}
    ],
    "discount": 0.1,
    "tax": 0.07
  }
}
FieldWhat it doesRequiredDefault
transaction_typecharge, or credit to take an amount offYes—
descriptionWhat the line is forYes—
valueThe price of one, in whole cents: 35000 is $350.00Yes—
quantityHow many, a whole number from 1No1
currencyusd, the only currencyNousd
discount, taxRates between 0 and 1: 0.1 is 10%No0
  • Each call replaces all the lines and both rates. A rate you leave out goes back to 0.
  • The subtotal is the charges less the credits, never below 0. The discount comes off the subtotal, then the tax is added to what's left. Every amount is rounded to whole cents.
  • The lines above make a subtotal of $1,000.00, a discount of $100.00, tax of $63.00 and a total of $963.00.

Changing or deleting it before publishing

PUT /invoices/<invoice_id> takes the same fields as creating it, but status, and changes only the ones you send. Send "" to clear description, invoice_number, po_number, terms or notes, and {} to clear notifications. DELETE /invoices/<invoice_id> deletes it. Neither works once it's published: void it instead.

Publishing

PUT /invoices/<invoice_id>/publish takes no body and answers 200.

  • Each recipient is emailed a request to pay with a link to the invoice, or texted if they have no confirmed email, at once, unless instant_notify is false. It appears on their To DoTo Do The list on a case of things waiting for you, such as forms to fill in, documents to sign or events to confirm. and in their portal notifications.
  • Reminders go out at each time in notifications still ahead. Nothing is sent at the due date, and the invoice can still be paid after it.
  • The staff on the case are copied on the request and its reminders.

Your hub doesn't need Stripe to publish. To be paid online, it must be connected and switched on, and the total must be $1.00 or more; otherwise the client can view the invoice but not pay it online. See Connect Stripe to collect invoice payments.

Status

PUT /invoices/<invoice_id>/status takes status and, optionally, status_reason, a note kept with it.

statusAllowed fromWhat it does
paidopen, processing, uncollectibleMarks it paid by hand. Final. The client gets no receipt.
voidopen, processing, uncollectibleCancels it. Final.
processingopen, uncollectibleA payment is on its way: reminders stop and it leaves the client's To Do, but it can still be paid
uncollectibleopen, processingNot expected to be paid: as processing
openprocessing, uncollectibleBack on the client's To Do. If it isn't due yet they're asked for it again at once, unless instant_notify is false, and reminders still ahead go out

When it's paid, online or by hand, or voided, the staff on the case are told, and completed_on is set. An invoice paid online reads paid with payment_gateway stripe; one marked paid here reads manual.

A key can't pay an invoice, or refund one. Refunds are made in the Admin Panel; see Refund a paid invoice.

Reading invoices

GET /invoices needs filter: all lists every invoice on the case, unpublished ones included, newest first, and self those the Virtual Assistant created. paid and unpaid list the caller's own, so they're always empty for a key. limit (default 20) and start_key page as every list does.

Each invoice holds:

FieldWhat it holds
invoice_id, name, descriptionIts ID, title and description
participants_idsWho it's billed to
status, status_reasonopen, paid, void, processing or uncollectible, and the note sent with it
published1 once published
due_date, completed_onWhen it's due, and when it was paid or voided
subtotal, discount_amount, tax_amount, totalAmounts in whole cents
discount, taxThe rates, between 0 and 1
transactionsIts lines
payment_gateway, refundedHow it was paid, and any refund
invoice_number, po_number, host_ref_id, terms, notesYour numbers and notes

To read invoices across every case, use a manage key; see Read invoices with a manage key.

If a call is refused

StatusmessageWhy
400SchemaFieldsExceptionA field is missing or invalid, such as a status other than open, a value that isn't whole cents, a rate of 7 rather than 0.07, or a recipient who isn't on the case; errors names it
400ReferenceIdExistsExceptionAnother invoice in your hub has that host_ref_id; reason holds its invoice_id
403PublishAlreadyPublishedExceptionIt's already published, so it can't be published again, changed or deleted
403PublishTransactionsMissingExceptionIt has no line items
403Its own nameIts due date has passed or it has nobody to send it to, so it can't be published; or it can't take that status
403BotNotAllowedExceptionA key tried to pay it, or to record a payment attempt on it
403CaseClosedExceptionThe case is closed
404ItemNotFoundExceptionThe invoice doesn't exist

For the error body and the rest of the codes, see Handle API errors and status codes.

Related articles

Read invoices with a manage keyList your hub's published invoices and read one, with its amounts, payment and refund, for your own accounting or reporting.IntegrationsConnect Stripe to collect invoice paymentsSet up a Stripe account and switch on online payments so clients can pay your invoices online.Cases & intake · 15 minHandle API errors and status codesRead the error body, what 400, 401, 403, 404, 500 and 503 mean, and why an item your key can't see answers 404.Integrations