Added

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

EndpointActionReturnsPermission
POST /api/p/v1.0/customersCreate201 + CustomerWriteResponsecustomer:create
PATCH /api/p/v1.0/customers/{id}Update (partial, RFC 7396 merge)200 + CustomerWriteResponsecustomer:update
DELETE /api/p/v1.0/customers/{id}Soft-delete204customer: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 editsETag / If-Match optimistic 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

FieldValidation
NameRequired. Must not be blank. Maximum 200 characters.
CompanyNumberMaximum 32 characters. Placeholder values are not accepted.
ExternalIdMaximum 100 characters.
StatusMust 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:readGET / search
  • customer:createPOST
  • customer:updatePATCH
  • customer:deleteDELETE

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.