Create a team
const url = 'https://api.deploybase.eu/api/v1/api/v1/me/teams';const options = { method: 'POST', headers: {Authorization: '<Authorization>', 'Content-Type': 'application/json'}, body: '{"dpa_version":"example","entity_name":"Acme B.V.","interval":"monthly","name":"Acme web","plan":"pro","role":"own","slug":"acme-web","terms_version":"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://api.deploybase.eu/api/v1/api/v1/me/teams \ --header 'Authorization: <Authorization>' \ --header 'Content-Type: application/json' \ --data '{ "dpa_version": "example", "entity_name": "Acme B.V.", "interval": "monthly", "name": "Acme web", "plan": "pro", "role": "own", "slug": "acme-web", "terms_version": "example" }'Creates a new team owned by the signed-in person, with its own identity organization, its own billing and its own data processing agreement. Requires a signed-in user with a confirmed email address: API keys and agent tokens are refused. On a paid plan the team is created awaiting payment (awaiting_payment_until, 48 hours): until its first checkout completes it cannot create projects, deploy or invite, and it is removed if still unpaid at that time. The Free plan is refused while the person owns a Free team or created one in the last 30 days. At most 5 teams per person per 24 hours, deleted ones included. Creating a team does not switch to it. Send an Idempotency-Key header to retry safely: a repeat returns the original team with 200.
Authorizations
Section titled “ Authorizations ”Parameters
Section titled “ Parameters ”Header Parameters
Section titled “ Header Parameters ”Up to 255 characters; a repeat returns the first result
Request Body
Section titled “ Request Body ”The team to create
object
EntityName is the organisation named on the team’s data processing agreement, 2 to 200 characters.
Example
Acme B.V.Interval is monthly or annual; required for a paid plan.
Example
monthlyName is the team’s display name, 1 to 100 characters.
Example
Acme webPlan is free, starter, pro or scale.
Example
proRole is own (your organisation) or client (a client who needs their own team).
Example
ownSlug is the team URL, validated like a rename (PATCH /team/profile).
Example
acme-webTermsVersion and DPAVersion echo the versions the page showed (GET /me/team-creation).
Responses
Section titled “ Responses ”Idempotent replay
object
object
object
DisplayLabel is what to show a human. Never empty, even for teams whose name is still a raw Zitadel org UUID — models.Team.DisplayLabel owns that fallback.
IsActive marks the team the current request is acting on.
IsHome marks the team the caller’s own Zitadel org maps to. Exactly one entry has it.
LapsedAt is set while this extra team is blocked as a second Free team of one of its owners (DEP-889): its sites keep serving, but nobody can deploy or create projects until it is paid for again. LapseRemovalAt is when it is deleted if that does not happen. Shown to every member, not just owners: a member who cannot deploy needs to know why.
PendingPlan and PendingInterval are the paid plan chosen when the team was created, so the waiting-for-payment page can restart the same checkout. Set only alongside AwaitingPaymentUntil, and only for owners.
Plan, Interval and AwaitingPaymentUntil are filled only on teams the caller OWNS (DEP-766): what a team pays is the owner’s business, not a member’s. Plan is free, starter, pro or scale; Interval (monthly or annual) is absent on Free. AwaitingPaymentUntil is set while a team created on a paid plan waits for its first payment: the team is removed at that time if it is still unpaid. Such a team reads as Free until the payment lands.
Status is the team’s lifecycle state, with “suspended” taking precedence over the
deletion state machine: a suspended team is usually active, and “active” is
exactly the wrong thing to tell someone whose team is closed.
Example
{ "data": { "interval": "monthly", "pending_interval": "monthly", "pending_plan": "pro", "plan": "pro" }}Created
object
object
object
DisplayLabel is what to show a human. Never empty, even for teams whose name is still a raw Zitadel org UUID — models.Team.DisplayLabel owns that fallback.
IsActive marks the team the current request is acting on.
IsHome marks the team the caller’s own Zitadel org maps to. Exactly one entry has it.
LapsedAt is set while this extra team is blocked as a second Free team of one of its owners (DEP-889): its sites keep serving, but nobody can deploy or create projects until it is paid for again. LapseRemovalAt is when it is deleted if that does not happen. Shown to every member, not just owners: a member who cannot deploy needs to know why.
PendingPlan and PendingInterval are the paid plan chosen when the team was created, so the waiting-for-payment page can restart the same checkout. Set only alongside AwaitingPaymentUntil, and only for owners.
Plan, Interval and AwaitingPaymentUntil are filled only on teams the caller OWNS (DEP-766): what a team pays is the owner’s business, not a member’s. Plan is free, starter, pro or scale; Interval (monthly or annual) is absent on Free. AwaitingPaymentUntil is set while a team created on a paid plan waits for its first payment: the team is removed at that time if it is still unpaid. Such a team reads as Free until the payment lands.
Status is the team’s lifecycle state, with “suspended” taking precedence over the
deletion state machine: a suspended team is usually active, and “active” is
exactly the wrong thing to tell someone whose team is closed.
Example
{ "data": { "interval": "monthly", "pending_interval": "monthly", "pending_plan": "pro", "plan": "pro" }}Bad Request
object
object
Example generated
{ "code": "example", "details": "example", "error": "example", "meta": { "request_id": "example", "timestamp": "example", "trace_id": "example" }}Unauthorized
object
object
Example generated
{ "code": "example", "details": "example", "error": "example", "meta": { "request_id": "example", "timestamp": "example", "trace_id": "example" }}FORBIDDEN (API key or agent token), EMAIL_NOT_CONFIRMED or TEAM_CREATION_UNAVAILABLE
object
object
Example generated
{ "code": "example", "details": "example", "error": "example", "meta": { "request_id": "example", "timestamp": "example", "trace_id": "example" }}SLUG_TAKEN with details.suggestions, FREE_TEAM_LIMIT with details.reason, LEGAL_VERSION_STALE with the current versions, IDEMPOTENCY_KEY_REUSED
object
object
Example generated
{ "code": "example", "details": "example", "error": "example", "meta": { "request_id": "example", "timestamp": "example", "trace_id": "example" }}INVALID_INPUT or SLUG_RESERVED, with details.field
object
object
Example generated
{ "code": "example", "details": "example", "error": "example", "meta": { "request_id": "example", "timestamp": "example", "trace_id": "example" }}TEAM_CREATE_RATE_LIMITED, with Retry-After and details.retry_after
object
object
Example generated
{ "code": "example", "details": "example", "error": "example", "meta": { "request_id": "example", "timestamp": "example", "trace_id": "example" }}Internal Server Error
object
object
Example generated
{ "code": "example", "details": "example", "error": "example", "meta": { "request_id": "example", "timestamp": "example", "trace_id": "example" }}PROVISIONING_FAILED
object
object
Example generated
{ "code": "example", "details": "example", "error": "example", "meta": { "request_id": "example", "timestamp": "example", "trace_id": "example" }}Live f79d25b6 built