> ## Documentation Index
> Fetch the complete documentation index at: https://docs.credibledata.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Create a new organization

> Creates a new organization with the specified configuration. Organizations serve as the top-level
container for all resources including environments, packages, workspaces, and user groups.

**Authorization (two paths):**
- *Direct create.* Default. Requires the system-level `can_create_organization` permission.
- *Invite redemption.* Supply the raw invite token in the `X-Invite-Token` header. The
  invite is the authorization — any authenticated user may redeem. The caller is granted
  admin on the new organization, the caller's user row is ensured, MPA acceptance is
  recorded (using the server's current MPA version), and the invite is marked consumed.
  If the invite was minted with a `boundEmail`, the caller's email must match
  (case-insensitive). If the token has already been redeemed, a 409 is returned naming
  the prior organization.

**Error codes.** On 4xx the response body carries an `Error { code, message }`. Clients
should branch on `code`:

| Status | `code`                    | Meaning                                                   |
|--------|---------------------------|-----------------------------------------------------------|
| 400    | `VALIDATION_ERROR`        | Body field validation failed (e.g. bad `displayName`).    |
| 400    | `INVITE_INVALID`          | `X-Invite-Token` is malformed or unknown.                 |
| 400    | `INVITE_EXPIRED`          | `X-Invite-Token` is past its `expiresAt`.                 |
| 403    | `INSUFFICIENT_PERMISSIONS`| Direct create attempted without the required permission. |
| 403    | `INVITE_EMAIL_MISMATCH`   | Invite is bound to a different email than the caller.    |
| 409    | `ORGANIZATION_NAME_TAKEN` | Requested `name` (URL slug) is taken — retry with another.|
| 409    | `ORGANIZATION_NAME_RESERVED` | Requested `name` collides with a platform subdomain.   |
| 409    | `INVITE_ALREADY_CONSUMED` | Token was already redeemed; retry will not help.          |

**Validation**: Organization names must be unique and follow naming conventions.
**Side Effects**: Creates default permissions and initializes organizational structure.




## OpenAPI

````yaml /controlplane-public-api-doc.yaml post /organizations
openapi: 3.1.0
info:
  title: Credible Admin API
  description: >
    The Credible Admin API is a comprehensive REST API that empowers
    organizations to manage their Malloy data modeling ecosystem with
    enterprise-grade security and governance. This API provides programmatic
    access to all administrative functions, enabling seamless integration with
    existing workflows and automation systems.


    ## Key Features


    - **Organization Management**: Create and manage organizations with
    fine-grained access controls

    - **Environment & Package Lifecycle**: Full CRUD operations for
    environments, packages, and versions

    - **Connection Management**: Secure database connection configuration and
    management

    - **Permission Management**: Granular role-based access control (RBAC) at
    organization, environment, package, workspace, and document levels

    - **Workspace Management**: Collaborative workspaces for data modeling and
    analysis

    - **User & Group Management**: Comprehensive user administration with
    group-based permissions


    ## Resource Hierarchy


    The API follows a hierarchical resource structure with fine-grained
    permission management at each level:

    ```

    Organizations

    ├── Permissions

    ├── Environments

    │   ├── Permissions

    │   ├── Packages

    │   │   ├── Permissions

    │   │   └── Versions

    │   └── Connections

    ├── Workspaces

    │   ├── Permissions

    │   └── Documents

    │       └── Permissions

    └── Groups
        ├── Permissions
        └── Members

    System-Level Resources:

    ├── Users

    ├── System Permissions

    └── Demo Operations

    ```


    ## Authentication & Authorization


    All API endpoints require proper authentication. The API implements
    fine-grained authorization using role-based permissions:

    - **Admin**: Full access to all resources within scope

    - **Modeler**: Can create and modify data models and packages

    - **Viewer**: Read-only access to resources

    - **Manager**: Workspace management capabilities

    - **Editor**: Document editing permissions


    ## Rate Limiting & Best Practices


    - API requests are rate-limited to ensure system stability

    - Implement proper error handling and retry logic

    - Cache responses when appropriate to reduce API calls


    ## Support & Documentation


    For additional support, examples, and integration guides, visit our
    developer documentation or contact our support team.
  version: v0
  contact:
    name: Credible Support
    email: support@credibledata.com
    url: https://credibledata.com/support
  license:
    name: Proprietary
    url: https://credibledata.com/license
  termsOfService: https://credibledata.com/terms
servers:
  - url: https://{organization}.admin.credibledata.com/api/v0/
    description: Production API server
    variables:
      organization:
        default: demo
        description: Your organization subdomain
security:
  - bearerAuth: []
tags:
  - name: organizations
    description: >-
      Organization management operations for creating, updating, and managing
      organizational entities
  - name: organizationPermissions
    description: >-
      Fine-grained permission management for organizations, including role
      assignments and access controls
  - name: environments
    description: >-
      Environment lifecycle management including creation, configuration, and
      deletion of data modeling environments
  - name: environmentPermissions
    description: >-
      Permission management for environments, controlling access to environment
      resources and capabilities
  - name: packages
    description: >-
      Package management for Malloy data models, including versioning,
      publishing, and distribution
  - name: packagePermissions
    description: >-
      Access control for packages, managing who can view, modify, or publish
      package versions
  - name: versions
    description: >-
      Version management for packages, including archiving, status updates, and
      lifecycle management
  - name: connections
    description: >-
      Database connection management for secure data source configuration and
      access
  - name: materializations
    description: >-
      Malloy Persistence materializations (per-version serving anchors for
      persisted sources)
  - name: indexes
    description: >-
      Malloy Persistence dimensional search indexes (per-version serving anchors
      for indexed dimensions)
  - name: runs
    description: >-
      Malloy Persistence build/refresh runs — one package-level build event
      carrying typed units (materialized sources + built indexes)
  - name: workspaces
    description: >-
      Collaborative workspace management for team-based data modeling and
      analysis
  - name: workspacePermissions
    description: >-
      Access control for workspaces, managing who can view, manage, or
      collaborate in workspaces
  - name: documents
    description: >-
      Document management within workspaces, including workbooks, dashboards,
      and other content
  - name: documentPermissions
    description: >-
      Access control for documents, managing who can view, edit, or share
      document content
  - name: groups
    description: >-
      User group management for organizing users and managing group-based
      permissions
  - name: users
    description: >-
      User account management including creation, updates, and profile
      management
  - name: demo
    description: Demo and self-service operations for quick setup and testing scenarios
  - name: permissions
    description: System-level permission management for administrative functions
  - name: bookmarks
    description: >-
      User bookmark management for saving references to workspaces, models, and
      chats
  - name: attributes
    description: Trusted user attributes for fine-grain (row/column-level) access control
  - name: invites
    description: >-
      Organization-creation invite tokens. A super-admin mints tokens one per
      call (call `POST /invites` repeatedly to populate an outreach campaign);
      each token can be redeemed once by an authenticated user to create a new
      organization on the fly.
paths:
  /organizations:
    post:
      tags:
        - organizations
      summary: Create a new organization
      description: >
        Creates a new organization with the specified configuration.
        Organizations serve as the top-level

        container for all resources including environments, packages,
        workspaces, and user groups.


        **Authorization (two paths):**

        - *Direct create.* Default. Requires the system-level
        `can_create_organization` permission.

        - *Invite redemption.* Supply the raw invite token in the
        `X-Invite-Token` header. The
          invite is the authorization — any authenticated user may redeem. The caller is granted
          admin on the new organization, the caller's user row is ensured, MPA acceptance is
          recorded (using the server's current MPA version), and the invite is marked consumed.
          If the invite was minted with a `boundEmail`, the caller's email must match
          (case-insensitive). If the token has already been redeemed, a 409 is returned naming
          the prior organization.

        **Error codes.** On 4xx the response body carries an `Error { code,
        message }`. Clients

        should branch on `code`:


        | Status | `code`                    |
        Meaning                                                   |

        |--------|---------------------------|-----------------------------------------------------------|

        | 400    | `VALIDATION_ERROR`        | Body field validation failed
        (e.g. bad `displayName`).    |

        | 400    | `INVITE_INVALID`          | `X-Invite-Token` is malformed or
        unknown.                 |

        | 400    | `INVITE_EXPIRED`          | `X-Invite-Token` is past its
        `expiresAt`.                 |

        | 403    | `INSUFFICIENT_PERMISSIONS`| Direct create attempted without
        the required permission. |

        | 403    | `INVITE_EMAIL_MISMATCH`   | Invite is bound to a different
        email than the caller.    |

        | 409    | `ORGANIZATION_NAME_TAKEN` | Requested `name` (URL slug) is
        taken — retry with another.|

        | 409    | `ORGANIZATION_NAME_RESERVED` | Requested `name` collides with
        a platform subdomain.   |

        | 409    | `INVITE_ALREADY_CONSUMED` | Token was already redeemed; retry
        will not help.          |


        **Validation**: Organization names must be unique and follow naming
        conventions.

        **Side Effects**: Creates default permissions and initializes
        organizational structure.
      operationId: createOrganization
      parameters:
        - in: header
          name: X-Invite-Token
          required: false
          schema:
            type: string
          description: |
            Raw invite token (e.g. `ABCDE-FGHJK`). When supplied, the
            system-level `can_create_organization` permission check is
            bypassed — the invite is the authorization. Required for
            self-serve signup; omit for direct-create by privileged users.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Organization'
      responses:
        '200':
          description: Organization created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Organization'
        '400':
          description: >
            Request was rejected. `code` distinguishes the cause:
            `VALIDATION_ERROR`,

            `INVITE_INVALID`, or `INVITE_EXPIRED`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: |
            Caller is not authorized. `code` distinguishes the cause:
            `INSUFFICIENT_PERMISSIONS` (direct path) or `INVITE_EMAIL_MISMATCH`
            (invite path; caller's email doesn't match the bound email).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          description: |
            Conflict. `code` distinguishes the cause: `ORGANIZATION_NAME_TAKEN`
            (retry with a different `name`), `ORGANIZATION_NAME_RESERVED`
            (the requested name collides with a platform subdomain), or
            `INVITE_ALREADY_CONSUMED` (the invite is dead; retry will not help —
            message includes the prior organization name).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    Organization:
      type: object
      description: >-
        Represents an organization entity that serves as the top-level container
        for all resources
      properties:
        name:
          $ref: '#/components/schemas/DnsLabelPattern'
          type: string
          description: |
            The unique identifier for the organization. Used as the resource
            name in API paths AND as the DNS subdomain label routing traffic
            to the org, so it follows RFC 1035 hostname rules — lowercase
            letters, digits, and hyphens; no underscores; no leading or
            trailing hyphen; max 63 chars.
        displayName:
          $ref: '#/components/schemas/HumanTextPattern'
          description: >-
            Human-readable name for the organization, displayed in user
            interfaces
        createdAt:
          type: string
          format: date-time
          description: ISO 8601 timestamp indicating when the organization was created
        updatedAt:
          type: string
          format: date-time
          description: >-
            ISO 8601 timestamp indicating when the organization was last
            modified
        mpaVersion:
          $ref: '#/components/schemas/MpaVersionPattern'
          type: string
          readOnly: true
          description: |
            Version identifier of the Master Platform Agreement the organization
            accepted at creation time (file basename, e.g. `v1-2026-05-19`).
            Server-set: clients do not (and cannot) submit this field — when an
            organization is created via the invite-redemption path, the server
            stamps its current active MPA version. Null on legacy organizations
            created before MPA acceptance was required.

            Only the version is exposed on this resource. The per-user / per-
            timestamp audit fields (`mpa_accepted_by`, `mpa_accepted_at`)
            are kept internal — useful for compliance audit on the server
            side, not for API consumers. If a future use case needs them on
            the API, add them then; widening is easier than narrowing.
    Error:
      type: object
      x-model-name: ModelError
      description: Standard error response format used across all API endpoints
      properties:
        code:
          type: string
          description: >
            Machine-readable error code that identifies the specific error
            condition.

            Clients should branch on `code`, not on the human-readable `message`
            —

            the message text is informational and may change over time.


            Generic codes (may appear on any endpoint):

            - `VALIDATION_ERROR`: Request body or path/query parameter failed
            validation

            - `AUTHENTICATION_REQUIRED`: Valid authentication is required

            - `INSUFFICIENT_PERMISSIONS`: User lacks required permissions

            - `RESOURCE_NOT_FOUND`: Requested resource does not exist

            - `CONFLICT`: Generic resource state conflict (used when no more
            specific code applies)

            - `RATE_LIMIT_EXCEEDED`: API rate limit exceeded

            - `INTERNAL_ERROR`: Unexpected server error


            Endpoint-specific codes used by the signup / invites flow:

            - `ORGANIZATION_NAME_TAKEN`: 409 on `POST /organizations` — the
            requested
              org name (URL slug) is already in use. Retry with a different name.
            - `ORGANIZATION_NAME_RESERVED`: 409 on `POST /organizations` — the
            requested
              org name collides with a platform subdomain (e.g. `signup`, `admin`,
              `data`, `login`) and cannot be claimed. Retry with a different name.
            - `INVITE_ALREADY_CONSUMED`: 409 on `POST /organizations` — the
            supplied
              invite token has already been redeemed into an existing organization.
              Retry will not help; the token is dead.
            - `INVITE_ALREADY_CONSUMED_REVOKE`: 409 on `DELETE /invites/{token}`
            —
              consumed invites are preserved for audit and cannot be revoked.
            - `INVITE_INVALID`: 400 on `POST /organizations` — the supplied
            invite
              token is malformed or unknown.
            - `INVITE_EXPIRED`: 400 on `POST /organizations` — the supplied
            invite
              token is past its `expiresAt`.
            - `INVITE_EMAIL_MISMATCH`: 403 on `POST /organizations` — the invite
            is
              bound to a different email address than the caller.
        message:
          type: string
          description: Human-readable error message providing details about what went wrong
    DnsLabelPattern:
      type: string
      minLength: 1
      maxLength: 63
      pattern: ^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$
      description: >-
        DNS label — 1–63 chars, lowercase letters / digits / hyphens, no leading
        or trailing hyphen. Used as a subdomain for organizations.
    HumanTextPattern:
      type: string
      minLength: 1
      maxLength: 128
      pattern: ^[^\u0000-\u001F\u007F]+$
      description: >-
        Short human-readable text — non-empty, no ASCII control characters,
        capped at 128 chars. Used for display names, person names, and similar
        free-text fields where we want to keep things short and printable.
    MpaVersionPattern:
      type: string
      minLength: 1
      maxLength: 32
      pattern: ^[a-zA-Z0-9._-]+$
      description: >-
        MPA version identifier — alphanumeric, dot, hyphen, underscore; mirrors
        the version-string convention used in the on-disk markdown file names
        (e.g. v1-2026-05-19).
  responses:
    Unauthorized:
      description: Unauthorized
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    NotFound:
      description: The specified resource was not found.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

````