Events
Marketing event ingest. Single + batch. Identity resolves
email > phone > externalId. ISO-8601 timestamp is preserved on
the resulting Touchpoint. Backed by MCP tool ingest_event.
Use this for any agent action that should land in the customer’s timeline: emails sent, calls placed, pages observed, signals fired. The event is identity-resolved against the existing customer graph and dropped on the right node automatically.
Request
POST /v1/events
Body is either a single EventIngest object, or { events: EventIngest[] }
for batches up to 500.
| Field | Type | Notes |
|---|---|---|
event | string, required | Event name. Pick a stable verb-tense slug. (email_sent, call_placed) |
customer | string, optional | Customer ID. If absent, identity resolves via email, then phone, then externalId. |
email | string, optional | One of customer, email, phone, externalId MUST be present. |
phone | string, optional | Falls back to +1 for bare 10-digit US numbers. |
externalId | string, optional | Your stable customer ID in another system. |
properties | object, optional | Free-form. Lands on the Touchpoint node. |
timestamp | string, optional | ISO-8601. Strict regex. Defaults to now if missing. 400 on malformed. |
Required scope: events:write.
Examples
curl, single
curl https://api.waypath.app/v1/events \
-H "X-API-Key: wp_live_..." \
-H "Content-Type: application/json" \
-d '{
"event": "page_viewed",
"email": "jane@acme.com",
"properties": { "url": "/pricing", "referrer": "https://google.com" },
"timestamp": "2026-04-29T10:14:32Z"
}'curl, batch
curl https://api.waypath.app/v1/events \
-H "X-API-Key: wp_live_..." \
-H "Content-Type: application/json" \
-d '{
"events": [
{ "event": "email_opened", "email": "jane@acme.com", "properties": { "campaign_id": "camp_42" } },
{ "event": "link_clicked", "email": "jane@acme.com", "properties": { "url": "/book-demo" } }
]
}'node-fetch
await fetch('https://api.waypath.app/v1/events', {
method: 'POST',
headers: {
'X-API-Key': process.env.WAYPATH_API_KEY!,
'Content-Type': 'application/json',
},
body: JSON.stringify({
event: 'page_viewed',
email: 'jane@acme.com',
properties: { url: '/pricing' },
}),
})python
import os, requests
requests.post(
'https://api.waypath.app/v1/events',
headers={'X-API-Key': os.environ['WAYPATH_API_KEY']},
json={
'event': 'page_viewed',
'email': 'jane@acme.com',
'properties': {'url': '/pricing'},
},
timeout=5,
)MCP
await mcp.tools.ingest_event({
event: 'page_viewed',
email: 'jane@acme.com',
properties: { url: '/pricing' },
})Response
Single
{
"eventId": "evt_91ab2c",
"customerId": "cus_8af2",
"resolved": "email"
}Batch
{
"accepted": 2,
"results": [
{ "eventId": "evt_91ab2c", "customerId": "cus_8af2", "resolved": "email" },
{ "eventId": "evt_91ab2d", "customerId": "cus_8af2", "resolved": "email" }
]
}resolved reports which key matched. new means a new Customer node
was created.
Identity resolution
Match priority is email (1.0), then phone (0.9), then externalId
(0.8). Phone numbers are normalized to E.164. When nothing matches,
a new Customer node is created using whichever keys you provided.
If you already have the canonical customer ID (e.g. from a previous
/v1/context call), pass it directly and skip resolution.
Errors
| Status | Code | Cause |
|---|---|---|
| 400 | invalid_payload | Missing event, no identity key, or malformed timestamp. |
| 401 | unauthenticated | Missing or invalid X-API-Key. |
| 403 | forbidden_scope | Key lacks events:write. |
| 429 | rate_limited | Per-key cap. Honor Retry-After. |