: "${PLAINROUTER_SIGNAL_SECRET:?Set your Signals workspace secret in the server environment}"
curl --include https://plainrouter.com/api/v1/events \
--request POST \
--header "Authorization: Bearer $PLAINROUTER_SIGNAL_SECRET" \
--header "Content-Type: application/json" \
--data '{
"event_id": "order-123",
"event_name": "Purchase",
"event_source": "https://shop.example/thank-you",
"action_source": "website",
"consent_basis": "consent",
"consent": {
"ad_storage": "granted",
"ad_user_data": "granted",
"ad_personalization": "granted",
"source": "checkout-consent"
},
"value_data": {
"value": "49.90",
"currency": "EUR",
"order_id": "order-123"
}
}'
{
"event_id": "order-123",
"duplicate": false,
"warnings": []
}
{
"event_id": "order-123",
"duplicate": true
}
Submit a conversion event
Send a consented purchase through Plainrouter’s Conversion API, preserve its event ID on retries, and inspect the event trace for Meta acceptance.
: "${PLAINROUTER_SIGNAL_SECRET:?Set your Signals workspace secret in the server environment}"
curl --include https://plainrouter.com/api/v1/events \
--request POST \
--header "Authorization: Bearer $PLAINROUTER_SIGNAL_SECRET" \
--header "Content-Type: application/json" \
--data '{
"event_id": "order-123",
"event_name": "Purchase",
"event_source": "https://shop.example/thank-you",
"action_source": "website",
"consent_basis": "consent",
"consent": {
"ad_storage": "granted",
"ad_user_data": "granted",
"ad_personalization": "granted",
"source": "checkout-consent"
},
"value_data": {
"value": "49.90",
"currency": "EUR",
"order_id": "order-123"
}
}'
{
"event_id": "order-123",
"duplicate": false,
"warnings": []
}
{
"event_id": "order-123",
"duplicate": true
}
202; a retry of the same event ID returns 200 with duplicate: true. Neither receipt alone confirms Meta delivery.
Before sending a purchase
- Use the Signals workspace secret on your server. MCP execution tokens and OAuth management credentials cannot authenticate this endpoint.
- Connect the intended Meta dataset for eligible destination delivery.
- Read the actual paid order and its recorded advertising consent. The example assumes all three grants; setting these fields does not obtain consent.
- Choose one purchase sender. Do not also send the same checkout through a browser purchase or Stripe settlement flow.
data envelope. For synthetic payload checks without production writes, use the sandbox.
Example: an immediate, consented purchase
Replace the order ID, source URL, amount and currency with the actual purchase. This immediate-event example omitsevent_time, so Plainrouter uses receipt time. For queued events, supply the original Unix timestamp or ISO-8601 payment time from your order record and preserve it on retries. Do not replace an old payment time with the current time.
: "${PLAINROUTER_SIGNAL_SECRET:?Set your Signals workspace secret in the server environment}"
curl --include https://plainrouter.com/api/v1/events \
--request POST \
--header "Authorization: Bearer $PLAINROUTER_SIGNAL_SECRET" \
--header "Content-Type: application/json" \
--data '{
"event_id": "order-123",
"event_name": "Purchase",
"event_source": "https://shop.example/thank-you",
"action_source": "website",
"consent_basis": "consent",
"consent": {
"ad_storage": "granted",
"ad_user_data": "granted",
"ad_personalization": "granted",
"source": "checkout-consent"
},
"value_data": {
"value": "49.90",
"currency": "EUR",
"order_id": "order-123"
}
}'
event_id for the logical purchase. You can use Idempotency-Key instead; if you supply both, they must match. Reuse the original payload after an uncertain timeout, subject to continued consent eligibility. A duplicate receipt does not update the accepted event or replay a failed Meta delivery.
{
"event_id": "order-123",
"duplicate": false,
"warnings": []
}
{
"event_id": "order-123",
"duplicate": true
}
warnings. If you supply identity data without a valid consent capture time, read the consent warning guidance before treating the event as linked. Duplicate acknowledgements retain the response shape shown above.
How do I verify the result?
Follow the returnedLocation header or retrieve the event and delivery trace. A delivery with status: "accepted" confirms Meta acceptance. Queued or retrying delivery remains pending, and an empty delivery list is not acceptance. See delivery statuses for failed and skipped outcomes. Acceptance does not establish ad attribution or better performance.
| Failure | Next step |
|---|---|
401 | Stop retries and check the Signals secret and workspace. |
422 | Read field errors; check consent, decimal-string values, original event time and matching idempotency keys. |
| Timeout without a receipt | The write may have succeeded. Retry the original ID and payload rather than creating a new ID. |
Authorizations
Per-workspace bearer secret. It authenticates only the Signals workspace represented by the credential.
Headers
Optional idempotency key. When event_id is omitted, Plainrouter uses this value as event_id. If both are supplied, they must match.
Body
Authenticated secret-key server callers may supply client_ip_address and client_user_agent in user_data; publishable-key browser traffic takes those fields only from the trusted edge.
- Option 1
- Option 2
Signal event name; maximum 100 characters.
Legal basis for processing. Legitimate-interest revenue lifecycle events are rejected; use an authenticated server adapter.
"consent"Caller-supplied idempotency key; maximum 128 characters.
Optional parent event id; maximum 128 characters.
Unix timestamp or ISO-8601 date-time. Defaults to receipt time.
Optional absolute source URL.
Optional action source; defaults to website and is limited to 50 characters.
Optional visitor identifier; maximum 255 characters.
Consent state supplied with the event.
Show child attributes
Show child attributes
Consent Mode v2 signal values supplied with the event.
Show child attributes
Show child attributes
TCF v2 data containing string and optional captured_at.
Show child attributes
Show child attributes
Identity fields accepted by the tracker.
Show child attributes
Show child attributes
Advertising click identifiers.
Show child attributes
Show child attributes
Optional commerce data. Contents accepts at most 50 items and 16 KB serialized.
Show child attributes
Show child attributes