openapi: 3.0.1 info: title: Ninetailed Experience Events Profiles API description: The core REST API for the Ninetailed (now Contentful Personalization) platform. Returns visitor profiles and resolves which experience and variant to render based on audience rules. Deployed on the edge for high performance. Supports profile creation, updates, retrieval, deletion, event tracking, and batch event import for audience segmentation and A/B test delivery. version: '2' contact: name: Ninetailed Support url: https://www.contentful.com/help/ license: name: Proprietary servers: - url: https://experience.ninetailed.co/v2/organizations/{organizationId}/environments/{environmentSlug} description: Ninetailed Experience API edge endpoint variables: organizationId: description: The organization ID (Client ID) found in the SDK Keys section on the Optimization tab. default: YOUR_ORGANIZATION_ID environmentSlug: description: The environment slug (e.g. "main"). default: main tags: - name: Profiles description: Operations for creating, reading, updating, and deleting visitor profiles. paths: /profiles: post: operationId: createProfile summary: Create Profile description: Creates a new visitor profile and returns the profile object including resolved experiences and variant assignments. tags: - Profiles parameters: - $ref: '#/components/parameters/locale' - $ref: '#/components/parameters/type' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ProfileRequest' example: events: - type: page name: Home properties: url: https://example.com/ path: / title: Home Page text/plain: schema: $ref: '#/components/schemas/ProfileRequest' responses: '200': description: Profile created successfully with resolved experiences. content: application/json: schema: $ref: '#/components/schemas/ProfileResponse' '400': $ref: '#/components/responses/BadRequest' '404': $ref: '#/components/responses/NotFound' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalServerError' /profiles/{profileId}: get: operationId: getProfile summary: Get Profile description: Retrieves an existing visitor profile by ID. Does not return experiences or changes. tags: - Profiles parameters: - $ref: '#/components/parameters/profileId' - $ref: '#/components/parameters/locale' responses: '200': description: Profile retrieved successfully. content: application/json: schema: $ref: '#/components/schemas/ProfileOnlyResponse' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalServerError' post: operationId: updateProfile summary: Update Profile description: Updates an existing visitor profile by sending new events. Returns the updated profile with resolved experiences and variant assignments. tags: - Profiles parameters: - $ref: '#/components/parameters/profileId' - $ref: '#/components/parameters/locale' - $ref: '#/components/parameters/type' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ProfileRequest' example: events: - type: identify userId: user-123 traits: email: user@example.com plan: pro text/plain: schema: $ref: '#/components/schemas/ProfileRequest' responses: '200': description: Profile updated successfully with resolved experiences. content: application/json: schema: $ref: '#/components/schemas/ProfileResponse' '400': $ref: '#/components/responses/BadRequest' '404': $ref: '#/components/responses/NotFound' '429': $ref: '#/components/responses/TooManyRequests' '500': $ref: '#/components/responses/InternalServerError' delete: operationId: deleteProfile summary: Delete Profile description: Deletes a visitor profile by ID for GDPR/right-to-erasure compliance. tags: - Profiles parameters: - $ref: '#/components/parameters/profileId' responses: '200': description: Profile deleted successfully. content: application/json: schema: $ref: '#/components/schemas/DeleteResponse' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalServerError' components: schemas: Session: type: object description: Session-level metadata for the visitor. properties: id: type: string description: Unique session identifier. isReturningVisitor: type: boolean description: True if the visitor has been seen in a previous session. landingPage: type: string description: URL of the first page visited in this session. count: type: integer description: Number of sessions this visitor has had. sessionLength: type: integer description: Length of the current session in seconds. ProfileResponse: type: object description: Standard envelope response containing a profile with resolved experiences and changes. properties: data: type: object description: Response payload. properties: profile: $ref: '#/components/schemas/Profile' experiences: type: array description: Resolved experiences for this profile. items: $ref: '#/components/schemas/Experience' changes: type: array description: Content changes to apply for personalization. items: $ref: '#/components/schemas/Change' error: type: object nullable: true description: Null on success; error details on failure. message: type: string example: ok DeleteResponse: type: object description: Response envelope for a successful delete operation. properties: data: type: object description: Empty object on successful deletion. error: type: object nullable: true message: type: string example: ok ProfileRequestOptions: type: object description: Optional configuration for the profile request. properties: preflight: type: boolean description: When true, performs edge-optimized preflight resolution without full profile persistence. Event: type: object required: - type description: A behavioral or identity event associated with a visitor profile. properties: type: type: string enum: - page - track - identify - screen - component description: The type of event being recorded. userId: type: string description: Stable user identifier for linking anonymous and identified sessions. anonymousId: type: string description: Anonymous identifier for unidentified visitors. name: type: string description: Name of the page, screen, or track event. traits: type: object additionalProperties: true description: Key-value pairs describing user attributes (used with identify events). properties: type: object additionalProperties: true description: Key-value pairs describing event properties (used with page/track events). properties: url: type: string format: uri description: Full URL of the page. path: type: string description: Path portion of the URL. title: type: string description: Page title. referrer: type: string format: uri description: Referring URL. timestamp: type: string format: date-time description: ISO 8601 timestamp of when the event occurred. Location: type: object description: Geographic location resolved from the visitor's IP address. properties: lat: type: number format: double description: Latitude coordinate. lon: type: number format: double description: Longitude coordinate. city: type: string description: City name. region: type: string description: Region or state code. country: type: string description: ISO 3166-1 alpha-2 country code. timezone: type: string description: IANA timezone identifier (e.g. "America/New_York"). ProfileRequest: type: object required: - events description: Request body for creating or updating a visitor profile. properties: events: type: array description: One or more events to record for this profile. items: $ref: '#/components/schemas/Event' options: $ref: '#/components/schemas/ProfileRequestOptions' ApiError: type: object description: Error response envelope. required: - message - error properties: message: type: string description: Human-readable error message. data: type: object description: Empty object on error. error: type: object description: Structured error details. properties: code: type: string enum: - ERR_INVALID_DATA - ERR_CONFIG_NOT_FOUND - ERR_PROFILE_NOT_FOUND - ERR_NAMESPACE_MISMATCH - ERR_PROFILE_OVERLOAD - ERR_INTERNAL_SERVER_ERROR description: Machine-readable error code. Profile: type: object description: A visitor profile containing identity, behavioral, and session data used for personalization. properties: id: type: string description: Unique identifier for the visitor profile. stableId: type: string description: Stable cross-session identifier for the visitor. random: type: number format: double minimum: 0 maximum: 1 description: Random value (0-1) used for traffic splitting in A/B tests. audiences: type: array description: List of audience IDs the visitor currently qualifies for. items: type: string traits: type: object additionalProperties: true description: Merged identify traits for the visitor. location: $ref: '#/components/schemas/Location' session: $ref: '#/components/schemas/Session' jurisdiction: type: string description: Regulatory jurisdiction code (e.g. "GDPR") resolved from location. stickyVariants: type: object additionalProperties: type: string description: Map of experience ID to variant index for sticky (consistent) assignment. Change: type: object description: A content change to apply for a personalized experience, keyed by component. properties: key: type: string description: Identifier of the component or content slot to change. type: type: string enum: - Variable description: Type of change (currently only "Variable" is supported). value: type: string description: The variant entry ID to render for this component. meta: type: object description: Metadata about the experience driving this change. properties: experienceId: type: string description: ID of the experience that produced this change. variantIndex: type: integer description: Variant index assigned for this experience. ProfileOnlyResponse: type: object description: Response envelope containing only the profile (no experiences or changes). properties: data: $ref: '#/components/schemas/Profile' error: type: object nullable: true message: type: string example: ok Experience: type: object description: A resolved experience with the variant the visitor should receive. properties: experienceId: type: string description: Unique identifier of the experience/experiment. variantIndex: type: integer description: Zero-based index of the assigned variant (0 = control, 1+ = variants). variants: type: object additionalProperties: type: string description: Map of component keys to variant entry IDs for this experience assignment. sticky: type: boolean description: When true, the variant assignment is persisted for consistency. responses: NotFound: description: The requested resource was not found. content: application/json: schema: $ref: '#/components/schemas/ApiError' example: message: Profile not found data: {} error: code: ERR_PROFILE_NOT_FOUND InternalServerError: description: An unexpected server error occurred. content: application/json: schema: $ref: '#/components/schemas/ApiError' example: message: Internal server error data: {} error: code: ERR_INTERNAL_SERVER_ERROR TooManyRequests: description: Profile has exceeded the allowed number of concurrent requests. content: application/json: schema: $ref: '#/components/schemas/ApiError' example: message: Profile overload data: {} error: code: ERR_PROFILE_OVERLOAD BadRequest: description: Invalid request data. content: application/json: schema: $ref: '#/components/schemas/ApiError' example: message: Invalid data provided data: {} error: code: ERR_INVALID_DATA parameters: type: name: type in: query required: false description: Optional request type modifier. Set to "preflight" for pre-render edge requests. schema: type: string enum: - preflight profileId: name: profileId in: path required: true description: Unique identifier of the visitor profile. schema: type: string locale: name: locale in: query required: false description: BCP 47 locale string used for resolving localized experiences. Defaults to "en". schema: type: string default: en example: en-US