Edara API v3: Customers
Read the guide first: authentication, paging, errors, rate limits and the shared PagedResult, BatchResult and *Reference shapes.
GET /v3/customers: Lists customers.GET /v3/customers/{id}: Gets a customer by id.GET /v3/customers/{id}/addresses: Gets customer addresses by id.GET /v3/customers/{id}/balance: Gets a customer balance by id.GET /v3/customers/{id}/invoiceable-documents: Lists invoiceable source documents for a customer.POST /v3/customers: Creates a customer.POST /v3/customers/batch: Creates customers in batch.POST /v3/customers/find-by-ids: Finds customers by ids.POST /v3/customers/find-by-external-ids: Finds customers by external ids.PUT /v3/customers/{id}: Updates a customer by id.PUT /v3/customers/code/{code}: Updates a customer by code.PUT /v3/customers/batch/by-id: Updates customers in batch by id.PUT /v3/customers/batch/by-name: Updates customers in batch by name.PUT /v3/customers/batch/by-code: Updates customers in batch by code.DELETE /v3/customers/{id}: Deletes a customer by id.DELETE /v3/customers/code/{code}: Deletes a customer by code.PATCH /v3/customers/{id}/deactivate: Deactivates a customer by id.PATCH /v3/customers/code/{code}/deactivate: Deactivates a customer by code.
Endpoints
GET /v3/customers: Lists customers.
Operation GetCustomers · permission read:customer
Query string: GetCustomersQuery
| field | type | default | validation | description |
|---|---|---|---|---|
offset |
int? |
0 | >= 0 | Number of items to skip before returning results. Defaults to 0. |
limit |
int? |
100 | 1..1000 (out of range → 400) | Maximum number of items to return. Defaults to 100, maximum 1000. |
code |
string |
MaximumLength(50) | CONTAINS filter on code. | |
name |
string |
MaximumLength(250) | CONTAINS filter on name. | |
phone |
string |
MaximumLength(50) | CONTAINS filter on primary phone. | |
mobile |
string |
MaximumLength(50) | CONTAINS filter on mobile. | |
email |
string |
MaximumLength(250) | CONTAINS filter on email. | |
externalId |
string |
MaximumLength(50) | CONTAINS filter on external id. | |
updateDate |
DateTime? |
Returns records modified on or after this date (UTC, inclusive). | ||
search |
string |
Free-text search across name/code/phone/mobile/email. Takes precedence over individual filters. |
Responses: OK PagedResult<CustomerResponse>: Paged list of customers.
Notes
- When you send
search, all other filters are ignored andtotalCountis the number of search matches. searchmatches only active customers. By default it looks for the text inside the customer name and the mobile number, compared without spaces, and it does not look at the code or phone.- Organization settings decide which fields
searchlooks at (name, mobile, code, phone) and how each one is matched. The same search can behave differently between organizations, so code defensively. searchreturns at most 50 customers for each field it looks at, which is about 100 in total with the default fields. Further matches are left out without any warning, so do not treat a search result as a complete list.- If the calling user is linked to a sales person,
searchreturns only customers that are unassigned, assigned to that sales person, or assigned to a sales person they supervise. - Results are ordered by customer id, with or without
search. code,name,phoneandemailmatch any part of the stored value.mobilealso matches any part: a plus sign, spaces and a leading 00 are removed from the value you send, and spaces in the stored number are ignored.externalIdis an exact match, not a contains match as its description suggests.updateDatereturns customers created or updated strictly after the value you send, not on or after it. A customer changed at exactly that time is not returned.- Without
search, when you filter bycode,name,phone,mobileoremail, only active customers whose receivable account is also active are returned. With none of these filters (no filter,externalIdonly orupdateDateonly), inactive customers are included too. - Without
search, when an organization setting applies data permissions to customers, the list contains only the customers the calling user is permitted to see. A user with no customer data permissions gets an empty list. - A
namefilter longer than 100 characters or anemailfilter longer than 50 characters is cut to that length before matching. balancein list items is always 0, except whenupdateDateis the only filter. In that case it is calculated for every customer and the request is slow. To read a balance, use GET /v3/customers/{id}/balance.- An empty result returns
200with an emptyitemslist, never404.
GET /v3/customers/{id}: Gets a customer by id.
Operation GetCustomerById · permission read:customer
Parameters
| name | in | type | default | description |
|---|---|---|---|---|
id |
route | int |
The customer id. |
Responses: OK CustomerResponse: The customer.
Notes
- An id that does not exist gives
404. Inactive customers are returned too. balancein this response is always 0. Use GET /v3/customers/{id}/balance for the real balance.- The response includes the customer's addresses.
salesPerson,relatedAccountanddefaultForeignCurrencyare null when they are not set.
GET /v3/customers/{id}/addresses: Gets customer addresses by id.
Operation GetCustomerAddresses · permission read:customer
Parameters
| name | in | type | default | description |
|---|---|---|---|---|
id |
route | int |
The customer id. |
Responses: OK IReadOnlyCollection<CustomerAddressWithLocationResponse>: Customer addresses.
Notes
- A customer id that does not exist gives
404. Inactive customers work the same as active ones. - A customer with no addresses gives
200with an empty array. - Addresses come back in no guaranteed order, so do not rely on their position.
- The country, city and district references on an address are null when the referenced record is not found.
GET /v3/customers/{id}/balance: Gets a customer balance by id.
Operation GetCustomerBalance · permission read:customer
Parameters
| name | in | type | default | description |
|---|---|---|---|---|
id |
route | int |
The customer id. |
Responses: OK decimal: Customer balance.
Notes
- The response body is a bare decimal number, not an object. A customer that does not exist gives
404. - The balance covers all dates and includes both posted and unposted entries.
GET /v3/customers/{id}/invoiceable-documents: Lists invoiceable source documents for a customer.
Operation GetInvoiceableDocuments · permission read:customer
Parameters
| name | in | type | default | description |
|---|---|---|---|---|
id |
route | int |
The customer id. |
Query string: GetInvoiceableDocumentsQuery
| field | type | default | validation | description |
|---|---|---|---|---|
offset |
int? |
0 | >= 0 | Number of items to skip before returning results. Defaults to 0. |
limit |
int? |
100 | 1..1000 (out of range → 400); NotNull(); InclusiveBetween(1, 20) .When(x => x.Limit.HasValue) | Maximum number of items to return. Defaults to 100, maximum 1000. |
documentTypes |
List<string> |
new List |
NotEmpty(); each: Must(type => SupportedDocumentTypes.Contains(type ?? string.Empty)) | The source document types to include. Supported values: SO, SR, IO, RR. |
| (object rule) | private static readonly HashSet |
Responses: OK PagedResult<InvoiceableDocumentResponse>: Paged list of invoiceable documents.
Notes
- A customer that does not exist gives
404. documentTypesmust contain at least one value, and onlySO,SR,IOandRRare accepted. Anything else giveserrorCodeInvalidInvoiceableDocumentType.SOandSRdocuments are listed only while they are not fully invoiced. They must also have passed all approvals or be flagged to create a work order automatically.IOandRRwork orders are listed only when they are not fully invoiced, are not linked to a sales order and were not generated automatically.- For
IOandRR,netTotalis the sum of quantity times value over the lines, divided by the exchange rate. - All types come back in one list, ordered by date and then document code, both descending.
totalCountcounts the whole merged list. - When nothing matches, you get
200with emptyitems.
POST /v3/customers: Creates a customer.
Operation CreateCustomer · permission create:customer
Body: CustomerUpsertRequest
| field | type | default | validation | description |
|---|---|---|---|---|
id |
int? |
Customer id. Required for batch update; ignored on create. | ||
code |
string |
MaximumLength(50) | Business code (max 50). Required on create. | |
name |
string |
NotEmpty().MaximumLength(250) | Display name (max 250). Required on create. | |
customerType |
CustomerType? |
Customer classification. Defaults to Consumer on create. | ||
pricingType |
CustomerPricingType? |
Pricing strategy. | ||
priceListId |
int? |
NotNull() .GreaterThan(0) .When(x => x.PricingType == CustomerPricingType.Custom) | Price list id, used when PricingType is PriceList. |
|
taxRegistrationId |
string |
MaximumLength(20) | Tax registration id (max 20). May be required for business customers. | |
nationalId |
string |
MaximumLength(14) | National identifier (max 14). May be required for consumer customers. | |
shippingTerm |
string |
Shipping terms (e.g. "FOB", "CIF"). | ||
insurance |
string |
Insurance terms or notes. | ||
guarantee |
decimal? |
GreaterThanOrEqualTo(0) .When(x => x.Guarantee.HasValue) | Optional guarantee amount. | |
creditLimit |
decimal? |
GreaterThanOrEqualTo(0) .When(x => x.CreditLimit.HasValue) | Optional credit limit. | |
hasDiscount |
bool? |
Whether line discounts are allowed. | ||
discountMandatory |
bool? |
Whether discount is mandatory. | ||
discountFrom |
decimal? |
GreaterThanOrEqualTo(0) .When(x => x.DiscountFrom.HasValue) | Minimum allowed discount percentage. | |
discountTo |
decimal? |
GreaterThanOrEqualTo(0) .When(x => x.DiscountTo.HasValue) | Maximum allowed discount percentage. | |
paymentType |
CustomerPaymentType? |
Default payment type. | ||
paymentMaxDueDays |
int? |
GreaterThanOrEqualTo(0) .When(x => x.PaymentMaxDueDays.HasValue) | Maximum credit days allowed. | |
relatedAccountId |
int? |
Existing receivable account id. Mutually exclusive with RelatedAccountParentId. |
||
relatedAccountParentId |
int? |
AR parent CoA node under which a new related account is created. Only used when "create AR with new customer" is on. | ||
salesPersonId |
int? |
Optional sales person id assigned to the customer. | ||
defaultForeignCurrencyId |
int? |
Default foreign-currency id. | ||
externalId |
string |
MaximumLength(50) | Optional external id (max 50). Must be unique across customers. | |
active |
bool? |
Whether the customer is active. Defaults to true on create. | ||
contactPerson |
string |
MaximumLength(250) | Primary contact person name. | |
contactCountryId |
int? |
Primary contact country id. | ||
contactCityId |
int? |
Primary contact city id. | ||
contactDistrictId |
int? |
Primary contact district id. | ||
postalZipCode |
string |
MaximumLength(50) | Primary contact postal / ZIP code. | |
phone |
string |
MaximumLength(50) | Primary contact phone (max 50). | |
phone2 |
string |
MaximumLength(50) | Secondary contact phone (max 50). | |
fax |
string |
MaximumLength(50) | Fax number (max 50). | |
mobile |
string |
MaximumLength(50) | Primary contact mobile (max 50). May be required (CustomerMobileRequired). | |
email |
string |
MaximumLength(250) | Primary contact email (max 250). May be required (CustomerEmailRequired). | |
tags |
List<string> |
Customer tags. | ||
addresses |
List<CustomerAddressUpsertRequest> |
each: SetValidator(new CustomerAddressUpsertRequestValidator()) | Customer addresses to create or update. |
Responses: Created CustomerResponse: Customer created.
Business errors (HTTP 409, match on errorCode):
CityNotFound: A city with the specified identifier was not found.CountryNotFound: A country with the specified identifier was not found.CustomerAddressMustContainBuildingNumber: Address must include a building number.CustomerAddressMustHaveDistrict: Address district is required.CustomerAddressRequired: Customer addresses are required.CustomerCodeExists: Another customer already uses the same code.CustomerCodeRequired: Customer code is required.CustomerEmailExists: Another customer already uses the same email.CustomerEmailRequired: Customer email is required.CustomerMobileExists: Another customer already uses the same mobile.CustomerMobileRequired: Customer mobile is required.CustomerNameExists: Another customer already uses the same name.CustomerNationalIDRequired: Customer national identifier is required.DistrictNotFound: A district with the specified identifier was not found.DuplicatedExternalId: Another customer already uses the same external identifier.DupplicatedARAccount: Another customer already uses the same accounting name.DupplicatedName: Another customer already uses the same name.NationalIDExists: Another customer already uses the same national identifier.NationalIDMustBeOfLength: National identifier length is invalid.TaxRegisterationIDExists: Another customer already uses the same tax registration identifier.TaxRegisterationIDMustBeOfLength: Tax registration identifier length is invalid.TaxRegistrationIdRequired: Customer tax registration identifier is required.
Notes
- A
salesPersonIdthat does not exist gives400. - Send at most one default address, because more than one gives
400. If none is marked as default, the first address becomes the default. - Each address's country and city, and its district when you send one, must exist. Otherwise you get
409witherrorCodeCountryNotFound,CityNotFoundorDistrictNotFound. - An address with a blank
nameis named automatically from its country and city, in the form "Country, City". - When omitted,
customerTypedefaults toConsumer,pricingTypetoEndUser,paymentTypetoCashandactiveto true. - How the customer's accounts receivable account is set depends on an organization setting, so handle both cases described in the next two notes.
- If the organization does not create an account for each new customer, the customer is linked to
relatedAccountId, which must be an accounts receivable account, or to the organization's default account for customers. If neither is available, you get400. - If the organization creates an account for each new customer, the new account is created under
relatedAccountParentId, which must be an accounts receivable node with no child nodes. - If the organization generates customer codes automatically, the
codeyou send is replaced with the next generated code. Do not assume the customer keeps thecodeyou sent. - Many checks depend on organization settings: whether the name must be unique, whether mobile, email, code and tax registration id are required or unique, whether an address is required, and how many digits some numbers must have. Code defensively and handle these errors for every organization.
nationalIdmust always be unique, whatever the organization settings.- Special characters are removed from
codeandnamebefore saving, so the stored values can differ from what you sent. pricingTypeCustomneeds a price list, otherwise you geterrorCodeCustomerCustomPricingTypeMustHavePriceList. With any otherpricingType,priceListIdis cleared without an error.- The customer, its addresses, sales person, account and tags are saved together. If anything fails, nothing is created.
- A duplicate name, accounts receivable account or
externalIdgiveserrorCodeDupplicatedName,DupplicatedARAccountorDuplicatedExternalId. Note that the spellings differ. - Create is not idempotent. Sending the same customer twice is stopped only by the uniqueness rules, for example a duplicate
externalId. - Also handle these
errorCodevalues:CustomerCustomPricingTypeMustHavePriceList,CustomerNameRequired,PriceListNotFound,AddressCountryRequiredandAddressCityRequired.
POST /v3/customers/batch: Creates customers in batch.
Operation CreateCustomersBatch · permission create:customer
See
CreateCustomerfor the list of business errors that can be reported per item.
Body: IEnumerable<CustomerUpsertRequest> (JSON array)
| field | type | default | validation | description |
|---|---|---|---|---|
id |
int? |
Customer id. Required for batch update; ignored on create. | ||
code |
string |
MaximumLength(50) | Business code (max 50). Required on create. | |
name |
string |
NotEmpty().MaximumLength(250) | Display name (max 250). Required on create. | |
customerType |
CustomerType? |
Customer classification. Defaults to Consumer on create. | ||
pricingType |
CustomerPricingType? |
Pricing strategy. | ||
priceListId |
int? |
NotNull() .GreaterThan(0) .When(x => x.PricingType == CustomerPricingType.Custom) | Price list id, used when PricingType is PriceList. |
|
taxRegistrationId |
string |
MaximumLength(20) | Tax registration id (max 20). May be required for business customers. | |
nationalId |
string |
MaximumLength(14) | National identifier (max 14). May be required for consumer customers. | |
shippingTerm |
string |
Shipping terms (e.g. "FOB", "CIF"). | ||
insurance |
string |
Insurance terms or notes. | ||
guarantee |
decimal? |
GreaterThanOrEqualTo(0) .When(x => x.Guarantee.HasValue) | Optional guarantee amount. | |
creditLimit |
decimal? |
GreaterThanOrEqualTo(0) .When(x => x.CreditLimit.HasValue) | Optional credit limit. | |
hasDiscount |
bool? |
Whether line discounts are allowed. | ||
discountMandatory |
bool? |
Whether discount is mandatory. | ||
discountFrom |
decimal? |
GreaterThanOrEqualTo(0) .When(x => x.DiscountFrom.HasValue) | Minimum allowed discount percentage. | |
discountTo |
decimal? |
GreaterThanOrEqualTo(0) .When(x => x.DiscountTo.HasValue) | Maximum allowed discount percentage. | |
paymentType |
CustomerPaymentType? |
Default payment type. | ||
paymentMaxDueDays |
int? |
GreaterThanOrEqualTo(0) .When(x => x.PaymentMaxDueDays.HasValue) | Maximum credit days allowed. | |
relatedAccountId |
int? |
Existing receivable account id. Mutually exclusive with RelatedAccountParentId. |
||
relatedAccountParentId |
int? |
AR parent CoA node under which a new related account is created. Only used when "create AR with new customer" is on. | ||
salesPersonId |
int? |
Optional sales person id assigned to the customer. | ||
defaultForeignCurrencyId |
int? |
Default foreign-currency id. | ||
externalId |
string |
MaximumLength(50) | Optional external id (max 50). Must be unique across customers. | |
active |
bool? |
Whether the customer is active. Defaults to true on create. | ||
contactPerson |
string |
MaximumLength(250) | Primary contact person name. | |
contactCountryId |
int? |
Primary contact country id. | ||
contactCityId |
int? |
Primary contact city id. | ||
contactDistrictId |
int? |
Primary contact district id. | ||
postalZipCode |
string |
MaximumLength(50) | Primary contact postal / ZIP code. | |
phone |
string |
MaximumLength(50) | Primary contact phone (max 50). | |
phone2 |
string |
MaximumLength(50) | Secondary contact phone (max 50). | |
fax |
string |
MaximumLength(50) | Fax number (max 50). | |
mobile |
string |
MaximumLength(50) | Primary contact mobile (max 50). May be required (CustomerMobileRequired). | |
email |
string |
MaximumLength(250) | Primary contact email (max 250). May be required (CustomerEmailRequired). | |
tags |
List<string> |
Customer tags. | ||
addresses |
List<CustomerAddressUpsertRequest> |
each: SetValidator(new CustomerAddressUpsertRequestValidator()) | Customer addresses to create or update. |
Responses: OK BatchResult<CustomerResponse>: Batch insert result.
Business errors (HTTP 409, match on errorCode):
CityNotFound: A city with the specified identifier was not found.CountryNotFound: A country with the specified identifier was not found.CustomerAddressMustContainBuildingNumber: Address must include a building number.CustomerAddressMustHaveDistrict: Address district is required.CustomerAddressRequired: Customer addresses are required.CustomerCodeExists: Another customer already uses the same code.CustomerCodeRequired: Customer code is required.CustomerEmailExists: Another customer already uses the same email.CustomerEmailRequired: Customer email is required.CustomerMobileExists: Another customer already uses the same mobile.CustomerMobileRequired: Customer mobile is required.CustomerNameExists: Another customer already uses the same name.CustomerNationalIDRequired: Customer national identifier is required.DistrictNotFound: A district with the specified identifier was not found.DuplicatedExternalId: Another customer already uses the same external identifier.DupplicatedARAccount: Another customer already uses the same accounting name.DupplicatedName: Another customer already uses the same name.NationalIDExists: Another customer already uses the same national identifier.NationalIDMustBeOfLength: National identifier length is invalid.TaxRegisterationIDExists: Another customer already uses the same tax registration identifier.TaxRegisterationIDMustBeOfLength: Tax registration identifier length is invalid.TaxRegistrationIdRequired: Customer tax registration identifier is required.
Notes
- The batch is not atomic. Each customer is created on its own, and a failed item does not stop or undo the others.
- The response is
200even when items fail, so always checkfailed. Each entry is a string in the form "ErrorCode: message". failedis keyed by the item's name, or its code when there is no name, or its id. Two failed items with the same name overwrite each other, so you see only one of them.- An empty body or more than 1000 items gives
400. - An unexpected server error stops the batch with
500, but customers created before it stay created. Check what was created before you retry.
POST /v3/customers/find-by-ids: Finds customers by ids.
Operation FindCustomersByIds · permission read:customer
Body: IEnumerable<int> (JSON array)
Responses: OK IReadOnlyCollection<CustomerResponse>: Matched customers.
Notes
- Ids of 0 or less and duplicate ids are ignored. An empty list gives
200with an empty array, and more than 1000 distinct ids gives400. - Inactive customers are returned too.
- Ids that do not exist are left out without an error, and results come back in no guaranteed order. Match results to your request by
id. balancehere is the current balance of the customer's linked accounts receivable account.
POST /v3/customers/find-by-external-ids: Finds customers by external ids.
Operation FindCustomersByExternalIds · permission read:customer
Body: IEnumerable<string> (JSON array)
Responses: OK IReadOnlyCollection<CustomerResponse>: Matched customers.
Notes
- Values are trimmed, blank values are ignored and duplicates are removed without regard to letter case. An empty list gives
200with an empty array, and more than 1000 values gives400. - Matching is exact on the whole
externalId. Whether letter case matters is not guaranteed, so send each value in the same case you stored it. - Only active customers are returned. A deactivated customer is not found here, although POST /v3/customers/find-by-ids returns it.
- Use this endpoint to look up customers by external id. GET /v3/customers with
externalIdalso matches exactly, but it can return inactive customers. - External ids with no match are left out without an error.
PUT /v3/customers/{id}: Updates a customer by id.
Operation UpdateCustomerById · permission update:customer
Parameters
| name | in | type | default | description |
|---|---|---|---|---|
id |
route | int |
The customer id. |
Body: CustomerUpsertRequest
| field | type | default | validation | description |
|---|---|---|---|---|
id |
int? |
Customer id. Required for batch update; ignored on create. | ||
code |
string |
MaximumLength(50) | Business code (max 50). Required on create. | |
name |
string |
NotEmpty().MaximumLength(250) | Display name (max 250). Required on create. | |
customerType |
CustomerType? |
Customer classification. Defaults to Consumer on create. | ||
pricingType |
CustomerPricingType? |
Pricing strategy. | ||
priceListId |
int? |
NotNull() .GreaterThan(0) .When(x => x.PricingType == CustomerPricingType.Custom) | Price list id, used when PricingType is PriceList. |
|
taxRegistrationId |
string |
MaximumLength(20) | Tax registration id (max 20). May be required for business customers. | |
nationalId |
string |
MaximumLength(14) | National identifier (max 14). May be required for consumer customers. | |
shippingTerm |
string |
Shipping terms (e.g. "FOB", "CIF"). | ||
insurance |
string |
Insurance terms or notes. | ||
guarantee |
decimal? |
GreaterThanOrEqualTo(0) .When(x => x.Guarantee.HasValue) | Optional guarantee amount. | |
creditLimit |
decimal? |
GreaterThanOrEqualTo(0) .When(x => x.CreditLimit.HasValue) | Optional credit limit. | |
hasDiscount |
bool? |
Whether line discounts are allowed. | ||
discountMandatory |
bool? |
Whether discount is mandatory. | ||
discountFrom |
decimal? |
GreaterThanOrEqualTo(0) .When(x => x.DiscountFrom.HasValue) | Minimum allowed discount percentage. | |
discountTo |
decimal? |
GreaterThanOrEqualTo(0) .When(x => x.DiscountTo.HasValue) | Maximum allowed discount percentage. | |
paymentType |
CustomerPaymentType? |
Default payment type. | ||
paymentMaxDueDays |
int? |
GreaterThanOrEqualTo(0) .When(x => x.PaymentMaxDueDays.HasValue) | Maximum credit days allowed. | |
relatedAccountId |
int? |
Existing receivable account id. Mutually exclusive with RelatedAccountParentId. |
||
relatedAccountParentId |
int? |
AR parent CoA node under which a new related account is created. Only used when "create AR with new customer" is on. | ||
salesPersonId |
int? |
Optional sales person id assigned to the customer. | ||
defaultForeignCurrencyId |
int? |
Default foreign-currency id. | ||
externalId |
string |
MaximumLength(50) | Optional external id (max 50). Must be unique across customers. | |
active |
bool? |
Whether the customer is active. Defaults to true on create. | ||
contactPerson |
string |
MaximumLength(250) | Primary contact person name. | |
contactCountryId |
int? |
Primary contact country id. | ||
contactCityId |
int? |
Primary contact city id. | ||
contactDistrictId |
int? |
Primary contact district id. | ||
postalZipCode |
string |
MaximumLength(50) | Primary contact postal / ZIP code. | |
phone |
string |
MaximumLength(50) | Primary contact phone (max 50). | |
phone2 |
string |
MaximumLength(50) | Secondary contact phone (max 50). | |
fax |
string |
MaximumLength(50) | Fax number (max 50). | |
mobile |
string |
MaximumLength(50) | Primary contact mobile (max 50). May be required (CustomerMobileRequired). | |
email |
string |
MaximumLength(250) | Primary contact email (max 250). May be required (CustomerEmailRequired). | |
tags |
List<string> |
Customer tags. | ||
addresses |
List<CustomerAddressUpsertRequest> |
each: SetValidator(new CustomerAddressUpsertRequestValidator()) | Customer addresses to create or update. |
Responses: OK CustomerResponse: The updated customer.
Business errors (HTTP 409, match on errorCode):
CannotDeleteCustomerAddress: An existing customer address cannot be removed because it is referenced by other records.CityNotFound: A city with the specified identifier was not found.CountryNotFound: A country with the specified identifier was not found.CustomerAddressMustContainBuildingNumber: Address must include a building number.CustomerAddressMustHaveDistrict: Address district is required.CustomerAddressRequired: Customer addresses are required.CustomerCodeExists: Another customer already uses the same code.CustomerCodeRequired: Customer code is required.CustomerEmailExists: Another customer already uses the same email.CustomerEmailRequired: Customer email is required.CustomerMobileExists: Another customer already uses the same mobile.CustomerMobileRequired: Customer mobile is required.CustomerNameExists: Another customer already uses the same name.CustomerNationalIDRequired: Customer national identifier is required.CutomerMustHaveSingleDefaultAddress: Customer cannot have more than one default address.DistrictNotFound: A district with the specified identifier was not found.DuplicatedExternalId: Another customer already uses the same external identifier.DupplicatedName: Another customer already uses the same name.NationalIDExists: Another customer already uses the same national identifier.NationalIDMustBeOfLength: National identifier length is invalid.TaxRegisterationIDExists: Another customer already uses the same tax registration identifier.TaxRegisterationIDMustBeOfLength: Tax registration identifier length is invalid.TaxRegistrationIdRequired: Customer tax registration identifier is required.
Notes
- An id that does not exist gives
404. Anidin the body that differs from the id in the URL gives400, and so does asalesPersonIdthat does not exist. - This is a full replace, not a partial update. Fields you omit are cleared or set to 0, including phones, email, tags, contact ids, discounts, credit limit and currency.
- Only
code,customerType,pricingType,paymentTypeandexternalIdkeep their stored values when omitted. If the storedpricingTypeorpaymentTypeis empty, it becomesEndUserorCash. - Because an omitted
externalIdkeeps its stored value, you cannot clear it by leaving it out. - If you omit
active, it is set to true, so an update withoutactivereactivates a deactivated customer. - If you omit
salesPersonId, the customer's sales person is removed. relatedAccountIdandrelatedAccountParentIdare ignored on update.- If the linked accounts receivable account is used only by this customer, its name and active state are updated to match the customer.
- Addresses are the exception to the full replace: omit them or send an empty list and they stay unchanged.
- If none of the addresses you send has an
id, all existing addresses are deleted and the ones you send are added. - If some addresses have an
id, those are updated, the ones without anidare added and existing addresses missing from the request are deleted. An address that is in use cannot be deleted and giveserrorCodeCannotDeleteCustomerAddress. - The same organization-dependent required and unique checks as POST /v3/customers apply.
- On update, any uniqueness conflict gives
errorCodeDupplicatedName, whichever field is duplicated. - A customer must have a single default address. Breaking this rule gives
errorCodeCutomerMustHaveSingleDefaultAddress. - The update is saved completely or not at all.
- Also handle these
errorCodevalues:CustomerHasdefaultWarehouses,CannotDeactivateCustomersWithNonZeroBalance,CustomerCustomPricingTypeMustHavePriceListandPriceListNotFound.
PUT /v3/customers/code/{code}: Updates a customer by code.
Operation UpdateCustomerByCode · permission update:customer
Parameters
| name | in | type | default | description |
|---|---|---|---|---|
code |
route | string |
The customer code. |
Body: CustomerUpsertRequest
| field | type | default | validation | description |
|---|---|---|---|---|
id |
int? |
Customer id. Required for batch update; ignored on create. | ||
code |
string |
MaximumLength(50) | Business code (max 50). Required on create. | |
name |
string |
NotEmpty().MaximumLength(250) | Display name (max 250). Required on create. | |
customerType |
CustomerType? |
Customer classification. Defaults to Consumer on create. | ||
pricingType |
CustomerPricingType? |
Pricing strategy. | ||
priceListId |
int? |
NotNull() .GreaterThan(0) .When(x => x.PricingType == CustomerPricingType.Custom) | Price list id, used when PricingType is PriceList. |
|
taxRegistrationId |
string |
MaximumLength(20) | Tax registration id (max 20). May be required for business customers. | |
nationalId |
string |
MaximumLength(14) | National identifier (max 14). May be required for consumer customers. | |
shippingTerm |
string |
Shipping terms (e.g. "FOB", "CIF"). | ||
insurance |
string |
Insurance terms or notes. | ||
guarantee |
decimal? |
GreaterThanOrEqualTo(0) .When(x => x.Guarantee.HasValue) | Optional guarantee amount. | |
creditLimit |
decimal? |
GreaterThanOrEqualTo(0) .When(x => x.CreditLimit.HasValue) | Optional credit limit. | |
hasDiscount |
bool? |
Whether line discounts are allowed. | ||
discountMandatory |
bool? |
Whether discount is mandatory. | ||
discountFrom |
decimal? |
GreaterThanOrEqualTo(0) .When(x => x.DiscountFrom.HasValue) | Minimum allowed discount percentage. | |
discountTo |
decimal? |
GreaterThanOrEqualTo(0) .When(x => x.DiscountTo.HasValue) | Maximum allowed discount percentage. | |
paymentType |
CustomerPaymentType? |
Default payment type. | ||
paymentMaxDueDays |
int? |
GreaterThanOrEqualTo(0) .When(x => x.PaymentMaxDueDays.HasValue) | Maximum credit days allowed. | |
relatedAccountId |
int? |
Existing receivable account id. Mutually exclusive with RelatedAccountParentId. |
||
relatedAccountParentId |
int? |
AR parent CoA node under which a new related account is created. Only used when "create AR with new customer" is on. | ||
salesPersonId |
int? |
Optional sales person id assigned to the customer. | ||
defaultForeignCurrencyId |
int? |
Default foreign-currency id. | ||
externalId |
string |
MaximumLength(50) | Optional external id (max 50). Must be unique across customers. | |
active |
bool? |
Whether the customer is active. Defaults to true on create. | ||
contactPerson |
string |
MaximumLength(250) | Primary contact person name. | |
contactCountryId |
int? |
Primary contact country id. | ||
contactCityId |
int? |
Primary contact city id. | ||
contactDistrictId |
int? |
Primary contact district id. | ||
postalZipCode |
string |
MaximumLength(50) | Primary contact postal / ZIP code. | |
phone |
string |
MaximumLength(50) | Primary contact phone (max 50). | |
phone2 |
string |
MaximumLength(50) | Secondary contact phone (max 50). | |
fax |
string |
MaximumLength(50) | Fax number (max 50). | |
mobile |
string |
MaximumLength(50) | Primary contact mobile (max 50). May be required (CustomerMobileRequired). | |
email |
string |
MaximumLength(250) | Primary contact email (max 250). May be required (CustomerEmailRequired). | |
tags |
List<string> |
Customer tags. | ||
addresses |
List<CustomerAddressUpsertRequest> |
each: SetValidator(new CustomerAddressUpsertRequestValidator()) | Customer addresses to create or update. |
Responses: OK CustomerResponse: The updated customer.
Business errors (HTTP 409, match on errorCode):
CannotDeleteCustomerAddress: An existing customer address cannot be removed because it is referenced by other records.CityNotFound: A city with the specified identifier was not found.CountryNotFound: A country with the specified identifier was not found.CustomerAddressMustContainBuildingNumber: Address must include a building number.CustomerAddressMustHaveDistrict: Address district is required.CustomerAddressRequired: Customer addresses are required.CustomerCodeExists: Another customer already uses the same code.CustomerCodeRequired: Customer code is required.CustomerEmailExists: Another customer already uses the same email.CustomerEmailRequired: Customer email is required.CustomerMobileExists: Another customer already uses the same mobile.CustomerMobileRequired: Customer mobile is required.CustomerNameExists: Another customer already uses the same name.CustomerNationalIDRequired: Customer national identifier is required.CutomerMustHaveSingleDefaultAddress: Customer cannot have more than one default address.DistrictNotFound: A district with the specified identifier was not found.DuplicatedExternalId: Another customer already uses the same external identifier.DupplicatedName: Another customer already uses the same name.NationalIDExists: Another customer already uses the same national identifier.NationalIDMustBeOfLength: National identifier length is invalid.TaxRegisterationIDExists: Another customer already uses the same tax registration identifier.TaxRegisterationIDMustBeOfLength: Tax registration identifier length is invalid.TaxRegistrationIdRequired: Customer tax registration identifier is required.
Notes
- The
codein the URL is trimmed and always replaces anycodein the body, so you cannot change a customer's code with this endpoint. - The
codemust match exactly, and inactive customers are matched too. Whether letter case matters is not guaranteed, and a code that matches no customer gives404. - If several customers share the same code, only one of them is updated and you cannot choose which. Use PUT /v3/customers/{id} when codes are not unique.
- Everything else works like PUT /v3/customers/{id}: it is a full replace, an omitted
activebecomes true and an omittedsalesPersonIdremoves the sales person.
PUT /v3/customers/batch/by-id: Updates customers in batch by id.
Operation BatchUpdateCustomersById · permission update:customer
Body: IEnumerable<CustomerUpsertRequest> (JSON array)
| field | type | default | validation | description |
|---|---|---|---|---|
id |
int? |
Customer id. Required for batch update; ignored on create. | ||
code |
string |
MaximumLength(50) | Business code (max 50). Required on create. | |
name |
string |
NotEmpty().MaximumLength(250) | Display name (max 250). Required on create. | |
customerType |
CustomerType? |
Customer classification. Defaults to Consumer on create. | ||
pricingType |
CustomerPricingType? |
Pricing strategy. | ||
priceListId |
int? |
NotNull() .GreaterThan(0) .When(x => x.PricingType == CustomerPricingType.Custom) | Price list id, used when PricingType is PriceList. |
|
taxRegistrationId |
string |
MaximumLength(20) | Tax registration id (max 20). May be required for business customers. | |
nationalId |
string |
MaximumLength(14) | National identifier (max 14). May be required for consumer customers. | |
shippingTerm |
string |
Shipping terms (e.g. "FOB", "CIF"). | ||
insurance |
string |
Insurance terms or notes. | ||
guarantee |
decimal? |
GreaterThanOrEqualTo(0) .When(x => x.Guarantee.HasValue) | Optional guarantee amount. | |
creditLimit |
decimal? |
GreaterThanOrEqualTo(0) .When(x => x.CreditLimit.HasValue) | Optional credit limit. | |
hasDiscount |
bool? |
Whether line discounts are allowed. | ||
discountMandatory |
bool? |
Whether discount is mandatory. | ||
discountFrom |
decimal? |
GreaterThanOrEqualTo(0) .When(x => x.DiscountFrom.HasValue) | Minimum allowed discount percentage. | |
discountTo |
decimal? |
GreaterThanOrEqualTo(0) .When(x => x.DiscountTo.HasValue) | Maximum allowed discount percentage. | |
paymentType |
CustomerPaymentType? |
Default payment type. | ||
paymentMaxDueDays |
int? |
GreaterThanOrEqualTo(0) .When(x => x.PaymentMaxDueDays.HasValue) | Maximum credit days allowed. | |
relatedAccountId |
int? |
Existing receivable account id. Mutually exclusive with RelatedAccountParentId. |
||
relatedAccountParentId |
int? |
AR parent CoA node under which a new related account is created. Only used when "create AR with new customer" is on. | ||
salesPersonId |
int? |
Optional sales person id assigned to the customer. | ||
defaultForeignCurrencyId |
int? |
Default foreign-currency id. | ||
externalId |
string |
MaximumLength(50) | Optional external id (max 50). Must be unique across customers. | |
active |
bool? |
Whether the customer is active. Defaults to true on create. | ||
contactPerson |
string |
MaximumLength(250) | Primary contact person name. | |
contactCountryId |
int? |
Primary contact country id. | ||
contactCityId |
int? |
Primary contact city id. | ||
contactDistrictId |
int? |
Primary contact district id. | ||
postalZipCode |
string |
MaximumLength(50) | Primary contact postal / ZIP code. | |
phone |
string |
MaximumLength(50) | Primary contact phone (max 50). | |
phone2 |
string |
MaximumLength(50) | Secondary contact phone (max 50). | |
fax |
string |
MaximumLength(50) | Fax number (max 50). | |
mobile |
string |
MaximumLength(50) | Primary contact mobile (max 50). May be required (CustomerMobileRequired). | |
email |
string |
MaximumLength(250) | Primary contact email (max 250). May be required (CustomerEmailRequired). | |
tags |
List<string> |
Customer tags. | ||
addresses |
List<CustomerAddressUpsertRequest> |
each: SetValidator(new CustomerAddressUpsertRequestValidator()) | Customer addresses to create or update. |
Responses: OK BatchResult<CustomerResponse>: Batch update result.
Business errors (HTTP 409, match on errorCode):
CannotDeleteCustomerAddress: An existing customer address cannot be removed because it is referenced by other records.CityNotFound: A city with the specified identifier was not found.CountryNotFound: A country with the specified identifier was not found.CustomerAddressMustContainBuildingNumber: Address must include a building number.CustomerAddressMustHaveDistrict: Address district is required.CustomerAddressRequired: Customer addresses are required.CustomerCodeExists: Another customer already uses the same code.CustomerCodeRequired: Customer code is required.CustomerEmailExists: Another customer already uses the same email.CustomerEmailRequired: Customer email is required.CustomerMobileExists: Another customer already uses the same mobile.CustomerMobileRequired: Customer mobile is required.CustomerNameExists: Another customer already uses the same name.CustomerNationalIDRequired: Customer national identifier is required.CutomerMustHaveSingleDefaultAddress: Customer cannot have more than one default address.DistrictNotFound: A district with the specified identifier was not found.DuplicatedExternalId: Another customer already uses the same external identifier.DupplicatedName: Another customer already uses the same name.NationalIDExists: Another customer already uses the same national identifier.NationalIDMustBeOfLength: National identifier length is invalid.TaxRegisterationIDExists: Another customer already uses the same tax registration identifier.TaxRegisterationIDMustBeOfLength: Tax registration identifier length is invalid.TaxRegistrationIdRequired: Customer tax registration identifier is required.
Notes
- Each item needs an
idgreater than 0, otherwise that item fails with "Customer Id is required." Each item is then a full replace, exactly like PUT /v3/customers/{id}. - The batch is not atomic. Each item is saved on its own, and failed items are reported in
failed, keyed by id or name, while the rest continue. - The response is
200even when items fail, so always checkfailed. - An empty body or more than 1000 items gives
400. - An unexpected server error stops the batch with
500, but items updated before it stay updated.
PUT /v3/customers/batch/by-name: Updates customers in batch by name.
Operation BatchUpdateCustomersByName · permission update:customer
Body: IEnumerable<CustomerUpsertRequest> (JSON array)
| field | type | default | validation | description |
|---|---|---|---|---|
id |
int? |
Customer id. Required for batch update; ignored on create. | ||
code |
string |
MaximumLength(50) | Business code (max 50). Required on create. | |
name |
string |
NotEmpty().MaximumLength(250) | Display name (max 250). Required on create. | |
customerType |
CustomerType? |
Customer classification. Defaults to Consumer on create. | ||
pricingType |
CustomerPricingType? |
Pricing strategy. | ||
priceListId |
int? |
NotNull() .GreaterThan(0) .When(x => x.PricingType == CustomerPricingType.Custom) | Price list id, used when PricingType is PriceList. |
|
taxRegistrationId |
string |
MaximumLength(20) | Tax registration id (max 20). May be required for business customers. | |
nationalId |
string |
MaximumLength(14) | National identifier (max 14). May be required for consumer customers. | |
shippingTerm |
string |
Shipping terms (e.g. "FOB", "CIF"). | ||
insurance |
string |
Insurance terms or notes. | ||
guarantee |
decimal? |
GreaterThanOrEqualTo(0) .When(x => x.Guarantee.HasValue) | Optional guarantee amount. | |
creditLimit |
decimal? |
GreaterThanOrEqualTo(0) .When(x => x.CreditLimit.HasValue) | Optional credit limit. | |
hasDiscount |
bool? |
Whether line discounts are allowed. | ||
discountMandatory |
bool? |
Whether discount is mandatory. | ||
discountFrom |
decimal? |
GreaterThanOrEqualTo(0) .When(x => x.DiscountFrom.HasValue) | Minimum allowed discount percentage. | |
discountTo |
decimal? |
GreaterThanOrEqualTo(0) .When(x => x.DiscountTo.HasValue) | Maximum allowed discount percentage. | |
paymentType |
CustomerPaymentType? |
Default payment type. | ||
paymentMaxDueDays |
int? |
GreaterThanOrEqualTo(0) .When(x => x.PaymentMaxDueDays.HasValue) | Maximum credit days allowed. | |
relatedAccountId |
int? |
Existing receivable account id. Mutually exclusive with RelatedAccountParentId. |
||
relatedAccountParentId |
int? |
AR parent CoA node under which a new related account is created. Only used when "create AR with new customer" is on. | ||
salesPersonId |
int? |
Optional sales person id assigned to the customer. | ||
defaultForeignCurrencyId |
int? |
Default foreign-currency id. | ||
externalId |
string |
MaximumLength(50) | Optional external id (max 50). Must be unique across customers. | |
active |
bool? |
Whether the customer is active. Defaults to true on create. | ||
contactPerson |
string |
MaximumLength(250) | Primary contact person name. | |
contactCountryId |
int? |
Primary contact country id. | ||
contactCityId |
int? |
Primary contact city id. | ||
contactDistrictId |
int? |
Primary contact district id. | ||
postalZipCode |
string |
MaximumLength(50) | Primary contact postal / ZIP code. | |
phone |
string |
MaximumLength(50) | Primary contact phone (max 50). | |
phone2 |
string |
MaximumLength(50) | Secondary contact phone (max 50). | |
fax |
string |
MaximumLength(50) | Fax number (max 50). | |
mobile |
string |
MaximumLength(50) | Primary contact mobile (max 50). May be required (CustomerMobileRequired). | |
email |
string |
MaximumLength(250) | Primary contact email (max 250). May be required (CustomerEmailRequired). | |
tags |
List<string> |
Customer tags. | ||
addresses |
List<CustomerAddressUpsertRequest> |
each: SetValidator(new CustomerAddressUpsertRequestValidator()) | Customer addresses to create or update. |
Responses: OK BatchResult<CustomerResponse>: Batch update result.
Business errors (HTTP 409, match on errorCode):
CannotDeleteCustomerAddress: An existing customer address cannot be removed because it is referenced by other records.CityNotFound: A city with the specified identifier was not found.CountryNotFound: A country with the specified identifier was not found.CustomerAddressMustContainBuildingNumber: Address must include a building number.CustomerAddressMustHaveDistrict: Address district is required.CustomerAddressRequired: Customer addresses are required.CustomerCodeExists: Another customer already uses the same code.CustomerCodeRequired: Customer code is required.CustomerEmailExists: Another customer already uses the same email.CustomerEmailRequired: Customer email is required.CustomerMobileExists: Another customer already uses the same mobile.CustomerMobileRequired: Customer mobile is required.CustomerNameExists: Another customer already uses the same name.CustomerNationalIDRequired: Customer national identifier is required.CutomerMustHaveSingleDefaultAddress: Customer cannot have more than one default address.DistrictNotFound: A district with the specified identifier was not found.DuplicatedExternalId: Another customer already uses the same external identifier.DupplicatedName: Another customer already uses the same name.NationalIDExists: Another customer already uses the same national identifier.NationalIDMustBeOfLength: National identifier length is invalid.TaxRegisterationIDExists: Another customer already uses the same tax registration identifier.TaxRegisterationIDMustBeOfLength: Tax registration identifier length is invalid.TaxRegistrationIdRequired: Customer tax registration identifier is required.
Notes
- Each item is matched by
name, which is trimmed and compared exactly. Inactive customers are matched too. - Because
nameis the key, you cannot rename a customer with this endpoint. - If several customers share the same name, only one of them is updated and you cannot choose which.
- Each matched item is a full replace, exactly like PUT /v3/customers/{id}.
- The batch is not atomic and takes at most 1000 items. Failed items are reported in
failed, keyed by name, and the response is200even when items fail.
PUT /v3/customers/batch/by-code: Updates customers in batch by code.
Operation BatchUpdateCustomersByCode · permission update:customer
Body: IEnumerable<CustomerUpsertRequest> (JSON array)
| field | type | default | validation | description |
|---|---|---|---|---|
id |
int? |
Customer id. Required for batch update; ignored on create. | ||
code |
string |
MaximumLength(50) | Business code (max 50). Required on create. | |
name |
string |
NotEmpty().MaximumLength(250) | Display name (max 250). Required on create. | |
customerType |
CustomerType? |
Customer classification. Defaults to Consumer on create. | ||
pricingType |
CustomerPricingType? |
Pricing strategy. | ||
priceListId |
int? |
NotNull() .GreaterThan(0) .When(x => x.PricingType == CustomerPricingType.Custom) | Price list id, used when PricingType is PriceList. |
|
taxRegistrationId |
string |
MaximumLength(20) | Tax registration id (max 20). May be required for business customers. | |
nationalId |
string |
MaximumLength(14) | National identifier (max 14). May be required for consumer customers. | |
shippingTerm |
string |
Shipping terms (e.g. "FOB", "CIF"). | ||
insurance |
string |
Insurance terms or notes. | ||
guarantee |
decimal? |
GreaterThanOrEqualTo(0) .When(x => x.Guarantee.HasValue) | Optional guarantee amount. | |
creditLimit |
decimal? |
GreaterThanOrEqualTo(0) .When(x => x.CreditLimit.HasValue) | Optional credit limit. | |
hasDiscount |
bool? |
Whether line discounts are allowed. | ||
discountMandatory |
bool? |
Whether discount is mandatory. | ||
discountFrom |
decimal? |
GreaterThanOrEqualTo(0) .When(x => x.DiscountFrom.HasValue) | Minimum allowed discount percentage. | |
discountTo |
decimal? |
GreaterThanOrEqualTo(0) .When(x => x.DiscountTo.HasValue) | Maximum allowed discount percentage. | |
paymentType |
CustomerPaymentType? |
Default payment type. | ||
paymentMaxDueDays |
int? |
GreaterThanOrEqualTo(0) .When(x => x.PaymentMaxDueDays.HasValue) | Maximum credit days allowed. | |
relatedAccountId |
int? |
Existing receivable account id. Mutually exclusive with RelatedAccountParentId. |
||
relatedAccountParentId |
int? |
AR parent CoA node under which a new related account is created. Only used when "create AR with new customer" is on. | ||
salesPersonId |
int? |
Optional sales person id assigned to the customer. | ||
defaultForeignCurrencyId |
int? |
Default foreign-currency id. | ||
externalId |
string |
MaximumLength(50) | Optional external id (max 50). Must be unique across customers. | |
active |
bool? |
Whether the customer is active. Defaults to true on create. | ||
contactPerson |
string |
MaximumLength(250) | Primary contact person name. | |
contactCountryId |
int? |
Primary contact country id. | ||
contactCityId |
int? |
Primary contact city id. | ||
contactDistrictId |
int? |
Primary contact district id. | ||
postalZipCode |
string |
MaximumLength(50) | Primary contact postal / ZIP code. | |
phone |
string |
MaximumLength(50) | Primary contact phone (max 50). | |
phone2 |
string |
MaximumLength(50) | Secondary contact phone (max 50). | |
fax |
string |
MaximumLength(50) | Fax number (max 50). | |
mobile |
string |
MaximumLength(50) | Primary contact mobile (max 50). May be required (CustomerMobileRequired). | |
email |
string |
MaximumLength(250) | Primary contact email (max 250). May be required (CustomerEmailRequired). | |
tags |
List<string> |
Customer tags. | ||
addresses |
List<CustomerAddressUpsertRequest> |
each: SetValidator(new CustomerAddressUpsertRequestValidator()) | Customer addresses to create or update. |
Responses: OK BatchResult<CustomerResponse>: Batch update result.
Business errors (HTTP 409, match on errorCode):
CannotDeleteCustomerAddress: An existing customer address cannot be removed because it is referenced by other records.CityNotFound: A city with the specified identifier was not found.CountryNotFound: A country with the specified identifier was not found.CustomerAddressMustContainBuildingNumber: Address must include a building number.CustomerAddressMustHaveDistrict: Address district is required.CustomerAddressRequired: Customer addresses are required.CustomerCodeExists: Another customer already uses the same code.CustomerCodeRequired: Customer code is required.CustomerEmailExists: Another customer already uses the same email.CustomerEmailRequired: Customer email is required.CustomerMobileExists: Another customer already uses the same mobile.CustomerMobileRequired: Customer mobile is required.CustomerNameExists: Another customer already uses the same name.CustomerNationalIDRequired: Customer national identifier is required.CutomerMustHaveSingleDefaultAddress: Customer cannot have more than one default address.DistrictNotFound: A district with the specified identifier was not found.DuplicatedExternalId: Another customer already uses the same external identifier.DupplicatedName: Another customer already uses the same name.NationalIDExists: Another customer already uses the same national identifier.NationalIDMustBeOfLength: National identifier length is invalid.TaxRegisterationIDExists: Another customer already uses the same tax registration identifier.TaxRegisterationIDMustBeOfLength: Tax registration identifier length is invalid.TaxRegistrationIdRequired: Customer tax registration identifier is required.
Notes
- Each item is matched by
code, which is trimmed and compared exactly. Inactive customers are matched too. - An item without
codefails with "Customer Code is required." - Each matched item is a full replace, exactly like PUT /v3/customers/{id}.
- The batch is not atomic and takes at most 1000 items. Failed items are reported in
failed, keyed by code or name, and the response is200even when items fail.
DELETE /v3/customers/{id}: Deletes a customer by id.
Operation DeleteCustomerById · permission delete:customer
Parameters
| name | in | type | default | description |
|---|---|---|---|---|
id |
route | int |
The customer id. |
Responses: NoContent: (not declared; read from the method body)
Business errors (HTTP 409, match on errorCode):
ItemCannotDeleteItInUse: The customer is referenced by existing documents or related records.
Notes
- This permanently deletes the customer and all its addresses. An id that does not exist gives
404. - The customer's linked accounts receivable account is deleted too when no other customer uses it.
- A customer that is used elsewhere, for example on documents, cannot be deleted. You get
409witherrorCodeItemCannotDeleteItInUseand nothing is deleted, so deactivate customers that have history instead.
DELETE /v3/customers/code/{code}: Deletes a customer by code.
Operation DeleteCustomerByCode · permission delete:customer
Parameters
| name | in | type | default | description |
|---|---|---|---|---|
code |
route | string |
The customer code. |
Responses: NoContent: (not declared; read from the method body)
Business errors (HTTP 409, match on errorCode):
ItemCannotDeleteItInUse: The customer is referenced by existing documents or related records.
Notes
- The
codeis trimmed and must match exactly, and inactive customers are matched too. A code that matches no customer gives404. - After the lookup, this behaves exactly like DELETE /v3/customers/{id}: the customer is permanently deleted.
PATCH /v3/customers/{id}/deactivate: Deactivates a customer by id.
Operation DeactivateCustomerById · permission update:customer-status
Parameters
| name | in | type | default | description |
|---|---|---|---|---|
id |
route | int |
The customer id. |
Responses: OK: Customer deactivated.
Notes
- An
idof 0 or less gives400, and an id that does not exist gives404. Success returns200with the updated customer. - Deactivation is refused with
409anderrorCodeCannotDeactivateCustomersWithNonZeroBalanceonly when the balance is greater than 0. A customer with a negative (credit) balance can be deactivated. - Deactivating does not change the customer's update date, so GET /v3/customers filtered by
updateDatedoes not pick it up. - The customer's linked accounts receivable account stays active.
- The balance check runs on every call, so repeating the call on an inactive customer succeeds only while the balance is 0 or less.
- There is no reactivate endpoint. To reactivate a customer, update it with PUT, where an omitted
activebecomes true.
PATCH /v3/customers/code/{code}/deactivate: Deactivates a customer by code.
Operation DeactivateCustomerByCode · permission update:customer-status
Parameters
| name | in | type | default | description |
|---|---|---|---|---|
code |
route | string |
The customer code. |
Responses: OK: Customer deactivated.
Notes
- The
codeis trimmed and must match exactly, and inactive customers are matched too. A code that matches no customer gives404. - After the lookup, this behaves exactly like PATCH /v3/customers/{id}/deactivate: a balance greater than 0 blocks it, only the active state changes.
Types
AccountReference
Lightweight account reference (id + code + name).
| field | type | description |
|---|---|---|
id |
int |
The account id. |
code |
string |
The account code. |
name |
string |
The account name. |
CityReference
Lightweight city reference (id + name).
| field | type | description |
|---|---|---|
id |
int |
The city id. |
name |
string |
The city name. |
CountryReference
Lightweight country reference (id + name).
| field | type | description |
|---|---|---|
id |
int |
The country id. |
name |
string |
The country name. |
CurrencyReference
Lightweight currency reference (id + ISO code + name).
| field | type | description |
|---|---|---|
id |
int |
The currency id. |
code |
string |
The ISO 4217 currency code. |
name |
string |
The currency name. |
CustomerAddressResponse
Response describing a customer address.
| field | type | description |
|---|---|---|
id |
int |
Address identifier. |
customerId |
int |
Owning customer identifier. |
name |
string |
Address label. |
countryId |
int |
Country identifier. |
cityId |
int |
City identifier. |
districtId |
int? |
District identifier, if any. |
streetDescription |
string |
Street description (building number, floor, etc.). |
description |
string |
Full printable address description. |
isDefault |
bool |
Indicates whether this is the default address. |
addressPhone |
string |
Address phone number. |
externalId |
string |
External identifier for the address. |
CustomerAddressUpsertRequest
Request to create or update a customer address.
| field | type | validation | description |
|---|---|---|---|
id |
int? |
Existing address id. Null on create; required on update. Addresses absent from the request are deleted. | |
name |
string |
MaximumLength(250) | Address label. Defaults to "{Country}, {City}" when empty. |
countryId |
int? |
NotNull() | Country identifier. Required. |
cityId |
int? |
NotNull() | City identifier. Required. |
districtId |
int? |
Optional district identifier. | |
streetDescription |
string |
MaximumLength(500) | Free-form street description. |
isDefault |
bool |
Whether this is the customer's default address. Only one per customer; first is promoted if none set. | |
addressPhone |
string |
MaximumLength(50) | Optional address phone number. |
externalId |
string |
MaximumLength(50) | Optional external identifier. |
CustomerAddressWithLocationResponse
Response describing a customer address, including resolved location names.
| field | type | description |
|---|---|---|
id |
int |
Address identifier. |
customerId |
int |
Owning customer identifier. |
name |
string |
Address label. |
country |
CountryReference |
Country reference. |
city |
CityReference |
City reference. |
district |
DistrictReference |
District reference, if any. |
streetDescription |
string |
Street description (building number, floor, etc.). |
description |
string |
Full printable address description. |
isDefault |
bool |
Indicates whether this is the default address. |
addressPhone |
string |
Address phone number. |
externalId |
string |
External identifier for the address. |
CustomerPaymentType
Customer default payment method.
Values (sent/returned as the name): Cash=0, Credit=1
CustomerPricingType
Customer pricing tier.
Values (sent/returned as the name): EndUser=0, Dealer=1, SuperDealer=2, Custom=3
CustomerResponse
Response describing a customer.
| field | type | description |
|---|---|---|
id |
int |
Customer identifier. |
code |
string |
Customer business code. |
name |
string |
Customer display name. |
customerType |
CustomerType? |
Customer classification (Business / Consumer). |
pricingType |
CustomerPricingType? |
Pricing strategy. |
priceListId |
int? |
Identifier of the price list linked to this customer. |
nationalId |
string |
National identifier. |
taxRegistrationId |
string |
Tax registration identifier. |
shippingTerm |
string |
Shipping terms applicable to the customer. |
insurance |
string |
Insurance terms or notes. |
guarantee |
decimal? |
Guarantee amount. |
creditLimit |
decimal? |
Credit limit value. |
hasDiscount |
bool? |
Indicates whether discounts are allowed. |
discountMandatory |
bool? |
Indicates whether a discount is mandatory. |
discountFrom |
decimal? |
Minimum discount percentage. |
discountTo |
decimal? |
Maximum discount percentage. |
paymentType |
CustomerPaymentType? |
Default payment type. |
paymentMaxDueDays |
int? |
Maximum number of credit days allowed. |
relatedAccount |
AccountReference |
Reference to the linked receivable account. |
salesPerson |
SalesPersonReference |
Reference to the assigned sales person, if any. |
defaultForeignCurrency |
CurrencyReference |
Default foreign currency reference, if any. |
balance |
decimal? |
Current customer balance (read-only). |
active |
bool? |
Indicates whether the customer is active. |
externalId |
string |
External identifier. |
contactPerson |
string |
Name of the primary contact person at the customer. |
contactCountryId |
int? |
Country identifier of the primary contact address. |
contactCityId |
int? |
City identifier of the primary contact address. |
contactDistrictId |
int? |
District identifier of the primary contact address. |
postalZipCode |
string |
Postal / ZIP code for the primary contact address. |
phone |
string |
Primary contact phone number. |
phone2 |
string |
Secondary contact phone number. |
fax |
string |
Fax number. |
mobile |
string |
Primary contact mobile number. |
email |
string |
Primary contact email. |
tags |
List<string> |
Tags associated with the customer. |
addresses |
List<CustomerAddressResponse> |
Customer addresses. |
CustomerType
Customer classification type.
Values (sent/returned as the name): Consumer=0, Business=1
DistrictReference
Lightweight district reference (id + name).
| field | type | description |
|---|---|---|
id |
int |
The district id. |
name |
string |
The district name. |
InvoiceableDocumentResponse
Response describing an invoiceable source document header (SO/SR/IO/RR).
| field | type | description |
|---|---|---|
code |
string |
The source document code. |
type |
string |
The source document type. |
date |
DateTime |
The document date. |
customer |
string |
The customer name. |
currency |
string |
The document currency code. |
netTotal |
decimal |
The document net total. For IO/RR this is computed from Warehouse.WHWorkOrderDetails (SUM(Quantity * Value)). |
SalesPersonReference
Lightweight sales-person reference (id + code + name).
| field | type | description |
|---|---|---|
id |
int |
The sales-person id. |
code |
string |
The sales-person code. |
name |
string |
The sales-person name. |