Consultainer Docs

Endpoints

Invoices

List invoices, generate a draft or bill a set amount, and record payments

List invoices

GET /api/v1/invoices

Any role. Returns the organization's invoices, newest first, each with its client ({ id, name }). Owner and admin keys get every invoice. A member's key doesn't get invoices with a line on a confidential project the member isn't on.

statusstringquery

Only DRAFT, SENT, PAID, or VOID invoices. Any other value is ignored. A VOID invoice keeps its lines and total, but the time entries, milestones and expenses on it were released when it was voided and can be generated onto a new invoice.

curl "https://<your-instance>/api/v1/invoices?status=SENT" \
  -H "Authorization: Bearer ch_live_..."
{
  "invoices": [
    {
      "id": "cm9...",
      "number": "INV-0042",
      "status": "SENT",
      "issueDate": "2026-08-01T00:00:00.000Z",
      "dueDate": "2026-08-31T00:00:00.000Z",
      "paymentTerms": "NET30",
      "subtotal": "5250",
      "taxAmount": "0",
      "total": "5250",
      "currency": "USD",
      "kind": "STANDARD",
      "amountPaid": "2000.00",
      "creditApplied": "0.00",
      "balanceDue": "3250.00",
      "paidAt": null,
      "firstViewedAt": "2026-08-02T16:40:12.000Z",
      "viewCount": 3,
      "client": { "id": "cm9...", "name": "Fintra Labs" },
      "...": "..."
    }
  ]
}

amountPaid is the sum of the payments recorded on the invoice and creditApplied the client credit applied to it; balanceDue is total minus both (never below 0.00, and 0.00 for a VOID invoice). A partly paid invoice stays SENT until balanceDue reaches 0.00. kind is STANDARD, or DEPOSIT for a deposit invoice. paidAt is when the invoice became paid in full (by hand, or when an online payment went through), or null. firstViewedAt, lastViewedAt and viewCount track when the client opened the invoice. To find overdue invoices, look for SENT invoices whose dueDate has passed (the MCP list_invoices tool returns isOverdue and daysOverdue for you).

Generate an invoice

POST /api/v1/invoices/generate

Owner/admin only. Creates a draft from unbilled time entries, completed milestones, and/or approved expenses, the same as Generate invoice in the app. Returns 201 with { "invoice": { ... } }, including its id, number and computed subtotal, taxAmount and total. Review and send the draft in the app, or with the MCP email_invoice or mark_invoice_sent tools.

clientIdstringrequired
timeEntryIdsstring[]

Billable time entries not yet on an invoice, on this client's projects. If your organization requires timesheet approval, the time must be approved.

milestoneIdsstring[]

Completed milestones not yet on an invoice.

expenseIdsstring[]

Approved expenses not yet on an invoice.

issueDatestringrequired

YYYY-MM-DD.

dueDatestring

YYYY-MM-DD. Defaults to issueDate plus the payment terms. Required when paymentTerms is CUSTOM.

paymentTermsstring

DUE_ON_RECEIPT, NET15, NET30, NET45, NET60, NET90, or CUSTOM. Defaults to the project's terms when every item is from one project that sets them, otherwise the client's, otherwise the organization's default.

poNumberstring
Up to 100 characters.
taxRatenumberdefault: 0

Percent, 0 to 100.

notesstring
Up to 2,000 characters.

At least one of timeEntryIds, milestoneIds, or expenseIds is required. IDs that don't qualify (already invoiced, not billable, on another client's project, and so on) are skipped. The invoice uses the organization's default currency.

curl -X POST https://<your-instance>/api/v1/invoices/generate \
  -H "Authorization: Bearer ch_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "clientId": "cm9...",
    "timeEntryIds": ["cm9...", "cm9..."],
    "issueDate": "2026-08-01",
    "paymentTerms": "NET30"
  }'

Errors

StatusMessageFix
403Only owners and admins can generate invoices.Use an owner or admin key.
422{ "timeEntryIds": ["Select at least one time entry, milestone, or expense"] }Send at least one ID.
422Client not found.Check clientId.
422No eligible unbilled time entries, milestones, or expenses were selected.None of the IDs qualified. Check they're on this client's projects, billable, approved, and not already invoiced.
422Custom payment terms need a due date.Send dueDate with CUSTOM terms.

Bill a set amount

POST /api/v1/invoices/custom

Owner/admin only. Creates a draft for amounts you name rather than logged work: a set fee, a retainer or a deposit, the same as Set amount in the app. Nothing is marked billed. Returns 201 with { "invoice": { ... } }.

clientIdstringrequired
linesobject[]required

1 to 100 lines, each { "description": string, "amount": number }. The amount is to the cent and greater than zero.

depositbooleandefault: false

A deposit invoice: untaxed, and its payments become client credit.

projectIdstring

One of the client's projects. Its payment terms are the default, and a confidential project's invoice is hidden like its others.

issueDatestringrequired
YYYY-MM-DD.
dueDatestring

YYYY-MM-DD. Defaults to issueDate plus the payment terms.

paymentTermsstring

As for generate. Defaults to the project's terms, else the client's, else the organization's.

poNumberstring
Up to 100 characters.
taxRatenumberdefault: 0

Percent, 0 to 100. Ignored for a deposit.

notesstring
Up to 2,000 characters, shown on the invoice.
curl -X POST https://<your-instance>/api/v1/invoices/custom \
  -H "Authorization: Bearer ch_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "clientId": "cm9...",
    "lines": [{ "description": "Initial deposit", "amount": 500 }],
    "deposit": true,
    "issueDate": "2026-10-19",
    "paymentTerms": "DUE_ON_RECEIPT"
  }'

Errors

StatusMessageFix
403Only owners and admins can create invoices.Use an owner or admin key.
422{ "lines": [...] }Send at least one line with a description and a positive amount.
422Client not found.Check clientId.
422Project not found for this client.Use one of the client's projects, or leave projectId out.
422Custom payment terms need a due date.Send dueDate with CUSTOM terms.

List an invoice's payments

GET /api/v1/invoices/{id}/payments

Any role that can see the invoice. Returns its amountPaid, creditApplied and balanceDue, plus:

  • payments: each with amount, currency, receivedAt, source (MANUAL, STRIPE, MERCURY or QUICKBOOKS), method, reference, note and recordedBy (a name, or null for payments recorded by an integration), newest first.
  • creditApplications: client credit applied to the invoice.
  • creditNotes: credit notes issued against it.

Returns 404 with Invoice not found. for an invoice in another organization or one the key can't see.

Record a payment

POST /api/v1/invoices/{id}/payments

Owner/admin only. Records money received against a sent invoice, the same as Record payment in the app. The invoice becomes PAID when its balance reaches zero (with the invoice paid alert); a part payment leaves it SENT and sends the part payment received alert. Returns 201 with { "payment": { ... }, "invoice": { ... } }; invoice includes the new amountPaid and balanceDue.

amountnumberrequired

In the invoice's currency, greater than zero, to the cent. Can't be more than balanceDue.

receivedAtstring

YYYY-MM-DD. Defaults to today.

methodstring
For example Wire. Up to 100 characters.
referencestring
For example a check number. Up to 200 characters.
notestring
Up to 1,000 characters.
curl -X POST https://<your-instance>/api/v1/invoices/cm9.../payments \
  -H "Authorization: Bearer ch_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "amount": 2000, "receivedAt": "2026-08-20", "method": "Wire" }'

Errors

StatusMessageFix
403Only owners and admins can record payments.Use an owner or admin key.
404Invoice not found.Check the id, and that the key can see the invoice.
422{ "amount": ["Amount must be greater than zero"] }Send a positive amount.
422That's more than the $3,250.00 still due on this invoice.Record at most balanceDue.
422Send the invoice before recording a payment.The invoice is a draft.
422This invoice is already paid in full.Nothing is due.
422This invoice is void.Void invoices can't be paid.
422Enter an amount greater than zero, to the cent.Use at most two decimal places.

To delete a payment recorded by mistake, use the invoice's Payments card in the app.