Skip to content

Product Contacts v4

Sub-resource of products holding the people and departments a trading partner or authority contacts about a title: product safety, metadata corrections, review copies, rights enquiries. Each record pairs a role from ONIX Codelist 198 with the name, telephone, e-mail and postal address of the party to approach.

A contact belongs to a single product format rather than to the product, so the same contact for two formats is held as two records.


Endpoints


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

Retrieve contacts for a product

Description

Returns every contact recorded for the product, across all formats, paginated.

Exactly three fields are filterable — product_type and product_contact_role by equality only, and product_contact_name with the full operator syntax. Any other query parameter is rejected with 400 Bad Request. sort is accepted but has no effect, so result order is unspecified. See Resource Queries for the query syntax.

Input parameters

Path parameters

Parameter Type Default Nullable Description
product_id string No UUID of the product whose contacts are returned.

Query parameters

Parameter Type Default Nullable Description
product_contact_name string No Match on the organisation name — the only field of this resource that accepts comparison operators, e.g. `?product_contact_name__contains=Verlagsgruppe`.
product_contact_role string No Restrict to one ONIX [Codelist 198](https://ns.editeur.org/onix/en/198) role, leading zero included — e.g. `10` for the product safety contact. Equality only.
product_type string No Restrict to one product format (`ebook`, `book`, `audiobook`, `nonbook`). Equality only.

Responses

{
    "_links": {},
    "_pagination": {},
    "items": [
        {
            "_id": "c9d0e1f2-a3b4-5678-abcd-ef1234567890",
            "_version": "4.0",
            "_legacy_id": 88214,
            "_links": {},
            "product_type": "book",
            "product_contact_role": "10",
            "product_contact_name": "Zeilenquarz Verlagsgruppe GmbH",
            "contact_name": "Almut Rethwisch",
            "telephone_number": "+49 123 4567890",
            "email_adress": "produktsicherheit@example.com",
            "street_address": "Kolophonstraße 8",
            "location_name": "Rheinbergen",
            "postal_code": "41569",
            "country": "DE"
        }
    ]
}
⚠️ 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 contact for one product format, identified by its ONIX product contact role.",
                "properties": {
                    "_id": {
                        "type": "string",
                        "description": "UUID of the contact record.",
                        "example": "c9d0e1f2-a3b4-5678-abcd-ef1234567890"
                    },
                    "_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.",
                        "example": 88214
                    },
                    "_links": {
                        "type": "object"
                    },
                    "product_type": {
                        "type": "string",
                        "description": "The product format this contact belongs to. A contact applies only to the format it\nnames, so the same person often needs one record per format. Always present.\n\nAny of the platform's product types is accepted, but only the four publishing\nformats are meaningful here: `ebook`, `book`, `audiobook`, `nonbook`. An invalid\nvalue is rejected with `400 Bad Request`.\n\nFilterable on the collection endpoint, equality only.\n",
                        "example": "book",
                        "x-enum-descriptions": {
                            "ebook": "E-book in any file format (EPUB, PDF, …)",
                            "book": "Physical book, including print-on-demand",
                            "audiobook": "Audiobook, downloadable or streaming",
                            "nonbook": "Non-book article"
                        }
                    },
                    "product_contact_role": {
                        "type": "string",
                        "description": "What this contact is *for*: a two-character code from ONIX\n[Codelist 198, Product contact role](https://ns.editeur.org/onix/en/198). Codes are\naccepted and returned verbatim including the leading zero — `\"00\"`, not `0`. The whole\ncodelist is accepted; anything else is rejected with `400 Bad Request`. Always present.\n\nTwo codes matter more than the rest in practice:\n\n- `\"10\"` **Product safety contact** — the responsible-person details that EU product\n  safety rules require to accompany a printed book.\n- `\"00\"` **Metadata contact** — where a retailer sends corrections to the\n  bibliographic record.\n\nLook the remaining codes up in Codelist 198; they are not reproduced here.\n\nFilterable on the collection endpoint, equality only.\n",
                        "example": "10"
                    },
                    "product_contact_name": {
                        "type": "string",
                        "description": "The organisation to contact, as free text — a company or department name, not a\nreference to a business partner or imprint record.\n\nExactly three fields are filterable on the collection endpoint: `product_type`,\n`product_contact_role` and `product_contact_name` — and this is the only one of them\nthat accepts comparison operators. Any other query parameter is rejected with\n`400 Bad Request`; `product_id` is part of the path, not a filter. `sort` is accepted\nbut has no effect, leaving the order of results unspecified. See\n[Resource Queries](/resource_queries/) for the query syntax.\n",
                        "nullable": true,
                        "example": "Zeilenquarz Verlagsgruppe GmbH"
                    },
                    "contact_name": {
                        "type": "string",
                        "description": "The named individual or role-based addressee at that organisation. Prefer a function\naddress over a person for safety and metadata roles, since the record outlives staff\nchanges and is published to trading partners.\n",
                        "nullable": true,
                        "example": "Almut Rethwisch"
                    },
                    "telephone_number": {
                        "type": "string",
                        "description": "Telephone number as free text; no format is imposed or validated. Include the\ninternational dialling prefix, because the value is published to partners in other\ncountries.\n",
                        "nullable": true,
                        "example": "+49 123 4567890"
                    },
                    "email_adress": {
                        "type": "string",
                        "description": "E-mail address of the contact. Not validated — any string is accepted.\n\n**Note the spelling.** The field is `email_adress`, with one `d`. That is its name in\nboth requests and responses, and it is part of the API contract.\n",
                        "nullable": true,
                        "example": "produktsicherheit@example.com"
                    },
                    "street_address": {
                        "type": "string",
                        "description": "Street and building number, as a single free-text line. Product safety roles need a\nfull postal address to satisfy the responsible-person requirement, so this, plus\n`postal_code`, `location_name` and `country`, should be complete for role `\"10\"`.\n",
                        "nullable": true,
                        "example": "Kolophonstraße 8"
                    },
                    "location_name": {
                        "type": "string",
                        "description": "Town or city.",
                        "nullable": true,
                        "example": "Rheinbergen"
                    },
                    "postal_code": {
                        "type": "string",
                        "description": "Postal code, as free text — no country-specific validation.",
                        "nullable": true,
                        "example": "41569"
                    },
                    "country": {
                        "type": "string",
                        "description": "Country as an ISO 3166-1 alpha-2 code (e.g. `DE`, `AT`, `US`). Validated against the\nplatform's known countries, so an unrecognised code is rejected. `null` when no\ncountry is recorded.\n",
                        "nullable": true,
                        "example": "DE"
                    }
                },
                "required": []
            }
        }
    },
    "required": [
        "_links",
        "_pagination",
        "items"
    ]
}

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

Create a new product contact

Description

Creates one contact for one format. product_type and product_contact_role are required in practice — both are always present in a response — and everything else is optional.

The example registers the product safety contact for a printed book: the role that EU product safety rules require, with the full postal address that requirement implies. A complete address is preferable to a partial one.

Input parameters

Path parameters

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

Request body

{
    "product_type": "book",
    "product_contact_role": "10",
    "product_contact_name": "Zeilenquarz Verlagsgruppe GmbH",
    "contact_name": "Almut Rethwisch",
    "telephone_number": "+49 123 4567890",
    "email_adress": "produktsicherheit@example.com",
    "street_address": "Kolophonstraße 8",
    "location_name": "Rheinbergen",
    "postal_code": "41569",
    "country": "DE"
}
Schema of the request body
{
    "type": "object",
    "additionalProperties": false,
    "description": "One contact for one product format, identified by its ONIX product contact role.",
    "properties": {
        "_id": {
            "type": "string",
            "description": "UUID of the contact record.",
            "example": "c9d0e1f2-a3b4-5678-abcd-ef1234567890"
        },
        "_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.",
            "example": 88214
        },
        "_links": {
            "type": "object"
        },
        "product_type": {
            "type": "string",
            "description": "The product format this contact belongs to. A contact applies only to the format it\nnames, so the same person often needs one record per format. Always present.\n\nAny of the platform's product types is accepted, but only the four publishing\nformats are meaningful here: `ebook`, `book`, `audiobook`, `nonbook`. An invalid\nvalue is rejected with `400 Bad Request`.\n\nFilterable on the collection endpoint, equality only.\n",
            "example": "book",
            "x-enum-descriptions": {
                "ebook": "E-book in any file format (EPUB, PDF, …)",
                "book": "Physical book, including print-on-demand",
                "audiobook": "Audiobook, downloadable or streaming",
                "nonbook": "Non-book article"
            }
        },
        "product_contact_role": {
            "type": "string",
            "description": "What this contact is *for*: a two-character code from ONIX\n[Codelist 198, Product contact role](https://ns.editeur.org/onix/en/198). Codes are\naccepted and returned verbatim including the leading zero — `\"00\"`, not `0`. The whole\ncodelist is accepted; anything else is rejected with `400 Bad Request`. Always present.\n\nTwo codes matter more than the rest in practice:\n\n- `\"10\"` **Product safety contact** — the responsible-person details that EU product\n  safety rules require to accompany a printed book.\n- `\"00\"` **Metadata contact** — where a retailer sends corrections to the\n  bibliographic record.\n\nLook the remaining codes up in Codelist 198; they are not reproduced here.\n\nFilterable on the collection endpoint, equality only.\n",
            "example": "10"
        },
        "product_contact_name": {
            "type": "string",
            "description": "The organisation to contact, as free text — a company or department name, not a\nreference to a business partner or imprint record.\n\nExactly three fields are filterable on the collection endpoint: `product_type`,\n`product_contact_role` and `product_contact_name` — and this is the only one of them\nthat accepts comparison operators. Any other query parameter is rejected with\n`400 Bad Request`; `product_id` is part of the path, not a filter. `sort` is accepted\nbut has no effect, leaving the order of results unspecified. See\n[Resource Queries](/resource_queries/) for the query syntax.\n",
            "nullable": true,
            "example": "Zeilenquarz Verlagsgruppe GmbH"
        },
        "contact_name": {
            "type": "string",
            "description": "The named individual or role-based addressee at that organisation. Prefer a function\naddress over a person for safety and metadata roles, since the record outlives staff\nchanges and is published to trading partners.\n",
            "nullable": true,
            "example": "Almut Rethwisch"
        },
        "telephone_number": {
            "type": "string",
            "description": "Telephone number as free text; no format is imposed or validated. Include the\ninternational dialling prefix, because the value is published to partners in other\ncountries.\n",
            "nullable": true,
            "example": "+49 123 4567890"
        },
        "email_adress": {
            "type": "string",
            "description": "E-mail address of the contact. Not validated — any string is accepted.\n\n**Note the spelling.** The field is `email_adress`, with one `d`. That is its name in\nboth requests and responses, and it is part of the API contract.\n",
            "nullable": true,
            "example": "produktsicherheit@example.com"
        },
        "street_address": {
            "type": "string",
            "description": "Street and building number, as a single free-text line. Product safety roles need a\nfull postal address to satisfy the responsible-person requirement, so this, plus\n`postal_code`, `location_name` and `country`, should be complete for role `\"10\"`.\n",
            "nullable": true,
            "example": "Kolophonstraße 8"
        },
        "location_name": {
            "type": "string",
            "description": "Town or city.",
            "nullable": true,
            "example": "Rheinbergen"
        },
        "postal_code": {
            "type": "string",
            "description": "Postal code, as free text — no country-specific validation.",
            "nullable": true,
            "example": "41569"
        },
        "country": {
            "type": "string",
            "description": "Country as an ISO 3166-1 alpha-2 code (e.g. `DE`, `AT`, `US`). Validated against the\nplatform's known countries, so an unrecognised code is rejected. `null` when no\ncountry is recorded.\n",
            "nullable": true,
            "example": "DE"
        }
    },
    "required": []
}

Responses

{
    "_id": "c9d0e1f2-a3b4-5678-abcd-ef1234567890",
    "_legacy_id": 88214,
    "_version": "4.0",
    "_links": {
        "self": "https://api.openpublishing.com/resource/v4/products/3f8c1a52-9b7d-4e16-8a0c-2d5f7e91b4c3/contacts/c9d0e1f2-a3b4-5678-abcd-ef1234567890"
    },
    "product_type": "book",
    "product_contact_role": "10",
    "product_contact_name": "Zeilenquarz Verlagsgruppe GmbH",
    "contact_name": "Almut Rethwisch",
    "telephone_number": "+49 123 4567890",
    "email_adress": "produktsicherheit@example.com",
    "street_address": "Kolophonstraße 8",
    "location_name": "Rheinbergen",
    "postal_code": "41569",
    "country": "DE"
}
Schema of the response body
{
    "type": "object",
    "additionalProperties": false,
    "description": "One contact for one product format, identified by its ONIX product contact role.",
    "properties": {
        "_id": {
            "type": "string",
            "description": "UUID of the contact record.",
            "example": "c9d0e1f2-a3b4-5678-abcd-ef1234567890"
        },
        "_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.",
            "example": 88214
        },
        "_links": {
            "type": "object"
        },
        "product_type": {
            "type": "string",
            "description": "The product format this contact belongs to. A contact applies only to the format it\nnames, so the same person often needs one record per format. Always present.\n\nAny of the platform's product types is accepted, but only the four publishing\nformats are meaningful here: `ebook`, `book`, `audiobook`, `nonbook`. An invalid\nvalue is rejected with `400 Bad Request`.\n\nFilterable on the collection endpoint, equality only.\n",
            "example": "book",
            "x-enum-descriptions": {
                "ebook": "E-book in any file format (EPUB, PDF, …)",
                "book": "Physical book, including print-on-demand",
                "audiobook": "Audiobook, downloadable or streaming",
                "nonbook": "Non-book article"
            }
        },
        "product_contact_role": {
            "type": "string",
            "description": "What this contact is *for*: a two-character code from ONIX\n[Codelist 198, Product contact role](https://ns.editeur.org/onix/en/198). Codes are\naccepted and returned verbatim including the leading zero — `\"00\"`, not `0`. The whole\ncodelist is accepted; anything else is rejected with `400 Bad Request`. Always present.\n\nTwo codes matter more than the rest in practice:\n\n- `\"10\"` **Product safety contact** — the responsible-person details that EU product\n  safety rules require to accompany a printed book.\n- `\"00\"` **Metadata contact** — where a retailer sends corrections to the\n  bibliographic record.\n\nLook the remaining codes up in Codelist 198; they are not reproduced here.\n\nFilterable on the collection endpoint, equality only.\n",
            "example": "10"
        },
        "product_contact_name": {
            "type": "string",
            "description": "The organisation to contact, as free text — a company or department name, not a\nreference to a business partner or imprint record.\n\nExactly three fields are filterable on the collection endpoint: `product_type`,\n`product_contact_role` and `product_contact_name` — and this is the only one of them\nthat accepts comparison operators. Any other query parameter is rejected with\n`400 Bad Request`; `product_id` is part of the path, not a filter. `sort` is accepted\nbut has no effect, leaving the order of results unspecified. See\n[Resource Queries](/resource_queries/) for the query syntax.\n",
            "nullable": true,
            "example": "Zeilenquarz Verlagsgruppe GmbH"
        },
        "contact_name": {
            "type": "string",
            "description": "The named individual or role-based addressee at that organisation. Prefer a function\naddress over a person for safety and metadata roles, since the record outlives staff\nchanges and is published to trading partners.\n",
            "nullable": true,
            "example": "Almut Rethwisch"
        },
        "telephone_number": {
            "type": "string",
            "description": "Telephone number as free text; no format is imposed or validated. Include the\ninternational dialling prefix, because the value is published to partners in other\ncountries.\n",
            "nullable": true,
            "example": "+49 123 4567890"
        },
        "email_adress": {
            "type": "string",
            "description": "E-mail address of the contact. Not validated — any string is accepted.\n\n**Note the spelling.** The field is `email_adress`, with one `d`. That is its name in\nboth requests and responses, and it is part of the API contract.\n",
            "nullable": true,
            "example": "produktsicherheit@example.com"
        },
        "street_address": {
            "type": "string",
            "description": "Street and building number, as a single free-text line. Product safety roles need a\nfull postal address to satisfy the responsible-person requirement, so this, plus\n`postal_code`, `location_name` and `country`, should be complete for role `\"10\"`.\n",
            "nullable": true,
            "example": "Kolophonstraße 8"
        },
        "location_name": {
            "type": "string",
            "description": "Town or city.",
            "nullable": true,
            "example": "Rheinbergen"
        },
        "postal_code": {
            "type": "string",
            "description": "Postal code, as free text — no country-specific validation.",
            "nullable": true,
            "example": "41569"
        },
        "country": {
            "type": "string",
            "description": "Country as an ISO 3166-1 alpha-2 code (e.g. `DE`, `AT`, `US`). Validated against the\nplatform's known countries, so an unrecognised code is rejected. `null` when no\ncountry is recorded.\n",
            "nullable": true,
            "example": "DE"
        }
    },
    "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}/contacts/{id}

Retrieve a single product contact

Description

Returns one contact by id. The example is a metadata contact (role "00") on an e-book — the address where a retailer sends corrections to the bibliographic record. Note that the postal fields are all null: a metadata contact rarely needs one, and only role "10" has a reason to be complete.

A contact id that exists but belongs to a different product returns 403, not 404. An id that exists nowhere returns 404.

Input parameters

Path parameters

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

Responses

{
    "_id": "7a1b4c9e-2d35-4f80-91ab-6c0e5d3f2718",
    "_legacy_id": 88215,
    "_version": "4.0",
    "_links": {
        "self": "https://api.openpublishing.com/resource/v4/products/3f8c1a52-9b7d-4e16-8a0c-2d5f7e91b4c3/contacts/7a1b4c9e-2d35-4f80-91ab-6c0e5d3f2718"
    },
    "product_type": "ebook",
    "product_contact_role": "00",
    "product_contact_name": "Zeilenquarz Verlagsgruppe GmbH",
    "contact_name": "Cornelius Baldauf",
    "telephone_number": "+49 123 4567891",
    "email_adress": "metadaten@example.com",
    "street_address": null,
    "location_name": null,
    "postal_code": null,
    "country": null
}
Schema of the response body
{
    "type": "object",
    "additionalProperties": false,
    "description": "One contact for one product format, identified by its ONIX product contact role.",
    "properties": {
        "_id": {
            "type": "string",
            "description": "UUID of the contact record.",
            "example": "c9d0e1f2-a3b4-5678-abcd-ef1234567890"
        },
        "_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.",
            "example": 88214
        },
        "_links": {
            "type": "object"
        },
        "product_type": {
            "type": "string",
            "description": "The product format this contact belongs to. A contact applies only to the format it\nnames, so the same person often needs one record per format. Always present.\n\nAny of the platform's product types is accepted, but only the four publishing\nformats are meaningful here: `ebook`, `book`, `audiobook`, `nonbook`. An invalid\nvalue is rejected with `400 Bad Request`.\n\nFilterable on the collection endpoint, equality only.\n",
            "example": "book",
            "x-enum-descriptions": {
                "ebook": "E-book in any file format (EPUB, PDF, …)",
                "book": "Physical book, including print-on-demand",
                "audiobook": "Audiobook, downloadable or streaming",
                "nonbook": "Non-book article"
            }
        },
        "product_contact_role": {
            "type": "string",
            "description": "What this contact is *for*: a two-character code from ONIX\n[Codelist 198, Product contact role](https://ns.editeur.org/onix/en/198). Codes are\naccepted and returned verbatim including the leading zero — `\"00\"`, not `0`. The whole\ncodelist is accepted; anything else is rejected with `400 Bad Request`. Always present.\n\nTwo codes matter more than the rest in practice:\n\n- `\"10\"` **Product safety contact** — the responsible-person details that EU product\n  safety rules require to accompany a printed book.\n- `\"00\"` **Metadata contact** — where a retailer sends corrections to the\n  bibliographic record.\n\nLook the remaining codes up in Codelist 198; they are not reproduced here.\n\nFilterable on the collection endpoint, equality only.\n",
            "example": "10"
        },
        "product_contact_name": {
            "type": "string",
            "description": "The organisation to contact, as free text — a company or department name, not a\nreference to a business partner or imprint record.\n\nExactly three fields are filterable on the collection endpoint: `product_type`,\n`product_contact_role` and `product_contact_name` — and this is the only one of them\nthat accepts comparison operators. Any other query parameter is rejected with\n`400 Bad Request`; `product_id` is part of the path, not a filter. `sort` is accepted\nbut has no effect, leaving the order of results unspecified. See\n[Resource Queries](/resource_queries/) for the query syntax.\n",
            "nullable": true,
            "example": "Zeilenquarz Verlagsgruppe GmbH"
        },
        "contact_name": {
            "type": "string",
            "description": "The named individual or role-based addressee at that organisation. Prefer a function\naddress over a person for safety and metadata roles, since the record outlives staff\nchanges and is published to trading partners.\n",
            "nullable": true,
            "example": "Almut Rethwisch"
        },
        "telephone_number": {
            "type": "string",
            "description": "Telephone number as free text; no format is imposed or validated. Include the\ninternational dialling prefix, because the value is published to partners in other\ncountries.\n",
            "nullable": true,
            "example": "+49 123 4567890"
        },
        "email_adress": {
            "type": "string",
            "description": "E-mail address of the contact. Not validated — any string is accepted.\n\n**Note the spelling.** The field is `email_adress`, with one `d`. That is its name in\nboth requests and responses, and it is part of the API contract.\n",
            "nullable": true,
            "example": "produktsicherheit@example.com"
        },
        "street_address": {
            "type": "string",
            "description": "Street and building number, as a single free-text line. Product safety roles need a\nfull postal address to satisfy the responsible-person requirement, so this, plus\n`postal_code`, `location_name` and `country`, should be complete for role `\"10\"`.\n",
            "nullable": true,
            "example": "Kolophonstraße 8"
        },
        "location_name": {
            "type": "string",
            "description": "Town or city.",
            "nullable": true,
            "example": "Rheinbergen"
        },
        "postal_code": {
            "type": "string",
            "description": "Postal code, as free text — no country-specific validation.",
            "nullable": true,
            "example": "41569"
        },
        "country": {
            "type": "string",
            "description": "Country as an ISO 3166-1 alpha-2 code (e.g. `DE`, `AT`, `US`). Validated against the\nplatform's known countries, so an unrecognised code is rejected. `null` when no\ncountry is recorded.\n",
            "nullable": true,
            "example": "DE"
        }
    },
    "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}/contacts/{id}

Update product contact

Description

Updates one contact. Despite being a PUT this is a partial update: only the keys present in the body are applied, so any omitted field keeps its current value. Sending {} changes nothing, and a field can only be cleared by sending an explicit null.

The example refines the town of the product safety contact created above, sending location_name alone. The response returns the complete merged record.

Input parameters

Path parameters

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

Request body

{
    "location_name": "Rheinbergen / Niederrhein"
}
Schema of the request body
{
    "type": "object",
    "additionalProperties": false,
    "description": "One contact for one product format, identified by its ONIX product contact role.",
    "properties": {
        "_id": {
            "type": "string",
            "description": "UUID of the contact record.",
            "example": "c9d0e1f2-a3b4-5678-abcd-ef1234567890"
        },
        "_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.",
            "example": 88214
        },
        "_links": {
            "type": "object"
        },
        "product_type": {
            "type": "string",
            "description": "The product format this contact belongs to. A contact applies only to the format it\nnames, so the same person often needs one record per format. Always present.\n\nAny of the platform's product types is accepted, but only the four publishing\nformats are meaningful here: `ebook`, `book`, `audiobook`, `nonbook`. An invalid\nvalue is rejected with `400 Bad Request`.\n\nFilterable on the collection endpoint, equality only.\n",
            "example": "book",
            "x-enum-descriptions": {
                "ebook": "E-book in any file format (EPUB, PDF, …)",
                "book": "Physical book, including print-on-demand",
                "audiobook": "Audiobook, downloadable or streaming",
                "nonbook": "Non-book article"
            }
        },
        "product_contact_role": {
            "type": "string",
            "description": "What this contact is *for*: a two-character code from ONIX\n[Codelist 198, Product contact role](https://ns.editeur.org/onix/en/198). Codes are\naccepted and returned verbatim including the leading zero — `\"00\"`, not `0`. The whole\ncodelist is accepted; anything else is rejected with `400 Bad Request`. Always present.\n\nTwo codes matter more than the rest in practice:\n\n- `\"10\"` **Product safety contact** — the responsible-person details that EU product\n  safety rules require to accompany a printed book.\n- `\"00\"` **Metadata contact** — where a retailer sends corrections to the\n  bibliographic record.\n\nLook the remaining codes up in Codelist 198; they are not reproduced here.\n\nFilterable on the collection endpoint, equality only.\n",
            "example": "10"
        },
        "product_contact_name": {
            "type": "string",
            "description": "The organisation to contact, as free text — a company or department name, not a\nreference to a business partner or imprint record.\n\nExactly three fields are filterable on the collection endpoint: `product_type`,\n`product_contact_role` and `product_contact_name` — and this is the only one of them\nthat accepts comparison operators. Any other query parameter is rejected with\n`400 Bad Request`; `product_id` is part of the path, not a filter. `sort` is accepted\nbut has no effect, leaving the order of results unspecified. See\n[Resource Queries](/resource_queries/) for the query syntax.\n",
            "nullable": true,
            "example": "Zeilenquarz Verlagsgruppe GmbH"
        },
        "contact_name": {
            "type": "string",
            "description": "The named individual or role-based addressee at that organisation. Prefer a function\naddress over a person for safety and metadata roles, since the record outlives staff\nchanges and is published to trading partners.\n",
            "nullable": true,
            "example": "Almut Rethwisch"
        },
        "telephone_number": {
            "type": "string",
            "description": "Telephone number as free text; no format is imposed or validated. Include the\ninternational dialling prefix, because the value is published to partners in other\ncountries.\n",
            "nullable": true,
            "example": "+49 123 4567890"
        },
        "email_adress": {
            "type": "string",
            "description": "E-mail address of the contact. Not validated — any string is accepted.\n\n**Note the spelling.** The field is `email_adress`, with one `d`. That is its name in\nboth requests and responses, and it is part of the API contract.\n",
            "nullable": true,
            "example": "produktsicherheit@example.com"
        },
        "street_address": {
            "type": "string",
            "description": "Street and building number, as a single free-text line. Product safety roles need a\nfull postal address to satisfy the responsible-person requirement, so this, plus\n`postal_code`, `location_name` and `country`, should be complete for role `\"10\"`.\n",
            "nullable": true,
            "example": "Kolophonstraße 8"
        },
        "location_name": {
            "type": "string",
            "description": "Town or city.",
            "nullable": true,
            "example": "Rheinbergen"
        },
        "postal_code": {
            "type": "string",
            "description": "Postal code, as free text — no country-specific validation.",
            "nullable": true,
            "example": "41569"
        },
        "country": {
            "type": "string",
            "description": "Country as an ISO 3166-1 alpha-2 code (e.g. `DE`, `AT`, `US`). Validated against the\nplatform's known countries, so an unrecognised code is rejected. `null` when no\ncountry is recorded.\n",
            "nullable": true,
            "example": "DE"
        }
    },
    "required": []
}

Responses

{
    "_id": "c9d0e1f2-a3b4-5678-abcd-ef1234567890",
    "_legacy_id": 88214,
    "_version": "4.0",
    "_links": {
        "self": "https://api.openpublishing.com/resource/v4/products/3f8c1a52-9b7d-4e16-8a0c-2d5f7e91b4c3/contacts/c9d0e1f2-a3b4-5678-abcd-ef1234567890"
    },
    "product_type": "book",
    "product_contact_role": "10",
    "product_contact_name": "Zeilenquarz Verlagsgruppe GmbH",
    "contact_name": "Almut Rethwisch",
    "telephone_number": "+49 123 4567890",
    "email_adress": "produktsicherheit@example.com",
    "street_address": "Kolophonstraße 8",
    "location_name": "Rheinbergen / Niederrhein",
    "postal_code": "41569",
    "country": "DE"
}
Schema of the response body
{
    "type": "object",
    "additionalProperties": false,
    "description": "One contact for one product format, identified by its ONIX product contact role.",
    "properties": {
        "_id": {
            "type": "string",
            "description": "UUID of the contact record.",
            "example": "c9d0e1f2-a3b4-5678-abcd-ef1234567890"
        },
        "_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.",
            "example": 88214
        },
        "_links": {
            "type": "object"
        },
        "product_type": {
            "type": "string",
            "description": "The product format this contact belongs to. A contact applies only to the format it\nnames, so the same person often needs one record per format. Always present.\n\nAny of the platform's product types is accepted, but only the four publishing\nformats are meaningful here: `ebook`, `book`, `audiobook`, `nonbook`. An invalid\nvalue is rejected with `400 Bad Request`.\n\nFilterable on the collection endpoint, equality only.\n",
            "example": "book",
            "x-enum-descriptions": {
                "ebook": "E-book in any file format (EPUB, PDF, …)",
                "book": "Physical book, including print-on-demand",
                "audiobook": "Audiobook, downloadable or streaming",
                "nonbook": "Non-book article"
            }
        },
        "product_contact_role": {
            "type": "string",
            "description": "What this contact is *for*: a two-character code from ONIX\n[Codelist 198, Product contact role](https://ns.editeur.org/onix/en/198). Codes are\naccepted and returned verbatim including the leading zero — `\"00\"`, not `0`. The whole\ncodelist is accepted; anything else is rejected with `400 Bad Request`. Always present.\n\nTwo codes matter more than the rest in practice:\n\n- `\"10\"` **Product safety contact** — the responsible-person details that EU product\n  safety rules require to accompany a printed book.\n- `\"00\"` **Metadata contact** — where a retailer sends corrections to the\n  bibliographic record.\n\nLook the remaining codes up in Codelist 198; they are not reproduced here.\n\nFilterable on the collection endpoint, equality only.\n",
            "example": "10"
        },
        "product_contact_name": {
            "type": "string",
            "description": "The organisation to contact, as free text — a company or department name, not a\nreference to a business partner or imprint record.\n\nExactly three fields are filterable on the collection endpoint: `product_type`,\n`product_contact_role` and `product_contact_name` — and this is the only one of them\nthat accepts comparison operators. Any other query parameter is rejected with\n`400 Bad Request`; `product_id` is part of the path, not a filter. `sort` is accepted\nbut has no effect, leaving the order of results unspecified. See\n[Resource Queries](/resource_queries/) for the query syntax.\n",
            "nullable": true,
            "example": "Zeilenquarz Verlagsgruppe GmbH"
        },
        "contact_name": {
            "type": "string",
            "description": "The named individual or role-based addressee at that organisation. Prefer a function\naddress over a person for safety and metadata roles, since the record outlives staff\nchanges and is published to trading partners.\n",
            "nullable": true,
            "example": "Almut Rethwisch"
        },
        "telephone_number": {
            "type": "string",
            "description": "Telephone number as free text; no format is imposed or validated. Include the\ninternational dialling prefix, because the value is published to partners in other\ncountries.\n",
            "nullable": true,
            "example": "+49 123 4567890"
        },
        "email_adress": {
            "type": "string",
            "description": "E-mail address of the contact. Not validated — any string is accepted.\n\n**Note the spelling.** The field is `email_adress`, with one `d`. That is its name in\nboth requests and responses, and it is part of the API contract.\n",
            "nullable": true,
            "example": "produktsicherheit@example.com"
        },
        "street_address": {
            "type": "string",
            "description": "Street and building number, as a single free-text line. Product safety roles need a\nfull postal address to satisfy the responsible-person requirement, so this, plus\n`postal_code`, `location_name` and `country`, should be complete for role `\"10\"`.\n",
            "nullable": true,
            "example": "Kolophonstraße 8"
        },
        "location_name": {
            "type": "string",
            "description": "Town or city.",
            "nullable": true,
            "example": "Rheinbergen"
        },
        "postal_code": {
            "type": "string",
            "description": "Postal code, as free text — no country-specific validation.",
            "nullable": true,
            "example": "41569"
        },
        "country": {
            "type": "string",
            "description": "Country as an ISO 3166-1 alpha-2 code (e.g. `DE`, `AT`, `US`). Validated against the\nplatform's known countries, so an unrecognised code is rejected. `null` when no\ncountry is recorded.\n",
            "nullable": true,
            "example": "DE"
        }
    },
    "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}/contacts/{id}

Delete product contact

Description

Removes the contact.

Input parameters

Path parameters

Parameter Type Default Nullable Description
id string No
product_id string No

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 Contact

Name Type Description Example
_id string

UUID of the contact record.

c9d0e1f2-a3b4-5678-abcd-ef1234567890
_legacy_id integer

Legacy integer identifier of this resource, kept so existing integrations can correlate their own records.

88214
_links object
_version string

API Version

4.0
contact_name string| null

The named individual or role-based addressee at that organisation. Prefer a function address over a person for safety and metadata roles, since the record outlives staff changes and is published to trading partners.

Almut Rethwisch
country string| null

Country as an ISO 3166-1 alpha-2 code (e.g. DE, AT, US). Validated against the platform's known countries, so an unrecognised code is rejected. null when no country is recorded.

DE
email_adress string| null

E-mail address of the contact. Not validated — any string is accepted.

Note the spelling. The field is email_adress, with one d. That is its name in both requests and responses, and it is part of the API contract.

produktsicherheit@example.com
location_name string| null

Town or city.

Rheinbergen
postal_code string| null

Postal code, as free text — no country-specific validation.

41569
product_contact_name string| null

The organisation to contact, as free text — a company or department name, not a reference to a business partner or imprint record.

Exactly three fields are filterable on the collection endpoint: product_type, product_contact_role and product_contact_name — and this is the only one of them that accepts comparison operators. Any other query parameter is rejected with 400 Bad Request; product_id is part of the path, not a filter. sort is accepted but has no effect, leaving the order of results unspecified. See Resource Queries for the query syntax.

Zeilenquarz Verlagsgruppe GmbH
product_contact_role string

What this contact is for: a two-character code from ONIX Codelist 198, Product contact role. Codes are accepted and returned verbatim including the leading zero — "00", not 0. The whole codelist is accepted; anything else is rejected with 400 Bad Request. Always present.

Two codes matter more than the rest in practice:

  • "10" Product safety contact — the responsible-person details that EU product safety rules require to accompany a printed book.
  • "00" Metadata contact — where a retailer sends corrections to the bibliographic record.

Look the remaining codes up in Codelist 198; they are not reproduced here.

Filterable on the collection endpoint, equality only.

10
product_type string

The product format this contact belongs to. A contact applies only to the format it names, so the same person often needs one record per format. Always present.

Any of the platform's product types is accepted, but only the four publishing formats are meaningful here: ebook, book, audiobook, nonbook. An invalid value is rejected with 400 Bad Request.

Filterable on the collection endpoint, equality only.

book
street_address string| null

Street and building number, as a single free-text line. Product safety roles need a full postal address to satisfy the responsible-person requirement, so this, plus postal_code, location_name and country, should be complete for role "10".

Kolophonstraße 8
telephone_number string| null

Telephone number as free text; no format is imposed or validated. Include the international dialling prefix, because the value is published to partners in other countries.

+49 123 4567890