Documentation
Sign In

Invoices

Create and manage invoices, generate them from approved time entries, and share client-facing links.

Required scopes:invoices:readinvoices:write

All endpoints require authentication with an API key via Authorization: Bearer anch_... — see Authentication. A :write scope implicitly includes its :read scope.

Quick example

curl "https://your-domain.com/api/invoices?status=sent" \
  -H "Authorization: Bearer anch_your_api_key"

Endpoints

GET/api/invoices
POST/api/invoices
GET/api/invoices/{id}
PATCH/api/invoices/{id}
DELETE/api/invoices/{id}
POST/api/invoices/from-time-entries
POST/api/invoices/{id}/send
POST/api/invoices/{id}/client-link
POST/api/invoices/{id}/payment-link

GET/api/invoices

Unlike the other list endpoints, this returns { data } without a meta pagination object.

Query parameters

FieldTypeDescription
dealIdstringFilter to invoices for a specific deal
statusstringFilter by status (see enumeration below)
limitintegerPage size (default: 50, max: 100)
offsetintegerPagination offset (default: 0)

Response (200)

{
  "data": [ { "id": "inv_...", "invoiceNumber": "INV-0042", "status": "sent", ... } ]
}

POST/api/invoices

All fields are optional — an empty body creates a draft with an auto-generated invoice number.

Body fields

FieldTypeDescription
dealIdstringAssociated deal
invoiceNumberstringAuto-generated when omitted
statusstringInvoice status (default: draft)
issuedDateinteger | stringIssue date — Unix ms or ISO string
dueDateinteger | stringDue date
paidDateinteger | stringPaid date
paymentMethodstringHow the invoice was paid
paymentReferencestringExternal payment reference
subtotalCentsintegerSubtotal in cents (default: 0)
taxRatenumberTax rate percentage (default: 0)
taxLabelstringLabel shown for tax (default: "Tax")
taxCentsintegerTax amount in cents (default: 0)
totalCentsintegerTotal in cents (default: 0)
currencystringISO currency code (default: USD)
notesstringNotes shown on the invoice
paymentTermsstringPayment terms text
showRateBreakdownbooleanShow hourly rate breakdown (default: false)
includeTimesheetbooleanAttach timesheet detail (default: false)

Response (201)

{ "id": "inv_V1StGXR8Z5jdHi6B", "invoiceNumber": "INV-0042" }

GET/api/invoices/{id}

Response (200)

{
  "data": {
    "id": "inv_V1StGXR8Z5jdHi6B",
    "organizationId": "org_4f90...",
    "invoiceNumber": "INV-0042",
    "dealId": "dl_...",
    "status": "sent",
    "issuedDate": 1736899200000,
    "dueDate": 1739577600000,
    "subtotalCents": 240000,
    "taxRate": 8.25,
    "taxCents": 19800,
    "totalCents": 259800,
    "currency": "USD",
    "createdAt": 1736899200000,
    "updatedAt": 1736899200000
  }
}

PATCH/api/invoices/{id}

PUT is also accepted. Marking an invoice paid can automatically advance the linked deal's stage; when that happens the response includes stageAdvanced.

Body fields

FieldTypeDescription
dealIdstringAssociated deal
invoiceNumberstringAuto-generated when omitted
statusstringInvoice status (default: draft)
issuedDateinteger | stringIssue date — Unix ms or ISO string
dueDateinteger | stringDue date
paidDateinteger | stringPaid date
paymentMethodstringHow the invoice was paid
paymentReferencestringExternal payment reference
subtotalCentsintegerSubtotal in cents (default: 0)
taxRatenumberTax rate percentage (default: 0)
taxLabelstringLabel shown for tax (default: "Tax")
taxCentsintegerTax amount in cents (default: 0)
totalCentsintegerTotal in cents (default: 0)
currencystringISO currency code (default: USD)
notesstringNotes shown on the invoice
paymentTermsstringPayment terms text
showRateBreakdownbooleanShow hourly rate breakdown (default: false)
includeTimesheetbooleanAttach timesheet detail (default: false)

Response (200)

{ "ok": true, "stageAdvanced": "paid_complete" }

DELETE/api/invoices/{id}

Permanent (hard) delete. With session auth this requires a manager or admin role.

Response (200)

{ "ok": true }

POST/api/invoices/from-time-entries

Builds an invoice from a set of time entries on a deal, grouping line items by task, deliverable, or a single line.

Body fields

FieldTypeDescription
dealIdrequiredstringDeal the entries belong to
timeEntryIdsrequiredstring[]Time entries to include
groupBystringtask, deliverable, or all
notesstringInvoice notes
paymentTermsstringPayment terms text
dueDateinteger | stringDue date
showRateBreakdownbooleanShow hourly rate breakdown
includeTimesheetbooleanAttach timesheet detail
taxRateIdstringApply a saved tax rate

Response (201)

{ "id": "inv_...", "invoiceNumber": "INV-0043" }

POST/api/invoices/{id}/send

Body fields

FieldTypeDescription
torequiredstringRecipient email address
messagestringCustom message included in the email

Response (200)

{ "ok": true }

GET on the same path reports whether outbound email is configured for your organization.

POST/api/invoices/{id}/client-link

Generates a public, tokenized link where the client can view the invoice without signing in. GET retrieves the existing link.

Response (200)

{ "url": "https://your-domain.com/view/invoice/<token>" }

POST/api/invoices/{id}/payment-link

Generates a Stripe payment link for the invoice. GET retrieves the existing link.

Response (200)

{ "url": "https://buy.stripe.com/..." }

Enumerations

Invoice statuses

  • draft
  • sent
  • paid
  • overdue
  • cancelled

Notes

  • Monetary values are integers in cents.
  • GET /api/invoices/public/{token} serves the client-facing invoice view and requires no authentication.