Skip to content

Product Publishing Dates v4

Sub-resource of products holding the dated milestones of a title: when it is published, when a sales embargo lifts, when it may be announced to the trade or the public, when it goes out of print. Each entry is one date with one meaning, for one product format.

The meaning of a date is a role code from ONIX Codelist 163. An entry is identified by the product, the product_type, the publishing_date_role_code and, optionally, a set of channels. Formats are dated independently, so an e-book and its printed counterpart carry separate entries even when the date is the same.


Endpoints


GET /resource/v4/products/{product_id}/publishing_dates

Retrieve publishing dates for a product

Description

Returns all publishing-date records for the product, across every format and role, paginated. Most products return one or two entries.

Only two filters are supported, and any other query parameter is rejected with 400 Bad Request rather than ignored:

  • ?product_type=ebook — narrow to one format.
  • ?channels= / ?channels__contains=… — narrow by channel scope.

There is no filter on publishing_date_role_code and none on publishing_date, so selecting "the publication date of the e-book" means fetching the product's records and filtering client-side. The sort parameter is accepted but has no effect; records come back in creation order. See Resource Queries for the query syntax.

Input parameters

Path parameters

Parameter Type Default Nullable Description
product_id string No UUID of the product.

Query parameters

Parameter Type Default Nullable Description
channels string No Exact match on the whole channel list. The value is normalised the same way as the field itself — lower-cased, de-duplicated, sorted — so `spotify,itunes` and `itunes,spotify` are equivalent. An empty value (`?channels=`) selects the records that are not scoped to any channel, which in practice is nearly all of them.
channels__contains string No Filter to records whose channel list contains the given value, e.g. `?channels__contains=itunes`. Several comma-separated values are combined with AND, so `itunes,spotify` returns only records scoped to both. Note that this is a substring match rather than a match on whole entries: `?channels__contains=book` also matches `bookbeat` and `bookwire`.
product_type string No Filter by product format, e.g. `ebook`, `book`, `audiobook`, `nonbook`. Matched case-insensitively, since values are normalised to lower case.

Responses

{
    "_links": {},
    "_pagination": {},
    "items": [
        {
            "_id": "888ffcf3-e685-4e4c-9999-b207a925d6e3",
            "_version": "4.0",
            "_links": {},
            "_legacy_id": 133777,
            "product_type": "ebook",
            "publishing_date_role_code": "01",
            "publishing_date": "2021-07-30",
            "channels": [],
            "created": 1779195413
        }
    ]
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "type": "object",
    "additionalProperties": false,
    "properties": {
        "_links": {
            "type": "object"
        },
        "_pagination": {
            "type": "object"
        },
        "items": {
            "type": "array",
            "items": {
                "type": "object",
                "additionalProperties": false,
                "description": "One dated milestone of a product — one ONIX publishing-date role with one date, for one product format and optionally for named distribution channels.",
                "properties": {
                    "_id": {
                        "type": "string",
                        "description": "UUID of this publishing date record. Stable for the life of the record.",
                        "example": "888ffcf3-e685-4e4c-9999-b207a925d6e3"
                    },
                    "_version": {
                        "type": "string",
                        "description": "API version of the returned resource.",
                        "example": "4.0"
                    },
                    "_links": {
                        "type": "object",
                        "description": "HAL-style links. Contains only `self`, the canonical URL of this record."
                    },
                    "_legacy_id": {
                        "type": "integer",
                        "description": "Legacy integer identifier of this resource, kept so existing integrations can correlate their own records. This is the value the v3 endpoint returns as `_id`; in v4 `_id` is the UUID and the integer moves here.",
                        "example": 133777
                    },
                    "product_type": {
                        "type": "string",
                        "description": "The product format this date applies to. Dates are held per format because formats\nare published, embargoed and withdrawn independently, so the same role may appear\nseveral times for one product with different dates. A product with an e-book and a\nprint edition that share a publication date therefore carries *two* records, not one.\n\nValidated against the platform's product types and normalised to lower case; an\nunrecognised value is rejected with `400 Bad Request`. In practice only `ebook`,\n`book`, `audiobook` and `nonbook` are meaningful here — the remaining accepted values\ndescribe order lines rather than publishable formats.\n",
                        "example": "ebook",
                        "x-enum-descriptions": {
                            "ebook": "Digital edition in any e-book file format (EPUB, PDF, MOBI).",
                            "book": "Printed edition, whether stocked or print-on-demand.",
                            "audiobook": "Audio edition, downloadable or streamed.",
                            "nonbook": "Non-book article sold alongside the title (merchandise, media, bundles).",
                            "print_author": "Author copies of the printed edition.",
                            "reviewers_copy": "Review copy of the digital edition.",
                            "shipment": "Shipping charge line. Not a publishable format; no publishing dates apply.",
                            "fee": "Fee line. Not a publishable format; no publishing dates apply.",
                            "service": "Service line. Not a publishable format; no publishing dates apply."
                        }
                    },
                    "publishing_date_role_code": {
                        "type": "string",
                        "description": "What the date *means*. A two-character code from ONIX\n[Codelist 163, Publishing date role](https://ns.editeur.org/onix/en/163). The full\ncodelist is accepted — 23 codes — and anything else is rejected with\n`400 Bad Request`. Note that these are the ONIX codes themselves, stored and returned\nverbatim including the leading zero: `\"01\"`, not `1` and not `\"publication\"`. Codes\n`32` and `33` postdate Codelist 163 Issue 67 and are accepted even though older\ncopies of the codelist do not list them.\n\nThe two codes that carry the day-to-day traffic:\n\n- `\"01\"` **Publication date** — the nominal publication date, used for planning and\n  promotion. In ONIX terms this is *not* by itself a permission to sell: absent an\n  embargo, retail sales may begin as soon as the retailer has stock. It is the code\n  most products carry.\n- `\"02\"` **Sales embargo date** — the date a retail sales embargo lifts, known in\n  some markets as the strict on-sale date. This is the code that tells a retailer\n  \"not before this day\". Where it appears it normally accompanies a role `\"01\"`\n  record, frequently carrying the same date.\n\nA role `\"02\"` record whose date has passed is a spent embargo rather than an active\nrestriction; nothing re-evaluates it, and such records are common.\n\nThis API maintains no relationship between roles: a record created, updated or\ndeleted here leaves every other record of the product untouched.\n\nThe remaining codes are accepted but exist only where they have been created\nexplicitly. The commercially significant ones:\n\n- `\"09\"` Public announcement date, `\"10\"` Trade announcement date — before these\n  dates the metadata is embargoed for internal or trade-only use respectively.\n- `\"11\"` Date of first publication (of the work, not this edition) and `\"20\"` the\n  same for the original language of a translation.\n- `\"13\"` Out-of-print / permanently withdrawn date, `\"22\"` Expected availability\n  date after a temporary withdrawal.\n- `\"27\"` Preorder embargo date — the earliest date a preorder may be accepted, which\n  is a different and usually earlier gate than `\"02\"`.\n- `\"23\"` Review embargo date, `\"25\"` Publisher's reservation order deadline.\n- `\"12\"` / `\"26\"` Latest and forthcoming reprint date, `\"16\"` / `\"21\"` latest and\n  forthcoming reissue date, `\"19\"` publication date of the print counterpart,\n  `\"28\"` transfer date, `\"29\"` date of production, `\"35\"` CIP date.\n- `\"30\"` / `\"31\"` / `\"32\"` / `\"33\"` Streaming, subscription, download and purchase\n  embargo dates — for digital products sold through more than one consumption model,\n  where one model becomes available later than another.\n\n**Uniqueness.** Within one product and `product_type` there may be at most one record\nper role with an empty `channels` list, and two channel-scoped records for the same\nrole must not share a channel. Either collision is rejected with `400 Bad Request`.\nNo role is required to be present, roles need not be in chronological order, and\nthere is no cross-role validation at all: an out-of-print date (`\"13\"`) earlier than\nthe publication date (`\"01\"`) is accepted.\n\n**These dates do not decide availability.** Whether a product is on sale is governed\nby the product's own expected publication date per format, which the v3 product\nresource exposes as `publication_date` and the v4 product resource does not expose at\nall. Creating a role `\"01\"` record here does not make a product available, and\ndeleting one does not withdraw it.\n",
                        "example": "01"
                    },
                    "publishing_date": {
                        "type": "string",
                        "format": "date",
                        "nullable": false,
                        "description": "The date itself, as a plain calendar date in `YYYY-MM-DD` form. Always returned in\nexactly that form; there is no time component, no time zone offset, and no\nnormalisation across zones. A date is the whole day, inclusive — an embargo dated\n`2026-04-15` lifts *on* 15 April, and an out-of-print date of `2026-04-15` means the\nproduct is withdrawn on that day.\n\n**Partial dates are not supported.** ONIX allows a publishing date to carry a reduced\nprecision such as `2026` or `202604`, declared through the `dateformat` attribute\n([Codelist 55](https://ns.editeur.org/onix/en/55)); this field does not. Source data\nthat names only a month or a year has to be resolved to a single day before it can be\nsent.\n\nInput is more forgiving than the output format suggests: `2026-4-5`, `20260405` and\n`20260405T00:00:00` are all accepted and all come back as `2026-04-05`, with any time\ncomponent discarded. A value that cannot be parsed as a whole day — including `2026`\nand `2026-04` — is rejected with `400 Bad Request`. `YYYY-MM-DD` avoids all of this.\n",
                        "example": "2021-07-30"
                    },
                    "channels": {
                        "type": "array",
                        "description": "Distribution channels this date is scoped to. An empty list — by far the normal case —\nmeans the date applies to every channel.\n\nA non-empty list narrows the record to named distribution partners, so that one format\ncan carry different dates for different partners: a title that becomes available on\none retailer a week before it reaches the library platforms, for example.\n\nValues are the platform's distribution-channel slugs. Those in common use are:\n\n- `amazon`\n- `itunes`\n- `kobo`\n- `spotify`\n- `skoobe`\n- `divibib`\n- `overdrive`\n- `bookbeat`\n- `bookwire`\n\nThe list is open-ended — a realm distributes through whichever partners it has\ncontracts with — and it is *not* validated against that vocabulary: a typo is accepted\nas given and will simply never match anything.\n\nValues are lower-cased, de-duplicated and sorted, so\n`[\"Spotify\", \"itunes\", \"itunes\"]` comes back as `[\"itunes\", \"spotify\"]`, and on update the\nlist is replaced wholesale rather than merged.\n\nUniqueness is enforced per channel, so `itunes` and `spotify` may each carry their own\nrole `\"02\"` alongside one unscoped role `\"02\"`.\n",
                        "items": {
                            "type": "string"
                        },
                        "example": []
                    },
                    "created": {
                        "type": "integer",
                        "description": "When this record was created, in seconds since the Unix epoch (UTC). This is the creation of the record, not the date it describes — a record created today can perfectly well carry a publication date from 2006.",
                        "nullable": true,
                        "example": 1779195413
                    }
                },
                "required": []
            }
        }
    },
    "required": [
        "_links",
        "_pagination",
        "items"
    ]
}

POST /resource/v4/products/{product_id}/publishing_dates

Create a publishing date

Description

Creates one publishing-date record. product_type, publishing_date_role_code and publishing_date are all required in practice — none of them has a usable default, and an omitted or empty product_type fails validation. channels may be omitted, which scopes the date to every channel.

The example below sets a sales embargo ("02") on the e-book for Apple Books and Kobo only: those two partners may not sell before 1 February 2026, while every other channel is governed by whatever unscoped records the product carries.

Input parameters

Path parameters

Parameter Type Default Nullable Description
product_id string No UUID of the product.

Request body

{
    "product_type": "ebook",
    "publishing_date_role_code": "02",
    "publishing_date": "2026-02-01",
    "channels": [
        "itunes",
        "spotify"
    ]
}
Schema of the request body
{
    "type": "object",
    "additionalProperties": false,
    "description": "One dated milestone of a product — one ONIX publishing-date role with one date, for one product format and optionally for named distribution channels.",
    "properties": {
        "_id": {
            "type": "string",
            "description": "UUID of this publishing date record. Stable for the life of the record.",
            "example": "888ffcf3-e685-4e4c-9999-b207a925d6e3"
        },
        "_version": {
            "type": "string",
            "description": "API version of the returned resource.",
            "example": "4.0"
        },
        "_links": {
            "type": "object",
            "description": "HAL-style links. Contains only `self`, the canonical URL of this record."
        },
        "_legacy_id": {
            "type": "integer",
            "description": "Legacy integer identifier of this resource, kept so existing integrations can correlate their own records. This is the value the v3 endpoint returns as `_id`; in v4 `_id` is the UUID and the integer moves here.",
            "example": 133777
        },
        "product_type": {
            "type": "string",
            "description": "The product format this date applies to. Dates are held per format because formats\nare published, embargoed and withdrawn independently, so the same role may appear\nseveral times for one product with different dates. A product with an e-book and a\nprint edition that share a publication date therefore carries *two* records, not one.\n\nValidated against the platform's product types and normalised to lower case; an\nunrecognised value is rejected with `400 Bad Request`. In practice only `ebook`,\n`book`, `audiobook` and `nonbook` are meaningful here — the remaining accepted values\ndescribe order lines rather than publishable formats.\n",
            "example": "ebook",
            "x-enum-descriptions": {
                "ebook": "Digital edition in any e-book file format (EPUB, PDF, MOBI).",
                "book": "Printed edition, whether stocked or print-on-demand.",
                "audiobook": "Audio edition, downloadable or streamed.",
                "nonbook": "Non-book article sold alongside the title (merchandise, media, bundles).",
                "print_author": "Author copies of the printed edition.",
                "reviewers_copy": "Review copy of the digital edition.",
                "shipment": "Shipping charge line. Not a publishable format; no publishing dates apply.",
                "fee": "Fee line. Not a publishable format; no publishing dates apply.",
                "service": "Service line. Not a publishable format; no publishing dates apply."
            }
        },
        "publishing_date_role_code": {
            "type": "string",
            "description": "What the date *means*. A two-character code from ONIX\n[Codelist 163, Publishing date role](https://ns.editeur.org/onix/en/163). The full\ncodelist is accepted — 23 codes — and anything else is rejected with\n`400 Bad Request`. Note that these are the ONIX codes themselves, stored and returned\nverbatim including the leading zero: `\"01\"`, not `1` and not `\"publication\"`. Codes\n`32` and `33` postdate Codelist 163 Issue 67 and are accepted even though older\ncopies of the codelist do not list them.\n\nThe two codes that carry the day-to-day traffic:\n\n- `\"01\"` **Publication date** — the nominal publication date, used for planning and\n  promotion. In ONIX terms this is *not* by itself a permission to sell: absent an\n  embargo, retail sales may begin as soon as the retailer has stock. It is the code\n  most products carry.\n- `\"02\"` **Sales embargo date** — the date a retail sales embargo lifts, known in\n  some markets as the strict on-sale date. This is the code that tells a retailer\n  \"not before this day\". Where it appears it normally accompanies a role `\"01\"`\n  record, frequently carrying the same date.\n\nA role `\"02\"` record whose date has passed is a spent embargo rather than an active\nrestriction; nothing re-evaluates it, and such records are common.\n\nThis API maintains no relationship between roles: a record created, updated or\ndeleted here leaves every other record of the product untouched.\n\nThe remaining codes are accepted but exist only where they have been created\nexplicitly. The commercially significant ones:\n\n- `\"09\"` Public announcement date, `\"10\"` Trade announcement date — before these\n  dates the metadata is embargoed for internal or trade-only use respectively.\n- `\"11\"` Date of first publication (of the work, not this edition) and `\"20\"` the\n  same for the original language of a translation.\n- `\"13\"` Out-of-print / permanently withdrawn date, `\"22\"` Expected availability\n  date after a temporary withdrawal.\n- `\"27\"` Preorder embargo date — the earliest date a preorder may be accepted, which\n  is a different and usually earlier gate than `\"02\"`.\n- `\"23\"` Review embargo date, `\"25\"` Publisher's reservation order deadline.\n- `\"12\"` / `\"26\"` Latest and forthcoming reprint date, `\"16\"` / `\"21\"` latest and\n  forthcoming reissue date, `\"19\"` publication date of the print counterpart,\n  `\"28\"` transfer date, `\"29\"` date of production, `\"35\"` CIP date.\n- `\"30\"` / `\"31\"` / `\"32\"` / `\"33\"` Streaming, subscription, download and purchase\n  embargo dates — for digital products sold through more than one consumption model,\n  where one model becomes available later than another.\n\n**Uniqueness.** Within one product and `product_type` there may be at most one record\nper role with an empty `channels` list, and two channel-scoped records for the same\nrole must not share a channel. Either collision is rejected with `400 Bad Request`.\nNo role is required to be present, roles need not be in chronological order, and\nthere is no cross-role validation at all: an out-of-print date (`\"13\"`) earlier than\nthe publication date (`\"01\"`) is accepted.\n\n**These dates do not decide availability.** Whether a product is on sale is governed\nby the product's own expected publication date per format, which the v3 product\nresource exposes as `publication_date` and the v4 product resource does not expose at\nall. Creating a role `\"01\"` record here does not make a product available, and\ndeleting one does not withdraw it.\n",
            "example": "01"
        },
        "publishing_date": {
            "type": "string",
            "format": "date",
            "nullable": false,
            "description": "The date itself, as a plain calendar date in `YYYY-MM-DD` form. Always returned in\nexactly that form; there is no time component, no time zone offset, and no\nnormalisation across zones. A date is the whole day, inclusive — an embargo dated\n`2026-04-15` lifts *on* 15 April, and an out-of-print date of `2026-04-15` means the\nproduct is withdrawn on that day.\n\n**Partial dates are not supported.** ONIX allows a publishing date to carry a reduced\nprecision such as `2026` or `202604`, declared through the `dateformat` attribute\n([Codelist 55](https://ns.editeur.org/onix/en/55)); this field does not. Source data\nthat names only a month or a year has to be resolved to a single day before it can be\nsent.\n\nInput is more forgiving than the output format suggests: `2026-4-5`, `20260405` and\n`20260405T00:00:00` are all accepted and all come back as `2026-04-05`, with any time\ncomponent discarded. A value that cannot be parsed as a whole day — including `2026`\nand `2026-04` — is rejected with `400 Bad Request`. `YYYY-MM-DD` avoids all of this.\n",
            "example": "2021-07-30"
        },
        "channels": {
            "type": "array",
            "description": "Distribution channels this date is scoped to. An empty list — by far the normal case —\nmeans the date applies to every channel.\n\nA non-empty list narrows the record to named distribution partners, so that one format\ncan carry different dates for different partners: a title that becomes available on\none retailer a week before it reaches the library platforms, for example.\n\nValues are the platform's distribution-channel slugs. Those in common use are:\n\n- `amazon`\n- `itunes`\n- `kobo`\n- `spotify`\n- `skoobe`\n- `divibib`\n- `overdrive`\n- `bookbeat`\n- `bookwire`\n\nThe list is open-ended — a realm distributes through whichever partners it has\ncontracts with — and it is *not* validated against that vocabulary: a typo is accepted\nas given and will simply never match anything.\n\nValues are lower-cased, de-duplicated and sorted, so\n`[\"Spotify\", \"itunes\", \"itunes\"]` comes back as `[\"itunes\", \"spotify\"]`, and on update the\nlist is replaced wholesale rather than merged.\n\nUniqueness is enforced per channel, so `itunes` and `spotify` may each carry their own\nrole `\"02\"` alongside one unscoped role `\"02\"`.\n",
            "items": {
                "type": "string"
            },
            "example": []
        },
        "created": {
            "type": "integer",
            "description": "When this record was created, in seconds since the Unix epoch (UTC). This is the creation of the record, not the date it describes — a record created today can perfectly well carry a publication date from 2006.",
            "nullable": true,
            "example": 1779195413
        }
    },
    "required": []
}

Responses

{
    "_id": "888ffcf3-e685-4e4c-9999-b207a925d6e3",
    "_version": "4.0",
    "_links": {},
    "_legacy_id": 133777,
    "product_type": "ebook",
    "publishing_date_role_code": "01",
    "publishing_date": "2021-07-30",
    "channels": [],
    "created": 1779195413
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "type": "object",
    "additionalProperties": false,
    "description": "One dated milestone of a product — one ONIX publishing-date role with one date, for one product format and optionally for named distribution channels.",
    "properties": {
        "_id": {
            "type": "string",
            "description": "UUID of this publishing date record. Stable for the life of the record.",
            "example": "888ffcf3-e685-4e4c-9999-b207a925d6e3"
        },
        "_version": {
            "type": "string",
            "description": "API version of the returned resource.",
            "example": "4.0"
        },
        "_links": {
            "type": "object",
            "description": "HAL-style links. Contains only `self`, the canonical URL of this record."
        },
        "_legacy_id": {
            "type": "integer",
            "description": "Legacy integer identifier of this resource, kept so existing integrations can correlate their own records. This is the value the v3 endpoint returns as `_id`; in v4 `_id` is the UUID and the integer moves here.",
            "example": 133777
        },
        "product_type": {
            "type": "string",
            "description": "The product format this date applies to. Dates are held per format because formats\nare published, embargoed and withdrawn independently, so the same role may appear\nseveral times for one product with different dates. A product with an e-book and a\nprint edition that share a publication date therefore carries *two* records, not one.\n\nValidated against the platform's product types and normalised to lower case; an\nunrecognised value is rejected with `400 Bad Request`. In practice only `ebook`,\n`book`, `audiobook` and `nonbook` are meaningful here — the remaining accepted values\ndescribe order lines rather than publishable formats.\n",
            "example": "ebook",
            "x-enum-descriptions": {
                "ebook": "Digital edition in any e-book file format (EPUB, PDF, MOBI).",
                "book": "Printed edition, whether stocked or print-on-demand.",
                "audiobook": "Audio edition, downloadable or streamed.",
                "nonbook": "Non-book article sold alongside the title (merchandise, media, bundles).",
                "print_author": "Author copies of the printed edition.",
                "reviewers_copy": "Review copy of the digital edition.",
                "shipment": "Shipping charge line. Not a publishable format; no publishing dates apply.",
                "fee": "Fee line. Not a publishable format; no publishing dates apply.",
                "service": "Service line. Not a publishable format; no publishing dates apply."
            }
        },
        "publishing_date_role_code": {
            "type": "string",
            "description": "What the date *means*. A two-character code from ONIX\n[Codelist 163, Publishing date role](https://ns.editeur.org/onix/en/163). The full\ncodelist is accepted — 23 codes — and anything else is rejected with\n`400 Bad Request`. Note that these are the ONIX codes themselves, stored and returned\nverbatim including the leading zero: `\"01\"`, not `1` and not `\"publication\"`. Codes\n`32` and `33` postdate Codelist 163 Issue 67 and are accepted even though older\ncopies of the codelist do not list them.\n\nThe two codes that carry the day-to-day traffic:\n\n- `\"01\"` **Publication date** — the nominal publication date, used for planning and\n  promotion. In ONIX terms this is *not* by itself a permission to sell: absent an\n  embargo, retail sales may begin as soon as the retailer has stock. It is the code\n  most products carry.\n- `\"02\"` **Sales embargo date** — the date a retail sales embargo lifts, known in\n  some markets as the strict on-sale date. This is the code that tells a retailer\n  \"not before this day\". Where it appears it normally accompanies a role `\"01\"`\n  record, frequently carrying the same date.\n\nA role `\"02\"` record whose date has passed is a spent embargo rather than an active\nrestriction; nothing re-evaluates it, and such records are common.\n\nThis API maintains no relationship between roles: a record created, updated or\ndeleted here leaves every other record of the product untouched.\n\nThe remaining codes are accepted but exist only where they have been created\nexplicitly. The commercially significant ones:\n\n- `\"09\"` Public announcement date, `\"10\"` Trade announcement date — before these\n  dates the metadata is embargoed for internal or trade-only use respectively.\n- `\"11\"` Date of first publication (of the work, not this edition) and `\"20\"` the\n  same for the original language of a translation.\n- `\"13\"` Out-of-print / permanently withdrawn date, `\"22\"` Expected availability\n  date after a temporary withdrawal.\n- `\"27\"` Preorder embargo date — the earliest date a preorder may be accepted, which\n  is a different and usually earlier gate than `\"02\"`.\n- `\"23\"` Review embargo date, `\"25\"` Publisher's reservation order deadline.\n- `\"12\"` / `\"26\"` Latest and forthcoming reprint date, `\"16\"` / `\"21\"` latest and\n  forthcoming reissue date, `\"19\"` publication date of the print counterpart,\n  `\"28\"` transfer date, `\"29\"` date of production, `\"35\"` CIP date.\n- `\"30\"` / `\"31\"` / `\"32\"` / `\"33\"` Streaming, subscription, download and purchase\n  embargo dates — for digital products sold through more than one consumption model,\n  where one model becomes available later than another.\n\n**Uniqueness.** Within one product and `product_type` there may be at most one record\nper role with an empty `channels` list, and two channel-scoped records for the same\nrole must not share a channel. Either collision is rejected with `400 Bad Request`.\nNo role is required to be present, roles need not be in chronological order, and\nthere is no cross-role validation at all: an out-of-print date (`\"13\"`) earlier than\nthe publication date (`\"01\"`) is accepted.\n\n**These dates do not decide availability.** Whether a product is on sale is governed\nby the product's own expected publication date per format, which the v3 product\nresource exposes as `publication_date` and the v4 product resource does not expose at\nall. Creating a role `\"01\"` record here does not make a product available, and\ndeleting one does not withdraw it.\n",
            "example": "01"
        },
        "publishing_date": {
            "type": "string",
            "format": "date",
            "nullable": false,
            "description": "The date itself, as a plain calendar date in `YYYY-MM-DD` form. Always returned in\nexactly that form; there is no time component, no time zone offset, and no\nnormalisation across zones. A date is the whole day, inclusive — an embargo dated\n`2026-04-15` lifts *on* 15 April, and an out-of-print date of `2026-04-15` means the\nproduct is withdrawn on that day.\n\n**Partial dates are not supported.** ONIX allows a publishing date to carry a reduced\nprecision such as `2026` or `202604`, declared through the `dateformat` attribute\n([Codelist 55](https://ns.editeur.org/onix/en/55)); this field does not. Source data\nthat names only a month or a year has to be resolved to a single day before it can be\nsent.\n\nInput is more forgiving than the output format suggests: `2026-4-5`, `20260405` and\n`20260405T00:00:00` are all accepted and all come back as `2026-04-05`, with any time\ncomponent discarded. A value that cannot be parsed as a whole day — including `2026`\nand `2026-04` — is rejected with `400 Bad Request`. `YYYY-MM-DD` avoids all of this.\n",
            "example": "2021-07-30"
        },
        "channels": {
            "type": "array",
            "description": "Distribution channels this date is scoped to. An empty list — by far the normal case —\nmeans the date applies to every channel.\n\nA non-empty list narrows the record to named distribution partners, so that one format\ncan carry different dates for different partners: a title that becomes available on\none retailer a week before it reaches the library platforms, for example.\n\nValues are the platform's distribution-channel slugs. Those in common use are:\n\n- `amazon`\n- `itunes`\n- `kobo`\n- `spotify`\n- `skoobe`\n- `divibib`\n- `overdrive`\n- `bookbeat`\n- `bookwire`\n\nThe list is open-ended — a realm distributes through whichever partners it has\ncontracts with — and it is *not* validated against that vocabulary: a typo is accepted\nas given and will simply never match anything.\n\nValues are lower-cased, de-duplicated and sorted, so\n`[\"Spotify\", \"itunes\", \"itunes\"]` comes back as `[\"itunes\", \"spotify\"]`, and on update the\nlist is replaced wholesale rather than merged.\n\nUniqueness is enforced per channel, so `itunes` and `spotify` may each carry their own\nrole `\"02\"` alongside one unscoped role `\"02\"`.\n",
            "items": {
                "type": "string"
            },
            "example": []
        },
        "created": {
            "type": "integer",
            "description": "When this record was created, in seconds since the Unix epoch (UTC). This is the creation of the record, not the date it describes — a record created today can perfectly well carry a publication date from 2006.",
            "nullable": true,
            "example": 1779195413
        }
    },
    "required": []
}

{
    "errors": [
        {
            "_id": "string",
            "stack_trace": [
                "string"
            ],
            "message": "string",
            "vars": {}
        }
    ]
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "type": "object",
    "additionalProperties": false,
    "required": [
        "errors"
    ],
    "properties": {
        "errors": {
            "type": "array",
            "description": "List of errors occurred",
            "items": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                    "_id",
                    "message",
                    "stack_trace",
                    "vars"
                ],
                "properties": {
                    "_id": {
                        "type": "string",
                        "description": "The identifier of the error"
                    },
                    "stack_trace": {
                        "type": "array",
                        "description": "A stacktrace of the error occurred. Only for testing systems.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "message": {
                        "type": "string",
                        "description": "A translated message of the error"
                    },
                    "vars": {
                        "type": "object",
                        "description": "A dict containing additional values of the context of the error."
                    }
                }
            }
        }
    }
}

GET /resource/v4/products/{product_id}/publishing_dates/{id}

Retrieve a single publishing date

Description

Returns one record by UUID. A well-formed UUID that belongs to a different product returns 403 Permission denied, not 404 — the check that the record belongs to this product is a permission check. 404 Resource not found means the UUID matches no record at all.

The example is an e-book publication date, and has the shape most records have: role "01", no channel scope.

Input parameters

Path parameters

Parameter Type Default Nullable Description
id string No UUID of the publishing date record.
product_id string No UUID of the product.

Responses

{
    "_id": "888ffcf3-e685-4e4c-9999-b207a925d6e3",
    "_legacy_id": 133777,
    "_version": "4.0",
    "_links": {
        "self": "https://api.openpublishing.com/resource/v4/products/e8659334-e616-11ee-a221-00505699575c/publishing_dates/888ffcf3-e685-4e4c-9999-b207a925d6e3"
    },
    "product_type": "ebook",
    "publishing_date_role_code": "01",
    "publishing_date": "2021-07-30",
    "channels": [],
    "created": 1779195413
}
Schema of the response body
{
    "type": "object",
    "additionalProperties": false,
    "description": "One dated milestone of a product — one ONIX publishing-date role with one date, for one product format and optionally for named distribution channels.",
    "properties": {
        "_id": {
            "type": "string",
            "description": "UUID of this publishing date record. Stable for the life of the record.",
            "example": "888ffcf3-e685-4e4c-9999-b207a925d6e3"
        },
        "_version": {
            "type": "string",
            "description": "API version of the returned resource.",
            "example": "4.0"
        },
        "_links": {
            "type": "object",
            "description": "HAL-style links. Contains only `self`, the canonical URL of this record."
        },
        "_legacy_id": {
            "type": "integer",
            "description": "Legacy integer identifier of this resource, kept so existing integrations can correlate their own records. This is the value the v3 endpoint returns as `_id`; in v4 `_id` is the UUID and the integer moves here.",
            "example": 133777
        },
        "product_type": {
            "type": "string",
            "description": "The product format this date applies to. Dates are held per format because formats\nare published, embargoed and withdrawn independently, so the same role may appear\nseveral times for one product with different dates. A product with an e-book and a\nprint edition that share a publication date therefore carries *two* records, not one.\n\nValidated against the platform's product types and normalised to lower case; an\nunrecognised value is rejected with `400 Bad Request`. In practice only `ebook`,\n`book`, `audiobook` and `nonbook` are meaningful here — the remaining accepted values\ndescribe order lines rather than publishable formats.\n",
            "example": "ebook",
            "x-enum-descriptions": {
                "ebook": "Digital edition in any e-book file format (EPUB, PDF, MOBI).",
                "book": "Printed edition, whether stocked or print-on-demand.",
                "audiobook": "Audio edition, downloadable or streamed.",
                "nonbook": "Non-book article sold alongside the title (merchandise, media, bundles).",
                "print_author": "Author copies of the printed edition.",
                "reviewers_copy": "Review copy of the digital edition.",
                "shipment": "Shipping charge line. Not a publishable format; no publishing dates apply.",
                "fee": "Fee line. Not a publishable format; no publishing dates apply.",
                "service": "Service line. Not a publishable format; no publishing dates apply."
            }
        },
        "publishing_date_role_code": {
            "type": "string",
            "description": "What the date *means*. A two-character code from ONIX\n[Codelist 163, Publishing date role](https://ns.editeur.org/onix/en/163). The full\ncodelist is accepted — 23 codes — and anything else is rejected with\n`400 Bad Request`. Note that these are the ONIX codes themselves, stored and returned\nverbatim including the leading zero: `\"01\"`, not `1` and not `\"publication\"`. Codes\n`32` and `33` postdate Codelist 163 Issue 67 and are accepted even though older\ncopies of the codelist do not list them.\n\nThe two codes that carry the day-to-day traffic:\n\n- `\"01\"` **Publication date** — the nominal publication date, used for planning and\n  promotion. In ONIX terms this is *not* by itself a permission to sell: absent an\n  embargo, retail sales may begin as soon as the retailer has stock. It is the code\n  most products carry.\n- `\"02\"` **Sales embargo date** — the date a retail sales embargo lifts, known in\n  some markets as the strict on-sale date. This is the code that tells a retailer\n  \"not before this day\". Where it appears it normally accompanies a role `\"01\"`\n  record, frequently carrying the same date.\n\nA role `\"02\"` record whose date has passed is a spent embargo rather than an active\nrestriction; nothing re-evaluates it, and such records are common.\n\nThis API maintains no relationship between roles: a record created, updated or\ndeleted here leaves every other record of the product untouched.\n\nThe remaining codes are accepted but exist only where they have been created\nexplicitly. The commercially significant ones:\n\n- `\"09\"` Public announcement date, `\"10\"` Trade announcement date — before these\n  dates the metadata is embargoed for internal or trade-only use respectively.\n- `\"11\"` Date of first publication (of the work, not this edition) and `\"20\"` the\n  same for the original language of a translation.\n- `\"13\"` Out-of-print / permanently withdrawn date, `\"22\"` Expected availability\n  date after a temporary withdrawal.\n- `\"27\"` Preorder embargo date — the earliest date a preorder may be accepted, which\n  is a different and usually earlier gate than `\"02\"`.\n- `\"23\"` Review embargo date, `\"25\"` Publisher's reservation order deadline.\n- `\"12\"` / `\"26\"` Latest and forthcoming reprint date, `\"16\"` / `\"21\"` latest and\n  forthcoming reissue date, `\"19\"` publication date of the print counterpart,\n  `\"28\"` transfer date, `\"29\"` date of production, `\"35\"` CIP date.\n- `\"30\"` / `\"31\"` / `\"32\"` / `\"33\"` Streaming, subscription, download and purchase\n  embargo dates — for digital products sold through more than one consumption model,\n  where one model becomes available later than another.\n\n**Uniqueness.** Within one product and `product_type` there may be at most one record\nper role with an empty `channels` list, and two channel-scoped records for the same\nrole must not share a channel. Either collision is rejected with `400 Bad Request`.\nNo role is required to be present, roles need not be in chronological order, and\nthere is no cross-role validation at all: an out-of-print date (`\"13\"`) earlier than\nthe publication date (`\"01\"`) is accepted.\n\n**These dates do not decide availability.** Whether a product is on sale is governed\nby the product's own expected publication date per format, which the v3 product\nresource exposes as `publication_date` and the v4 product resource does not expose at\nall. Creating a role `\"01\"` record here does not make a product available, and\ndeleting one does not withdraw it.\n",
            "example": "01"
        },
        "publishing_date": {
            "type": "string",
            "format": "date",
            "nullable": false,
            "description": "The date itself, as a plain calendar date in `YYYY-MM-DD` form. Always returned in\nexactly that form; there is no time component, no time zone offset, and no\nnormalisation across zones. A date is the whole day, inclusive — an embargo dated\n`2026-04-15` lifts *on* 15 April, and an out-of-print date of `2026-04-15` means the\nproduct is withdrawn on that day.\n\n**Partial dates are not supported.** ONIX allows a publishing date to carry a reduced\nprecision such as `2026` or `202604`, declared through the `dateformat` attribute\n([Codelist 55](https://ns.editeur.org/onix/en/55)); this field does not. Source data\nthat names only a month or a year has to be resolved to a single day before it can be\nsent.\n\nInput is more forgiving than the output format suggests: `2026-4-5`, `20260405` and\n`20260405T00:00:00` are all accepted and all come back as `2026-04-05`, with any time\ncomponent discarded. A value that cannot be parsed as a whole day — including `2026`\nand `2026-04` — is rejected with `400 Bad Request`. `YYYY-MM-DD` avoids all of this.\n",
            "example": "2021-07-30"
        },
        "channels": {
            "type": "array",
            "description": "Distribution channels this date is scoped to. An empty list — by far the normal case —\nmeans the date applies to every channel.\n\nA non-empty list narrows the record to named distribution partners, so that one format\ncan carry different dates for different partners: a title that becomes available on\none retailer a week before it reaches the library platforms, for example.\n\nValues are the platform's distribution-channel slugs. Those in common use are:\n\n- `amazon`\n- `itunes`\n- `kobo`\n- `spotify`\n- `skoobe`\n- `divibib`\n- `overdrive`\n- `bookbeat`\n- `bookwire`\n\nThe list is open-ended — a realm distributes through whichever partners it has\ncontracts with — and it is *not* validated against that vocabulary: a typo is accepted\nas given and will simply never match anything.\n\nValues are lower-cased, de-duplicated and sorted, so\n`[\"Spotify\", \"itunes\", \"itunes\"]` comes back as `[\"itunes\", \"spotify\"]`, and on update the\nlist is replaced wholesale rather than merged.\n\nUniqueness is enforced per channel, so `itunes` and `spotify` may each carry their own\nrole `\"02\"` alongside one unscoped role `\"02\"`.\n",
            "items": {
                "type": "string"
            },
            "example": []
        },
        "created": {
            "type": "integer",
            "description": "When this record was created, in seconds since the Unix epoch (UTC). This is the creation of the record, not the date it describes — a record created today can perfectly well carry a publication date from 2006.",
            "nullable": true,
            "example": 1779195413
        }
    },
    "required": []
}

PUT /resource/v4/products/{product_id}/publishing_dates/{id}

Update a publishing date

Description

Updates one record. Despite being a PUT this is a partial update: only the fields present in the body are applied and every omitted field keeps its current value. Sending {} changes nothing, and there is no way to clear a field by leaving it out.

channels is the one field where that matters in practice. Un-scoping a record so that the date applies to all channels requires an explicit "channels": []; omitting the key leaves the existing scope in place. null clears nothing here — a null in place of publishing_date, product_type, publishing_date_role_code or channels is rejected with 400 Bad Request.

Moving a record to a role or channel scope already occupied by another record of the same product and format fails with 400 Bad Request; the uniqueness check ignores the record being updated, so re-saving a record unchanged is always safe.

The example postpones a publication date by a fortnight, sending only the field that changed.

Input parameters

Path parameters

Parameter Type Default Nullable Description
id string No UUID of the publishing date record.
product_id string No UUID of the product.

Request body

{
    "publishing_date": "2025-12-14"
}
Schema of the request body
{
    "type": "object",
    "additionalProperties": false,
    "description": "One dated milestone of a product — one ONIX publishing-date role with one date, for one product format and optionally for named distribution channels.",
    "properties": {
        "_id": {
            "type": "string",
            "description": "UUID of this publishing date record. Stable for the life of the record.",
            "example": "888ffcf3-e685-4e4c-9999-b207a925d6e3"
        },
        "_version": {
            "type": "string",
            "description": "API version of the returned resource.",
            "example": "4.0"
        },
        "_links": {
            "type": "object",
            "description": "HAL-style links. Contains only `self`, the canonical URL of this record."
        },
        "_legacy_id": {
            "type": "integer",
            "description": "Legacy integer identifier of this resource, kept so existing integrations can correlate their own records. This is the value the v3 endpoint returns as `_id`; in v4 `_id` is the UUID and the integer moves here.",
            "example": 133777
        },
        "product_type": {
            "type": "string",
            "description": "The product format this date applies to. Dates are held per format because formats\nare published, embargoed and withdrawn independently, so the same role may appear\nseveral times for one product with different dates. A product with an e-book and a\nprint edition that share a publication date therefore carries *two* records, not one.\n\nValidated against the platform's product types and normalised to lower case; an\nunrecognised value is rejected with `400 Bad Request`. In practice only `ebook`,\n`book`, `audiobook` and `nonbook` are meaningful here — the remaining accepted values\ndescribe order lines rather than publishable formats.\n",
            "example": "ebook",
            "x-enum-descriptions": {
                "ebook": "Digital edition in any e-book file format (EPUB, PDF, MOBI).",
                "book": "Printed edition, whether stocked or print-on-demand.",
                "audiobook": "Audio edition, downloadable or streamed.",
                "nonbook": "Non-book article sold alongside the title (merchandise, media, bundles).",
                "print_author": "Author copies of the printed edition.",
                "reviewers_copy": "Review copy of the digital edition.",
                "shipment": "Shipping charge line. Not a publishable format; no publishing dates apply.",
                "fee": "Fee line. Not a publishable format; no publishing dates apply.",
                "service": "Service line. Not a publishable format; no publishing dates apply."
            }
        },
        "publishing_date_role_code": {
            "type": "string",
            "description": "What the date *means*. A two-character code from ONIX\n[Codelist 163, Publishing date role](https://ns.editeur.org/onix/en/163). The full\ncodelist is accepted — 23 codes — and anything else is rejected with\n`400 Bad Request`. Note that these are the ONIX codes themselves, stored and returned\nverbatim including the leading zero: `\"01\"`, not `1` and not `\"publication\"`. Codes\n`32` and `33` postdate Codelist 163 Issue 67 and are accepted even though older\ncopies of the codelist do not list them.\n\nThe two codes that carry the day-to-day traffic:\n\n- `\"01\"` **Publication date** — the nominal publication date, used for planning and\n  promotion. In ONIX terms this is *not* by itself a permission to sell: absent an\n  embargo, retail sales may begin as soon as the retailer has stock. It is the code\n  most products carry.\n- `\"02\"` **Sales embargo date** — the date a retail sales embargo lifts, known in\n  some markets as the strict on-sale date. This is the code that tells a retailer\n  \"not before this day\". Where it appears it normally accompanies a role `\"01\"`\n  record, frequently carrying the same date.\n\nA role `\"02\"` record whose date has passed is a spent embargo rather than an active\nrestriction; nothing re-evaluates it, and such records are common.\n\nThis API maintains no relationship between roles: a record created, updated or\ndeleted here leaves every other record of the product untouched.\n\nThe remaining codes are accepted but exist only where they have been created\nexplicitly. The commercially significant ones:\n\n- `\"09\"` Public announcement date, `\"10\"` Trade announcement date — before these\n  dates the metadata is embargoed for internal or trade-only use respectively.\n- `\"11\"` Date of first publication (of the work, not this edition) and `\"20\"` the\n  same for the original language of a translation.\n- `\"13\"` Out-of-print / permanently withdrawn date, `\"22\"` Expected availability\n  date after a temporary withdrawal.\n- `\"27\"` Preorder embargo date — the earliest date a preorder may be accepted, which\n  is a different and usually earlier gate than `\"02\"`.\n- `\"23\"` Review embargo date, `\"25\"` Publisher's reservation order deadline.\n- `\"12\"` / `\"26\"` Latest and forthcoming reprint date, `\"16\"` / `\"21\"` latest and\n  forthcoming reissue date, `\"19\"` publication date of the print counterpart,\n  `\"28\"` transfer date, `\"29\"` date of production, `\"35\"` CIP date.\n- `\"30\"` / `\"31\"` / `\"32\"` / `\"33\"` Streaming, subscription, download and purchase\n  embargo dates — for digital products sold through more than one consumption model,\n  where one model becomes available later than another.\n\n**Uniqueness.** Within one product and `product_type` there may be at most one record\nper role with an empty `channels` list, and two channel-scoped records for the same\nrole must not share a channel. Either collision is rejected with `400 Bad Request`.\nNo role is required to be present, roles need not be in chronological order, and\nthere is no cross-role validation at all: an out-of-print date (`\"13\"`) earlier than\nthe publication date (`\"01\"`) is accepted.\n\n**These dates do not decide availability.** Whether a product is on sale is governed\nby the product's own expected publication date per format, which the v3 product\nresource exposes as `publication_date` and the v4 product resource does not expose at\nall. Creating a role `\"01\"` record here does not make a product available, and\ndeleting one does not withdraw it.\n",
            "example": "01"
        },
        "publishing_date": {
            "type": "string",
            "format": "date",
            "nullable": false,
            "description": "The date itself, as a plain calendar date in `YYYY-MM-DD` form. Always returned in\nexactly that form; there is no time component, no time zone offset, and no\nnormalisation across zones. A date is the whole day, inclusive — an embargo dated\n`2026-04-15` lifts *on* 15 April, and an out-of-print date of `2026-04-15` means the\nproduct is withdrawn on that day.\n\n**Partial dates are not supported.** ONIX allows a publishing date to carry a reduced\nprecision such as `2026` or `202604`, declared through the `dateformat` attribute\n([Codelist 55](https://ns.editeur.org/onix/en/55)); this field does not. Source data\nthat names only a month or a year has to be resolved to a single day before it can be\nsent.\n\nInput is more forgiving than the output format suggests: `2026-4-5`, `20260405` and\n`20260405T00:00:00` are all accepted and all come back as `2026-04-05`, with any time\ncomponent discarded. A value that cannot be parsed as a whole day — including `2026`\nand `2026-04` — is rejected with `400 Bad Request`. `YYYY-MM-DD` avoids all of this.\n",
            "example": "2021-07-30"
        },
        "channels": {
            "type": "array",
            "description": "Distribution channels this date is scoped to. An empty list — by far the normal case —\nmeans the date applies to every channel.\n\nA non-empty list narrows the record to named distribution partners, so that one format\ncan carry different dates for different partners: a title that becomes available on\none retailer a week before it reaches the library platforms, for example.\n\nValues are the platform's distribution-channel slugs. Those in common use are:\n\n- `amazon`\n- `itunes`\n- `kobo`\n- `spotify`\n- `skoobe`\n- `divibib`\n- `overdrive`\n- `bookbeat`\n- `bookwire`\n\nThe list is open-ended — a realm distributes through whichever partners it has\ncontracts with — and it is *not* validated against that vocabulary: a typo is accepted\nas given and will simply never match anything.\n\nValues are lower-cased, de-duplicated and sorted, so\n`[\"Spotify\", \"itunes\", \"itunes\"]` comes back as `[\"itunes\", \"spotify\"]`, and on update the\nlist is replaced wholesale rather than merged.\n\nUniqueness is enforced per channel, so `itunes` and `spotify` may each carry their own\nrole `\"02\"` alongside one unscoped role `\"02\"`.\n",
            "items": {
                "type": "string"
            },
            "example": []
        },
        "created": {
            "type": "integer",
            "description": "When this record was created, in seconds since the Unix epoch (UTC). This is the creation of the record, not the date it describes — a record created today can perfectly well carry a publication date from 2006.",
            "nullable": true,
            "example": 1779195413
        }
    },
    "required": []
}

Responses

{
    "_id": "f2fb25d8-9160-4f35-b569-1b6ac44ad351",
    "_legacy_id": 719697,
    "_version": "4.0",
    "_links": {
        "self": "https://api.openpublishing.com/resource/v4/products/e58dacc3-e616-11ee-a221-00505699575c/publishing_dates/f2fb25d8-9160-4f35-b569-1b6ac44ad351"
    },
    "product_type": "ebook",
    "publishing_date_role_code": "01",
    "publishing_date": "2025-12-14",
    "channels": [],
    "created": 1779378856
}
Schema of the response body
{
    "type": "object",
    "additionalProperties": false,
    "description": "One dated milestone of a product — one ONIX publishing-date role with one date, for one product format and optionally for named distribution channels.",
    "properties": {
        "_id": {
            "type": "string",
            "description": "UUID of this publishing date record. Stable for the life of the record.",
            "example": "888ffcf3-e685-4e4c-9999-b207a925d6e3"
        },
        "_version": {
            "type": "string",
            "description": "API version of the returned resource.",
            "example": "4.0"
        },
        "_links": {
            "type": "object",
            "description": "HAL-style links. Contains only `self`, the canonical URL of this record."
        },
        "_legacy_id": {
            "type": "integer",
            "description": "Legacy integer identifier of this resource, kept so existing integrations can correlate their own records. This is the value the v3 endpoint returns as `_id`; in v4 `_id` is the UUID and the integer moves here.",
            "example": 133777
        },
        "product_type": {
            "type": "string",
            "description": "The product format this date applies to. Dates are held per format because formats\nare published, embargoed and withdrawn independently, so the same role may appear\nseveral times for one product with different dates. A product with an e-book and a\nprint edition that share a publication date therefore carries *two* records, not one.\n\nValidated against the platform's product types and normalised to lower case; an\nunrecognised value is rejected with `400 Bad Request`. In practice only `ebook`,\n`book`, `audiobook` and `nonbook` are meaningful here — the remaining accepted values\ndescribe order lines rather than publishable formats.\n",
            "example": "ebook",
            "x-enum-descriptions": {
                "ebook": "Digital edition in any e-book file format (EPUB, PDF, MOBI).",
                "book": "Printed edition, whether stocked or print-on-demand.",
                "audiobook": "Audio edition, downloadable or streamed.",
                "nonbook": "Non-book article sold alongside the title (merchandise, media, bundles).",
                "print_author": "Author copies of the printed edition.",
                "reviewers_copy": "Review copy of the digital edition.",
                "shipment": "Shipping charge line. Not a publishable format; no publishing dates apply.",
                "fee": "Fee line. Not a publishable format; no publishing dates apply.",
                "service": "Service line. Not a publishable format; no publishing dates apply."
            }
        },
        "publishing_date_role_code": {
            "type": "string",
            "description": "What the date *means*. A two-character code from ONIX\n[Codelist 163, Publishing date role](https://ns.editeur.org/onix/en/163). The full\ncodelist is accepted — 23 codes — and anything else is rejected with\n`400 Bad Request`. Note that these are the ONIX codes themselves, stored and returned\nverbatim including the leading zero: `\"01\"`, not `1` and not `\"publication\"`. Codes\n`32` and `33` postdate Codelist 163 Issue 67 and are accepted even though older\ncopies of the codelist do not list them.\n\nThe two codes that carry the day-to-day traffic:\n\n- `\"01\"` **Publication date** — the nominal publication date, used for planning and\n  promotion. In ONIX terms this is *not* by itself a permission to sell: absent an\n  embargo, retail sales may begin as soon as the retailer has stock. It is the code\n  most products carry.\n- `\"02\"` **Sales embargo date** — the date a retail sales embargo lifts, known in\n  some markets as the strict on-sale date. This is the code that tells a retailer\n  \"not before this day\". Where it appears it normally accompanies a role `\"01\"`\n  record, frequently carrying the same date.\n\nA role `\"02\"` record whose date has passed is a spent embargo rather than an active\nrestriction; nothing re-evaluates it, and such records are common.\n\nThis API maintains no relationship between roles: a record created, updated or\ndeleted here leaves every other record of the product untouched.\n\nThe remaining codes are accepted but exist only where they have been created\nexplicitly. The commercially significant ones:\n\n- `\"09\"` Public announcement date, `\"10\"` Trade announcement date — before these\n  dates the metadata is embargoed for internal or trade-only use respectively.\n- `\"11\"` Date of first publication (of the work, not this edition) and `\"20\"` the\n  same for the original language of a translation.\n- `\"13\"` Out-of-print / permanently withdrawn date, `\"22\"` Expected availability\n  date after a temporary withdrawal.\n- `\"27\"` Preorder embargo date — the earliest date a preorder may be accepted, which\n  is a different and usually earlier gate than `\"02\"`.\n- `\"23\"` Review embargo date, `\"25\"` Publisher's reservation order deadline.\n- `\"12\"` / `\"26\"` Latest and forthcoming reprint date, `\"16\"` / `\"21\"` latest and\n  forthcoming reissue date, `\"19\"` publication date of the print counterpart,\n  `\"28\"` transfer date, `\"29\"` date of production, `\"35\"` CIP date.\n- `\"30\"` / `\"31\"` / `\"32\"` / `\"33\"` Streaming, subscription, download and purchase\n  embargo dates — for digital products sold through more than one consumption model,\n  where one model becomes available later than another.\n\n**Uniqueness.** Within one product and `product_type` there may be at most one record\nper role with an empty `channels` list, and two channel-scoped records for the same\nrole must not share a channel. Either collision is rejected with `400 Bad Request`.\nNo role is required to be present, roles need not be in chronological order, and\nthere is no cross-role validation at all: an out-of-print date (`\"13\"`) earlier than\nthe publication date (`\"01\"`) is accepted.\n\n**These dates do not decide availability.** Whether a product is on sale is governed\nby the product's own expected publication date per format, which the v3 product\nresource exposes as `publication_date` and the v4 product resource does not expose at\nall. Creating a role `\"01\"` record here does not make a product available, and\ndeleting one does not withdraw it.\n",
            "example": "01"
        },
        "publishing_date": {
            "type": "string",
            "format": "date",
            "nullable": false,
            "description": "The date itself, as a plain calendar date in `YYYY-MM-DD` form. Always returned in\nexactly that form; there is no time component, no time zone offset, and no\nnormalisation across zones. A date is the whole day, inclusive — an embargo dated\n`2026-04-15` lifts *on* 15 April, and an out-of-print date of `2026-04-15` means the\nproduct is withdrawn on that day.\n\n**Partial dates are not supported.** ONIX allows a publishing date to carry a reduced\nprecision such as `2026` or `202604`, declared through the `dateformat` attribute\n([Codelist 55](https://ns.editeur.org/onix/en/55)); this field does not. Source data\nthat names only a month or a year has to be resolved to a single day before it can be\nsent.\n\nInput is more forgiving than the output format suggests: `2026-4-5`, `20260405` and\n`20260405T00:00:00` are all accepted and all come back as `2026-04-05`, with any time\ncomponent discarded. A value that cannot be parsed as a whole day — including `2026`\nand `2026-04` — is rejected with `400 Bad Request`. `YYYY-MM-DD` avoids all of this.\n",
            "example": "2021-07-30"
        },
        "channels": {
            "type": "array",
            "description": "Distribution channels this date is scoped to. An empty list — by far the normal case —\nmeans the date applies to every channel.\n\nA non-empty list narrows the record to named distribution partners, so that one format\ncan carry different dates for different partners: a title that becomes available on\none retailer a week before it reaches the library platforms, for example.\n\nValues are the platform's distribution-channel slugs. Those in common use are:\n\n- `amazon`\n- `itunes`\n- `kobo`\n- `spotify`\n- `skoobe`\n- `divibib`\n- `overdrive`\n- `bookbeat`\n- `bookwire`\n\nThe list is open-ended — a realm distributes through whichever partners it has\ncontracts with — and it is *not* validated against that vocabulary: a typo is accepted\nas given and will simply never match anything.\n\nValues are lower-cased, de-duplicated and sorted, so\n`[\"Spotify\", \"itunes\", \"itunes\"]` comes back as `[\"itunes\", \"spotify\"]`, and on update the\nlist is replaced wholesale rather than merged.\n\nUniqueness is enforced per channel, so `itunes` and `spotify` may each carry their own\nrole `\"02\"` alongside one unscoped role `\"02\"`.\n",
            "items": {
                "type": "string"
            },
            "example": []
        },
        "created": {
            "type": "integer",
            "description": "When this record was created, in seconds since the Unix epoch (UTC). This is the creation of the record, not the date it describes — a record created today can perfectly well carry a publication date from 2006.",
            "nullable": true,
            "example": 1779195413
        }
    },
    "required": []
}

{
    "errors": [
        {
            "_id": "string",
            "stack_trace": [
                "string"
            ],
            "message": "string",
            "vars": {}
        }
    ]
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "type": "object",
    "additionalProperties": false,
    "required": [
        "errors"
    ],
    "properties": {
        "errors": {
            "type": "array",
            "description": "List of errors occurred",
            "items": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                    "_id",
                    "message",
                    "stack_trace",
                    "vars"
                ],
                "properties": {
                    "_id": {
                        "type": "string",
                        "description": "The identifier of the error"
                    },
                    "stack_trace": {
                        "type": "array",
                        "description": "A stacktrace of the error occurred. Only for testing systems.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "message": {
                        "type": "string",
                        "description": "A translated message of the error"
                    },
                    "vars": {
                        "type": "object",
                        "description": "A dict containing additional values of the context of the error."
                    }
                }
            }
        }
    }
}

DELETE /resource/v4/products/{product_id}/publishing_dates/{id}

Delete a publishing date

Description

Removes one record. Nothing else changes: the product's availability is not affected, and no companion record is removed — deleting a role "01" entry leaves any role "02" entry in place.

Input parameters

Path parameters

Parameter Type Default Nullable Description
id string No UUID of the publishing date record.
product_id string No UUID of the product.

Responses

{
    "errors": [
        {
            "_id": "string",
            "stack_trace": [
                "string"
            ],
            "message": "string",
            "vars": {}
        }
    ]
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "type": "object",
    "additionalProperties": false,
    "required": [
        "errors"
    ],
    "properties": {
        "errors": {
            "type": "array",
            "description": "List of errors occurred",
            "items": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                    "_id",
                    "message",
                    "stack_trace",
                    "vars"
                ],
                "properties": {
                    "_id": {
                        "type": "string",
                        "description": "The identifier of the error"
                    },
                    "stack_trace": {
                        "type": "array",
                        "description": "A stacktrace of the error occurred. Only for testing systems.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "message": {
                        "type": "string",
                        "description": "A translated message of the error"
                    },
                    "vars": {
                        "type": "object",
                        "description": "A dict containing additional values of the context of the error."
                    }
                }
            }
        }
    }
}

Schemas

Product Publishing Date

Name Type Description Example
_id string

UUID of this publishing date record. Stable for the life of the record.

888ffcf3-e685-4e4c-9999-b207a925d6e3
_legacy_id integer

Legacy integer identifier of this resource, kept so existing integrations can correlate their own records. This is the value the v3 endpoint returns as _id; in v4 _id is the UUID and the integer moves here.

133777
_links object

HAL-style links. Contains only self, the canonical URL of this record.

_version string

API version of the returned resource.

4.0
channels Array<string>

Distribution channels this date is scoped to. An empty list — by far the normal case — means the date applies to every channel.

A non-empty list narrows the record to named distribution partners, so that one format can carry different dates for different partners: a title that becomes available on one retailer a week before it reaches the library platforms, for example.

Values are the platform's distribution-channel slugs. Those in common use are:

  • amazon
  • itunes
  • kobo
  • spotify
  • skoobe
  • divibib
  • overdrive
  • bookbeat
  • bookwire

The list is open-ended — a realm distributes through whichever partners it has contracts with — and it is not validated against that vocabulary: a typo is accepted as given and will simply never match anything.

Values are lower-cased, de-duplicated and sorted, so ["Spotify", "itunes", "itunes"] comes back as ["itunes", "spotify"], and on update the list is replaced wholesale rather than merged.

Uniqueness is enforced per channel, so itunes and spotify may each carry their own role "02" alongside one unscoped role "02".

[]
created integer| null

When this record was created, in seconds since the Unix epoch (UTC). This is the creation of the record, not the date it describes — a record created today can perfectly well carry a publication date from 2006.

1779195413
product_type string

The product format this date applies to. Dates are held per format because formats are published, embargoed and withdrawn independently, so the same role may appear several times for one product with different dates. A product with an e-book and a print edition that share a publication date therefore carries two records, not one.

Validated against the platform's product types and normalised to lower case; an unrecognised value is rejected with 400 Bad Request. In practice only ebook, book, audiobook and nonbook are meaningful here — the remaining accepted values describe order lines rather than publishable formats.

ebook
publishing_date string(date)

The date itself, as a plain calendar date in YYYY-MM-DD form. Always returned in exactly that form; there is no time component, no time zone offset, and no normalisation across zones. A date is the whole day, inclusive — an embargo dated 2026-04-15 lifts on 15 April, and an out-of-print date of 2026-04-15 means the product is withdrawn on that day.

Partial dates are not supported. ONIX allows a publishing date to carry a reduced precision such as 2026 or 202604, declared through the dateformat attribute (Codelist 55); this field does not. Source data that names only a month or a year has to be resolved to a single day before it can be sent.

Input is more forgiving than the output format suggests: 2026-4-5, 20260405 and 20260405T00:00:00 are all accepted and all come back as 2026-04-05, with any time component discarded. A value that cannot be parsed as a whole day — including 2026 and 2026-04 — is rejected with 400 Bad Request. YYYY-MM-DD avoids all of this.

2021-07-30
publishing_date_role_code string

What the date means. A two-character code from ONIX Codelist 163, Publishing date role. The full codelist is accepted — 23 codes — and anything else is rejected with 400 Bad Request. Note that these are the ONIX codes themselves, stored and returned verbatim including the leading zero: "01", not 1 and not "publication". Codes 32 and 33 postdate Codelist 163 Issue 67 and are accepted even though older copies of the codelist do not list them.

The two codes that carry the day-to-day traffic:

  • "01" Publication date — the nominal publication date, used for planning and promotion. In ONIX terms this is not by itself a permission to sell: absent an embargo, retail sales may begin as soon as the retailer has stock. It is the code most products carry.
  • "02" Sales embargo date — the date a retail sales embargo lifts, known in some markets as the strict on-sale date. This is the code that tells a retailer "not before this day". Where it appears it normally accompanies a role "01" record, frequently carrying the same date.

A role "02" record whose date has passed is a spent embargo rather than an active restriction; nothing re-evaluates it, and such records are common.

This API maintains no relationship between roles: a record created, updated or deleted here leaves every other record of the product untouched.

The remaining codes are accepted but exist only where they have been created explicitly. The commercially significant ones:

  • "09" Public announcement date, "10" Trade announcement date — before these dates the metadata is embargoed for internal or trade-only use respectively.
  • "11" Date of first publication (of the work, not this edition) and "20" the same for the original language of a translation.
  • "13" Out-of-print / permanently withdrawn date, "22" Expected availability date after a temporary withdrawal.
  • "27" Preorder embargo date — the earliest date a preorder may be accepted, which is a different and usually earlier gate than "02".
  • "23" Review embargo date, "25" Publisher's reservation order deadline.
  • "12" / "26" Latest and forthcoming reprint date, "16" / "21" latest and forthcoming reissue date, "19" publication date of the print counterpart, "28" transfer date, "29" date of production, "35" CIP date.
  • "30" / "31" / "32" / "33" Streaming, subscription, download and purchase embargo dates — for digital products sold through more than one consumption model, where one model becomes available later than another.

Uniqueness. Within one product and product_type there may be at most one record per role with an empty channels list, and two channel-scoped records for the same role must not share a channel. Either collision is rejected with 400 Bad Request. No role is required to be present, roles need not be in chronological order, and there is no cross-role validation at all: an out-of-print date ("13") earlier than the publication date ("01") is accepted.

These dates do not decide availability. Whether a product is on sale is governed by the product's own expected publication date per format, which the v3 product resource exposes as publication_date and the v4 product resource does not expose at all. Creating a role "01" record here does not make a product available, and deleting one does not withdraw it.

01