Invoices are emailed from Anytime Capital in your branding and paid at their url. Totals are calculated from the line items, an optional discount and tax. A customer can pay a deposit first, and automatic reminders go out around the due date unless you turn them off. Recurring invoices, bank transfer instructions and recording an offline payment are done in the dashboard.
| Topic | Detail |
|---|---|
| Endpoints | `POST /api/v1/invoices`, `GET /api/v1/invoices`, `GET /api/v1/invoices/{id}`, `POST /api/v1/invoices/{id}/send` |
| Key permissions | invoices:write, invoices:read |
| Samples | curl; Node.js 18+ with the built-in fetch (in an ES module); the Node SDK (preview: not on npm yet); Python with requests. |
| Every request can also answer | 401 UNAUTHORIZED, 401 API_KEY_EXPIRED, 403 NOT_ENROLLED, 403 PERMISSION_DENIED, 403 IP_NOT_ALLOWED, 429 RATE_LIMITED, 500 INTERNAL_ERROR. See Error codes. |
The invoice object
{
"object": "invoice",
"livemode": true,
"id": "inv_9QmR2vX7pLk3TzW8cN4b",
"number": "INV-0042",
"url": "https://anytime-capital.com/pay/invoice/inv_9QmR2vX7pLk3TzW8cN4b",
"status": "open",
"overdue": false,
"customer": {
"name": "Northwind LLC",
"email": "ap@northwind.example"
},
"lineItems": [
{
"description": "Website redesign",
"quantity": 1,
"unitCents": 450000
}
],
"subtotalCents": 450000,
"discountCents": 0,
"taxBps": 825,
"taxCents": 37125,
"totalCents": 487125,
"amountPaidCents": 0,
"balanceCents": 487125,
"depositCents": null,
"currency": "usd",
"dueDate": "2026-11-15",
"notes": "Thank you for your business.",
"paidVia": null,
"paidAt": null,
"paymentId": null,
"sentAt": "2026-10-16T14:00:00.000Z",
"voidedAt": null,
"createdAt": "2026-10-16T14:00:00.000Z"
}| Field | Type | Description |
|---|---|---|
object | string | The type of object. Always invoice. |
livemode | boolean | False for test-mode data (an ak_test_ key); true for live data. |
id | string | inv_ followed by 20 letters and digits. |
number | string | INV-0001. |
url | string (uri) | Where the customer views and pays it. |
status | string | open, partially_paid, paid, refunded, void: partially_paid after a deposit or part payment, refunded when paid and then refunded in full. |
overdue | boolean | Still owed and past its due date. |
customer | object | |
customer.name | string | Name. |
customer.email | string | Email. |
lineItems | object[] | |
lineItems[].description | string | Line. |
lineItems[].quantity | integer | Quantity. |
lineItems[].unitCents | integer | Unit price. Integer cents. |
subtotalCents | integer | Before discount and tax. Integer cents. |
discountCents | integer | Discount. Integer cents. |
taxBps | integer | Tax in basis points (825 is 8.25%). |
taxCents | integer | Tax, applied after the discount. |
totalCents | integer | Total. Integer cents. |
amountPaidCents | integer | Paid so far. Integer cents. |
balanceCents | integer | Still owed. Integer cents. |
depositCents | integer or null | Deposit the customer may pay first. Integer cents. |
currency | string | usd. |
dueDate | string (date) | YYYY-MM-DD. |
notes | string or null | Printed on the invoice. |
paidVia | string or null | card, or how it was recorded as paid in the dashboard. |
paidAt | string (date-time) or null | Paid in full. |
paymentId | string or null | The card payment that paid it. |
sentAt | string (date-time) or null | First emailed. |
voidedAt | string (date-time) or null | Voided. |
createdAt | string (date-time) | Created. |
Endpoints
Create an invoice
/api/v1/invoicesinvoices:writeSupports Idempotency-Key.Totals are calculated from the lines; emailed to the customer unless send: false. Totals are calculated from the lines (discount first, then tax) and run from $1.00 to $100,000.00. Recurring invoices are set up in the dashboard: sending recurrence answers 400 INVALID_INPUT. If the email fails, the invoice is still created with sentAt: null; send it later.
Headers
Idempotency-Keystring- Recommended. A unique key such as a UUID: a retry with the same key within 24 hours gets the first response back instead of acting twice. See Idempotency.
Body
customerNamestringrequired- Who the invoice is for. Up to 200 characters.
customerEmailstring (email)required- Where the invoice is emailed. Up to 255 characters.
lineItemsobject[]required- 1–50 items.
lineItems[].descriptionstringrequired- Up to 200 characters.
lineItems[].quantityintegerrequired- From 1 to 10,000.
lineItems[].unitCentsintegerrequired- From 1 ($0.01) to 10,000,000 ($100,000.00).
dueDatestring (date)required- YYYY-MM-DD.
discountCentsinteger- Taken off the subtotal before tax.
taxBpsinteger- Tax in basis points: 825 is 8.25%. From 0 to 3,000.
notesstring- Printed on the invoice. Up to 2000 characters.
depositobject- What the customer may pay first:
{"type": "amount", "amountCents": 50000}or{"type": "percent", "percent": 25}. At least $1.00, and less than the total with at least $1.00 left to pay. remindersEnabledboolean- Automatic reminders around the due date. Default true.
sendboolean- Email the invoice now. Default true.
saveCustomerboolean- Also add the customer to your customers (skipped when the email is already there). Default
false.
curl -X POST https://anytime-capital.com/api/v1/invoices \
-H "Authorization: Bearer $ANYTIME_API_KEY" \
-H "Idempotency-Key: invoice-northwind-oct" \
-H "Content-Type: application/json" \
-d '{
"customerName": "Northwind LLC",
"customerEmail": "ap@northwind.example",
"lineItems": [
{
"description": "Website redesign",
"quantity": 1,
"unitCents": 450000
}
],
"taxBps": 825,
"dueDate": "2026-11-15"
}'const res = await fetch("https://anytime-capital.com/api/v1/invoices", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.ANYTIME_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": "invoice-northwind-oct",
},
body: JSON.stringify({
customerName: "Northwind LLC",
customerEmail: "ap@northwind.example",
lineItems: [{ description: "Website redesign", quantity: 1, unitCents: 450000 }],
taxBps: 825,
dueDate: "2026-11-15",
}),
});
const invoice = await res.json();
if (!res.ok) throw new Error(`${invoice.error.code}: ${invoice.error.message}`);import { AnytimeCapital } from "@anytimecapital/node";
const client = new AnytimeCapital({ apiKey: process.env.ANYTIME_API_KEY! });
const invoice = await client.invoices.create(
{
customerName: "Northwind LLC",
customerEmail: "ap@northwind.example",
lineItems: [{ description: "Website redesign", quantity: 1, unitCents: 450000 }],
taxBps: 825,
dueDate: "2026-11-15",
},
{ idempotencyKey: "invoice-northwind-oct" },
);import os
import requests
res = requests.post(
"https://anytime-capital.com/api/v1/invoices",
headers={
"Authorization": f"Bearer {os.environ['ANYTIME_API_KEY']}",
"Idempotency-Key": "invoice-northwind-oct",
},
json={
"customerName": "Northwind LLC",
"customerEmail": "ap@northwind.example",
"lineItems": [
{"description": "Website redesign", "quantity": 1, "unitCents": 450000},
],
"taxBps": 825,
"dueDate": "2026-11-15",
},
timeout=30,
)
invoice = res.json()
if not res.ok:
raise RuntimeError(f"{invoice['error']['code']}: {invoice['error']['message']}"){
"object": "invoice",
"livemode": true,
"id": "inv_9QmR2vX7pLk3TzW8cN4b",
"number": "INV-0042",
"url": "https://anytime-capital.com/pay/invoice/inv_9QmR2vX7pLk3TzW8cN4b",
"status": "open",
"overdue": false,
"customer": {
"name": "Northwind LLC",
"email": "ap@northwind.example"
},
"lineItems": [
{
"description": "Website redesign",
"quantity": 1,
"unitCents": 450000
}
],
"subtotalCents": 450000,
"discountCents": 0,
"taxBps": 825,
"taxCents": 37125,
"totalCents": 487125,
"amountPaidCents": 0,
"balanceCents": 487125,
"depositCents": null,
"currency": "usd",
"dueDate": "2026-11-15",
"notes": "Thank you for your business.",
"paidVia": null,
"paidAt": null,
"paymentId": null,
"sentAt": "2026-10-16T14:00:00.000Z",
"voidedAt": null,
"createdAt": "2026-10-16T14:00:00.000Z"
}Errors
- 400
INVALID_JSON - The body isn't valid JSON, or couldn't be read. An empty body reads as
{}. SendContent-Type: application/jsonand a JSON object. - 400
INVALID_INPUT - A field, filter,
limitorcursoris missing or invalid. The message starts with the field's name, as inamountCents: …, or readsInvalid cursor.Fix the named field. Don't retry the same request unchanged. - 400
INVALID_IDEMPOTENCY_KEY - The
Idempotency-Keyheader is empty, longer than 255 characters, or has characters other than printable ASCII. Use a UUID. See Idempotency. - 422
IDEMPOTENCY_KEY_REUSED - The
Idempotency-Keywas used in the last 24 hours with a different body or endpoint. Use a new key for a new request; reuse a key only to retry the same request.
List invoices
/api/v1/invoicesinvoices:readInvoices with totals, what is paid and owed, and the pay page url.
Query
statusstring- Only invoices with this status. One of
open,partially_paid,paid,refunded,void. limitinteger- How many objects per page, 1–100. Default 25. See Pagination.
cursorstring- The previous page's
nextCursor, for the page after it.
curl "https://anytime-capital.com/api/v1/invoices?status=open" \
-H "Authorization: Bearer $ANYTIME_API_KEY"const res = await fetch("https://anytime-capital.com/api/v1/invoices?status=open", {
headers: { Authorization: `Bearer ${process.env.ANYTIME_API_KEY}` },
});
const page = await res.json();
if (!res.ok) throw new Error(`${page.error.code}: ${page.error.message}`);import { AnytimeCapital } from "@anytimecapital/node";
const client = new AnytimeCapital({ apiKey: process.env.ANYTIME_API_KEY! });
const page = await client.invoices.list({ status: "open" });import os
import requests
res = requests.get(
"https://anytime-capital.com/api/v1/invoices",
headers={"Authorization": f"Bearer {os.environ['ANYTIME_API_KEY']}"},
params={"status": "open"},
timeout=30,
)
page = res.json()
if not res.ok:
raise RuntimeError(f"{page['error']['code']}: {page['error']['message']}"){
"object": "list",
"data": [
{
"object": "invoice",
"livemode": true,
"id": "inv_9QmR2vX7pLk3TzW8cN4b",
"number": "INV-0042",
"url": "https://anytime-capital.com/pay/invoice/inv_9QmR2vX7pLk3TzW8cN4b",
"status": "open",
"overdue": false,
"customer": {
"name": "Northwind LLC",
"email": "ap@northwind.example"
},
"lineItems": [
{
"description": "Website redesign",
"quantity": 1,
"unitCents": 450000
}
],
"subtotalCents": 450000,
"discountCents": 0,
"taxBps": 825,
"taxCents": 37125,
"totalCents": 487125,
"amountPaidCents": 0,
"balanceCents": 487125,
"depositCents": null,
"currency": "usd",
"dueDate": "2026-11-15",
"notes": "Thank you for your business.",
"paidVia": null,
"paidAt": null,
"paymentId": null,
"sentAt": "2026-10-16T14:00:00.000Z",
"voidedAt": null,
"createdAt": "2026-10-16T14:00:00.000Z"
}
],
"hasMore": false,
"nextCursor": null
}Errors
- 400
INVALID_INPUT - A field, filter,
limitorcursoris missing or invalid. The message starts with the field's name, as inamountCents: …, or readsInvalid cursor.Fix the named field. Don't retry the same request unchanged.
Get an invoice
/api/v1/invoices/{id}invoices:readOne invoice by id.
Path
idstringrequiredinv_…
curl https://anytime-capital.com/api/v1/invoices/inv_9QmR2vX7pLk3TzW8cN4b \
-H "Authorization: Bearer $ANYTIME_API_KEY"const res = await fetch("https://anytime-capital.com/api/v1/invoices/inv_9QmR2vX7pLk3TzW8cN4b", {
headers: { Authorization: `Bearer ${process.env.ANYTIME_API_KEY}` },
});
const invoice = await res.json();
if (!res.ok) throw new Error(`${invoice.error.code}: ${invoice.error.message}`);import { AnytimeCapital } from "@anytimecapital/node";
const client = new AnytimeCapital({ apiKey: process.env.ANYTIME_API_KEY! });
const invoice = await client.invoices.retrieve("inv_9QmR2vX7pLk3TzW8cN4b");import os
import requests
res = requests.get(
"https://anytime-capital.com/api/v1/invoices/inv_9QmR2vX7pLk3TzW8cN4b",
headers={"Authorization": f"Bearer {os.environ['ANYTIME_API_KEY']}"},
timeout=30,
)
invoice = res.json()
if not res.ok:
raise RuntimeError(f"{invoice['error']['code']}: {invoice['error']['message']}"){
"object": "invoice",
"livemode": true,
"id": "inv_9QmR2vX7pLk3TzW8cN4b",
"number": "INV-0042",
"url": "https://anytime-capital.com/pay/invoice/inv_9QmR2vX7pLk3TzW8cN4b",
"status": "open",
"overdue": false,
"customer": {
"name": "Northwind LLC",
"email": "ap@northwind.example"
},
"lineItems": [
{
"description": "Website redesign",
"quantity": 1,
"unitCents": 450000
}
],
"subtotalCents": 450000,
"discountCents": 0,
"taxBps": 825,
"taxCents": 37125,
"totalCents": 487125,
"amountPaidCents": 0,
"balanceCents": 487125,
"depositCents": null,
"currency": "usd",
"dueDate": "2026-11-15",
"notes": "Thank you for your business.",
"paidVia": null,
"paidAt": null,
"paymentId": null,
"sentAt": "2026-10-16T14:00:00.000Z",
"voidedAt": null,
"createdAt": "2026-10-16T14:00:00.000Z"
}Errors
- 404
NOT_FOUND - No such object on your business (an id from another business reads the same), or no such endpoint under
/api/v1, which still answers in JSON. Check the id and the path. Ids are case-sensitive.
Send an invoice
/api/v1/invoices/{id}/sendinvoices:writeSupports Idempotency-Key.Email it (a reminder after the first time), at most once a day, while something is owed. The invoice itself the first time (sends invoice.sent), a reminder after that.
Path
idstringrequiredinv_…
Headers
Idempotency-Keystring- Recommended. A unique key such as a UUID: a retry with the same key within 24 hours gets the first response back instead of acting twice. See Idempotency.
curl -X POST https://anytime-capital.com/api/v1/invoices/inv_9QmR2vX7pLk3TzW8cN4b/send \
-H "Authorization: Bearer $ANYTIME_API_KEY" \
-H "Idempotency-Key: send-inv-0042"const res = await fetch("https://anytime-capital.com/api/v1/invoices/inv_9QmR2vX7pLk3TzW8cN4b/send", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.ANYTIME_API_KEY}`,
"Idempotency-Key": "send-inv-0042",
},
});
const invoice = await res.json();
if (!res.ok) throw new Error(`${invoice.error.code}: ${invoice.error.message}`);import { AnytimeCapital } from "@anytimecapital/node";
const client = new AnytimeCapital({ apiKey: process.env.ANYTIME_API_KEY! });
const invoice = await client.invoices.send(
"inv_9QmR2vX7pLk3TzW8cN4b",
{ idempotencyKey: "send-inv-0042" },
);import os
import requests
res = requests.post(
"https://anytime-capital.com/api/v1/invoices/inv_9QmR2vX7pLk3TzW8cN4b/send",
headers={
"Authorization": f"Bearer {os.environ['ANYTIME_API_KEY']}",
"Idempotency-Key": "send-inv-0042",
},
timeout=30,
)
invoice = res.json()
if not res.ok:
raise RuntimeError(f"{invoice['error']['code']}: {invoice['error']['message']}"){
"object": "invoice",
"livemode": true,
"id": "inv_9QmR2vX7pLk3TzW8cN4b",
"number": "INV-0042",
"url": "https://anytime-capital.com/pay/invoice/inv_9QmR2vX7pLk3TzW8cN4b",
"status": "open",
"overdue": false,
"customer": {
"name": "Northwind LLC",
"email": "ap@northwind.example"
},
"lineItems": [
{
"description": "Website redesign",
"quantity": 1,
"unitCents": 450000
}
],
"subtotalCents": 450000,
"discountCents": 0,
"taxBps": 825,
"taxCents": 37125,
"totalCents": 487125,
"amountPaidCents": 0,
"balanceCents": 487125,
"depositCents": null,
"currency": "usd",
"dueDate": "2026-11-15",
"notes": "Thank you for your business.",
"paidVia": null,
"paidAt": null,
"paymentId": null,
"sentAt": "2026-10-16T14:00:00.000Z",
"voidedAt": null,
"createdAt": "2026-10-16T14:00:00.000Z"
}Errors
- 400
INVALID_IDEMPOTENCY_KEY - The
Idempotency-Keyheader is empty, longer than 255 characters, or has characters other than printable ASCII. Use a UUID. See Idempotency. - 404
NOT_FOUND - No such object on your business (an id from another business reads the same), or no such endpoint under
/api/v1, which still answers in JSON. Check the id and the path. Ids are case-sensitive. - 409
INVOICE_CLOSED - The invoice is already paid, refunded or void, so there's nothing to send. Read the invoice's
status; nothing to do. - 422
IDEMPOTENCY_KEY_REUSED - The
Idempotency-Keywas used in the last 24 hours with a different body or endpoint. Use a new key for a new request; reuse a key only to retry the same request. - 429
TOO_SOON - The invoice was already emailed in the last 24 hours. Wait the seconds in
Retry-After. - 502
EMAIL_FAILED - We couldn't send the email. Retry. Nothing was marked as sent.
Knowing when an invoice is paid
Subscribe to the invoice.paid webhook, which carries the invoice object once it is paid in full. Each card payment on an invoice, deposits included, also sends payment.succeeded with source.type invoice and source.id the invoice id. invoice.created, invoice.sent, invoice.overdue and invoice.voided follow the rest of its life. See Webhooks.