Skip to main content

Invoices

A sales invoice (crm_invoices) with line items, VAT, payment tracking, and Stripe hosted invoice / payment link integration. Scopes: sales.invoices.read / sales.invoices.write / sales.invoices.delete.

Endpoints

GET/api/workspace/v1/invoices
GET/api/workspace/v1/invoices/{id}
POST/api/workspace/v1/invoices
PATCH/api/workspace/v1/invoices/{id} (draft only)
POST/api/workspace/v1/invoices/{id}/send
POST/api/workspace/v1/invoices/{id}/mark-paid
POST/api/workspace/v1/invoices/{id}/void
POST/api/workspace/v1/invoices/{id}/credit-note
POST/api/workspace/v1/invoices/{id}/send-reminder
DELETE/api/workspace/v1/invoices/{id} (draft only)
POST/api/workspace/v1/invoices/{id}/restore
POST/api/workspace/v1/invoices/bulk-delete

The invoice object

FieldTypeDescription
crm_contact_id*integerContact the invoice is addressed to (required on create)
crm_deal_idintegerOptional linked CRM deal
lines*array1-100 line items — see line schema below
notesstringFree-form notes on the invoice (<= 5000 chars)
payment_terms_daysintegerPayment terms in days (1-365, default 14). Sets due_at at create time.
discount_amountnumberAbsolute discount amount
discount_reasonstringShort reason shown on the invoice
manual_labelstringOptional label (e.g. project ref)
referencestringFree-form PO / reference number
currencystring(3)ISO 4217 (defaults to workspace currency)
statusenumdraft | sent | overdue | paid | cancelled | void | credit_note (read-only)
credit_note_for_idintegerSet on credit-notes only. References the original invoice.

The line item

FieldTypeDescription
description*string1-500 chars
quantity*numberPositive quantity
unit_price*numberNon-negative unit price
vat_ratenumberVAT percentage 0-100 (default 21)
price_includes_vatbooleanDefault false
discount_percentnumberPer-line % discount (0-100)
product_idintegerOptional catalog product id
sort_orderintegerDisplay order (default insert order)

Create a draft invoice

Invoices are created in draft status. Totals (subtotal, VAT, total) are calculated server-side from the lines and returned in the response.

curl "https://app.staffifyai.com/api/workspace/v1/invoices" \
  -X POST \
  -H "Authorization: Bearer sfy_wsp_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "crm_contact_id": 1893,
    "crm_deal_id": 1024,
    "payment_terms_days": 14,
    "reference": "PO-2026-0912",
    "lines": [
      { "description": "AI Voice Agent — Sept", "quantity": 1, "unit_price": 499.00, "vat_rate": 21 },
      { "description": "Onboarding + setup",     "quantity": 1, "unit_price": 299.00, "vat_rate": 21 }
    ]
  }'

Send the invoice

POST /invoices/{id}/send transitions draft → sent. If the workspace has Stripe Connect + the recipient has an email, Stripe Invoicing hosts the invoice email itself; otherwise we fall back to a Stripe Payment Link and send a Staffify SES email. A public accept URL is always returned as public_url.

curl -X POST "https://app.staffifyai.com/api/workspace/v1/invoices/551/send" \
  -H "Authorization: Bearer sfy_wsp_live_YOUR_KEY" \
  -H "Idempotency-Key: send-551-2026-09-16"

Mark as paid (manual/bank/cash)

Records a row in the payments audit trail and updates amount_paid. If the cumulative amount covers the total (including any deposit), status flips to paid. Partial payments leave status at sent.

curl -X POST "https://app.staffifyai.com/api/workspace/v1/invoices/551/mark-paid" \
  -H "Authorization: Bearer sfy_wsp_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 949.00,
    "method": "bank_transfer",
    "reference": "SEPA-2026-09-16",
    "paid_at": "2026-09-16T10:30:00Z"
  }'

Void or credit-note

void is for unpaid invoices — the invoice is cancelled and (if applicable) Stripe is instructed to void the hosted invoice. Paid invoices cannot be voided; issue a credit-note instead which creates a NEW invoice with negative amounts and credit_note_for_id pointing back at the original.

# Void (unpaid only)
curl -X POST "https://app.staffifyai.com/api/workspace/v1/invoices/551/void" \
  -H "Authorization: Bearer sfy_wsp_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "reason": "Customer withdrew order" }'

# Credit-note (returns the NEW invoice)
curl -X POST "https://app.staffifyai.com/api/workspace/v1/invoices/551/credit-note" \
  -H "Authorization: Bearer sfy_wsp_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "reason": "Partial refund for missed delivery" }'

Send a reminder

Manually trigger a reminder email for sent or overdue invoices. Rate-limited to once per hour per invoice (returns 422 with "A reminder was already sent in the last hour" if throttled).

curl -X POST "https://app.staffifyai.com/api/workspace/v1/invoices/551/send-reminder" \
  -H "Authorization: Bearer sfy_wsp_live_YOUR_KEY"

List invoices

Filter by status, deal_id, contact_id. Set overdue=true to select sent invoices past their due_at. Recycle-bin filter via deleted=true | false | any.

curl "https://app.staffifyai.com/api/workspace/v1/invoices?status=sent&overdue=true" \
  -H "Authorization: Bearer sfy_wsp_live_YOUR_KEY"

Delete / restore / bulk-delete

Only draft invoices can be soft-deleted. Sent/paid invoices need to be voided or credit-noted for audit trail. Soft-deleted drafts move to a 30-day recycle bin; POST /:id/restore puts them back. Requires the separate sales.invoices.delete scope.

# Soft-delete draft
curl -X DELETE "https://app.staffifyai.com/api/workspace/v1/invoices/551" \
  -H "Authorization: Bearer sfy_wsp_live_YOUR_KEY"

# Restore
curl -X POST "https://app.staffifyai.com/api/workspace/v1/invoices/551/restore" \
  -H "Authorization: Bearer sfy_wsp_live_YOUR_KEY"

# Bulk-delete (max 500 draft ids; non-draft ids silently skipped)
curl -X POST "https://app.staffifyai.com/api/workspace/v1/invoices/bulk-delete" \
  -H "Authorization: Bearer sfy_wsp_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "ids": [551, 552, 553] }'

Webhooks

Invoice mutations fire the following events (subscribe via webhook endpoints):

  • invoice.created
  • invoice.updated
  • invoice.sent
  • invoice.paid
  • invoice.voided
  • invoice.credit_note_issued
  • invoice.reminder_sent
  • invoice.deleted
  • invoice.restored
Invoices - Workspace API - Staffify