access
PUT /v1/orgs/{orgId}/delegated-access
Set exactly which sites one person holds, and the role on each.
Authentication
Send an API key as a bearer token. This endpoint does not state a specific permission in the specification, so give your key the least it needs and check the response rather than assuming.
Where your organisation id goes
This endpoint takes your organisation id in the URL itself, as orgId. Substitute it into the path — there is no header or query parameter that will do instead.
Your organisation id is on the API keys screen in your dashboard, beside the key itself. It is the same id in every call you make.
Try it
Replace anything in angle brackets with your own values, and the key placeholder with a key from your dashboard.
curl -X PUT https://api.zinndigital.com/v1/orgs/{orgId}/delegated-access \
-H "Authorization: Bearer zdk_live_…" \
-H "Content-Type: application/json" \
-d '{ "email": <string>, "sites": <object[]> }'Signed in? The API console in your dashboard fills in your real organisation id and your own key, and runs the request against the live API so you can see the actual response. Open this endpoint in the API console
Details
One call for every change to one person: invite them, add a site, change a role, remove a site. After it the person holds EXACTLY the sites in sites. Sites they already hold keep their grant and have the role (and, when expires_at is sent, the end date) updated in place; new sites are granted — or, for an address with no account, invited, with one invitation however many sites; sites left out are revoked. The whole call is atomic: one refused site leaves every other site as it was. The same rules as sharing one site (shareSiteWithCollaborator) apply, with the same codes: SITE_COLLABORATOR_ALREADY_A_MEMBER (409), SITE_COLLABORATOR_ALREADY_INVITED (409), SITE_COLLABORATOR_EXPIRY_IN_THE_PAST (422) and SITE_COLLABORATOR_REASON_REQUIRED (422 — a new site for somebody with no reason on record). Two are this endpoint's own: SITE_COLLABORATOR_SITE_NOT_IN_ORG (422 — one code for "no such site" and "a site of another organisation", so it is not an oracle) and SITE_COLLABORATOR_DUPLICATE_SITE (422). Saving a person whose invitation has lapsed sends it again; saving one whose invitation is still live does not. To remove every site, use the revoke endpoint — an empty sites is refused, so an accidental untick of the last box is never a revoke.
Parameters
| Name | Type | Required | What it is |
|---|---|---|---|
orgId (path) | Uuid | Yes | Organization ID (UUIDv7). |
Request body
| Name | Type | Required | What it is |
|---|---|---|---|
email | string | Yes | — |
sites | object[] | Yes | The EXACT sites the person should hold after the call. |
reason | string | No | Why this person is being given these sites. Required when the call writes a new grant for somebody with no reason on record; otherwise the reason on record is kept. |
expires_at | object | No | Omitted leaves every end date as it is; null means until revoked, for every site. |
Response
| Name | Type | Required | What it is |
|---|---|---|---|
email | string | Yes | — |
user_id | object | Yes | Null for somebody who has only been invited. |
name | string | Yes | — |
status | string<active, pending, expired> | Yes | — |
site_count | integer | Yes | Sites in force or awaiting acceptance. |
reason | string | Yes | The most recent reason recorded for sharing with this person. |
invited_at | string | Yes | — |
accepted_at | object | Yes | When they accepted — or, shared straight to an existing account, when access began. Null while pending. |
invitation_expires_at | object | Yes | When a pending invitation stops being acceptable. Saving the person sends a lapsed one again. |
last_active_at | object | Yes | — |
sites | DelegatedSite[] | Yes | — |
Errors this endpoint can return
401 · 403 · 404 · 409 · 422 · 429