eva crm Public API

Supplier invoices

Add supplier invoices in bulk the way the CRM's grid does, read and update them, and mark them exported — which locks them until unmarked.

A supplier invoice is what the CRM lists under Purchasing → Supplier Invoices: one row per invoice or credit note from a supplier, with the supplier's own number, a date, net, VAT and total, a nominal code and VAT rate, and optionally the purchase order and contract it belongs to. There are no line items and no status. The one state an invoice has is exported: once an accounts export has taken it, it is read-only here until it is unmarked.

GET List suppliers

GET/v1/suppliers

The suppliers you can invoice against, by id or code, with the nominal code and VAT rate an invoice gets when the row leaves them out. Inactive suppliers are listed so you can read their invoices, but cannot be invoiced, as in the CRM. Only suppliers with exportToAccounts are picked up by the CRM's accounts exports. No parameters. Cached for five minutes.

Responses
200
`data`, the suppliers, ordered by code.
Example request
curl https://api.evacrm.co.uk/v1/suppliers \
  -H "Authorization: Bearer sk_..."
Example response · 200
{
  "object": "list",
  "data": [
    {
      "id": "c5c5ea34-994b-4278-8f34-1fb9047cb6fe",
      "code": "EMP",
      "name": "Emplas Windows Systems Ltd",
      "tradingName": null,
      "active": true,
      "onStop": false,
      "exportToAccounts": true,
      "accountsReference": "EMP01",
      "defaults": { "nominalCode": { "code": "000", "name": "None - Use contract nc" }, "vatRate": { "code": "0", "name": "Zero-Rated" } }
    }
  ]
}

GET Reference data

GET/v1/supplier-invoices/types

What the write calls accept: the invoice types, the nominal codes flagged for suppliers, and the VAT rates with the percentage in force today. Send a type by name, value or id; a nominal code by code or id; a VAT rate by code, name or id. No parameters. Cached for five minutes.

Responses
200
`types`, `nominalCodes` and `vatRates`.
Example request
curl https://api.evacrm.co.uk/v1/supplier-invoices/types \
  -H "Authorization: Bearer sk_..."
Example response · 200
{
  "types": [
    { "id": "b96b8164-873e-47c2-aa3e-2c4741d518bf", "name": "Invoice", "value": "invoice", "credit": false },
    { "id": "c8575baa-242e-4e1f-b4ed-7e0a9e64f2e2", "name": "Credit Note", "value": "credit_note", "credit": true }
  ],
  "nominalCodes": [{ "id": "2c4f4109-86c6-4d73-aa28-dc51aa455d9b", "code": "201", "name": "COS - Supply Only - Windows & Doors" }],
  "vatRates": [
    { "id": "79785292-0368-40fd-a119-3ef06abb33e2", "code": "1", "name": "Standard Rates", "percent": 20, "default": true },
    { "id": "f84f5a52-55f3-40cb-921a-2ca8aabc6290", "code": "0", "name": "Zero-Rated", "percent": 0, "default": false }
  ]
}

GET List supplier invoices

GET/v1/supplier-invoices

Newest first, with cursor paging as for leads. A supplier's invoice number is not unique, so lookup by number is a list with supplier and number.

Query parameters
supplierstring · list

One or more suppliers by id or code.

numberstring · max 64

Exact match, case-insensitive.

referencestring · max 255

Exact match, case-insensitive.

typestring · list

One or more types by name, value or id.

creditboolean
exportedboolean
nominalCodestring · list

One or more, by id or code.

vatRatestring · list

One or more, by id, code or name.

purchaseOrderstring

A purchase order's code or id.

contractIdstring · uuid

Invoices on a contract, directly or through its purchase orders.

dateFromstring · date or date-time

Invoice date, from.

dateTostring · date or date-time

Invoice date, to. A date-only value covers that whole day.

dueFromstring · date or date-time

Payment due date, from.

dueTostring · date or date-time

Payment due date, to; date-only covers the day.

exportedFromstring · date or date-time

Exported date, from.

exportedTostring · date or date-time

Exported date, to; date-only covers the day.

createdSincestring · date or date-time
createdBeforestring · date or date-time
updatedSincestring · date or date-time

The way to keep a mirror. Implies order=updatedAt:asc.

orderstring
Valid values: createdAt:desc, createdAt:asc, updatedAt:asc
Default: createdAt:desc
limitinteger · 1 to 100
Default: 50
cursorstring

From a previous nextCursor.

Responses
200
A page of invoices, `hasMore` and `nextCursor`.
422
An unknown parameter, a bad flag or date, or a stale cursor. `fields` names it.
Example request
# everything from one supplier that has not been exported yet
curl "https://api.evacrm.co.uk/v1/supplier-invoices?supplier=EMP&exported=false" \
  -H "Authorization: Bearer sk_..."

# credit notes dated in september
curl "https://api.evacrm.co.uk/v1/supplier-invoices?credit=true&dateFrom=2026-09-01&dateTo=2026-09-30" \
  -H "Authorization: Bearer sk_..."

# a supplier's number — numbers are not unique, so this is a list
curl "https://api.evacrm.co.uk/v1/supplier-invoices?supplier=EMP&number=INV-88812" \
  -H "Authorization: Bearer sk_..."
Example response · 200
{
  "object": "list",
  "data": [
    {
      "id": "e94cc565-b021-46af-bcd7-ced0d70111c2",
      "number": "INV-88812",
      "reference": "INV-88812",
      "detail": "Frames for plot 4",
      "type": { "id": "b96b8164-873e-47c2-aa3e-2c4741d518bf", "name": "Invoice", "value": "invoice" },
      "credit": false,
      "supplier": { "id": "c5c5ea34-994b-4278-8f34-1fb9047cb6fe", "code": "EMP", "name": "Emplas Windows Systems Ltd" },
      "date": "2026-09-02T00:00:00.000+01:00",
      "dateReceived": "2026-09-03T00:00:00.000+01:00",
      "dueDate": "2026-10-02T00:00:00.000+01:00",
      "amounts": { "net": 5638, "vat": 1127.6, "total": 6765.6, "vatPercent": 20 },
      "nominalCode": { "id": "2c4f4109-86c6-4d73-aa28-dc51aa455d9b", "code": "201", "name": "COS - Supply Only - Windows & Doors" },
      "vatRate": { "id": "79785292-0368-40fd-a119-3ef06abb33e2", "code": "1", "name": "Standard Rates" },
      "purchaseOrder": { "id": "ed0a9368-f8c7-45de-ae77-a7ff6129d09b", "code": "PO000116" },
      "contract": { "id": "1553a10d-1150-47e1-86d9-d3323798227e", "code": "CON000561" },
      "exported": false,
      "exportedAt": null,
      "createdBy": { "id": "cd9356b7-dd81-4f9a-a6fd-9cc9ae967a4e", "name": "Tuan Dinh" },
      "createdAt": "2026-09-02T14:45:53.405+01:00",
      "updatedAt": "2026-09-02T14:45:53.405+01:00"
    }
  ],
  "hasMore": false,
  "nextCursor": null
}

amounts.vatPercent is the rate that was applied; vatRate is the band it came from. contract is the one the invoice sits on, directly or through its purchase order, which is how the CRM's profit and loss tab reads it.

GET Get a supplier invoice

GET/v1/supplier-invoices/{id}

One invoice, in the same shape.

Path parameters
idstring · uuidRequired

The invoice's id.

Responses
200
The invoice.
404
No such invoice in your organisation, or the value is not an id.
Example request
curl https://api.evacrm.co.uk/v1/supplier-invoices/e94cc565-b021-46af-bcd7-ced0d70111c2 \
  -H "Authorization: Bearer sk_..."
Example response · 200
{
  "id": "e94cc565-b021-46af-bcd7-ced0d70111c2",
  "number": "INV-88812",
  "reference": "INV-88812",
  "detail": "Frames for plot 4",
  "type": {
    "id": "b96b8164-873e-47c2-aa3e-2c4741d518bf",
    "name": "Invoice",
    "value": "invoice"
  },
  "credit": false,
  "supplier": {
    "id": "c5c5ea34-994b-4278-8f34-1fb9047cb6fe",
    "code": "EMP",
    "name": "Emplas Windows Systems Ltd"
  },
  "date": "2026-09-02T00:00:00.000+01:00",
  "dateReceived": "2026-09-03T00:00:00.000+01:00",
  "dueDate": "2026-10-02T00:00:00.000+01:00",
  "amounts": {
    "net": 5638,
    "vat": 1127.6,
    "total": 6765.6,
    "vatPercent": 20
  },
  "nominalCode": {
    "id": "2c4f4109-86c6-4d73-aa28-dc51aa455d9b",
    "code": "201",
    "name": "COS - Supply Only - Windows & Doors"
  },
  "vatRate": {
    "id": "79785292-0368-40fd-a119-3ef06abb33e2",
    "code": "1",
    "name": "Standard Rates"
  },
  "purchaseOrder": {
    "id": "ed0a9368-f8c7-45de-ae77-a7ff6129d09b",
    "code": "PO000116"
  },
  "contract": {
    "id": "1553a10d-1150-47e1-86d9-d3323798227e",
    "code": "CON000561"
  },
  "exported": false,
  "exportedAt": null,
  "createdBy": {
    "id": "cd9356b7-dd81-4f9a-a6fd-9cc9ae967a4e",
    "name": "Tuan Dinh"
  },
  "createdAt": "2026-09-02T14:45:53.405+01:00",
  "updatedAt": "2026-09-02T14:45:53.405+01:00"
}

POST Add supplier invoices

POST/v1/supplier-invoices

Adds invoices in bulk, exactly as the CRM's Create Supplier Invoice grid does: send up to 200 rows, every row is checked, and either all of them are written or none. VAT is worked out the way the grid does it: the rate on the VAT band in force on the invoice date, applied to the net and rounded to pence, with the total as net plus VAT. Send vat when the supplier's figure differs by a penny or two.

Request bodyapplication/json
invoicesobject[] · 1 to 200Required

The rows, each with the fields below.

forceboolean

Add rows whose supplier and number already exist.

Default: false
Each row
numberstring · max 20Required

The supplier's invoice number.

supplierstring · id or codeRequired

Inactive suppliers are refused.

datestring · date or date-timeRequired

The invoice date.

netnumber · 0 or moreRequired

Credit notes are positive amounts with a credit type.

typestring · name, value or id
Default: the plain invoice type
vatRatestring · id, code or name

A supplier with no default needs one.

Default: the supplier's
vatnumber · 0 or more

The supplier's own VAT figure. Left out, it is worked out from the rate.

nominalCodestring · id or code

A supplier with no default needs one.

Default: the supplier's
referencestring · max 255

The CRM requires one.

Default: the invoice number
detailstring · max 2000
dueDatestring · date or date-time
dateReceivedstring · date or date-time
purchaseOrderstring · code or id

Must belong to the supplier; fills in the contract.

contractIdstring · uuid

The contract, when there is no purchase order to take it from.

Responses
201
`data`, the rows as GET shows them, in the order sent.
422
Something missing or unknown on a row, or a purchase order that belongs to another supplier. `rows` names each row by `index` with its `fields`; nothing was written.
409
A row's supplier already has an invoice with that number. The CRM allows duplicates; the API refuses them so a retried import cannot double up. `rows` names them; send `force: true` to add anyway.
502
The CRM did not answer. Nothing was written; repeat the request.
Example request
curl https://api.evacrm.co.uk/v1/supplier-invoices \
  -H "Authorization: Bearer sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "invoices": [
      { "number": "INV-88812", "supplier": "EMP", "date": "2026-09-02", "net": 5638, "purchaseOrder": "PO000116" },
      { "number": "CN-0091", "supplier": "EMP", "type": "Credit Note", "date": "2026-09-02", "net": 120, "vatRate": "Reduced Rate", "reference": "Damaged sash", "dueDate": "2026-10-02" }
    ]
  }'
Example response · 422
{
  "error": "Some invoices need attention",
  "fields": { "invoices": "1 of 2 row(s) refused, nothing was written — see rows" },
  "rows": [{ "index": 1, "fields": { "supplier": "no supplier with id or code ACME — GET /v1/suppliers lists them" } }]
}

PATCH Update a supplier invoice

PATCH/v1/supplier-invoices/{id}

Changes only the fields sent, with the same fields and lookups as a row above. No field is required; send at least one. null clears detail, dueDate, dateReceived, purchaseOrder and contractId. A change to net, vat, vatRate or date re-derives the VAT and total, unless vat itself is sent.

Path parameters
idstring · uuidRequired

The invoice's id.

Headers
If-Unmodified-Sincestring · date-time

The updatedAt you last saw; a 409 if someone else changed the invoice first.

Request bodyapplication/json — at least one field
numberstring · max 20

The supplier's invoice number.

supplierstring · id or code

Inactive suppliers are refused.

typestring · name, value or id

Changes whether it is a credit note.

datestring · date or date-time

The invoice date. Re-derives the VAT from the rate in force on it.

netnumber · 0 or more

Re-derives the VAT and total.

vatnumber · 0 or more

The supplier's own VAT figure; the total follows.

vatRatestring · id, code or name

Re-derives the VAT and total.

nominalCodestring · id or code
referencestring · max 255
detailstring · max 2000, or null

null clears.

dueDatestring · date or date-time, or null

null clears.

dateReceivedstring · date or date-time, or null

null clears.

purchaseOrderstring · code or id, or null

Must belong to the supplier; fills in the contract. null clears.

contractIdstring · uuid, or null

null clears.

Responses
200
The invoice, updated.
404
No such invoice.
409
The invoice is exported (`fields.exported` says to unmark it first), or `If-Unmodified-Since` is stale.
422
A field is wrong or a lookup failed. `fields` names it.
502
The CRM did not answer. Nothing changed; repeat the request.
Example request
curl -X PATCH https://api.evacrm.co.uk/v1/supplier-invoices/e94cc565-b021-46af-bcd7-ced0d70111c2 \
  -H "Authorization: Bearer sk_..." \
  -H "Content-Type: application/json" \
  -d '{ "net": 5700, "dueDate": "2026-10-09" }'
Example response · 200
{
  "id": "e94cc565-b021-46af-bcd7-ced0d70111c2",
  "number": "INV-88812",
  "reference": "INV-88812",
  "detail": "Frames for plot 4",
  "type": {
    "id": "b96b8164-873e-47c2-aa3e-2c4741d518bf",
    "name": "Invoice",
    "value": "invoice"
  },
  "credit": false,
  "supplier": {
    "id": "c5c5ea34-994b-4278-8f34-1fb9047cb6fe",
    "code": "EMP",
    "name": "Emplas Windows Systems Ltd"
  },
  "date": "2026-09-02T00:00:00.000+01:00",
  "dateReceived": "2026-09-03T00:00:00.000+01:00",
  "dueDate": "2026-10-09T00:00:00.000+01:00",
  "amounts": {
    "net": 5700,
    "vat": 1140,
    "total": 6840,
    "vatPercent": 20
  },
  "nominalCode": {
    "id": "2c4f4109-86c6-4d73-aa28-dc51aa455d9b",
    "code": "201",
    "name": "COS - Supply Only - Windows & Doors"
  },
  "vatRate": {
    "id": "79785292-0368-40fd-a119-3ef06abb33e2",
    "code": "1",
    "name": "Standard Rates"
  },
  "purchaseOrder": {
    "id": "ed0a9368-f8c7-45de-ae77-a7ff6129d09b",
    "code": "PO000116"
  },
  "contract": {
    "id": "1553a10d-1150-47e1-86d9-d3323798227e",
    "code": "CON000561"
  },
  "exported": false,
  "exportedAt": null,
  "createdBy": {
    "id": "cd9356b7-dd81-4f9a-a6fd-9cc9ae967a4e",
    "name": "Tuan Dinh"
  },
  "createdAt": "2026-09-02T14:45:53.405+01:00",
  "updatedAt": "2026-09-03T09:30:12.774+01:00"
}

POST Mark exported

POST/v1/supplier-invoices/{id}/export

Marks the invoice exported. From then on update and delete are refused until it is unmarked. Marking an invoice that is already exported changes nothing and is not an error.

Path parameters
idstring · uuidRequired

The invoice's id.

Request bodyapplication/json, optional
exportedDatestring · date or date-time

When it was exported.

Default: now
Responses
200
`changed`, and `invoice` as GET shows it.
404
No such invoice.
422
`exportedDate` is not a date.
Example request
curl -X POST https://api.evacrm.co.uk/v1/supplier-invoices/e94cc565-b021-46af-bcd7-ced0d70111c2/export \
  -H "Authorization: Bearer sk_..." \
  -H "Content-Type: application/json" \
  -d '{ "exportedDate": "2026-09-15" }'
Example response · 200
{ "changed": true, "invoice": { "id": "e94cc565-…", "exported": true, "exportedAt": "2026-09-15T00:00:00.000+01:00", "…": "…" } }

POST Unmark exported

POST/v1/supplier-invoices/{id}/unexport

Clears the exported flag and date. This is the only way to reopen an exported invoice, so a correction after an export is always two calls: unexport, then update. The CRM's own accounts export will pick the invoice up again on its next run unless it is re-marked. No body.

Path parameters
idstring · uuidRequired

The invoice's id.

Responses
200
`changed`, and `invoice` as GET shows it. `changed: false` when it was not exported.
404
No such invoice.
Example request
curl -X POST https://api.evacrm.co.uk/v1/supplier-invoices/e94cc565-b021-46af-bcd7-ced0d70111c2/unexport \
  -H "Authorization: Bearer sk_..."
Example response · 200
{
  "changed": true,
  "invoice": {
    "id": "e94cc565-b021-46af-bcd7-ced0d70111c2",
    "number": "INV-88812",
    "reference": "INV-88812",
    "detail": "Frames for plot 4",
    "type": {
      "id": "b96b8164-873e-47c2-aa3e-2c4741d518bf",
      "name": "Invoice",
      "value": "invoice"
    },
    "credit": false,
    "supplier": {
      "id": "c5c5ea34-994b-4278-8f34-1fb9047cb6fe",
      "code": "EMP",
      "name": "Emplas Windows Systems Ltd"
    },
    "date": "2026-09-02T00:00:00.000+01:00",
    "dateReceived": "2026-09-03T00:00:00.000+01:00",
    "dueDate": "2026-10-02T00:00:00.000+01:00",
    "amounts": {
      "net": 5638,
      "vat": 1127.6,
      "total": 6765.6,
      "vatPercent": 20
    },
    "nominalCode": {
      "id": "2c4f4109-86c6-4d73-aa28-dc51aa455d9b",
      "code": "201",
      "name": "COS - Supply Only - Windows & Doors"
    },
    "vatRate": {
      "id": "79785292-0368-40fd-a119-3ef06abb33e2",
      "code": "1",
      "name": "Standard Rates"
    },
    "purchaseOrder": {
      "id": "ed0a9368-f8c7-45de-ae77-a7ff6129d09b",
      "code": "PO000116"
    },
    "contract": {
      "id": "1553a10d-1150-47e1-86d9-d3323798227e",
      "code": "CON000561"
    },
    "exported": false,
    "exportedAt": null,
    "createdBy": {
      "id": "cd9356b7-dd81-4f9a-a6fd-9cc9ae967a4e",
      "name": "Tuan Dinh"
    },
    "createdAt": "2026-09-02T14:45:53.405+01:00",
    "updatedAt": "2026-09-03T09:31:05.209+01:00"
  }
}

DEL Delete a supplier invoice

DEL/v1/supplier-invoices/{id}

Removes the invoice.

Path parameters
idstring · uuidRequired

The invoice's id.

Responses
204
Deleted. No body.
404
No such invoice.
409
The invoice is exported; unmark it first.
Example request
curl -X DELETE https://api.evacrm.co.uk/v1/supplier-invoices/e94cc565-b021-46af-bcd7-ced0d70111c2 \
  -H "Authorization: Bearer sk_..."
Example response · 204
HTTP/1.1 204 No Content

On this page