Customers
Manage the contacts you invoice and receive from.
Customers are contacts of the organization. The same records serve as buyers on outgoing invoices and as suppliers on incoming ones (type: buyer, seller, both).
The app shows these types with the organization's own words (default Customer and Supplier; for example Client and Vendor). The words are the terminology option of GET / PATCH /settings/options; the stored and accepted type values never change:
curl -X PATCH "$BASE/settings/options" -H "X-API-KEY: $KEY" -H "Content-Type: application/json" \
-d '{ "terminology": { "buyer": { "singular": "client", "plural": "clients" }, "seller": { "singular": "vendor", "plural": "vendors" } } }'
Words are stored in lower case, up to 30 characters each; a role you leave out keeps its current words, and "terminology": null resets everything. The same option also names received supplier documents in the app: "incoming": { "singular": "bill" } (one of incoming invoice, bill, receipt, purchase invoice).
Fields
| Field | Notes |
|---|---|
name, nameAr, tradingName | Legal name (BT-44), Arabic name for bilingual PDFs, trading name |
type | buyer (default), seller, both |
trn | 15-digit Tax Registration Number (BT-48); validated |
peppolId, peppolSchemeId | Peppol participant id, 0235:<TIN>, where the TIN is the first 10 digits of the TRN; peppolId holds the 10-digit TIN without the prefix and peppolSchemeId is 0235 |
customerNumber | Your reference; generateNumber: true allocates the next number of the customer series |
email, contactName, phone, website | Contact details; email is the default recipient when sending; if it is empty, the contact person with receivesInvoices (primary first) is used |
address | street, additional, city, emirate, postalCode, country (ISO 3166-1 alpha-2, default AE) |
paymentTermsDays, defaultCurrency, notes, isActive | Defaults applied in the editor |
isCompany, legalForm, firstName, lastName | Company (default) with legal form, or natural person |
category | Free-text group, e.g. wholesale |
defaultPriceListId | Price list applied to this customer (see Products) |
peppolVerifiedAt | Set by POST /customers/{id}/verify-peppol when the SML confirms the registration |
Routes
curl "$BASE/customers?keyword=buyer&type=buyer&perPage=50" -H "X-API-KEY: $KEY"
curl -X POST "$BASE/customers" -H "X-API-KEY: $KEY" -H "Content-Type: application/json" \
-d '{ "name": "Buyer LLC", "trn": "100000000000011", "email": "ap@buyer.ae", "address": { "city": "Dubai", "country": "AE" }, "generateNumber": true }'
curl -X PATCH "$BASE/customers/{id}" -H "X-API-KEY: $KEY" -H "Content-Type: application/json" -d '{ "paymentTermsDays": 45 }'
curl -X DELETE "$BASE/customers/{id}" -H "X-API-KEY: $KEY"
Changing trn or name updates the contact's draft and validated invoices; a value set differently on one invoice is kept, and submitted invoices never change.
DELETE removes a contact without invoices; a contact that has invoices is deactivated instead (deactivated: true in the response) so history stays intact. GET /customers/next-number previews the next customer number and GET /customers/verify-number?value= checks one.
POST /customers/import creates up to 500 contacts in one call and returns a per-element result (201 when all succeed, 207 otherwise).
Inline buyers on invoices
When you create an invoice with a buyer object instead of buyer.id, Alya Books matches an existing contact by TRN, then by exact name, and otherwise creates one from the inline data. The customer.created webhook fires in that case as well.
Contact persons and addresses
curl -X POST "$BASE/customers/{id}/contact-persons" -H "X-API-KEY: $KEY" -H "Content-Type: application/json" \
-d '{ "salutation": "Ms", "firstName": "Amal", "lastName": "Hassan", "position": "Finance manager", "email": "amal@buyer.ae", "isPrimary": true }'
curl -X POST "$BASE/customers/{id}/addresses" -H "X-API-KEY: $KEY" -H "Content-Type: application/json" \
-d '{ "kind": "delivery", "label": "Warehouse", "street": "Al Quoz 3", "city": "Dubai", "emirate": "Dubai", "isDefault": true }'
GET, PATCH and DELETE on /customers/{id}/contact-persons/{personId} and /customers/{id}/addresses/{addressId} complete the set. One person per contact is isPrimary; one address per kind (delivery, billing, other) is isDefault. Recurring invoices reference them by contactPersonId (email recipient) and deliveryAddressId (BT-70 to BT-80).
Peppol lookup
GET /customers/peppol-lookup?participantId=0235:1000000000 (a bare 15-digit TRN is accepted and converted to its TIN) validates the format and, when DNS is available, checks the Peppol SML for the participant. The response carries valid, registered (true, false, or null when the check could not run), checked (sml, smk, format-only) and a message. POST /customers/{id}/verify-peppol runs the same check for a customer and stores peppolVerifiedAt on success. In mock ASP mode every well-formed id is reported as registered.