Invoices & Income

API reference for creating, updating, and managing invoices with PDF generation.
Invoices are also available via the Public API using API keys: GET/POST https://dev.taxmtd.uk/api/v1/invoices. See Authentication for details.

List Invoices

JavaScript
const invoices = await $fetch('https://dev.taxmtd.uk/api/invoices')
// Returns: Array<{
//   id, invoiceNumber, clientName, clientEmail,
//   items, subtotal, vatAmount, total,
//   status, dueDate, createdAt
// }>
Python
res = requests.get(
    "https://dev.taxmtd.uk/api/invoices",
    cookies=session_cookies,
)
invoices = res.json()["data"]
PHP
$response = Http::withCookies($session)
    ->get('https://dev.taxmtd.uk/api/invoices');

$invoices = $response->json()['data'];
Rust
#[derive(Deserialize)]
struct Invoice {
    id: i64,
    invoice_number: String,
    client_name: String,
    total: f64,
    status: String,
}

let invoices: Vec<Invoice> = client
    .get("https://dev.taxmtd.uk/api/invoices")
    .send().await?
    .json::<serde_json::Value>().await?["data"]
    .as_array().unwrap()
    .iter()
    .map(|v| serde_json::from_value(v.clone()).unwrap())
    .collect();
cURL
curl https://dev.taxmtd.uk/api/invoices

Create Invoice

JavaScript
const invoice = await $fetch('https://dev.taxmtd.uk/api/invoices', {
  method: 'POST',
  body: {
    clientName: 'Acme Ltd',
    clientEmail: 'billing@acme.com',
    clientAddress: '456 Business Park, Manchester',
    items: [
      { description: 'Web Development', quantity: 40, unitPrice: 75.00 },
      { description: 'Annual Hosting', quantity: 1, unitPrice: 120.00 }
    ],
    vatRate: 20,
    dueDate: '2026-04-15',
    notes: 'Payment via bank transfer to sort code 12-34-56, account 12345678'
  }
})
Python
res = requests.post(
    "https://dev.taxmtd.uk/api/invoices",
    json={
        "clientName": "Acme Ltd",
        "clientEmail": "billing@acme.com",
        "clientAddress": "456 Business Park, Manchester",
        "items": [
            {"description": "Web Development", "quantity": 40, "unitPrice": 75.00},
            {"description": "Annual Hosting", "quantity": 1, "unitPrice": 120.00},
        ],
        "vatRate": 20,
        "dueDate": "2026-04-15",
        "notes": "Payment via bank transfer to sort code 12-34-56, account 12345678",
    },
    cookies=session_cookies,
)
invoice = res.json()["data"]
PHP
$invoice = Http::withCookies($session)->post(
    'https://dev.taxmtd.uk/api/invoices',
    [
        'clientName' => 'Acme Ltd',
        'clientEmail' => 'billing@acme.com',
        'items' => [
            ['description' => 'Web Development', 'quantity' => 40, 'unitPrice' => 75.00],
            ['description' => 'Annual Hosting', 'quantity' => 1, 'unitPrice' => 120.00],
        ],
        'vatRate' => 20,
        'dueDate' => '2026-04-15',
    ]
);

$data = $invoice->json()['data'];
Rust
let invoice = client.post("https://dev.taxmtd.uk/api/invoices")
    .json(&serde_json::json!({
        "clientName": "Acme Ltd",
        "clientEmail": "billing@acme.com",
        "items": [
            { "description": "Web Development", "quantity": 40, "unitPrice": 75.0 }
        ],
        "vatRate": 20,
        "dueDate": "2026-04-15"
    }))
    .send().await?;
cURL
curl -X POST https://dev.taxmtd.uk/api/invoices \
  -H "Content-Type: application/json" \
  -d '{
    "clientName": "Acme Ltd",
    "clientEmail": "billing@acme.com",
    "items": [{"description":"Web Dev","quantity":40,"unitPrice":75}],
    "vatRate": 20,
    "dueDate": "2026-04-15"
  }'

Update Invoice

JavaScript
await $fetch('https://dev.taxmtd.uk/api/invoices', {
  method: 'PUT',
  body: { id: 1, status: 'paid', paidDate: '2026-04-10' }
})
Python
res = requests.put(
    "https://dev.taxmtd.uk/api/invoices",
    json={"id": 1, "status": "paid", "paidDate": "2026-04-10"},
    cookies=session_cookies,
)
data = res.json()["data"]
PHP
$response = Http::withCookies($session)->put(
    'https://dev.taxmtd.uk/api/invoices',
    ['id' => 1, 'status' => 'paid', 'paidDate' => '2026-04-10']
);

$data = $response->json()['data'];
Rust
let res = client.put("https://dev.taxmtd.uk/api/invoices")
    .json(&serde_json::json!({
        "id": 1,
        "status": "paid",
        "paidDate": "2026-04-10"
    }))
    .send().await?;
cURL
curl -X PUT https://dev.taxmtd.uk/api/invoices \
  -H "Content-Type: application/json" \
  -d '{"id":1,"status":"paid"}'

Download PDF

JavaScript
const pdf = await $fetch(`https://dev.taxmtd.uk/api/invoices/${id}/pdf`)
// Returns PDF binary data
Python
res = requests.get(
    f"https://dev.taxmtd.uk/api/invoices/{invoice_id}/pdf",
    cookies=session_cookies,
)
with open("invoice-001.pdf", "wb") as f:
    f.write(res.content)
PHP
$response = Http::withCookies($session)
    ->get("https://dev.taxmtd.uk/api/invoices/{$id}/pdf");

Storage::put('invoice-001.pdf', $response->body());
Rust
let bytes = client
    .get(&format!("https://dev.taxmtd.uk/api/invoices/{}/pdf", id))
    .send().await?
    .bytes().await?;
std::fs::write("invoice-001.pdf", &bytes)?;
cURL
curl https://dev.taxmtd.uk/api/invoices/1/pdf -o invoice-001.pdf

Contact Activity Timeline

Returns all invoices, bills, and estimates linked to a contact, sorted by date.

JavaScript
const activity = await $fetch(`https://dev.taxmtd.uk/api/contacts/${contactId}/activity`)
// Returns: {
//   timeline: Array<{ type, id, number, date, total, status }>,
//   totals: { invoices, bills, invoiceCount, billCount, estimateCount }
// }
Python
res = requests.get(
    f"https://dev.taxmtd.uk/api/contacts/{contact_id}/activity",
    cookies=session_cookies,
)
activity = res.json()["data"]
timeline = activity["timeline"]
totals = activity["totals"]
PHP
$response = Http::withCookies($session)
    ->get("https://dev.taxmtd.uk/api/contacts/{$contactId}/activity");

$activity = $response->json()['data'];
$timeline = $activity['timeline'];
$totals = $activity['totals'];
Rust
let activity: serde_json::Value = client
    .get(&format!(
        "https://dev.taxmtd.uk/api/contacts/{}/activity",
        contact_id
    ))
    .send().await?
    .json::<serde_json::Value>().await?["data"]
    .clone();
let timeline = &activity["timeline"];
let totals = &activity["totals"];
cURL
curl https://dev.taxmtd.uk/api/contacts/UUID/activity

Customer Statement PDF

Generates a PDF statement showing all invoices and outstanding balance for a contact.

JavaScript
const blob = await $fetch(`https://dev.taxmtd.uk/api/contacts/${contactId}/statement`, {
  responseType: 'blob'
})
Python
res = requests.get(
    f"https://dev.taxmtd.uk/api/contacts/{contact_id}/statement",
    cookies=session_cookies,
)
with open("statement.pdf", "wb") as f:
    f.write(res.content)
PHP
$response = Http::withCookies($session)
    ->get("https://dev.taxmtd.uk/api/contacts/{$contactId}/statement");

Storage::put('statement.pdf', $response->body());
Rust
let bytes = client
    .get(&format!(
        "https://dev.taxmtd.uk/api/contacts/{}/statement",
        contact_id
    ))
    .send().await?
    .bytes().await?;
std::fs::write("statement.pdf", &bytes)?;
cURL
curl https://dev.taxmtd.uk/api/contacts/UUID/statement -o statement.pdf

Delete Invoice

JavaScript
await $fetch('https://dev.taxmtd.uk/api/invoices', {
  method: 'DELETE',
  body: { id: 1 }
})
Python
res = requests.delete(
    "https://dev.taxmtd.uk/api/invoices",
    json={"id": 1},
    cookies=session_cookies,
)
data = res.json()["data"]
PHP
$response = Http::withCookies($session)->delete(
    'https://dev.taxmtd.uk/api/invoices',
    ['id' => 1]
);

$data = $response->json()['data'];
Rust
let res = client.delete("https://dev.taxmtd.uk/api/invoices")
    .json(&serde_json::json!({ "id": 1 }))
    .send().await?;
cURL
curl -X DELETE https://dev.taxmtd.uk/api/invoices \
  -H "Content-Type: application/json" \
  -d '{"id":1}'