Contacts
Create and manage customers and suppliers.
Contacts represent counterparties in the ledger. They are referenced by invoices, payments, and transactions.
Authentication
All endpoints require a valid API key. See Authentication.
The contact object
{
"id": "cont_17",
"contactType": "customer",
"name": "Acme Corporation",
"company": "Acme Corp Ltd",
"email": "accounts@acme.com",
"phone": "+44 20 7123 4567",
"addressLine1": "123 Business Park",
"addressLine2": "Suite 100",
"city": "London",
"region": "Greater London",
"postalCode": "EC1A 1BB",
"country": "United Kingdom",
"vatNumber": "GB123456789",
"paymentTerms": 30,
"currency": "GBP",
"bankName": null,
"bankSortCode": null,
"bankAccount": null,
"bankIban": null,
"isActive": true,
"notes": "Key client since 2024",
"createdAt": "2026-01-15T10:00:00Z",
"updatedAt": "2026-01-31T14:30:00Z"
}
Contact attributes
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier (e.g., cont_17) |
contactType | string | customer, supplier, or both |
name | string | Contact name |
company | string | Company name (optional) |
email | string | Email address |
phone | string | Phone number |
addressLine1 | string | Address line 1 |
addressLine2 | string | Address line 2 |
city | string | City |
region | string | Region or county |
postalCode | string | Postal code |
country | string | Country |
vatNumber | string | VAT registration number |
paymentTerms | integer | Default payment terms (days) |
currency | string | Default currency (ISO 4217) |
bankName | string | Bank name (suppliers only) |
bankSortCode | string | Sort code (suppliers only) |
bankAccount | string | Account number (suppliers only) |
bankIban | string | IBAN (suppliers only) |
isActive | boolean | Whether the contact is active |
notes | string | Internal notes |
createdAt | string | Creation timestamp (UTC) |
updatedAt | string | Last update timestamp (UTC) |
Create a contact
POST /v1/contacts
curl -X POST https://api.speybooks.com/v1/contacts \
-H "Authorization: Bearer sk_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"contactType": "customer",
"name": "Acme Corporation",
"company": "Acme Corp Ltd",
"email": "accounts@acme.com",
"phone": "+44 20 7123 4567",
"addressLine1": "123 Business Park",
"city": "London",
"postalCode": "EC1A 1BB",
"vatNumber": "GB123456789",
"paymentTerms": 30
}'
Create parameters
| Field | Type | Required | Description |
|---|---|---|---|
contactType | string | Yes | customer, supplier, or both |
name | string | Yes | Contact name (max 200 chars) |
company | string | No | Company name |
email | string | No | Email address |
phone | string | No | Phone number |
addressLine1 | string | No | Address line 1 |
addressLine2 | string | No | Address line 2 |
city | string | No | City |
region | string | No | Region or county |
postalCode | string | No | Postal code |
country | string | No | Defaults to United Kingdom |
vatNumber | string | No | VAT registration number |
paymentTerms | integer | No | Default payment terms (days) |
currency | string | No | Default currency (defaults to GBP) |
bankName | string | No | Bank name |
bankSortCode | string | No | Sort code |
bankAccount | string | No | Account number |
bankIban | string | No | IBAN |
notes | string | No | Internal notes |
Response
{
"success": true,
"data": {
"id": "cont_17",
"contactType": "customer",
"name": "Acme Corporation",
"company": "Acme Corp Ltd",
"email": "accounts@acme.com",
"phone": "+44 20 7123 4567",
"addressLine1": "123 Business Park",
"city": "London",
"postalCode": "EC1A 1BB",
"country": "United Kingdom",
"vatNumber": "GB123456789",
"paymentTerms": 30,
"currency": "GBP",
"isActive": true,
"createdAt": "2026-01-31T10:00:00Z",
"updatedAt": "2026-01-31T10:00:00Z"
}
}
Retrieve a contact
GET /v1/contacts/:id
curl https://api.speybooks.com/v1/contacts/cont_17 \
-H "Authorization: Bearer sk_live_your_api_key"
Response
{
"success": true,
"data": {
"id": "cont_17",
"contactType": "customer",
"name": "Acme Corporation",
"company": "Acme Corp Ltd",
"email": "accounts@acme.com",
"isActive": true,
"createdAt": "2026-01-31T10:00:00Z",
"updatedAt": "2026-01-31T10:00:00Z"
}
}
List contacts
GET /v1/contacts
curl "https://api.speybooks.com/v1/contacts?type=customer&active=true&limit=20" \
-H "Authorization: Bearer sk_live_your_api_key"
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
type | string | — | customer, supplier, or both |
search | string | — | Search by name, company, or email |
active | boolean | true | Filter by active status |
page | integer | 1 | Page number |
limit | integer | 50 | Results per page (max 100) |
Response
{
"success": true,
"data": [
{
"id": "cont_17",
"contactType": "customer",
"name": "Acme Corporation",
"company": "Acme Corp Ltd",
"email": "accounts@acme.com",
"isActive": true
},
{
"id": "cont_18",
"contactType": "customer",
"name": "TechStart Ltd",
"company": null,
"email": "hello@techstart.io",
"isActive": true
}
],
"meta": {
"page": 1,
"limit": 20,
"total": 47,
"hasMore": true
}
}
Update a contact
PUT /v1/contacts/:id
curl -X PUT https://api.speybooks.com/v1/contacts/cont_17 \
-H "Authorization: Bearer sk_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"phone": "+44 20 7123 9999",
"paymentTerms": 14,
"notes": "Updated contact details"
}'
Only provided fields are updated. Unspecified fields are left unchanged.
Response
{
"success": true,
"data": {
"id": "cont_17",
"updatedAt": "2026-01-31T15:00:00Z"
}
}
Delete or deactivate a contact
DELETE /v1/contacts/:id
curl -X DELETE https://api.speybooks.com/v1/contacts/cont_17 \
-H "Authorization: Bearer sk_live_your_api_key"
Deletion rules
- Contacts without linked invoices are deleted
- Contacts with linked invoices are deactivated instead
Deletion is prevented to preserve accounting history.
Response (deleted)
{
"success": true,
"data": {
"deleted": true
}
}
Response (deactivated)
{
"success": true,
"data": {
"deactivated": true,
"message": "Contact deactivated (has linked invoices)"
}
}
Get contact summary
GET /v1/contacts/:id/summary
Returns contact details with a financial summary.
curl https://api.speybooks.com/v1/contacts/cont_17/summary \
-H "Authorization: Bearer sk_live_your_api_key"
Response
{
"success": true,
"data": {
"contact": {
"id": "cont_17",
"contactType": "customer",
"name": "Acme Corporation",
"company": "Acme Corp Ltd",
"email": "accounts@acme.com",
"phone": "+44 20 7123 4567",
"isActive": true
},
"summary": {
"totalInvoices": 12,
"openInvoices": 3,
"totalInvoiced": 2500000,
"outstanding": 450000
}
}
}
Summary fields
| Field | Type | Description |
|---|---|---|
totalInvoices | integer | Total invoices issued |
openInvoices | integer | Unpaid invoices |
totalInvoiced | integer | Total invoiced amount (minor units) |
outstanding | integer | Outstanding balance (minor units) |
Common errors
| Code | HTTP | Description |
|---|---|---|
validation_error | 400 | Missing required field (e.g., name, contactType) |
invalid_id | 400 | Malformed contact ID (expected cont_*) |
not_found | 404 | Contact does not exist or belongs to another organisation |
conflict | 409 | Email already exists for another contact |
Key principles
- Contacts are reference data, not financial records
- Contacts with history are never destroyed
- Deactivation preserves auditability
- Contacts are safe to reference across the ledger
Contacts define who you do business with — transactions define what happens financially.
Amount format
All monetary values are in minor units (pence for GBP). 2500000 = £25,000.00