Profiles & Events API
Update Profiles and Raise Events
Use phone numbers instead of Querygen conversation IDs to update a customer profile or record an event on an existing direct-message conversation. Set channel to whatsapp for Connected WhatsApp or waba for the WhatsApp Business Platform. from_number is your connected business number, and user_phone_number is the customer’s number. Use digits with the country code and no leading +.
Update profile attributes
Send one or more values with PUT /api/v1/profile-attributes. New definitions infer text, number, boolean, or multi-select types from the first value. Existing date and select definitions keep their configured type and allowed values. Names are normalized to snake case, so do not send two names that normalize to the same value in one request.
curl -X PUT "https://app.querygen.ai/api/v1/profile-attributes" \
-H "Authorization: Bearer qg_xxxxxxxxxxxxx" \
-H "X-Organization-Id: <organization-id>" \
-H "Content-Type: application/json" \
-d '{
"channel": "waba",
"from_number": "919820160046",
"user_phone_number": "919876543210",
"attributes": {
"customer_tier": "gold",
"order_count": 4,
"is_verified": true,
"interests": ["retail", "priority"]
}
}'{
"success": true,
"data": {
"updated": ["customer_tier", "order_count", "is_verified", "interests"]
}
}Export profile attributes
Read profiles with GET /api/v1/profile-attributes to copy them into a CDP such as CleverTap, MoEngage, or WebEngage. Each contact comes back once with all of its current attributes. Pass updated_since to get only contacts that changed after that time, or phone for one contact. Up to limit contacts (default 100, maximum 500) are returned per page; send next_cursor as cursor until it is null. For the next sync, use the time your previous sync started as updated_since. The API key owner needs Read access to profile attributes.
curl "https://app.querygen.ai/api/v1/profile-attributes?updated_since=2026-10-01T00:00:00Z&limit=100" \
-H "Authorization: Bearer qg_xxxxxxxxxxxxx" \
-H "X-Organization-Id: <organization-id>"{
"success": true,
"data": {
"contacts": [
{
"phone": "919876543210",
"name": "Asha Rao",
"email": null,
"instagram_username": null,
"attributes": { "customer_tier": "gold", "interests": ["retail", "priority"] },
"updated_at": "2026-10-03T09:30:00.000Z"
}
],
"next_cursor": 1842
}
}Raise an event
Record one immutable occurrence with POST /api/v1/events. properties, description, occurred_at, and idempotency_key are optional. Reuse the same idempotency key when retrying the same occurrence.
curl -X POST "https://app.querygen.ai/api/v1/events" \
-H "Authorization: Bearer qg_xxxxxxxxxxxxx" \
-H "X-Organization-Id: <organization-id>" \
-H "Content-Type: application/json" \
-d '{
"channel": "waba",
"from_number": "919820160046",
"user_phone_number": "919876543210",
"event": "order_placed",
"description": "Customer placed order ORD-42",
"properties": {
"order_id": "ORD-42",
"amount": 1250,
"paid": true
},
"occurred_at": "2026-09-07T11:25:14Z",
"idempotency_key": "order-42"
}'{
"success": true,
"data": {
"id": "event_abc123",
"duplicate": false
}
}Property types are inferred when first observed and displayed with the event under Settings > Events. Later calls may add properties but cannot change an established type. Null values are stored on the occurrence but do not establish a property type.
| Status | Meaning |
|---|---|
| 400 | Invalid identity, value, property, timestamp, or duplicate normalized attribute name |
| 403 | The API key owner lacks the required feature permission or record access |
| 404 | The customer contact or direct-message conversation was not found |
| 409 | An attribute or event property does not match its configured type |