# Influencers and videos

AI influencers are virtual personas used to front content: each has a name, a base image and optional persona details like niche, gender and age. A persona can be a photoreal human (`style: "realistic"`, the default) or a stylized non-human character such as a mascot, cartoon or stick figure (`style: "character"`). Feature one in generated suggestions (`influencerId` on `POST /generations`), run influencer-owned automations, or generate talking-head videos of the persona speaking a script. Influencer endpoints need the `influencers:read` and `influencers:write` scopes.

## Listing and getting

`GET /influencers` lists the workspace's influencers with `search` (matches name, description and tags), `niche`, `page`, `limit` and `workspaceId` filters. `GET /influencers/{id}` returns one influencer including its base image, preview video state and Turbo settings (`turboEnabled`, `allowedAngles`).

```bash
curl -s "https://viraloop.io/api/v1/influencers" \
  -H "Authorization: Bearer $VIRALOOP_API_KEY"
```

```bash
viraloop influencers list --json
viraloop influencers get <id> --json
```

## Creating an influencer

`POST /influencers` creates an influencer from a base image you provide. `name` and `imageUrl` are required, and `imageUrl` must be a publicly reachable image of the persona. Optional persona fields: `description`, `niche` (one of the app's niche slugs, e.g. `fitness`, `tech`, `food`), `gender` (`male` or `female`), `age` (18 to 99), `ethnicity`, `tags` and `workspaceId`.

```bash
curl -s -X POST "https://viraloop.io/api/v1/influencers" \
  -H "Authorization: Bearer $VIRALOOP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Maya","imageUrl":"https://example.com/maya.jpg","niche":"fitness","gender":"female"}'
```

```bash
viraloop influencers create --name Maya --image-url https://example.com/maya.jpg \
  --niche fitness --json
```

A short animated preview generates in the background when the team has credits: it costs 10 credits and is skipped when the team is out of credits. The response shows it as `videoPreview` with status `pending`. To generate a base image from a prompt instead of providing one, use the web app. The endpoint is rate limited to 10 requests per 3600 seconds and supports the `Idempotency-Key` header.

### Non-human characters

Set `style` to `"character"` to create a persona that is not a real person, and pass `characterDescription` describing how it looks and the art style it is drawn in:

```bash
curl -s -X POST "https://viraloop.io/api/v1/influencers" \
  -H "Authorization: Bearer $VIRALOOP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Doodle","imageUrl":"https://example.com/doodle.png","style":"character","characterDescription":"A black stick figure with a round head and large white eyes, clean hand-drawn doodle style on a plain background"}'
```

`style` decides how every prompt the platform builds for this influencer describes it. A `character` influencer is never described as a real person and is never asked for a photograph, across scene images, talking-head videos and automated posting. `gender`, `age` and `ethnicity` do not apply and are ignored; `characterDescription` takes their place in keeping later generations on-model, so keep it specific.

Both fields are returned by `GET /influencers` and `GET /influencers/{id}`. `style` is always present (`"realistic"` for anything created before this field existed), and `characterDescription` is `null` for realistic personas.

## Generating a talking-head video

`POST /influencers/{id}/videos` generates a talking-head UGC video of the influencer speaking your script (Seedance 2, 9:16). It costs 20 credits, deducted up front; without enough credits it fails with error type `insufficient_credits` (see [credits and limits](/developers/docs/credits-and-limits)).

`script` is required (max 1000 characters). Optional fields: `imageUrl` (a reference image, defaults to the influencer's base image), `language` (spoken language, default English), `duration` (5 to 30 seconds) and `mode` (`speaker` for a talking head, `scene` for a wider shot). Rate limited to 10 requests per 600 seconds; supports the `Idempotency-Key` header.

```bash
curl -s -X POST "https://viraloop.io/api/v1/influencers/<id>/videos" \
  -H "Authorization: Bearer $VIRALOOP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"script":"Three things I wish I knew before my first marathon","duration":10}'
```

```bash
viraloop videos create --influencer <id> \
  --script "Three things I wish I knew before my first marathon" --duration 10 --json
```

The call is asynchronous and returns `202` with the video in `processing`:

```json
{
	"success": true,
	"data": {
		"id": "665f1b2a9c31a2b3c4d5e730",
		"kind": "video",
		"influencerId": "665f1b2a9c31a2b3c4d5e720",
		"status": "processing",
		"model": "seedance_2",
		"creditsUsed": 20,
		"statusUrl": "/api/v1/videos/665f1b2a9c31a2b3c4d5e730"
	}
}
```

## Polling

Poll `GET /videos/{id}` until a terminal status: `completed` (with `videoUrl` set) or `failed` (with `error` set). Generation typically takes 2 to 10 minutes.

```bash
curl -s "https://viraloop.io/api/v1/videos/<id>" \
  -H "Authorization: Bearer $VIRALOOP_API_KEY"
```

```bash
viraloop videos get <id> --json
```

## Posting the video

A completed video has a publicly reachable `videoUrl`, so publish it like any of your own media via `POST /posts`:

```bash
curl -s -X POST "https://viraloop.io/api/v1/posts" \
  -H "Authorization: Bearer $VIRALOOP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"videoUrl":"https://cdn.viraloop.io/videos/abc.mp4","selectedAccounts":{"tiktok":["665f1b2a9c31a2b3c4d5e700"]},"schedule":"asap"}'
```

```bash
viraloop posts create --video-url https://cdn.viraloop.io/videos/abc.mp4 \
  --accounts tiktok:<accountId> --when asap --wait --json
```

To publish under an influencer-scoped account, set `ownerType` to `influencer` with the `influencerId` (accounts from `GET /accounts?ownerType=influencer`). See [posts and scheduling](/developers/docs/posts-and-scheduling) for accounts, timing and polling.

## Listing an influencer's videos

`GET /influencers/{id}/videos` lists the influencer's generated videos, newest first, with status and URLs. Filters: `status` (`pending`, `processing`, `completed`, `failed`), `page` and `limit`.

```bash
curl -s "https://viraloop.io/api/v1/influencers/<id>/videos" \
  -H "Authorization: Bearer $VIRALOOP_API_KEY"
```

```bash
viraloop videos list --influencer <id> --json
```

## Assets

`GET /assets` (scope `assets:read`) lists the workspace's uploaded media library: the videos and images used as generation backgrounds and sources. The endpoint is read-only in v1; uploading happens in the web app. Filters: `kind` (`video`, `image`, `audio`), `category`, `turboEnabled`, `page`, `limit` and `workspaceId`.

```bash
curl -s "https://viraloop.io/api/v1/assets?kind=video" \
  -H "Authorization: Bearer $VIRALOOP_API_KEY"
```

```bash
viraloop assets list --json
```
