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
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": , "prep_minutes": 25, "option_groups": [ { "id": "proteina", "required": , "min": 1, "max": 1, "options": [{ "id": "peixe", "price_delta_minor": 0 }, { "id": "carne", "price_delta_minor": 500 }] } ] } ] }'Why an offer is refused
| code | What to change |
|---|---|
| price_not_minor_units | The price looks like a major-unit amount. 30 in Bissau is 30 FCFA, which is almost certainly wrong. |
| missing_required_modifier | A required group arrived with no selectable option. Either give it options or make it optional. |
| currency_not_market | The offer's currency is not the store's market currency. |
| unknown_merchant | Your 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
{ "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": }, { "external_id": "POS-1004", "code": "missing_photo", "blocking": } ]}