Enrichment API
Find the email address, profile, and social footprint for any Instagram, TikTok or YouTube creator from a single handle. One request returns the result, and you only pay a credit when an email is found.
Base URL
All requests are made over HTTPS.
https://enrichment.socialgems.ioAgents and code generators can read this reference as an OpenAPI 3.1 spec or as llms.txt.
Authentication
Every request requires an API key sent as a Bearer token in the Authorization header. Keys are tied to a customer and a tier, which determines rate limits.
Authorization: Bearer YOUR_API_KEYQuickstart
Send a handle and read the result from the response. New accounts start with 10 free credits, and repeat requests for the same creator are free. Creators we've already looked up come back in under a second, but the first lookup of a new creator can take up to about 90 seconds, so set your client timeout to at least 2 minutes.
Try it
// The live response appears hereFrom your code
curl -X POST https://enrichment.socialgems.io/api/v1/enrich \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"handle": "zendaya"
}'curl -X POST https://enrichment.socialgems.io/api/v1/enrich \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"handle": "khaby.lame",
"platform": "tiktok"
}'curl -X POST https://enrichment.socialgems.io/api/v1/enrich \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"handle": "https://www.youtube.com/@mattdavella",
"platform": "youtube"
}'const res = await fetch("https://enrichment.socialgems.io/api/v1/enrich", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
handle: "zendaya",
platform: "instagram", // optional; defaults to "instagram"
}),
})
if (res.status === 402) {
// Out of credits — the body's buyUrl sells the next pack.
}
if (res.status === 503) {
// Upstream briefly unavailable — retry after the Retry-After header.
}
const { status, result, credits } = await res.json()
// status: "completed" (email found) or "partial" (no email found)
// credits: { charged: 1, remaining: 259 } — only a found email costs a credit
const primaryEmail = result.emails[0]?.emailPricing
You pay in credits, and only for results. One credit unlocks one email for a creator you haven't looked up before.
10 credits when your account is created.
$0.12 per email found. Credits land as soon as the payment clears.
| Request | Cost |
|---|---|
| Email found for a creator you haven't unlocked | 1 credit |
| The same creator again, any time later | Free |
No email found (status: "partial") | Free |
Upstream error (503) | Free |
Every response says what it cost in credits.charged and what is left in credits.remaining. Out of credits, requests for new creators return 402 insufficient_credits with a buyUrl, and nothing is charged. Creators you've already unlocked keep working.
Enrich a creator
Look up the email and profile for an Instagram, TikTok or YouTube handle.
Request body
| Parameter | Type | Description |
|---|---|---|
| handlerequired | string | Creator handle with or without the leading @. Normalized to lowercase. 1–30 characters, alphanumeric plus . and _. YouTube handles are 3–30 characters and may also contain -; you can pass the channel URL instead (https://www.youtube.com/@name). Channel ids (UC…) aren't supported. |
| platformoptional | enum | "instagram", "tiktok" or "youtube". Defaults to "instagram". Results are cached independently per platform, so the same handle can be enriched on each without collisions. |
| forceRefreshadmin only | boolean | Bypass the result cache and look the creator up again. Ignored unless the API key is on the admin tier. |
Example request
{
"handle": "zendaya",
"platform": "instagram"
}Responses
| Status | Condition |
|---|---|
| 200 | The result. status is completed when an email was found and partial when not. credits says what the call cost. Cache hits carry cached: true. |
| 402 | Out of credits for a creator you haven't unlocked. No credit was spent. See Pricing. |
| 4xx | Validation, auth, or rate-limit error. See Errors. |
| 503 | The upstream data source is briefly unavailable. Nothing was cached — retry after the Retry-After header. |
{
"handle": "zendaya",
"platform": "instagram",
"customerId": "acct_V1StGXR8_Z5j",
"status": "completed",
"result": {
"emails": [
{
"email": "team@zendaya.com",
"confidence": 0.9
}
],
"profile": {
"firstName": "Zendaya",
"gender": "female",
"country": "US",
"state": "California",
"city": "Los Angeles"
},
"socialProfiles": [
{ "platform": "tiktok", "url": "https://tiktok.com/@zendaya" }
]
},
"credits": { "charged": 1, "remaining": 259 }
}{
"handle": "somecreator",
"platform": "tiktok",
"customerId": "acct_V1StGXR8_Z5j",
"status": "partial",
"result": {
"emails": [],
"profile": {},
"socialProfiles": []
},
"credits": { "charged": 0, "remaining": 259 }
}{
"handle": "zendaya",
"platform": "instagram",
"customerId": "acct_V1StGXR8_Z5j",
"status": "completed",
"cached": true,
"result": {
"emails": [
{
"email": "team@zendaya.com",
"confidence": 0.9
}
],
"profile": {
"firstName": "Zendaya",
"gender": "female",
"country": "US",
"state": "California",
"city": "Los Angeles"
},
"socialProfiles": [
{ "platform": "tiktok", "url": "https://tiktok.com/@zendaya" }
]
},
"credits": { "charged": 0, "remaining": 259 }
}{
"error": "insufficient_credits",
"remaining": 0,
"buyUrl": "https://buy.stripe.com/…?client_reference_id=acct_V1StGXR8_Z5j"
}Check credits
Your balance, the credit pack, your recent credit movements and what you spent on each item over the last 30 days. Free to call. You can also sign in, top right, with your Social Gems login to see your organization's balance, and as an admin, copy its API key.
curl https://enrichment.socialgems.io/api/v1/account \
-H "Authorization: Bearer $API_KEY"{
"id": "acct_V1StGXR8_Z5j",
"name": "Acme",
"kind": "direct",
"credits": 259,
"pack": {
"credits": 250,
"priceUsd": 29,
"buyUrl": "https://buy.stripe.com/…?client_reference_id=acct_V1StGXR8_Z5j"
},
"history": [
{ "at": "2026-10-21T10:12:05.904Z", "type": "usage", "credits": -1, "ref": "instagram:zendaya", "item": "contact" },
{ "at": "2026-10-20T16:02:11.517Z", "type": "credit", "credits": 250, "ref": "pi_3Q…", "note": "250-credit pack" },
{ "at": "2026-10-20T15:58:30.004Z", "type": "credit", "credits": 10, "ref": "free:acct_V1StGXR8_Z5j", "note": "free credits" }
],
"usage": {
"since": "2026-09-21T10:12:05.904Z",
"items": [{ "item": "contact", "charges": 1, "credits": 1 }]
}
}Result object
Every 200 response includes a result object with the fields below. Missing optional fields are omitted.
| Field | Type | Description |
|---|---|---|
| emails[] | array | Primary first. Each entry has email and confidence (0–1). Higher confidence means stronger evidence the address is deliverable. |
| profile.firstName | string | Given name. |
| profile.country | string | ISO 3166 alpha-2 code when recognized, otherwise the country name as reported. |
| profile.state | string | State or region, where available. |
| profile.city | string | City, where available. |
| profile.gender | enum | male or female. |
| profile.phoneNumber | string | Contact phone when publicly listed. |
| socialProfiles[] | array | The creator's accounts on other platforms (YouTube, TikTok, X, …), returned with the same lookup. |
Rate limits
Limits are applied per API key. Hitting a limit returns 429 with a retryAt ISO timestamp.
| Tier | Limit | Notes |
|---|---|---|
| starter | 60 / minute | Production workloads. |
| pro | 300 / minute | High-volume ingestion. |
| admin | 1,000 / minute | Internal only. Enables forceRefresh. |
Errors
Errors return a JSON body with an error code. Some errors include additional fields (e.g. retryAt on 429).
| Status | Code | When it happens |
|---|---|---|
| 400 | invalid request body | Body failed schema validation. |
| 400 | invalid_handle | Handle contains characters outside a–z, 0–9, . and _ (YouTube also allows -), has the wrong length, or is a YouTube channel id. |
| 401 | missing bearer token | Authorization header is missing or malformed. |
| 401 | invalid api key | Key not found or revoked. |
| 402 | insufficient_credits | No credits left for a creator you haven't unlocked. Buy a pack at buyUrl. |
| 403 | account_not_found | The key isn't linked to an account. |
| 429 | rate_limited | Tier limit exceeded. Retry after retryAt. |
| 503 | upstream_unavailable | The creator database timed out or is rate-limited. Retry after Retry-After when present. |
{
"error": "rate_limited",
"retryAt": "2026-10-21T10:13:04.112Z"
}