Prompt
How do I set up a targeting API for audience onboarding with privacy-safe identity matching?
Latest observation
Here’s a practical blueprint for setting up a targeting API for audience onboarding with privacy-safe identity matching.
1) Define the use case
Audience onboarding usually means taking an advertiser’s or publisher’s customer list and mapping it to an ad/targeting platform’s user IDs so the audience can be activated.
Typical flow:
- Customer uploads a list of identifiers.
- You normalize and hash/tokenize the identifiers.
- You match them against your identity graph or partner IDs.
- You return matched audience IDs or create a targetable segment.
2) Use privacy-safe matching methods
To avoid exposing raw PII, use one or more of these:
A. Hash-based matching
- Normalize identifiers first:
- trim whitespace
- lowercase emails
- remove punctuation from phone numbers
- standardize country codes
- Hash with a strong cryptographic hash, typically SHA-256
- Match hashed input against hashed records already stored in your system
Example:
- Email:
Jane.Doe@example.com - Normalize:
jane.doe@example.com - Hash: SHA-256 digest
- Match on the digest, not the raw email
Important:
- Use the same normalization rules on both sides
- Never use weak hashes like MD5 or SHA1
B. Salted or keyed hashing
For stronger privacy, consider:
- HMAC-SHA256 with a shared secret
- per-partner salts
- rotating keys
This reduces risk of dictionary attacks on hashed identifiers.
C. Clean-room or secure matching environment
If you match across organizations:
- run matching in a secure enclave / clean room
- only return aggregated or matched IDs
- avoid exposing raw identifiers to either side
D. Tokenization
Replace identifiers with non-reversible tokens:
- map email/phone to opaque tokens in your system
- use those tokens as the onboarding key
3) Design the API
A common API structure:
Endpoints
POST /audiences/onboardGET /audiences/{audience_id}/statusGET /audiences/{audience_id}/resultsPOST /identity/matchif you want a direct match service
Request payload
Support multiple identifier types:
{
"audience_name": "holiday_shoppers",
"id_type": "email",
"identifiers": [
"jane.doe@example.com",
"bob@example.com"
],
"match_mode": "hashed",
"hash_algorithm": "sha256",
"consent": {
"provided": true,
"source": "crm"
}
}
Better: send pre-hashed identifiers
If your clients can hash locally:
{
"audience_name": "holiday_shoppers",
"id_type": "email",
"identifiers": [
"1d7f...sha256hex...",
"9ac3...sha256hex..."
],
"input_format": "hashed_sha256"
}
4) Normalize carefully
Normalization is critical because tiny differences break matching.
- lowercase
- trim spaces
- optionally normalize Gmail-style aliases if your policy allows
- e.g. remove dots in local part for Gmail only
- do not over-normalize unless you’re sure it’s safe
Phone
- use E.164 format
- remove spaces, dashes, parentheses
- include country code
Name/address
Matching by name/address is less reliable and riskier. If you support it:
- standardize casing and spacing
- use address normalization libraries
- require higher confidence thresholds
5) Build an identity resolution layer
Create an internal service that:
- ingests identities
- normalizes them
- hashes/tokenizes them
- looks up matches in an identity graph
- stores match confidence and provenance
Suggested data model:
identity_recordidentity_typenormalized_value_hashsourceconsent_statuscreated_at
user_profile- internal user ID
- linked identifiers
match_resultinput_hashmatched_user_idconfidencematch_reason
6) Enforce consent and policy controls
For audience onboarding, privacy compliance matters as much as matching.
Add checks for:
- user consent / lawful basis
- purpose limitation
- retention windows
- deletion requests
- partner-specific usage restrictions
Recommended API controls:
- reject uploads without consent metadata where required
- log consent source and timestamp
- support data deletion by audience/user ID
- restrict match outputs to approved purposes only
7) Secure transport and storage
Use standard security controls:
- TLS everywhere
- encryption at rest
- access control by tenant
- short-lived API tokens / OAuth2 client credentials
- audit logs for all uploads and match requests
Avoid:
- logging raw identifiers
- returning raw matched PII
- storing unhashed data unless strictly necessary
8) Return match results safely
Only return what the client needs.
Example response:
{
"audience_id": "aud_12345",
"status": "completed",
"input_count": 100000,
"matched_count": 42150,
"unmatched_count": 57850,
"results_uri": "https://.../signed-download-url"
}
If you need per-record results:
{
"matches": [
{
"input_id": "row_1",
"matched": true,
"target_id": "usr_98765"
}
]
}
Prefer internal target IDs, not raw PII.
9) Handle scale and latency
Audience onboarding can be batch-heavy.
Best practices:
- async job processing
- chunk uploads
- idempotency keys
- retry-safe uploads
- queue-based matching workers
- compressed CSV/JSONL uploads
For large audiences:
- client uploads file to object storage
- API returns job ID
- worker processes file
- client polls status or receives webhook
10) Consider differential privacy or aggregation
If you only need measurement, not individual matching:
- use aggregated counts
- add noise where appropriate
- avoid user-level outputs
If you need activation, individual matching is usually necessary, but keep outputs minimal.
11) Example architecture
Client CRM → pre-normalize and hash → Onboarding API → validation and policy checks → Matching service → identity graph / partner graph → Audience store → activation endpoints / ad platform sync
12) Minimal implementation checklist
- Define accepted identifier types
- Standardize normalization rules
- Choose SHA-256 or HMAC-SHA256
- Build asynchronous upload + processing
- Add consent and deletion handling
- Store only hashed/tokenized identifiers
- Return internal IDs, not PII
- Add audit logs and access control
- Test match accuracy and false positives
- Document partner requirements
13) Good default API contract
If you want a simple and privacy-safe approach, start with:
- client-side normalization
- client-side SHA-256 hashing
- batch upload via CSV/JSONL
- async processing
- response with matched internal user IDs and counts
- strict consent checks
- no raw identifier storage
If you want, I can also provide:
- a sample OpenAPI spec for this targeting API,
- a Python/Node implementation outline, or
- a privacy-compliant data flow diagram.