Skip to content

Tenancy and access

Collaterate is multi-tenant. A site is the unit of tenancy, and your partner record carries a set of granted site ids. Everything this API returns is filtered to that set.

Grants are configured by Collaterate, per environment, and are not something you can inspect indirectly or extend yourself. The authoritative view of your own grant is GET /v1/me:

{
"partnerId": "1",
"partnerName": "Acme",
"grantedSiteIds": [7, 8],
"authMethod": "COGNITO_M2M",
"scopes": ["partner-api/orders:read"]
}

grantedSiteIds is never empty for a working credential. A partner with no granted sites cannot authenticate at all - see when authentication fails.

Two distinct things control what you may do, and it is worth keeping them apart when debugging:

Concept Question it answers Where you see it Failure looks like
Grant Which sites’ data? grantedSiteIds 404 on an order, or 400 invalid_site_id on a filter
Scope Which operations? scopes 403 insufficient_scope

Site scoping is applied when the query is built, on every read, unconditionally. There is no code path in this API that can construct a query without it, and no parameter you can send that relaxes it. A row belonging to a site outside your grant is not filtered out of a response - it never leaves the database in the first place.

Two consequences follow, and both are visible to you:

Filtering by siteId narrows, it never widens. If you pass a siteId that is in your grant, you get that site’s orders. If you pass one that is not, you get a 400 invalid_site_id. The parameter is never silently ignored, which would quietly widen the result back to all of your sites and give you a different answer than the one you asked for, and it never returns an empty page, which would be indistinguishable from a legitimate site with no orders.

Some orders are excluded from every response. Orders that Collaterate does not mark as live - test and internal orders - are never returned to partners, regardless of grant. This is not configurable and there is no parameter to include them.

GET /v1/orders/{orderNumber} returns the same 404 order_not_found for an order number that was never issued and for an order that exists in a site you are not granted.

This is deliberate and permanent. Because a row outside your grant never comes back from the database, the service genuinely cannot distinguish the two cases - and it must not try, since confirming that an order exists somewhere you cannot see is itself a disclosure. Returning 403 here would let anyone holding any credential enumerate valid order numbers across the whole platform.

On your next request. Your partner record, your grants and your capabilities are looked up fresh on every call rather than being baked into your credential.

This has a practical consequence in both directions:

  • A new site added to your grant is visible immediately. You do not need a new token, and a token you already hold picks up the new site on its next use.
  • Access removed is gone immediately, for the same reason. There is no window in which an already-minted token keeps working against a site you no longer have.

The one exception is mutual TLS offboarding: removing a certificate from the truststore takes several minutes to propagate through the edge, though the partner record change itself is immediate and the credential stops resolving right away.

Site ids are integers, stable, and assigned by Collaterate. You get yours from GET /v1/me, and every order carries its own in the siteId field so you can attribute a result from an unfiltered list.

There is no endpoint in v1 that lists sites beyond your own grant, and there is no way to discover whether a given site id exists. A site id you are not granted behaves identically to one that was never issued.

Successful reads are audited. The record holds who called, which endpoint, which sites were in the grant at the time, how many rows were returned, and the request id. It does not hold order contents - copying the data into a second store would double the exposure surface and buy nothing.

Requests that returned an error are not audited as accesses, because they read nothing.

GET /v1/ping has no authentication and therefore no tenancy. It reports whether the service is reachable and nothing about you or your data. It is the one endpoint here that behaves identically for everyone.