---
title: "Create Records"
method: POST
path: "/records"
tags: ["Sports Inventory"]
---

# Create Records

`POST /records`

## Request

- Base URL: `https://api.opti-x.optimove.net/sports-inventory/v1`
- URL: `https://api.opti-x.optimove.net/sports-inventory/v1/records`
- Auth: API key in header `x-api-key`

Creates a new entity, or **fully replaces the stored row** for an existing key (a full-row upsert): omitted optional fields are reset, not preserved. Use PUT when you need to retain fields you are not changing.

**Batch rules**
- The body is a JSON array of 1–500 records. The limit is a record count, not a byte-size guarantee — split earlier when records carry large translation or `extra` objects.
- Entities must be sent in order of hierarchy: Category → Class → Type → Event → Market → Selection, parents before children.
- Each HTTP method applies one action to the whole array — do not mix create, update, and delete in one request.
- Do not include the same entity type and key more than once in a batch; the first occurrence wins.

**Record expiry** — the optional `X-Expires-After` header (integer seconds, minimum 60, at most 2147483647) applies the same relative expiry to every record in the request. POST without the header creates or replaces the row without an expiry — clearing any existing expiry as part of the full-row replacement. Expiry is evaluated asynchronously and is not an exact client-side scheduler.

**Retries** — there is no client-supplied idempotency key. A repeated POST converges to the full row in the retried request, potentially overwriting a newer change. Ordering is not guaranteed across concurrent requests, so serialise dependent writes.

## Headers

- `x-api-key` string, required
- `x-brand-key` string, required
- `X-Expires-After` integer

## Request body

- union[]: Creates new entities
  - union
    - Selection: A specific betting selection within a Market. **Pricing rules:** You must provide pricing in one of the following ways: - **Full pricing:** provide all three fields (denPrice, numPrice, decPrice) - **Fractional only:** provide denPrice and numPrice (omit decPrice) - **Decimal only:** provide decPrice (omit denPrice and numPrice) - **Null decimal:** set decPrice to null (omit denPrice and numPrice) - **Null fractional:** set denPrice and numPrice to null (omit decPrice) - **All null:** set all three to null denPrice and numPrice must always be provided or omitted together.
      - `displayOrder` integer: The order by which this Selection should be displayed relative to others. Lower values display first
      - `displayStatus` 'Displayed' | 'NotDisplayed', required: Whether this Selection should be displayed in results or not. Setting this to NotDisplayed will mean all children will also not be displayed
      - `eventKey` string, required: The identifier of the Event this Selection belongs to
      - `extra` object: Extra metadata about this selection passed through the system for customer use
      - `marketKey` string, required: The identifier of the Market this Selection belongs to
      - `outcomeMeaningMajorCode` string: The major code of the outcome
      - `selectionKey` string, required: The unique identifier of this Selection
      - `selectionName` string, required: The publicly displayed name of this Selection
      - `selectionNameTranslated` object: The name of this Selection translated into other languages
      - `selectionPriceType` string: The price type of the Selection
      - `selectionStatus` 'Active' | 'Inactive', required: Whether this Selection is Active or Inactive. Inactive Selections are ignored by Optimove Personalize
      - `denPrice` integer, nullable
      - `numPrice` integer, nullable
      - `decPrice` number, nullable
    - Market: An outcome that can be bet on by users. This might be overall winner, or it could be a specific score
      - `categoryKey` string: The identifier of the Category this Market belongs to
      - `classKey` string: The identifier of the Class this Market belongs to
      - `displayOrder` integer: The order by which this Market should be displayed relative to others. Lower values display first
      - `displayStatus` 'Displayed' | 'NotDisplayed': Whether this Market should be displayed in results or not. Setting this to NotDisplayed will mean all children will also not be displayed
      - `eventKey` string, required: The identifier of the Event this Market belongs to
      - `extra` object: Extra metadata about this market passed through the system for customer use
      - `marketKey` string, required: The unique identifier of this Market
      - `marketName` string, required: The publicly displayed name of this Market
      - `marketNameTranslated` object: The name of this Market translated into other languages
      - `marketSort` string
      - `marketStatus` 'Active' | 'Inactive', required: Whether this Market is Active or Inactive. Inactive Markets are ignored by Optimove Personalize
      - `participants` string
      - `typeKey` string: The identifier of the Type this Market belongs to
    - Event: Represents the sporting Event instance. This could be a match between teams, Events are what bets are made on
      - `awayName` string: The name of the Away team for this Event
      - `categoryKey` string: The identifier of the Category this Event belongs to
      - `classKey` string: The identifier of the Class this Event belongs to
      - `classSortCode` string
      - `displayOrder` integer: The order by which this Event should be displayed relative to others. Lower values display first
      - `displayStatus` 'Displayed' | 'NotDisplayed': Whether this Event should be displayed in results or not. Setting this to NotDisplayed will mean all children will also not be displayed
      - `eventDateTime` string, date-time, required: The date and time of this Event. Required. Must be in ISO 8601 format with a timezone offset. Accepted offset forms are Z, ±hh:mm, ±hhmm, or ±hh (e.g. 2025-02-09T14:30:00Z, 2025-02-09T14:30:00+00:00, 2025-02-09T14:30:00.000+0000). Fractional seconds optional.
      - `eventEndDateTime` string, date-time: The end date and time of this Event. Optional. Must be in ISO 8601 UTC format (e.g. 2025-02-09T17:30:00Z or 2025-02-09T17:30:00.000+0000). Fractional seconds optional. When omitted, the effective end defaults to eventDateTime + 24h.
      - `eventKey` string, required: The unique identifier of this Event
      - `eventName` string, required: The publicly displayed name of this Event
      - `eventNameTranslated` object: The name of this Event translated into other languages
      - `eventSort` string
      - `eventStatus` 'Active' | 'Inactive', required: Whether this Event is Active or Inactive. Inactive Events are ignored by Optimove Personalize
      - `extra` object: Extra metadata about this event passed through the system for customer use
      - `homeName` string: The name of the Home team for this Event
      - `isEventFinished` boolean: Whether this Event is finished or not
      - `isEventStarted` boolean, required: Whether this Event is started or not
      - `typeKey` string, required: The identifier of the Type this Event belongs to
    - Category: Represents the top-level category for sports. Some examples include Football, or Tennis
      - `categoryKey` string, required: The unique identifier of this Category
      - `categoryName` string, required: The publicly displayed name of this Category
      - `categoryNameTranslated` object: The name of this Category translated into other languages
      - `displayOrder` integer: The order by which this Category should be displayed relative to others. Lower values display first.
      - `displayStatus` 'Displayed' | 'NotDisplayed': The display status - propagates to all children
      - `extra` object: Extra metadata about this category passed through the system for customer use
    - Class: Represents the second level classification for a sporting category. Often used for countries/regions to group sports Types
      - `categoryKey` string, required: The identifier of the Category this Class belongs to
      - `classKey` string, required: The unique identifier of this Class
      - `className` string, required: The publicly displayed name of this Class
      - `classNameTranslated` object: The name of this Class translated into other languages
      - `classStatus` 'Active' | 'Inactive': Whether this Class is Active or Inactive. Inactive Classes are ignored by Optimove Personalize
      - `displayOrder` integer: The order by which this Class should be displayed relative to others. Lower values display first
      - `displayStatus` 'Displayed' | 'NotDisplayed': Whether this Class should be displayed in results or not. Setting this to NotDisplayed will mean all children will also not be displayed
      - `extra` object: Extra metadata about this Class passed through the system for customer use
    - Type: Represents the Type of Event for the sporting Category. Used to group Events by championship, or league etc
      - `categoryKey` string: The identifier of the Category this Type belongs to
      - `classKey` string, required: The identifier of the Class this Type belongs to
      - `displayOrder` integer: The order by which this Type should be displayed relative to others. Lower values display first
      - `displayStatus` 'Displayed' | 'NotDisplayed': Whether this Type should be displayed in results or not. Setting this to NotDisplayed will mean all children will also not be displayed
      - `extra` object: Extra metadata about this Type passed through the system for customer use
      - `typeKey` string, required: The unique identifier of this Type
      - `typeName` string, required: The publicly displayed name of this Type
      - `typeNameTranslated` object: The name of this Type translated into other languages

## Response `202`

Accepted request

- Response: A 202 confirms **acceptance only**: the array passed validation and was accepted for asynchronous processing. It does not confirm that entities are visible downstream, that hierarchy references resolve, that a PUT matched an existing row, or that a DELETE matched an existing row. Treat a 202 with `success: false` as retryable — do not rely on the HTTP status alone.
  - `success` boolean: Have all records been accepted successfully. If false, some or all records may not have been recorded

## Other responses

- `400`: Bad Request

---

[API](https://skmtc.dev/optimove/apis/personalize-api.md) - [All operations](https://skmtc.dev/optimove/apis/personalize-api/llms.txt) - [OpenAPI document](https://skmtc.dev/optimove/apis/personalize-api/revisions/acd0c1299e2b?raw)
