Skip to main content

Content Requests

What is a content request?​

A content request is your proposal to create or update a product, a brand or a manufacturer in the catalog. You submit it with the createContentRequest mutation.

  • The request is created in a pending state and is reviewed by the marketplace team before any catalog change is applied.
  • The mutation returns 202 Accepted — it does not change the catalog immediately.
  • The id you send is also the idempotency key: sending the same id again will not create a duplicate.

The mutation​

mutation CreateContentRequest($input: CreateContentRequestInput!) {
createContentRequest(input: $input) {
code
message
}
}

The input has four fields:

FieldRequiredDescription
id✅A UUID you generate. Also the idempotency key.
resourceType✅"product", "brand" or "manufacturer".
operation✅"create" or "update".
payload✅The resource fields. See the payload sections below.

⚠️ Important rules — please read​

  • Use only the field names listed for each resource. Do not invent fields — a request with any payload field that is not in the contract is automatically rejected with rejection reason unsupported_fields.
  • On create you must include every mandatory field (marked ✅ below).
  • On update send only the identifier (ean for a product, brand_id for a brand, manufacturer_id for a manufacturer) plus the fields you want to change.
  • A brand cannot exist without a manufacturer: a brand create requires manufacturer_id. If the manufacturer does not exist yet, create the manufacturer first with its own content request, wait for its approval, then create the brand.
  • A manufacturer create must NOT include manufacturer_id — sending one means an update.
  • Field names and shapes must match exactly (e.g. category_id, not main_category).

Errors​

When a content request is not accepted, the mutation does not return code/message — the response contains a GraphQL errors entry with extensions.code: "BAD_REQUEST" and a descriptive message:

{
"errors": [
{
"message": "There is already an identical pending content request",
"extensions": { "code": "BAD_REQUEST" }
}
],
"data": null
}

These are the most common rejections:

Product with EAN 4262493171667 already exists​

You sent a product create for an EAN that already belongs to a product of the catalog. The request is not created and it does not reach the review team, so you will not see it in sellerContentRequests.

  • If you want to change that product, send an update instead: operation: "update" with the ean plus the fields you want to change (see Update).
  • The message includes the EAN you sent, e.g. Product with EAN 4262493171667 already exists.
  • If you are sure the EAN is not in the catalog, reach out to the Marketplace Catalog Team (marktplatzkatalog@docmorris.de).

There is already an identical pending content request​

You already have a pending content request with the same resourceType, the same operation and an identical payload. The new request is not created.

  • Wait for the pending request to be reviewed, or change the payload if you actually want to submit something different.
  • This is different from resending the same id: resending an id you already used is idempotent and simply returns 202 Accepted without creating anything.

You have submitted too many changes for product 4262493171667 today​

You can submit one content request per resource per day (today is the calendar day in German time, Europe/Berlin). The resource is identified by the product EAN, the brand or the manufacturer, per resourceType — so on the same day you can still submit requests for other products, brands or manufacturers, or for the same EAN as a different resource type.

  • The message includes the resource type and identifier, e.g. You have submitted too many changes for brand Premium Healthcare today.
  • Requests that were automatically rejected (for example with rejection reason unsupported_video) do not count towards the limit: you can fix the payload and resubmit the same day.
  • If you hit the limit, batch your changes into a single request and resubmit the next day.

Product payload fields​

For resourceType: "product". The fields are grouped by what they affect: Product, Enrichment (descriptive texts) and Media. For brand and manufacturer requests see the Brand content requests and Manufacturer content requests sections below.

Product​

FieldRequired on createTypeAllowed values / notes
ean✅stringProduct EAN. Identifies the product.
product_name✅stringMust not contain dosage or size information
sales_type✅stringBPC or OTC
brand_id✅string (UUID)
manufacturer_id✅string (UUID)
category_id✅string (UUID)
vat✅arrayInform { vat_country, vat_type }. vat_type: for VAT 0% inform ZERO, for VAT 7% inform R1, for VAT 19% inform GENERAL
recommended_prices✅arrayInform { value, rrp_currency, rrp_origin }. For rrp_origin, the value must be entered in uppercase. If the value has been provided by an official source inform OFFICIAL, otherwise inform UNKNOWN
net_weight—numberValue in grams (gr)
net_volume—numberValue in millilitres (ml)
alternative_package_size_quantity—string
alternative_package_size_unit—stringcm, Fl, g, kg, l, m, mg, ml, P, Sp, St, µg, Set
alternative_dose_form—string
food_supplement—boolean
is_cosmetic_product—boolean
is_cbd—boolean
dangerous_goods—boolean
is_electronic_device—boolean
uses_batteries—boolean

Enrichment (descriptive texts — all optional)​

FieldTypeNotes
sub_headlinestringShort subtitle shown under the product name
marketingstringHTML allowed
how_to_usestringHTML allowed
compositionstringHTML allowed
advicestringHTML allowed
safety_informationstringHTML allowed
usp_onestringMax 150 characters
usp_twostringMax 150 characters
usp_threestringMax 150 characters
keywordsarray of stringsMax 15 keywords, 50 chars each

When you send a descriptive text (for example a sub_headline), its content source is recorded as marketplace.

Media (optional)​

medias is an array (up to 12 entries). If you include it, every item must have all three fields:

FieldRequired (per item)TypeAllowed values / notes
type✅stringimage, video, leaflet, biocide, lmiv
resource✅string (URL)Public URL we can download. For video, it must be a YouTube link (youtube.com, youtu.be or youtube-nocookie.com) or a Shopify link (cdn.shopify.com).
position✅integer0 = main image, 1–7 = additional images; non-image types use 0; only one video
Videos must be hosted on YouTube or Shopify

If a video entry points to any other host, the content request is automatically rejected with rejection reason unsupported_video. You will see it as REJECTED in the sellerContentRequests query.

IMPORTANT: image content sources and priority

Product images may be provided by different content sources. The content provided by the highest priority source will be the one selected and published. The content source priority is:

  1. Manufacturer (highest)
  2. Inhouse
  3. Marketplace Sellers
  4. Ixxilon
  5. Apopixx (lowest)

This means an image you submit (source Marketplace) is displayed as the main image only if no manufacturer or in-house image exists for the product.

Which image is currently displayed?​

Before submitting an image, check which image is published as the main image and where it comes from with the products query and its publishedMainImage field:

query MainImage($productEans: [String!]) {
products(productEans: $productEans) {
collection {
id
publishedMainImage {
url
source
}
}
}
}

publishedMainImage.source is one of MANUFACTURER, INHOUSE, MARKETPLACE, IXXILON, APOPIXX. If it is MANUFACTURER or INHOUSE, a new image sent through a content request will be stored but will not replace the published one. If it is MARKETPLACE, IXXILON, APOPIXX or null, your image can become the main image once approved.

Mandatory on create (quick summary)​

ean, product_name, sales_type, brand_id, manufacturer_id, category_id, vat (with a vat_type), recommended_prices (with value, rrp_currency). If you send medias, each item needs type, resource and position.

On update: only ean + the fields you change.

Examples​

Create​

mutation CreateContentRequest($input: CreateContentRequestInput!) {
createContentRequest(input: $input) {
code
message
}
}

Variables:

{
"input": {
"id": "b3f1c2a4-5d6e-4f70-8a91-2c3d4e5f6071",
"resourceType": "product",
"operation": "create",
"payload": {
"ean": "4262493171667",
"product_name": "supplenatura® Citicolin",
"sales_type": "BPC",
"brand_id": "507f5e47-363e-4206-a42c-c3cafb61a31c",
"manufacturer_id": "cd45a842-4f4d-4580-8e63-fb81100e95a6",
"category_id": "0c2a1b3c-4d5e-6f70-8a91-2c3d4e5f6071",
"vat": [
{ "vat_country": "DE", "vat_type": "GENERAL" }
],
"recommended_prices": [
{ "value": 29.99, "rrp_currency": "EUR", "rrp_origin": "OFFICIAL" }
],
"net_weight": 189,
"alternative_package_size_quantity": "540",
"alternative_package_size_unit": "St",
"alternative_dose_form": "Kapseln",
"food_supplement": true,
"is_cosmetic_product": false,
"is_cbd": false,
"dangerous_goods": false,
"is_electronic_device": false,
"uses_batteries": false,
"sub_headline": "Nahrungsergänzungsmittel mit Citicolin",
"marketing": "Citicolin – biochemisch bekannt als CDP-Cholin …",
"how_to_use": "Täglich 1 Kapsel mit Wasser einnehmen.",
"composition": "Citicolin (CDP-Cholin), Kapselhülle …",
"usp_one": "250 mg CDP-Cholin pro Kapsel",
"usp_two": "6 Monate Vorrat",
"usp_three": "Nur 2 Zutaten",
"keywords": ["Citicolin", "CDP-Cholin", "Citicoline Kapseln"],
"medias": [
{ "type": "image", "resource": "https://cdn.seller.com/citicolin/main.jpg", "position": 0 },
{ "type": "image", "resource": "https://cdn.seller.com/citicolin/front.jpg", "position": 1 },
{ "type": "video", "resource": "https://www.youtube.com/watch?v=aBcDeFgHiJk", "position": 0 },
{ "type": "leaflet", "resource": "https://cdn.seller.com/citicolin/otc.pdf", "position": 0 }
]
}
}
}

Update​

Send ean to identify the product, then only the fields you want to change:

{
"input": {
"id": "9b2d7e10-3a4b-4c5d-8e9f-1a2b3c4d5e6f",
"resourceType": "product",
"operation": "update",
"payload": {
"ean": "4262493171667",
"product_name": "supplenatura® Citicolin Kapseln",
"recommended_prices": [
{ "value": 27.99, "rrp_currency": "EUR", "rrp_origin": "OFFICIAL" }
]
}
}
}

Response​

{
"data": {
"createContentRequest": {
"code": 202,
"message": "Accepted"
}
}
}

Brand content requests​

Create​

Propose a new brand. Set resourceType: "brand" and operation: "create". A brand cannot exist without a manufacturer, so manufacturer_id is mandatory — if the manufacturer does not exist yet, create it first with its own content request.

FieldRequiredTypeNotes
brand_name✅stringThe name of the new brand.
manufacturer_id✅string (UUID)The brand's manufacturer. It must already exist.
brand_logo—string (URL)Public image URL (jpg, jpeg, png). Applied right after the brand is created.

Example​

{
"input": {
"id": "6c2c2509-8190-4c3e-9d4f-708192030415",
"resourceType": "brand",
"operation": "create",
"payload": {
"brand_name": "Premium Healthcare",
"manufacturer_id": "cd45a842-4f4d-4580-8e63-fb81100e95a6",
"brand_logo": "https://cdn.seller.com/brands/premium-healthcare.png"
}
}
}

Update​

Propose an update to an existing brand. Set resourceType: "brand" and operation: "update"; the brand is identified by brand_id. Send brand_id plus at least one field you want to change.

FieldRequiredTypeNotes
brand_id✅string (UUID)The brand to update.
brand_name—string
manufacturer_id—string (UUID)Link the brand to this manufacturer.
brand_logo—string (URL)Public image URL (jpg, jpeg, png). Send #DELETE# to remove it.

Example​

{
"input": {
"id": "3f7c1a90-2b4d-4e6f-8a01-b2c3d4e5f601",
"resourceType": "brand",
"operation": "update",
"payload": {
"brand_id": "44d9212d-0c27-4289-802e-4f07b6576694",
"brand_name": "Premium Healthcare",
"manufacturer_id": "cd45a842-4f4d-4580-8e63-fb81100e95a6",
"brand_logo": "https://cdn.seller.com/brands/premium-healthcare.png"
}
}
}

Manufacturer content requests​

Create​

Propose a new manufacturer. Set resourceType: "manufacturer" and operation: "create". Do not include manufacturer_id — the id is assigned when the request is approved (you can read it from affectedResourceId in sellerContentRequests). A manufacturer create must include its address: street, zip code, city, country and a contact email.

FieldRequiredTypeNotes
manufacturer_name✅stringThe name of the new manufacturer.
address_street✅stringe.g. Luise-Ullrich-Str
address_street_number—stringe.g. 20
address_zip_code✅stringe.g. 10789
address_city✅stringe.g. Berlin
address_country✅stringe.g. Germany
address_contact_person—stringe.g. Dr. Mueller
address_email✅stringe.g. berlin@isdin.com
address_phone_number—stringe.g. +49 30 12345678
address_website—stringe.g. https://www.isdin.com
address_imprint_url—stringe.g. https://www.isdin.com/de/kontakt

The address source is recorded as marketplace.

Example​

{
"input": {
"id": "8e4e472b-a3b2-4e50-9f61-920304152637",
"resourceType": "manufacturer",
"operation": "create",
"payload": {
"manufacturer_name": "ISDIN GmbH",
"address_street": "Luise-Ullrich-Str",
"address_street_number": "20",
"address_zip_code": "10789",
"address_city": "Berlin",
"address_country": "Germany",
"address_email": "berlin@isdin.com"
}
}
}

Update​

Propose an update to an existing manufacturer. Set resourceType: "manufacturer" and operation: "update"; the manufacturer is identified by manufacturer_id. Send manufacturer_id plus at least one field you want to change.

FieldRequiredTypeNotes
manufacturer_id✅string (UUID)The manufacturer to update.
manufacturer_name—string
address_street—string
address_street_number—string
address_zip_code—string
address_city—string
address_country—string
address_contact_person—string
address_email—string
address_phone_number—string
address_website—string
address_imprint_url—string

If you send any address_* field, the address source is recorded as marketplace.

Example​

{
"input": {
"id": "5b1b14f8-708f-4b2d-8c3e-6f7081920304",
"resourceType": "manufacturer",
"operation": "update",
"payload": {
"manufacturer_id": "0d780958-8176-4e20-8e8d-ce2af1a5dd32",
"manufacturer_name": "ISDIN GmbH",
"address_street": "Luise-Ullrich-Str",
"address_street_number": "20",
"address_zip_code": "10789",
"address_city": "Berlin",
"address_country": "Germany"
}
}
}

Checking your content requests​

Use the sellerContentRequests query to retrieve the content requests you have submitted, with their full detail in a single call — status, review date, rejection reason, the id of the product created on approval, the result of applying it in the catalog, and the original payload. There is no need to fetch each request of the list separately; when you only need one request, for example to refresh it right after creating it, use sellerContentRequest with its id.

query SellerContentRequests(
$status: ContentRequestStatus
$referenceCode: String
$referenceName: String
$resourceType: String
$page: Int
$size: Int
) {
sellerContentRequests(
status: $status
referenceCode: $referenceCode
referenceName: $referenceName
resourceType: $resourceType
sortDirection: DESC
page: $page
size: $size
) {
metadata {
totalItems
totalPages
currentPage
}
collection {
id
resourceType
operation
status
referenceCode
referenceName
requestDate
reviewDate
rejectionReason
rejectionReasonDetail
affectedResourceId
approvalResult
approvalResultDetail
payload
}
}
}

Arguments​

ArgumentRequiredDescription
status—Filter by status: PENDING, APPROVED or REJECTED. Omit to get all yours.
referenceCode—Contains match on the reference code (the EAN for product requests). Combinable with the other filters.
referenceName—Contains match on the reference name (the product name for product requests, the brand or manufacturer name otherwise).
resourceType—Only the requests of one kind of resource: product, brand or manufacturer. Omit to get every kind. Combinable with the other filters; totalItems and pagination reflect it.
sortDirection—ASC or DESC by request date (default DESC).
page—The page to fetch (default 1).
size—The page size.

Item fields​

FieldDescription
idThe content request id (the UUID you supplied on create).
operationCREATE or UPDATE.
statusPENDING, APPROVED or REJECTED.
referenceCodeThe resource identifier: product EAN, or brand_id / manufacturer_id.
referenceNameThe resource name: product name, or brand / manufacturer name.
requestDateWhen you submitted the request, formatted as YYYY-MM-DD HH:MM:SS in UTC (no timezone offset).
reviewDateWhen it was reviewed, same format and timezone as requestDate (null while pending).
rejectionReasonWhy it was rejected (only present when REJECTED). See Rejection reasons.
rejectionReasonDetailThe detail of the rejection. For unsupported_fields, the payload fields that are not part of the contract (empty otherwise).
affectedResourceIdThe id of the product, brand or manufacturer created/updated on approval (null otherwise).
approvalResultThe result of applying the approved request in the catalog: OK, OK_WARNING or KO. null until it has been applied. See Approval result.
approvalResultDetailThe errors found while applying the request. Only filled when approvalResult is OK_WARNING or KO (empty otherwise).
payloadThe payload exactly as you submitted it.

Example response​

{
"data": {
"sellerContentRequests": {
"metadata": { "totalItems": 2, "totalPages": 1, "currentPage": 1 },
"collection": [
{
"id": "b3f1c2a4-5d6e-4f70-8a91-2c3d4e5f6071",
"resourceType": "product",
"operation": "CREATE",
"status": "APPROVED",
"referenceCode": "4262493171667",
"referenceName": "supplenatura® Citicolin",
"requestDate": "2026-06-30 12:22:39",
"reviewDate": "2026-07-01 12:21:17",
"rejectionReason": null,
"rejectionReasonDetail": [],
"affectedResourceId": "c7f46fb9-b396-423c-90b6-d4cad26694cb",
"approvalResult": "OK_WARNING",
"approvalResultDetail": ["Invalid HTML content"],
"payload": { "ean": "4262493171667", "product_name": "supplenatura® Citicolin" }
}
]
}
}
}

Fetching a single content request​

Use the sellerContentRequest query to get one of your content requests by its id (the UUID you supplied on create), for example to refresh it right after creating it or to open its detail directly. It returns the same fields as each item of sellerContentRequests (see Item fields).

query SellerContentRequest($id: ID!) {
sellerContentRequest(id: $id) {
id
resourceType
operation
status
referenceCode
referenceName
requestDate
reviewDate
rejectionReason
rejectionReasonDetail
affectedResourceId
approvalResult
approvalResultDetail
payload
}
}
{
"data": {
"sellerContentRequest": {
"id": "b3f1c2a4-5d6e-4f70-8a91-2c3d4e5f6071",
"resourceType": "product",
"operation": "CREATE",
"status": "PENDING",
"referenceCode": "4262493171667",
"referenceName": "supplenatura® Citicolin",
"requestDate": "2026-06-30 12:22:39",
"reviewDate": null,
"rejectionReason": null,
"rejectionReasonDetail": [],
"affectedResourceId": null,
"approvalResult": null,
"approvalResultDetail": [],
"payload": { "ean": "4262493171667", "product_name": "supplenatura® Citicolin" }
}
}
}

You only ever get your own content requests. When the id does not exist, or it belongs to another seller, the query returns a NOT_FOUND error and sellerContentRequest is null:

{
"errors": [
{
"message": "The requested resource could not be found.",
"extensions": { "code": "NOT_FOUND" }
}
],
"data": { "sellerContentRequest": null }
}

Approval result​

An APPROVED request is then applied in the catalog. Some of its data may fail at that point, so APPROVED alone does not mean that all your content is published. Check approvalResult:

Approval resultDescription
OKThe request was applied completely.
OK_WARNINGThe request was applied, but part of its data could not be applied. See approvalResultDetail.
KOThe request could not be applied. See approvalResultDetail.

Fix the data listed in approvalResultDetail and submit a new content request.

Rejection reasons​

When a content request is REJECTED, the rejectionReason field tells you why:

Rejection reasonDescription
duplicated_requestThe same request has already been submitted by this or another seller.
incorrect_manufacturer_or_brandThe manufacturer and the brand informed do not match.
incorrect_categoryThe category informed does not match.
inconsistent_contentThe product's name, image and texts are not coherent.
wrong_languageThe content is not in German language.
bad_quality_imageThe image does not meet the minimum image quality requirements.
unsupported_videoThe video link does not belong to YouTube or Shopify.
unsupported_fieldsThe payload contains at least one field that is not part of the contract. The fields are listed in rejectionReasonDetail.
assortmentThe product does not fit/is inappropriate for the DocMorris assortment.
otherMost common: wrong recommended price, net weight/volume, alternative_package_size_quantity.
note

In case of doubt, reach out to the Marketplace Catalog Team (marktplatzkatalog@docmorris.de) and they will provide further details on rejections.