Organizations
Create organization and initial owner invitation
Creates a new customer organization under the specified partner (MSP), creates its owner invitation record, and attempts to send the invitation email.
What happens:
- The organization is created with the selected plan and linked to the partner via partnerId.
- The organization is marked as partner-managed - no Stripe billing is set up for the customer.
- An invitation record is created for owner.email. Email delivery is best-effort.
- Once the owner accepts, they have full product access but cannot manage billing or subscriptions.
The externalCustomerId must be unique across all your organizations (not just per partner).
AuthorizationBearer <token>
Long-lived distributor API key scoped to a channel partner on the shared smao instance.
In: header
organization
owner
externalCustomerIdstring
Your unique customer identifier on the distributor side.
Length
1 <= length <= 255externalContractId?string|null
Optional contract identifier on the distributor side.
Length
length <= 255partnerIdstring
ID of the partner (MSP) this organization belongs to. Must reference an active partner.
Match
^[a-fA-F0-9]{24}$plan
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://api.smao.ai/api/distributor/v1/organizations" \ -H "Content-Type: application/json" \ -d '{ "organization": { "name": "Acme GmbH", "timezone": "Europe/Berlin" }, "owner": { "email": "[email protected]", "firstName": "Alice", "lastName": "Müller" }, "externalCustomerId": "SYN-4711", "partnerId": "665abc123def456789012345", "plan": { "slug": "advanced", "commitment": "monthly" } }'{
"status": "success",
"organization": {
"id": "69c175970f3e28310926a1aa",
"name": "Acme GmbH",
"industry": "IT Services",
"timezone": "Europe/Berlin",
"channelPartner": "acme",
"externalCustomerId": "SYN-4711",
"externalContractId": "CON-2026-0001",
"partnerId": "665abc123def456789012345",
"ownerEmail": "[email protected]",
"createdAt": "2026-03-23T17:17:11.605Z",
"plan": {
"id": "6967b1c7138bed3e7f6bf7e6",
"slug": "advanced",
"name": "Advanced",
"commitment": "monthly",
"currency": "EUR",
"baseFee": 6900
}
},
"owner": {
"email": "[email protected]",
"firstName": "Alice",
"lastName": "Müller",
"role": "admin",
"status": "invited",
"source": "distributor-api",
"invitationId": "69c175970f3e28310926a1bb",
"expiresAt": "2026-03-30T17:17:11.814Z"
}
}{
"status": "error",
"errorCode": "INVALID_DATE_RANGE",
"message": "from and to must be valid YYYY-MM-DD values"
}{
"status": "error",
"errorCode": "INVALID_DATE_RANGE",
"message": "from and to must be valid YYYY-MM-DD values"
}{
"status": "error",
"errorCode": "INVALID_DATE_RANGE",
"message": "from and to must be valid YYYY-MM-DD values"
}{
"status": "error",
"errorCode": "INVALID_DATE_RANGE",
"message": "from and to must be valid YYYY-MM-DD values"
}{
"status": "error",
"errorCode": "RATE_LIMITED",
"message": "Too many requests for this API key."
}{
"status": "error",
"errorCode": "INVALID_DATE_RANGE",
"message": "from and to must be valid YYYY-MM-DD values"
}{
"status": "error",
"errorCode": "RATE_LIMIT_UNAVAILABLE",
"message": "Rate limit storage is unavailable. Try again shortly."
}