Skip to main content

The API

Hosthttps://business-partner-api.retailsvc.com
Base path/api/v1
Writes answer202 Accepted, with an empty body

The authoritative technical reference is the OpenAPI specification. This page covers what the specification cannot tell you.

EndpointDoesPermission
PUT /business-partners/{businessPartnerId}creates or replaces a partnerbpa.business-partner.write
DELETE /business-partners/{businessPartnerId}marks a partner Deletedbpa.business-partner.write
GET /business-partners/{businessPartnerId}reads one partnerbpa.business-partner.read
GET /business-partnerslists partners, filtered and pagedbpa.business-partner.read
PUT /warehouse-supply-terms/{businessUnitId}sets a warehouse's supply termsbpa.business-partner.write, for that business unit
DELETE /warehouse-supply-terms/{businessUnitId}deletes a warehouse's supply termsbpa.business-partner.write, for that business unit
GET /warehouse-supply-terms/{businessUnitId}reads a warehouse's supply termsbpa.business-partner.read, for that business unit

The tenant always comes from the caller's token. Every read and write is confined to that tenant, so the same partner id under two tenants is two separate partners.

Permissions​

RolePermissionsTypical holder
Business Partner Adminbpa.business-partner.read, bpa.business-partner.writeyour ERP integration
Business Partner Readerbpa.business-partner.reada system that only looks partners up

Partners belong to the whole tenant, so the partner endpoints need the permission only. Warehouse supply terms belong to one business unit, so for those endpoints the permission must also cover the business unit in the URL. A caller without the permission gets 403 Forbidden.

Sending a partner​

PUT creates the partner or replaces it entirely. Send the whole partner every time, as your ERP holds it now.

PUT /api/v1/business-partners/V-20417
Content-Type: application/json
Correlation-Id: erp-sync-2026-10-20-0001

{
"displayId": "20417",
"status": "Active",
"name": "Fjord Garden",
"description": "Garden tools and outdoor furniture",
"legalName": "Fjord Garden AB",
"vatNumber": "SE556677889901",
"gln": "7350001234564",
"roles": [
{ "role": "SUPPLIER", "isActive": true, "defaultLeadTimeHours": 168, "reliabilityScore": 0.95 },
{ "role": "MANUFACTURER", "isActive": true }
],
"addresses": [
{
"addressType": "Delivery",
"careOf": null,
"street": "Lagervägen 4",
"zipCode": "504 62",
"city": "Borås",
"county": "Västra Götaland",
"country": "Sweden",
"countryCode": "SE",
"phone": "+46 33 123 45 00",
"mobile": null,
"email": "returns@fjordgarden.example",
"contactPerson": "Returns desk"
}
],
"additionalProperties": [
{ "id": "paymentTerms", "name": "Payment terms", "code": "PT30", "description": null,
"dataType": "STRING", "value": "30 days net" }
]
}

The answer is 202 Accepted. The event this produces is shown under The partner event.

🛑 Leaving something out removes it​

A role, an address or an additional property that is not in the body is deleted from the stored partner. There is no partial update. To change one address, send the partner with all its addresses, one of them changed.

PUT replaces the whole partner. Before, Fjord Garden has the roles SUPPLIER and MANUFACTURER and a Visit and a Delivery address. A PUT that sends only the SUPPLIER role and the Delivery address leaves the partner with exactly those: the MANUFACTURER role and the Visit address are gone. To keep something, send it again.

What the body must hold​

FieldRequiredRule
name✅text
status✅Active, Passive, Expired, Discontinued, Replaced or Deleted. See Status
roles✅at least one; each of SUPPLIER and MANUFACTURER at most once; each with role and isActive
roles[].defaultLeadTimeHoursSUPPLIER only. A whole number of calendar hours, 0 to 8760, or null
roles[].reliabilityScoreSUPPLIER only. 0.0 to 1.0 with at most 9 decimals, or null
addresses✅may be empty; at most one of each addressType; each with zipCode and city; countryCode an ISO 3166-1 alpha-2 code
additionalProperties✅may be empty; each with id, name, dataType and value
gln13 digits with a valid GS1 check digit, or null
displayId, description, legalName, vatNumbertext, or null

The id in the URL is 1 to 64 characters, with no spaces and none of /, ?, # or %.

A request that breaks any rule gets 400 Bad Request naming the problem, and nothing is queued. So does a request with a field that is not listed above, at any level, and a MANUFACTURER role that carries defaultLeadTimeHours or reliabilityScore, even as null.

Writes are asynchronous​

The API checks the request, queues it and answers 202 Accepted straight away. Business Partner then stores the change and publishes its event, normally within moments.

What happens after a PUT. The ERP sends PUT for V-20417 and gets 202 at once: the request is valid and queued. Shortly afterwards Business Partner stores the partner, and only then does GET return the new state and the business-partner-changed event go out. A GET sent in between still returns the previous state, or 404 for a new partner.

What that means for your integration:

  • A 202 is a promise, not a confirmation. The request was valid. The change is not yet readable.
  • A GET straight after a PUT may return the previous state, or 404 for a partner that did not exist before. To confirm a write, wait for its event or read again a little later.
  • Of two PUTs for the same partner, the one the API accepted last wins, even if the two are stored in the other order. An older change that arrives after a newer one is discarded.

The request accepted last wins. At 08:00:01 the API accepts a PUT setting Fjord Garden's lead time to 168 hours. At 08:00:03 it accepts a second PUT setting it to 120 hours. If the second is stored first and the first arrives afterwards, the first is discarded because it was accepted earlier. The partner ends with 120 hours, the value of the request accepted last.

Retrying​

A PUT is safe to retry. It replaces the whole partner, so sending the same body twice leaves the same partner. If a call times out or answers 5xx, send it again. Each accepted PUT publishes an event, even when nothing changed, so a retry can produce a second event with the same content.

Deleting a partner​

DELETE marks the partner Deleted. It is a soft delete: the record, its roles and its addresses are kept, and an event is published with status: "Deleted".

After a DELETE
GET /business-partners/{id}still 200, with status: "Deleted"
GET /business-partnersleaves the partner out, unless you ask for status=Deleted
a later PUT for the same idrestores the partner, with whatever that PUT sends

Delete keeps the partner and a PUT brings it back. Fjord Garden is Active. After DELETE it is marked Deleted, keeps its roles and addresses, is left out of the list, and can still be read by id. A later PUT stores it again with the status and contents that PUT sends.

DELETE answers 404 Not Found when no partner with that id is stored for your tenant.

⚠ A DELETE sent straight after the PUT that created the partner can answer 404. The DELETE checks the stored partners, and the PUT may not be stored yet. If you create and remove a partner in quick succession, for example in a test, wait for the creation's event or retry the DELETE after a moment.

Reading partners​

One partner​

GET /business-partners/{businessPartnerId} returns the partner as it is stored, in the same shape as the PUT body plus businessPartnerId and modifiedDatetime, the time the stored state was last written. It returns 404 Not Found when there is no such partner for your tenant, and a Deleted partner with 200.

A list​

GET /business-partners returns { "items": [...], "nextCursor": "..." }, sorted by businessPartnerId. Each item has the same shape as a single partner.

ParameterMeaning
roleonly partners holding this role: SUPPLIER or MANUFACTURER, active or not
isActivewith role: only partners whose role has this active flag. Without role it answers 400, because the flag belongs to a role
statusonly partners with this status. Without it, every partner except Deleted ones is returned; pass status=Deleted to list those
glnonly partners with this GLN, 13 digits
pageSize1 to 200; 50 when left out
cursorthe nextCursor of the previous page

Filters combine: role=SUPPLIER&isActive=true&gln=7350001234564 returns active suppliers with that GLN.

When there are more partners, the response carries nextCursor; pass it as cursor to get the next page. The last page has no nextCursor. Treat the cursor as an opaque string.

Warehouse supply terms​

PUT /warehouse-supply-terms/{businessUnitId} with { "defaultLeadTimeHours": 48 } sets the lead time of one of your own warehouses, and GET returns { "businessUnitId": "DC-JKP", "defaultLeadTimeHours": 48 }. The rules, and the check against Business Unit Management, are on Partners and your own warehouses.

They behave like partners in the ways that matter: the write is asynchronous, the body replaces what is stored, a field that is not declared is refused with 400, and the request accepted last wins.

They differ in one way: DELETE answers 202 whether or not any terms were stored for that business unit, and publishes a deleted event either way. After it, GET answers 404 until the next PUT.

Responses​

StatusMeansWhat to do
200 OKthe read succeeded
202 Acceptedthe write is valid and queuedwait for the event if you need confirmation
400 Bad Requestthe request breaks a rule; the message names it. For warehouse supply terms, also: the business unit is not a WAREHOUSEfix the request; resending it unchanged fails again
403 Forbiddenthe token lacks the permission, or for warehouse supply terms does not cover the business unitgrant the role
404 Not Foundno such partner, or no such business unit, or no stored supply termssee Deleting a partner for the one case that resolves itself
502 Bad Gatewaywarehouse supply terms only: Business Unit Management could not be askedsend the request again
5xxthe request could not be queuedsend the request again. Retrying is safe