# Influencers (/docs/api/concepts/influencers)



An influencer is a brand-ambassador persona attached to a [project](/docs/api/concepts/projects). 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 [#where-they-come-from]

Two paths:

1. **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.
2. **Created on demand.** `POST /v1/projects/:projectId/influencers` creates an influencer row. For simple cases you pass only `name`; the schema accepts the full persona (archetype, primary language, voice profile, personality fields) as optional fields on the same call.

## Schema [#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:

```json
{
  "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.

<Callout>
  Changing personality fields doesn't retroactively regenerate existing content. It only affects new generations that reference this influencer after the patch lands.
</Callout>

## Cloning [#cloning]

```http
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 [#selecting-an-influencer-for-content]

When you generate content, the brief can carry an `influencerId`:

```json
{
  "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 [#lifecycle]

* `PATCH /v1/influencers/:influencerId` updates personality, name, or gender / age-range.
* `DELETE /v1/influencers/:influencerId` soft-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-images` binds media-library assets as references. Body: `{ "assetIds": ["med_..."] }` — array-of-ids. The response echoes the full `referenceImages[]` list on the influencer. Assets that don't resolve are silently dropped; the response only contains resolved ones.
