Skip to main content

Bit CRM Invoices API Documentation for Developers

Estimated reading: 12 minutes 19 views

The Invoices API lets you create, list, update, and trash invoices, move them through their status lifecycle, download the generated PDF, and create a public share link. Invoices belong to deals: module is always deal and entity_id is the deal’s ID. All endpoints are relative to your base URL and authenticated with an API key, see Introduction & Authentication.

Invoice statuses

An invoice is always in one of five statuses: draft, sent, overdue, partially_paid, or paid. Transitions are validated — the allowed moves are:

  • draft → sent, paid, or overdue
  • sent → paid, overdue, or partially_paid
  • overdue → paid, sent, or partially_paid
  • partially_paid → paid
  • paid — final; a paid invoice’s status cannot change.

Create an invoice

POST /invoices/store — requires capability bit_crm_invoice_create. The invoice total is calculated on the server from the line items, tax option, and gross discount.

  • module — string, required. Always deal.
  • entity_id — integer, required. The ID of the deal the invoice belongs to.
  • invoice_date — string, required, e.g. 2026-08-05.
  • due_date — string, required.
  • term_key — string, required. The key of an invoice term defined in Settings → Invoice Settings.
  • invoice_prefix — string, required. The invoice number prefix, e.g. INV; the invoice number is the prefix plus the invoice ID.
  • currency — string, required. A currency code enabled on the site, e.g. USD.
  • tax_option — string, required. exclusive, inclusive, or no_tax. The value is not validated as an enum — anything other than exclusive/inclusive is treated as no tax.
  • line_items — array, required. Item fields (all optional at the validation layer): product_name (string), unit_price (number), quantity (integer), discount_percentage (number, 0–100), tax_rate (number, 0–1000), description (string), plus product_id, product_code, product_source to reference a CRM product.
  • gross_discount_amount — number, optional. A discount applied on top of the line items.
  • gross_discount_type — string, optional. amount (flat, default) or rate (percentage). Not validated — any other value is treated as amount.
  • top_section_notes / bottom_section_notes — arrays of {"label", "value"} objects, optional. Free-form text shown above and below the line items on the invoice.
POST https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/store
  • Bash
  • PHP
  • JavaScript
curl -X POST "https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/store" \
  --user "your-username:YOUR API KEY" \
  -H "Content-Type: application/json" \
  -d '{"module":"deal","entity_id":8,"invoice_date":"2026-08-05","due_date":"2026-08-19","term_key":"net_14","invoice_prefix":"INV","currency":"USD","tax_option":"exclusive","line_items":[{"product_name":"Consulting hours","unit_price":120,"quantity":10,"discount_percentage":0,"tax_rate":10,"description":"August retainer"}]}'
$ch = curl_init('https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/store');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERPWD        => 'your-username:YOUR API KEY',
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS     => json_encode(['module' => 'deal', 'entity_id' => 8, 'invoice_date' => '2026-08-05', 'due_date' => '2026-08-19', 'term_key' => 'net_14', 'invoice_prefix' => 'INV', 'currency' => 'USD', 'tax_option' => 'exclusive', 'line_items' => [['product_name' => 'Consulting hours', 'unit_price' => 120, 'quantity' => 10, 'discount_percentage' => 0, 'tax_rate' => 10, 'description' => 'August retainer']]]),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
const response = await fetch('https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/store', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Basic ' + btoa('your-username:YOUR API KEY'),
  },
  body: JSON.stringify({"module":"deal","entity_id":8,"invoice_date":"2026-08-05","due_date":"2026-08-19","term_key":"net_14","invoice_prefix":"INV","currency":"USD","tax_option":"exclusive","line_items":[{"product_name":"Consulting hours","unit_price":120,"quantity":10,"discount_percentage":0,"tax_rate":10,"description":"August retainer"}]}),
});
const result = await response.json();

Example response — data carries the new invoice’s ID:

{
  "status": "success",
  "message": "Invoice created successfully",
  "code": "SUCCESS",
  "data": { "id": 5 }
}

List invoices

GET /invoices/index — requires capability bit_crm_invoice_view. Parameters go in the query string. Trashed invoices are excluded.

  • page — integer, optional, default 1.
  • perPage — integer, optional, default 10.
  • sortBy — string, optional, default id.
  • sortOrder — asc or desc, optional, default desc.
  • statuses — string, optional. A comma-separated list of statuses to filter by, e.g. sent,overdue.
GET https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/index
  • Bash
  • PHP
  • JavaScript
curl "https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/index?page=1&statuses=sent,overdue" \
  --user "your-username:YOUR API KEY"
$ch = curl_init('https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/index?page=1&statuses=sent,overdue');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERPWD        => 'your-username:YOUR API KEY',
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
const response = await fetch('https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/index?page=1&statuses=sent,overdue', {
  headers: { 'Authorization': 'Basic ' + btoa('your-username:YOUR API KEY') },
});
const result = await response.json();

Example response — a paginated object; each row is an invoice and includes deal_name from the joined deal:

{
  "status": "success",
  "code": "SUCCESS",
  "data": {
    "data": [
      {
        "id": 5,
        "module": "deal",
        "entity_id": 8,
        "invoice_prefix": "INV",
        "invoice_date": "2026-08-05",
        "due_date": "2026-08-19",
        "status": "sent",
        "currency": "USD",
        "amount": "1320.0000",
        "deal_name": "Acme renewal"
      }
    ],
    "pages": 1,
    "total": 1,
    "current_total": 1,
    "current_page": 1,
    "last_page": 1,
    "per_page": 10
  }
}

Retrieve an invoice

GET /invoices/{id} — requires capability bit_crm_invoice_view.

GET https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/5
  • Bash
  • PHP
  • JavaScript
curl "https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/5" \
  --user "your-username:YOUR API KEY"
$ch = curl_init('https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/5');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERPWD        => 'your-username:YOUR API KEY',
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
const response = await fetch('https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/5', {
  headers: { 'Authorization': 'Basic ' + btoa('your-username:YOUR API KEY') },
});
const result = await response.json();

Example response — data bundles the invoice with its deal, the deal’s contact, the line items, and currency data:

{
  "status": "success",
  "code": "SUCCESS",
  "data": {
    "invoice": { "id": 5, "status": "sent", "amount": "1320.0000", "...": "..." },
    "deal": { "id": 8, "name": "Acme renewal", "...": "..." },
    "contact": { "id": 42, "first_name": "Jane", "...": "..." },
    "line_items": [ { "product_name": "Consulting hours", "unit_price": "120.0000", "quantity": 10, "...": "..." } ],
    "currency_data": { "currency": "USD", "...": "..." }
  }
}

Update an invoice

POST /invoices/{id} — requires capability bit_crm_invoice_update. Takes the same fields as Create an invoice except module and entity_id (an invoice cannot move to another deal). Invoices that are paid or partially_paid cannot be updated. An optional status field may be sent and is validated against the transition rules above; for sent/overdue invoices the status is recalculated automatically from the due date, overwriting any status you send other than paid.

  • id — integer, required (also the path parameter).
  • All other fields — same as Create an invoice.
  • status — string, optional. Target status; see Invoice statuses.
POST https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/5
  • Bash
  • PHP
  • JavaScript
curl -X POST "https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/5" \
  --user "your-username:YOUR API KEY" \
  -H "Content-Type: application/json" \
  -d '{"id":5,"invoice_date":"2026-08-05","due_date":"2026-08-26","term_key":"net_14","invoice_prefix":"INV","currency":"USD","tax_option":"exclusive","line_items":[{"product_name":"Consulting hours","unit_price":120,"quantity":10,"discount_percentage":0,"tax_rate":10,"description":"August retainer"}]}'
$ch = curl_init('https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/5');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERPWD        => 'your-username:YOUR API KEY',
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS     => json_encode(['id' => 5, 'invoice_date' => '2026-08-05', 'due_date' => '2026-08-26', 'term_key' => 'net_14', 'invoice_prefix' => 'INV', 'currency' => 'USD', 'tax_option' => 'exclusive', 'line_items' => [['product_name' => 'Consulting hours', 'unit_price' => 120, 'quantity' => 10, 'discount_percentage' => 0, 'tax_rate' => 10, 'description' => 'August retainer']]]),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
const response = await fetch('https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/5', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Basic ' + btoa('your-username:YOUR API KEY'),
  },
  body: JSON.stringify({"id":5,"invoice_date":"2026-08-05","due_date":"2026-08-26","term_key":"net_14","invoice_prefix":"INV","currency":"USD","tax_option":"exclusive","line_items":[{"product_name":"Consulting hours","unit_price":120,"quantity":10,"discount_percentage":0,"tax_rate":10,"description":"August retainer"}]}),
});
const result = await response.json();

Example response — data is null; re-fetch the invoice to see the recalculated amounts:

{
  "status": "success",
  "message": "Invoice updated successfully",
  "code": "SUCCESS",
  "data": null
}

Update an invoice’s status

POST /invoices/{id}/status — requires capability bit_crm_invoice_update. Moves the invoice through its lifecycle without touching any other field. The transition must be allowed (see Invoice statuses); a paid invoice’s status cannot change. Setting sent stamps sent_at; setting paid stamps paid_at.

  • status — string, required. One of draft, sent, overdue, partially_paid, paid.
POST https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/5/status
  • Bash
  • PHP
  • JavaScript
curl -X POST "https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/5/status" \
  --user "your-username:YOUR API KEY" \
  -H "Content-Type: application/json" \
  -d '{"status":"sent"}'
$ch = curl_init('https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/5/status');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERPWD        => 'your-username:YOUR API KEY',
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS     => json_encode(['status' => 'sent']),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
const response = await fetch('https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/5/status', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Basic ' + btoa('your-username:YOUR API KEY'),
  },
  body: JSON.stringify({"status":"sent"}),
});
const result = await response.json();

Example response — note that data is a plain string on this endpoint: "Invoice status updated successfully".

Move invoices to the trash

POST /invoices/trash — requires capability bit_crm_invoice_delete. This is a soft delete: the invoices move to the recycle bin (Settings → Data Management) and can be restored from there.

  • ids — array of integers, required. The invoice IDs to trash.
POST https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/trash
  • Bash
  • PHP
  • JavaScript
curl -X POST "https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/trash" \
  --user "your-username:YOUR API KEY" \
  -H "Content-Type: application/json" \
  -d '{"ids":[5,6]}'
$ch = curl_init('https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/trash');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERPWD        => 'your-username:YOUR API KEY',
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS     => json_encode(['ids' => [5, 6]]),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
const response = await fetch('https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/trash', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Basic ' + btoa('your-username:YOUR API KEY'),
  },
  body: JSON.stringify({"ids":[5,6]}),
});
const result = await response.json();

Example response:

{
  "status": "success",
  "message": "Invoices trashed successfully",
  "code": "SUCCESS",
  "data": []
}

List invoices for a deal

GET /invoices/deals/{id} — requires capability bit_crm_invoice_view. Returns the invoices that belong to one deal; {id} is the deal’s ID. Takes the same pagination and sorting parameters as List invoices in the query string.

GET https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/deals/8
  • Bash
  • PHP
  • JavaScript
curl "https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/deals/8?page=1" \
  --user "your-username:YOUR API KEY"
$ch = curl_init('https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/deals/8?page=1');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERPWD        => 'your-username:YOUR API KEY',
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
const response = await fetch('https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/deals/8?page=1', {
  headers: { 'Authorization': 'Basic ' + btoa('your-username:YOUR API KEY') },
});
const result = await response.json();

Example response — the same paginated shape as List invoices.

Download the invoice PDF

GET /invoices/download — requires capability bit_crm_invoice_view. Unlike every other endpoint, the response is not JSON: the server generates the invoice PDF and streams it back as a file download.

  • id — required, in the query string. The numeric invoice ID (validated as a string).
GET https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/download
  • Bash
  • PHP
  • JavaScript
curl "https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/download?id=5" \
  --user "your-username:YOUR API KEY"
$ch = curl_init('https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/download?id=5');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERPWD        => 'your-username:YOUR API KEY',
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
const response = await fetch('https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/download?id=5', {
  headers: { 'Authorization': 'Basic ' + btoa('your-username:YOUR API KEY') },
});
const result = await response.json();

The response body is the PDF itself, served with a Content-Disposition: attachment header and a file name like invoice-INV-5.pdf. In Bash, add -o invoice.pdf to save it.

Create a share link

POST /invoices/{id}/share-link — requires capability bit_crm_invoice_update. Publishes the invoice and returns a public URL guarded by a per-invoice token — anyone with the link can view the invoice without logging in. Calling the endpoint again returns the same link.

POST https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/5/share-link
  • Bash
  • PHP
  • JavaScript
curl -X POST "https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/5/share-link" \
  --user "your-username:YOUR API KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
$ch = curl_init('https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/5/share-link');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERPWD        => 'your-username:YOUR API KEY',
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS     => '{}',
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
const response = await fetch('https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/invoices/5/share-link', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Basic ' + btoa('your-username:YOUR API KEY'),
  },
  body: JSON.stringify({}),
});
const result = await response.json();

Example response — url is the public invoice page; published is true only when this call changed the invoice’s status to sent/overdue as part of publishing; it is false when no status change was needed — including for paid/partially_paid invoices, which still receive a working link:

{
  "status": "success",
  "code": "SUCCESS",
  "data": {
    "url": "https://your-site.com/bit-crm/invoice?id=5&token=…",
    "published": true
  }
}

Share this Doc

Bit CRM Invoices API Documentation for Developers

Or copy link

CONTENTS

Subscribe

×
Cancel