POST /v1/projects/:projectId/influencers
Kick off an influencer-create job. Returns 202 with a job envelope.
/v1/projects/:projectId/influencers- Auth
- Bearer
- Scope
- influencers:write
Starts an influencer_create job. The influencer is created in status: "pending" while the persona + portrait render. The response is a job envelope — poll /v1/jobs/:jobId for terminal state, then read the influencer at /v1/influencers/:influencerId.
The body is intentionally tiny. Layers generates the display name, portrait, and persona attributes from the project's brand context plus the optional hints you supply. There is no name field on this request — read it back from GET /v1/influencers/:id after the job lands.
Most partners never need to call this endpoint directly — Layers auto-creates a first influencer in the background as soon as you supply appDescription on POST /v1/projects. Reach for this endpoint when the customer needs additional personas (different gender, ageRange, or prompt vibe) for variation across content batches.
Idempotency
Send an Idempotency-Key header so retries replay the same response. The influencer's id is server-generated and returned in the accept envelope — persist it and map it back to your entity. You cannot supply your own id.
Path parameters
projectIdstring (uuid)requiredThe project this influencer belongs to.
Body
Every field is optional. When omitted, Layers falls back to the project's defaults — most notably, gender falls back to the project's targetGender so the generated persona reflects the customer's audience.
genderstringoptionalDrives persona and rendering. Required for content generation, so always carries a real value on the row. Server default chain when omitted: project's `targetGender` if `female` / `male`, else `female`.One of:male,female,non_binaryageRangestringoptionalCanonical age band keyed to the renderer's persona presets. Same enum as the in-product dialog. Defaults to `young_adult` when omitted.One of:teen,young_adult,adult,mid_adult,mature,seniorpromptstringoptionalOptional free-text hint that steers visual generation — e.g. `70s rocker vibe`, `soft librarian energy`, `barista energy`. 1-60 chars. Omit for a generic persona based on `gender` + `ageRange` alone.
Voice (brandVoice) and language are inherited from the project and not accepted here. To override per persona after creation, use PATCH /v1/influencers/:id.
Request
curl -X POST https://api.layers.com/v1/projects/{projectId}/influencers \
-H "Authorization: Bearer $LAYERS_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 8d2f1a3e-0b4c-4a11-9f7e-33c0a2c1bd55" \
-d '{
"gender": "female",
"ageRange": "young_adult",
"prompt": "barista energy, soft morning light"
}'const res = await fetch(
`https://api.layers.com/v1/projects/${projectId}/influencers`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.LAYERS_API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify({
gender: 'female',
ageRange: 'young_adult',
prompt: 'barista energy, soft morning light',
}),
},
);
const { jobId, influencerId } = await res.json();import os, uuid, httpx
r = httpx.post(
f"https://api.layers.com/v1/projects/{project_id}/influencers",
headers={
"Authorization": f"Bearer {os.environ['LAYERS_API_KEY']}",
"Content-Type": "application/json",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"gender": "female",
"ageRange": "young_adult",
"prompt": "barista energy, soft morning light",
},
)
job = r.json()You can also send an empty body — every field is optional. Layers picks gender/age/prompt defaults from the project.
Responses
{
"jobId": "job_01HXZ9G7KMV2QX8Y1S5RJW3B7T",
"kind": "influencer_create",
"status": "running",
"influencerId": "inf_4a8e1bc2...",
"locationUrl": "/v1/jobs/job_01HXZ9G7KMV2QX8Y1S5RJW3B7T"
}{
"error": {
"code": "VALIDATION",
"message": "Invalid body.",
"requestId": "req_...",
"details": { "fieldErrors": { "name": ["Unrecognized key — name is server-generated."] } }
}
}Notes
Creation is async. The influencer starts in status: "pending", then moves through training to ready. The display name, portrait, and persona attributes are generated server-side; partners cannot supply reference images.
- Safe to reference immediately. You can use the
influencerIdinPOST /v1/projects/:projectId/content/slideshow-remixthe moment this call returns. Content generation waits until the influencer is ready. - Status values.
pending,training,ready,failed. - Idempotency. Set an
Idempotency-Keyheader so a retry replays the same accept envelope. The influencer id is server-generated; you cannot pass your own.
Errors
| Code | When |
|---|---|
VALIDATION | Unknown field (e.g. name, brandVoice, language), enum out of range, or bad JSON. |
NOT_FOUND | Project id not in this org. |
FORBIDDEN_SCOPE | Key lacks influencers:write. |
See also
- The jobs envelope
- Clone an influencer
- Patch an influencer — override
brandVoiceorlanguageafter creation