Docs menu · API reference
Getting Started
Integrations
Server-side GTM
COD Order Protection
Advanced Features
Downloads
Tools & Support
Docs / COD Order Protection
COD Order Protection
API reference: hold and webhook
The endpoints, headers and payloads, for stores and systems calling PixelFly directly.
Two endpoints, two different secrets
| Endpoint | Header | What it does |
|---|---|---|
POST /cod/hold | X-PF-Key: pf_live_… | Holds a COD order at checkout |
POST /cod/webhook | X-Webhook-Secret: pfwh_… | Confirms or rejects a held order |
Both live on your tracking domain: your sGTM domain or custom domain, or https://track.pixelfly.io for proxy containers without one. Using the API Key where the webhook secret belongs (or the reverse) returns 401 — they are not interchangeable.
Holding an order
{
"order_id": "12345",
"event_time": 1699012345,
"value": 1500.00,
"currency": "BDT",
"payment_method": "cod",
"email": "customer@example.com",
"phone": "01712345678",
"name": "Rina Begum",
"fbp": "fb.1....", "fbc": "fb.1....",
"gclid": "CjwK...", "ga_client_id": "1234567890.1790000000", "ga_session_id": "1790933629",
"contents": [{ "item_id": "101", "item_name": "Product", "price": 750, "quantity": 2 }]
}
value and currency are what make the order sendable later; order_id is how you confirm it. The identifiers (email, phone, fbp, gclid, the GA IDs) are captured now because they are gone by the time you confirm — they decide whether the platforms can credit the sale to the right ad.
Attribution fields worth sending
The example above shows gclid, but a hold stores any of these. Send whichever your site captured — they are gone by the time the order is confirmed, and each one is what lets that platform credit the sale.
| Platform | Fields |
|---|---|
| Google Ads | gclid wbraid gbraid dclid |
| Meta | fbclid, plus the fbp / fbc cookies |
| TikTok | ttclid |
| Microsoft | msclkid |
li_fat_id | |
| Snapchat | sccid |
| GA4 / reporting | ga_client_id ga_session_id utm_source utm_medium utm_campaign utm_content utm_term |
Browser tags can also call GET /cod/hold?k=<API Key>&d=<URL-encoded JSON>. If PixelFly is briefly unreachable the Worker queues the request and answers 202 {"action":"queued"} — a queued hold is not a lost one.
Confirming or rejecting an order
curl -X POST https://<your-tracking-domain>/cod/webhook \
-H "Content-Type: application/json" -H "X-Webhook-Secret: pfwh_…" \
-d '{"type":"order.status","order_id":"1042","status":"completed"}'
event_time is the original order time and is kept when the platform still accepts it. Meta refuses anything dated more than 7 days back, so a later confirmation is sent dated now rather than being dropped.
Which statuses confirm, reject or are ignored: see confirming orders. A confirmation that arrives before the hold is kept, and applied when the hold lands.
value and currency with the webhook too, plus email and phone if you have them. Without them nothing can be sent, and the order waits as missing purchase data.
GTM tag templates
If you are calling these endpoints from GTM rather than your own backend, these templates do it for you.
The Data Client is what receives the confirmed order at /data in a server container. Made by Stape, not PixelFly — also available in GTM's Community Template Gallery, which is the copy we recommend.