Public API: Customer write endpoints (create, update, delete)
The Public API now supports writes on the Customer resource. Partners can create new customers, update existing ones, and soft-delete them directly through the API — no more read-only ceiling.
This release is purely additive. The existing GET reads and POST /api/p/v1.0/customers/search are unchanged.
What's new
| Endpoint | Action | Returns | Permission |
|---|---|---|---|
POST /api/p/v1.0/customers | Create | 201 + CustomerWriteResponse | customer:create |
PATCH /api/p/v1.0/customers/{id} | Update (partial, RFC 7396 merge) | 200 + CustomerWriteResponse | customer:update |
DELETE /api/p/v1.0/customers/{id} | Soft-delete | 204 | customer:delete |
Applies to both business-company types: Customer and Broker/3PL.
Why it matters
- Real-time CRM sync — push customer records straight into Alvys from your TMS, ERP, or CRM instead of entering them by hand.
- Conflict-safe edits —
ETag/If-Matchoptimistic concurrency means two concurrent edits never silently overwrite each other.
Create
POST /api/p/v1.0/customers
Authorization: Bearer <token with customer:create>
Content-Type: application/json
{
"Name": "Acme Logistics",
"Type": "Customer",
"CompanyNumber": "ACME-1",
"Status": "Active",
"BillingAddress": { "Street": "1 Main", "City": "City", "State": "NY", "Zip": "10001" },
"Email": ["[email protected]"],
"Phone": ["555-1234"]
}Returns 201 Created with a Response body. The ETag is returned both in the body and on the response header. Name and Type are required on create; Type must be Customer or Broker/3PL.
Update (partial)
PATCH /api/p/v1.0/customers/{id}
Authorization: Bearer <token with customer:update>
If-Match: "etag-from-prior-read"
{ "Status": "Inactive" }Returns 200 OK. PATCH is a true partial update (RFC 7396 JSON Merge Patch) — omit any field to leave it unchanged.
Delete
DELETE /api/p/v1.0/customers/{id}
Authorization: Bearer <token with customer:delete>
If-Match: "etag-from-prior-read"Returns 204 No Content. The record moves to Status: Inactive (soft-delete) and its CompanyNumber stays reserved to prevent reuse.
Supported writable fields
The following fields can be created or updated through the Customer write endpoints:
Name, Type, CompanyNumber, Status, BillingAddress, Email, Phone, Fax, ExternalId.
All other fields are read-only or managed by Alvys, including SalesAgentId, Contacts, Notes, InvoicingInformation, Id, DateCreated, and DateModified.
Unsupported or read-only fields included in the request body are ignored.
Field validation
| Field | Validation |
|---|---|
Name | Required. Must not be blank. Maximum 200 characters. |
CompanyNumber | Maximum 32 characters. Placeholder values are not accepted. |
ExternalId | Maximum 100 characters. |
Status | Must be Active or Inactive. |
Request behavior
PATCH and DELETE require the If-Match header.
If If-Match is missing, the API returns 428 Precondition Required. If the ETag is outdated, the API returns 412 Precondition Failed. Retrieve the customer again to get the latest ETag, then retry.
Duplicate CompanyNumber, ExternalId, or Name + billing ZIP code returns 409 Conflict. The response identifies the conflicting field and existing customerId.
If customer writes are temporarily unavailable, the API returns 503 Service Unavailable with Retry-After: 3600 and the EndpointDisabled problem type. Customer read endpoints remain available.
Write and read responses
Successful POST and PATCH requests return CustomerWriteResponse.
The write response includes:
Id, ETag, Name, CompanyNumber, Type, Status, BillingAddress, Email, Phone, Fax, DateCreated, DateModified, InvoicingInformation, ExternalId.
For write responses, ETag is returned in both the response body and response header.
Existing GET and search endpoints are unchanged. They continue to return CustomerResponse, with Status as Active or Inactive and ETag in the response header only.
Access
Use your existing Client Credentials and add the scopes you need:
customer:read—GET/searchcustomer:create—POSTcustomer:update—PATCHcustomer:delete—DELETE
No new credential or OAuth client is required. Scopes are granted per Client Credentials in API management.
FAQ
Do I need a new credential or OAuth client?
No. Your existing Client Credentials works — just add the customer:create / customer:update / customer:delete scopes you need. customer:read is unchanged.
How do I get the ETag for an update or delete?
It's returned on the response header of any GET, POST, or PATCH, and additionally in the body of POST / PATCH. Use it as If-Match on your next mutation. On a 412, re-GET for the fresh value.
What happens if two callers update the same customer at once?
The first PATCH wins (200); the second sees a stale If-Match and gets 412. Re-GET, reapply, retry. No silent overwrite.
Does DELETE actually remove the record?
No — it's a soft-delete. Status goes to Inactive and the CompanyNumber stays reserved (a duplicate POST with that number returns 409). To restore, PATCH with { "Status": "Active" }.
What happens if I send an unsupported field like Notes in the body?
It's silently ignored. Only the writable fields listed above are applied.
Does this change the existing GET or search response shape?
No. The read surface is unchanged; this release is purely additive.
When do I see 404 vs 412?
404 = the id does not exist in your tenant (ids in another tenant also return 404). 412 = the id exists in your tenant but your If-Match is stale — re-GET for the current ETag.