Production is locked until a market agreement is recorded

Catalogue sync

Push offers, prices and availability from a POS, and read back exactly which offer was refused and why.

Commerce7 min

Catalogue pushes are a merge, not a replace: an offer you do not send is left alone. Deleting is explicit, because an integration that drops a row by accident should not empty a store's menu.

Pushing offers

POST /v1/catalog/offers
curl https://api.palopgo.com/v1/catalog/offers \  -H "Authorization: Bearer $PALOPGO_KEY" \  -H "Idempotency-Key: cmd_pos_2026w41_03" \  -d '{    "merchant_id": "m-gw-001",    "currency": "XOF",    "offers": [      {        "external_id": "POS-1001",        "name_pt": "Caldo de chabéu com arroz",        "name_en": "Chabéu palm-oil stew with rice",        "price_minor": 3000,        "available": true,        "prep_minutes": 25,        "option_groups": [          { "id": "proteina", "required": true, "min": 1, "max": 1,            "options": [{ "id": "peixe", "price_delta_minor": 0 }, { "id": "carne", "price_delta_minor": 500 }] }        ]      }    ]  }'

Why an offer is refused

Rejection codes and the fix
codeWhat to change
price_not_minor_unitsThe price looks like a major-unit amount. 30 in Bissau is 30 FCFA, which is almost certainly wrong.
missing_required_modifierA required group arrived with no selectable option. Either give it options or make it optional.
currency_not_marketThe offer's currency is not the store's market currency.
unknown_merchantYour key is not scoped to that store, or the id is from another environment.

Photographs

An offer without a photograph is accepted and shows a placeholder tile. Send a URL we can fetch once; we resize and serve it ourselves so a store's menu still loads on a 2G connection in Mafalala.

Checking the state of a store

GET /v1/catalog/sync/m-gw-001
{  "merchant_id": "m-gw-001",  "last_push_at": "2026-10-07T11:12:40+00:00",  "offers": 6,  "rejected": 1,  "warnings": 2,  "issues": [    { "external_id": "POS-1009", "code": "missing_required_modifier", "blocking": true },    { "external_id": "POS-1004", "code": "missing_photo", "blocking": false }  ]}

Keep going