Skip to main content

Overview

POST /api/buyer/advertisers/:advertiserId/log-event is a single-call ingest endpoint for sending conversion or marketing events to an advertiser. It accepts the standard ADCP event types — purchase, lead, add_to_cart, initiate_checkout, view_content, complete_registration, page_view, app_install, deposit, subscription — and a custom event type for events that don’t map to any of those. Use it for:
  • Bespoke conversion definitions — a “qualified demo booked” or “tier upgrade” event that doesn’t fit the standard taxonomy. Send event_type: custom with custom_event_name.
  • Internal-only events for ML training — engagement signals you want to feed measurement, even if they aren’t reportable conversions.
  • Custom funnel steps — domain-specific milestones (game level reached, KYC step completed) that drive your bidding logic.
  • Server-to-server batch ingestion — up to 10,000 events per call.

How it differs from event sources and measurement data

The three measurement ingest paths overlap; pick the one that matches the shape of your data.
SurfaceWhat you sendGranularityBest for
Event sources (/event-sources/sync)The configuration of where events come from (pixels, SDKs, MMPs)Source registrationOnboarding a new pixel or feed once, then sending events through it
Log events (/log-event)Per-user, per-event records keyed to a registered event_source_idOne record per event (1–10,000 per call)Bespoke conversion taxonomies, custom funnel steps, server-to-server event ingestion
Measurement data (/measurement-data/sync)Pre-aggregated outcomes for a time window and entityOne record per metric × window × campaignMMP, CRM, or warehouse exports of weekly/daily aggregates
log-event is the path for identified, per-user events at advertiser scope. Event sources are the configuration layer you call once; log-event is the runtime path you call repeatedly.
Every event must reference an event_source_id that is already registered on the advertiser via POST /advertisers/:advertiserId/event-sources/sync. Events sent against an unregistered source are rejected. See the Measurement & Incrementality guide for event-source setup.

Request shape

All examples use:
BASE = https://api.agentic.scope3.com/api/buyer
AUTH = Authorization: Bearer scope3_<your_api_key>
curl -X POST "$BASE/advertisers/12345/log-event" \
  -H "Authorization: Bearer scope3_<your_api_key>" \
  -H "Content-Type: application/json" \
  -d '{
    "event_source_id": "website_pixel",
    "events": [
      {
        "event_id": "txn_abc123",
        "event_type": "purchase",
        "event_time": "2026-04-26T14:30:00-05:00",
        "action_source": "website",
        "event_source_url": "https://shop.example.com/checkout/complete",
        "user_match": {
          "hashed_email": "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8",
          "click_id": "fb.1.1700000000.AbCdEfGh",
          "click_id_type": "fbclid"
        },
        "custom_data": {
          "value": 89.99,
          "currency": "USD",
          "order_id": "order_55512",
          "content_ids": ["sku_red_shoe_42"],
          "num_items": 1
        }
      },
      {
        "event_id": "demo_booked_98765",
        "event_type": "custom",
        "custom_event_name": "qualified_demo_booked",
        "event_time": "2026-04-26T15:05:00-05:00",
        "action_source": "website",
        "user_match": {
          "hashed_email": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
        }
      }
    ]
  }'
Response
{
  "events_received": 2,
  "events_processed": 2,
  "warnings": [],
  "match_quality": 0.87
}

Top-level fields

FieldTypeRequiredNotes
event_source_idstringyesMust match an event_source_id registered on the advertiser
eventsarrayyes1–10,000 events per call
test_event_codestringnoMarks the request as test traffic — events are validated but excluded from production data

Per-event fields

FieldTypeRequiredNotes
event_idstringyesUnique within event_type + event_source_id. Resends with the same event_id are deduplicated.
event_typeenumyespurchase, lead, add_to_cart, initiate_checkout, view_content, complete_registration, page_view, app_install, deposit, subscription, or custom
event_timeISO 8601yesMust include offset (e.g. 2026-04-26T14:30:00-05:00)
custom_event_namestringconditionalRequired when event_type: custom
action_sourceenumnowebsite, app, in_store, phone_call, system_generated, other
event_source_urlURLconditionalRequired when action_source: website
user_matchobjectnoIdentity fields for attribution (see below)
custom_dataobjectnoValue, currency, order ID, items

user_match — identity fields

Send at least one identifier per event. More identifiers = higher match rate.
FieldFormatNotes
uidsarray of { type, value }Universal IDs: rampid, id5, uid2, euid, pairid, maid
hashed_email64-char lowercase hexSHA-256 of lowercased, trimmed email
hashed_phone64-char lowercase hexSHA-256 of E.164-formatted phone
click_id + click_id_typestringPlatform click identifier (fbclid, gclid, ttclid)
client_ipstringIP for probabilistic matching
client_user_agentstringUA for probabilistic matching

custom_data — event payload

FieldTypeNotes
valuenumberMonetary value of the event
currencystringISO 4217 (USD, EUR, GBP) — required when value is set
order_idstringUnique transaction ID
content_idsarray of stringsSKU / product IDs
content_typestringCategory (product, service)
num_itemsintegerItem count
contentsarray of { id, quantity, price, brand }Per-item detail

Response shape

FieldTypeNotes
events_receivedintegerCount of events in the request
events_processedintegerCount successfully queued
partial_failuresarrayPer-event failures with event_id, code, message
warningsarray of stringsNon-fatal issues — low match quality, missing optional fields
match_qualitynumber (0–1)Aggregate match-quality score for the batch
A 200 with partial_failures is normal — bad events are rejected individually, the rest succeed. Treat any failure as something to fix at source, not a transient error.

Best practices

Custom event names become the join key for downstream measurement and reporting. Pick names you won’t want to change (qualified_demo_booked, kyc_step_2_complete). Renaming after launch breaks historical continuity.
If your event is genuinely a purchase or a lead, use purchase or lead. Standard types get first-class treatment in measurement and optimization; custom events fall back to generic handling.
event_id is the dedup key, scoped to event_type + event_source_id. Re-sending the same event_id is safe — duplicates are dropped. Use your stable upstream identifier (transaction ID, demo booking ID) so retries don’t double-count.
Recent events match better — click IDs and probabilistic signals decay quickly. Aim for sub-hour latency for behavioral events; daily batches are fine for offline conversions like CRM exports.
Set test_event_code for staging traffic. Events validate end-to-end but are excluded from production reporting and the measurement engine.
The endpoint accepts up to 10,000 events per call. Batch larger flows rather than firing one HTTP request per event — same data, much less overhead.

Privacy

Never send raw PII. No plaintext emails, phone numbers, names, or addresses. Only pre-hashed identifiers (SHA-256, lowercase, 64-char hex) or pre-resolved identity tokens (RampID, UID2, ID5, etc.). Normalize the email (lowercase, trimmed) and phone (E.164) before hashing — see the Conversion API guide for hashing rules. Malformed hashes are silently dropped.
The same privacy contract applies whether an event is purchase or custom. Custom events are not a back door for raw PII.

Conversion API

Detailed identity-hashing rules and the same log-event payload viewed as a conversion-tracking integration.

Measurement & Incrementality

Register event sources, configure measurement, and run incrementality tests against the events you log.