Influencers
AI brand ambassadors that drive your customer's UGC content. Created automatically on project provision; customizable per-project.
An influencer is a brand-ambassador persona attached to a project. It has a look, a voice, a speaking style, a sense of humor, and a set of content themes. When you generate UGC-style content, the influencer is what the hook, the caption, and the narrative speak as.
Influencers aren't real people. They're synthetic personas, rendered consistently across generations so a customer's feed reads like one creator instead of a pile of LLM output. One project can have many; most projects ship with one auto-created at onboarding and add more over time.
Where they come from
Two paths:
- Auto-created at project provision. When brand ingestion completes (GitHub, website, or App Store), Layers seeds the project with an initial influencer whose personality is derived from brand context — voice, target audience, language. You don't have to do anything for this to happen.
- Created on demand.
POST /v1/projects/:projectId/influencerscreates an influencer row. For simple cases you pass onlyname; the schema accepts the full persona (archetype, primary language, voice profile, personality fields) as optional fields on the same call.
Schema
An influencer row exposes identity fields (influencerId, name, gender, ageRange, status), a personality object describing voice, and a referenceImages[] array describing the appearance anchor. Full shape:
{
"influencerId": "inf_01HX9Y6K7EJ4T2ABCDEF",
"projectId": "254a4ce1-f4ca-42b1-9e36-17ca45ef3d39",
"name": "Nova",
"gender": "nonbinary",
"ageRange": "25-34",
"status": "ready",
"thumbnailUrl": "https://media.layers.com/inf/thumb.jpg",
"personality": {
"traits": ["earnest", "thorough"],
"tone": "conversational",
"humor": "deadpan",
"formality": "casual",
"values": ["transparency", "craft"],
"interests": ["productivity", "tools-I-use"],
"speakingStyle": "direct",
"catchphrases": ["Ship it."]
},
"referenceImages": [
{
"assetId": "med_01HX9Y6K7EJ4T2ABCDEF",
"url": "https://media.layers.com/...",
"thumbnailUrl": "https://media.layers.com/...",
"addedAt": "2026-04-18T12:04:11.000Z"
}
],
"createdAt": "2026-04-18T12:04:11.000Z",
"updatedAt": "2026-04-18T12:04:11.000Z"
}Status values: draft | pending | training | ready | failed. Gender values: male | female | nonbinary | unspecified.
The personality block is consumed by the narrative generator during UGC content generation. It doesn't affect organic engagement logic, ad bidding, or approval scoring — purely narrative.
Changing personality fields doesn't retroactively regenerate existing content. It only affects new generations that reference this influencer after the patch lands.
Cloning
POST /v1/influencers/:influencerId/clone
{
"name": "Nova (B variant)",
"newInfluencerId": "inf_01HX9Y6K7EJ4T2NOVAB",
"overrides": {
"personality": { "humorStyle": "dry-witty" }
}
}
→ 202
{
"jobId": "job_01HX9Y6K7EJ4T2ABCDEF01234",
"kind": "influencer_clone",
"status": "running",
"influencerId": "inf_01HX9Y6K7EJ4T2NOVAB"
}Clone is async; a render job produces fresh reference images using the source influencer's appearance as an anchor, then applies any overrides before the new row lands in status: ready.
Selecting an influencer for content
When you generate content, the brief can carry an influencerId:
{
"brief": {
"targetPlatforms": ["tiktok", "instagram"],
"influencerId": "inf_01HX9Y6K7EJ4T2ABCDEF",
"themeTags": ["launch", "feature-spotlight"]
}
}If you don't pass one, the generator picks the project's primary influencer. If you want a round-robin across multiple influencers on a single project, do the selection in your own code before calling — the API doesn't rotate for you.
Lifecycle
PATCH /v1/influencers/:influencerIdupdates personality, name, or gender / age-range.DELETE /v1/influencers/:influencerIdsoft-deletes. Body is optional{ "reason": "..." }which is persisted on the deleted row for audit. The response is{ "influencerId", "status": "deleted", "deletedAt" }. Deleted influencers still appear on any historical content that used them; they just can't be selected for new generations.POST /v1/influencers/:influencerId/reference-imagesbinds media-library assets as references. Body:{ "assetIds": ["med_..."] }— array-of-ids. The response echoes the fullreferenceImages[]list on the influencer. Assets that don't resolve are silently dropped; the response only contains resolved ones.