Link a user to an organization
const url = 'https://apisandbox.puurk.com/organizations/example/user/example/link';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"status":"active","start_date":"2026-04-15T12:00:00Z","termination_date":"2026-04-15T12:00:00Z","commission_basis":"profit","commission_fixed":1,"commission_rate":1,"commission_trigger":"sale","role":"owner","oldUid":"example"}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://apisandbox.puurk.com/organizations/example/user/example/link \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "status": "active", "start_date": "2026-04-15T12:00:00Z", "termination_date": "2026-04-15T12:00:00Z", "commission_basis": "profit", "commission_fixed": 1, "commission_rate": 1, "commission_trigger": "sale", "role": "owner", "oldUid": "example" }'Link an existing user to an organization, optionally migrating them from a previous uid. This writes the organization’s roles map, so it is a role modification. Setting a role requires one of: an organization role of owner or agencyadmin in this organization; a superadmin claim; or a service token holding the admin scope action on organizations (globally or for this organization). admin is a scope action, not an organization role, and is rejected as a role value with 400.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Organization ID
User ID
Request Body
Section titled “Request Body”Request body
Body for POST /organizations/{oid}/user/{uid}/link. Every field is optional.
object
Membership status.
When the person started with this organization. ISO 8601, or null to clear.
When the person left. ISO 8601, or null to clear.
Fixed commission amount in cents
Commission rate
The role to grant. Defaults to read. Setting a role requires one of: an organization role of owner or agencyadmin in this organization; a superadmin claim; or a service token holding the admin scope action on organizations (globally or for this organization). admin is a scope action, not an organization role, and is rejected as a role value with 400.
A previous uid for this person. When supplied, its entry is removed from the organization’s roles map in the same write. Note the camelCase name: unlike the other fields, the service reads oldUid, and an old_uid is silently ignored.
Responses
Section titled “Responses”User linked. The body is the organization, not the user — its roles map reflects the change.
object
Unique identifier for the organization
External identifier for the organization
Name of the organization
Employer Identification Number
Path to the organization’s logo
Type of organization. Validated on create and update; any other value is rejected with 400 Invalid type. Must be one of: client, test.
User roles in the organization
object
Role of a user in an organization, as stored in the organization’s roles map. admin is not a role: it is a service-token scope action, and a request that sends it as a role gets 400. Of the organization roles, only owner and agencyadmin may change other members’ roles.
Organization settings
object
Puurk features enabled for the organization
object
Example
{ "type": "client", "roles": { "additionalProperty": "owner" }}bad_request — invalid start_date or termination_date, or role is not an OrganizationRole (Invalid role. Must be one of: owner, manager, read, write, provider, accountant, officeadmin, agencyadmin, agencyuser, none). admin is rejected here: it is a scope action, not a role.
The standard error body. error is a stable, machine-readable code — branch on it rather than on message, which is for humans and may change.
object
Machine-readable error code.
Human-readable detail.
Example
{ "error": "merchant_account_missing", "message": "The organization has no merchant account. Complete Stripe Connect onboarding for this organization before generating pricing."}Unauthorized
forbidden — the caller is the target user, or the caller holds none of: an organization role of owner or agencyadmin, a superadmin claim, or a service token with the admin scope action on organizations.
The standard error body. error is a stable, machine-readable code — branch on it rather than on message, which is for humans and may change.
object
Machine-readable error code.
Human-readable detail.
Example
{ "error": "merchant_account_missing", "message": "The organization has no merchant account. Complete Stripe Connect onboarding for this organization before generating pricing."}not_found — the organization does not exist.
The standard error body. error is a stable, machine-readable code — branch on it rather than on message, which is for humans and may change.
object
Machine-readable error code.
Human-readable detail.
Example
{ "error": "merchant_account_missing", "message": "The organization has no merchant account. Complete Stripe Connect onboarding for this organization before generating pricing."}conflict — this would remove the organization’s last owner.
The standard error body. error is a stable, machine-readable code — branch on it rather than on message, which is for humans and may change.
object
Machine-readable error code.
Human-readable detail.
Example
{ "error": "merchant_account_missing", "message": "The organization has no merchant account. Complete Stripe Connect onboarding for this organization before generating pricing."}