Profiles
A profile is the unified view of one customer: the customer block, its per-platform identities, its consent map, and computed traits. Every lookup follows the merge chain to the surviving customer, and traits are computed on read on the fee-free money basis the producers stored. All profile endpoints take the profile scope.
Look up a profile
GET /v1/profiles/lookup resolves one profile by exactly one selector. Supplying zero or more than one selector returns 422.
- Name
zbIdSubject- Type
- query
- Description
The ZB ID subject UUID.
- Name
platform + userId- Type
- query
- Description
A platform key plus your user id on that platform (both required together).
- Name
phone- Type
- query
- Description
A phone, normalized Zimbabwe-aware.
- Name
email- Type
- query
- Description
An email, lowercased.
- Name
nationalId- Type
- query
- Description
A national id.
Returns the full profile bundle. 404 when nothing matches.
Request
curl "https://c360-api.lioncapventures.com/v1/profiles/lookup?zbIdSubject=b1e5c8a0-1111-2222-3333-444455556666" \
-H "X-API-Key: $C360_API_KEY"
Get a profile by id
GET /v1/profiles/{publicId} returns the full profile for a customer public id (for example a customerId from the feed). It follows the merge chain; when the requested id was a merged tombstone, the response includes resolvedFrom naming the id you asked for.
The bundle has four parts:
customerthe surviving customer block:publicId,zbIdSubject,status,displayName,primaryPhone,primaryEmail,nationalId,firstSeenAt,lastSeenAt.identitiesthe per-platform identity rows:platform,identifierType,identifierValue,linkMethod,linkConfidence,firstSeenAt,lastSeenAt.consentsa map keyed by purpose, each{ status, occurredAt, source }.traitscomputed counts and fee-free money maps (see the sample).
Response (200)
{
"success": true,
"data": {
"customer": {
"publicId": "cus_a1b2c3",
"zbIdSubject": "b1e5c8a0-...",
"status": "resolved",
"displayName": "Jane M",
"primaryPhone": "+263771234567",
"primaryEmail": "jane@example.com"
},
"identities": [
{
"platform": "smilemall",
"identifierType": "user_id",
"identifierValue": "42",
"linkMethod": "deterministic",
"linkConfidence": 1.0
}
],
"consents": {
"marketing": {
"status": "granted",
"occurredAt": "2026-08-10T09:00:00.000Z",
"source": "smilemall"
}
},
"traits": {
"ordersPaidCount": 3,
"ordersPaidTotal": { "USD": "132.00" },
"billpayCount": 5,
"billpayTotal": { "USD": "88.50" },
"loansApplied": 1,
"platforms": ["smilemall", "qupa"]
}
}
}
A customer's events
GET /v1/profiles/{publicId}/events returns a customer's own events, newest first by occurred time. Query params: beforeId, beforeOccurredAt, limit (1..1000, default 50). Page older by passing both nextBeforeOccurredAt and nextBeforeId back as beforeOccurredAt and beforeId (a keyset cursor). It follows the merge chain, so a survivor's page includes events originally emitted against a merged customer.
Request
curl "https://c360-api.lioncapventures.com/v1/profiles/cus_a1b2c3/events?limit=50" \
-H "X-API-Key: $C360_API_KEY"
Set consent
PUT /v1/profiles/{publicId}/consents records a consent decision, latest-wins. status must be granted or revoked (else 422). A missing occurredAt defaults to now; an occurredAt older than the stored decision is ignored, and the response reports applied: false in that case.
- Name
purpose- Type
- string, required
- Description
The consent purpose, for example
marketing.
- Name
status- Type
- string, required
- Description
grantedorrevoked.
- Name
source- Type
- string
- Description
Optional. Defaults to the caller's
callerId.
- Name
occurredAt- Type
- ISO-8601
- Description
Optional. Defaults to now.
Request
curl -X PUT https://c360-api.lioncapventures.com/v1/profiles/cus_a1b2c3/consents \
-H "X-API-Key: $C360_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"purpose": "marketing",
"status": "granted",
"source": "smilemall",
"occurredAt": "2026-08-10T09:00:00.000Z"
}'
Response (200)
{
"success": true,
"data": {
"purpose": "marketing",
"status": "granted",
"applied": true
}
}