Skip to main content

Organizations

Manage tenant organizations via the Provisioning API.

The Provisioning API is used by Super Terra (the parent platform) to create and manage Courimax tenants. All provisioning endpoints require the X-Provisioning-Secret header.

List Organizations​

GET /provisioning/organizations

Headers​

HeaderRequiredDescription
X-Provisioning-SecretYesProvisioning secret

Example​

curl -X GET "https://api.courimax.com/api/provisioning/organizations" \
-H "X-Provisioning-Secret: your_provisioning_secret"

Response (200 OK)​

[
{
"id": "org-uuid",
"slug": "acme-corp",
"name": "Acme Corporation",
"isActive": true,
"createdAt": "2026-08-19T10:00:00.000Z",
"counts": {
"members": 5,
"drivers": 12,
"orders": 342
},
"admins": [
{
"id": "user-uuid",
"email": "admin@acme.com",
"name": "John Doe",
"orgRole": "admin",
"invitePending": false
}
]
}
]

Create Organization​

POST /provisioning/organizations

Headers​

HeaderRequiredDescription
X-Provisioning-SecretYesProvisioning secret
Content-TypeYesapplication/json

Body Parameters​

ParameterTypeRequiredDescription
namestringYesOrganization name
slugstringNoURL-safe slug (auto-generated if not provided)
admin.emailstringYesFirst admin's email
admin.namestringNoFirst admin's name

Example​

curl -X POST "https://api.courimax.com/api/provisioning/organizations" \
-H "X-Provisioning-Secret: your_provisioning_secret" \
-H "Content-Type: application/json" \
-d '{
"name": "Acme Corporation",
"slug": "acme-corp",
"admin": {
"email": "admin@acme.com",
"name": "John Doe"
}
}'

Response (201 Created)​

{
"organization": {
"id": "org-uuid",
"slug": "acme-corp",
"name": "Acme Corporation",
"isActive": true,
"createdAt": "2026-08-19T10:00:00.000Z"
},
"admin": {
"id": "user-uuid",
"email": "admin@acme.com",
"name": "John Doe",
"isNewUser": true
},
"invite": {
"expiresAt": "2026-08-26T10:00:00.000Z",
"emailSent": true
}
}

Response Fields​

FieldTypeDescription
organizationobjectCreated organization
adminobjectAdmin user details
admin.isNewUserbooleanWhether admin is a new user
inviteobjectInvite details (null if user already exists)
invite.expiresAtstringInvite expiration (7 days)
invite.emailSentbooleanWhether invite email was sent

Error Responses​

400 Bad Request - Validation error

{
"statusCode": 400,
"message": "Organization name is required",
"error": "Bad Request"
}

409 Conflict - Slug already taken

{
"statusCode": 400,
"message": "Slug \"acme-corp\" is already taken",
"error": "Bad Request"
}

Add Admin​

POST /provisioning/organizations/:id/admins

Path Parameters​

ParameterTypeRequiredDescription
idstringYesOrganization ID

Headers​

HeaderRequiredDescription
X-Provisioning-SecretYesProvisioning secret
Content-TypeYesapplication/json

Body Parameters​

ParameterTypeRequiredDescription
emailstringYesAdmin email
namestringNoAdmin name

Example​

curl -X POST "https://api.courimax.com/api/provisioning/organizations/org-uuid/admins" \
-H "X-Provisioning-Secret: your_provisioning_secret" \
-H "Content-Type: application/json" \
-d '{
"email": "newadmin@acme.com",
"name": "Jane Smith"
}'

Response (201 Created)​

{
"admin": {
"id": "user-uuid",
"email": "newadmin@acme.com",
"name": "Jane Smith",
"isNewUser": true,
"alreadyMember": false
},
"invite": {
"expiresAt": "2026-08-26T10:00:00.000Z",
"emailSent": true
}
}

Resend Invite​

POST /provisioning/admins/:userId/resend-invite

Path Parameters​

ParameterTypeRequiredDescription
userIdstringYesUser ID

Headers​

HeaderRequiredDescription
X-Provisioning-SecretYesProvisioning secret

Example​

curl -X POST "https://api.courimax.com/api/provisioning/admins/user-uuid/resend-invite" \
-H "X-Provisioning-Secret: your_provisioning_secret"

Response (200 OK)​

{
"admin": {
"id": "user-uuid",
"email": "admin@acme.com",
"name": "John Doe"
},
"invite": {
"expiresAt": "2026-08-26T10:00:00.000Z",
"emailSent": true
}
}

Reset Password​

POST /provisioning/admins/:userId/reset-password

Path Parameters​

ParameterTypeRequiredDescription
userIdstringYesUser ID

Headers​

HeaderRequiredDescription
X-Provisioning-SecretYesProvisioning secret
Content-TypeYesapplication/json

Body Parameters​

ParameterTypeRequiredDescription
passwordstringNoNew password (auto-generated if not provided)

Example​

curl -X POST "https://api.courimax.com/api/provisioning/admins/user-uuid/reset-password" \
-H "X-Provisioning-Secret: your_provisioning_secret" \
-H "Content-Type: application/json" \
-d '{
"password": "NewSecurePassword123!"
}'

Response (200 OK)​

{
"ok": true,
"email": "admin@acme.com"
}

If no password is provided, a secure temporary password is generated and returned.

Invite Acceptance​

Get Invite​

GET /provisioning/invite/:token

This endpoint is public (no authentication required) and is used to display invite details before acceptance.

curl -X GET "https://api.courimax.com/api/provisioning/invite/invite-token"

Accept Invite​

POST /provisioning/invite/:token/accept
curl -X POST "https://api.courimax.com/api/provisioning/invite/invite-token/accept" \
-H "Content-Type: application/json" \
-d '{
"password": "SecurePassword123!"
}'

Response (200 OK)​

{
"ok": true,
"email": "admin@acme.com"
}

Rate Limiting​

Provisioning endpoints have rate limits:

  • GET /organizations: 120 requests per hour
  • POST /organizations: 30 requests per hour
  • POST /organizations/:id/admins: 60 requests per hour
  • POST /admins/:userId/resend-invite: 30 requests per hour
  • POST /admins/:userId/reset-password: 30 requests per hour

Next Steps​