Developer
Send conversions
One request sends a conversion. DataCops checks it, finds the ad click behind it, and delivers it to every platform you have connected.
What it does
You POST one event with your private key. DataCops reads it, skips it if it has seen the same messageId before, joins it to the visitor's browser session and past visits to recover click IDs, and sends it through the same delivery path as your website events. It reaches every ad platform you have connected: Meta, Google Ads, TikTok, LinkedIn, Microsoft Ads, Reddit, Pinterest and X.This is the endpoint behind the DataCops Zapier action, and it works the same from Make, n8n or your own backend. To send a whole spreadsheet of past sales instead, see offline conversions.
How it works
- Auth. The
x-dc-keyheader picks the website. See Authentication. - Paused check. If the site is paused for billing, the request gets 402 and nothing is sent.
- Read.
eventis the only required field. A missing or empty event returns 422. - Duplicate check. Each messageId is stored once per site. A repeat is skipped, never sent twice. See deduplication.
- Match. If you pass the DataCops session id or an email, DataCops looks for the visit and recovers click IDs like gclid, fbc, ttclid, li_fat_id, rdt_cid and epik.
- Deliver. The event runs through your Event Manager mapping, consent and bot rules, then goes to each connected platform. Each result lands in your delivery report.
The request
POST https://api.joindatacops.com/api/v1/conversions/zapier
curl -X POST https://api.joindatacops.com/api/v1/conversions/zapier \
-H "x-dc-key: dcp_your_private_api_key" \
-H "Content-Type: application/json" \
-d '{
"event": "Purchase",
"messageId": "order-1001",
"timestamp": "2026-10-01T09:30:00Z",
"properties": { "value": 49.0, "currency": "USD", "order_id": "1001" },
"context": {
"traits": { "email": "person@example.com", "phone": "+15551234567" },
"identifiers": { "gclid": "Cj0KCQ..." }
}
}'Use an event name your Event Manager knows. GET /api/v1/export/events lists them (see Export data). Standard names are Purchase, Lead, CompleteRegistration and Schedule.
The fields
| Field | Required | What it is |
|---|---|---|
| event | Yes | The conversion name, like Purchase or Lead. |
| messageId | Strongly advised | Your unique id for this event. Without it DataCops makes one up, so a retry could be sent twice. |
| timestamp | No | ISO string, unix seconds or unix ms. Defaults to now. |
| userId, anonymousId | No | Your own user id, and a pre-login visitor id. |
| properties | No | value, currency, order_id, items (sku, product_id, name, category, brand, quantity, price, currency), channel (online, in_store, phone, bopis). |
| context.traits | No | email, phone, first_name, last_name, street, postal_code, city, state, country. Send plain text; DataCops hashes before sending to platforms. |
| context.identifiers | No | gclid, wbraid, gbraid, fbp, fbc, fbclid, ttclid, li_fat_id, rdt_cid, epik, customer_id, dc_session_id. |
| context.ip, context.userAgent | No | The buyer's IP and browser, if you have them. |
The response
You get one result per event: whether the send worked, a short message, and what identity matching found.
{
"accepted": true,
"source": "generic",
"adapter_version": "v2026-05",
"events": [
{
"messageId": "order-1001",
"success": true,
"message": "Conversion sent to 3 platform(s)",
"identity": { "matched": 1, "created": 0, "enriched": ["gclid"] }
}
],
"duration_ms": 184
}identity.matched and identity.created count the people DataCops matched or newly recorded for this event, and enriched lists the click IDs it recovered from earlier visits. Those recovered IDs are what let a platform tie an offline sale back to the ad that started it.
A repeat of the same messageId comes back with "message": "duplicate_delivery_skipped" and is not sent again.
Status codes
- 202: accepted, every event processed without error.
- 207: accepted, but at least one event could not be sent to any platform. Check
messageanderrorson that event. - 401: missing or invalid
x-dc-key. - 402:
APP_INACTIVE, the site is paused. Upgrade to resume. - 422: the body is not a JSON object, or
eventis missing.
Retrying after a timeout or a 5xx is safe as long as you send the same messageId. For a sale that comes in through Shopify or another connected store, let that integration send it instead, so the same order is not posted twice under two different messageIds.