Skip to content

Invoices ​

3 endpoints. Every path below is relative to the API base URL and already includes the /api/v1 prefix — see conventions for authentication, pagination, errors and idempotency.

Endpoint
GET/billing/invoicesList invoices newest first, optionally filtered by status, with totals and amount due
GET/billing/invoices/{invoice}Retrieve one invoice with its line items, usage appendix, bill-to block and tax breakdown
GET/billing/invoices/{invoice}/downloadRender the invoice as a printable HTML document the browser can save as a PDF

Endpoints ​

List invoices newest first, optionally filtered by status, with totals and amount due ​

GET/billing/invoices
  • Requires billing.read.
  • status accepts repeated values and is matched with whereIn
bash
curl -X GET "$CALLAGENT_API_URL/billing/invoices" \
  -H "Authorization: Bearer $CALLAGENT_API_KEY" \
  -H "Accept: application/json"
js
const response = await fetch(`${process.env.CALLAGENT_API_URL}/billing/invoices`, {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
    Accept: 'application/json',
  },
});

if (!response.ok) {
  const { error } = await response.json();
  throw new Error(`${error.type}: ${error.message}`);
}

const { data } = await response.json();
php
<?php

$handle = curl_init(getenv('CALLAGENT_API_URL') . '/billing/invoices');

curl_setopt_array($handle, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
        'Accept: application/json',
    ],
]);

$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);

if ($status >= 400) {
    throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}

$data = $body['data'];
python
import os, requests

response = requests.get(
    f"{os.environ['CALLAGENT_API_URL']}/billing/invoices",
    headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
    timeout=30,
)
response.raise_for_status()
data = response.json()["data"]

Responses

StatusBody
200data-wrapped array

Errors

StatusWhen it happens
403Neither the API key scope nor the session user's permission allows billing.read

Example response, generated from the schema:

json
{
  "data": [
    {
      "id": null,
      "number": "+40712345678",
      "status": "string",
      "type": "string",
      "currency": "string",
      "period_start": "string",
      "period_end": "string",
      "issue_date": "string",
      "due_date": "string",
      "subtotal": "string",
      "tax_total": "string",
      "credit_total": "string",
      "total": "string",
      "amount_paid": "string",
      "amount_due": "string",
      "overdue": true,
      "hosted_invoice_url": "https://example.com/hook"
    }
  ],
  "meta": {
    "current_page": 1,
    "per_page": 25,
    "total": 1,
    "last_page": 1
  }
}

Retrieve one invoice with its line items, usage appendix, bill-to block and tax breakdown ​

GET/billing/invoices/{invoice}
  • Requires billing.read.

Path parameters

NameTypeRequiredNotes
invoicestringyes
bash
curl -X GET "$CALLAGENT_API_URL/billing/invoices/01JQ0000000000000000000000" \
  -H "Authorization: Bearer $CALLAGENT_API_KEY" \
  -H "Accept: application/json"
js
const response = await fetch(`${process.env.CALLAGENT_API_URL}/billing/invoices/01JQ0000000000000000000000`, {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
    Accept: 'application/json',
  },
});

if (!response.ok) {
  const { error } = await response.json();
  throw new Error(`${error.type}: ${error.message}`);
}

const { data } = await response.json();
php
<?php

$handle = curl_init(getenv('CALLAGENT_API_URL') . '/billing/invoices/01JQ0000000000000000000000');

curl_setopt_array($handle, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
        'Accept: application/json',
    ],
]);

$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);

if ($status >= 400) {
    throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}

$data = $body['data'];
python
import os, requests

response = requests.get(
    f"{os.environ['CALLAGENT_API_URL']}/billing/invoices/01JQ0000000000000000000000",
    headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
    timeout=30,
)
response.raise_for_status()
data = response.json()["data"]

Responses

StatusBody
200data-wrapped object

Errors

StatusWhen it happens
403Neither the API key scope nor the session user's permission allows billing.read
404No invoice with that id in this organization

Example response, generated from the schema:

json
{
  "data": {
    "id": null,
    "number": "+40712345678",
    "status": "string",
    "type": "string",
    "currency": "string",
    "period_start": "string",
    "period_end": "string",
    "issue_date": "string",
    "due_date": "string",
    "subtotal": "string",
    "tax_total": "string",
    "credit_total": "string",
    "total": "string",
    "amount_paid": "string",
    "amount_due": "string",
    "overdue": true,
    "hosted_invoice_url": "https://example.com/hook",
    "lines": [
      {}
    ],
    "usage_appendix": {},
    "bill_to": {},
    "tax": {
      "rate": "string",
      "total": "string",
      "type": "string",
      "jurisdiction": "https://example.com/hook",
      "reverse_charge": true,
      "exempt": true,
      "note": "string"
    }
  }
}

Render the invoice as a printable HTML document the browser can save as a PDF ​

GET/billing/invoices/{invoice}/download
  • Requires billing.read.
  • This response is not data-wrapped.
  • Returns text/html served inline, never a PDF and never JSON, despite the endpoint being named download

Path parameters

NameTypeRequiredNotes
invoicestringyes
bash
curl -X GET "$CALLAGENT_API_URL/billing/invoices/01JQ0000000000000000000000/download" \
  -H "Authorization: Bearer $CALLAGENT_API_KEY" \
  -H "Accept: application/json"
js
const response = await fetch(`${process.env.CALLAGENT_API_URL}/billing/invoices/01JQ0000000000000000000000/download`, {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
    Accept: 'application/json',
  },
});

if (!response.ok) {
  const { error } = await response.json();
  throw new Error(`${error.type}: ${error.message}`);
}

const { data } = await response.json();
php
<?php

$handle = curl_init(getenv('CALLAGENT_API_URL') . '/billing/invoices/01JQ0000000000000000000000/download');

curl_setopt_array($handle, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
        'Accept: application/json',
    ],
]);

$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);

if ($status >= 400) {
    throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}

$data = $body['data'];
python
import os, requests

response = requests.get(
    f"{os.environ['CALLAGENT_API_URL']}/billing/invoices/01JQ0000000000000000000000/download",
    headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
    timeout=30,
)
response.raise_for_status()
data = response.json()["data"]

Responses

StatusBody
200Not JSON — text/html; charset=utf-8

Errors

StatusWhen it happens
403Neither the API key scope nor the session user's permission allows billing.read
404No invoice with that id in this organization

Documented against the code. Anything not yet implemented is labelled, never described as working.