Contacts
Customers and vendors. Each contact carries optional nested billing + shipping addresses and a list of contact persons.
Resource shape
{
"contact_id": "ct_acme",
"contact_type": "CUSTOMER", // CUSTOMER | VENDOR | BOTH
"contact_name": "Acme Corp",
"display_name": "Acme Corp",
"legal_name": "Acme Industries Pvt Ltd",
"company_name": null,
"gst_no": "27AABCC1234D1Z5",
"gst_treatment": "REGISTERED",
"pan": "AABCC1234D",
"place_of_contact": "IN-MH",
"email": "ap@acme.in",
"phone": "+91 22 1234 5678",
"website": "https://acme.in",
"billing_address": { "address": "5 MG Rd", "city": "Mumbai", "state_code": "IN-MH", "zip": "400001", "country": "India" },
"shipping_address": { … },
"contact_persons": [ { "first_name": "Asha", "email": "asha@acme.in", "is_primary": true } ],
"payment_terms": 30,
"opening_balance": 0,
"credit_limit": null,
"currency_code": "INR",
"status": "ACTIVE",
"created_time": "2026-05-12T08:30:00",
"last_modified_time": "2026-05-12T08:30:00"
}/contactsList contactsAIBooks.contacts.READCursor-paginated. Filters by query string.
Query params
| Param | Type | Notes |
|---|---|---|
per_page | int | 1 – 200. Default 50. |
cursor | string | Opaque cursor from page_context.next_cursor. |
contact_type | string | CUSTOMER / VENDOR / BOTH |
status | string | ACTIVE / INACTIVE |
search | string | Substring match on name, GSTIN, email. |
curl -X GET 'https://api.aibooks.in/api/public/v1/contacts?per_page=50&contact_type=CUSTOMER' \
-H 'Authorization: Bearer aibk_pat_…'/contacts/{contact_id}Get one contactAIBooks.contacts.READGET /contacts/ct_acme
Authorization: Bearer aibk_pat_…
200 OK
{ "code": 0, "message": "success", "contact": { … } }/contactsCreate a contactAIBooks.contacts.CREATEOnly contact_name is required. Nested addresses and contact_persons[] are optional — pass them inline.
POST /contacts
Authorization: Bearer aibk_pat_…
Content-Type: application/json
Idempotency-Key: bf3e1b08-9a4d-…
{
"contact_name": "Acme Corp",
"contact_type": "CUSTOMER",
"gst_treatment": "REGISTERED",
"gst_no": "27AABCC1234D1Z5",
"place_of_contact": "IN-MH",
"billing_address": {
"address": "5 MG Rd",
"city": "Mumbai",
"state_code": "IN-MH",
"zip": "400001"
},
"contact_persons": [
{ "first_name": "Asha", "email": "asha@acme.in", "is_primary": true }
]
}/contacts/{contact_id}Update a contactAIBooks.contacts.UPDATEPartial merge — only the fields you send are touched. Nested objects also partial-merge: { "billing_address": { "zip": "560050" } } only updates the ZIP and leaves city + address line 1 alone. Pass null explicitly to clear a field.
For contact_persons[]: passing the array REPLACES it in full. Each item is matched by contact_person_id if present (update); items without an id are inserted as new rows.
/contacts/{contact_id}/archiveArchive (soft-delete)AIBooks.contacts.UPDATE/contacts/{contact_id}Hard deleteAIBooks.contacts.DELETEHard delete only works for contacts with no posted documents. Use archive otherwise — keeps the contact for history but hides it from autocomplete.