{
    "meta": {
        "schema": 1,
        "git_sha": "1d18d3d5795fd5835cb056cfbd1a87d66213192bf3a943ec282c2464bd29a3c2",
        "doc_url": "https://api.usequeek.com/docs/capabilities.json"
    },
    "primitives": {
        "api_scopes": {
            "source": "The Merchant API operation table that the scopes page is generated from.",
            "non_delegable_prefixes": [
                "merchant-api_keys-",
                "merchant-roles-",
                "merchant-users-",
                "merchant-employees-",
                "merchant-partners-",
                "merchant-pos-",
                "merchant-apps-",
                "merchant-items-update-all",
                "merchant-settings-payments-"
            ],
            "resources": [
                {
                    "resource": "analytics",
                    "scopes": [
                        {
                            "scope": "merchant-analytics-customers-read",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "customers_read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "analytics.retrieve_customers"
                            ]
                        },
                        {
                            "scope": "merchant-analytics-products-read",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "products_read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "analytics.retrieve_products"
                            ]
                        },
                        {
                            "scope": "merchant-analytics-sales-read",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "sales_read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "analytics.retrieve_sales"
                            ]
                        },
                        {
                            "scope": "merchant-analytics-traffic-read",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "traffic_read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "analytics.retrieve_traffic"
                            ]
                        }
                    ]
                },
                {
                    "resource": "app",
                    "scopes": [
                        {
                            "scope": "merchant-app-requirements-write",
                            "methods": [
                                "PUT"
                            ],
                            "verbs": [
                                "requirements_write"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "app.line_inputs_write",
                                "app.requirements_write"
                            ]
                        }
                    ]
                },
                {
                    "resource": "app_alerts",
                    "scopes": [
                        {
                            "scope": "merchant-app_alerts-create",
                            "methods": [
                                "POST"
                            ],
                            "verbs": [
                                "create"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "app.alerts_create"
                            ]
                        }
                    ]
                },
                {
                    "resource": "app_setup",
                    "scopes": [
                        {
                            "scope": "merchant-app_setup-update",
                            "methods": [
                                "PUT"
                            ],
                            "verbs": [
                                "update"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "app.setup_update"
                            ]
                        }
                    ]
                },
                {
                    "resource": "business_profile",
                    "scopes": [
                        {
                            "scope": "merchant-business_profile-read",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "store.retrieve"
                            ]
                        }
                    ]
                },
                {
                    "resource": "checkouts",
                    "scopes": [
                        {
                            "scope": "merchant-checkouts-read",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "checkouts.list_abandoned"
                            ]
                        }
                    ]
                },
                {
                    "resource": "collected",
                    "scopes": [
                        {
                            "scope": "merchant-collected-definitions-manage",
                            "methods": [
                                "GET",
                                "PATCH",
                                "POST"
                            ],
                            "verbs": [
                                "definitions_manage"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "app.collected_definitions_create",
                                "app.collected_definitions_list",
                                "app.collected_definitions_update"
                            ]
                        },
                        {
                            "scope": "merchant-collected-records-read",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "records_read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "app.records_list",
                                "app.records_show"
                            ]
                        },
                        {
                            "scope": "merchant-collected-records-submit",
                            "methods": [
                                "POST"
                            ],
                            "verbs": [
                                "records_submit"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "app.records_submit"
                            ]
                        },
                        {
                            "scope": "merchant-collected-records-update",
                            "methods": [
                                "PATCH"
                            ],
                            "verbs": [
                                "records_update"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "app.records_update"
                            ]
                        }
                    ]
                },
                {
                    "resource": "collections",
                    "scopes": [
                        {
                            "scope": "merchant-collections-create",
                            "methods": [
                                "POST"
                            ],
                            "verbs": [
                                "create"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "collections.bulk_create"
                            ]
                        },
                        {
                            "scope": "merchant-collections-read",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "collections.list"
                            ]
                        },
                        {
                            "scope": "merchant-collections-update",
                            "methods": [
                                "POST"
                            ],
                            "verbs": [
                                "update"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "collections.pin_product",
                                "collections.reorder_products"
                            ]
                        }
                    ]
                },
                {
                    "resource": "conversations",
                    "scopes": [
                        {
                            "scope": "merchant-conversations-read",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "conversations.list",
                                "conversations.list_messages",
                                "conversations.retrieve"
                            ]
                        },
                        {
                            "scope": "merchant-conversations-reply",
                            "methods": [
                                "POST"
                            ],
                            "verbs": [
                                "reply"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "conversations.reply"
                            ]
                        },
                        {
                            "scope": "merchant-conversations-update",
                            "methods": [
                                "POST"
                            ],
                            "verbs": [
                                "update"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "conversations.mark_read"
                            ]
                        }
                    ]
                },
                {
                    "resource": "coupons",
                    "scopes": [
                        {
                            "scope": "merchant-coupons-create",
                            "methods": [
                                "POST"
                            ],
                            "verbs": [
                                "create"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "coupons.create"
                            ]
                        },
                        {
                            "scope": "merchant-coupons-read",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "coupons.list"
                            ]
                        },
                        {
                            "scope": "merchant-coupons-update",
                            "methods": [
                                "PATCH"
                            ],
                            "verbs": [
                                "update"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "coupons.update"
                            ]
                        }
                    ]
                },
                {
                    "resource": "customer",
                    "scopes": [
                        {
                            "scope": "merchant-customer-segments-create",
                            "methods": [
                                "POST"
                            ],
                            "verbs": [
                                "segments_create"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "customer_segments.create"
                            ]
                        },
                        {
                            "scope": "merchant-customer-segments-delete",
                            "methods": [
                                "DELETE"
                            ],
                            "verbs": [
                                "segments_delete"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "customer_segments.delete"
                            ]
                        },
                        {
                            "scope": "merchant-customer-segments-read",
                            "methods": [
                                "GET",
                                "POST"
                            ],
                            "verbs": [
                                "segments_read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "customer_segments.list",
                                "customer_segments.preview",
                                "customer_segments.retrieve"
                            ]
                        },
                        {
                            "scope": "merchant-customer-segments-update",
                            "methods": [
                                "PATCH"
                            ],
                            "verbs": [
                                "segments_update"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "customer_segments.update"
                            ]
                        }
                    ]
                },
                {
                    "resource": "customers",
                    "scopes": [
                        {
                            "scope": "merchant-customers-consent-update",
                            "methods": [
                                "POST"
                            ],
                            "verbs": [
                                "consent_update"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "customers.update_email_marketing_consent"
                            ]
                        },
                        {
                            "scope": "merchant-customers-detail",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "detail"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "customers.list_wishlist_items",
                                "customers.retrieve"
                            ]
                        },
                        {
                            "scope": "merchant-customers-read",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "customers.list",
                                "customers.list_followers"
                            ]
                        },
                        {
                            "scope": "merchant-customers-sms-consent-update",
                            "methods": [
                                "POST"
                            ],
                            "verbs": [
                                "sms_consent_update"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "customers.update_sms_marketing_consent"
                            ]
                        }
                    ]
                },
                {
                    "resource": "discounts",
                    "scopes": [
                        {
                            "scope": "merchant-discounts-create",
                            "methods": [
                                "POST"
                            ],
                            "verbs": [
                                "create"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "discounts.create"
                            ]
                        },
                        {
                            "scope": "merchant-discounts-detail",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "detail"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "discounts.retrieve"
                            ]
                        },
                        {
                            "scope": "merchant-discounts-read",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "discounts.list"
                            ]
                        },
                        {
                            "scope": "merchant-discounts-update",
                            "methods": [
                                "PATCH",
                                "POST"
                            ],
                            "verbs": [
                                "update"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "discounts.publish",
                                "discounts.unpublish",
                                "discounts.update"
                            ]
                        }
                    ]
                },
                {
                    "resource": "exports",
                    "scopes": [
                        {
                            "scope": "merchant-exports-create",
                            "methods": [
                                "POST"
                            ],
                            "verbs": [
                                "create"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "exports.create"
                            ]
                        },
                        {
                            "scope": "merchant-exports-read",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "exports.get"
                            ]
                        }
                    ]
                },
                {
                    "resource": "inventory",
                    "scopes": [
                        {
                            "scope": "merchant-inventory-detail",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "detail"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "inventory.history"
                            ]
                        },
                        {
                            "scope": "merchant-inventory-read",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "inventory.levels",
                                "inventory.low_stock",
                                "inventory.out_of_stock",
                                "inventory.overview"
                            ]
                        },
                        {
                            "scope": "merchant-inventory-update",
                            "methods": [
                                "POST"
                            ],
                            "verbs": [
                                "update"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "inventory.adjust_level",
                                "inventory.create_adjustment"
                            ]
                        }
                    ]
                },
                {
                    "resource": "items",
                    "scopes": [
                        {
                            "scope": "merchant-items-create",
                            "methods": [
                                "POST"
                            ],
                            "verbs": [
                                "create"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "products.create"
                            ]
                        },
                        {
                            "scope": "merchant-items-delete",
                            "methods": [
                                "DELETE"
                            ],
                            "verbs": [
                                "delete"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "products.delete"
                            ]
                        },
                        {
                            "scope": "merchant-items-detail",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "detail"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "images.list",
                                "products.retrieve",
                                "variants.list"
                            ]
                        },
                        {
                            "scope": "merchant-items-read",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "products.list",
                                "products.search"
                            ]
                        },
                        {
                            "scope": "merchant-items-update",
                            "methods": [
                                "DELETE",
                                "PATCH",
                                "POST",
                                "PUT"
                            ],
                            "verbs": [
                                "update"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "images.create",
                                "images.delete",
                                "images.update",
                                "products.publish",
                                "products.update",
                                "variants.create",
                                "variants.delete",
                                "variants.update"
                            ]
                        }
                    ]
                },
                {
                    "resource": "locales",
                    "scopes": [
                        {
                            "scope": "merchant-locales-read",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "locales.list"
                            ]
                        },
                        {
                            "scope": "merchant-locales-write",
                            "methods": [
                                "DELETE",
                                "PATCH",
                                "POST"
                            ],
                            "verbs": [
                                "write"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "locales.create",
                                "locales.delete",
                                "locales.set_default",
                                "locales.update"
                            ]
                        }
                    ]
                },
                {
                    "resource": "media",
                    "scopes": [
                        {
                            "scope": "merchant-media-create",
                            "methods": [
                                "POST"
                            ],
                            "verbs": [
                                "create"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "files.create"
                            ]
                        },
                        {
                            "scope": "merchant-media-delete",
                            "methods": [
                                "DELETE"
                            ],
                            "verbs": [
                                "delete"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "files.delete"
                            ]
                        },
                        {
                            "scope": "merchant-media-read",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "files.list",
                                "files.references"
                            ]
                        },
                        {
                            "scope": "merchant-media-update",
                            "methods": [
                                "PATCH"
                            ],
                            "verbs": [
                                "update"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "files.update"
                            ]
                        }
                    ]
                },
                {
                    "resource": "metafields",
                    "scopes": [
                        {
                            "scope": "merchant-metafields-create",
                            "methods": [
                                "POST"
                            ],
                            "verbs": [
                                "create"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "metafields.create_definition"
                            ]
                        },
                        {
                            "scope": "merchant-metafields-read",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "metafields.list_definitions"
                            ]
                        }
                    ]
                },
                {
                    "resource": "metaobjects",
                    "scopes": [
                        {
                            "scope": "merchant-metaobjects-create",
                            "methods": [
                                "POST"
                            ],
                            "verbs": [
                                "create"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "metaobjects.create",
                                "metaobjects.create_definition"
                            ]
                        },
                        {
                            "scope": "merchant-metaobjects-read",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "metaobjects.list",
                                "metaobjects.list_definitions"
                            ]
                        }
                    ]
                },
                {
                    "resource": "options",
                    "scopes": [
                        {
                            "scope": "merchant-options-create",
                            "methods": [
                                "POST"
                            ],
                            "verbs": [
                                "create"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "addons.create"
                            ]
                        },
                        {
                            "scope": "merchant-options-delete",
                            "methods": [
                                "DELETE"
                            ],
                            "verbs": [
                                "delete"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "addons.delete"
                            ]
                        },
                        {
                            "scope": "merchant-options-detail",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "detail"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "addons.retrieve"
                            ]
                        },
                        {
                            "scope": "merchant-options-read",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "addons.list"
                            ]
                        },
                        {
                            "scope": "merchant-options-update",
                            "methods": [
                                "DELETE",
                                "PATCH",
                                "POST"
                            ],
                            "verbs": [
                                "update"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "addons.attach",
                                "addons.detach",
                                "addons.update"
                            ]
                        }
                    ]
                },
                {
                    "resource": "orders",
                    "scopes": [
                        {
                            "scope": "merchant-orders-create",
                            "methods": [
                                "POST"
                            ],
                            "verbs": [
                                "create"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "orders.create"
                            ]
                        },
                        {
                            "scope": "merchant-orders-import",
                            "methods": [
                                "POST"
                            ],
                            "verbs": [
                                "import"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "orders.import"
                            ]
                        },
                        {
                            "scope": "merchant-orders-read",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "orders.list",
                                "orders.retrieve"
                            ]
                        },
                        {
                            "scope": "merchant-orders-refund-create",
                            "methods": [
                                "POST"
                            ],
                            "verbs": [
                                "refund_create"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "orders.refund"
                            ]
                        },
                        {
                            "scope": "merchant-orders-status-update",
                            "methods": [
                                "POST"
                            ],
                            "verbs": [
                                "status_update"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "orders.assign_rider",
                                "orders.update_status"
                            ]
                        },
                        {
                            "scope": "merchant-orders-update",
                            "methods": [
                                "PATCH"
                            ],
                            "verbs": [
                                "update"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "orders.update",
                                "orders.update_shipment"
                            ]
                        }
                    ]
                },
                {
                    "resource": "pages",
                    "scopes": [
                        {
                            "scope": "merchant-pages-create",
                            "methods": [
                                "POST"
                            ],
                            "verbs": [
                                "create"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "pages.create"
                            ]
                        },
                        {
                            "scope": "merchant-pages-delete",
                            "methods": [
                                "DELETE"
                            ],
                            "verbs": [
                                "delete"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "pages.delete"
                            ]
                        },
                        {
                            "scope": "merchant-pages-detail",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "detail"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "pages.get"
                            ]
                        },
                        {
                            "scope": "merchant-pages-read",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "pages.list"
                            ]
                        },
                        {
                            "scope": "merchant-pages-update",
                            "methods": [
                                "PATCH"
                            ],
                            "verbs": [
                                "update"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "pages.update"
                            ]
                        }
                    ]
                },
                {
                    "resource": "payout",
                    "scopes": [
                        {
                            "scope": "merchant-payout-batches-read",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "batches_read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "payouts.list",
                                "payouts.retrieve"
                            ]
                        },
                        {
                            "scope": "merchant-payout-ledger-read",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "ledger_read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "payout_transactions.list",
                                "payout_transactions.retrieve"
                            ]
                        }
                    ]
                },
                {
                    "resource": "posts",
                    "scopes": [
                        {
                            "scope": "merchant-posts-create",
                            "methods": [
                                "POST"
                            ],
                            "verbs": [
                                "create"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "posts.create"
                            ]
                        },
                        {
                            "scope": "merchant-posts-delete",
                            "methods": [
                                "DELETE"
                            ],
                            "verbs": [
                                "delete"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "posts.delete"
                            ]
                        },
                        {
                            "scope": "merchant-posts-detail",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "detail"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "posts.get"
                            ]
                        },
                        {
                            "scope": "merchant-posts-read",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "posts.list"
                            ]
                        },
                        {
                            "scope": "merchant-posts-update",
                            "methods": [
                                "PUT"
                            ],
                            "verbs": [
                                "update"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "posts.update"
                            ]
                        }
                    ]
                },
                {
                    "resource": "product_reviews",
                    "scopes": [
                        {
                            "scope": "merchant-product_reviews-moderate",
                            "methods": [
                                "PATCH"
                            ],
                            "verbs": [
                                "moderate"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "product_reviews.moderate"
                            ]
                        },
                        {
                            "scope": "merchant-product_reviews-read",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "product_reviews.list",
                                "product_reviews.retrieve"
                            ]
                        },
                        {
                            "scope": "merchant-product_reviews-respond",
                            "methods": [
                                "POST"
                            ],
                            "verbs": [
                                "respond"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "product_reviews.respond"
                            ]
                        }
                    ]
                },
                {
                    "resource": "publications",
                    "scopes": [
                        {
                            "scope": "merchant-publications-create",
                            "methods": [
                                "POST"
                            ],
                            "verbs": [
                                "create"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "publications.create"
                            ]
                        },
                        {
                            "scope": "merchant-publications-read",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "publications.list"
                            ]
                        },
                        {
                            "scope": "merchant-publications-update",
                            "methods": [
                                "PATCH"
                            ],
                            "verbs": [
                                "update"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "publications.update_resources"
                            ]
                        }
                    ]
                },
                {
                    "resource": "purchase_orders",
                    "scopes": [
                        {
                            "scope": "merchant-purchase_orders-create",
                            "methods": [
                                "POST"
                            ],
                            "verbs": [
                                "create"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "purchase_orders.create"
                            ]
                        },
                        {
                            "scope": "merchant-purchase_orders-detail",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "detail"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "purchase_orders.retrieve"
                            ]
                        },
                        {
                            "scope": "merchant-purchase_orders-read",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "purchase_orders.list"
                            ]
                        },
                        {
                            "scope": "merchant-purchase_orders-update",
                            "methods": [
                                "POST"
                            ],
                            "verbs": [
                                "update"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "purchase_orders.receive"
                            ]
                        }
                    ]
                },
                {
                    "resource": "reviews",
                    "scopes": [
                        {
                            "scope": "merchant-reviews-import",
                            "methods": [
                                "POST"
                            ],
                            "verbs": [
                                "import"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "reviews.import"
                            ]
                        },
                        {
                            "scope": "merchant-reviews-read",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "reviews.list_imported"
                            ]
                        }
                    ]
                },
                {
                    "resource": "shipping",
                    "scopes": [
                        {
                            "scope": "merchant-shipping-create",
                            "methods": [
                                "POST"
                            ],
                            "verbs": [
                                "create"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "shipping_zones.create"
                            ]
                        },
                        {
                            "scope": "merchant-shipping-read",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "shipping_zones.list"
                            ]
                        },
                        {
                            "scope": "merchant-shipping-update",
                            "methods": [
                                "PUT"
                            ],
                            "verbs": [
                                "update"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "shipping_zones.update"
                            ]
                        }
                    ]
                },
                {
                    "resource": "stock_adjustments",
                    "scopes": [
                        {
                            "scope": "merchant-stock_adjustments-read",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "inventory.list_adjustments"
                            ]
                        }
                    ]
                },
                {
                    "resource": "suppliers",
                    "scopes": [
                        {
                            "scope": "merchant-suppliers-read",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "suppliers.list"
                            ]
                        }
                    ]
                },
                {
                    "resource": "taxes",
                    "scopes": [
                        {
                            "scope": "merchant-taxes-create",
                            "methods": [
                                "POST"
                            ],
                            "verbs": [
                                "create"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "taxes.create"
                            ]
                        },
                        {
                            "scope": "merchant-taxes-read",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "taxes.list",
                                "taxes.retrieve"
                            ]
                        },
                        {
                            "scope": "merchant-taxes-update",
                            "methods": [
                                "PATCH"
                            ],
                            "verbs": [
                                "update"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "taxes.update"
                            ]
                        }
                    ]
                },
                {
                    "resource": "team",
                    "scopes": [
                        {
                            "scope": "merchant-team-directory-read",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "directory_read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "team.list"
                            ]
                        }
                    ]
                },
                {
                    "resource": "translations",
                    "scopes": [
                        {
                            "scope": "merchant-translations-read",
                            "methods": [
                                "GET"
                            ],
                            "verbs": [
                                "read"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "translatable_resources.list",
                                "translatable_resources.retrieve"
                            ]
                        },
                        {
                            "scope": "merchant-translations-write",
                            "methods": [
                                "DELETE",
                                "PUT"
                            ],
                            "verbs": [
                                "write"
                            ],
                            "delegable": true,
                            "optional_capable": true,
                            "operations": [
                                "translations.delete",
                                "translations.update"
                            ]
                        }
                    ]
                }
            ]
        },
        "webhook_topics": [
            "orders/create",
            "orders/paid",
            "orders/updated",
            "orders/fulfilled",
            "orders/cancelled",
            "products/create",
            "products/update",
            "products/delete",
            "customers/create",
            "customers/update",
            "customers/delete",
            "customers/data_request",
            "customers/redact",
            "customers_email_marketing_consent/update",
            "customers_marketing_consent/update",
            "inventory_levels/update",
            "locales/create",
            "locales/update",
            "locales/destroy",
            "translations/update",
            "translations/delete",
            "checkouts/create",
            "checkouts/update",
            "refunds/create",
            "conversation_messages/create"
        ],
        "storefront_extensions": {
            "block_targets": [
                "product"
            ],
            "block_types": [
                "app_block",
                "app_embed"
            ],
            "embed_targets": [
                "body"
            ],
            "embed_capabilities": [
                "chat-bubble",
                "banner",
                "popup",
                "scroll-top"
            ],
            "field_primitives": [
                "date",
                "time",
                "select"
            ],
            "line_input_primitives": [
                "line_text"
            ],
            "line_text_limits": {
                "max_length": 500,
                "default_max_length": 100,
                "fields_per_manifest": 3,
                "property_key_max_length": 64
            },
            "available_if": [
                "declared_products"
            ]
        },
        "dashboard": {
            "targets": [
                "order-details",
                "product-details",
                "order-print"
            ],
            "block_targets": [
                "order-details",
                "product-details"
            ],
            "action_targets": [
                "order-details"
            ],
            "print_targets": [
                "order-print"
            ],
            "action_effects": [
                "order_appointment"
            ],
            "field_primitives": [
                "date",
                "time",
                "select",
                "text",
                "slot-list"
            ],
            "when_fields": [
                "order.has_appointment",
                "order.is_paid",
                "product.has_files"
            ]
        },
        "manifest": {
            "top_level_keys": [
                "slug",
                "name",
                "description",
                "icon",
                "developer",
                "version",
                "distribution",
                "category",
                "tagline",
                "description_long",
                "highlights",
                "logo_url",
                "pricing",
                "developer_url",
                "privacy_url",
                "support_url",
                "demo_url",
                "video_url",
                "scopes",
                "optional_scopes",
                "webhook_topics",
                "settings",
                "install_url",
                "uninstall_url",
                "settings_url",
                "webhook_url",
                "extensions",
                "dashboard",
                "payment_provider"
            ],
            "count_caps": {
                "extensions_blocks": 10,
                "extensions_nav": 10,
                "extensions_embeds": 3,
                "dashboard_blocks": 10,
                "dashboard_actions": 10,
                "dashboard_print": 5,
                "schema_fields": 12,
                "print_fields": 20,
                "select_options": 50,
                "highlights": 5
            },
            "string_limits": {
                "name": 120,
                "developer": 120,
                "field_label": 120,
                "option": 120,
                "tagline": 80,
                "pricing_note": 80,
                "block_title": 80,
                "print_label": 80,
                "description": 2000,
                "description_long": 2000,
                "highlight": 90,
                "icon": 64,
                "media_id": 64,
                "version": 32,
                "key": 64,
                "help": 500,
                "block_description": 500,
                "nav_label": 40,
                "embed_title": 80,
                "url": 2048
            },
            "setting_types": [
                "string",
                "secret",
                "number",
                "boolean",
                "select"
            ],
            "pricing_models": [
                "free",
                "free_trial",
                "paid"
            ]
        },
        "handoff_event_types": [
            "app/installed",
            "app/uninstalled",
            "app/resync",
            "app/scopes_update",
            "app/settings_updated"
        ],
        "app_credential_endpoints": [
            {
                "method": "GET",
                "uri": "api/v1/apps/installations",
                "name": "apps.installations.index"
            },
            {
                "method": "POST",
                "uri": "api/v1/apps/installations/{installation}/access_tokens",
                "name": "apps.installations.access-tokens.store"
            },
            {
                "method": "POST",
                "uri": "api/v1/apps/installations/{installation}/resync",
                "name": "apps.installations.resync"
            },
            {
                "method": "POST",
                "uri": "api/v1/apps/installations/{installation}/scopes/revoke",
                "name": "apps.installations.scopes.revoke"
            }
        ],
        "app_proxy": {
            "methods": [
                "GET",
                "POST"
            ],
            "uri": "api/v1/client/apps/{appSlug}/{path}",
            "max_bytes": 262144,
            "connect_timeout_seconds": 3,
            "timeout_seconds": 5,
            "signature_skew_seconds": 300,
            "per_minute": 120,
            "share_customer_id_kill_switch": "apps.proxy_share_customer_id_enabled",
            "post": {
                "manifest_key": "extensions.proxy.allow_post",
                "content_type": "application/json",
                "max_bytes": 65536,
                "per_minute": 20,
                "per_minute_install": 600,
                "kill_switch": "apps.proxy_post_enabled",
                "signed_params": [
                    "method",
                    "body_sha256",
                    "idempotency_key"
                ],
                "relayed_statuses": [
                    200,
                    201,
                    202,
                    204,
                    400,
                    409,
                    422
                ]
            }
        },
        "session_token": {
            "ttl_seconds": 60,
            "skew_seconds": 20,
            "mint_per_minute": 30
        },
        "installation_token": {
            "ttl_seconds": 3600,
            "slots": 2,
            "mint_per_minute": 6500
        },
        "app_jwt": {
            "max_lifetime_seconds": 600,
            "skew_seconds": 120
        },
        "throttles": {
            "app_list_per_minute": 120,
            "app_resync_per_minute": 30,
            "app_failure_per_minute": 60,
            "app_resync_cooldown_seconds": 3600,
            "app_store_per_vendor_per_minute": 10,
            "app_store_per_ip_per_minute": 30,
            "proxy_per_minute": 120,
            "dashboard_list_per_minute": 60,
            "dashboard_block_per_minute": 120,
            "dashboard_action_per_minute": 30,
            "dashboard_print_per_minute": 30
        },
        "error_codes": [
            "ai_unavailable_in_test_mode",
            "api_key_expired",
            "api_key_mode_mismatch",
            "api_key_revoked",
            "app_embed_not_ready",
            "app_grant_insufficient",
            "app_handoff_failed",
            "app_installation_gone",
            "app_installation_pending",
            "app_ip_not_allowed",
            "app_proxy_failed",
            "app_proxy_gone",
            "app_token_revoked",
            "bad_request",
            "bank_unverifiable",
            "bank_unverified",
            "channel_gateway_unreachable",
            "client_key_required",
            "conflict",
            "custom_domain_provisioning_failed",
            "custom_gateway_forbidden",
            "custom_gateway_kyc_required",
            "custom_gateway_not_configured",
            "custom_gateway_not_verified",
            "custom_gateway_plan_required",
            "custom_gateway_store_ineligible",
            "custom_gateway_verification_failed",
            "delivery_location_unserved",
            "forbidden",
            "gone",
            "idempotency_key_in_progress",
            "idempotency_key_required",
            "idempotency_key_reuse",
            "insufficient_scope",
            "invalid_client",
            "invalid_client_key",
            "invalid_pin",
            "invalid_refund_amount",
            "messaging_window_closed",
            "metafield_definition_missing",
            "metafield_filter_unsupported_type",
            "metafield_namespace_reserved",
            "metafield_value_invalid",
            "metaobject_definition_missing",
            "metaobject_field_invalid",
            "metaobject_reference_invalid",
            "metaobject_type_reserved",
            "method_not_allowed",
            "not_found",
            "nothing_to_refund",
            "order_not_refundable",
            "origin_not_allowed",
            "origin_required",
            "otp_required",
            "payload_too_large",
            "payment_amount_mismatch",
            "payment_method_unavailable",
            "payout_hold",
            "pin_required",
            "plan_inactive",
            "private_key_required",
            "refund_amount_below_minimum",
            "refund_amount_exceeds_refundable",
            "refund_line_invalid",
            "refund_payment_not_found",
            "refund_provider_unavailable",
            "refund_provider_unsupported",
            "refunds_disabled",
            "requires_line_text",
            "requires_slot",
            "resync_cooldown",
            "route_not_available",
            "server_error",
            "service_unavailable",
            "store_build_gated",
            "store_region_missing",
            "subscription_feature_locked",
            "too_many_requests",
            "transaction_pin_required",
            "translation_digest_stale",
            "translation_locale_is_default",
            "translation_locale_is_primary",
            "translation_locale_not_published",
            "translation_max_published_locales",
            "translation_unknown_key",
            "translation_unknown_locale",
            "unauthenticated",
            "unknown_product_ref",
            "unknown_service",
            "unknown_variant_ref",
            "unsupported_media_type",
            "validation_failed",
            "variant_required",
            "vendor_access_denied",
            "vendor_mail_sender_forbidden",
            "vendor_mail_sender_key_unavailable",
            "vendor_mail_sender_not_configured",
            "vendor_mail_sender_plan_required",
            "vendor_mail_sender_verification_failed"
        ]
    },
    "needs": [
        {
            "id": "auth.app_jwt",
            "area": "auth",
            "title": "App-credential API",
            "summary": "Third-party servers authenticate with a short-lived signed app token to list installations, mint installation tokens and resync.",
            "status": "supported",
            "surface": [
                {
                    "kind": "route",
                    "name": "GET api/v1/apps/installations"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/apps/installations/{installation}/access_tokens"
                }
            ],
            "limits": [
                "Per-app throttle after verify; per-IP failure bucket before verify."
            ],
            "workaround": "",
            "tags": [
                "auth",
                "app-api"
            ],
            "design_note": ""
        },
        {
            "id": "auth.handoffs",
            "area": "auth",
            "title": "Install lifecycle handoffs",
            "summary": "Signed server-to-server install, uninstall, resync, settings and scope-change events to the app URLs. Answer first, then verify: a proof call inside the handoff deadlocks. The uninstalled handoff carries data.reason store_deleted when the whole store is deleted; a merchant uninstall sends no reason.",
            "status": "supported",
            "surface": [
                {
                    "kind": "handoff",
                    "name": "app/installed"
                },
                {
                    "kind": "handoff",
                    "name": "app/uninstalled"
                },
                {
                    "kind": "handoff",
                    "name": "app/resync"
                },
                {
                    "kind": "handoff",
                    "name": "app/scopes_update"
                },
                {
                    "kind": "handoff",
                    "name": "app/settings_updated"
                }
            ],
            "limits": [
                "Bounded by the handoff timeout; installations flip active only after the app answers success.",
                "Delivery of the uninstalled handoff is queued and retried with backoff, and a store deletion does not wait for the app to answer."
            ],
            "workaround": "",
            "tags": [
                "auth",
                "lifecycle",
                "handoffs"
            ],
            "design_note": ""
        },
        {
            "id": "auth.optional_scopes",
            "area": "auth",
            "title": "Optional scopes (request at runtime)",
            "summary": "Install grants required scopes only; optional scopes are requested after install, approved or declined by the merchant, revocable by the app, and announced over the signed scope-change handoff.",
            "status": "supported",
            "surface": [
                {
                    "kind": "manifest",
                    "name": "optional_scopes"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/biz/vendor/app-store/{slug}/scopes/approve"
                }
            ],
            "limits": [
                "Required scopes are never revocable; the merchant remedy is uninstall."
            ],
            "workaround": "",
            "tags": [
                "auth",
                "scopes"
            ],
            "design_note": ""
        },
        {
            "id": "auth.session",
            "area": "auth",
            "title": "Embedded session tokens",
            "summary": "Short-lived signed tokens per installation and user for framed pages. There are no refresh tokens; the app fetches a fresh token per need.",
            "status": "supported",
            "surface": [
                {
                    "kind": "config",
                    "name": "apps.session_token_ttl"
                }
            ],
            "limits": [
                "Fetch a fresh token per need; replay window is bounded and documented."
            ],
            "workaround": "",
            "tags": [
                "auth",
                "embedded"
            ],
            "design_note": ""
        },
        {
            "id": "b2b.catalogs",
            "area": "b2b",
            "title": "Company catalogs and price lists",
            "summary": "Apps have no company, contact or location model, no negotiated catalogs or price lists, and no company payment terms. Price resolution stays on the single customer-price path.",
            "status": "missing",
            "surface": [],
            "limits": [],
            "workaround": "Keep the business-buyer mapping in the app database; it cannot change the platform price.",
            "tags": [
                "b2b",
                "catalogs",
                "pricing"
            ],
            "design_note": ""
        },
        {
            "id": "channels.feed",
            "area": "channels",
            "title": "Product feed and external order import",
            "summary": "Apps build product feeds and channel syncs from Merchant API reads: each product carries its storefront url, base price and storefront_price (the shopper price), currency, barcode, stock, images and variants; a registered publication limits the list to the products published to it; updated_after surfaces edited products and a full list walk reconciles stock, price and removals; an order imported with a publication carries its p_id. The app generates and uploads the feed itself; brand, condition and channel category are not product fields, so read them from merchant-defined metafields or map them in the app.",
            "status": "supported",
            "surface": [
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/publications"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/products"
                },
                {
                    "kind": "scope",
                    "name": "merchant-items-read"
                },
                {
                    "kind": "scope",
                    "name": "merchant-publications-read"
                },
                {
                    "kind": "scope",
                    "name": "merchant-orders-import"
                }
            ],
            "limits": [
                "Pull only: nothing is pushed to the app. updated_after finds new and edited product rows but can miss variant, image, metafield, stock, price and discount changes, so re-read the full list on a schedule for price and stock, and use that full walk to find removals.",
                "No per-product sync status or rejection reason can be written back to Queek; the app keeps its own feed status.",
                "Each product and variant carries a base `price` and a shopper `storefront_price` (use `storefront_price` in a feed), both in the product's `currency`; there are no per-market prices, so the app converts when a channel needs another currency.",
                "Product list rows include drafts and out-of-stock products; filter on status and published before emitting a feed.",
                "No brand, condition or channel-category field on the product; use a merchant-defined, non-hidden metafield (the product object carries metafields) or app-side mapping.",
                "Imported orders must already be charged externally."
            ],
            "workaround": "",
            "tags": [
                "channels",
                "feeds",
                "marketplace"
            ],
            "design_note": ""
        },
        {
            "id": "content.posts",
            "area": "content",
            "title": "Blog-post reads and markdown writes",
            "summary": "Apps can list and read blog posts, and create, update, publish and delete them with a markdown body through the merchant API. Builder pages and block-composed layouts stay dashboard-side.",
            "status": "supported",
            "surface": [
                {
                    "kind": "scope",
                    "name": "merchant-posts-read"
                },
                {
                    "kind": "scope",
                    "name": "merchant-posts-detail"
                },
                {
                    "kind": "scope",
                    "name": "merchant-posts-create"
                },
                {
                    "kind": "scope",
                    "name": "merchant-posts-update"
                },
                {
                    "kind": "scope",
                    "name": "merchant-posts-delete"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/merchant/posts"
                }
            ],
            "limits": [
                "Markdown body only; block-built posts and builder pages cannot be written through the merchant API."
            ],
            "workaround": "",
            "tags": [
                "content",
                "posts",
                "merchant-api"
            ],
            "design_note": ""
        },
        {
            "id": "conversations.api",
            "area": "conversations",
            "title": "Conversation and message API for apps",
            "summary": "Installed apps can list and read the store's WhatsApp, Instagram and Telegram conversations and messages, mark a conversation read, reply to a shopper on the store's own line, and subscribe to conversation_messages/create to be told when a shopper writes. The shopper's name and channel handle are masked unless the app also holds the customer contact grant.",
            "status": "supported",
            "surface": [
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/conversations"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/conversations/{conversation}"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/conversations/{conversation}/messages"
                },
                {
                    "kind": "scope",
                    "name": "merchant-conversations-read"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/merchant/conversations/{conversation}/mark-read"
                },
                {
                    "kind": "scope",
                    "name": "merchant-conversations-update"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/merchant/conversations/{conversation}/messages"
                },
                {
                    "kind": "scope",
                    "name": "merchant-conversations-reply"
                },
                {
                    "kind": "webhook",
                    "name": "conversation_messages/create"
                }
            ],
            "limits": [
                "conversation_messages/create fires once for each message a shopper writes, with the conversation id, the channel and the message. It needs the conversations read grant, and the message text can contain contact details. The assistant's and the team's replies do not fire it, and there is no topic for a conversation that changes mode or closes. Delivery is at least once, a message is reported within a few minutes of being stored, and an app added later catches up by listing conversations.",
                "Message text is written by shoppers and can contain contact details; only the shopper's name and channel handle are masked.",
                "A reply is text, an image or a product card: no buttons, voice, files or templates. It needs an Idempotency-Key, and on WhatsApp and Instagram it is refused 24 hours after the shopper's last message. Each installation may send 20 replies a minute and 1,000 a day.",
                "A reply pauses the store's AI on that conversation for the store's takeover window. Apps cannot switch between AI and team, assign or close a conversation, or start a conversation with a shopper.",
                "The store needs a plan that includes the messaging inbox, and a version that declares the read or reply scope goes through review before release."
            ],
            "workaround": "To change who answers, or to message a shopper who has not written first, use the merchant dashboard inbox.",
            "tags": [
                "conversations",
                "messaging",
                "channels"
            ],
            "design_note": ""
        },
        {
            "id": "customers.read",
            "area": "customers",
            "title": "Customers and followers",
            "summary": "List customers and followers with cursor pagination, each carrying its tags and filterable with the tag parameter; campaign audience reads can include non-buyers. Contact fields and email/SMS marketing consent state require the review-protected contact scope.",
            "status": "supported",
            "surface": [
                {
                    "kind": "scope",
                    "name": "merchant-customers-read"
                },
                {
                    "kind": "scope",
                    "name": "merchant-customers-contact-read"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/customers"
                }
            ],
            "limits": [
                "Use audience=campaign to include non-buyers; this mode requires merchant-customers-contact-read. Poll this audience to discover new subscribers. not_opted_out means only that the person has not used Queek\u2019s email unsubscribe; it is not permission to send. An import that stores info.marketing_opt_in=false excludes that contact from campaign reachability. sms_marketing_consent.state is not_subscribed until an app reports explicit opt-in; stored unsubscribed state and its consent timestamp remain visible even when the phone is absent or invalid; not_subscribed exposes no hidden ordering timestamp; phone presence and email consent do not imply SMS consent."
            ],
            "workaround": "",
            "tags": [
                "customers",
                "merchant-api",
                "privacy"
            ],
            "design_note": ""
        },
        {
            "id": "customers.segments",
            "area": "customers",
            "title": "Segments, tags and consent",
            "summary": "Apps can read the campaign audience and email and SMS consent state, update consent for both channels, receive minimal consent events and manage saved customer segments: list, read, create, update and delete them, and preview who a set of rules matches. A previewed customer\u2019s name, email and phone are null without merchant-customers-contact-read. Customers carry the store\u2019s own tags, read on the customer object and matched by a segment rule (tags_any, any of the listed tags); a static segment stays the hand-picked grouping.",
            "status": "supported",
            "surface": [
                {
                    "kind": "scope",
                    "name": "merchant-customers-read"
                },
                {
                    "kind": "scope",
                    "name": "merchant-customers-contact-read"
                },
                {
                    "kind": "scope",
                    "name": "merchant-customers-consent-update"
                },
                {
                    "kind": "scope",
                    "name": "merchant-customers-sms-consent-update"
                },
                {
                    "kind": "scope",
                    "name": "merchant-customer-segments-read"
                },
                {
                    "kind": "scope",
                    "name": "merchant-customer-segments-create"
                },
                {
                    "kind": "scope",
                    "name": "merchant-customer-segments-update"
                },
                {
                    "kind": "scope",
                    "name": "merchant-customer-segments-delete"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/customers"
                },
                {
                    "kind": "webhook",
                    "name": "customers/update"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/merchant/customers/{customer}/email-marketing-consent"
                },
                {
                    "kind": "webhook",
                    "name": "customers_email_marketing_consent/update"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/merchant/customers/{customer}/sms-marketing-consent"
                },
                {
                    "kind": "webhook",
                    "name": "customers_marketing_consent/update"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/customer-segments"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/customer-segments/{segment}"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/merchant/customer-segments"
                },
                {
                    "kind": "route",
                    "name": "PATCH api/v1/merchant/customer-segments/{segment}"
                },
                {
                    "kind": "route",
                    "name": "DELETE api/v1/merchant/customer-segments/{segment}"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/merchant/customer-segments/preview"
                }
            ],
            "limits": [
                "Customer tags are the store\u2019s own labels: a customer holds at most 250 tags of 255 characters, lowercased and deduplicated, and a tag name is private to its store. Apps read tags on the customer (tags) and in the customers/create and customers/update webhooks with the existing customers read grants, and a segment rule tags_any matches a customer carrying any of the listed tags. Apps cannot set a customer\u2019s tags: the merchant sets them in the dashboard or the customer import.",
                "App-reported consent evidence is not independently verified.",
                "An import that stores info.marketing_opt_in=false excludes that contact from campaign reachability.",
                "SMS consent is stored only from explicit app or provider reports; there is no WhatsApp consent state.",
                "A segment is a saved set of rules (`auto`) or a hand-picked list of up to 1,000 customers (`static`). The built-in default segments are not listed; reproduce one with rules.",
                "Segments are identified by a UUID and members by customer id. A segment\u2019s stored recipient count is the count at its last save; the preview answers the live count.",
                "The customer_ids of a static segment are store customer ids (the p_id from the customer reads), and an update that sends customer_ids replaces the whole member list rather than adding to it.",
                "Changing or deleting a segment a campaign uses changes who that campaign reaches at its next send. Apps cannot create or send campaigns.",
                "The segment scopes are customer-data scopes: declaring them needs approval, and installed stores must grant them."
            ],
            "workaround": "Create a static segment with the matching customer ids and send the complete member list on every update. Keep any attribute that is not a customer id in the app database and write its matches into the segment.",
            "tags": [
                "customers",
                "segments",
                "consent"
            ],
            "design_note": ""
        },
        {
            "id": "customers.wishlists",
            "area": "customers",
            "title": "Customer wishlists",
            "summary": "Shoppers can add, list and remove saved product and variant entries in a store-scoped wishlist through the storefront API, and apps with merchant-customers-detail can read a customer\u2019s list. Only shoppers write, and Queek ships no wishlist page: an app supplies its own shopper interface.",
            "status": "supported",
            "surface": [
                {
                    "kind": "route",
                    "name": "GET api/v1/client/store/wishlist-items"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/client/store/wishlist-items"
                },
                {
                    "kind": "route",
                    "name": "DELETE api/v1/client/store/wishlist-items/{ref}"
                },
                {
                    "kind": "scope",
                    "name": "merchant-customers-detail"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/customers/{customer}/wishlist-items"
                }
            ],
            "limits": [
                "One flat list per store customer; no sharing or cross-store lookup.",
                "A wishlist holds at most 100 visible items.",
                "There are no wishlist events or webhooks: read a customer\u2019s list again to see changes.",
                "Merchants and apps can only read; only signed-in shoppers write, through the storefront API.",
                "There is no Merchant API or app-proxy write: a wishlist change has to come from the shopper\u2019s own signed-in session.",
                "Queek\u2019s hosted storefront has no wishlist page, so the shopper-facing view is the app\u2019s to build."
            ],
            "workaround": "Build the shopper interface in your own storefront code and call the storefront wishlist endpoints with the signed-in shopper\u2019s token. Read any customer\u2019s list from the Merchant API with the customer detail scope.",
            "tags": [
                "wishlist",
                "customers",
                "storefront"
            ],
            "design_note": ""
        },
        {
            "id": "dashboard.alerts",
            "area": "dashboard",
            "title": "Merchant alerts (in-app bell)",
            "summary": "Apps can page the merchant through the in-app bell with a severity, title and message, a dedupe key that collapses repeats, and a link to the app\u2019s page in the dashboard. Alerts are rate-capped per installation. Delivery is the bell only: there is no push, text, email, per-staff targeting or delivery receipt from apps.",
            "status": "supported",
            "surface": [
                {
                    "kind": "scope",
                    "name": "merchant-app_alerts-create"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/merchant/app/alerts"
                }
            ],
            "limits": [
                "In-app bell only, on purpose: an app message never triggers push, text or email to the merchant.",
                "An alert reaches the staff who may see installed apps; an app cannot pick a recipient or learn who read it.",
                "Each installation is capped per hour, and error-severity alerts per day; past a cap the call answers 429 with Retry-After, and a repeated dedupe key within its window is dropped.",
                "The bell link opens the app\u2019s own page in the dashboard; an app cannot choose another destination."
            ],
            "workaround": "Use the bell for alerts that can wait for the merchant to open the dashboard. For urgent or targeted messages, the app contacts the merchant itself over its own channel.",
            "tags": [
                "notifications",
                "merchant-api"
            ],
            "design_note": ""
        },
        {
            "id": "dashboard.details",
            "area": "dashboard",
            "title": "App details page data",
            "summary": "The merchant app-details view serves the access table, privacy block, proxy address, extension counts and install timeline for an installed app.",
            "status": "supported",
            "surface": [
                {
                    "kind": "route",
                    "name": "GET api/v1/biz/vendor/app-store/{slug}/details"
                }
            ],
            "limits": [
                "Served for active installations only."
            ],
            "workaround": "",
            "tags": [
                "dashboard",
                "listing",
                "transparency"
            ],
            "design_note": ""
        },
        {
            "id": "dashboard.embed",
            "area": "dashboard",
            "title": "Embedded app page with session token",
            "summary": "The dashboard frames the app merchant page in a sandboxed view with short-lived session tokens minted per installation and user.",
            "status": "supported",
            "surface": [
                {
                    "kind": "manifest",
                    "name": "extensions.merchant_page_url"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/biz/vendor/app-session-token"
                }
            ],
            "limits": [
                "Token lifetime is short; the framed origin is frozen at the install-time grant until an origin change is re-consented."
            ],
            "workaround": "",
            "tags": [
                "dashboard",
                "embedded",
                "auth"
            ],
            "design_note": ""
        },
        {
            "id": "dashboard.nav",
            "area": "dashboard",
            "title": "Declared app nav and pins",
            "summary": "Manifest-declared sidebar entries rendered under the open app, resolved per installation, with per-user per-store pins.",
            "status": "supported",
            "surface": [
                {
                    "kind": "manifest",
                    "name": "extensions.nav"
                }
            ],
            "limits": [
                "Pinning is per the open app; no global pin board."
            ],
            "workaround": "",
            "tags": [
                "dashboard",
                "extensions",
                "nav"
            ],
            "design_note": ""
        },
        {
            "id": "dashboard.sheets",
            "area": "dashboard",
            "title": "Dashboard sheet blocks, actions and print",
            "summary": "Apps can mount blocks on order and product sheets, an action on order sheets that records an appointment on the order and notifies the app, and a print template in the order print dialog.",
            "status": "supported",
            "surface": [
                {
                    "kind": "manifest",
                    "name": "dashboard.blocks"
                },
                {
                    "kind": "manifest",
                    "name": "dashboard.actions"
                },
                {
                    "kind": "manifest",
                    "name": "dashboard.print"
                }
            ],
            "limits": [
                "Blocks mount on order and product sheets only, actions on order sheets only, and print on the order print dialog only; there are no other dashboard targets.",
                "An action runs one effect from a closed list, today order_appointment; apps cannot define their own effects.",
                "There are no nav badges or unread counts."
            ],
            "workaround": "Deep-link into the embedded app page for any target, effect or badge a sheet mount cannot express.",
            "tags": [
                "dashboard",
                "extensions"
            ],
            "design_note": ""
        },
        {
            "id": "developer.cli",
            "area": "developer",
            "title": "Command-line app flow",
            "summary": "The command-line tool covers scaffolding, the tunnel dev loop with dev-installs (optionally previewed through a localhost page) and their cleanup, deploy, version release, review submission and spec codegen against the live merchant contract.",
            "status": "supported",
            "surface": [
                {
                    "kind": "package",
                    "name": "@usequeek/cli"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/biz/vendor/developer/apps/{app}/dev-installs"
                },
                {
                    "kind": "route",
                    "name": "DELETE api/v1/biz/vendor/developer/apps/{app}/dev-installs/{store}"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/biz/vendor/developer/apps/{app}/versions"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/biz/vendor/developer/apps/{app}/versions/{version}/release"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/biz/vendor/developer/apps/{app}/versions/{sequence}/submit"
                }
            ],
            "limits": [
                "Automation tokens never substitute for dev-install routes."
            ],
            "workaround": "",
            "tags": [
                "cli",
                "developer-experience"
            ],
            "design_note": ""
        },
        {
            "id": "developer.dev_stores",
            "area": "developer",
            "title": "Dev stores and test data",
            "summary": "Developer-owned sandbox stores with a capped count, storefront password lock, rename and slug control, generated test data that can be re-run at any time to top up what is missing (pages, posts, menus, locales, orders, reviews, suppliers and more), a dev-install flow that refreshes the grant in place without re-consent, and day-one test orders: a new dev store has a region, so the dashboard Create Order, the Merchant API order create and the password-protected storefront checkout all work with no setup, using simulated money only.",
            "status": "supported",
            "surface": [
                {
                    "kind": "config",
                    "name": "developer.max_dev_stores"
                },
                {
                    "kind": "config",
                    "name": "developer.dev_store_location"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/biz/vendor/developer/dev-stores"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/biz/vendor/developer/dev-stores/{store}/test-data"
                }
            ],
            "limits": [
                "Capped per developer; sandboxes never transfer to merchants.",
                "A dev store has every plan feature switched on (suppliers, purchase orders and the other plan-gated capabilities), so you can build and test against them; a live store only has the features of its plan, and a call to a plan-gated route there is refused with an upgrade-required answer.",
                "Re-running the test data only creates what is missing; records you changed or added are never touched. Only the owner can run it, and an automation token cannot.",
                "Orders on a dev store use simulated money only: cash is recorded without a provider, and an online payment lands on a hosted test page where you choose paid or declined. Nothing is ever charged or paid out. A dev store has no bank account, so Merchant API orders pay online (name a customer); bank transfer is refused with payment_method_unavailable.",
                "Stock tracking is the store's own setting and is off until you turn it on; with it on, completing an order writes the normal sale movement. A store with no region refuses orders with the code store_region_missing."
            ],
            "workaround": "",
            "tags": [
                "dev-stores",
                "sandbox",
                "testing"
            ],
            "design_note": ""
        },
        {
            "id": "developer.sdk",
            "area": "developer",
            "title": "App SDK (install, session, scopes)",
            "summary": "The app SDK covers install and webhook handling, the single embedded session-token model, typed merchant clients generated from the live spec, and the scopes catalogue.",
            "status": "supported",
            "surface": [
                {
                    "kind": "package",
                    "name": "@usequeek/app-sdk"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/apps/installations/{installation}/access_tokens"
                }
            ],
            "limits": [
                "Bridge coverage is a subset: title, toast, save bar, navigation, open and product picker today."
            ],
            "workaround": "",
            "tags": [
                "sdk",
                "bridge",
                "developer-experience"
            ],
            "design_note": ""
        },
        {
            "id": "developer.toolkit",
            "area": "developer",
            "title": "AI builder toolkit and live capacity doc",
            "summary": "The AI toolkit skills fetch this live capability document before planning any app, so the building model checks what the platform can do instead of trusting memory. The document is generated from the code at build time.",
            "status": "supported",
            "surface": [
                {
                    "kind": "repository",
                    "name": "usequeek/queek-ai-toolkit"
                },
                {
                    "kind": "route",
                    "name": "GET docs/capabilities.json"
                }
            ],
            "limits": [
                "The toolkit points at the live doc; no capability facts are baked into skills."
            ],
            "workaround": "",
            "tags": [
                "ai",
                "toolkit",
                "docs",
                "developer-experience"
            ],
            "design_note": ""
        },
        {
            "id": "discounts.cart_transform",
            "area": "discounts",
            "title": "Transform cart lines and bundles",
            "summary": "Apps create scoped discounts with quantity and spend thresholds, priority and stacking, and manage priced add-on groups. All of it runs through the one price path the shopper sees, so the displayed price is the charged price. Apps cannot run code at cart time.",
            "status": "partial",
            "surface": [
                {
                    "kind": "route",
                    "name": "POST api/v1/merchant/discounts"
                },
                {
                    "kind": "scope",
                    "name": "merchant-discounts-create"
                },
                {
                    "kind": "route",
                    "name": "PATCH api/v1/merchant/discounts/{discount}"
                },
                {
                    "kind": "scope",
                    "name": "merchant-discounts-update"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/merchant/addon-groups"
                }
            ],
            "limits": [
                "No code runs at cart time: an app cannot rewrite cart lines or reprice them.",
                "There is no rule for all of product A and B and no automatically added free gift; a fixed-price bundle is a product with its own price and stock.",
                "A discount is edited in place with PATCH api/v1/merchant/discounts/{discount} (scope merchant-discounts-update): the usage count is kept and the shopper price follows the edit at once. The scope can reprice any live discount of the store, including ones the merchant made by hand, so the merchant approves it at install."
            ],
            "workaround": "Use quantity-threshold discounts for tiers, priced add-on groups for options, and a product with its own price for a fixed bundle.",
            "tags": [
                "cart",
                "checkout",
                "functions"
            ],
            "design_note": ""
        },
        {
            "id": "discounts.checkout_validation",
            "area": "discounts",
            "title": "App checkout validation rules",
            "summary": "No app extension point validates a cart or order on the server beyond the platform\u2019s own request checks.",
            "status": "missing",
            "surface": [],
            "limits": [],
            "workaround": "Enforce merchant-side rules through discount targeting and coupon limits when you create them.",
            "tags": [
                "checkout",
                "validation",
                "functions"
            ],
            "design_note": ""
        },
        {
            "id": "discounts.primitives",
            "area": "discounts",
            "title": "Discounts and coupons create/publish",
            "summary": "List, retrieve, create, edit, publish and unpublish discounts; list, create and edit coupons, all through the merchant API.",
            "status": "supported",
            "surface": [
                {
                    "kind": "scope",
                    "name": "merchant-discounts-create"
                },
                {
                    "kind": "scope",
                    "name": "merchant-coupons-create"
                },
                {
                    "kind": "scope",
                    "name": "merchant-discounts-update"
                },
                {
                    "kind": "scope",
                    "name": "merchant-coupons-update"
                },
                {
                    "kind": "route",
                    "name": "PATCH api/v1/merchant/discounts/{discount}"
                },
                {
                    "kind": "route",
                    "name": "PATCH api/v1/merchant/coupons/{coupon}"
                }
            ],
            "limits": [
                "No cart/checkout-time custom logic: created discounts apply through the platform pricing path only."
            ],
            "workaround": "",
            "tags": [
                "discounts",
                "coupons",
                "merchant-api"
            ],
            "design_note": ""
        },
        {
            "id": "discounts.storefront_redeem",
            "area": "discounts",
            "title": "Shopper coupon redemption on the storefront",
            "summary": "The storefront API can apply and remove a discount code on a shopper\u2019s cart, checked against the same rules as checkout, and the cart totals show its effect. A code is consumed only when the order is placed, and no event tells an app that a code was redeemed.",
            "status": "supported",
            "surface": [
                {
                    "kind": "route",
                    "name": "POST store/cart/discounts"
                },
                {
                    "kind": "route",
                    "name": "DELETE store/cart/discounts/{code}"
                }
            ],
            "limits": [
                "Apply requests are throttled to 10 per minute.",
                "Applying a code does not consume it: usage is counted when the order is placed.",
                "There is no separate redemption topic: an app learns which code was used from the coupon_code on the paid order, which the order webhook carries too."
            ],
            "workaround": "Read the paid order after checkout: its coupon_code names the discount code the shopper used (null when none) and its discount_total shows the effect. Webhooks carry the same object.",
            "tags": [
                "discounts",
                "coupons",
                "storefront",
                "checkout"
            ],
            "design_note": ""
        },
        {
            "id": "inventory.stock",
            "area": "inventory",
            "title": "Inventory, purchase orders and stock alerts",
            "summary": "Apps can read store-level on-hand stock, make audited set or delta adjustments, list suppliers, create and read purchase orders, receive goods against them (which adds stock), and list low-stock and out-of-stock products through the Merchant API. There are no locations or per-location levels, and a received purchase order line can name the variant it is for.",
            "status": "supported",
            "surface": [
                {
                    "kind": "scope",
                    "name": "merchant-inventory-read"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/merchant/inventory/adjustments"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/inventory/levels"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/merchant/inventory/levels/adjustments"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/inventory/low-stock"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/inventory/out-of-stock"
                },
                {
                    "kind": "scope",
                    "name": "merchant-suppliers-read"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/suppliers"
                },
                {
                    "kind": "scope",
                    "name": "merchant-purchase_orders-read"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/purchase-orders"
                },
                {
                    "kind": "scope",
                    "name": "merchant-purchase_orders-detail"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/purchase-orders/{po}"
                },
                {
                    "kind": "scope",
                    "name": "merchant-purchase_orders-create"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/merchant/purchase-orders"
                },
                {
                    "kind": "scope",
                    "name": "merchant-purchase_orders-update"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/merchant/purchase-orders/{po}/receive"
                }
            ],
            "limits": [
                "No per-location stock.",
                "A level adjustment changes one item per call; only bulk restock handles several products, and it skips products with variants.",
                "Receiving a purchase order adds each line\u2019s quantity to one variant (items[].variant, its p_id) or, for a product without active variants, to the product\u2019s stock. A line for a product with active variants must name a variant: the answer is 422 variant_required and nothing is received. A line is a product-level allocation, so one line\u2019s quantity cannot be split across several variants in a single request: send one receive per variant.",
                "Receiving needs an Idempotency-Key header. It records the ordered unit cost on the receipt but never changes the product\u2019s own cost price.",
                "Suppliers are read only: apps cannot create, change or delete them. Suppliers and purchase orders have no short numeric id, only an opaque one.",
                "A purchase order cannot be edited, cancelled or deleted through the API; the only change is receiving goods.",
                "Suppliers and purchase orders need the supplier management and purchase orders features on the store\u2019s plan; a live store without them is refused with the usual upgrade-required answer. A dev store carries every plan feature, so build and test against them there; a live store needs the plan.",
                "There are no forecasts or reorder points.",
                "Adjustments do not check open-order reservations."
            ],
            "workaround": "Use a small `limit` when listing products with many variants: each product lists all of its variants, with no per-product cap. Create and edit suppliers, and cancel a purchase order, in the merchant dashboard.",
            "tags": [
                "inventory",
                "merchant-api",
                "purchasing"
            ],
            "design_note": ""
        },
        {
            "id": "loyalty.gift_cards",
            "area": "loyalty",
            "title": "Gift cards and store credit",
            "summary": "Apps can sell a gift card as a digital product and issue each one as a single-use fixed-amount code that redeems at checkout. There is no balance ledger or store credit, so a partly used code is re-valued in place by lowering its value to the remainder.",
            "status": "partial",
            "surface": [
                {
                    "kind": "route",
                    "name": "POST api/v1/merchant/coupons"
                },
                {
                    "kind": "scope",
                    "name": "merchant-coupons-create"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/coupons"
                },
                {
                    "kind": "route",
                    "name": "PATCH api/v1/merchant/coupons/{coupon}"
                },
                {
                    "kind": "scope",
                    "name": "merchant-coupons-update"
                },
                {
                    "kind": "webhook",
                    "name": "orders/paid"
                }
            ],
            "limits": [
                "A code redeems once for a fixed amount; there is no balance ledger and no store credit, so a partly used code burns its remainder.",
                "The wallet that holds marketplace refunds is not available to apps.",
                "A coupon is edited in place with PATCH api/v1/merchant/coupons/{coupon} (scope merchant-coupons-update): lower discount_value to the remainder, and raise usage_limit (never below the used count) and usage_limit_per_user (at most 10) to re-use a partly spent code. The code and the used count never change, so a card allows at most 10 redemptions per customer."
            ],
            "workaround": "Sell the card as a product, issue a fixed-amount code on orders/paid, and when a code is partly used lower its value to the remainder and raise its usage limit. Keep any balance record in the app\u2019s own database.",
            "tags": [
                "loyalty",
                "gift-cards",
                "checkout"
            ],
            "design_note": ""
        },
        {
            "id": "loyalty.points",
            "area": "loyalty",
            "title": "Loyalty points ledger",
            "summary": "No points ledger, earn or burn events, or checkout redemption API exists. An app can keep points itself but cannot apply them to the platform price.",
            "status": "missing",
            "surface": [
                {
                    "kind": "webhook",
                    "name": "orders/paid"
                }
            ],
            "limits": [],
            "workaround": "Credit points off paid-order webhooks in the app database and reward with coupons; reconcile reversals off cancelled-order events.",
            "tags": [
                "loyalty",
                "checkout",
                "ledger"
            ],
            "design_note": "Apps keep their own points ledger and reward customers with discount codes created through the Merchant API."
        },
        {
            "id": "markets.currency",
            "area": "markets",
            "title": "Regional catalogs and display currency",
            "summary": "Apps have no market, catalog or currency-context API. Currency is store and provider configuration, with no market-specific publication.",
            "status": "missing",
            "surface": [],
            "limits": [],
            "workaround": "Run one store per currency region and convert for display on the app-hosted page.",
            "tags": [
                "markets",
                "currency",
                "catalog"
            ],
            "design_note": ""
        },
        {
            "id": "markets.translations",
            "area": "markets",
            "title": "Translated commerce content",
            "summary": "Apps can read and write locales, translatable content and translations through the Merchant API, set the store\u2019s default language, and receive locale and translation webhooks. Translations are not scoped to markets.",
            "status": "supported",
            "surface": [
                {
                    "kind": "scope",
                    "name": "merchant-locales-read"
                },
                {
                    "kind": "scope",
                    "name": "merchant-locales-write"
                },
                {
                    "kind": "scope",
                    "name": "merchant-translations-read"
                },
                {
                    "kind": "scope",
                    "name": "merchant-translations-write"
                },
                {
                    "kind": "webhook",
                    "name": "locales/create"
                },
                {
                    "kind": "webhook",
                    "name": "locales/update"
                },
                {
                    "kind": "webhook",
                    "name": "locales/destroy"
                },
                {
                    "kind": "webhook",
                    "name": "translations/update"
                },
                {
                    "kind": "webhook",
                    "name": "translations/delete"
                }
            ],
            "limits": [
                "Translation writes carry at most 100 items per call.",
                "A stored translation keeps the digest of the source it was written against and reads back outdated once the source changes.",
                "A write must echo the current digest of each item, or the whole batch is rejected.",
                "The theme_string type is one record per store, keyed <theme-slug>.<dotted-key>; its English defaults travel with the active theme.",
                "The storefront serves theme_string overrides for non-primary published locales.",
                "theme_string keys carry the theme slug, so switching theme leaves the old slug overrides dormant until pruned.",
                "machine_translation_allowed advises against machine-filling privacy-policy, terms-of-service, returns-policy and shipping-policy.",
                "Manual writes to those policy pages stay allowed.",
                "The default language (POST locales/{locale}/default) sets which published locale the root address serves; empty means the primary.",
                "Changing the default language emits locales/update for the gaining and the losing locale.",
                "Translations are per store and locale, not per market: apps have no market model, so one translation serves that locale everywhere the store sells."
            ],
            "workaround": "Read current digests from the translatable-resource show endpoint, echo them on write, and chunk larger jobs into batches of 100 items. Re-read after a theme publish. Policy pages accept manual writes.",
            "tags": [
                "translations",
                "localization",
                "merchant-api"
            ],
            "design_note": ""
        },
        {
            "id": "merchant.carts",
            "area": "merchant",
            "title": "Active carts",
            "summary": "Apps cannot read live carts: carts stay storefront-only, on the anonymous cart session or the customer token. Carts a signed-in customer left unchanged are offered separately as abandoned checkouts.",
            "status": "missing",
            "surface": [],
            "limits": [],
            "workaround": "Share the storefront cart URL into the chat and read the converted order through the order webhooks.",
            "tags": [
                "carts",
                "merchant-api"
            ],
            "design_note": "Carts belong to the shopper session. Apps do not read live carts; they see the order once it is placed."
        },
        {
            "id": "merchant.forms_records",
            "area": "merchant",
            "title": "Forms and collected records",
            "summary": "Apps create and manage their own collected form definitions, submit records under them, and list, read, update and triage records under definitions they own.",
            "status": "supported",
            "surface": [
                {
                    "kind": "route",
                    "name": "POST api/v1/merchant/records"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/records"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/records/{record}"
                },
                {
                    "kind": "route",
                    "name": "PATCH api/v1/merchant/records/{record}"
                },
                {
                    "kind": "scope",
                    "name": "merchant-collected-definitions-manage"
                },
                {
                    "kind": "scope",
                    "name": "merchant-collected-records-submit"
                },
                {
                    "kind": "scope",
                    "name": "merchant-collected-records-read"
                },
                {
                    "kind": "scope",
                    "name": "merchant-collected-records-update"
                }
            ],
            "limits": [
                "Installation keys can access only records under their own collected definitions; merchant-held and other-installation records are unavailable. Uninstall makes former app records merchant-held. Apps cannot delete records or receive record webhooks.",
                "A json field keeps numeric-string keys (a map such as 4262: {...} stays a map), but JSON objects are stored unordered: key order is not preserved, an object whose keys are exactly 0, 1, 2\u2026 reads back as a list, and an empty object reads back as an empty list."
            ],
            "workaround": "Use the merchant Submissions screen to review merchant-held records; an app can process only its own definitions.",
            "tags": [
                "forms",
                "metaobjects",
                "merchant-api"
            ],
            "design_note": ""
        },
        {
            "id": "merchant.line_inputs",
            "area": "merchant",
            "title": "Shopper text declarations",
            "summary": "Installation-bound sheet declaring which products take shopper text on a line, and under which of the app\u2019s line_text fields; the label comes from the manifest and a required field is verified at checkout.",
            "status": "supported",
            "surface": [
                {
                    "kind": "scope",
                    "name": "merchant-app-requirements-write"
                },
                {
                    "kind": "route",
                    "name": "PUT api/v1/merchant/app/line-inputs"
                }
            ],
            "limits": [
                "A key must be a line_text field of the extensions the merchant granted; up to 3 fields per product, max_length 1 to 500, never above the manifest value (100 when the manifest sets none); 200 products per sheet; the whole sheet is replaced on every call."
            ],
            "workaround": "",
            "tags": [
                "checkout",
                "storefront",
                "merchant-api"
            ],
            "design_note": ""
        },
        {
            "id": "merchant.metafields",
            "area": "merchant",
            "title": "Metafields, metaobjects and app data",
            "summary": "Structured per-store config and app data through definitions, values, metaobjects and the installation-owned collected-records path.",
            "status": "supported",
            "surface": [
                {
                    "kind": "scope",
                    "name": "merchant-metafields-create"
                },
                {
                    "kind": "scope",
                    "name": "merchant-metaobjects-create"
                }
            ],
            "limits": [
                "No app-namespaced convention: colliding keys across apps are possible."
            ],
            "workaround": "",
            "tags": [
                "metafields",
                "merchant-api",
                "app-data"
            ],
            "design_note": ""
        },
        {
            "id": "merchant.order_actions",
            "area": "merchant",
            "title": "Order status, payment approval and riders",
            "summary": "Move orders through the status machine, manually record qualifying offline payments as received, assign self-delivery riders, and patch shipment and app-namespaced extension fields.",
            "status": "supported",
            "surface": [
                {
                    "kind": "scope",
                    "name": "merchant-orders-status-update"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/merchant/orders/{order}/status"
                }
            ],
            "limits": [
                "Manual approval requires payment_status awaiting_confirmation, a method other than online or wallet, and a payment that is not already paid. Cancelled or rejected orders cannot be updated. It records the payment and marks the order paid, does not verify provider receipt, and does not call a provider. Extension writes remain under the installation namespace."
            ],
            "workaround": "",
            "tags": [
                "orders",
                "merchant-api"
            ],
            "design_note": ""
        },
        {
            "id": "merchant.product_addons",
            "area": "merchant",
            "title": "Priced add-on groups on products",
            "summary": "Stores define priced choice-list groups and attach them to products through 7 Merchant API rows; the product object and products/* webhooks carry them additively under `addons` (bounded at 20 groups with 20 items each). Add-ons are not variants: a variant axis combines name and values into product variants and its price lives on the variant, while an add-on group carries its own prices.",
            "status": "supported",
            "surface": [
                {
                    "kind": "scope",
                    "name": "merchant-options-read"
                },
                {
                    "kind": "scope",
                    "name": "merchant-options-detail"
                },
                {
                    "kind": "scope",
                    "name": "merchant-options-create"
                },
                {
                    "kind": "scope",
                    "name": "merchant-options-update"
                },
                {
                    "kind": "scope",
                    "name": "merchant-options-delete"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/addon-groups"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/addon-groups/{group}"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/merchant/addon-groups"
                },
                {
                    "kind": "route",
                    "name": "PATCH api/v1/merchant/addon-groups/{group}"
                },
                {
                    "kind": "route",
                    "name": "DELETE api/v1/merchant/addon-groups/{group}"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/merchant/products/{product}/addons"
                },
                {
                    "kind": "route",
                    "name": "DELETE api/v1/merchant/products/{product}/addons/{group}"
                }
            ],
            "limits": [
                "Queek apps author add-on data through these rows; they cannot run pricing logic at cart time.",
                "Arbitrary price-rewrite apps (bundles, rule-based pricing) stay unserved: discounts.cart_transform is still missing.",
                "A product that sells through variants refuses attach with 422; add-on prices ride as-is, outside the customer-price path."
            ],
            "workaround": "",
            "tags": [
                "catalog",
                "merchant-api",
                "cart"
            ],
            "design_note": ""
        },
        {
            "id": "merchant.products",
            "area": "merchant",
            "title": "Products, variants and images",
            "summary": "List, retrieve, create, replace and delete products with variants and images; bulk publish.",
            "status": "supported",
            "surface": [
                {
                    "kind": "scope",
                    "name": "merchant-items-read"
                },
                {
                    "kind": "scope",
                    "name": "merchant-items-create"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/products"
                }
            ],
            "limits": [
                "Full-body update only; variants and images are partial.",
                "The product object carries priced choice-list add-ons under `addons` (see merchant.product_addons)."
            ],
            "workaround": "",
            "tags": [
                "catalog",
                "merchant-api"
            ],
            "design_note": ""
        },
        {
            "id": "merchant.records_read",
            "area": "merchant",
            "title": "Apps read and update their own collected records",
            "summary": "Apps can list, read and update collected records under definitions they own.",
            "status": "supported",
            "surface": [
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/records"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/records/{record}"
                },
                {
                    "kind": "route",
                    "name": "PATCH api/v1/merchant/records/{record}"
                },
                {
                    "kind": "scope",
                    "name": "merchant-collected-records-read"
                },
                {
                    "kind": "scope",
                    "name": "merchant-collected-records-update"
                }
            ],
            "limits": [
                "Installation keys can access only records under their own collected definitions; merchant-held and other-installation records are unavailable. Uninstall makes former app records merchant-held. Apps cannot delete records or receive record webhooks."
            ],
            "workaround": "Use the merchant Submissions screen to review merchant-held records; an app can process only its own definitions.",
            "tags": [
                "forms",
                "collected-records",
                "merchant-api"
            ],
            "design_note": ""
        },
        {
            "id": "merchant.requirements",
            "area": "merchant",
            "title": "Booking requirements sheet",
            "summary": "Installation-bound product requirements map declaring which products require line properties under the installation namespace; verified at checkout by the claim guard.",
            "status": "supported",
            "surface": [
                {
                    "kind": "scope",
                    "name": "merchant-app-requirements-write"
                },
                {
                    "kind": "route",
                    "name": "PUT api/v1/merchant/app/requirements"
                }
            ],
            "limits": [
                "Claim binding is installation-scoped; property keys only."
            ],
            "workaround": "",
            "tags": [
                "bookings",
                "checkout",
                "merchant-api"
            ],
            "design_note": ""
        },
        {
            "id": "merchant.staff",
            "area": "merchant",
            "title": "Staff directory read",
            "summary": "An app can list the store staff directory: stable id, display name, role names and an active flag. Contact details, permissions and credentials are never exposed.",
            "status": "supported",
            "surface": [
                {
                    "kind": "scope",
                    "name": "merchant-team-directory-read"
                },
                {
                    "kind": "route",
                    "name": "GET team-directory"
                }
            ],
            "limits": [
                "Read-only and narrow: no email, phone, permissions or roles management; removed staff are never listed; inactive staff are listed with is_active false."
            ],
            "workaround": "",
            "tags": [
                "staff",
                "merchant-api"
            ],
            "design_note": ""
        },
        {
            "id": "messaging.send",
            "area": "messaging",
            "title": "Send shopper messages",
            "summary": "Queek has no send API for apps; apps send through their own providers. Queek\u2019s own merchant campaigns are a separate product: their SMS sends skip contacts whose SMS consent is unsubscribed but do not require a recorded opt-in.",
            "status": "missing",
            "surface": [
                {
                    "kind": "scope",
                    "name": "merchant-customers-read"
                },
                {
                    "kind": "scope",
                    "name": "merchant-customers-contact-read"
                },
                {
                    "kind": "scope",
                    "name": "merchant-customers-consent-update"
                },
                {
                    "kind": "scope",
                    "name": "merchant-customers-sms-consent-update"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/customers"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/merchant/customers/{customer}/email-marketing-consent"
                },
                {
                    "kind": "webhook",
                    "name": "customers_email_marketing_consent/update"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/merchant/customers/{customer}/sms-marketing-consent"
                },
                {
                    "kind": "webhook",
                    "name": "customers_marketing_consent/update"
                }
            ],
            "limits": [
                "Queek stores email unsubscribe and SMS consent states, and has no WhatsApp consent state.",
                "Queek does not ingest STOP replies.",
                "An import that stores info.marketing_opt_in=false excludes that contact from campaign reachability."
            ],
            "workaround": "Send through an app-owned provider. Read Queek\u2019s campaign audience and channel consent state, report consent and suppression changes through the consent endpoints, and handle STOP replies with the provider.",
            "tags": [
                "messaging",
                "marketing",
                "email",
                "sms",
                "whatsapp"
            ],
            "design_note": "Apps send through their own email or SMS provider. Queek provides consent state and events, not a send API."
        },
        {
            "id": "orders.read_import_status",
            "area": "orders",
            "title": "Orders read, create, import and status",
            "summary": "Apps can list and read orders in the same shape the order webhooks send, create an order for a customer that waits for payment (priced by the same engine the dashboard uses), import orders already charged elsewhere idempotently, move orders through the status machine including payment approval and rider assignment, and patch shipment and extension fields. Imports take their source attribution from the authenticated app installation.",
            "status": "supported",
            "surface": [
                {
                    "kind": "scope",
                    "name": "merchant-orders-read"
                },
                {
                    "kind": "scope",
                    "name": "merchant-orders-create"
                },
                {
                    "kind": "scope",
                    "name": "merchant-orders-status-update"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/orders"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/merchant/orders"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/orders/{order}"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/merchant/orders/import"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/merchant/orders/{order}/status"
                }
            ],
            "limits": [
                "Imports accept only orders already charged outside Queek.",
                "A created order is a real order that waits for payment by bank transfer or online; there is no separate draft record, no payment link in the response, and no way to create it already paid. Cash, wallet and split payments are not offered.",
                "Created orders are for pickup, in-store or delivery with one price from the engine: an app cannot set a price, a total or a status, and creation takes no metafields (patch them afterwards).",
                "Fulfilment orders are not available.",
                "Only recorded payment and Queek wallet-refund transactions are readable.",
                "Merchant-collected, offline, provider-side and manual-review refunds have no recorded refund row.",
                "Payouts are read as settlement batches and as withdrawal and rider settlement rows through their own scopes (see payments.payouts).",
                "A generic app installation takes its source from its key and omits channel; a supplied channel is rejected with 422.",
                "An installed legacy marketplace app must send a channel matching its own slug, or it receives 422.",
                "An import made with a merchant\u2019s own key must send a channel and may choose either legacy slug; the slugs are not reserved.",
                "Order lines carry variant_id (the variant p_id, null for a product without variants or a deleted variant), variant_uid and sku (the variant\u2019s, or the product\u2019s for a line without a variant), so sales per variant never need a match on variant_title; the sku is the store\u2019s current one, not a snapshot.",
                "The order list narrows to a creation window with from_date and to_date (whole days, YYYY-MM-DD) or date_range (today, this_week, this_month), counted in the platform time zone (Africa/Lagos); they combine with updated_after and every other filter.",
                "An import\u2019s delivery_fee and discount are required (send 0.00 for none). On a dev store its placed_at becomes the order\u2019s created_at (updated_at stays the import time, so updated_after polling still sees it) and must be within the last 120 days, the time a dev store keeps imported and generated test-data orders (older is 422; other dev-store orders are pruned at 30 days). On a live store the order is recorded now and placed_at is kept as its order date."
            ],
            "workaround": "",
            "tags": [
                "orders",
                "import",
                "cursor",
                "merchant-api"
            ],
            "design_note": ""
        },
        {
            "id": "orders.returns",
            "area": "orders",
            "title": "Returns and exchanges",
            "summary": "Apps can refund an order with line-level restocking through the refund operation, but there is no return workflow: no return request, no receive or inspect step and no exchange.",
            "status": "missing",
            "surface": [],
            "limits": [],
            "workaround": "Handle returns in the app-hosted flow, then refund the order with POST /orders/{order}/refunds; send the returned lines in line_items to put the stock back.",
            "tags": [
                "orders",
                "returns",
                "refunds"
            ],
            "design_note": ""
        },
        {
            "id": "payments.operations",
            "area": "payments",
            "title": "Refund an order",
            "summary": "Merchants and apps with the merchant-orders-refund-create scope can refund an order payment, in full or in part, from the dashboard or with POST /orders/{order}/refunds. The refund follows the original payment: a payment the merchant took on their own gateway or offline is recorded only, with no money moved by Queek; a wallet payment goes back to the wallet; a card or bank payment Queek collected goes back to the original card or bank through the payment provider. The store\u2019s ledger is debited, tracked stock is restocked and the customer is notified. Capture and void are not offered.",
            "status": "supported",
            "surface": [
                {
                    "kind": "scope",
                    "name": "merchant-orders-refund-create"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/merchant/orders/{order}/refunds"
                },
                {
                    "kind": "webhook",
                    "name": "refunds/create"
                },
                {
                    "kind": "webhook",
                    "name": "orders/updated"
                }
            ],
            "limits": [
                "A refund cannot exceed what was received minus what was already refunded, and it cannot be undone.",
                "A recorded refund moves no money: the merchant refunds the customer outside Queek.",
                "A provider refund starts pending and ends success or failed: read it from the order\u2019s refunds list or from the refunds/create and orders/updated events. A card refund can take up to 10 business days to reach the customer.",
                "Idempotency-Key is required on every refund request.",
                "Provider refunds are available for Naira payments Queek collected through Paystack, within the provider\u2019s one-year window; other payments are refunded to the wallet or recorded.",
                "Capture and void are not offered by design: Queek charges the customer immediately, so there is no authorised-but-uncaptured payment to capture or void.",
                "The scope is review-required: an app holds it only with the merchant\u2019s approval."
            ],
            "workaround": "",
            "tags": [
                "payments",
                "refunds",
                "transactions"
            ],
            "design_note": ""
        },
        {
            "id": "payments.payouts",
            "area": "payments",
            "title": "Payout and settlement reads",
            "summary": "Apps can read what the store has been paid and what has left it. Released daily seller settlement batches and their order entries need merchant-payout-batches-read; bank withdrawals and rider settlements need merchant-payout-ledger-read, a separate grant that shows the destination bank by name and last four digits only.",
            "status": "supported",
            "surface": [
                {
                    "kind": "scope",
                    "name": "merchant-payout-batches-read"
                },
                {
                    "kind": "scope",
                    "name": "merchant-payout-ledger-read"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/payouts"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/payouts/{payout}"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/payout-transactions"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/payout-transactions/{transaction}"
                }
            ],
            "limits": [
                "Payouts are read only: an app cannot start a withdrawal, change a bank account or move money.",
                "A withdrawal shows the bank name and the last four digits of the account. The account holder, the full number and the bank code are never returned.",
                "A batch is one released day of order settlements. Withdrawals and rider settlements are separate rows, read with payout-transactions and their own scope.",
                "Withdrawals and rider settlements are identified by a UUID, not a short numeric id.",
                "Both scopes are available to installed apps only, with merchant approval."
            ],
            "workaround": "",
            "tags": [
                "payments",
                "payouts",
                "accounting"
            ],
            "design_note": ""
        },
        {
            "id": "payments.provider_registration",
            "area": "payments",
            "title": "Register an app payment provider",
            "summary": "Released first-party payment apps add a payment provider through their manifest. The merchant installs the app, then connects and verifies credentials per store in the dashboard.",
            "status": "supported",
            "surface": [
                {
                    "kind": "config",
                    "name": "payment_providers"
                },
                {
                    "kind": "manifest",
                    "name": "payment_provider"
                }
            ],
            "limits": [
                "Approved Queek-built payment apps register providers. Third-party apps cannot: keeping third-party code out of the charge path is deliberate.",
                "A registered provider is not available until the merchant has an active install of the app and verified gateway credentials."
            ],
            "workaround": "A merchant who needs a provider Queek does not yet carry can connect one of the supported providers in the dashboard.",
            "tags": [
                "payments",
                "checkout",
                "extension"
            ],
            "design_note": ""
        },
        {
            "id": "payments.refund_events",
            "area": "payments",
            "title": "Refund and payment events",
            "summary": "Apps can subscribe to refunds/create, sent whenever Queek records a refund: a refund to the customer\u2019s wallet, a refund to the original card or bank through the payment provider, or a refund the merchant recorded after refunding outside Queek. Apps with the merchant-orders-read grant receive it. A card or bank refund finishing or failing is signalled by orders/updated and shown in the order\u2019s refunds list. There is no other payment-specific topic.",
            "status": "supported",
            "surface": [
                {
                    "kind": "webhook",
                    "name": "refunds/create"
                },
                {
                    "kind": "webhook",
                    "name": "orders/updated"
                },
                {
                    "kind": "scope",
                    "name": "merchant-orders-read"
                }
            ],
            "limits": [
                "refunds/create is sent once, when the refund is created, with its state at that moment; a card or bank refund is usually pending then, and it finishing or failing is signalled by orders/updated and shown in the order\u2019s refunds list.",
                "The payload is small: the refund id, the order id, the refunded payment id, the amount as a decimal string with its currency, the status, the type (wallet_credit, original_payment or recorded), the reason (order_cancelled or merchant_refund), and the time. It carries no note, customer details or balances.",
                "Delivery needs an active installation that holds merchant-orders-read, the scope that also gates recorded payments and refunds on the order read.",
                "Delivery is at least once; an app added later is not sent refunds already made and reads them from the order.",
                "There are no payment-created, payment-failed or payout topics."
            ],
            "workaround": "",
            "tags": [
                "payments",
                "refunds",
                "webhooks"
            ],
            "design_note": ""
        },
        {
            "id": "payments.session_lifecycle",
            "area": "payments",
            "title": "Create and resolve payment sessions",
            "summary": "App credentials expose no payment-session endpoint. Queek checkout runs the merchant or platform provider flow, so an app cannot create, resolve or reject a payment session.",
            "status": "missing",
            "surface": [],
            "limits": [
                "Apps cannot start Queek checkout payments or receive payment-session callbacks through app credentials."
            ],
            "workaround": "An installed app can import orders already charged on its external platform with POST /orders/import. This records the payment but does not create or resolve a payment session.",
            "tags": [
                "payments",
                "callbacks",
                "idempotency"
            ],
            "design_note": ""
        },
        {
            "id": "platform.ai_runtime",
            "area": "platform",
            "title": "Call an AI runtime from an app",
            "summary": "App credentials have no endpoint for invoking Queek AI services, and the merchant AI tools are not an app runtime.",
            "status": "missing",
            "surface": [],
            "limits": [
                "Apps cannot invoke Queek AI through their app credentials or receive app-scoped usage and billing."
            ],
            "workaround": "Call an AI provider from the app server and keep provider credentials and usage controls there.",
            "tags": [
                "ai",
                "runtime",
                "apps"
            ],
            "design_note": "Apps bring their own model. Queek does not host a model for apps to call."
        },
        {
            "id": "platform.analytics",
            "area": "platform",
            "title": "Analytics query and app events",
            "summary": "Apps can read up to 30 days of anonymous storefront traffic, and sales, product and customer aggregates for ranges of up to 90 days.",
            "status": "supported",
            "surface": [
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/analytics/traffic"
                },
                {
                    "kind": "scope",
                    "name": "merchant-analytics-traffic-read"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/analytics/sales"
                },
                {
                    "kind": "scope",
                    "name": "merchant-analytics-sales-read"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/analytics/products"
                },
                {
                    "kind": "scope",
                    "name": "merchant-analytics-products-read"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/analytics/customers"
                },
                {
                    "kind": "scope",
                    "name": "merchant-analytics-customers-read"
                }
            ],
            "limits": [
                "Sales, product and customer reads cover whole days, at most 90 days, ending no later than today. Answers are cached for up to three minutes and shared by every app of the store, so a new order can take that long to show.",
                "Each installation may make 20 analytics reads a minute and 1,000 a day across the sales, products and customers routes; a cached answer counts too.",
                "Customer analytics are counts, rates and one average: no customer, name or contact is returned. Sales leaves out net revenue, fees and settlements, which are payments data.",
                "There is no event ingestion, report builder or query language, and no row-level order, product or customer export through analytics."
            ],
            "workaround": "Use the fixed aggregates; list orders or customers through their own routes for row-level data. This API does not accept events or custom reports.",
            "tags": [
                "analytics",
                "reports",
                "events"
            ],
            "design_note": ""
        },
        {
            "id": "platform.automation",
            "area": "platform",
            "title": "Workflow automation",
            "summary": "Webhooks are notifications, not workflows. There is no trigger and action registry, no merchant workflow builder and no run history.",
            "status": "missing",
            "surface": [
                {
                    "kind": "manifest",
                    "name": "dashboard.actions"
                }
            ],
            "limits": [],
            "workaround": "Consume webhook events and run app-owned automation on the app server.",
            "tags": [
                "automation",
                "events",
                "workflow"
            ],
            "design_note": ""
        },
        {
            "id": "platform.billing",
            "area": "platform",
            "title": "App billing and usage metering",
            "summary": "Manifest pricing is display-only. There is no app-charge, recurring-billing or usage-metering API, so apps are free or bill outside Queek.",
            "status": "missing",
            "surface": [],
            "limits": [],
            "workaround": "Bill on the app-hosted page with an off-platform provider; gate features by installation in the app database.",
            "tags": [
                "billing",
                "monetisation"
            ],
            "design_note": ""
        },
        {
            "id": "platform.checkout_ui",
            "area": "platform",
            "title": "Checkout UI extensions",
            "summary": "Apps have no surface inside the checkout flow. Checkout stays closed because pricing and payment integrity depend on one platform path.",
            "status": "missing",
            "surface": [],
            "limits": [],
            "workaround": "Collect input and payment on the app-hosted page before handing off to checkout.",
            "tags": [
                "checkout",
                "extensions",
                "payments"
            ],
            "design_note": "Checkout stays one platform path so the price and the payment are exactly what the shopper saw; collect extra input on product blocks, through order attributes, or on an app page before checkout."
        },
        {
            "id": "platform.media",
            "area": "platform",
            "title": "App-owned files and uploads",
            "summary": "Apps can upload JPEG, PNG and WebP images, list the images uploaded by the same app connection, change their alt text, see where each one is used in the store and delete the ones nothing uses.",
            "status": "supported",
            "surface": [
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/files"
                },
                {
                    "kind": "scope",
                    "name": "merchant-media-read"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/merchant/files"
                },
                {
                    "kind": "scope",
                    "name": "merchant-media-create"
                },
                {
                    "kind": "route",
                    "name": "PATCH api/v1/merchant/files/{file}"
                },
                {
                    "kind": "scope",
                    "name": "merchant-media-update"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/files/{file}/references"
                },
                {
                    "kind": "route",
                    "name": "DELETE api/v1/merchant/files/{file}"
                },
                {
                    "kind": "scope",
                    "name": "merchant-media-delete"
                }
            ],
            "limits": [
                "Each upload is one JPEG, PNG or WebP image up to 10 MiB, 4,472 pixels on either side and 6 megapixels.",
                "Store up to 500 images.",
                "Make up to 300 uploads per day and 10 per minute.",
                "Use up to 256 MiB of storage counting generated sizes at three times the original.",
                "An app can change and delete only the images its own installation uploaded; images the merchant uploaded, or another app uploaded, answer not found.",
                "Only the alt text of an image can be changed. To replace a picture, upload a new image, move its users to it and delete the old one.",
                "An image used on a product (any image slot, a gallery, a video poster or a variant image), as the store logo or banner, or in a metafield value cannot be deleted: the answer is a conflict that lists those places. An app can never detach an image from them.",
                "Images placed on a storefront page or in a theme setting by address rather than by id are not tracked, so deleting such an image breaks that placement.",
                "Apps cannot upload documents or animated images, import a file from a URL, or accept shopper uploads."
            ],
            "workaround": "Downscale large photos in the app before upload, because a 12 megapixel phone photo is over the limit. For other file types or for merchant-uploaded files, use the merchant dashboard; app image settings can reference a URL.",
            "tags": [
                "files",
                "media",
                "uploads"
            ],
            "design_note": ""
        },
        {
            "id": "platform.pos",
            "area": "platform",
            "title": "POS extensions",
            "summary": "The POS is a first-party client with device sign-in and sync. App manifests have no POS target and there is no scoped POS bridge, so a third-party app cannot add tiles, cart actions or panels.",
            "status": "missing",
            "surface": [],
            "limits": [],
            "workaround": "Apps use the Merchant API where their credential permits; nothing renders inside the POS.",
            "tags": [
                "pos",
                "extensions",
                "native"
            ],
            "design_note": ""
        },
        {
            "id": "platform.realtime",
            "area": "platform",
            "title": "Realtime channel for apps",
            "summary": "Queek has no realtime channel for apps, and none is needed: an app runs its own socket server and loads it in a storefront embed, is told of new shopper messages by the conversation_messages/create webhook, and replies through the conversations API.",
            "status": "supported",
            "surface": [
                {
                    "kind": "webhook",
                    "name": "conversation_messages/create"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/merchant/conversations/{conversation}/messages"
                }
            ],
            "limits": [
                "Apps cannot publish to Queek\u2019s own merchant or storefront channels or subscribe to visitor presence or typing."
            ],
            "workaround": "Run your own socket server and load it in a storefront embed; learn of new shopper messages from the webhook and reply through the conversations API.",
            "tags": [
                "realtime",
                "chat"
            ],
            "design_note": ""
        },
        {
            "id": "platform.sales_channels",
            "area": "platform",
            "title": "Registerable sales channels",
            "summary": "Apps can register channel publications and curate products and collections through the Merchant API, and imported orders carry publication attribution. Product search can be narrowed to one of the app\u2019s publications. A headless or mobile app sells through the store\u2019s own client API key; its orders are not attributed to a publication unless the app imports them.",
            "status": "supported",
            "surface": [
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/publications"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/merchant/publications"
                },
                {
                    "kind": "route",
                    "name": "PATCH api/v1/merchant/publications/{publication}/resources"
                },
                {
                    "kind": "scope",
                    "name": "merchant-publications-read"
                },
                {
                    "kind": "scope",
                    "name": "merchant-publications-create"
                },
                {
                    "kind": "scope",
                    "name": "merchant-publications-update"
                }
            ],
            "limits": [
                "At most 10 publications per installation.",
                "At most 50 refs per write.",
                "Only the store\u2019s own collections can be published; global collections are refused.",
                "Filtering by collection and publication covers manual collections only; smart collection membership is not listable.",
                "Built-in sales channels are managed by Queek and cannot be changed by apps.",
                "Product search can be narrowed to one of the calling installation\u2019s publications (publication = its p_id or key); another app\u2019s or an unknown publication answers 404, an archived one 410, and a search cursor is bound to that publication.",
                "Checkout attribution is not provided: an order\u2019s publication is set only by the order import, and there is no shopper checkout context for it.",
                "Additions appear through a publication plus updated_after read; removals are found only by reconciling the full list, and collections are re-listed.",
                "Nothing is pushed to the app."
            ],
            "workaround": "Narrow product search to the publication, send shoppers to the store\u2019s own product page, and import the order to record attribution.",
            "tags": [
                "sales_channel",
                "catalog",
                "publication"
            ],
            "design_note": ""
        },
        {
            "id": "platform.versions",
            "area": "platform",
            "title": "App versions, review and release",
            "summary": "Apps keep immutable versions with versioned config, release control and review submission. Version history, review status, reviewer notes and the review thread can be read through the developer routes, but there is no dedicated rollback operation.",
            "status": "supported",
            "surface": [
                {
                    "kind": "route",
                    "name": "POST api/v1/biz/vendor/developer/apps/{app}/versions/{version}/release"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/biz/vendor/developer/apps/{app}/submit"
                }
            ],
            "limits": [
                "There is no dedicated rollback operation."
            ],
            "workaround": "Drive registration, versions, release and submission through the developer routes, and list versions to see history.",
            "tags": [
                "lifecycle",
                "versions",
                "review"
            ],
            "design_note": ""
        },
        {
            "id": "reviews.product_reviews",
            "area": "reviews",
            "title": "Product reviews: import, read, reply and moderate",
            "summary": "An app can import product reviews and read back the ones it imported. With merchant-product_reviews-read it reads every review of the store in any moderation state, the reviewer shown as first name and last initial. With merchant-product_reviews-respond it publishes the store\u2019s public reply, and with merchant-product_reviews-moderate it approves, hides or holds a review, which moves the product rating at once. Queek sends its own review request two days after delivery unless the store has switched review requests off; an app that sends its own can use the orders/fulfilled webhook as its trigger, once the merchant has switched Queek\u2019s request off so a shopper is not asked twice.",
            "status": "supported",
            "surface": [
                {
                    "kind": "scope",
                    "name": "merchant-reviews-read"
                },
                {
                    "kind": "scope",
                    "name": "merchant-reviews-import"
                },
                {
                    "kind": "scope",
                    "name": "merchant-product_reviews-read"
                },
                {
                    "kind": "scope",
                    "name": "merchant-product_reviews-respond"
                },
                {
                    "kind": "scope",
                    "name": "merchant-product_reviews-moderate"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/reviews"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/merchant/reviews/import"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/product-reviews"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/product-reviews/{review}"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/merchant/product-reviews/{review}/response"
                },
                {
                    "kind": "route",
                    "name": "PATCH api/v1/merchant/product-reviews/{review}/status"
                },
                {
                    "kind": "webhook",
                    "name": "orders/fulfilled"
                }
            ],
            "limits": [
                "Review requests, asking shoppers to review after delivery: Queek sends its own two days after delivery, on unless the store switches it off in its settings. Apps cannot send one through Queek or read that setting. An app that sends its own from its own channel when orders/fulfilled arrives should ask the merchant to switch Queek\u2019s off, or shoppers are asked twice. Request timing, contact permission and duplicate delivery are the app\u2019s to manage.",
                "Reviews are identified by a UUID, not a short numeric id; the product is its p_id.",
                "The reviewer is the first name and last initial only: no full name, avatar, email, phone or order.",
                "A reply is published under the store\u2019s name and replaces the previous one; there is no way to remove a reply.",
                "Moderating a review changes the public product rating at once and applies to any review of the store, including shopper reviews and other apps\u2019 imports.",
                "Imported reviews are marked unverified.",
                "Approved imports affect product ratings and Explore ordering, and appear in the shopper product review list, summary and latest approved reviews.",
                "Verified-only storefront blocks, store-wide block summaries and testimonials hide imports by default; merchants can opt in with verified_only=0.",
                "Apps cannot retract an imported review after submission, and cannot edit or delete a review."
            ],
            "workaround": "Ask the merchant to switch Queek\u2019s own review request off, then send review requests from the app\u2019s own channel when the orders/fulfilled webhook arrives, reading the shopper\u2019s contact and consent with the customer scopes. Ask the merchant to enable unverified reviews in the storefront blocks, summaries or testimonials that should show imports.",
            "tags": [
                "reviews",
                "products",
                "import",
                "moderation"
            ],
            "design_note": ""
        },
        {
            "id": "shipping.carrier_rates",
            "area": "shipping",
            "title": "Live carrier rates at checkout",
            "summary": "A shipping app cannot return live rates into checkout. Apps can manage static shipping zones, but checkout has no carrier callback for live quotes.",
            "status": "missing",
            "surface": [
                {
                    "kind": "scope",
                    "name": "merchant-shipping-read"
                }
            ],
            "limits": [],
            "workaround": "Keep merchant-configured flat zones, or quote live rates on the app-hosted page before handing the shopper to checkout.",
            "tags": [
                "shipping",
                "checkout",
                "carrier"
            ],
            "design_note": ""
        },
        {
            "id": "shipping.delivery_customization",
            "area": "shipping",
            "title": "Tailor checkout delivery options",
            "summary": "No app hook can rename, reorder, hide or generate delivery choices at checkout. The available delivery modes are merchant configuration.",
            "status": "missing",
            "surface": [],
            "limits": [],
            "workaround": "Shape the offer with the merchant-configured fulfilment modes for each store.",
            "tags": [
                "shipping",
                "checkout",
                "functions"
            ],
            "design_note": "Queek presents one resolved Delivery option per order; shape the offer with shipping zones and the store\u2019s own delivery settings."
        },
        {
            "id": "shipping.fulfillment",
            "area": "shipping",
            "title": "Fulfil shipped orders",
            "summary": "Apps can fulfil shipped orders end to end: react to orders/paid, write the carrier and tracking, assign the store rider and move the order status. Each store is one fulfilment location, and orders have no accept or reject step for external providers.",
            "status": "supported",
            "surface": [
                {
                    "kind": "scope",
                    "name": "merchant-orders-status-update"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/merchant/orders/{order}/assign-rider"
                },
                {
                    "kind": "route",
                    "name": "PATCH api/v1/merchant/orders/{order}/shipment"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/merchant/orders/{order}/status"
                },
                {
                    "kind": "webhook",
                    "name": "orders/paid"
                },
                {
                    "kind": "webhook",
                    "name": "orders/fulfilled"
                }
            ],
            "limits": [
                "Each store is one fulfilment location: there are no fulfilment locations and no per-location stock.",
                "There is no fulfilment-order workflow and no accept or reject step for external providers.",
                "The shipment write needs a shipping-method or courier order: self-delivery and pickup orders answer 404, so read the order\u2019s delivery method first."
            ],
            "workaround": "Subscribe to orders/paid, write carrier and tracking through the shipment endpoint, then move the order status. For self-delivery and pickup orders assign the store rider and move the status instead.",
            "tags": [
                "fulfillment",
                "shipping",
                "locations"
            ],
            "design_note": ""
        },
        {
            "id": "shipping.tracking",
            "area": "shipping",
            "title": "Shipment tracking writes",
            "summary": "Apps can write carrier, tracking number, tracking URL and shipment status onto an order through the merchant API.",
            "status": "supported",
            "surface": [
                {
                    "kind": "scope",
                    "name": "merchant-orders-update"
                },
                {
                    "kind": "route",
                    "name": "PATCH api/v1/merchant/orders/{order}/shipment"
                }
            ],
            "limits": [
                "Writes only; there is no carrier tracking-event callback or polling contract."
            ],
            "workaround": "",
            "tags": [
                "shipping",
                "tracking",
                "merchant-api"
            ],
            "design_note": ""
        },
        {
            "id": "shipping.zones",
            "area": "shipping",
            "title": "Static shipping zones and rates",
            "summary": "Apps can list, create and update the merchant static shipping zones and rates through the merchant API.",
            "status": "supported",
            "surface": [
                {
                    "kind": "scope",
                    "name": "merchant-shipping-read"
                },
                {
                    "kind": "scope",
                    "name": "merchant-shipping-create"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/shipping-zones"
                }
            ],
            "limits": [
                "Flat merchant-configured zones only; no live rate callback (see carrier rates)."
            ],
            "workaround": "",
            "tags": [
                "shipping",
                "zones",
                "merchant-api"
            ],
            "design_note": ""
        },
        {
            "id": "storefront.blocks",
            "area": "storefront",
            "title": "Product-page app blocks",
            "summary": "Declared app blocks on product targets from a small schema (date, time, select, shopper text input (line_text), and one optional submit button); availability reads through the signed proxy (a line_text block needs no proxy read), the submit button posts the block\u2019s choices to the app, other actions deep-link out.",
            "status": "supported",
            "surface": [
                {
                    "kind": "manifest",
                    "name": "extensions.blocks"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/client/app-placements"
                }
            ],
            "limits": [
                "Product targets only.",
                "A block may declare one submit element, accepted only for an app that declares extensions.proxy.allow_post and granted by the merchant; the storefront posts the block\u2019s other choices as one JSON object, with the product, through the signed proxy. Without the grant the block stays read-only.",
                "A block renders only after its read at the same path answers, so an app with a submit element must answer that read, even with an empty object. A block made only of line_text fields makes no proxy read.",
                "A line_text field takes shopper text up to its max_length (1 to 500, default 100); a manifest declares at most 3, a block holding one holds only line_text fields and shows on declared products only, and the text is untrusted shopper input: treat every value as such. A version that adds line_text goes through review."
            ],
            "workaround": "",
            "tags": [
                "storefront",
                "extensions"
            ],
            "design_note": ""
        },
        {
            "id": "storefront.customer_account",
            "area": "storefront",
            "title": "Shopper account extensions",
            "summary": "Apps cannot mount on shopper account pages: there are no full-page, order, profile or block targets in the signed-in customer area.",
            "status": "missing",
            "surface": [],
            "limits": [],
            "workaround": "Serve account-adjacent features on the app-hosted page with the customer reads.",
            "tags": [
                "customer_account",
                "extensions",
                "identity"
            ],
            "design_note": ""
        },
        {
            "id": "storefront.embeds",
            "area": "storefront",
            "title": "Site-wide storefront embeds",
            "summary": "Apps can display merchant-enabled, sandboxed body embeds across eligible storefront pages through a controlled iframe surface.",
            "status": "supported",
            "surface": [
                {
                    "kind": "manifest",
                    "name": "extensions.blocks"
                },
                {
                    "kind": "manifest",
                    "name": "extensions.embeds"
                }
            ],
            "limits": [
                "Each embed has exactly one capability: chat bubble, banner, popup, or scroll to top.",
                "Embeds render in the storefront body only; apps cannot add head content or inline scripts.",
                "The iframe sandbox does not allow forms or popups. Link-out chat buttons such as wa.me and t.me, and native form posts, cannot work inside an embed.",
                "At most three embeds can be enabled per store; each embed is off until the merchant enables it.",
                "Embeds support the functional consent category only.",
                "The iframe receives no shopper or customer identity.",
                "The queek app deploy command rejects embeds until the developer CLI is updated."
            ],
            "workaround": "First-party apps can be registered through the Developer page until queek app deploy is updated to accept embeds.",
            "tags": [
                "storefront",
                "extensions",
                "chat"
            ],
            "design_note": ""
        },
        {
            "id": "storefront.identity",
            "area": "storefront",
            "title": "Shopper identity to apps",
            "summary": "The proxy passes the logged-in customer id only when the app\u2019s grant, the manifest flag, the platform switch and the shopper\u2019s session all agree. Logged-out shoppers read as blank, and a POST carries the same identity rules as a read.",
            "status": "supported",
            "surface": [
                {
                    "kind": "route",
                    "name": "GET api/v1/client/apps/{appSlug}/{path}"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/client/apps/{appSlug}/{path}"
                },
                {
                    "kind": "config",
                    "name": "apps.proxy_share_customer_id_enabled"
                }
            ],
            "limits": [
                "There is no anonymous visitor id: a logged-out shopper reads as blank, and the id Queek passes is the store customer id, never a cross-store identity.",
                "The proxy has no email-capture call, and a collected email is neither proof of identity nor permission to market to that person. A storefront can subscribe a shopper to the store\u2019s email list through the public subscribe endpoint, and an app can file what it captured as a collected record from its server.",
                "Apps cannot start a conversation with a shopper; they can reply to a conversation the shopper started through the conversation API."
            ],
            "workaround": "Read the passed customer id for signed-in shoppers. For anyone else, capture identity on the app-hosted page behind the deep link from the block.",
            "tags": [
                "storefront",
                "proxy",
                "identity",
                "privacy"
            ],
            "design_note": ""
        },
        {
            "id": "storefront.page_composition",
            "area": "storefront",
            "title": "Compose storefront pages",
            "summary": "An app can list, read, create, update and delete a store\u2019s pages and write their sections, always as drafts. The merchant reviews and publishes in the dashboard; an app cannot publish.",
            "status": "supported",
            "surface": [
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/pages"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/pages/{page}"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/merchant/pages"
                },
                {
                    "kind": "route",
                    "name": "PATCH api/v1/merchant/pages/{page}"
                },
                {
                    "kind": "route",
                    "name": "DELETE api/v1/merchant/pages/{page}"
                },
                {
                    "kind": "scope",
                    "name": "merchant-pages-read"
                },
                {
                    "kind": "scope",
                    "name": "merchant-pages-detail"
                },
                {
                    "kind": "scope",
                    "name": "merchant-pages-create"
                },
                {
                    "kind": "scope",
                    "name": "merchant-pages-update"
                },
                {
                    "kind": "scope",
                    "name": "merchant-pages-delete"
                }
            ],
            "limits": [
                "Drafts only: a page an app creates is a draft and a change to a published page is saved as a draft beside it. An app cannot publish, schedule or unpublish, so status, published_at, is_home, template and chrome are refused.",
                "On a published page only sections can be written; its title, slug and SEO would change the live page, so they answer 409. A published page or the home page cannot be deleted by an app.",
                "Sections use the same section list the dashboard saves, limited to a safe subset for apps: no embed, video, contact or metaobjects sections, no raw HTML, links only as http(s), root-relative or #fragment (mailto: and tel: on link fields), background colour as a hex value, and no per-section tokens or dynamic-source bindings. At most 50 sections and 256 KB per page.",
                "The page list and read answer the live sections beside the draft sections; there is no preview link for a draft.",
                "The scopes merchant-pages-create, merchant-pages-update and merchant-pages-delete are review-required when added to an app version."
            ],
            "workaround": "Write the page as a draft through the pages API and ask the merchant to review and publish it in the storefront editor; use an app block for app-owned content in supported placements.",
            "tags": [
                "storefront",
                "pages",
                "sections",
                "page-builder"
            ],
            "design_note": ""
        },
        {
            "id": "storefront.proxy",
            "area": "storefront",
            "title": "Storefront app proxy (read)",
            "summary": "One signed server-to-server read per shopper request, with replay rules, pinned fetch, per-install throttling and no shared caching.",
            "status": "supported",
            "surface": [
                {
                    "kind": "route",
                    "name": "GET api/v1/client/apps/{appSlug}/{path}"
                },
                {
                    "kind": "config",
                    "name": "apps.proxy_max_bytes"
                }
            ],
            "limits": [
                "GET reads; writes are a separate opt-in (see storefront proxy writes). Tight body and time budgets per call."
            ],
            "workaround": "",
            "tags": [
                "storefront",
                "proxy"
            ],
            "design_note": ""
        },
        {
            "id": "storefront.proxy_post",
            "area": "storefront",
            "title": "Storefront proxy writes",
            "summary": "An app that declares extensions.proxy.allow_post, and whose merchant has accepted it, receives signed JSON POSTs from the storefront at its proxy URL. The signed query carries the verb, a sha256 of the exact body and the shopper\u2019s Idempotency-Key. A Queek-rendered product block can post its choices through a submit element.",
            "status": "supported",
            "surface": [
                {
                    "kind": "route",
                    "name": "POST api/v1/client/apps/{appSlug}/{path}"
                },
                {
                    "kind": "manifest",
                    "name": "extensions.proxy.allow_post"
                },
                {
                    "kind": "config",
                    "name": "apps.proxy_post_max_bytes"
                }
            ],
            "limits": [
                "POST only, application/json only, one JSON object or array of at most 65,536 bytes; PUT, PATCH and DELETE are refused.",
                "Off until the app declares extensions.proxy.allow_post and the merchant accepts the update; installs made before the declaration stay read-only.",
                "Queek forwards the body and the signed query only: no cookies, Authorization header, client key, Origin or shopper IP reach the app. The shopper\u2019s customer id follows the same rules as reads.",
                "The app\u2019s 200, 201, 202, 204, 400, 409 and 422 answers are relayed; any other status, a non-JSON body or a timeout reads as a 424 app_proxy_failed. A timed-out POST may still have been processed, so dedupe on the signed idempotency_key.",
                "At most 20 submissions a minute per shopper IP and 600 a minute per installation.",
                "Embeds cannot post. A block posts only through its submit element, to its own proxy path, which is the same path its read uses, so an app with several blocks tells them apart by the body.",
                "The queek app deploy command accepts extensions.proxy.allow_post from CLI 0.15.5; older versions reject it."
            ],
            "workaround": "Declare allow_post and a submit element in the block schema and deploy with the queek CLI (a release newer than 0.15.5) or the Developer page. For any other surface, send the POST from storefront code on the store\u2019s own origin or deep-link to an app-hosted page.",
            "tags": [
                "storefront",
                "proxy",
                "mutations"
            ],
            "design_note": ""
        },
        {
            "id": "storefront.search",
            "area": "storefront",
            "title": "App-scoped product search",
            "summary": "Apps can search a store\u2019s shopper-visible products by keyword, availability and defined metafields.",
            "status": "supported",
            "surface": [
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/storefront/search"
                },
                {
                    "kind": "scope",
                    "name": "merchant-items-read"
                }
            ],
            "limits": [
                "Products only: this endpoint has no collection filters or results, recommendations, app-managed synonyms, total counts or facets.",
                "Keyword matching is a substring match on title, description or SKU with no relevance ranking, stemming or typo tolerance.",
                "The in_stock field in a result is the stored product value, while the in_stock filter checks active variants."
            ],
            "workaround": "Follow next_cursor for more products. For collections, pages and posts call the public storefront search (GET api/v1/client/store/search), which resolves the store from its host and needs no app credentials, or list collections with merchant-collections-read. Implement app-specific suggestions, synonyms and facets on the app server.",
            "tags": [
                "search",
                "discovery",
                "products"
            ],
            "design_note": ""
        },
        {
            "id": "storefront.theme_assets",
            "area": "storefront",
            "title": "Manage storefront theme assets",
            "summary": "Apps can register storefront blocks and use the app proxy, but cannot read or write theme files or inject arbitrary scripts.",
            "status": "missing",
            "surface": [],
            "limits": [
                "The app manifest has no theme asset or script-tag extension, and the public API has no route to read or write theme files."
            ],
            "workaround": "Use registered storefront blocks for app content, or ask the merchant to make theme edits in the storefront editor.",
            "tags": [
                "storefront",
                "theme",
                "assets",
                "scripts"
            ],
            "design_note": "Queek does not let apps inject scripts into storefronts or edit theme files. Use storefront embeds and product-page app blocks instead."
        },
        {
            "id": "storefront.web_pixels",
            "area": "storefront",
            "title": "Run consent-aware tracking pixels",
            "summary": "Apps have no pixel runtime for shopper events, consent-gated execution or conversion delivery.",
            "status": "missing",
            "surface": [],
            "limits": [
                "Storefront page-view tracking is not an app event subscription, and apps cannot register a pixel or receive consent-aware conversion events.",
                "The store itself can run Meta, TikTok and Pinterest browser pixels from ids the merchant sets (page view only, after the shopper accepts marketing cookies). An app cannot set, read or add to them."
            ],
            "workaround": "Ask the merchant to enter the network id in the dashboard Ad pixels card, or use the app backend for server-side events it can observe through the webhooks; do not install shopper-side tracking through Queek.",
            "tags": [
                "storefront",
                "marketing",
                "analytics",
                "consent",
                "pixels"
            ],
            "design_note": ""
        },
        {
            "id": "subscriptions.selling_plans",
            "area": "subscriptions",
            "title": "Recurring purchases",
            "summary": "The subscription feature bills merchants for their Queek plan, not shoppers. Apps get no customer subscription plans, billing contracts, renewal orders or billing attempts.",
            "status": "missing",
            "surface": [],
            "limits": [],
            "workaround": "Bill repeat purchases outside Queek and create each order through normal checkout when it is due.",
            "tags": [
                "subscriptions",
                "billing",
                "orders"
            ],
            "design_note": ""
        },
        {
            "id": "sync.bulk",
            "area": "sync",
            "title": "Bulk export and change feed",
            "summary": "An app can queue a whole-store export file (POST exports, then read the export until its download link is ready) and poll product, order and customer lists with best-effort updated_after reads. The export carries only the resources the app can read, with customer contact blank unless the app holds the contact scope. Deleted products and customers arrive as webhooks, so an app does not need to diff to find them.",
            "status": "supported",
            "surface": [
                {
                    "kind": "route",
                    "name": "POST api/v1/merchant/exports"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/exports/{export}"
                },
                {
                    "kind": "scope",
                    "name": "merchant-exports-create"
                },
                {
                    "kind": "scope",
                    "name": "merchant-exports-read"
                },
                {
                    "kind": "scope",
                    "name": "merchant-items-read"
                },
                {
                    "kind": "scope",
                    "name": "merchant-orders-read"
                },
                {
                    "kind": "scope",
                    "name": "merchant-customers-read"
                },
                {
                    "kind": "webhook",
                    "name": "products/delete"
                },
                {
                    "kind": "webhook",
                    "name": "customers/delete"
                }
            ],
            "limits": [
                "The export is a zip of products.csv, orders.csv and customers.csv with a manifest.json. Each file is included only when the app holds merchant-items-read, merchant-orders-read or merchant-customers-read; an app holding none of them cannot export. Without merchant-customers-contact-read the name, email and phone cells are blank.",
                "The export is built in the background and is a snapshot of the moment it was built. Order line items, delivery addresses and saved customer addresses are not in the files; manifest.json lists what is missing.",
                "One export runs per store at a time, and an installation may request three per 24 hours.",
                "The download link is a bearer link valid for seven days: anyone holding it can download the customer data in the archive. The two export scopes are protected, so adding them to an app version needs Queek review and the merchant approves them at install.",
                "Only product, order and customer lists support updated_after.",
                "Product changes to variants, images, metafields, stock, region, price, discounts, bulk publish, unpublish, archive status or inventory tracking may be missed.",
                "Order changes to items, properties, shipment, metafields or the customer profile may be missed.",
                "Customer changes are compared on each customer\u2019s updated_at, which has second precision; changes stored outside the customer record, such as order history, may be missed.",
                "Deletions arrive as products/delete and customers/delete webhooks, which carry the product or only the customer id. A customer who stops being a customer without the row being removed is reported by customers/delete as well. The lists and the export do not mark a record as removed, and delivery is at least once.",
                "Long-running updates can appear late.",
                "The comparison time is not returned and may differ from each object\u2019s updated_at.",
                "There is no snapshot or high-water mark for the lists."
            ],
            "workaround": "Request an export for the first full load, then poll products, orders and customers with updated_after, starting each poll at least five minutes before the previous poll started. Deduplicate by resource id, keep other filters fixed, consume webhooks including products/delete and customers/delete, and reconcile occasionally against a fresh export (or a full list walk) with what the app holds.",
            "tags": [
                "integrations",
                "bulk",
                "sync",
                "export"
            ],
            "design_note": ""
        },
        {
            "id": "sync.safety",
            "area": "sync",
            "title": "Idempotency, cursors and rate policy",
            "summary": "App writes are idempotent, list APIs page with cursors, and rate limits and retry guidance are published. There is no bulk reconciliation envelope.",
            "status": "supported",
            "surface": [],
            "limits": [
                "There is no bulk reconciliation endpoint; reconcile with cursor reads and updated_after (see sync.bulk)."
            ],
            "workaround": "Send an idempotency key on every write, page with cursors, and wait for Retry-After on a 429.",
            "tags": [
                "idempotency",
                "rate-limits",
                "cursor"
            ],
            "design_note": ""
        },
        {
            "id": "tax.calculation",
            "area": "tax",
            "title": "App-calculated tax at checkout",
            "summary": "Apps have no tax-calculation callback, and there is no tax-provider integration. Checkout applies only the tax rows the merchant configured.",
            "status": "missing",
            "surface": [],
            "limits": [],
            "workaround": "Ship jurisdiction logic in the app-hosted flow and keep the store rows aligned with it.",
            "tags": [
                "tax",
                "checkout",
                "partner"
            ],
            "design_note": ""
        },
        {
            "id": "tax.configuration",
            "area": "tax",
            "title": "Tax rows through the app API",
            "summary": "Apps can list, read, create and change the store\u2019s tax rows (name, rate, channel, priority, active) through the Merchant API, with the same rules as the dashboard. Checkout still applies only those rows.",
            "status": "supported",
            "surface": [
                {
                    "kind": "scope",
                    "name": "merchant-taxes-read"
                },
                {
                    "kind": "scope",
                    "name": "merchant-taxes-create"
                },
                {
                    "kind": "scope",
                    "name": "merchant-taxes-update"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/taxes"
                },
                {
                    "kind": "route",
                    "name": "GET api/v1/merchant/taxes/{tax}"
                },
                {
                    "kind": "route",
                    "name": "POST api/v1/merchant/taxes"
                },
                {
                    "kind": "route",
                    "name": "PATCH api/v1/merchant/taxes/{tax}"
                }
            ],
            "limits": [
                "A store keeps one active tax per channel: switching a tax on, or moving an active tax into a channel, switches off that channel\u2019s other active tax. A tax on `all` applies together with the active tax of the checkout\u2019s own channel.",
                "Taxes are exclusive: a rate is added on top of the discounted subtotal and never included in a price. Several taxes that apply are added side by side, never compounded, and each is rounded in the store\u2019s currency.",
                "A rate is 0 to 100 percent with at most two decimals. It is not validated against any country\u2019s tax rules: the merchant is responsible for the rate.",
                "There is no delete: switch a tax off with `active: false`. A name is unique per channel, switched-off taxes included, so bring a tax back with `active: true`.",
                "There is no tax-calculation callback and no tax-provider integration.",
                "The write scopes change what shoppers are charged: declaring them needs app approval, and installed stores must grant them. Reading taxes does not need approval."
            ],
            "workaround": "For jurisdiction logic, keep it in the app-hosted flow and write the resulting rows here.",
            "tags": [
                "tax",
                "merchant-api"
            ],
            "design_note": ""
        },
        {
            "id": "webhooks.carts_chat",
            "area": "webhooks",
            "title": "Abandoned-cart topics",
            "summary": "An app can read abandoned checkouts and subscribe to checkouts/create and checkouts/update. A signed-in customer's cart is reported once it has been unchanged for the idle delay (60 minutes by default). Shopper messages have their own topic, conversation_messages/create.",
            "status": "supported",
            "surface": [
                {
                    "kind": "webhook",
                    "name": "checkouts/create"
                },
                {
                    "kind": "webhook",
                    "name": "checkouts/update"
                },
                {
                    "kind": "scope",
                    "name": "merchant-checkouts-read"
                },
                {
                    "kind": "route",
                    "name": "GET abandoned-checkouts"
                }
            ],
            "limits": [
                "Events fire after a cart has been unchanged for the delay, not when it is created or edited, and a cart that keeps changing is not reported.",
                "Only carts of signed-in customers with a record at the store are reported, and only ones changed in the last 72 hours; guest carts, carts written only on the Queek marketplace, empty carts, carts not edited since this launched and carts of a customer the merchant deleted are not.",
                "A customer who placed an order after the cart last changed is not reported; abandoned payments are orders, so use orders/create and GET orders.",
                "A cart first built on the marketplace and later edited on the store's own channel is reported from that edit on.",
                "Delivery and the read need the merchant-checkouts-read grant; name, email and phone are null without merchant-customers-contact-read.",
                "The link is the store's checkout page, the same for every shopper, who signs in to see their cart. There are no prices, totals or per-cart recovery links.",
                "Delivery is at least once. An app added later is not sent carts already reported; it catches up with the list. A page walk is not a snapshot."
            ],
            "workaround": "Poll GET abandoned-checkouts with updated_since and deduplicate on the cart id and updated_at; use orders/create to detect completion.",
            "tags": [
                "webhooks",
                "events",
                "chat",
                "carts"
            ],
            "design_note": ""
        },
        {
            "id": "webhooks.core",
            "area": "webhooks",
            "title": "Orders, products, customers, inventory, locales webhooks",
            "summary": "Eighteen topics across orders, products, customers, inventory levels, locales and translations, with pinned delivery, multi-hour retry horizon and per-install echo suppression.",
            "status": "supported",
            "surface": [
                {
                    "kind": "webhook",
                    "name": "orders/create"
                },
                {
                    "kind": "webhook",
                    "name": "orders/paid"
                },
                {
                    "kind": "webhook",
                    "name": "products/update"
                }
            ],
            "limits": [
                "Customer topics are additionally gated by a privacy kill-switch."
            ],
            "workaround": "",
            "tags": [
                "webhooks",
                "events"
            ],
            "design_note": ""
        },
        {
            "id": "webhooks.delivery",
            "area": "webhooks",
            "title": "Delivery retries, replay and ordering",
            "summary": "Deliveries are signed, retried with backoff, and carry an event id that a retry reuses; an endpoint that keeps failing is disabled. Delivery replay exists in the merchant dashboard only.",
            "status": "supported",
            "surface": [],
            "limits": [
                "Deliveries are at-least-once and unordered; reconcile after any missed delivery.",
                "Replay is available in the merchant dashboard only, not through the Merchant API.",
                "A replay creates a new event id, so event-id deduplication alone does not make an operation idempotent."
            ],
            "workaround": "Dedupe on the event id and on the resource and operation, and reconcile against cursor reads.",
            "tags": [
                "webhooks",
                "reliability",
                "replay"
            ],
            "design_note": ""
        },
        {
            "id": "webhooks.lifecycle",
            "area": "webhooks",
            "title": "Lifecycle as subscribable topics",
            "summary": "Install, uninstall, resync, settings and scope-change events reach an app as signed server-to-server handoffs to the URLs in its manifest. They are handoffs rather than webhook topics because an uninstalled app\u2019s endpoint no longer exists.",
            "status": "supported",
            "surface": [
                {
                    "kind": "handoff",
                    "name": "app/uninstalled"
                }
            ],
            "limits": [
                "Handoffs need declared install and uninstall URLs and are verified by signature; they cannot be subscribed to as topics."
            ],
            "workaround": "Declare the handoff URLs and verify the envelope signature on your server.",
            "tags": [
                "webhooks",
                "events",
                "lifecycle"
            ],
            "design_note": ""
        },
        {
            "id": "webhooks.privacy",
            "area": "webhooks",
            "title": "Erasure and redaction topics",
            "summary": "A merchant can ask, from a customer's profile in the dashboard, for the customer's data (a data request, sent at once) or for the customer's personal data to be erased (an erasure, which waits ten days so it can be cancelled, and is held until 180 days after the customer's last order). The topics customers/data_request and customers/redact carry ids only and are delivered to every active install whose manifest declares them, with no scope or approval line. Shop redaction is the app/uninstalled handoff with data.reason set to store_deleted, sent when a store is deleted.",
            "status": "supported",
            "surface": [
                {
                    "kind": "webhook",
                    "name": "customers/data_request"
                },
                {
                    "kind": "webhook",
                    "name": "customers/redact"
                },
                {
                    "kind": "handoff",
                    "name": "app/uninstalled"
                },
                {
                    "kind": "webhook",
                    "name": "customers/delete"
                }
            ],
            "limits": [
                "Both requests are filed by the merchant in the dashboard. An app cannot file one, and deleting an account in the Queek mobile app does not send anything to the stores that customer bought from.",
                "The payload has ids only: the request id, the customer id, the customer's order ids (capped, with orders_truncated) and the request time. It never carries a name, email or phone, so an app that stored data keyed only by something it collected itself cannot be addressed by id.",
                "Delivery is at-least-once: dedupe on data.id, which a retry or a resend after a crash reuses. Delivery follows the webhook retry schedule and stops when the app's endpoint is disabled; Queek does not wait for the app to answer and does not track completion.",
                "An install whose manifest listed no webhook topics when it was installed has no endpoint and cannot receive these topics until it is reinstalled.",
                "The erasure notice is sent when the request falls due, then Queek anonymises its own copy for that store only. Queek keeps the financial order record (customer links and addresses removed), records tied to the customer's global platform account (reviews, ratings, comments, bookmarks, assistant threads) and messaging-gateway transcripts.",
                "customers/delete means removed from the store's directory, not erased.",
                "The store-deleted handoff is sent once per installation, after the 14-day grace period, and the store name in it reads as a deleted store. Delivery is queued and retried with backoff, and a store deletion does not wait for the app to answer."
            ],
            "workaround": "Declare customers/data_request and customers/redact in the manifest, answer 2xx, dedupe on data.id, and on customers/redact erase the customer's data in your own storage by the ids in the payload. On app/uninstalled with reason store_deleted, delete the installation and every copy of the store's customer data.",
            "tags": [
                "webhooks",
                "compliance",
                "privacy"
            ],
            "design_note": ""
        }
    ],
    "use_cases": [
        {
            "id": "analytics_reporting",
            "title": "Analytics and reporting app",
            "summary": "Store performance dashboards and event-driven insights per installation.",
            "needs": [
                {
                    "id": "platform.analytics",
                    "critical": true,
                    "status": "supported"
                },
                {
                    "id": "webhooks.core",
                    "critical": false,
                    "status": "supported"
                },
                {
                    "id": "webhooks.delivery",
                    "critical": false,
                    "status": "supported"
                },
                {
                    "id": "sync.bulk",
                    "critical": false,
                    "status": "supported"
                }
            ],
            "verdict": "buildable",
            "optional_gaps": []
        },
        {
            "id": "automation",
            "title": "Automation app",
            "summary": "Merchant-built workflows with app triggers and actions.",
            "needs": [
                {
                    "id": "platform.automation",
                    "critical": true,
                    "status": "missing"
                },
                {
                    "id": "webhooks.core",
                    "critical": false,
                    "status": "supported"
                },
                {
                    "id": "webhooks.delivery",
                    "critical": false,
                    "status": "supported"
                },
                {
                    "id": "sync.bulk",
                    "critical": false,
                    "status": "supported"
                }
            ],
            "verdict": "blocked",
            "optional_gaps": []
        },
        {
            "id": "b2b",
            "title": "B2B wholesale app",
            "summary": "Company buyers, negotiated catalogs and terms for wholesale storefronts.",
            "needs": [
                {
                    "id": "b2b.catalogs",
                    "critical": true,
                    "status": "missing"
                },
                {
                    "id": "customers.segments",
                    "critical": false,
                    "status": "supported"
                },
                {
                    "id": "discounts.checkout_validation",
                    "critical": true,
                    "status": "missing"
                },
                {
                    "id": "markets.currency",
                    "critical": false,
                    "status": "missing"
                }
            ],
            "verdict": "blocked",
            "optional_gaps": [
                {
                    "id": "markets.currency",
                    "status": "missing"
                }
            ]
        },
        {
            "id": "bookings",
            "title": "Bookings app",
            "summary": "Availability slots on product pages, hold tokens, merchant calendar on the dashboard sheet.",
            "needs": [
                {
                    "id": "storefront.blocks",
                    "critical": true,
                    "status": "supported"
                },
                {
                    "id": "storefront.proxy",
                    "critical": true,
                    "status": "supported"
                },
                {
                    "id": "merchant.requirements",
                    "critical": true,
                    "status": "supported"
                },
                {
                    "id": "dashboard.sheets",
                    "critical": false,
                    "status": "supported"
                },
                {
                    "id": "orders.read_import_status",
                    "critical": false,
                    "status": "supported"
                },
                {
                    "id": "webhooks.core",
                    "critical": false,
                    "status": "supported"
                }
            ],
            "verdict": "buildable",
            "optional_gaps": []
        },
        {
            "id": "discounts_loyalty",
            "title": "Discounts and loyalty app",
            "summary": "Points earning and redemption plus merchant-created discounts and coupons.",
            "needs": [
                {
                    "id": "discounts.primitives",
                    "critical": true,
                    "status": "supported"
                },
                {
                    "id": "discounts.storefront_redeem",
                    "critical": true,
                    "status": "supported"
                },
                {
                    "id": "loyalty.points",
                    "critical": false,
                    "status": "missing"
                },
                {
                    "id": "loyalty.gift_cards",
                    "critical": false,
                    "status": "partial"
                },
                {
                    "id": "customers.read",
                    "critical": false,
                    "status": "supported"
                },
                {
                    "id": "merchant.metafields",
                    "critical": false,
                    "status": "supported"
                }
            ],
            "verdict": "buildable",
            "optional_gaps": [
                {
                    "id": "loyalty.points",
                    "status": "missing"
                },
                {
                    "id": "loyalty.gift_cards",
                    "status": "partial"
                }
            ]
        },
        {
            "id": "erp_accounting_sync",
            "title": "ERP and accounting sync",
            "summary": "Keep an external ledger in sync with orders, stock, customers and payouts.",
            "needs": [
                {
                    "id": "orders.read_import_status",
                    "critical": true,
                    "status": "supported"
                },
                {
                    "id": "inventory.stock",
                    "critical": true,
                    "status": "supported"
                },
                {
                    "id": "customers.read",
                    "critical": false,
                    "status": "supported"
                },
                {
                    "id": "webhooks.core",
                    "critical": true,
                    "status": "supported"
                },
                {
                    "id": "webhooks.delivery",
                    "critical": false,
                    "status": "supported"
                },
                {
                    "id": "sync.bulk",
                    "critical": false,
                    "status": "supported"
                },
                {
                    "id": "sync.safety",
                    "critical": true,
                    "status": "supported"
                },
                {
                    "id": "payments.payouts",
                    "critical": false,
                    "status": "supported"
                }
            ],
            "verdict": "buildable",
            "optional_gaps": []
        },
        {
            "id": "forms",
            "title": "Forms app",
            "summary": "Merchant-built forms rendered on the storefront with submissions collected per installation.",
            "needs": [
                {
                    "id": "storefront.blocks",
                    "critical": true,
                    "status": "supported"
                },
                {
                    "id": "storefront.proxy",
                    "critical": true,
                    "status": "supported"
                },
                {
                    "id": "storefront.proxy_post",
                    "critical": false,
                    "status": "supported"
                },
                {
                    "id": "merchant.forms_records",
                    "critical": true,
                    "status": "supported"
                },
                {
                    "id": "platform.media",
                    "critical": false,
                    "status": "supported"
                }
            ],
            "verdict": "buildable",
            "optional_gaps": []
        },
        {
            "id": "marketplace_feed",
            "title": "Marketplace channel feed",
            "summary": "Publish the catalog to an external marketplace and pull its orders back in.",
            "needs": [
                {
                    "id": "channels.feed",
                    "critical": true,
                    "status": "supported"
                },
                {
                    "id": "platform.sales_channels",
                    "critical": true,
                    "status": "supported"
                },
                {
                    "id": "markets.currency",
                    "critical": false,
                    "status": "missing"
                },
                {
                    "id": "inventory.stock",
                    "critical": true,
                    "status": "supported"
                },
                {
                    "id": "orders.read_import_status",
                    "critical": true,
                    "status": "supported"
                },
                {
                    "id": "sync.safety",
                    "critical": true,
                    "status": "supported"
                }
            ],
            "verdict": "buildable",
            "optional_gaps": [
                {
                    "id": "markets.currency",
                    "status": "missing"
                }
            ]
        },
        {
            "id": "notifications",
            "title": "Notifications app",
            "summary": "Merchant alerts from an installed app in the dashboard bell, deduplicated and rate-capped, with a link to the app\u2019s page. Push, text, email, per-staff targeting and delivery receipts are not available to apps.",
            "needs": [
                {
                    "id": "dashboard.alerts",
                    "critical": true,
                    "status": "supported"
                },
                {
                    "id": "platform.realtime",
                    "critical": false,
                    "status": "supported"
                },
                {
                    "id": "merchant.staff",
                    "critical": false,
                    "status": "supported"
                },
                {
                    "id": "webhooks.core",
                    "critical": false,
                    "status": "supported"
                }
            ],
            "verdict": "buildable",
            "optional_gaps": []
        },
        {
            "id": "payment_gateway",
            "title": "Payment gateway app",
            "summary": "A third-party gateway that takes payment inside checkout and settles orders.",
            "needs": [
                {
                    "id": "payments.provider_registration",
                    "critical": true,
                    "status": "supported"
                },
                {
                    "id": "payments.session_lifecycle",
                    "critical": true,
                    "status": "missing"
                },
                {
                    "id": "payments.operations",
                    "critical": true,
                    "status": "supported"
                },
                {
                    "id": "payments.refund_events",
                    "critical": true,
                    "status": "supported"
                },
                {
                    "id": "payments.payouts",
                    "critical": false,
                    "status": "supported"
                },
                {
                    "id": "merchant.order_actions",
                    "critical": false,
                    "status": "supported"
                },
                {
                    "id": "webhooks.core",
                    "critical": true,
                    "status": "supported"
                },
                {
                    "id": "dashboard.embed",
                    "critical": false,
                    "status": "supported"
                }
            ],
            "verdict": "blocked",
            "optional_gaps": []
        },
        {
            "id": "pos_extension",
            "title": "POS extension app",
            "summary": "Tiles, cart actions and panels inside the point-of-sale client.",
            "needs": [
                {
                    "id": "platform.pos",
                    "critical": true,
                    "status": "missing"
                },
                {
                    "id": "developer.sdk",
                    "critical": false,
                    "status": "supported"
                },
                {
                    "id": "dashboard.alerts",
                    "critical": false,
                    "status": "supported"
                },
                {
                    "id": "webhooks.core",
                    "critical": false,
                    "status": "supported"
                }
            ],
            "verdict": "blocked",
            "optional_gaps": []
        },
        {
            "id": "reviews",
            "title": "Reviews app",
            "summary": "Import product reviews, read every review of the store, reply to reviews and approve or hide them. Storefront display of imports requires merchant approval and an explicit choice to include unverified reviews. Queek sends no review requests on an app\u2019s behalf: the app sends its own when the orders/fulfilled webhook announces a completed order.",
            "needs": [
                {
                    "id": "reviews.product_reviews",
                    "critical": true,
                    "status": "supported"
                },
                {
                    "id": "storefront.blocks",
                    "critical": true,
                    "status": "supported"
                },
                {
                    "id": "storefront.customer_account",
                    "critical": false,
                    "status": "missing"
                },
                {
                    "id": "dashboard.sheets",
                    "critical": false,
                    "status": "supported"
                },
                {
                    "id": "webhooks.core",
                    "critical": false,
                    "status": "supported"
                }
            ],
            "verdict": "buildable",
            "optional_gaps": [
                {
                    "id": "storefront.customer_account",
                    "status": "missing"
                }
            ]
        },
        {
            "id": "sales_channel",
            "title": "Sales channel app",
            "summary": "A new selling surface with its own catalog publication and attributed orders.",
            "needs": [
                {
                    "id": "platform.sales_channels",
                    "critical": true,
                    "status": "supported"
                },
                {
                    "id": "channels.feed",
                    "critical": true,
                    "status": "supported"
                },
                {
                    "id": "conversations.api",
                    "critical": false,
                    "status": "supported"
                },
                {
                    "id": "webhooks.core",
                    "critical": false,
                    "status": "supported"
                },
                {
                    "id": "platform.media",
                    "critical": false,
                    "status": "supported"
                },
                {
                    "id": "storefront.search",
                    "critical": false,
                    "status": "supported"
                }
            ],
            "verdict": "buildable",
            "optional_gaps": []
        },
        {
            "id": "shipping_carrier",
            "title": "Shipping carrier app",
            "summary": "Live carrier rates at checkout, label purchase, tracking on orders.",
            "needs": [
                {
                    "id": "shipping.zones",
                    "critical": false,
                    "status": "supported"
                },
                {
                    "id": "shipping.carrier_rates",
                    "critical": true,
                    "status": "missing"
                },
                {
                    "id": "shipping.fulfillment",
                    "critical": true,
                    "status": "supported"
                },
                {
                    "id": "shipping.tracking",
                    "critical": true,
                    "status": "supported"
                },
                {
                    "id": "webhooks.core",
                    "critical": true,
                    "status": "supported"
                },
                {
                    "id": "dashboard.embed",
                    "critical": false,
                    "status": "supported"
                }
            ],
            "verdict": "blocked",
            "optional_gaps": []
        },
        {
            "id": "storefront_chat",
            "title": "Storefront chat app",
            "summary": "A chat bubble on the storefront with merchant inbox, visitor identity and live messages.",
            "needs": [
                {
                    "id": "storefront.embeds",
                    "critical": true,
                    "status": "supported"
                },
                {
                    "id": "storefront.proxy",
                    "critical": true,
                    "status": "supported"
                },
                {
                    "id": "platform.realtime",
                    "critical": true,
                    "status": "supported"
                },
                {
                    "id": "storefront.identity",
                    "critical": false,
                    "status": "supported"
                },
                {
                    "id": "conversations.api",
                    "critical": false,
                    "status": "supported"
                },
                {
                    "id": "merchant.carts",
                    "critical": false,
                    "status": "missing"
                },
                {
                    "id": "customers.read",
                    "critical": false,
                    "status": "supported"
                },
                {
                    "id": "dashboard.embed",
                    "critical": false,
                    "status": "supported"
                }
            ],
            "verdict": "buildable",
            "optional_gaps": [
                {
                    "id": "merchant.carts",
                    "status": "missing"
                }
            ]
        },
        {
            "id": "subscriptions",
            "title": "Subscriptions app",
            "summary": "Recurring shopper purchases with subscription plans, renewal billing and lifecycle states.",
            "needs": [
                {
                    "id": "subscriptions.selling_plans",
                    "critical": true,
                    "status": "missing"
                },
                {
                    "id": "payments.session_lifecycle",
                    "critical": true,
                    "status": "missing"
                },
                {
                    "id": "orders.read_import_status",
                    "critical": true,
                    "status": "supported"
                }
            ],
            "verdict": "blocked",
            "optional_gaps": []
        },
        {
            "id": "tax",
            "title": "Tax app",
            "summary": "Jurisdiction-aware tax calculation and store tax maintenance from an app.",
            "needs": [
                {
                    "id": "tax.calculation",
                    "critical": true,
                    "status": "missing"
                },
                {
                    "id": "tax.configuration",
                    "critical": false,
                    "status": "supported"
                },
                {
                    "id": "markets.currency",
                    "critical": false,
                    "status": "missing"
                }
            ],
            "verdict": "blocked",
            "optional_gaps": [
                {
                    "id": "markets.currency",
                    "status": "missing"
                }
            ]
        },
        {
            "id": "translation",
            "title": "Translation app",
            "summary": "Translate store catalogue, pages and theme strings and serve them per published locale; policy pages stay manual-write by advisory flag and writes carry at most 100 keys per call.",
            "needs": [
                {
                    "id": "markets.translations",
                    "critical": true,
                    "status": "supported"
                },
                {
                    "id": "markets.currency",
                    "critical": false,
                    "status": "missing"
                },
                {
                    "id": "dashboard.sheets",
                    "critical": false,
                    "status": "supported"
                },
                {
                    "id": "webhooks.core",
                    "critical": false,
                    "status": "supported"
                },
                {
                    "id": "developer.cli",
                    "critical": false,
                    "status": "supported"
                }
            ],
            "verdict": "buildable",
            "optional_gaps": [
                {
                    "id": "markets.currency",
                    "status": "missing"
                }
            ]
        }
    ]
}