If your environment supports one of our SDKs, that is the recommended approach — the SDK handles identity, event collection, caching, and activation delivery automatically. Use a Direct API deployment only when an SDK is not feasible.
Deployment Flow
A Direct API deployment involves two Permutive APIs, each serving a different purpose:| API | Purpose | Requires consent | Requires user identity |
|---|---|---|---|
| Custom Cohort Segmentation (CCS) API | Collect events and retrieve behavioral cohort signals | Yes | Yes |
| Contextual API | Retrieve contextual cohort signals based on content | No | No |
Step 1: Manage Consent
Your application is responsible for enforcing consent before collecting any user data.- CCS API — only call this for users who have given appropriate consent under your applicable privacy framework (GDPR, CCPA, etc.). The API processes all events it receives; there is no server-side consent gate.
- Contextual API — this can be called for all users, regardless of consent status, because it evaluates content properties rather than user behavior.
| User consent status | APIs to call | Signals available |
|---|---|---|
| Consented | CCS API + Contextual API | Behavioral + Contextual |
| Not consented | Contextual API only | Contextual only |
Step 2: Manage Identity
For consented users, you need a stable identifier to send with CCS API requests. Your application owns the identity lifecycle — generating, persisting, and passing identifiers consistently.Choosing a User Identifier
Permutive supports three types of user identifier. They differ in scope — that is, how broadly the identifier can link a user across different contexts. We recommend using the broadest-scope identifier available in your environment.| # | User identifier | Scope | Links a user across… |
|---|---|---|---|
| 1 | Authenticated first-party ID (e.g., hashed email, internal login ID) | Broadest | Multiple devices and environments |
| 2 | Device ID (e.g., IDFA, AAID, CTV device identifiers, Alexa Advertising ID) | Device-level | Multiple applications on the same device |
| 3 | Generated Permutive ID (a Version 4 UUID your application generates) | Application-level | Sessions within the current application only |
A Direct API deployment does not require third-party identifiers such as cookies, universal IDs, or authenticated logins. A device ID or a self-generated Permutive ID is sufficient for real-time, cross-session behavioral segmentation. This means your deployment is not constrained by identity availability — even in environments where traditional identifiers are limited (e.g., iOS, CTV).
Sending the User Identifier
Authenticated First-Party ID
Pass as analias, with the tag matching a user identifier configured in your Permutive workspace (e.g., email_sha256, internal_id):
Device ID
Pass as analias, with the tag matching the device identifier type (e.g., idfa, aaid, tifa, alexa_advertising_id):
Generated Permutive ID
For users without an authenticated ID or accessible device ID, your application can generate a Version 4 UUID on-device, persist it in local storage, and reuse it across sessions. Pass it directly asuser_id:
Multiple Identifiers
If you have more than one identifier available, pass them inaliases with priorities (lower number = higher priority). Ordering by scope maximizes the chance of linking the user across sessions, devices, and environments:
Key Considerations
- Consistency — always use the same identifier for the same user. Inconsistent identifiers create duplicate profiles and fragment cohort history.
- Uniqueness - make sure the identifiers are unique for each individual user. If multiple users share the same identity then all behavior from those users will be shared between them.
- Persistence — a generated Permutive ID must be stored in durable storage (e.g., device local storage) so it survives across sessions.
- Workspace configuration — user identifiers must be configured in your Permutive workspace before use. You can do this in the Permutive dashboard — see Configuring identifiers.
- Identity resolution — when multiple identifiers map to different Permutive user IDs, the highest-priority identifier (lowest number) wins and all future activity resolves to that user ID. Historical state under other user IDs is not retroactively merged into the winning profile — so consistent priority ordering across all platforms is important from the start. See Identity concepts and the Identify API reference for the full resolution model.
Step 3: Collect Data via the CCS API
For consented users, send events to the CCS API to collect behavioral data and trigger real-time cohort evaluation. Each request contains a user identity and one or more events.Event Structure
Each event requires aname, time, and properties object that matches the schema defined in your Permutive workspace.
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | The event name as defined in your workspace (e.g., "Videoview", "AudioPlay") |
time | string | Yes | ISO 8601 timestamp of when the event occurred |
view_id | UUID | No | Groups events within a single content engagement (e.g., watching a TV program or listening to a podcast) |
session_id | UUID | No | Groups events within a single session, across multiple content engagements |
properties | object | Yes | Event properties matching your workspace schema |
Each request can include up to 10 events. If you need to send more, split them across multiple requests. Events should be sent in chronological order.
bluetooth_audio_active on a web client), omit it entirely rather than sending it as null or an empty value.
Session and View IDs
session_id— generate a new UUID at the start of each user session and reuse it for all events within that session, which may span multiple content engagements. Define what a “session” means for your application (e.g., a 30-minute inactivity timeout).view_id— generate a new UUID for each content engagement (e.g., a video watched or a podcast listened to), and include it on every event that occurs within that engagement.
These IDs are required for creating cohorts which target using ‘this session’ and ‘the current page’ time windows.
Play and Completion Events
For any given content engagement, we recommend tracking two events:- A play event when playback starts (e.g.,
Videoview,AudioPlay) — captures content metadata - A completion event when playback ends or the user stops (e.g.,
VideoCompletion,AudioCompletion) — captures engagement metrics such as time spent and percentage completed
view_id to link them together. The exact event names and property schemas are configured in your Permutive workspace during onboarding.
- Video
- Audio
1. Play event — sent when the video starts playing:2. Completion event — sent when the video ends or the user stops watching:
Engagement Metrics
Your application is responsible for measuring engagement and including it on the completion event. Two metrics are typically captured:| Metric | Description |
|---|---|
| Time spent | Total seconds the user spent engaging with the content |
| Completion | Proportion of the content consumed (0–1). For video and audio, this is the percentage watched or listened to. For article web pages, it is the scroll depth. |
Step 4: Retrieve Behavioral Cohort Signals
The CCS API response contains the user’s updated cohort membership and, if requested, activations grouped by ad platform.Response Format
user_id— the Permutive user ID assigned to this user.cohorts— all cohort IDs the user currently belongs to.activations— cohorts grouped by the ad platform they are activated for. Only included ifactivations=trueis set as a query parameter. The keys (e.g.,freewheel,adswizz_keyvalue,dfp) correspond to activation platforms configured in your Permutive dashboard.
Always request activations by adding
?activations=true to your API call if you intend to use cohorts for ad targeting.Caching
Call the CCS API on every content view to keep cohort membership up to date. However, cache the most recent response as a fallback:- Cache each response — store the latest cohorts and activations in a location accessible to your ad-serving logic (server-side session, in-memory cache, or device storage).
- Use cached values as fallback — if the API call fails or is too slow, use cached cohorts from the previous response.
- Set a TTL — a long TTL (e.g., 30 days or longer) is reasonable since the cached data is a short list of cohort IDs.
Step 5: Retrieve Contextual Cohort Signals
The Contextual API returns cohort signals based on the content being viewed, rather than the user’s behavior. This means it:- Does not require user identity
- Does not require consent
- Should be called for every content view, regardless of consent status
Example Request
properties object from your CCS API event, omitting any user-related fields. This ensures the Contextual API classifies the same content the user is engaging with. See the Contextual API reference for full request and response details.
The url Field
The Contextual API requires a url field. Any URL scheme is accepted, so in audio, video, or other non-web environments, construct a URL that uniquely and deterministically identifies the active content.
Recommendations:
- Use the public web URL where one exists (e.g.,
https://example.com/shows/morning-news/). If the content has a web presence that drives traffic, Permutive may already have URL-based affinity scores associated with it, improving contextual classification. - Use an app-schema URL for in-app content (e.g.,
myapp://podcast/1234) when no public web URL applies. - Construct a deterministic URL for environments without a natural URL (e.g., smart speakers). Build one from a stable content identifier, such as
smartspeaker://station/abc123.
Contextual cohorts are configured separately in the Permutive dashboard. If your workspace uses contextual cohorts, this API call is essential for maximizing signal coverage — especially for unconsented users where it is the only source of cohort signals.
Step 6: Merge Signals and Activate
Before passing cohort signals to your ad server, merge the behavioral activations (from the CCS API) with the contextual activations (from the Contextual API) into a single set of key-values.In some cases it may make sense to send behavioral and contextual cohorts as separate key-values (e.g.,
permutive and prmtvctx) rather than merging them into one. This can enable separate reporting and targeting on each signal type in your ad platform. Discuss with your Customer Success Manager to decide on the right approach for your ad stack.Attaching Signals to Ad Requests
Once merged (or split, depending on your approach), append the signals to your ad request as key-values. The exact format depends on your ad platform — we recommend working with Technical Services during setup to confirm the correct key-value structure for each platform you are activating against.End-to-End Example
The following sequence diagram shows a complete content engagement — from playback start through to completion — illustrating how the CCS API, Contextual API, and ad server interact in practice.Request and Response Payloads
Expand each step below to see the corresponding request or response body. Step numbers match the sequence diagram above.Step 3 — Videoview: CCS API request body
Step 3 — Videoview: CCS API request body
The play event sent when playback starts, including the user identifier and content metadata:
Step 4 — CCS API response
Step 4 — CCS API response
The response includes the user’s cohort membership and activations grouped by ad platform:
Step 5 — Contextual API request body
Step 5 — Contextual API request body
Mirrors the content properties from the CCS API event, with a URL and no user-related data:
Step 6 — Contextual API response
Step 6 — Contextual API response
Contextual cohort activations based on the content, independent of user identity:
Step 10 — VideoCompletion: CCS API request body
Step 10 — VideoCompletion: CCS API request body
The completion event sent when playback ends. Note the same user identifier,
view_id, and session_id as the play event, with added engagement metrics:Feature Comparison: Direct API vs SDK
| Capability | SDK | Direct API |
|---|---|---|
| Event tracking | Simple — helper functions in our Web and CTV SDKs make event tracking straightforward | Manual — events must be sent explicitly via API |
| Engagement tracking (time spent, completion) | Automatic — the SDK measures engagement and manages state | Manual — your application must measure and track engagement |
| Identity management | Partially managed — the SDK generates a Permutive ID and collects device IDs where configured | Manual — your application must generate, persist, and send user identifiers |
| Classification Modeled Cohorts | Supported | Unsupported |
| Cohort evaluation lookback | Supported — the SDK stores event history on-device, so newly created cohorts can be evaluated against the user’s historical events | Unsupported |
| Cohort caching | Automatic — cohorts are cached in local/device storage | Manual — your application must cache API responses |
| Activation to ad platforms | Fully automatic on Web for supported platforms; on Mobile and CTV, cohorts are exposed via SDK APIs for your application to attach to ad calls | Manual — extract activations from the response and attach them to ad calls |
| Latency | Real-time — on-device segmentation with minimal network dependency | Near real-time — dependent on the API round-trip |
Verification and Troubleshooting
Verifying Your Integration
After implementing a Direct API deployment, verify each step:- Identity — send a request and confirm the response returns a stable
user_id. Send a second request with the same user identifier and confirm the sameuser_idis returned. - Event collection — create a test cohort in the Permutive dashboard with simple rules (e.g., “any AudioPlay event”) and confirm the user enters it after sending a matching event.
- Activations — with
activations=true, check that the response includes the expected platforms and cohort IDs. - Contextual signals — call the Contextual API with a known URL and confirm contextual cohorts are returned.
- Signal merging — verify that both behavioral and contextual signals appear in your ad requests.
- Consent gating — confirm that no CCS API calls are made for unconsented users, and that contextual signals still flow.
Common Issues
Event schema mismatch
Event schema mismatch
Problem: Events are being sent but the user is not entering expected cohorts.Cause: The event name or property structure does not match the schema defined in your Permutive workspace.Solutions:
- Verify the event
namematches exactly (case-sensitive) what is configured in your workspace - Check that
propertiesmatch the expected schema — missing required fields or incorrect types will cause the event to be ignored - Use the Permutive dashboard to inspect the event schema and compare it with what your application is sending
- Ensure nested properties follow the correct structure (e.g.,
audio.categoriesshould be an array, not a string) - For debugging, add
synchronous-validation=trueas a query parameter to your API call — this forces the CCS API to validate the event schema synchronously and return any schema mismatch errors in the response (by default, validation is asynchronous and schema errors return a200response). Use this only for testing — synchronous validation has performance implications and should not be enabled in production.
Duplicate or fragmented users
Duplicate or fragmented users
Problem: The same real user appears as multiple users in Permutive, or cohort history is fragmented across sessions.Cause: Inconsistent identifiers are being sent across requests, or the identifier is not being persisted between sessions.Solutions:
- Ensure you are using the same user identifier for the same user across all requests
- If passing a tagged identifier, ensure both the tag and value are identical across all touchpoints
- If you are generating a Permutive ID on-device, check that it is being read from durable storage on subsequent sessions and not regenerated
- Verify that the user identifier is configured in your Permutive workspace
Incorrect API key
Incorrect API key
Problem: API requests return
401 Unauthorized or 403 Forbidden.Solutions:- Find your API key in the Permutive Dashboard under Settings
- Provide the key as a query parameter (
?k=YOUR_API_KEY) or header (X-Api-Key: YOUR_API_KEY) - Ensure you are using the key for the correct workspace
- Check that the key has not been rotated or revoked
Empty cohorts in response
Empty cohorts in response
Problem: The API returns successfully but
cohorts is always an empty array.Solutions:- Check that cohorts are configured and active in your Permutive dashboard
- Verify that the events you are sending match the rules defined in your cohorts
- Ensure the event properties contain the values that your cohort rules are looking for
- Allow a few requests to build up user history — some cohorts require multiple events or sessions to qualify
Activations missing from response
Activations missing from response
Problem: The response includes
cohorts but no activations.Solutions:- Ensure you are passing
activations=trueas a query parameter - Check that cohorts are activated for at least one platform in the Permutive dashboard
- A cohort must be explicitly activated for a platform to appear in the activations map
High latency or timeouts
High latency or timeouts
Problem: API requests are slow or timing out, delaying ad requests.Solutions:
- Implement a timeout on your API call (e.g., 200-500ms) and fall back to cached cohorts
- Send API requests as early as possible in the page/screen lifecycle
- Contact Support if latency persists
Next Steps
CCS API Reference
Full request and response schemas for behavioral cohort segmentation
Contextual API Reference
Request and response schemas for contextual cohort signals
Identity Management
Learn more about Permutive’s identity resolution
SDK Deployment
Consider an SDK if your environment supports it