Skip to content

Product Texts v4

Sub-resource of products holding the descriptive copy that goes with a title: the main blurb, the short annotation used in feeds, the table of contents, the author biography, review quotes and endorsements, cover copy, excerpts. Each entry is one text, in one language, with a type tag and an optional distribution-channel scope. A product carries as many entries as it needs — one blurb per language, one biography per contributor, one entry per review quote.

The model follows the ONIX 3 <TextContent> composite, with this API's own lowercase-slug vocabulary in type rather than raw ONIX codes; the matching ONIX Codelist 153 code is derived by the server into type_onix.


Endpoints


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

Retrieve texts for a product

Description

Returns every text entry for the product, paginated. type is the only field that can be filtered on — ?type=description for the blurbs, for example; language and channel have to be filtered client-side. Results cannot be sorted. See Resource Queries for the filter, sort and pagination syntax.

An unknown product_id returns 404. A product belonging to another realm returns 403.

Input parameters

Path parameters

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

Query parameters

Parameter Type Default Nullable Description
page integer No Page number, starting at 1.
page_size integer No Entries per page; defaults to 100. `display` is accepted as a legacy alias.
type string No Filter by text type slug, e.g. `description`, `biographical-note`, `table-of-contents`. The only filterable field; any other name returns 400. Operator suffixes are supported — see [Resource Queries](/resource_queries/).

Responses

{
    "_links": {},
    "_pagination": {},
    "items": [
        {
            "_id": "3d5a9c14-7b02-4e88-9a61-0c7f2e4d8b35",
            "_version": "4.0",
            "_legacy_id": 4180231,
            "_links": {},
            "text": "Marit Sallenberg arbeitete als Lektorin und Kulturjournalistin, bevor sie ihren ersten Roman veroeffentlichte. Sie schreibt Gesellschaftsromane und lebt als freie Autorin in Rheinbergen.",
            "channels": [],
            "language": "ger",
            "type": "biographical-note",
            "type_onix": "12",
            "mime_type": "text/plain"
        }
    ]
}
⚠️ 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 piece of descriptive copy attached to a product, in a single language, tagged by text type.",
                "properties": {
                    "_id": {
                        "type": "string",
                        "description": "Unique identifier (UUID) for the product text.",
                        "example": "3d5a9c14-7b02-4e88-9a61-0c7f2e4d8b35"
                    },
                    "_version": {
                        "type": "string",
                        "description": "API Version.",
                        "example": "4.0"
                    },
                    "_legacy_id": {
                        "type": "integer",
                        "description": "Legacy integer identifier of this resource, kept so existing integrations can correlate their own records. This is the `_id` the same record has on the v3 endpoint.",
                        "example": 4180231
                    },
                    "_links": {
                        "type": "object"
                    },
                    "text": {
                        "type": "string",
                        "description": "The text itself. Its interpretation follows `mime_type`: with `text/plain` it is\nliteral characters and line breaks; with `text/html` it is a fragment of markup\n(typically `<p>` paragraphs) that a storefront can drop into a page.\n\nMust not be empty — a create or update that would leave `text` empty is rejected\nwith `400 Bad Request`.\n\nThere is no business length limit: an entry comfortably holds a full table of contents\nor a sample chapter, and the practical ceiling comes from the receiving channel rather\nthan from this API. Characters outside the Basic Multilingual Plane — emoji, and some\nrarely used CJK and historic scripts — are not supported.\n\n**This sub-resource is a standalone store.** It is independent of the legacy\ndescriptive fields carried directly on the v3 product record (`abstract`,\n`abstract_prefix`, `biographical_note`, `table_of_content`): a text written here does\nnot update those, and reading them does not surface entries created here. An entry is\nreachable through this sub-resource and its v3 equivalent, and nowhere else in the\nAPI.\n",
                        "example": "Marit Sallenberg arbeitete als Lektorin und Kulturjournalistin, bevor sie ihren ersten Roman veroeffentlichte. Sie schreibt Gesellschaftsromane und lebt als freie Autorin in Rheinbergen."
                    },
                    "channels": {
                        "type": "array",
                        "description": "Distribution channels this text is intended for. An **empty list means the text\napplies to every channel** and is the normal case; it is populated only when a partner\nneeds different copy from everyone else — for example a shortened blurb for a\nretailer with a character limit, or a description that omits a competitor's name.\n\nValues are the platform's distribution-channel slugs. Those in common use are:\n\n- `google`\n- `amazon`\n- `kobo`\n- `spotify`\n- `libri`\n- `ciando`\n- `divibib`\n- `overdrive`\n- `scribd`\n- `bookwire`\n\nThe list is open-ended — a realm distributes through whichever partners it has\ncontracts with. **They are not validated against the channel list** — any string of lowercase letters and\nhyphens is accepted, so a typo silently produces a text that no channel will ever\nmatch. Note that channel slugs containing digits or underscores (`24symbols`,\n`manual_sale`, `zeitfracht_sa02e`) are valid channels elsewhere in the API but are\n**rejected** here, because this field allows only `[a-z-]`.\n\nThe list is normalised on write: values are lower-cased, de-duplicated and sorted\nalphabetically. Sending `[\"Google\", \"amazon\", \"google\"]` stores and returns\n`[\"amazon\", \"google\"]`. On update the list is replaced wholesale, never merged.\n\nThis endpoint applies no fallback logic of its own: it returns the entries exactly as\nstored, so selecting copy for one channel means preferring an entry that names that\nchannel and otherwise taking the unscoped one.\n\n**`channels` is the only scoping axis this resource has, and it is narrower than\nONIX.** An ONIX 3 `<TextContent>` is also scoped by content audience\n([Codelist 154](https://ns.editeur.org/onix/en/154) — booktrade, end-customers,\nlibrarians, press, …) and by text source and validity dates; none of those fields\nexist here. `channels` names distribution partners, not classes of reader.\n\n**Storefronts are a separate axis and are not handled here.** Per-shop copy — HTML\ntitle, meta description, meta keywords — belongs to the\n`/resource/v4/products/{product_id}/storefronts` sub-resource.\n",
                        "items": {
                            "type": "string"
                        },
                        "example": []
                    },
                    "language": {
                        "type": "string",
                        "description": "Language of `text`, as a three-letter ISO 639-2/B (bibliographic) code — `ger` for\nGerman, `eng` for English, `fre` for French. Note the B-codes: German is `ger`, not\n`deu`. Case is normalised to lower case on write; an unknown code is rejected with\n`400 Bad Request`.\n\n`null` when the language is unknown or not meaningful. A product carrying the same\n`type` in several languages holds one entry per language — nothing prevents\nduplicates, so a consumer picking \"the description\" should filter by the language it\nwants and fall back to the product's own `language`.\n\nNote that a language once set cannot be cleared: sending `\"language\": null` is\nrejected with `400 Bad Request`.\n",
                        "nullable": true,
                        "example": "ger"
                    },
                    "type": {
                        "type": "string",
                        "description": "What kind of text this is. **Not a closed enumeration** — any non-empty string of\nlowercase letters and hyphens (`[a-z-]`, up to 255 characters) is accepted. Digits,\nunderscores, spaces and upper case are rejected with `400 Bad Request`, as is an\nempty value.\n\n37 slugs are recognised as equivalents of [ONIX Codelist\n153](https://ns.editeur.org/onix/en/153) values; for those the server derives\n`type_onix`. Anything else is stored as given with `type_onix: null`, which is the\nsupported way to carry copy that ONIX has no code for.\n\nA few of the distinctions in the list are easy to get wrong:\n\n- `description` (03) is the main long-form selling copy;\n  `short-description-annotation` (02) is the abridged version for listings and feeds\n  with a length budget. They are separate entries, not two renderings of one.\n- `biographical-note` (12) is about the author, not about the book, and takes one entry\n  per contributor where there are several.\n- `review-quote` (06) is a quotation from a published review of *this* edition;\n  `review-quote-previous-edition` (07) and `review-quote-previous-work` (08) exist for\n  quotes that refer to something else.\n- `endorsement` (09) is a commendation solicited by the publisher, as distinct from a\n  review published independently.\n- `abstract` (30) is the scholarly abstract, not a marketing blurb.\n- `table-of-contents` (04) is conventionally `text/plain` with one heading per line.\n\nThe complete set of recognised slugs, with the [Codelist\n153](https://ns.editeur.org/onix/en/153) code each one derives:\n\n| `type` | `type_onix` | Meaning |\n|---|---|---|\n| `sender-defined-text` | `01` | Sender-defined text |\n| `short-description-annotation` | `02` | Short description / annotation — the abridged blurb for listings and feeds |\n| `description` | `03` | Description — the main long-form selling copy |\n| `table-of-contents` | `04` | Table of contents |\n| `primary-cover-copy` | `05` | Primary cover copy — text printed on the cover or jacket |\n| `review-quote` | `06` | Review quote |\n| `review-quote-previous-edition` | `07` | Review quote, previous edition |\n| `review-quote-previous-work` | `08` | Review quote, previous work |\n| `endorsement` | `09` | Endorsement — solicited by the publisher, unlike a review |\n| `promotional-headline` | `10` | Promotional headline |\n| `feature` | `11` | Feature — a single selling point |\n| `biographical-note` | `12` | Biographical note about a contributor |\n| `publishers-notive` | `13` | Publisher's notice *(slug misspelled — send it exactly as shown)* |\n| `excerpt` | `14` | Excerpt |\n| `index` | `15` | Index |\n| `short-description-annotiation-for-collation` | `16` | Short description for the collection *(slug misspelled — send it exactly as shown)* |\n| `description-for-collection` | `17` | Description for the collection (series) |\n| `new-feature` | `18` | New feature — what changed in this edition |\n| `version-history` | `19` | Version history |\n| `open-access-statement` | `20` | Open access statement |\n| `digital-exclusivity-statement` | `21` | Digital exclusivity statement |\n| `official-recommendation` | `22` | Official recommendation |\n| `jbpa-description` | `23` | JBPA description |\n| `schema-org-snippet` | `24` | schema.org snippet |\n| `errata` | `25` | Errata |\n| `intriduction` | `26` | Introduction *(slug misspelled — send it exactly as shown)* |\n| `secondary-cover-copy` | `27` | Secondary cover copy |\n| `full-cast-and-credit-list` | `28` | Full cast and credit list |\n| `bibliography` | `29` | Bibliography |\n| `abstract` | `30` | Abstract — the scholarly summary, not a marketing blurb |\n| `rules-or-instructions` | `31` | Rules or instructions |\n| `list-of-contents` | `32` | List of contents — components of a multi-item product |\n| `short-description-annotation-for-imprint` | `33` | Short description for the imprint |\n| `description-for-imprint` | `34` | Description for the imprint |\n| `short-description-annotation-for-publisher` | `35` | Short description for the publisher |\n| `description-for-publisher` | `36` | Description for the publisher |\n| `cover-line` | `37` | Cover line |\n\nThree of those slugs — `publishers-notive`, `short-description-annotiation-for-collation`\nand `intriduction` — are misspelled, and the table lists them as they must be sent to\nobtain a code. The correctly spelled forms `publishers-notice`,\n`short-description-annotation-for-collection` and `introduction` are accepted as well,\nbut they are not recognised and yield `type_onix: null`.\n\n**This is the only field the collection endpoint can filter on**, with the operators\ndescribed under [Resource Queries](/resource_queries/). Any other field name is\nrejected with `400 Bad Request`, as is an unknown operator suffix, so `language` and\n`channels` have to be narrowed down client-side. Results cannot be sorted: a `sort`\nparameter is accepted and applied to nothing, which leaves the order of results\nunspecified. Pagination is standard, with a default page size of 100.\n",
                        "example": "biographical-note",
                        "x-enum-descriptions": {
                            "sender-defined-text": "ONIX 153 code 01 — Sender-defined text.",
                            "short-description-annotation": "ONIX 153 code 02 — Short description/annotation; the abridged blurb for listings and feeds.",
                            "description": "ONIX 153 code 03 — Description; the main long-form selling copy.",
                            "table-of-contents": "ONIX 153 code 04 — Table of contents.",
                            "primary-cover-copy": "ONIX 153 code 05 — Primary cover copy; the text printed on the cover or jacket.",
                            "review-quote": "ONIX 153 code 06 — Review quote for this edition.",
                            "review-quote-previous-edition": "ONIX 153 code 07 — Review quote taken from a review of a previous edition.",
                            "review-quote-previous-work": "ONIX 153 code 08 — Review quote taken from a review of a previous work by the same author.",
                            "endorsement": "ONIX 153 code 09 — Endorsement; a commendation solicited by the publisher.",
                            "promotional-headline": "ONIX 153 code 10 — Promotional headline; the one-line hook.",
                            "feature": "ONIX 153 code 11 — Feature; a single selling point, usually one of a set of bullets.",
                            "biographical-note": "ONIX 153 code 12 — Biographical note about a contributor.",
                            "publishers-notive": "ONIX 153 code 13 — Publisher's notice. The slug is misspelled; send it exactly as shown.",
                            "excerpt": "ONIX 153 code 14 — Excerpt; a sample passage from the work.",
                            "index": "ONIX 153 code 15 — Index.",
                            "short-description-annotiation-for-collation": "ONIX 153 code 16 — Short description/annotation for the collection (series) this product belongs to. The slug is misspelled; send it exactly as shown.",
                            "description-for-collection": "ONIX 153 code 17 — Description of the collection (series) this product belongs to.",
                            "new-feature": "ONIX 153 code 18 — New feature; what changed in this edition.",
                            "version-history": "ONIX 153 code 19 — Version history.",
                            "open-access-statement": "ONIX 153 code 20 — Open access statement; the licence and access terms.",
                            "digital-exclusivity-statement": "ONIX 153 code 21 — Digital exclusivity statement.",
                            "official-recommendation": "ONIX 153 code 22 — Official recommendation, e.g. by an educational authority.",
                            "jbpa-description": "ONIX 153 code 23 — JBPA description (Japanese Book Publishers Association).",
                            "schema-org-snippet": "ONIX 153 code 24 — schema.org snippet for search-engine markup.",
                            "errata": "ONIX 153 code 25 — Errata.",
                            "intriduction": "ONIX 153 code 26 — Introduction. The slug is misspelled; send it exactly as shown.",
                            "secondary-cover-copy": "ONIX 153 code 27 — Secondary cover copy, e.g. back cover as opposed to front.",
                            "full-cast-and-credit-list": "ONIX 153 code 28 — Full cast and credit list; used for audiobooks and dramatisations.",
                            "bibliography": "ONIX 153 code 29 — Bibliography.",
                            "abstract": "ONIX 153 code 30 — Abstract; the scholarly summary, distinct from a marketing blurb.",
                            "rules-or-instructions": "ONIX 153 code 31 — Rules or instructions, e.g. for a game or kit.",
                            "list-of-contents": "ONIX 153 code 32 — List of contents; the components of a multi-item product.",
                            "short-description-annotation-for-imprint": "ONIX 153 code 33 — Short description/annotation for the imprint.",
                            "description-for-imprint": "ONIX 153 code 34 — Description of the imprint.",
                            "short-description-annotation-for-publisher": "ONIX 153 code 35 — Short description/annotation for the publisher.",
                            "description-for-publisher": "ONIX 153 code 36 — Description of the publisher.",
                            "cover-line": "ONIX 153 code 37 — Cover line; a strapline carried on the cover."
                        }
                    },
                    "type_onix": {
                        "type": "string",
                        "description": "The [ONIX Codelist 153](https://ns.editeur.org/onix/en/153) text type code\ncorresponding to `type`, as a two-digit string (`\"03\"` description, `\"12\"`\nbiographical note, …). Present so that ONIX consumers do not have to reimplement the\nslug mapping.\n\n**Read-only in effect.** The field is accepted in a request body but the value is\ndiscarded: the server recomputes it from `type` on every write. It is `null` whenever\n`type` is not one of the 37 recognised slugs. To change it, change `type`.\n\nNote that this is Codelist **153** (ONIX 3 `<TextType>`), not the ONIX 2.1 Codelist 33\n(`<OtherText>` type) that earlier revisions of this schema named. The two lists assign\ndifferent codes to the same concepts — a biographical note is `12` in 153 and `13` in\n33 — so a consumer that reads these codes against Codelist 33 will mislabel them.\n",
                        "nullable": true,
                        "example": "12"
                    },
                    "mime_type": {
                        "type": "string",
                        "description": "How `text` is encoded. In practice two values are used:\n\n- `text/plain` — literal text; line breaks are significant and a consumer must escape\n  it before putting it into a web page. The default when the field is omitted on\n  create.\n- `text/html` — an HTML fragment, typically wrapped in `<p>` elements. The API stores\n  it as sent and does not sanitise it, so a storefront rendering the value unescaped\n  is trusting whoever wrote it.\n\nValidation is **syntactic only**: any well-formed `type/subtype[; parameters]` string\nup to 255 characters is accepted, so a misspelling such as `text/htlm` is stored\nwithout complaint and is only noticed when the value is used. A malformed value is\nrejected with `400 Bad Request`, as is an empty one.\n\nBook-trade descriptions are usually HTML, while biographies and tables of contents are\nusually plain text, but nothing in the API enforces that pairing — `mime_type` is\nrecorded independently of `type`.\n",
                        "example": "text/plain"
                    }
                },
                "required": []
            }
        }
    },
    "required": [
        "_links",
        "_pagination",
        "items"
    ]
}

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

Create a new product text

Description

Creates one text entry on the product. text and type are required — both must be non-empty, or the request is rejected with 400. Everything else may be omitted: mime_type then defaults to text/plain, language to null, and channels to the empty list (meaning all channels).

type_onix is ignored when sent; the server derives it from type.

The example creates a German author biography: plain text, no channel restriction, so every channel and storefront can use it.

Input parameters

Path parameters

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

Request body

{
    "type": "biographical-note",
    "text": "Marit Sallenberg arbeitete als Lektorin und Kulturjournalistin, bevor sie ihren ersten Roman veroeffentlichte. Sie schreibt Gesellschaftsromane und lebt als freie Autorin in Rheinbergen.",
    "mime_type": "text/plain",
    "language": "ger",
    "channels": []
}
Schema of the request body
{
    "type": "object",
    "additionalProperties": false,
    "description": "One piece of descriptive copy attached to a product, in a single language, tagged by text type.",
    "properties": {
        "_id": {
            "type": "string",
            "description": "Unique identifier (UUID) for the product text.",
            "example": "3d5a9c14-7b02-4e88-9a61-0c7f2e4d8b35"
        },
        "_version": {
            "type": "string",
            "description": "API Version.",
            "example": "4.0"
        },
        "_legacy_id": {
            "type": "integer",
            "description": "Legacy integer identifier of this resource, kept so existing integrations can correlate their own records. This is the `_id` the same record has on the v3 endpoint.",
            "example": 4180231
        },
        "_links": {
            "type": "object"
        },
        "text": {
            "type": "string",
            "description": "The text itself. Its interpretation follows `mime_type`: with `text/plain` it is\nliteral characters and line breaks; with `text/html` it is a fragment of markup\n(typically `<p>` paragraphs) that a storefront can drop into a page.\n\nMust not be empty — a create or update that would leave `text` empty is rejected\nwith `400 Bad Request`.\n\nThere is no business length limit: an entry comfortably holds a full table of contents\nor a sample chapter, and the practical ceiling comes from the receiving channel rather\nthan from this API. Characters outside the Basic Multilingual Plane — emoji, and some\nrarely used CJK and historic scripts — are not supported.\n\n**This sub-resource is a standalone store.** It is independent of the legacy\ndescriptive fields carried directly on the v3 product record (`abstract`,\n`abstract_prefix`, `biographical_note`, `table_of_content`): a text written here does\nnot update those, and reading them does not surface entries created here. An entry is\nreachable through this sub-resource and its v3 equivalent, and nowhere else in the\nAPI.\n",
            "example": "Marit Sallenberg arbeitete als Lektorin und Kulturjournalistin, bevor sie ihren ersten Roman veroeffentlichte. Sie schreibt Gesellschaftsromane und lebt als freie Autorin in Rheinbergen."
        },
        "channels": {
            "type": "array",
            "description": "Distribution channels this text is intended for. An **empty list means the text\napplies to every channel** and is the normal case; it is populated only when a partner\nneeds different copy from everyone else — for example a shortened blurb for a\nretailer with a character limit, or a description that omits a competitor's name.\n\nValues are the platform's distribution-channel slugs. Those in common use are:\n\n- `google`\n- `amazon`\n- `kobo`\n- `spotify`\n- `libri`\n- `ciando`\n- `divibib`\n- `overdrive`\n- `scribd`\n- `bookwire`\n\nThe list is open-ended — a realm distributes through whichever partners it has\ncontracts with. **They are not validated against the channel list** — any string of lowercase letters and\nhyphens is accepted, so a typo silently produces a text that no channel will ever\nmatch. Note that channel slugs containing digits or underscores (`24symbols`,\n`manual_sale`, `zeitfracht_sa02e`) are valid channels elsewhere in the API but are\n**rejected** here, because this field allows only `[a-z-]`.\n\nThe list is normalised on write: values are lower-cased, de-duplicated and sorted\nalphabetically. Sending `[\"Google\", \"amazon\", \"google\"]` stores and returns\n`[\"amazon\", \"google\"]`. On update the list is replaced wholesale, never merged.\n\nThis endpoint applies no fallback logic of its own: it returns the entries exactly as\nstored, so selecting copy for one channel means preferring an entry that names that\nchannel and otherwise taking the unscoped one.\n\n**`channels` is the only scoping axis this resource has, and it is narrower than\nONIX.** An ONIX 3 `<TextContent>` is also scoped by content audience\n([Codelist 154](https://ns.editeur.org/onix/en/154) — booktrade, end-customers,\nlibrarians, press, …) and by text source and validity dates; none of those fields\nexist here. `channels` names distribution partners, not classes of reader.\n\n**Storefronts are a separate axis and are not handled here.** Per-shop copy — HTML\ntitle, meta description, meta keywords — belongs to the\n`/resource/v4/products/{product_id}/storefronts` sub-resource.\n",
            "items": {
                "type": "string"
            },
            "example": []
        },
        "language": {
            "type": "string",
            "description": "Language of `text`, as a three-letter ISO 639-2/B (bibliographic) code — `ger` for\nGerman, `eng` for English, `fre` for French. Note the B-codes: German is `ger`, not\n`deu`. Case is normalised to lower case on write; an unknown code is rejected with\n`400 Bad Request`.\n\n`null` when the language is unknown or not meaningful. A product carrying the same\n`type` in several languages holds one entry per language — nothing prevents\nduplicates, so a consumer picking \"the description\" should filter by the language it\nwants and fall back to the product's own `language`.\n\nNote that a language once set cannot be cleared: sending `\"language\": null` is\nrejected with `400 Bad Request`.\n",
            "nullable": true,
            "example": "ger"
        },
        "type": {
            "type": "string",
            "description": "What kind of text this is. **Not a closed enumeration** — any non-empty string of\nlowercase letters and hyphens (`[a-z-]`, up to 255 characters) is accepted. Digits,\nunderscores, spaces and upper case are rejected with `400 Bad Request`, as is an\nempty value.\n\n37 slugs are recognised as equivalents of [ONIX Codelist\n153](https://ns.editeur.org/onix/en/153) values; for those the server derives\n`type_onix`. Anything else is stored as given with `type_onix: null`, which is the\nsupported way to carry copy that ONIX has no code for.\n\nA few of the distinctions in the list are easy to get wrong:\n\n- `description` (03) is the main long-form selling copy;\n  `short-description-annotation` (02) is the abridged version for listings and feeds\n  with a length budget. They are separate entries, not two renderings of one.\n- `biographical-note` (12) is about the author, not about the book, and takes one entry\n  per contributor where there are several.\n- `review-quote` (06) is a quotation from a published review of *this* edition;\n  `review-quote-previous-edition` (07) and `review-quote-previous-work` (08) exist for\n  quotes that refer to something else.\n- `endorsement` (09) is a commendation solicited by the publisher, as distinct from a\n  review published independently.\n- `abstract` (30) is the scholarly abstract, not a marketing blurb.\n- `table-of-contents` (04) is conventionally `text/plain` with one heading per line.\n\nThe complete set of recognised slugs, with the [Codelist\n153](https://ns.editeur.org/onix/en/153) code each one derives:\n\n| `type` | `type_onix` | Meaning |\n|---|---|---|\n| `sender-defined-text` | `01` | Sender-defined text |\n| `short-description-annotation` | `02` | Short description / annotation — the abridged blurb for listings and feeds |\n| `description` | `03` | Description — the main long-form selling copy |\n| `table-of-contents` | `04` | Table of contents |\n| `primary-cover-copy` | `05` | Primary cover copy — text printed on the cover or jacket |\n| `review-quote` | `06` | Review quote |\n| `review-quote-previous-edition` | `07` | Review quote, previous edition |\n| `review-quote-previous-work` | `08` | Review quote, previous work |\n| `endorsement` | `09` | Endorsement — solicited by the publisher, unlike a review |\n| `promotional-headline` | `10` | Promotional headline |\n| `feature` | `11` | Feature — a single selling point |\n| `biographical-note` | `12` | Biographical note about a contributor |\n| `publishers-notive` | `13` | Publisher's notice *(slug misspelled — send it exactly as shown)* |\n| `excerpt` | `14` | Excerpt |\n| `index` | `15` | Index |\n| `short-description-annotiation-for-collation` | `16` | Short description for the collection *(slug misspelled — send it exactly as shown)* |\n| `description-for-collection` | `17` | Description for the collection (series) |\n| `new-feature` | `18` | New feature — what changed in this edition |\n| `version-history` | `19` | Version history |\n| `open-access-statement` | `20` | Open access statement |\n| `digital-exclusivity-statement` | `21` | Digital exclusivity statement |\n| `official-recommendation` | `22` | Official recommendation |\n| `jbpa-description` | `23` | JBPA description |\n| `schema-org-snippet` | `24` | schema.org snippet |\n| `errata` | `25` | Errata |\n| `intriduction` | `26` | Introduction *(slug misspelled — send it exactly as shown)* |\n| `secondary-cover-copy` | `27` | Secondary cover copy |\n| `full-cast-and-credit-list` | `28` | Full cast and credit list |\n| `bibliography` | `29` | Bibliography |\n| `abstract` | `30` | Abstract — the scholarly summary, not a marketing blurb |\n| `rules-or-instructions` | `31` | Rules or instructions |\n| `list-of-contents` | `32` | List of contents — components of a multi-item product |\n| `short-description-annotation-for-imprint` | `33` | Short description for the imprint |\n| `description-for-imprint` | `34` | Description for the imprint |\n| `short-description-annotation-for-publisher` | `35` | Short description for the publisher |\n| `description-for-publisher` | `36` | Description for the publisher |\n| `cover-line` | `37` | Cover line |\n\nThree of those slugs — `publishers-notive`, `short-description-annotiation-for-collation`\nand `intriduction` — are misspelled, and the table lists them as they must be sent to\nobtain a code. The correctly spelled forms `publishers-notice`,\n`short-description-annotation-for-collection` and `introduction` are accepted as well,\nbut they are not recognised and yield `type_onix: null`.\n\n**This is the only field the collection endpoint can filter on**, with the operators\ndescribed under [Resource Queries](/resource_queries/). Any other field name is\nrejected with `400 Bad Request`, as is an unknown operator suffix, so `language` and\n`channels` have to be narrowed down client-side. Results cannot be sorted: a `sort`\nparameter is accepted and applied to nothing, which leaves the order of results\nunspecified. Pagination is standard, with a default page size of 100.\n",
            "example": "biographical-note",
            "x-enum-descriptions": {
                "sender-defined-text": "ONIX 153 code 01 — Sender-defined text.",
                "short-description-annotation": "ONIX 153 code 02 — Short description/annotation; the abridged blurb for listings and feeds.",
                "description": "ONIX 153 code 03 — Description; the main long-form selling copy.",
                "table-of-contents": "ONIX 153 code 04 — Table of contents.",
                "primary-cover-copy": "ONIX 153 code 05 — Primary cover copy; the text printed on the cover or jacket.",
                "review-quote": "ONIX 153 code 06 — Review quote for this edition.",
                "review-quote-previous-edition": "ONIX 153 code 07 — Review quote taken from a review of a previous edition.",
                "review-quote-previous-work": "ONIX 153 code 08 — Review quote taken from a review of a previous work by the same author.",
                "endorsement": "ONIX 153 code 09 — Endorsement; a commendation solicited by the publisher.",
                "promotional-headline": "ONIX 153 code 10 — Promotional headline; the one-line hook.",
                "feature": "ONIX 153 code 11 — Feature; a single selling point, usually one of a set of bullets.",
                "biographical-note": "ONIX 153 code 12 — Biographical note about a contributor.",
                "publishers-notive": "ONIX 153 code 13 — Publisher's notice. The slug is misspelled; send it exactly as shown.",
                "excerpt": "ONIX 153 code 14 — Excerpt; a sample passage from the work.",
                "index": "ONIX 153 code 15 — Index.",
                "short-description-annotiation-for-collation": "ONIX 153 code 16 — Short description/annotation for the collection (series) this product belongs to. The slug is misspelled; send it exactly as shown.",
                "description-for-collection": "ONIX 153 code 17 — Description of the collection (series) this product belongs to.",
                "new-feature": "ONIX 153 code 18 — New feature; what changed in this edition.",
                "version-history": "ONIX 153 code 19 — Version history.",
                "open-access-statement": "ONIX 153 code 20 — Open access statement; the licence and access terms.",
                "digital-exclusivity-statement": "ONIX 153 code 21 — Digital exclusivity statement.",
                "official-recommendation": "ONIX 153 code 22 — Official recommendation, e.g. by an educational authority.",
                "jbpa-description": "ONIX 153 code 23 — JBPA description (Japanese Book Publishers Association).",
                "schema-org-snippet": "ONIX 153 code 24 — schema.org snippet for search-engine markup.",
                "errata": "ONIX 153 code 25 — Errata.",
                "intriduction": "ONIX 153 code 26 — Introduction. The slug is misspelled; send it exactly as shown.",
                "secondary-cover-copy": "ONIX 153 code 27 — Secondary cover copy, e.g. back cover as opposed to front.",
                "full-cast-and-credit-list": "ONIX 153 code 28 — Full cast and credit list; used for audiobooks and dramatisations.",
                "bibliography": "ONIX 153 code 29 — Bibliography.",
                "abstract": "ONIX 153 code 30 — Abstract; the scholarly summary, distinct from a marketing blurb.",
                "rules-or-instructions": "ONIX 153 code 31 — Rules or instructions, e.g. for a game or kit.",
                "list-of-contents": "ONIX 153 code 32 — List of contents; the components of a multi-item product.",
                "short-description-annotation-for-imprint": "ONIX 153 code 33 — Short description/annotation for the imprint.",
                "description-for-imprint": "ONIX 153 code 34 — Description of the imprint.",
                "short-description-annotation-for-publisher": "ONIX 153 code 35 — Short description/annotation for the publisher.",
                "description-for-publisher": "ONIX 153 code 36 — Description of the publisher.",
                "cover-line": "ONIX 153 code 37 — Cover line; a strapline carried on the cover."
            }
        },
        "type_onix": {
            "type": "string",
            "description": "The [ONIX Codelist 153](https://ns.editeur.org/onix/en/153) text type code\ncorresponding to `type`, as a two-digit string (`\"03\"` description, `\"12\"`\nbiographical note, …). Present so that ONIX consumers do not have to reimplement the\nslug mapping.\n\n**Read-only in effect.** The field is accepted in a request body but the value is\ndiscarded: the server recomputes it from `type` on every write. It is `null` whenever\n`type` is not one of the 37 recognised slugs. To change it, change `type`.\n\nNote that this is Codelist **153** (ONIX 3 `<TextType>`), not the ONIX 2.1 Codelist 33\n(`<OtherText>` type) that earlier revisions of this schema named. The two lists assign\ndifferent codes to the same concepts — a biographical note is `12` in 153 and `13` in\n33 — so a consumer that reads these codes against Codelist 33 will mislabel them.\n",
            "nullable": true,
            "example": "12"
        },
        "mime_type": {
            "type": "string",
            "description": "How `text` is encoded. In practice two values are used:\n\n- `text/plain` — literal text; line breaks are significant and a consumer must escape\n  it before putting it into a web page. The default when the field is omitted on\n  create.\n- `text/html` — an HTML fragment, typically wrapped in `<p>` elements. The API stores\n  it as sent and does not sanitise it, so a storefront rendering the value unescaped\n  is trusting whoever wrote it.\n\nValidation is **syntactic only**: any well-formed `type/subtype[; parameters]` string\nup to 255 characters is accepted, so a misspelling such as `text/htlm` is stored\nwithout complaint and is only noticed when the value is used. A malformed value is\nrejected with `400 Bad Request`, as is an empty one.\n\nBook-trade descriptions are usually HTML, while biographies and tables of contents are\nusually plain text, but nothing in the API enforces that pairing — `mime_type` is\nrecorded independently of `type`.\n",
            "example": "text/plain"
        }
    },
    "required": []
}

Responses

{
    "_id": "3d5a9c14-7b02-4e88-9a61-0c7f2e4d8b35",
    "_legacy_id": 4180231,
    "_version": "4.0",
    "_links": {
        "self": "https://api.openpublishing.com/resource/v4/products/e8659334-e616-11ee-a221-00505699575c/texts/c6f34176-c138-47d7-9627-dce17b4a948d"
    },
    "type": "biographical-note",
    "type_onix": "12",
    "text": "Marit Sallenberg arbeitete als Lektorin und Kulturjournalistin, bevor sie ihren ersten Roman veroeffentlichte. Sie schreibt Gesellschaftsromane und lebt als freie Autorin in Rheinbergen.",
    "mime_type": "text/plain",
    "language": "ger",
    "channels": []
}
Schema of the response body
{
    "type": "object",
    "additionalProperties": false,
    "description": "One piece of descriptive copy attached to a product, in a single language, tagged by text type.",
    "properties": {
        "_id": {
            "type": "string",
            "description": "Unique identifier (UUID) for the product text.",
            "example": "3d5a9c14-7b02-4e88-9a61-0c7f2e4d8b35"
        },
        "_version": {
            "type": "string",
            "description": "API Version.",
            "example": "4.0"
        },
        "_legacy_id": {
            "type": "integer",
            "description": "Legacy integer identifier of this resource, kept so existing integrations can correlate their own records. This is the `_id` the same record has on the v3 endpoint.",
            "example": 4180231
        },
        "_links": {
            "type": "object"
        },
        "text": {
            "type": "string",
            "description": "The text itself. Its interpretation follows `mime_type`: with `text/plain` it is\nliteral characters and line breaks; with `text/html` it is a fragment of markup\n(typically `<p>` paragraphs) that a storefront can drop into a page.\n\nMust not be empty — a create or update that would leave `text` empty is rejected\nwith `400 Bad Request`.\n\nThere is no business length limit: an entry comfortably holds a full table of contents\nor a sample chapter, and the practical ceiling comes from the receiving channel rather\nthan from this API. Characters outside the Basic Multilingual Plane — emoji, and some\nrarely used CJK and historic scripts — are not supported.\n\n**This sub-resource is a standalone store.** It is independent of the legacy\ndescriptive fields carried directly on the v3 product record (`abstract`,\n`abstract_prefix`, `biographical_note`, `table_of_content`): a text written here does\nnot update those, and reading them does not surface entries created here. An entry is\nreachable through this sub-resource and its v3 equivalent, and nowhere else in the\nAPI.\n",
            "example": "Marit Sallenberg arbeitete als Lektorin und Kulturjournalistin, bevor sie ihren ersten Roman veroeffentlichte. Sie schreibt Gesellschaftsromane und lebt als freie Autorin in Rheinbergen."
        },
        "channels": {
            "type": "array",
            "description": "Distribution channels this text is intended for. An **empty list means the text\napplies to every channel** and is the normal case; it is populated only when a partner\nneeds different copy from everyone else — for example a shortened blurb for a\nretailer with a character limit, or a description that omits a competitor's name.\n\nValues are the platform's distribution-channel slugs. Those in common use are:\n\n- `google`\n- `amazon`\n- `kobo`\n- `spotify`\n- `libri`\n- `ciando`\n- `divibib`\n- `overdrive`\n- `scribd`\n- `bookwire`\n\nThe list is open-ended — a realm distributes through whichever partners it has\ncontracts with. **They are not validated against the channel list** — any string of lowercase letters and\nhyphens is accepted, so a typo silently produces a text that no channel will ever\nmatch. Note that channel slugs containing digits or underscores (`24symbols`,\n`manual_sale`, `zeitfracht_sa02e`) are valid channels elsewhere in the API but are\n**rejected** here, because this field allows only `[a-z-]`.\n\nThe list is normalised on write: values are lower-cased, de-duplicated and sorted\nalphabetically. Sending `[\"Google\", \"amazon\", \"google\"]` stores and returns\n`[\"amazon\", \"google\"]`. On update the list is replaced wholesale, never merged.\n\nThis endpoint applies no fallback logic of its own: it returns the entries exactly as\nstored, so selecting copy for one channel means preferring an entry that names that\nchannel and otherwise taking the unscoped one.\n\n**`channels` is the only scoping axis this resource has, and it is narrower than\nONIX.** An ONIX 3 `<TextContent>` is also scoped by content audience\n([Codelist 154](https://ns.editeur.org/onix/en/154) — booktrade, end-customers,\nlibrarians, press, …) and by text source and validity dates; none of those fields\nexist here. `channels` names distribution partners, not classes of reader.\n\n**Storefronts are a separate axis and are not handled here.** Per-shop copy — HTML\ntitle, meta description, meta keywords — belongs to the\n`/resource/v4/products/{product_id}/storefronts` sub-resource.\n",
            "items": {
                "type": "string"
            },
            "example": []
        },
        "language": {
            "type": "string",
            "description": "Language of `text`, as a three-letter ISO 639-2/B (bibliographic) code — `ger` for\nGerman, `eng` for English, `fre` for French. Note the B-codes: German is `ger`, not\n`deu`. Case is normalised to lower case on write; an unknown code is rejected with\n`400 Bad Request`.\n\n`null` when the language is unknown or not meaningful. A product carrying the same\n`type` in several languages holds one entry per language — nothing prevents\nduplicates, so a consumer picking \"the description\" should filter by the language it\nwants and fall back to the product's own `language`.\n\nNote that a language once set cannot be cleared: sending `\"language\": null` is\nrejected with `400 Bad Request`.\n",
            "nullable": true,
            "example": "ger"
        },
        "type": {
            "type": "string",
            "description": "What kind of text this is. **Not a closed enumeration** — any non-empty string of\nlowercase letters and hyphens (`[a-z-]`, up to 255 characters) is accepted. Digits,\nunderscores, spaces and upper case are rejected with `400 Bad Request`, as is an\nempty value.\n\n37 slugs are recognised as equivalents of [ONIX Codelist\n153](https://ns.editeur.org/onix/en/153) values; for those the server derives\n`type_onix`. Anything else is stored as given with `type_onix: null`, which is the\nsupported way to carry copy that ONIX has no code for.\n\nA few of the distinctions in the list are easy to get wrong:\n\n- `description` (03) is the main long-form selling copy;\n  `short-description-annotation` (02) is the abridged version for listings and feeds\n  with a length budget. They are separate entries, not two renderings of one.\n- `biographical-note` (12) is about the author, not about the book, and takes one entry\n  per contributor where there are several.\n- `review-quote` (06) is a quotation from a published review of *this* edition;\n  `review-quote-previous-edition` (07) and `review-quote-previous-work` (08) exist for\n  quotes that refer to something else.\n- `endorsement` (09) is a commendation solicited by the publisher, as distinct from a\n  review published independently.\n- `abstract` (30) is the scholarly abstract, not a marketing blurb.\n- `table-of-contents` (04) is conventionally `text/plain` with one heading per line.\n\nThe complete set of recognised slugs, with the [Codelist\n153](https://ns.editeur.org/onix/en/153) code each one derives:\n\n| `type` | `type_onix` | Meaning |\n|---|---|---|\n| `sender-defined-text` | `01` | Sender-defined text |\n| `short-description-annotation` | `02` | Short description / annotation — the abridged blurb for listings and feeds |\n| `description` | `03` | Description — the main long-form selling copy |\n| `table-of-contents` | `04` | Table of contents |\n| `primary-cover-copy` | `05` | Primary cover copy — text printed on the cover or jacket |\n| `review-quote` | `06` | Review quote |\n| `review-quote-previous-edition` | `07` | Review quote, previous edition |\n| `review-quote-previous-work` | `08` | Review quote, previous work |\n| `endorsement` | `09` | Endorsement — solicited by the publisher, unlike a review |\n| `promotional-headline` | `10` | Promotional headline |\n| `feature` | `11` | Feature — a single selling point |\n| `biographical-note` | `12` | Biographical note about a contributor |\n| `publishers-notive` | `13` | Publisher's notice *(slug misspelled — send it exactly as shown)* |\n| `excerpt` | `14` | Excerpt |\n| `index` | `15` | Index |\n| `short-description-annotiation-for-collation` | `16` | Short description for the collection *(slug misspelled — send it exactly as shown)* |\n| `description-for-collection` | `17` | Description for the collection (series) |\n| `new-feature` | `18` | New feature — what changed in this edition |\n| `version-history` | `19` | Version history |\n| `open-access-statement` | `20` | Open access statement |\n| `digital-exclusivity-statement` | `21` | Digital exclusivity statement |\n| `official-recommendation` | `22` | Official recommendation |\n| `jbpa-description` | `23` | JBPA description |\n| `schema-org-snippet` | `24` | schema.org snippet |\n| `errata` | `25` | Errata |\n| `intriduction` | `26` | Introduction *(slug misspelled — send it exactly as shown)* |\n| `secondary-cover-copy` | `27` | Secondary cover copy |\n| `full-cast-and-credit-list` | `28` | Full cast and credit list |\n| `bibliography` | `29` | Bibliography |\n| `abstract` | `30` | Abstract — the scholarly summary, not a marketing blurb |\n| `rules-or-instructions` | `31` | Rules or instructions |\n| `list-of-contents` | `32` | List of contents — components of a multi-item product |\n| `short-description-annotation-for-imprint` | `33` | Short description for the imprint |\n| `description-for-imprint` | `34` | Description for the imprint |\n| `short-description-annotation-for-publisher` | `35` | Short description for the publisher |\n| `description-for-publisher` | `36` | Description for the publisher |\n| `cover-line` | `37` | Cover line |\n\nThree of those slugs — `publishers-notive`, `short-description-annotiation-for-collation`\nand `intriduction` — are misspelled, and the table lists them as they must be sent to\nobtain a code. The correctly spelled forms `publishers-notice`,\n`short-description-annotation-for-collection` and `introduction` are accepted as well,\nbut they are not recognised and yield `type_onix: null`.\n\n**This is the only field the collection endpoint can filter on**, with the operators\ndescribed under [Resource Queries](/resource_queries/). Any other field name is\nrejected with `400 Bad Request`, as is an unknown operator suffix, so `language` and\n`channels` have to be narrowed down client-side. Results cannot be sorted: a `sort`\nparameter is accepted and applied to nothing, which leaves the order of results\nunspecified. Pagination is standard, with a default page size of 100.\n",
            "example": "biographical-note",
            "x-enum-descriptions": {
                "sender-defined-text": "ONIX 153 code 01 — Sender-defined text.",
                "short-description-annotation": "ONIX 153 code 02 — Short description/annotation; the abridged blurb for listings and feeds.",
                "description": "ONIX 153 code 03 — Description; the main long-form selling copy.",
                "table-of-contents": "ONIX 153 code 04 — Table of contents.",
                "primary-cover-copy": "ONIX 153 code 05 — Primary cover copy; the text printed on the cover or jacket.",
                "review-quote": "ONIX 153 code 06 — Review quote for this edition.",
                "review-quote-previous-edition": "ONIX 153 code 07 — Review quote taken from a review of a previous edition.",
                "review-quote-previous-work": "ONIX 153 code 08 — Review quote taken from a review of a previous work by the same author.",
                "endorsement": "ONIX 153 code 09 — Endorsement; a commendation solicited by the publisher.",
                "promotional-headline": "ONIX 153 code 10 — Promotional headline; the one-line hook.",
                "feature": "ONIX 153 code 11 — Feature; a single selling point, usually one of a set of bullets.",
                "biographical-note": "ONIX 153 code 12 — Biographical note about a contributor.",
                "publishers-notive": "ONIX 153 code 13 — Publisher's notice. The slug is misspelled; send it exactly as shown.",
                "excerpt": "ONIX 153 code 14 — Excerpt; a sample passage from the work.",
                "index": "ONIX 153 code 15 — Index.",
                "short-description-annotiation-for-collation": "ONIX 153 code 16 — Short description/annotation for the collection (series) this product belongs to. The slug is misspelled; send it exactly as shown.",
                "description-for-collection": "ONIX 153 code 17 — Description of the collection (series) this product belongs to.",
                "new-feature": "ONIX 153 code 18 — New feature; what changed in this edition.",
                "version-history": "ONIX 153 code 19 — Version history.",
                "open-access-statement": "ONIX 153 code 20 — Open access statement; the licence and access terms.",
                "digital-exclusivity-statement": "ONIX 153 code 21 — Digital exclusivity statement.",
                "official-recommendation": "ONIX 153 code 22 — Official recommendation, e.g. by an educational authority.",
                "jbpa-description": "ONIX 153 code 23 — JBPA description (Japanese Book Publishers Association).",
                "schema-org-snippet": "ONIX 153 code 24 — schema.org snippet for search-engine markup.",
                "errata": "ONIX 153 code 25 — Errata.",
                "intriduction": "ONIX 153 code 26 — Introduction. The slug is misspelled; send it exactly as shown.",
                "secondary-cover-copy": "ONIX 153 code 27 — Secondary cover copy, e.g. back cover as opposed to front.",
                "full-cast-and-credit-list": "ONIX 153 code 28 — Full cast and credit list; used for audiobooks and dramatisations.",
                "bibliography": "ONIX 153 code 29 — Bibliography.",
                "abstract": "ONIX 153 code 30 — Abstract; the scholarly summary, distinct from a marketing blurb.",
                "rules-or-instructions": "ONIX 153 code 31 — Rules or instructions, e.g. for a game or kit.",
                "list-of-contents": "ONIX 153 code 32 — List of contents; the components of a multi-item product.",
                "short-description-annotation-for-imprint": "ONIX 153 code 33 — Short description/annotation for the imprint.",
                "description-for-imprint": "ONIX 153 code 34 — Description of the imprint.",
                "short-description-annotation-for-publisher": "ONIX 153 code 35 — Short description/annotation for the publisher.",
                "description-for-publisher": "ONIX 153 code 36 — Description of the publisher.",
                "cover-line": "ONIX 153 code 37 — Cover line; a strapline carried on the cover."
            }
        },
        "type_onix": {
            "type": "string",
            "description": "The [ONIX Codelist 153](https://ns.editeur.org/onix/en/153) text type code\ncorresponding to `type`, as a two-digit string (`\"03\"` description, `\"12\"`\nbiographical note, …). Present so that ONIX consumers do not have to reimplement the\nslug mapping.\n\n**Read-only in effect.** The field is accepted in a request body but the value is\ndiscarded: the server recomputes it from `type` on every write. It is `null` whenever\n`type` is not one of the 37 recognised slugs. To change it, change `type`.\n\nNote that this is Codelist **153** (ONIX 3 `<TextType>`), not the ONIX 2.1 Codelist 33\n(`<OtherText>` type) that earlier revisions of this schema named. The two lists assign\ndifferent codes to the same concepts — a biographical note is `12` in 153 and `13` in\n33 — so a consumer that reads these codes against Codelist 33 will mislabel them.\n",
            "nullable": true,
            "example": "12"
        },
        "mime_type": {
            "type": "string",
            "description": "How `text` is encoded. In practice two values are used:\n\n- `text/plain` — literal text; line breaks are significant and a consumer must escape\n  it before putting it into a web page. The default when the field is omitted on\n  create.\n- `text/html` — an HTML fragment, typically wrapped in `<p>` elements. The API stores\n  it as sent and does not sanitise it, so a storefront rendering the value unescaped\n  is trusting whoever wrote it.\n\nValidation is **syntactic only**: any well-formed `type/subtype[; parameters]` string\nup to 255 characters is accepted, so a misspelling such as `text/htlm` is stored\nwithout complaint and is only noticed when the value is used. A malformed value is\nrejected with `400 Bad Request`, as is an empty one.\n\nBook-trade descriptions are usually HTML, while biographies and tables of contents are\nusually plain text, but nothing in the API enforces that pairing — `mime_type` is\nrecorded independently of `type`.\n",
            "example": "text/plain"
        }
    },
    "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}/texts/{id}

Retrieve a single product text

Description

Returns one text entry. The example is a German blurb held as an HTML fragment and truncated here; a blurb may run to a thousand characters or more.

A text id that exists but belongs to a different product returns 403, not 404 — the record is real, it is simply not reachable through that parent. An id that exists nowhere returns 404.

Input parameters

Path parameters

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

Responses

{
    "_id": "66a7ef3c-03ab-40ed-abff-4bb22bfa702d",
    "_legacy_id": 4180232,
    "_version": "4.0",
    "_links": {
        "self": "https://api.openpublishing.com/resource/v4/products/e86581a9-e616-11ee-a221-00505699575c/texts/66a7ef3c-03ab-40ed-abff-4bb22bfa702d"
    },
    "type": "description",
    "type_onix": "03",
    "text": "<p>Als die Restauratorin Juli Sanwald einen unsignierten Wandteppich aus dem Nachlass ihrer Grossmutter uebernimmt, beginnt sie eine Spur zu verfolgen, die drei Generationen zurueckreicht - und die ihre Familie lieber vergessen haette. […]</p>",
    "mime_type": "text/html",
    "language": "ger",
    "channels": []
}
Schema of the response body
{
    "type": "object",
    "additionalProperties": false,
    "description": "One piece of descriptive copy attached to a product, in a single language, tagged by text type.",
    "properties": {
        "_id": {
            "type": "string",
            "description": "Unique identifier (UUID) for the product text.",
            "example": "3d5a9c14-7b02-4e88-9a61-0c7f2e4d8b35"
        },
        "_version": {
            "type": "string",
            "description": "API Version.",
            "example": "4.0"
        },
        "_legacy_id": {
            "type": "integer",
            "description": "Legacy integer identifier of this resource, kept so existing integrations can correlate their own records. This is the `_id` the same record has on the v3 endpoint.",
            "example": 4180231
        },
        "_links": {
            "type": "object"
        },
        "text": {
            "type": "string",
            "description": "The text itself. Its interpretation follows `mime_type`: with `text/plain` it is\nliteral characters and line breaks; with `text/html` it is a fragment of markup\n(typically `<p>` paragraphs) that a storefront can drop into a page.\n\nMust not be empty — a create or update that would leave `text` empty is rejected\nwith `400 Bad Request`.\n\nThere is no business length limit: an entry comfortably holds a full table of contents\nor a sample chapter, and the practical ceiling comes from the receiving channel rather\nthan from this API. Characters outside the Basic Multilingual Plane — emoji, and some\nrarely used CJK and historic scripts — are not supported.\n\n**This sub-resource is a standalone store.** It is independent of the legacy\ndescriptive fields carried directly on the v3 product record (`abstract`,\n`abstract_prefix`, `biographical_note`, `table_of_content`): a text written here does\nnot update those, and reading them does not surface entries created here. An entry is\nreachable through this sub-resource and its v3 equivalent, and nowhere else in the\nAPI.\n",
            "example": "Marit Sallenberg arbeitete als Lektorin und Kulturjournalistin, bevor sie ihren ersten Roman veroeffentlichte. Sie schreibt Gesellschaftsromane und lebt als freie Autorin in Rheinbergen."
        },
        "channels": {
            "type": "array",
            "description": "Distribution channels this text is intended for. An **empty list means the text\napplies to every channel** and is the normal case; it is populated only when a partner\nneeds different copy from everyone else — for example a shortened blurb for a\nretailer with a character limit, or a description that omits a competitor's name.\n\nValues are the platform's distribution-channel slugs. Those in common use are:\n\n- `google`\n- `amazon`\n- `kobo`\n- `spotify`\n- `libri`\n- `ciando`\n- `divibib`\n- `overdrive`\n- `scribd`\n- `bookwire`\n\nThe list is open-ended — a realm distributes through whichever partners it has\ncontracts with. **They are not validated against the channel list** — any string of lowercase letters and\nhyphens is accepted, so a typo silently produces a text that no channel will ever\nmatch. Note that channel slugs containing digits or underscores (`24symbols`,\n`manual_sale`, `zeitfracht_sa02e`) are valid channels elsewhere in the API but are\n**rejected** here, because this field allows only `[a-z-]`.\n\nThe list is normalised on write: values are lower-cased, de-duplicated and sorted\nalphabetically. Sending `[\"Google\", \"amazon\", \"google\"]` stores and returns\n`[\"amazon\", \"google\"]`. On update the list is replaced wholesale, never merged.\n\nThis endpoint applies no fallback logic of its own: it returns the entries exactly as\nstored, so selecting copy for one channel means preferring an entry that names that\nchannel and otherwise taking the unscoped one.\n\n**`channels` is the only scoping axis this resource has, and it is narrower than\nONIX.** An ONIX 3 `<TextContent>` is also scoped by content audience\n([Codelist 154](https://ns.editeur.org/onix/en/154) — booktrade, end-customers,\nlibrarians, press, …) and by text source and validity dates; none of those fields\nexist here. `channels` names distribution partners, not classes of reader.\n\n**Storefronts are a separate axis and are not handled here.** Per-shop copy — HTML\ntitle, meta description, meta keywords — belongs to the\n`/resource/v4/products/{product_id}/storefronts` sub-resource.\n",
            "items": {
                "type": "string"
            },
            "example": []
        },
        "language": {
            "type": "string",
            "description": "Language of `text`, as a three-letter ISO 639-2/B (bibliographic) code — `ger` for\nGerman, `eng` for English, `fre` for French. Note the B-codes: German is `ger`, not\n`deu`. Case is normalised to lower case on write; an unknown code is rejected with\n`400 Bad Request`.\n\n`null` when the language is unknown or not meaningful. A product carrying the same\n`type` in several languages holds one entry per language — nothing prevents\nduplicates, so a consumer picking \"the description\" should filter by the language it\nwants and fall back to the product's own `language`.\n\nNote that a language once set cannot be cleared: sending `\"language\": null` is\nrejected with `400 Bad Request`.\n",
            "nullable": true,
            "example": "ger"
        },
        "type": {
            "type": "string",
            "description": "What kind of text this is. **Not a closed enumeration** — any non-empty string of\nlowercase letters and hyphens (`[a-z-]`, up to 255 characters) is accepted. Digits,\nunderscores, spaces and upper case are rejected with `400 Bad Request`, as is an\nempty value.\n\n37 slugs are recognised as equivalents of [ONIX Codelist\n153](https://ns.editeur.org/onix/en/153) values; for those the server derives\n`type_onix`. Anything else is stored as given with `type_onix: null`, which is the\nsupported way to carry copy that ONIX has no code for.\n\nA few of the distinctions in the list are easy to get wrong:\n\n- `description` (03) is the main long-form selling copy;\n  `short-description-annotation` (02) is the abridged version for listings and feeds\n  with a length budget. They are separate entries, not two renderings of one.\n- `biographical-note` (12) is about the author, not about the book, and takes one entry\n  per contributor where there are several.\n- `review-quote` (06) is a quotation from a published review of *this* edition;\n  `review-quote-previous-edition` (07) and `review-quote-previous-work` (08) exist for\n  quotes that refer to something else.\n- `endorsement` (09) is a commendation solicited by the publisher, as distinct from a\n  review published independently.\n- `abstract` (30) is the scholarly abstract, not a marketing blurb.\n- `table-of-contents` (04) is conventionally `text/plain` with one heading per line.\n\nThe complete set of recognised slugs, with the [Codelist\n153](https://ns.editeur.org/onix/en/153) code each one derives:\n\n| `type` | `type_onix` | Meaning |\n|---|---|---|\n| `sender-defined-text` | `01` | Sender-defined text |\n| `short-description-annotation` | `02` | Short description / annotation — the abridged blurb for listings and feeds |\n| `description` | `03` | Description — the main long-form selling copy |\n| `table-of-contents` | `04` | Table of contents |\n| `primary-cover-copy` | `05` | Primary cover copy — text printed on the cover or jacket |\n| `review-quote` | `06` | Review quote |\n| `review-quote-previous-edition` | `07` | Review quote, previous edition |\n| `review-quote-previous-work` | `08` | Review quote, previous work |\n| `endorsement` | `09` | Endorsement — solicited by the publisher, unlike a review |\n| `promotional-headline` | `10` | Promotional headline |\n| `feature` | `11` | Feature — a single selling point |\n| `biographical-note` | `12` | Biographical note about a contributor |\n| `publishers-notive` | `13` | Publisher's notice *(slug misspelled — send it exactly as shown)* |\n| `excerpt` | `14` | Excerpt |\n| `index` | `15` | Index |\n| `short-description-annotiation-for-collation` | `16` | Short description for the collection *(slug misspelled — send it exactly as shown)* |\n| `description-for-collection` | `17` | Description for the collection (series) |\n| `new-feature` | `18` | New feature — what changed in this edition |\n| `version-history` | `19` | Version history |\n| `open-access-statement` | `20` | Open access statement |\n| `digital-exclusivity-statement` | `21` | Digital exclusivity statement |\n| `official-recommendation` | `22` | Official recommendation |\n| `jbpa-description` | `23` | JBPA description |\n| `schema-org-snippet` | `24` | schema.org snippet |\n| `errata` | `25` | Errata |\n| `intriduction` | `26` | Introduction *(slug misspelled — send it exactly as shown)* |\n| `secondary-cover-copy` | `27` | Secondary cover copy |\n| `full-cast-and-credit-list` | `28` | Full cast and credit list |\n| `bibliography` | `29` | Bibliography |\n| `abstract` | `30` | Abstract — the scholarly summary, not a marketing blurb |\n| `rules-or-instructions` | `31` | Rules or instructions |\n| `list-of-contents` | `32` | List of contents — components of a multi-item product |\n| `short-description-annotation-for-imprint` | `33` | Short description for the imprint |\n| `description-for-imprint` | `34` | Description for the imprint |\n| `short-description-annotation-for-publisher` | `35` | Short description for the publisher |\n| `description-for-publisher` | `36` | Description for the publisher |\n| `cover-line` | `37` | Cover line |\n\nThree of those slugs — `publishers-notive`, `short-description-annotiation-for-collation`\nand `intriduction` — are misspelled, and the table lists them as they must be sent to\nobtain a code. The correctly spelled forms `publishers-notice`,\n`short-description-annotation-for-collection` and `introduction` are accepted as well,\nbut they are not recognised and yield `type_onix: null`.\n\n**This is the only field the collection endpoint can filter on**, with the operators\ndescribed under [Resource Queries](/resource_queries/). Any other field name is\nrejected with `400 Bad Request`, as is an unknown operator suffix, so `language` and\n`channels` have to be narrowed down client-side. Results cannot be sorted: a `sort`\nparameter is accepted and applied to nothing, which leaves the order of results\nunspecified. Pagination is standard, with a default page size of 100.\n",
            "example": "biographical-note",
            "x-enum-descriptions": {
                "sender-defined-text": "ONIX 153 code 01 — Sender-defined text.",
                "short-description-annotation": "ONIX 153 code 02 — Short description/annotation; the abridged blurb for listings and feeds.",
                "description": "ONIX 153 code 03 — Description; the main long-form selling copy.",
                "table-of-contents": "ONIX 153 code 04 — Table of contents.",
                "primary-cover-copy": "ONIX 153 code 05 — Primary cover copy; the text printed on the cover or jacket.",
                "review-quote": "ONIX 153 code 06 — Review quote for this edition.",
                "review-quote-previous-edition": "ONIX 153 code 07 — Review quote taken from a review of a previous edition.",
                "review-quote-previous-work": "ONIX 153 code 08 — Review quote taken from a review of a previous work by the same author.",
                "endorsement": "ONIX 153 code 09 — Endorsement; a commendation solicited by the publisher.",
                "promotional-headline": "ONIX 153 code 10 — Promotional headline; the one-line hook.",
                "feature": "ONIX 153 code 11 — Feature; a single selling point, usually one of a set of bullets.",
                "biographical-note": "ONIX 153 code 12 — Biographical note about a contributor.",
                "publishers-notive": "ONIX 153 code 13 — Publisher's notice. The slug is misspelled; send it exactly as shown.",
                "excerpt": "ONIX 153 code 14 — Excerpt; a sample passage from the work.",
                "index": "ONIX 153 code 15 — Index.",
                "short-description-annotiation-for-collation": "ONIX 153 code 16 — Short description/annotation for the collection (series) this product belongs to. The slug is misspelled; send it exactly as shown.",
                "description-for-collection": "ONIX 153 code 17 — Description of the collection (series) this product belongs to.",
                "new-feature": "ONIX 153 code 18 — New feature; what changed in this edition.",
                "version-history": "ONIX 153 code 19 — Version history.",
                "open-access-statement": "ONIX 153 code 20 — Open access statement; the licence and access terms.",
                "digital-exclusivity-statement": "ONIX 153 code 21 — Digital exclusivity statement.",
                "official-recommendation": "ONIX 153 code 22 — Official recommendation, e.g. by an educational authority.",
                "jbpa-description": "ONIX 153 code 23 — JBPA description (Japanese Book Publishers Association).",
                "schema-org-snippet": "ONIX 153 code 24 — schema.org snippet for search-engine markup.",
                "errata": "ONIX 153 code 25 — Errata.",
                "intriduction": "ONIX 153 code 26 — Introduction. The slug is misspelled; send it exactly as shown.",
                "secondary-cover-copy": "ONIX 153 code 27 — Secondary cover copy, e.g. back cover as opposed to front.",
                "full-cast-and-credit-list": "ONIX 153 code 28 — Full cast and credit list; used for audiobooks and dramatisations.",
                "bibliography": "ONIX 153 code 29 — Bibliography.",
                "abstract": "ONIX 153 code 30 — Abstract; the scholarly summary, distinct from a marketing blurb.",
                "rules-or-instructions": "ONIX 153 code 31 — Rules or instructions, e.g. for a game or kit.",
                "list-of-contents": "ONIX 153 code 32 — List of contents; the components of a multi-item product.",
                "short-description-annotation-for-imprint": "ONIX 153 code 33 — Short description/annotation for the imprint.",
                "description-for-imprint": "ONIX 153 code 34 — Description of the imprint.",
                "short-description-annotation-for-publisher": "ONIX 153 code 35 — Short description/annotation for the publisher.",
                "description-for-publisher": "ONIX 153 code 36 — Description of the publisher.",
                "cover-line": "ONIX 153 code 37 — Cover line; a strapline carried on the cover."
            }
        },
        "type_onix": {
            "type": "string",
            "description": "The [ONIX Codelist 153](https://ns.editeur.org/onix/en/153) text type code\ncorresponding to `type`, as a two-digit string (`\"03\"` description, `\"12\"`\nbiographical note, …). Present so that ONIX consumers do not have to reimplement the\nslug mapping.\n\n**Read-only in effect.** The field is accepted in a request body but the value is\ndiscarded: the server recomputes it from `type` on every write. It is `null` whenever\n`type` is not one of the 37 recognised slugs. To change it, change `type`.\n\nNote that this is Codelist **153** (ONIX 3 `<TextType>`), not the ONIX 2.1 Codelist 33\n(`<OtherText>` type) that earlier revisions of this schema named. The two lists assign\ndifferent codes to the same concepts — a biographical note is `12` in 153 and `13` in\n33 — so a consumer that reads these codes against Codelist 33 will mislabel them.\n",
            "nullable": true,
            "example": "12"
        },
        "mime_type": {
            "type": "string",
            "description": "How `text` is encoded. In practice two values are used:\n\n- `text/plain` — literal text; line breaks are significant and a consumer must escape\n  it before putting it into a web page. The default when the field is omitted on\n  create.\n- `text/html` — an HTML fragment, typically wrapped in `<p>` elements. The API stores\n  it as sent and does not sanitise it, so a storefront rendering the value unescaped\n  is trusting whoever wrote it.\n\nValidation is **syntactic only**: any well-formed `type/subtype[; parameters]` string\nup to 255 characters is accepted, so a misspelling such as `text/htlm` is stored\nwithout complaint and is only noticed when the value is used. A malformed value is\nrejected with `400 Bad Request`, as is an empty one.\n\nBook-trade descriptions are usually HTML, while biographies and tables of contents are\nusually plain text, but nothing in the API enforces that pairing — `mime_type` is\nrecorded independently of `type`.\n",
            "example": "text/plain"
        }
    },
    "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."
                    }
                }
            }
        }
    }
}

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

Update product text

Description

Updates one text entry. Despite being a PUT this is a partial update: only the keys present in the body are applied, and every omitted key keeps its current value, so sending {} changes nothing, and a field cannot be cleared by leaving it out.

Sending an explicit null clears only type_onix — and that has no effect, since the value is recomputed from type regardless. text, type, mime_type and language reject null with 400 Bad Request.

channels is replaced wholesale, not merged, so the request must carry the complete list.

The example replaces the body of an existing table of contents — that of a scholarly title, truncated here — leaving type, mime_type, language and channels untouched. The response returns the complete merged record.

Input parameters

Path parameters

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

Request body

{
    "text": "1. Einleitung 2. Forschungsstand 3. Methodisches Vorgehen 3.1 Korpusauswahl 3.2 Auswertungsverfahren 4. Ergebnisse […] 7. Fazit"
}
Schema of the request body
{
    "type": "object",
    "additionalProperties": false,
    "description": "One piece of descriptive copy attached to a product, in a single language, tagged by text type.",
    "properties": {
        "_id": {
            "type": "string",
            "description": "Unique identifier (UUID) for the product text.",
            "example": "3d5a9c14-7b02-4e88-9a61-0c7f2e4d8b35"
        },
        "_version": {
            "type": "string",
            "description": "API Version.",
            "example": "4.0"
        },
        "_legacy_id": {
            "type": "integer",
            "description": "Legacy integer identifier of this resource, kept so existing integrations can correlate their own records. This is the `_id` the same record has on the v3 endpoint.",
            "example": 4180231
        },
        "_links": {
            "type": "object"
        },
        "text": {
            "type": "string",
            "description": "The text itself. Its interpretation follows `mime_type`: with `text/plain` it is\nliteral characters and line breaks; with `text/html` it is a fragment of markup\n(typically `<p>` paragraphs) that a storefront can drop into a page.\n\nMust not be empty — a create or update that would leave `text` empty is rejected\nwith `400 Bad Request`.\n\nThere is no business length limit: an entry comfortably holds a full table of contents\nor a sample chapter, and the practical ceiling comes from the receiving channel rather\nthan from this API. Characters outside the Basic Multilingual Plane — emoji, and some\nrarely used CJK and historic scripts — are not supported.\n\n**This sub-resource is a standalone store.** It is independent of the legacy\ndescriptive fields carried directly on the v3 product record (`abstract`,\n`abstract_prefix`, `biographical_note`, `table_of_content`): a text written here does\nnot update those, and reading them does not surface entries created here. An entry is\nreachable through this sub-resource and its v3 equivalent, and nowhere else in the\nAPI.\n",
            "example": "Marit Sallenberg arbeitete als Lektorin und Kulturjournalistin, bevor sie ihren ersten Roman veroeffentlichte. Sie schreibt Gesellschaftsromane und lebt als freie Autorin in Rheinbergen."
        },
        "channels": {
            "type": "array",
            "description": "Distribution channels this text is intended for. An **empty list means the text\napplies to every channel** and is the normal case; it is populated only when a partner\nneeds different copy from everyone else — for example a shortened blurb for a\nretailer with a character limit, or a description that omits a competitor's name.\n\nValues are the platform's distribution-channel slugs. Those in common use are:\n\n- `google`\n- `amazon`\n- `kobo`\n- `spotify`\n- `libri`\n- `ciando`\n- `divibib`\n- `overdrive`\n- `scribd`\n- `bookwire`\n\nThe list is open-ended — a realm distributes through whichever partners it has\ncontracts with. **They are not validated against the channel list** — any string of lowercase letters and\nhyphens is accepted, so a typo silently produces a text that no channel will ever\nmatch. Note that channel slugs containing digits or underscores (`24symbols`,\n`manual_sale`, `zeitfracht_sa02e`) are valid channels elsewhere in the API but are\n**rejected** here, because this field allows only `[a-z-]`.\n\nThe list is normalised on write: values are lower-cased, de-duplicated and sorted\nalphabetically. Sending `[\"Google\", \"amazon\", \"google\"]` stores and returns\n`[\"amazon\", \"google\"]`. On update the list is replaced wholesale, never merged.\n\nThis endpoint applies no fallback logic of its own: it returns the entries exactly as\nstored, so selecting copy for one channel means preferring an entry that names that\nchannel and otherwise taking the unscoped one.\n\n**`channels` is the only scoping axis this resource has, and it is narrower than\nONIX.** An ONIX 3 `<TextContent>` is also scoped by content audience\n([Codelist 154](https://ns.editeur.org/onix/en/154) — booktrade, end-customers,\nlibrarians, press, …) and by text source and validity dates; none of those fields\nexist here. `channels` names distribution partners, not classes of reader.\n\n**Storefronts are a separate axis and are not handled here.** Per-shop copy — HTML\ntitle, meta description, meta keywords — belongs to the\n`/resource/v4/products/{product_id}/storefronts` sub-resource.\n",
            "items": {
                "type": "string"
            },
            "example": []
        },
        "language": {
            "type": "string",
            "description": "Language of `text`, as a three-letter ISO 639-2/B (bibliographic) code — `ger` for\nGerman, `eng` for English, `fre` for French. Note the B-codes: German is `ger`, not\n`deu`. Case is normalised to lower case on write; an unknown code is rejected with\n`400 Bad Request`.\n\n`null` when the language is unknown or not meaningful. A product carrying the same\n`type` in several languages holds one entry per language — nothing prevents\nduplicates, so a consumer picking \"the description\" should filter by the language it\nwants and fall back to the product's own `language`.\n\nNote that a language once set cannot be cleared: sending `\"language\": null` is\nrejected with `400 Bad Request`.\n",
            "nullable": true,
            "example": "ger"
        },
        "type": {
            "type": "string",
            "description": "What kind of text this is. **Not a closed enumeration** — any non-empty string of\nlowercase letters and hyphens (`[a-z-]`, up to 255 characters) is accepted. Digits,\nunderscores, spaces and upper case are rejected with `400 Bad Request`, as is an\nempty value.\n\n37 slugs are recognised as equivalents of [ONIX Codelist\n153](https://ns.editeur.org/onix/en/153) values; for those the server derives\n`type_onix`. Anything else is stored as given with `type_onix: null`, which is the\nsupported way to carry copy that ONIX has no code for.\n\nA few of the distinctions in the list are easy to get wrong:\n\n- `description` (03) is the main long-form selling copy;\n  `short-description-annotation` (02) is the abridged version for listings and feeds\n  with a length budget. They are separate entries, not two renderings of one.\n- `biographical-note` (12) is about the author, not about the book, and takes one entry\n  per contributor where there are several.\n- `review-quote` (06) is a quotation from a published review of *this* edition;\n  `review-quote-previous-edition` (07) and `review-quote-previous-work` (08) exist for\n  quotes that refer to something else.\n- `endorsement` (09) is a commendation solicited by the publisher, as distinct from a\n  review published independently.\n- `abstract` (30) is the scholarly abstract, not a marketing blurb.\n- `table-of-contents` (04) is conventionally `text/plain` with one heading per line.\n\nThe complete set of recognised slugs, with the [Codelist\n153](https://ns.editeur.org/onix/en/153) code each one derives:\n\n| `type` | `type_onix` | Meaning |\n|---|---|---|\n| `sender-defined-text` | `01` | Sender-defined text |\n| `short-description-annotation` | `02` | Short description / annotation — the abridged blurb for listings and feeds |\n| `description` | `03` | Description — the main long-form selling copy |\n| `table-of-contents` | `04` | Table of contents |\n| `primary-cover-copy` | `05` | Primary cover copy — text printed on the cover or jacket |\n| `review-quote` | `06` | Review quote |\n| `review-quote-previous-edition` | `07` | Review quote, previous edition |\n| `review-quote-previous-work` | `08` | Review quote, previous work |\n| `endorsement` | `09` | Endorsement — solicited by the publisher, unlike a review |\n| `promotional-headline` | `10` | Promotional headline |\n| `feature` | `11` | Feature — a single selling point |\n| `biographical-note` | `12` | Biographical note about a contributor |\n| `publishers-notive` | `13` | Publisher's notice *(slug misspelled — send it exactly as shown)* |\n| `excerpt` | `14` | Excerpt |\n| `index` | `15` | Index |\n| `short-description-annotiation-for-collation` | `16` | Short description for the collection *(slug misspelled — send it exactly as shown)* |\n| `description-for-collection` | `17` | Description for the collection (series) |\n| `new-feature` | `18` | New feature — what changed in this edition |\n| `version-history` | `19` | Version history |\n| `open-access-statement` | `20` | Open access statement |\n| `digital-exclusivity-statement` | `21` | Digital exclusivity statement |\n| `official-recommendation` | `22` | Official recommendation |\n| `jbpa-description` | `23` | JBPA description |\n| `schema-org-snippet` | `24` | schema.org snippet |\n| `errata` | `25` | Errata |\n| `intriduction` | `26` | Introduction *(slug misspelled — send it exactly as shown)* |\n| `secondary-cover-copy` | `27` | Secondary cover copy |\n| `full-cast-and-credit-list` | `28` | Full cast and credit list |\n| `bibliography` | `29` | Bibliography |\n| `abstract` | `30` | Abstract — the scholarly summary, not a marketing blurb |\n| `rules-or-instructions` | `31` | Rules or instructions |\n| `list-of-contents` | `32` | List of contents — components of a multi-item product |\n| `short-description-annotation-for-imprint` | `33` | Short description for the imprint |\n| `description-for-imprint` | `34` | Description for the imprint |\n| `short-description-annotation-for-publisher` | `35` | Short description for the publisher |\n| `description-for-publisher` | `36` | Description for the publisher |\n| `cover-line` | `37` | Cover line |\n\nThree of those slugs — `publishers-notive`, `short-description-annotiation-for-collation`\nand `intriduction` — are misspelled, and the table lists them as they must be sent to\nobtain a code. The correctly spelled forms `publishers-notice`,\n`short-description-annotation-for-collection` and `introduction` are accepted as well,\nbut they are not recognised and yield `type_onix: null`.\n\n**This is the only field the collection endpoint can filter on**, with the operators\ndescribed under [Resource Queries](/resource_queries/). Any other field name is\nrejected with `400 Bad Request`, as is an unknown operator suffix, so `language` and\n`channels` have to be narrowed down client-side. Results cannot be sorted: a `sort`\nparameter is accepted and applied to nothing, which leaves the order of results\nunspecified. Pagination is standard, with a default page size of 100.\n",
            "example": "biographical-note",
            "x-enum-descriptions": {
                "sender-defined-text": "ONIX 153 code 01 — Sender-defined text.",
                "short-description-annotation": "ONIX 153 code 02 — Short description/annotation; the abridged blurb for listings and feeds.",
                "description": "ONIX 153 code 03 — Description; the main long-form selling copy.",
                "table-of-contents": "ONIX 153 code 04 — Table of contents.",
                "primary-cover-copy": "ONIX 153 code 05 — Primary cover copy; the text printed on the cover or jacket.",
                "review-quote": "ONIX 153 code 06 — Review quote for this edition.",
                "review-quote-previous-edition": "ONIX 153 code 07 — Review quote taken from a review of a previous edition.",
                "review-quote-previous-work": "ONIX 153 code 08 — Review quote taken from a review of a previous work by the same author.",
                "endorsement": "ONIX 153 code 09 — Endorsement; a commendation solicited by the publisher.",
                "promotional-headline": "ONIX 153 code 10 — Promotional headline; the one-line hook.",
                "feature": "ONIX 153 code 11 — Feature; a single selling point, usually one of a set of bullets.",
                "biographical-note": "ONIX 153 code 12 — Biographical note about a contributor.",
                "publishers-notive": "ONIX 153 code 13 — Publisher's notice. The slug is misspelled; send it exactly as shown.",
                "excerpt": "ONIX 153 code 14 — Excerpt; a sample passage from the work.",
                "index": "ONIX 153 code 15 — Index.",
                "short-description-annotiation-for-collation": "ONIX 153 code 16 — Short description/annotation for the collection (series) this product belongs to. The slug is misspelled; send it exactly as shown.",
                "description-for-collection": "ONIX 153 code 17 — Description of the collection (series) this product belongs to.",
                "new-feature": "ONIX 153 code 18 — New feature; what changed in this edition.",
                "version-history": "ONIX 153 code 19 — Version history.",
                "open-access-statement": "ONIX 153 code 20 — Open access statement; the licence and access terms.",
                "digital-exclusivity-statement": "ONIX 153 code 21 — Digital exclusivity statement.",
                "official-recommendation": "ONIX 153 code 22 — Official recommendation, e.g. by an educational authority.",
                "jbpa-description": "ONIX 153 code 23 — JBPA description (Japanese Book Publishers Association).",
                "schema-org-snippet": "ONIX 153 code 24 — schema.org snippet for search-engine markup.",
                "errata": "ONIX 153 code 25 — Errata.",
                "intriduction": "ONIX 153 code 26 — Introduction. The slug is misspelled; send it exactly as shown.",
                "secondary-cover-copy": "ONIX 153 code 27 — Secondary cover copy, e.g. back cover as opposed to front.",
                "full-cast-and-credit-list": "ONIX 153 code 28 — Full cast and credit list; used for audiobooks and dramatisations.",
                "bibliography": "ONIX 153 code 29 — Bibliography.",
                "abstract": "ONIX 153 code 30 — Abstract; the scholarly summary, distinct from a marketing blurb.",
                "rules-or-instructions": "ONIX 153 code 31 — Rules or instructions, e.g. for a game or kit.",
                "list-of-contents": "ONIX 153 code 32 — List of contents; the components of a multi-item product.",
                "short-description-annotation-for-imprint": "ONIX 153 code 33 — Short description/annotation for the imprint.",
                "description-for-imprint": "ONIX 153 code 34 — Description of the imprint.",
                "short-description-annotation-for-publisher": "ONIX 153 code 35 — Short description/annotation for the publisher.",
                "description-for-publisher": "ONIX 153 code 36 — Description of the publisher.",
                "cover-line": "ONIX 153 code 37 — Cover line; a strapline carried on the cover."
            }
        },
        "type_onix": {
            "type": "string",
            "description": "The [ONIX Codelist 153](https://ns.editeur.org/onix/en/153) text type code\ncorresponding to `type`, as a two-digit string (`\"03\"` description, `\"12\"`\nbiographical note, …). Present so that ONIX consumers do not have to reimplement the\nslug mapping.\n\n**Read-only in effect.** The field is accepted in a request body but the value is\ndiscarded: the server recomputes it from `type` on every write. It is `null` whenever\n`type` is not one of the 37 recognised slugs. To change it, change `type`.\n\nNote that this is Codelist **153** (ONIX 3 `<TextType>`), not the ONIX 2.1 Codelist 33\n(`<OtherText>` type) that earlier revisions of this schema named. The two lists assign\ndifferent codes to the same concepts — a biographical note is `12` in 153 and `13` in\n33 — so a consumer that reads these codes against Codelist 33 will mislabel them.\n",
            "nullable": true,
            "example": "12"
        },
        "mime_type": {
            "type": "string",
            "description": "How `text` is encoded. In practice two values are used:\n\n- `text/plain` — literal text; line breaks are significant and a consumer must escape\n  it before putting it into a web page. The default when the field is omitted on\n  create.\n- `text/html` — an HTML fragment, typically wrapped in `<p>` elements. The API stores\n  it as sent and does not sanitise it, so a storefront rendering the value unescaped\n  is trusting whoever wrote it.\n\nValidation is **syntactic only**: any well-formed `type/subtype[; parameters]` string\nup to 255 characters is accepted, so a misspelling such as `text/htlm` is stored\nwithout complaint and is only noticed when the value is used. A malformed value is\nrejected with `400 Bad Request`, as is an empty one.\n\nBook-trade descriptions are usually HTML, while biographies and tables of contents are\nusually plain text, but nothing in the API enforces that pairing — `mime_type` is\nrecorded independently of `type`.\n",
            "example": "text/plain"
        }
    },
    "required": []
}

Responses

{
    "_id": "e29bb6c0-dd03-47df-87bd-4b3f3881878c",
    "_legacy_id": 4180233,
    "_version": "4.0",
    "_links": {
        "self": "https://api.openpublishing.com/resource/v4/products/a65e2e05-e616-11ee-a221-00505699575c/texts/e29bb6c0-dd03-47df-87bd-4b3f3881878c"
    },
    "type": "table-of-contents",
    "type_onix": "04",
    "text": "1. Einleitung 2. Forschungsstand 3. Methodisches Vorgehen 3.1 Korpusauswahl 3.2 Auswertungsverfahren 4. Ergebnisse […] 7. Fazit",
    "mime_type": "text/plain",
    "language": "ger",
    "channels": []
}
Schema of the response body
{
    "type": "object",
    "additionalProperties": false,
    "description": "One piece of descriptive copy attached to a product, in a single language, tagged by text type.",
    "properties": {
        "_id": {
            "type": "string",
            "description": "Unique identifier (UUID) for the product text.",
            "example": "3d5a9c14-7b02-4e88-9a61-0c7f2e4d8b35"
        },
        "_version": {
            "type": "string",
            "description": "API Version.",
            "example": "4.0"
        },
        "_legacy_id": {
            "type": "integer",
            "description": "Legacy integer identifier of this resource, kept so existing integrations can correlate their own records. This is the `_id` the same record has on the v3 endpoint.",
            "example": 4180231
        },
        "_links": {
            "type": "object"
        },
        "text": {
            "type": "string",
            "description": "The text itself. Its interpretation follows `mime_type`: with `text/plain` it is\nliteral characters and line breaks; with `text/html` it is a fragment of markup\n(typically `<p>` paragraphs) that a storefront can drop into a page.\n\nMust not be empty — a create or update that would leave `text` empty is rejected\nwith `400 Bad Request`.\n\nThere is no business length limit: an entry comfortably holds a full table of contents\nor a sample chapter, and the practical ceiling comes from the receiving channel rather\nthan from this API. Characters outside the Basic Multilingual Plane — emoji, and some\nrarely used CJK and historic scripts — are not supported.\n\n**This sub-resource is a standalone store.** It is independent of the legacy\ndescriptive fields carried directly on the v3 product record (`abstract`,\n`abstract_prefix`, `biographical_note`, `table_of_content`): a text written here does\nnot update those, and reading them does not surface entries created here. An entry is\nreachable through this sub-resource and its v3 equivalent, and nowhere else in the\nAPI.\n",
            "example": "Marit Sallenberg arbeitete als Lektorin und Kulturjournalistin, bevor sie ihren ersten Roman veroeffentlichte. Sie schreibt Gesellschaftsromane und lebt als freie Autorin in Rheinbergen."
        },
        "channels": {
            "type": "array",
            "description": "Distribution channels this text is intended for. An **empty list means the text\napplies to every channel** and is the normal case; it is populated only when a partner\nneeds different copy from everyone else — for example a shortened blurb for a\nretailer with a character limit, or a description that omits a competitor's name.\n\nValues are the platform's distribution-channel slugs. Those in common use are:\n\n- `google`\n- `amazon`\n- `kobo`\n- `spotify`\n- `libri`\n- `ciando`\n- `divibib`\n- `overdrive`\n- `scribd`\n- `bookwire`\n\nThe list is open-ended — a realm distributes through whichever partners it has\ncontracts with. **They are not validated against the channel list** — any string of lowercase letters and\nhyphens is accepted, so a typo silently produces a text that no channel will ever\nmatch. Note that channel slugs containing digits or underscores (`24symbols`,\n`manual_sale`, `zeitfracht_sa02e`) are valid channels elsewhere in the API but are\n**rejected** here, because this field allows only `[a-z-]`.\n\nThe list is normalised on write: values are lower-cased, de-duplicated and sorted\nalphabetically. Sending `[\"Google\", \"amazon\", \"google\"]` stores and returns\n`[\"amazon\", \"google\"]`. On update the list is replaced wholesale, never merged.\n\nThis endpoint applies no fallback logic of its own: it returns the entries exactly as\nstored, so selecting copy for one channel means preferring an entry that names that\nchannel and otherwise taking the unscoped one.\n\n**`channels` is the only scoping axis this resource has, and it is narrower than\nONIX.** An ONIX 3 `<TextContent>` is also scoped by content audience\n([Codelist 154](https://ns.editeur.org/onix/en/154) — booktrade, end-customers,\nlibrarians, press, …) and by text source and validity dates; none of those fields\nexist here. `channels` names distribution partners, not classes of reader.\n\n**Storefronts are a separate axis and are not handled here.** Per-shop copy — HTML\ntitle, meta description, meta keywords — belongs to the\n`/resource/v4/products/{product_id}/storefronts` sub-resource.\n",
            "items": {
                "type": "string"
            },
            "example": []
        },
        "language": {
            "type": "string",
            "description": "Language of `text`, as a three-letter ISO 639-2/B (bibliographic) code — `ger` for\nGerman, `eng` for English, `fre` for French. Note the B-codes: German is `ger`, not\n`deu`. Case is normalised to lower case on write; an unknown code is rejected with\n`400 Bad Request`.\n\n`null` when the language is unknown or not meaningful. A product carrying the same\n`type` in several languages holds one entry per language — nothing prevents\nduplicates, so a consumer picking \"the description\" should filter by the language it\nwants and fall back to the product's own `language`.\n\nNote that a language once set cannot be cleared: sending `\"language\": null` is\nrejected with `400 Bad Request`.\n",
            "nullable": true,
            "example": "ger"
        },
        "type": {
            "type": "string",
            "description": "What kind of text this is. **Not a closed enumeration** — any non-empty string of\nlowercase letters and hyphens (`[a-z-]`, up to 255 characters) is accepted. Digits,\nunderscores, spaces and upper case are rejected with `400 Bad Request`, as is an\nempty value.\n\n37 slugs are recognised as equivalents of [ONIX Codelist\n153](https://ns.editeur.org/onix/en/153) values; for those the server derives\n`type_onix`. Anything else is stored as given with `type_onix: null`, which is the\nsupported way to carry copy that ONIX has no code for.\n\nA few of the distinctions in the list are easy to get wrong:\n\n- `description` (03) is the main long-form selling copy;\n  `short-description-annotation` (02) is the abridged version for listings and feeds\n  with a length budget. They are separate entries, not two renderings of one.\n- `biographical-note` (12) is about the author, not about the book, and takes one entry\n  per contributor where there are several.\n- `review-quote` (06) is a quotation from a published review of *this* edition;\n  `review-quote-previous-edition` (07) and `review-quote-previous-work` (08) exist for\n  quotes that refer to something else.\n- `endorsement` (09) is a commendation solicited by the publisher, as distinct from a\n  review published independently.\n- `abstract` (30) is the scholarly abstract, not a marketing blurb.\n- `table-of-contents` (04) is conventionally `text/plain` with one heading per line.\n\nThe complete set of recognised slugs, with the [Codelist\n153](https://ns.editeur.org/onix/en/153) code each one derives:\n\n| `type` | `type_onix` | Meaning |\n|---|---|---|\n| `sender-defined-text` | `01` | Sender-defined text |\n| `short-description-annotation` | `02` | Short description / annotation — the abridged blurb for listings and feeds |\n| `description` | `03` | Description — the main long-form selling copy |\n| `table-of-contents` | `04` | Table of contents |\n| `primary-cover-copy` | `05` | Primary cover copy — text printed on the cover or jacket |\n| `review-quote` | `06` | Review quote |\n| `review-quote-previous-edition` | `07` | Review quote, previous edition |\n| `review-quote-previous-work` | `08` | Review quote, previous work |\n| `endorsement` | `09` | Endorsement — solicited by the publisher, unlike a review |\n| `promotional-headline` | `10` | Promotional headline |\n| `feature` | `11` | Feature — a single selling point |\n| `biographical-note` | `12` | Biographical note about a contributor |\n| `publishers-notive` | `13` | Publisher's notice *(slug misspelled — send it exactly as shown)* |\n| `excerpt` | `14` | Excerpt |\n| `index` | `15` | Index |\n| `short-description-annotiation-for-collation` | `16` | Short description for the collection *(slug misspelled — send it exactly as shown)* |\n| `description-for-collection` | `17` | Description for the collection (series) |\n| `new-feature` | `18` | New feature — what changed in this edition |\n| `version-history` | `19` | Version history |\n| `open-access-statement` | `20` | Open access statement |\n| `digital-exclusivity-statement` | `21` | Digital exclusivity statement |\n| `official-recommendation` | `22` | Official recommendation |\n| `jbpa-description` | `23` | JBPA description |\n| `schema-org-snippet` | `24` | schema.org snippet |\n| `errata` | `25` | Errata |\n| `intriduction` | `26` | Introduction *(slug misspelled — send it exactly as shown)* |\n| `secondary-cover-copy` | `27` | Secondary cover copy |\n| `full-cast-and-credit-list` | `28` | Full cast and credit list |\n| `bibliography` | `29` | Bibliography |\n| `abstract` | `30` | Abstract — the scholarly summary, not a marketing blurb |\n| `rules-or-instructions` | `31` | Rules or instructions |\n| `list-of-contents` | `32` | List of contents — components of a multi-item product |\n| `short-description-annotation-for-imprint` | `33` | Short description for the imprint |\n| `description-for-imprint` | `34` | Description for the imprint |\n| `short-description-annotation-for-publisher` | `35` | Short description for the publisher |\n| `description-for-publisher` | `36` | Description for the publisher |\n| `cover-line` | `37` | Cover line |\n\nThree of those slugs — `publishers-notive`, `short-description-annotiation-for-collation`\nand `intriduction` — are misspelled, and the table lists them as they must be sent to\nobtain a code. The correctly spelled forms `publishers-notice`,\n`short-description-annotation-for-collection` and `introduction` are accepted as well,\nbut they are not recognised and yield `type_onix: null`.\n\n**This is the only field the collection endpoint can filter on**, with the operators\ndescribed under [Resource Queries](/resource_queries/). Any other field name is\nrejected with `400 Bad Request`, as is an unknown operator suffix, so `language` and\n`channels` have to be narrowed down client-side. Results cannot be sorted: a `sort`\nparameter is accepted and applied to nothing, which leaves the order of results\nunspecified. Pagination is standard, with a default page size of 100.\n",
            "example": "biographical-note",
            "x-enum-descriptions": {
                "sender-defined-text": "ONIX 153 code 01 — Sender-defined text.",
                "short-description-annotation": "ONIX 153 code 02 — Short description/annotation; the abridged blurb for listings and feeds.",
                "description": "ONIX 153 code 03 — Description; the main long-form selling copy.",
                "table-of-contents": "ONIX 153 code 04 — Table of contents.",
                "primary-cover-copy": "ONIX 153 code 05 — Primary cover copy; the text printed on the cover or jacket.",
                "review-quote": "ONIX 153 code 06 — Review quote for this edition.",
                "review-quote-previous-edition": "ONIX 153 code 07 — Review quote taken from a review of a previous edition.",
                "review-quote-previous-work": "ONIX 153 code 08 — Review quote taken from a review of a previous work by the same author.",
                "endorsement": "ONIX 153 code 09 — Endorsement; a commendation solicited by the publisher.",
                "promotional-headline": "ONIX 153 code 10 — Promotional headline; the one-line hook.",
                "feature": "ONIX 153 code 11 — Feature; a single selling point, usually one of a set of bullets.",
                "biographical-note": "ONIX 153 code 12 — Biographical note about a contributor.",
                "publishers-notive": "ONIX 153 code 13 — Publisher's notice. The slug is misspelled; send it exactly as shown.",
                "excerpt": "ONIX 153 code 14 — Excerpt; a sample passage from the work.",
                "index": "ONIX 153 code 15 — Index.",
                "short-description-annotiation-for-collation": "ONIX 153 code 16 — Short description/annotation for the collection (series) this product belongs to. The slug is misspelled; send it exactly as shown.",
                "description-for-collection": "ONIX 153 code 17 — Description of the collection (series) this product belongs to.",
                "new-feature": "ONIX 153 code 18 — New feature; what changed in this edition.",
                "version-history": "ONIX 153 code 19 — Version history.",
                "open-access-statement": "ONIX 153 code 20 — Open access statement; the licence and access terms.",
                "digital-exclusivity-statement": "ONIX 153 code 21 — Digital exclusivity statement.",
                "official-recommendation": "ONIX 153 code 22 — Official recommendation, e.g. by an educational authority.",
                "jbpa-description": "ONIX 153 code 23 — JBPA description (Japanese Book Publishers Association).",
                "schema-org-snippet": "ONIX 153 code 24 — schema.org snippet for search-engine markup.",
                "errata": "ONIX 153 code 25 — Errata.",
                "intriduction": "ONIX 153 code 26 — Introduction. The slug is misspelled; send it exactly as shown.",
                "secondary-cover-copy": "ONIX 153 code 27 — Secondary cover copy, e.g. back cover as opposed to front.",
                "full-cast-and-credit-list": "ONIX 153 code 28 — Full cast and credit list; used for audiobooks and dramatisations.",
                "bibliography": "ONIX 153 code 29 — Bibliography.",
                "abstract": "ONIX 153 code 30 — Abstract; the scholarly summary, distinct from a marketing blurb.",
                "rules-or-instructions": "ONIX 153 code 31 — Rules or instructions, e.g. for a game or kit.",
                "list-of-contents": "ONIX 153 code 32 — List of contents; the components of a multi-item product.",
                "short-description-annotation-for-imprint": "ONIX 153 code 33 — Short description/annotation for the imprint.",
                "description-for-imprint": "ONIX 153 code 34 — Description of the imprint.",
                "short-description-annotation-for-publisher": "ONIX 153 code 35 — Short description/annotation for the publisher.",
                "description-for-publisher": "ONIX 153 code 36 — Description of the publisher.",
                "cover-line": "ONIX 153 code 37 — Cover line; a strapline carried on the cover."
            }
        },
        "type_onix": {
            "type": "string",
            "description": "The [ONIX Codelist 153](https://ns.editeur.org/onix/en/153) text type code\ncorresponding to `type`, as a two-digit string (`\"03\"` description, `\"12\"`\nbiographical note, …). Present so that ONIX consumers do not have to reimplement the\nslug mapping.\n\n**Read-only in effect.** The field is accepted in a request body but the value is\ndiscarded: the server recomputes it from `type` on every write. It is `null` whenever\n`type` is not one of the 37 recognised slugs. To change it, change `type`.\n\nNote that this is Codelist **153** (ONIX 3 `<TextType>`), not the ONIX 2.1 Codelist 33\n(`<OtherText>` type) that earlier revisions of this schema named. The two lists assign\ndifferent codes to the same concepts — a biographical note is `12` in 153 and `13` in\n33 — so a consumer that reads these codes against Codelist 33 will mislabel them.\n",
            "nullable": true,
            "example": "12"
        },
        "mime_type": {
            "type": "string",
            "description": "How `text` is encoded. In practice two values are used:\n\n- `text/plain` — literal text; line breaks are significant and a consumer must escape\n  it before putting it into a web page. The default when the field is omitted on\n  create.\n- `text/html` — an HTML fragment, typically wrapped in `<p>` elements. The API stores\n  it as sent and does not sanitise it, so a storefront rendering the value unescaped\n  is trusting whoever wrote it.\n\nValidation is **syntactic only**: any well-formed `type/subtype[; parameters]` string\nup to 255 characters is accepted, so a misspelling such as `text/htlm` is stored\nwithout complaint and is only noticed when the value is used. A malformed value is\nrejected with `400 Bad Request`, as is an empty one.\n\nBook-trade descriptions are usually HTML, while biographies and tables of contents are\nusually plain text, but nothing in the API enforces that pairing — `mime_type` is\nrecorded independently of `type`.\n",
            "example": "text/plain"
        }
    },
    "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."
                    }
                }
            }
        }
    }
}

{
    "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}/texts/{id}

Delete product text

Description

Removes the text entry permanently; there is no soft delete and no undo. Returns 204 with an empty body. A second delete of the same id returns 404.

Input parameters

Path parameters

Parameter Type Default Nullable Description
id string No UUID of the text entry.
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."
                    }
                }
            }
        }
    }
}

{
    "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 Text

Name Type Description Example
_id string

Unique identifier (UUID) for the product text.

3d5a9c14-7b02-4e88-9a61-0c7f2e4d8b35
_legacy_id integer

Legacy integer identifier of this resource, kept so existing integrations can correlate their own records. This is the _id the same record has on the v3 endpoint.

4180231
_links object
_version string

API Version.

4.0
channels Array<string>

Distribution channels this text is intended for. An empty list means the text applies to every channel and is the normal case; it is populated only when a partner needs different copy from everyone else — for example a shortened blurb for a retailer with a character limit, or a description that omits a competitor's name.

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

  • google
  • amazon
  • kobo
  • spotify
  • libri
  • ciando
  • divibib
  • overdrive
  • scribd
  • bookwire

The list is open-ended — a realm distributes through whichever partners it has contracts with. They are not validated against the channel list — any string of lowercase letters and hyphens is accepted, so a typo silently produces a text that no channel will ever match. Note that channel slugs containing digits or underscores (24symbols, manual_sale, zeitfracht_sa02e) are valid channels elsewhere in the API but are rejected here, because this field allows only [a-z-].

The list is normalised on write: values are lower-cased, de-duplicated and sorted alphabetically. Sending ["Google", "amazon", "google"] stores and returns ["amazon", "google"]. On update the list is replaced wholesale, never merged.

This endpoint applies no fallback logic of its own: it returns the entries exactly as stored, so selecting copy for one channel means preferring an entry that names that channel and otherwise taking the unscoped one.

channels is the only scoping axis this resource has, and it is narrower than ONIX. An ONIX 3 <TextContent> is also scoped by content audience (Codelist 154 — booktrade, end-customers, librarians, press, …) and by text source and validity dates; none of those fields exist here. channels names distribution partners, not classes of reader.

Storefronts are a separate axis and are not handled here. Per-shop copy — HTML title, meta description, meta keywords — belongs to the /resource/v4/products/{product_id}/storefronts sub-resource.

[]
language string| null

Language of text, as a three-letter ISO 639-2/B (bibliographic) code — ger for German, eng for English, fre for French. Note the B-codes: German is ger, not deu. Case is normalised to lower case on write; an unknown code is rejected with 400 Bad Request.

null when the language is unknown or not meaningful. A product carrying the same type in several languages holds one entry per language — nothing prevents duplicates, so a consumer picking "the description" should filter by the language it wants and fall back to the product's own language.

Note that a language once set cannot be cleared: sending "language": null is rejected with 400 Bad Request.

ger
mime_type string

How text is encoded. In practice two values are used:

  • text/plain — literal text; line breaks are significant and a consumer must escape it before putting it into a web page. The default when the field is omitted on create.
  • text/html — an HTML fragment, typically wrapped in <p> elements. The API stores it as sent and does not sanitise it, so a storefront rendering the value unescaped is trusting whoever wrote it.

Validation is syntactic only: any well-formed type/subtype[; parameters] string up to 255 characters is accepted, so a misspelling such as text/htlm is stored without complaint and is only noticed when the value is used. A malformed value is rejected with 400 Bad Request, as is an empty one.

Book-trade descriptions are usually HTML, while biographies and tables of contents are usually plain text, but nothing in the API enforces that pairing — mime_type is recorded independently of type.

text/plain
text string

The text itself. Its interpretation follows mime_type: with text/plain it is literal characters and line breaks; with text/html it is a fragment of markup (typically <p> paragraphs) that a storefront can drop into a page.

Must not be empty — a create or update that would leave text empty is rejected with 400 Bad Request.

There is no business length limit: an entry comfortably holds a full table of contents or a sample chapter, and the practical ceiling comes from the receiving channel rather than from this API. Characters outside the Basic Multilingual Plane — emoji, and some rarely used CJK and historic scripts — are not supported.

This sub-resource is a standalone store. It is independent of the legacy descriptive fields carried directly on the v3 product record (abstract, abstract_prefix, biographical_note, table_of_content): a text written here does not update those, and reading them does not surface entries created here. An entry is reachable through this sub-resource and its v3 equivalent, and nowhere else in the API.

Marit Sallenberg arbeitete als Lektorin und Kulturjournalistin, bevor sie ihren ersten Roman veroeffentlichte. Sie schreibt Gesellschaftsromane und lebt als freie Autorin in Rheinbergen.
type string

What kind of text this is. Not a closed enumeration — any non-empty string of lowercase letters and hyphens ([a-z-], up to 255 characters) is accepted. Digits, underscores, spaces and upper case are rejected with 400 Bad Request, as is an empty value.

37 slugs are recognised as equivalents of ONIX Codelist 153 values; for those the server derives type_onix. Anything else is stored as given with type_onix: null, which is the supported way to carry copy that ONIX has no code for.

A few of the distinctions in the list are easy to get wrong:

  • description (03) is the main long-form selling copy; short-description-annotation (02) is the abridged version for listings and feeds with a length budget. They are separate entries, not two renderings of one.
  • biographical-note (12) is about the author, not about the book, and takes one entry per contributor where there are several.
  • review-quote (06) is a quotation from a published review of this edition; review-quote-previous-edition (07) and review-quote-previous-work (08) exist for quotes that refer to something else.
  • endorsement (09) is a commendation solicited by the publisher, as distinct from a review published independently.
  • abstract (30) is the scholarly abstract, not a marketing blurb.
  • table-of-contents (04) is conventionally text/plain with one heading per line.

The complete set of recognised slugs, with the Codelist 153 code each one derives:

type type_onix Meaning
sender-defined-text 01 Sender-defined text
short-description-annotation 02 Short description / annotation — the abridged blurb for listings and feeds
description 03 Description — the main long-form selling copy
table-of-contents 04 Table of contents
primary-cover-copy 05 Primary cover copy — text printed on the cover or jacket
review-quote 06 Review quote
review-quote-previous-edition 07 Review quote, previous edition
review-quote-previous-work 08 Review quote, previous work
endorsement 09 Endorsement — solicited by the publisher, unlike a review
promotional-headline 10 Promotional headline
feature 11 Feature — a single selling point
biographical-note 12 Biographical note about a contributor
publishers-notive 13 Publisher's notice (slug misspelled — send it exactly as shown)
excerpt 14 Excerpt
index 15 Index
short-description-annotiation-for-collation 16 Short description for the collection (slug misspelled — send it exactly as shown)
description-for-collection 17 Description for the collection (series)
new-feature 18 New feature — what changed in this edition
version-history 19 Version history
open-access-statement 20 Open access statement
digital-exclusivity-statement 21 Digital exclusivity statement
official-recommendation 22 Official recommendation
jbpa-description 23 JBPA description
schema-org-snippet 24 schema.org snippet
errata 25 Errata
intriduction 26 Introduction (slug misspelled — send it exactly as shown)
secondary-cover-copy 27 Secondary cover copy
full-cast-and-credit-list 28 Full cast and credit list
bibliography 29 Bibliography
abstract 30 Abstract — the scholarly summary, not a marketing blurb
rules-or-instructions 31 Rules or instructions
list-of-contents 32 List of contents — components of a multi-item product
short-description-annotation-for-imprint 33 Short description for the imprint
description-for-imprint 34 Description for the imprint
short-description-annotation-for-publisher 35 Short description for the publisher
description-for-publisher 36 Description for the publisher
cover-line 37 Cover line

Three of those slugs — publishers-notive, short-description-annotiation-for-collation and intriduction — are misspelled, and the table lists them as they must be sent to obtain a code. The correctly spelled forms publishers-notice, short-description-annotation-for-collection and introduction are accepted as well, but they are not recognised and yield type_onix: null.

This is the only field the collection endpoint can filter on, with the operators described under Resource Queries. Any other field name is rejected with 400 Bad Request, as is an unknown operator suffix, so language and channels have to be narrowed down client-side. Results cannot be sorted: a sort parameter is accepted and applied to nothing, which leaves the order of results unspecified. Pagination is standard, with a default page size of 100.

biographical-note
type_onix string| null

The ONIX Codelist 153 text type code corresponding to type, as a two-digit string ("03" description, "12" biographical note, …). Present so that ONIX consumers do not have to reimplement the slug mapping.

Read-only in effect. The field is accepted in a request body but the value is discarded: the server recomputes it from type on every write. It is null whenever type is not one of the 37 recognised slugs. To change it, change type.

Note that this is Codelist 153 (ONIX 3 <TextType>), not the ONIX 2.1 Codelist 33 (<OtherText> type) that earlier revisions of this schema named. The two lists assign different codes to the same concepts — a biographical note is 12 in 153 and 13 in 33 — so a consumer that reads these codes against Codelist 33 will mislabel them.

12