API and MCP reference

Invoices

9 operations. Each REST operation is also an MCP tool of the same name. REST https://tlntconnect.com/api/v1

GET/api/v1/invoicesList this workspace's invoices, newest first, with status and totals in integer cents. Admin members only.

Every invoice of the workspace (admin members on keys with finance:read only; a non-admin member is 403 role_forbidden, an admin key without the scope 403 missing_scope). Rows: id, invoice_number, status (draft, sent, paid, overdue, cancelled), campaign {id, name}, brand {id, name}, amount_cents, tax_cents, total_cents, currency, issued_date, due_date, sent_at, paid_date, voided_at, billing_name, billing_email, payment_status, created_at, updated_at. Filter by status, campaign_id or brand_id; paged with page/limit (limit ≤ 100, default 50). Billing links and provider ids are never returned.

MCP tool
list_invoices
Scopes
finance:read
Members
admin
Idempotency-Key
Ignored (read)
Rate weight
1

Input

status query"draft" | "sent" | "paid" | "overdue" | "cancelled"
campaign_id querystring (uuid) — Only this campaign's invoices.
brand_id querystring (uuid) — Only this brand's invoices.
limit queryinteger — Page size, default 50.
page queryinteger — 1-based page, default 1.

Responses

200Success
400invalid_input / invalid_json / invalid_id
401missing_token / invalid_token / revoked_token / expired_token
403missing_scope / actor_unavailable / plan_upgrade_required / role_forbidden
404not_found (unknown, cross-workspace or not visible to the key's member)
429rate_limited (honour Retry-After)
500internal_error
503service_unavailable
POST/api/v1/invoicesCreate a draft invoice (optionally with line items). Money is integer cents; totals are computed server-side.

Creates a DRAFT invoice through the same path as the app (src/lib/invoices/drafts.ts): number INV-YYYYMMDD-NNN, status draft, total_cents = amount_cents + tax_cents. With line_items, amount_cents is their sum (sending amount_cents too is a 400 unless it equals that sum); without, send amount_cents. brand_id / campaign_id / a line's creator_id or deliverable_id from another workspace is 404 / 400 before anything is written. Sending is a separate send_invoice, which needs the user's written confirmation in chat. Requires an Idempotency-Key (a blind retry never creates a second draft). Admin members on keys with finance:read + invoices:write.

MCP tool
create_invoice
Scopes
finance:read + invoices:write
Members
admin
Idempotency-Key
required
Rate weight
1

Input

Idempotency-Key header, requiredstring — Retry-safe key (1-255 printable ASCII; a UUID is recommended; an RFC 8941 quoted string is accepted). The same key with the same request within 24h replays the stored response byte for byte (Idempotent-Replayed: true) without running again; the replay still consumes the operation's rate weight.
brand_id bodystring (uuid) | null
campaign_id bodystring (uuid) | null
amount_cents bodyinteger — Subtotal in integer cents (omit when sending line_items).
tax_cents bodyinteger — Tax in integer cents, default 0.
currency bodystring — ISO currency, default USD.
issued_date bodystring | null
due_date bodystring | null
notes bodystring | null
email_subject bodystring | null
email_message bodystring | null
billing_name bodystring | null
billing_email bodystring (email) | null
billing_address_line1 bodystring | null
billing_address_line2 bodystring | null
billing_city bodystring | null
billing_state bodystring | null
billing_postal_code bodystring | null
billing_country bodystring | null
line_items bodyarray of object

Responses

201Success
400invalid_input / invalid_json / invalid_id / idempotency_key_required
401missing_token / invalid_token / revoked_token / expired_token
403missing_scope / actor_unavailable / plan_upgrade_required / role_forbidden
404not_found (unknown, cross-workspace or not visible to the key's member) / not_found / brand_not_found
409idempotency_key_reused / idempotency_in_progress / idempotency_context_changed / idempotency_response_too_large
429rate_limited (honour Retry-After)
500internal_error / idempotent_replay_of_failure
503service_unavailable
GET/api/v1/invoices/{invoice_id}One invoice with its line items, billing details and totals in integer cents. Admin members only.

The list row plus notes, the billing address, the composed email subject/message, payment_contract_file_id, creator_payout_portion_cents (when a direct payment recorded it) and line_items (id, description, quantity, unit_price_cents, total_cents, creator_id, deliverable_id). Another workspace's invoice is 404.

MCP tool
get_invoice
Scopes
finance:read
Members
admin
Idempotency-Key
Ignored (read)
Rate weight
1

Input

invoice_id path, requiredstring (uuid) — Invoice id in this workspace.

Responses

200Success
400invalid_input / invalid_json / invalid_id
401missing_token / invalid_token / revoked_token / expired_token
403missing_scope / actor_unavailable / plan_upgrade_required / role_forbidden
404not_found (unknown, cross-workspace or not visible to the key's member)
429rate_limited (honour Retry-After)
500internal_error
503service_unavailable
PATCH/api/v1/invoices/{invoice_id}Change a draft invoice's dates, notes, tax, billing details or email copy at the version you read.

Drafts only (a sent, paid or cancelled invoice is 409 conflict: change it in TLNT). expected_updated_at is required (428 expected_updated_at_required without it; 409 stale_target when the invoice changed since). The amount is the sum of the line items — edit those with the line-item tools; total_cents is recomputed from it and tax_cents. Status, sending and payment never change here.

MCP tool
update_invoice
Scopes
finance:read + invoices:write
Members
admin
Idempotency-Key
optional
Rate weight
1

Input

invoice_id path, requiredstring (uuid) — Invoice id in this workspace.
Idempotency-Key headerstring — Retry-safe key (1-255 printable ASCII; a UUID is recommended; an RFC 8941 quoted string is accepted). The same key with the same request within 24h replays the stored response byte for byte (Idempotent-Replayed: true) without running again; the replay still consumes the operation's rate weight.
expected_updated_at bodystring — The invoice's updated_at as you last read it. A changed invoice is refused (409 stale_target). In a query string, URL-encode it (+ as %2B).
tax_cents bodyinteger
currency bodystring
issued_date bodystring | null
due_date bodystring | null
notes bodystring | null
email_subject bodystring | null
email_message bodystring | null
billing_name bodystring | null
billing_email bodystring (email) | null
billing_address_line1 bodystring | null
billing_address_line2 bodystring | null
billing_city bodystring | null
billing_state bodystring | null
billing_postal_code bodystring | null
billing_country bodystring | null

Responses

200Success
400invalid_input / invalid_json / invalid_id
401missing_token / invalid_token / revoked_token / expired_token
403missing_scope / actor_unavailable / plan_upgrade_required / role_forbidden
404not_found (unknown, cross-workspace or not visible to the key's member)
409stale_target / conflict / idempotency_key_reused / idempotency_in_progress / idempotency_context_changed / idempotency_response_too_large
428expected_updated_at_required
429rate_limited (honour Retry-After)
500internal_error / idempotent_replay_of_failure
503service_unavailable
DELETE/api/v1/invoices/{invoice_id}Delete a draft invoice. Runs directly within the daily delete cap unless this credential asks for approval in TLNT for deletes (202 pending_approval: poll get_action).

Deletes one unlocked DRAFT invoice (a sent, paid, cancelled or payment-started invoice is 409 conflict). A `delete`-class action: by default it deletes at once (200 { status: "deleted" }) within the credential's daily delete cap. When the credential asks for approval in TLNT for deletes, the call answers 202 { status: "pending_approval", action_id, approval_url } instead and a workspace admin approves it in TLNT — the card names the invoice number, total and line-item count at the version you asked; an invoice edited before approval is not deleted. Requires finance:read + invoices:write + delete, an Idempotency-Key and an admin member.

MCP tool
delete_invoice
Scopes
finance:read + invoices:write + delete
Members
admin
Approval
Runs directly; queued when the credential asks for approval for delete
Idempotency-Key
required
Rate weight
1

Input

invoice_id path, requiredstring (uuid) — Invoice id in this workspace.
expected_updated_at querystring — The invoice's updated_at as you last read it. A changed invoice is refused (409 stale_target). In a query string, URL-encode it (+ as %2B).
Idempotency-Key header, requiredstring — Retry-safe key (1-255 printable ASCII; a UUID is recommended; an RFC 8941 quoted string is accepted). The same key with the same request within 24h replays the stored response byte for byte (Idempotent-Replayed: true) without running again; the replay still consumes the operation's rate weight.

Responses

200Success
202pending_approval — queued for approval in TLNT (only when the credential asks for approval for this action class; it runs directly by default)
400invalid_input / invalid_json / invalid_id / idempotency_key_required
401missing_token / invalid_token / revoked_token / expired_token
403missing_scope / actor_unavailable / plan_upgrade_required / role_forbidden
404not_found (unknown, cross-workspace or not visible to the key's member)
409stale_target / conflict / idempotency_key_reused / idempotency_in_progress / idempotency_context_changed / idempotency_response_too_large
429rate_limited (honour Retry-After) / daily_delete_cap_reached
500internal_error / idempotent_replay_of_failure
503service_unavailable
POST/api/v1/invoices/{invoice_id}/line-itemsAdd a line item (integer cents) to a draft invoice; the invoice totals are recalculated.

Same path as the app (src/lib/invoices/drafts.ts): integer quantity ≥ 1, unit_price_cents in integer cents, total = quantity × unit price; creator_id / deliverable_id must be this workspace's (400 otherwise). Drafts only over the API (409 conflict otherwise). Requires an Idempotency-Key (a blind retry never adds the line twice). Returns the invoice with its recalculated totals.

MCP tool
add_invoice_line_item
Scopes
finance:read + invoices:write
Members
admin
Idempotency-Key
required
Rate weight
1

Input

invoice_id path, requiredstring (uuid) — Invoice id in this workspace.
Idempotency-Key header, requiredstring — Retry-safe key (1-255 printable ASCII; a UUID is recommended; an RFC 8941 quoted string is accepted). The same key with the same request within 24h replays the stored response byte for byte (Idempotent-Replayed: true) without running again; the replay still consumes the operation's rate weight.
description body, requiredstring
quantity bodyinteger — Default 1.
unit_price_cents body, requiredinteger — Unit price in integer cents.
creator_id bodystring (uuid) | null — A roster creator in this workspace.
deliverable_id bodystring (uuid) | null — A deliverable in this workspace.

Responses

201Success
400invalid_input / invalid_json / invalid_id / idempotency_key_required
401missing_token / invalid_token / revoked_token / expired_token
403missing_scope / actor_unavailable / plan_upgrade_required / role_forbidden
404not_found (unknown, cross-workspace or not visible to the key's member)
409conflict / idempotency_key_reused / idempotency_in_progress / idempotency_context_changed / idempotency_response_too_large
429rate_limited (honour Retry-After)
500internal_error / idempotent_replay_of_failure
503service_unavailable
PATCH/api/v1/invoices/{invoice_id}/line-items/{line_item_id}Change a draft invoice's line item (description, quantity, unit price in cents); totals are recalculated.

As add_invoice_line_item, for one existing line (404 when it is not on this invoice). Drafts only over the API.

MCP tool
update_invoice_line_item
Scopes
finance:read + invoices:write
Members
admin
Idempotency-Key
optional
Rate weight
1

Input

invoice_id path, requiredstring (uuid) — Invoice id in this workspace.
line_item_id path, requiredstring (uuid) — Line item id on this invoice.
Idempotency-Key headerstring — Retry-safe key (1-255 printable ASCII; a UUID is recommended; an RFC 8941 quoted string is accepted). The same key with the same request within 24h replays the stored response byte for byte (Idempotent-Replayed: true) without running again; the replay still consumes the operation's rate weight.
description bodystring
quantity bodyinteger
unit_price_cents bodyinteger

Responses

200Success
400invalid_input / invalid_json / invalid_id
401missing_token / invalid_token / revoked_token / expired_token
403missing_scope / actor_unavailable / plan_upgrade_required / role_forbidden
404not_found (unknown, cross-workspace or not visible to the key's member)
409conflict / idempotency_key_reused / idempotency_in_progress / idempotency_context_changed / idempotency_response_too_large
429rate_limited (honour Retry-After)
500internal_error / idempotent_replay_of_failure
503service_unavailable
DELETE/api/v1/invoices/{invoice_id}/line-items/{line_item_id}Remove a line item from a draft invoice; totals are recalculated.

Removes one line of a DRAFT invoice (an edit of the draft, so it runs directly under invoices:write; 404 when the line is not on this invoice). Returns the invoice with its recalculated totals.

MCP tool
remove_invoice_line_item
Scopes
finance:read + invoices:write
Members
admin
Idempotency-Key
optional
Rate weight
1

Input

invoice_id path, requiredstring (uuid) — Invoice id in this workspace.
line_item_id path, requiredstring (uuid) — Line item id on this invoice.
Idempotency-Key headerstring — Retry-safe key (1-255 printable ASCII; a UUID is recommended; an RFC 8941 quoted string is accepted). The same key with the same request within 24h replays the stored response byte for byte (Idempotent-Replayed: true) without running again; the replay still consumes the operation's rate weight.

Responses

200Success
400invalid_input / invalid_json / invalid_id
401missing_token / invalid_token / revoked_token / expired_token
403missing_scope / actor_unavailable / plan_upgrade_required / role_forbidden
404not_found (unknown, cross-workspace or not visible to the key's member)
409conflict / idempotency_key_reused / idempotency_in_progress / idempotency_context_changed / idempotency_response_too_large
429rate_limited (honour Retry-After)
500internal_error / idempotent_replay_of_failure
503service_unavailable
POST/api/v1/invoices/{invoice_id}/sendEmail a draft invoice to its billing contact. Needs the user's written confirmation: the first call returns the preview and a confirmation_token and sends nothing.

The call validates the draft (total > 0, a brand, and a valid billing email — the invoice's billing_email, else its brand's contact). Written confirmation in chat: the first call (no confirmation_token) sends nothing and answers 200 { status: "confirmation_required", preview, confirmation_token, expires_at } — the preview is exactly what will be sent: invoice number, recipient, every line item with its quantity, unit price and total in integer cents, subtotal, tax, total, currency, due date, sender and the email copy. Show it to the user; only after they confirm in writing call again with the same arguments plus confirmation_token (single use, this credential only, valid 10 minutes). That call sends it once through the app's own send path (the agency's mailbox, else TLNT's invoice sender) with a link to the invoice's secure billing page, marks it sent and answers 200 { status: "executed", action_id, result: { delivery_id, recipient_email } }. A token for another invoice, another credential, expired or already used is refused (409 confirmation_invalid / confirmation_expired / confirmation_used); an invoice edited after the preview (amount, line items, recipient, due date, email) is 409 confirmation_stale — preview again; it is never sent in a form the user did not see. When the credential asks for approval in TLNT for "Sending email", the call is queued for an admin instead (202 pending_approval). Counts one recipient against the daily recipient cap. It moves no money. Requires finance:read + invoices:write + email:send, an Idempotency-Key and an admin member.

MCP tool
send_invoice
Scopes
finance:read + invoices:write + email:send
Members
admin
Approval
Runs after written confirmation in chat; queued when the credential asks for approval for external_send
Idempotency-Key
required
Rate weight
1
Untrusted fields
preview.recipient.name preview.email.text

Input

invoice_id path, requiredstring (uuid) — Invoice id in this workspace.
Idempotency-Key header, requiredstring — Retry-safe key (1-255 printable ASCII; a UUID is recommended; an RFC 8941 quoted string is accepted). The same key with the same request within 24h replays the stored response byte for byte (Idempotent-Replayed: true) without running again; the replay still consumes the operation's rate weight.
confirmation_token bodystring — Leave out on the first call: it answers status confirmation_required with the exact preview and this token, and sends nothing. Show the preview to the user; only after they confirm in writing, call again with the same arguments plus this token.

Responses

200Success
202pending_approval — queued for approval in TLNT (only when the credential asks for approval for this action class; it runs directly by default)
400invalid_input / invalid_json / invalid_id / idempotency_key_required
401missing_token / invalid_token / revoked_token / expired_token
403missing_scope / actor_unavailable / plan_upgrade_required / role_forbidden
404not_found (unknown, cross-workspace or not visible to the key's member)
409conflict / confirmation_invalid / confirmation_expired / confirmation_used / confirmation_stale / stale_target / idempotency_key_reused / idempotency_in_progress / idempotency_context_changed / idempotency_response_too_large
429rate_limited (honour Retry-After) / daily_send_cap_reached
500internal_error / idempotent_replay_of_failure
503service_unavailable