openapi: 3.1.0
info:
  title: Experience API
  version: 1.0.0
paths:
  /organizations/{organizationId}/environments/{environmentSlug}/profiles:
    post:
      operationId: createAProfile
      summary: Create a profile
      description: >-
        Creates or updates a profile and returns it with selected experience variants. The `organizationId` is the
        **Client ID** from **Settings → SDK Keys → Optimization**.
      tags:
        - profiles
      parameters:
        - name: environmentSlug
          in: path
          description: The slug of the environment of the profile to retrieve
          required: true
          schema:
            type: string
            default: main
        - name: organizationId
          in: path
          description: The ID of the organization of the profile to retrieve
          required: true
          schema:
            type: string
        - name: locale
          in: query
          description: An ISO 639-1 language code used for experience evaluation.
          required: false
          schema:
            type: string
            default: en
        - name: type
          in: query
          description: Set to `preflight` to evaluate experiences without persisting state. Useful for SSR/ESR.
          required: false
          schema:
            $ref: '#/components/schemas/OrganizationsOrganizationIdEnvironmentsEnvironmentSlugProfilesPostParametersType'
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Profiles_createAProfile_Response_200'
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/badRequest'
        '404':
          description: Organization or environment not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateAProfileRequestNotFoundError'
        '429':
          description: Profile overload
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateAProfileRequestTooManyRequestsError'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/internalServerError'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/event'
  /organizations/{organizationId}/environments/{environmentSlug}/profiles/{profileId}:
    get:
      operationId: getAProfile
      summary: Get a profile
      description: >-
        Returns a profile with its currently selected experience variants. The `organizationId` is the **Client ID**
        from **Settings → SDK Keys → Optimization**.
      tags:
        - profiles
      parameters:
        - name: environmentSlug
          in: path
          description: The slug of the environment of the profile to retrieve
          required: true
          schema:
            type: string
            default: main
        - name: organizationId
          in: path
          description: The ID of the organization of the profile to retrieve
          required: true
          schema:
            type: string
        - name: profileId
          in: path
          description: The ID of the profile to retrieve
          required: true
          schema:
            type: string
        - name: locale
          in: query
          description: An ISO 639-1 language code used for experience evaluation.
          required: false
          schema:
            type: string
            default: en
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Profiles_getAProfile_Response_200'
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/badRequest'
        '404':
          description: Profile not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetAProfileRequestNotFoundError'
        '429':
          description: Profile overload
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetAProfileRequestTooManyRequestsError'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/internalServerError'
    post:
      operationId: updateAProfile
      summary: Update a profile
      description: >-
        Updates an existing profile and returns it with updated variant selections. The `organizationId` is the **Client
        ID** from **Settings → SDK Keys → Optimization**.
      tags:
        - profiles
      parameters:
        - name: environmentSlug
          in: path
          description: The slug of the environment of the profile to retrieve
          required: true
          schema:
            type: string
            default: main
        - name: organizationId
          in: path
          description: The ID of the organization of the profile to retrieve
          required: true
          schema:
            type: string
        - name: profileId
          in: path
          description: The ID of the profile to retrieve
          required: true
          schema:
            type: string
        - name: locale
          in: query
          description: An ISO 639-1 language code used for experience evaluation.
          required: false
          schema:
            type: string
            default: en
        - name: type
          in: query
          description: Set to `preflight` to evaluate experiences without persisting state. Useful for SSR/ESR.
          required: false
          schema:
            $ref: >-
              #/components/schemas/OrganizationsOrganizationIdEnvironmentsEnvironmentSlugProfilesProfileIdPostParametersType
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Profiles_updateAProfile_Response_200'
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/badRequest'
        '404':
          description: Organization or environment not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UpdateAProfileRequestNotFoundError'
        '429':
          description: Profile overload
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UpdateAProfileRequestTooManyRequestsError'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/internalServerError'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
    delete:
      operationId: deleteAProfile
      summary: Delete a profile
      description: >-
        Permanently removes a profile and all its aliases. The `organizationId` is the **Client ID** from **Settings →
        SDK Keys → Optimization**.
      tags:
        - profiles
      parameters:
        - name: environmentSlug
          in: path
          description: The slug of the environment of the profile to retrieve
          required: true
          schema:
            type: string
            default: main
        - name: organizationId
          in: path
          description: The ID of the organization of the profile to retrieve
          required: true
          schema:
            type: string
        - name: profileId
          in: path
          description: The ID of the profile to retrieve
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Profiles_deleteAProfile_Response_200'
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/badRequest'
        '404':
          description: Organization or environment not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeleteAProfileRequestNotFoundError'
        '429':
          description: Profile overload
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeleteAProfileRequestTooManyRequestsError'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/internalServerError'
  /organizations/{organizationId}/environments/{environmentSlug}/events:
    post:
      operationId: createOrUpdateProfilesSync
      summary: Create or update profiles (sync)
      description: >-
        Upserts up to 200 profiles from a batch of events (max 50 identify events, 50 unique profiles); returns profiles
        only — no `experiences` or `changes`. Intended for server-side use and does not resolve location or IP address.
      tags:
        - profiles
      parameters:
        - name: environmentSlug
          in: path
          description: The slug of the environment of the profile to retrieve
          required: true
          schema:
            type: string
            default: main
        - name: organizationId
          in: path
          description: The ID of the organization of the profile to retrieve
          required: true
          schema:
            type: string
        - name: locale
          in: query
          description: An ISO 639-1 language code used for experience evaluation.
          required: false
          schema:
            type: string
            default: en
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Profiles_createOrUpdateProfilesSync_Response_200'
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/badRequest'
        '404':
          description: Profile not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateOrUpdateProfilesSyncRequestNotFoundError'
        '429':
          description: Profile overload
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateOrUpdateProfilesSyncRequestTooManyRequestsError'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/internalServerError'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
  /organizations/{organizationId}/environments/{environmentSlug}/import/events:
    post:
      operationId: createOrUpdateProfilesAsync
      summary: Create or update profiles (async)
      description: >-
        Same as Batch Upsert Profiles but processes asynchronously, returning immediately with a confirmation. Always
        returns 200 — errors during background processing are handled internally.
      tags:
        - profiles
      parameters:
        - name: environmentSlug
          in: path
          description: The slug of the environment of the profile to retrieve
          required: true
          schema:
            type: string
            default: main
        - name: organizationId
          in: path
          description: The ID of the organization of the profile to retrieve
          required: true
          schema:
            type: string
        - name: locale
          in: query
          description: An ISO 639-1 language code used for experience evaluation.
          required: false
          schema:
            type: string
            default: en
      responses:
        '200':
          description: Accepted — events will be processed asynchronously
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Profiles_createOrUpdateProfilesAsync_Response_200'
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/badRequest'
        '429':
          description: Profile overload
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateOrUpdateProfilesAsyncRequestTooManyRequestsError'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/internalServerError'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
servers:
  - url: https://experience.ninetailed.co/v2
    description: (Production)
components:
  schemas:
    OrganizationsOrganizationIdEnvironmentsEnvironmentSlugProfilesPostParametersType:
      type: string
      enum:
        - preflight
      title: OrganizationsOrganizationIdEnvironmentsEnvironmentSlugProfilesPostParametersType
    EventEventsItemsContextApp:
      type: object
      properties:
        name:
          type: string
        version:
          type: string
      required:
        - name
        - version
      title: EventEventsItemsContextApp
    EventEventsItemsContextLibrary:
      type: object
      properties:
        name:
          type: string
        version:
          type: string
      required:
        - name
        - version
      title: EventEventsItemsContextLibrary
    EventEventsItemsContextCampaign:
      type: object
      properties: {}
      title: EventEventsItemsContextCampaign
    EventEventsItemsContextPageQuery:
      type: object
      properties:
        utm_campaign:
          type: string
        utm_content:
          type: string
      title: EventEventsItemsContextPageQuery
    EventEventsItemsContextPage:
      type: object
      properties:
        path:
          type: string
        query:
          $ref: '#/components/schemas/EventEventsItemsContextPageQuery'
        referrer:
          type: string
        search:
          type: string
        url:
          type: string
      title: EventEventsItemsContextPage
    EventEventsItemsContext:
      type: object
      properties:
        app:
          $ref: '#/components/schemas/EventEventsItemsContextApp'
        library:
          $ref: '#/components/schemas/EventEventsItemsContextLibrary'
        userAgent:
          type: string
        campaign:
          $ref: '#/components/schemas/EventEventsItemsContextCampaign'
        locale:
          type: string
        page:
          $ref: '#/components/schemas/EventEventsItemsContextPage'
      title: EventEventsItemsContext
    EventEventsItemsType:
      type: string
      enum:
        - page
        - track
        - identify
        - screen
        - component
      title: EventEventsItemsType
    EventEventsItems:
      type: object
      properties:
        channel:
          type: string
        context:
          $ref: '#/components/schemas/EventEventsItemsContext'
        messageId:
          type: string
        anonymousId:
          type: string
        type:
          $ref: '#/components/schemas/EventEventsItemsType'
        properties:
          $ref: '#/components/schemas/EventEventsItems'
      required:
        - channel
        - context
        - messageId
        - type
      title: EventEventsItems
    event:
      type: object
      properties:
        events:
          type: array
          items:
            $ref: '#/components/schemas/EventEventsItems'
      title: event
    Profiles_createAProfile_Response_200:
      type: object
      properties: {}
      description: Empty response body
      title: Profiles_createAProfile_Response_200
    BadRequestData:
      type: object
      properties: {}
      title: BadRequestData
    BadRequestError:
      type: object
      properties:
        code:
          type: string
      title: BadRequestError
    badRequest:
      type: object
      properties:
        message:
          type: string
        data:
          $ref: '#/components/schemas/BadRequestData'
        error:
          $ref: '#/components/schemas/BadRequestError'
      required:
        - message
        - data
      title: badRequest
    ConfigNotFoundErrorData:
      type: object
      properties: {}
      title: ConfigNotFoundErrorData
    ConfigNotFoundErrorError:
      type: object
      properties:
        code:
          type: string
      title: ConfigNotFoundErrorError
    configNotFoundError:
      type: object
      properties:
        message:
          type: string
        data:
          $ref: '#/components/schemas/ConfigNotFoundErrorData'
        error:
          $ref: '#/components/schemas/ConfigNotFoundErrorError'
      required:
        - message
        - data
      title: configNotFoundError
    NotFoundErrorData:
      type: object
      properties: {}
      title: NotFoundErrorData
    NotFoundErrorError:
      type: object
      properties:
        code:
          type: string
      title: NotFoundErrorError
    notFoundError:
      type: object
      properties:
        message:
          type: string
        data:
          $ref: '#/components/schemas/NotFoundErrorData'
        error:
          $ref: '#/components/schemas/NotFoundErrorError'
      required:
        - message
        - data
      title: notFoundError
    CreateAProfileRequestNotFoundError:
      oneOf:
        - $ref: '#/components/schemas/configNotFoundError'
        - $ref: '#/components/schemas/notFoundError'
      title: CreateAProfileRequestNotFoundError
    ProfileOverloadErrorData:
      type: object
      properties: {}
      title: ProfileOverloadErrorData
    ProfileOverloadErrorError:
      type: object
      properties:
        code:
          type: string
      title: ProfileOverloadErrorError
    profileOverloadError:
      type: object
      properties:
        message:
          type: string
        data:
          $ref: '#/components/schemas/ProfileOverloadErrorData'
        error:
          $ref: '#/components/schemas/ProfileOverloadErrorError'
      required:
        - message
        - data
      title: profileOverloadError
    TooManyRequestsData:
      type: object
      properties: {}
      title: TooManyRequestsData
    TooManyRequestsError:
      type: object
      properties:
        code:
          type: string
      title: TooManyRequestsError
    tooManyRequests:
      type: object
      properties:
        message:
          type: string
        data:
          $ref: '#/components/schemas/TooManyRequestsData'
        error:
          $ref: '#/components/schemas/TooManyRequestsError'
      required:
        - message
        - data
      title: tooManyRequests
    CreateAProfileRequestTooManyRequestsError:
      oneOf:
        - $ref: '#/components/schemas/profileOverloadError'
        - $ref: '#/components/schemas/tooManyRequests'
      title: CreateAProfileRequestTooManyRequestsError
    InternalServerErrorData:
      type: object
      properties: {}
      title: InternalServerErrorData
    InternalServerErrorError:
      type: object
      properties:
        code:
          type: string
      title: InternalServerErrorError
    internalServerError:
      type: object
      properties:
        message:
          type: string
        data:
          $ref: '#/components/schemas/InternalServerErrorData'
        error:
          $ref: '#/components/schemas/InternalServerErrorError'
      required:
        - message
        - data
      title: internalServerError
    Profiles_getAProfile_Response_200:
      type: object
      properties: {}
      description: Empty response body
      title: Profiles_getAProfile_Response_200
    ProfileNotFoundErrorData:
      type: object
      properties: {}
      title: ProfileNotFoundErrorData
    ProfileNotFoundErrorError:
      type: object
      properties:
        code:
          type: string
      title: ProfileNotFoundErrorError
    profileNotFoundError:
      type: object
      properties:
        message:
          type: string
        data:
          $ref: '#/components/schemas/ProfileNotFoundErrorData'
        error:
          $ref: '#/components/schemas/ProfileNotFoundErrorError'
      required:
        - message
        - data
      title: profileNotFoundError
    GetAProfileRequestNotFoundError:
      oneOf:
        - $ref: '#/components/schemas/profileNotFoundError'
        - $ref: '#/components/schemas/notFoundError'
      title: GetAProfileRequestNotFoundError
    GetAProfileRequestTooManyRequestsError:
      oneOf:
        - $ref: '#/components/schemas/profileOverloadError'
        - $ref: '#/components/schemas/tooManyRequests'
      title: GetAProfileRequestTooManyRequestsError
    OrganizationsOrganizationIdEnvironmentsEnvironmentSlugProfilesProfileIdPostParametersType:
      type: string
      enum:
        - preflight
      title: OrganizationsOrganizationIdEnvironmentsEnvironmentSlugProfilesProfileIdPostParametersType
    Profiles_updateAProfile_Response_200:
      type: object
      properties: {}
      description: Empty response body
      title: Profiles_updateAProfile_Response_200
    UpdateAProfileRequestNotFoundError:
      oneOf:
        - $ref: '#/components/schemas/configNotFoundError'
        - $ref: '#/components/schemas/notFoundError'
      title: UpdateAProfileRequestNotFoundError
    UpdateAProfileRequestTooManyRequestsError:
      oneOf:
        - $ref: '#/components/schemas/profileOverloadError'
        - $ref: '#/components/schemas/tooManyRequests'
      title: UpdateAProfileRequestTooManyRequestsError
    Profiles_deleteAProfile_Response_200:
      type: object
      properties: {}
      description: Empty response body
      title: Profiles_deleteAProfile_Response_200
    DeleteAProfileRequestNotFoundError:
      oneOf:
        - $ref: '#/components/schemas/configNotFoundError'
        - $ref: '#/components/schemas/notFoundError'
      title: DeleteAProfileRequestNotFoundError
    DeleteAProfileRequestTooManyRequestsError:
      oneOf:
        - $ref: '#/components/schemas/profileOverloadError'
        - $ref: '#/components/schemas/tooManyRequests'
      title: DeleteAProfileRequestTooManyRequestsError
    Profiles_createOrUpdateProfilesSync_Response_200:
      type: object
      properties: {}
      description: Empty response body
      title: Profiles_createOrUpdateProfilesSync_Response_200
    CreateOrUpdateProfilesSyncRequestNotFoundError:
      oneOf:
        - $ref: '#/components/schemas/profileNotFoundError'
        - $ref: '#/components/schemas/notFoundError'
      title: CreateOrUpdateProfilesSyncRequestNotFoundError
    CreateOrUpdateProfilesSyncRequestTooManyRequestsError:
      oneOf:
        - $ref: '#/components/schemas/profileOverloadError'
        - $ref: '#/components/schemas/tooManyRequests'
      title: CreateOrUpdateProfilesSyncRequestTooManyRequestsError
    Profiles_createOrUpdateProfilesAsync_Response_200:
      type: object
      properties: {}
      description: Empty response body
      title: Profiles_createOrUpdateProfilesAsync_Response_200
    CreateOrUpdateProfilesAsyncRequestTooManyRequestsError:
      oneOf:
        - $ref: '#/components/schemas/profileOverloadError'
        - $ref: '#/components/schemas/tooManyRequests'
      title: CreateOrUpdateProfilesAsyncRequestTooManyRequestsError
