Skip to main content
Send conversions from your backend to Thrad for higher-fidelity attribution. The Server-to-server Conversions API is the one advertiser integration for Thrad attribution and, when enabled for the tag, OpenAI Conversions API delivery.
This endpoint is enabled per tag. Ask your Thrad contact to issue an events:write key for the tag IDs your service may send to. Keep the key on your server; never expose it in browser or mobile code.

Quickstart

The Thrad Tag captures browser activity and attribution context. For confirmed purchases, signups, subscriptions, and CRM events, send the conversion from your backend as well:
  • More reliable: server requests are not affected by ad blockers or browser lifecycle failures.
  • Richer: attach the order, line items, email, phone, or customer ID your frontend does not have.
  • Deduplicated: reuse event_id across browser and server copies of the same conversion.
  • Flexible: send offline, phone, app, and delayed lifecycle events.

How it works

  1. Install the Thrad Tag on your site. It captures consent-permitted Thrad and OpenAI attribution context.
  2. At conversion, pass window.thradTag.getServerContext() from the browser to your backend with the order or lead details.
  3. Your backend sends one event to Thrad. We record it once and route it to Thrad and/or enabled OpenAI measurement without the advertiser choosing a provider endpoint.
Provider delivery is controlled by Thrad. An accepted event and an events:write key do not by themselves turn on OpenAI forwarding; Thrad enables it only for an approved tag after the integration is ready. Your request format stays the same whether the event is used for Thrad attribution, OpenAI measurement, or both.

Reference guides

  • Authentication explains how to obtain and use an events:write key.
  • Identity and consent covers hashed and plaintext matching data, privacy, and routing.
  • Testing covers test_mode and common integration errors.
  • Event reference lists event names, data types, and response outcomes.

Step 1 — Install the Tag

Install the Thrad Tag on every page. The server integration also works for offline events without a browser context, but using the Tag improves attribution for web conversions.

Step 2 — Read context on conversion

On a confirmation page or in your checkout client, read the context and send it to your own backend unchanged. It is safe to call after the Tag loads. It contains no API key or raw matching identity.
If the visitor did not arrive from a Thrad or OpenAI ad, the context may have no attribution reference. The conversion can still be recorded; include your customer identity when consent permits it to improve matching.

Step 3 — Send the event from your backend

Endpoint and authentication

Each key has both the events:write capability and an allowlist of tag IDs. A key cannot submit an event for another advertiser’s tag. Use an events:write key issued for the tag. Keep it server-side only. Send a stable event ID on every event and reuse it for retries and any matching browser event.
The timestamp is Unix milliseconds. It must be no more than seven days old or ten minutes in the future. web events require source_url.

Envelope and results

An envelope has version: 1, one required tag_id, optional test_mode, and between one and 1,000 events. Unknown fields are rejected.
Possible event statuses are accepted, duplicate, suppressed, invalid, and, in test mode, validated. An invalid event has one or more machine-readable errors; duplicate and suppressed events can include warnings. Retry only events whose outcome is not known (503), using their original event_id. Set test_mode: true to validate the envelope and every event without creating a canonical record or forwarding to OpenAI. This is the safe integration check before sending live traffic.

Events and data

Use these canonical event names: page_viewed, contents_viewed, items_added, checkout_started, order_created, lead_created, registration_completed, appointment_scheduled, subscription_created, trial_started, app_installed, app_opened, and custom. Common aliases such as purchase, add_to_cart, page_view, and signup are normalized to their canonical names. custom requires custom_event_name. app_installed and app_opened require action_source: "mobile_app" and data.type: "customer_action". data.type must match the event:

Identity and OpenAI advanced matching

Pre-hashed email and phone are the recommended default. Send lowercase 64-character SHA-256 values in emails_sha256 and phone_numbers_sha256; include both whenever you collected them and consent permits it. Thrad also accepts external_ids_sha256, first_names_sha256, and last_names_sha256. Each field accepts up to three unique values; geographic fields (countries, cities, regions, postal_codes) remain raw. For a simpler first integration, Thrad can hash plaintext emails, phone_numbers, external_ids, first_names, and last_names at ingress. Plaintext is normalized and discarded before logs, errors, canonical records, or queues are created. Prefer pre-hashing when it is easy to do in your service. For example, this is the convenience form of the hashed identity in the request above:
Do not send plaintext fields in data.custom_fields or any other field. Use either form only when measurement consent is present. Thrad merges supplied hashes and locally generated hashes, deduplicates them, and retains at most three values per identity field. Normalize before hashing exactly as follows:
  • email: trim and lowercase;
  • phone: convert to international digits-only form, remove + or 00 and punctuation, then keep 8–15 digits;
  • external ID: trim only; preserve case;
  • first and last name: lowercase and remove whitespace and ASCII punctuation; preserve non-ASCII characters.
The following shared vectors let you verify that your implementation agrees with Thrad. They use example values only.

Dependency-free hashing examples

Node.js:
Python:
PHP:
Reject a phone number unless the normalized value is 8–15 digits and does not begin with 0. If your runtime cannot lowercase non-ASCII names consistently, use pre-hashed name values instead of relying on the plaintext convenience path. Use context.oppref unchanged when your server captured it from the Thrad/OpenAI browser flow. context.oppcref is an unchanged lowercase UUIDv4 and is valid only for page-view, item-added, checkout-started, and order-created events. Send user.obref unchanged when available and permitted by measurement consent. consent.measurement and consent.personalization default to true. Set measurement: false when the user has not consented to measurement. The event is returned as suppressed and is neither recorded nor forwarded. The same canonical event can route to Thrad, OpenAI, or both. A signed Thrad click context (click_id, click_exp, and click_sig) enables Thrad attribution. An OpenAI reference (oppref, oppcref, or obref) or a supported advanced-matching identifier enables OpenAI eligibility. Your advertiser-visible API response does not expose provider credentials or routing internals.

Using the Browser Tag and Server-to-server CAPI together

When the same purchase is reported by the updated Browser Tag or Shopify Custom Pixel and this API, the server must use the browser’s canonical purchase identity:
Trim the order ID. Normalize only an exact gid://shopify/Order/<positive numeric ID> to its numeric suffix; the equivalent numeric string uses that same suffix. Preserve other order IDs unchanged. JSON contains two strings, no spaces and literal Unicode. Do not use a cart/checkout token, callback ID, amount or timestamp as order identity. Different tag IDs produce different purchase identities. Node.js example for your server’s finalized order:
Send this ID as the purchase event’s event_id in the existing /v1/api/events envelope, and reuse it for retries. The updated browser can omit event_id and derive the same value; an explicitly supplied browser ID must match. This S2S schema does not accept an added order_id field. Thrad’s internal purchase-identity reservation endpoint is service-only and is not an advertiser API. Thrad must confirm release availability and reconcile existing purchase producers before cutover. A hosted pixel update cannot change your server’s existing random ID generator or recover historical order mappings. Preserve a working server integration while those identities are checked. Independent S2S events and conversions outside the updated browser purchase path can retain their valid stable IDs. Do not change unrelated IDs or generate a new ID for a retry. Thrad deduplicates per tag_id and event_id; matching provider delivery is checked separately from a canonical receipt.

Troubleshooting

  • invalid_timestamp: correct the system clock or send the event within the supported time window.
  • invalid_identity: send valid lowercase SHA-256 hex values, or send supported plaintext arrays for local hashing.
  • invalid_context: do not alter click signatures, oppref, oppcref, or obref.
  • no_attribution_signal: include a signed Thrad context, an OpenAI reference, or a supported matching identifier.
  • measurement_consent_denied: do not retry until measurement consent is granted for a new event.
  • duplicate_event: the original request was already accepted; do not create a new ID for a retry.
This is the only server-to-server events API for new integrations.