# Characters

`GET | POST | PATCH | DELETE /v1/characters` — Your cast: persona sheets, faces and voices, reusable everywhere.

- Base URL: https://eroq.ai/v1
- Auth: `Authorization: Bearer eroq_sk_…` (create keys at https://eroq.ai/dashboard/keys)
- Credits: Free

A character is the reusable identity of your products: a persona sheet (folded into chat context and render prompts), reference photos (they feed the look-sheet generation), an accepted **look sheet** (`sheetUrl` — the canonical image the renderers condition on) and a voice. Reference one as `char:<id>` in any `elements` array, or as the `voice` of /v1/audio/speech. To put the character in an image or video render, it needs a sheet first (see /v1/sheets) — chatting needs none.

`POST /v1/characters` creates one (`name`, `gender`, `prompt` persona sheet, `description`, `avatarUrl`, `age`, `voiceId`, `style`); `GET /v1/characters/{id}` fetches one with its reference photos and its `sheetUrl`; `PATCH /v1/characters/{id}` updates any field; `DELETE /v1/characters/{id}` removes it. Reference photo UPLOADS stay in the studio for now — pass hosted URLs via `avatarUrl` meanwhile.

## Operations

| Method | Path | What it does |
| --- | --- | --- |
| `GET` | `/v1/characters` | List your characters with their reference photos. |
| `POST` | `/v1/characters` | Create a character. |
| `GET` | `/v1/characters/{id}` | One character, reference photos included. |
| `PATCH` | `/v1/characters/{id}` | Update any field. |
| `DELETE` | `/v1/characters/{id}` | Remove the character — past renders are untouched. |

## GET /v1/characters

List your characters with their reference photos.

### Example request

```bash
curl https://eroq.ai/v1/characters \
  -H "Authorization: Bearer $EROQ_API_KEY"
```

```javascript
const res = await fetch('https://eroq.ai/v1/characters', {
  headers: { Authorization: `Bearer ${process.env.EROQ_API_KEY}` },
})
console.log(await res.json())
```

```python
import os, requests

res = requests.get("https://eroq.ai/v1/characters", headers={"Authorization": f"Bearer {os.environ['EROQ_API_KEY']}"})
print(res.json())
```

```go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, _ := http.NewRequest("GET", "https://eroq.ai/v1/characters", nil)
	req.Header.Set("Authorization", "Bearer "+os.Getenv("EROQ_API_KEY"))

	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(string(out))
}
```

### Response


```json
{
  "characters": [{
    "id": "9c1e…", "name": "Nova", "gender": "female",
    "prompt": "sardonic mechanic, quick wit…", "voiceId": "aria",
    "sheetUrl": "https://…", "sheetCreatedAt": "2026-09-20T…Z",
    "references": [{ "url": "https://…", "contentType": "image/webp" }]
  }]
}
```

## POST /v1/characters

Create a character.

### Request body

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | string | yes | Up to 80 characters. |
| `gender` | string | no | `female` (default), `male` or `nonbinary`. |
| `prompt` | string | no | The persona sheet — folded into chat context and render prompts, up to 4000 characters. |
| `description` | string | no | Short card description, up to 600 characters. |
| `avatarUrl` | string | no | Hosted portrait URL — drives image→video and face consistency. |
| `age` | integer | no | 18 or older — every character, no exceptions. |
| `voiceId` | string | no | A roster voice id or one of your clone ids — makes the character speakable via char:<id>. |
| `style` | string | no | Visual register (photoreal, anime, …) folded into renders. |

### Example request

```bash
curl https://eroq.ai/v1/characters \
  -H "Authorization: Bearer $EROQ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Nova",
  "gender": "female",
  "prompt": "Sardonic starship mechanic, dry humor, gold tooth.",
  "voiceId": "aria"
}'
```

```javascript
const res = await fetch('https://eroq.ai/v1/characters', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.EROQ_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "name": "Nova",
    "gender": "female",
    "prompt": "Sardonic starship mechanic, dry humor, gold tooth.",
    "voiceId": "aria"
  }),
})
console.log(await res.json())
```

```python
import os, requests

res = requests.post(
    "https://eroq.ai/v1/characters",
    headers={"Authorization": f"Bearer {os.environ['EROQ_API_KEY']}"},
    json={
        "name": "Nova",
        "gender": "female",
        "prompt": "Sardonic starship mechanic, dry humor, gold tooth.",
        "voiceId": "aria"
    },
)
print(res.json())
```

```go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"
)

func main() {
	body := strings.NewReader(`{
  "name": "Nova",
  "gender": "female",
  "prompt": "Sardonic starship mechanic, dry humor, gold tooth.",
  "voiceId": "aria"
}`)

	req, _ := http.NewRequest("POST", "https://eroq.ai/v1/characters", body)
	req.Header.Set("Authorization", "Bearer "+os.Getenv("EROQ_API_KEY"))
	req.Header.Set("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(string(out))
}
```

### Response


```json
{
  "id": "9c1e…", "name": "Nova", "gender": "female",
  "prompt": "Sardonic starship mechanic, dry humor, gold tooth.",
  "description": "", "avatarUrl": "https://…", "age": 29,
  "voiceId": "aria", "style": "photoreal",
  "createdAt": "2026-09-11T14:02:11Z", "updatedAt": "2026-09-11T14:02:11Z",
  "references": [{ "id": "…", "url": "https://…", "contentType": "image/webp" }]
}
```

## GET /v1/characters/{id}

One character, reference photos included.

### Example request

```bash
curl https://eroq.ai/v1/characters/CHARACTER_ID \
  -H "Authorization: Bearer $EROQ_API_KEY"
```

```javascript
const res = await fetch('https://eroq.ai/v1/characters/CHARACTER_ID', {
  headers: { Authorization: `Bearer ${process.env.EROQ_API_KEY}` },
})
console.log(await res.json())
```

```python
import os, requests

res = requests.get("https://eroq.ai/v1/characters/CHARACTER_ID", headers={"Authorization": f"Bearer {os.environ['EROQ_API_KEY']}"})
print(res.json())
```

```go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, _ := http.NewRequest("GET", "https://eroq.ai/v1/characters/CHARACTER_ID", nil)
	req.Header.Set("Authorization", "Bearer "+os.Getenv("EROQ_API_KEY"))

	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(string(out))
}
```

### Response


```json
{
  "id": "9c1e…", "name": "Nova", "gender": "female",
  "prompt": "Sardonic starship mechanic, dry humor, gold tooth.",
  "description": "", "avatarUrl": "https://…", "age": 29,
  "voiceId": "aria", "style": "photoreal",
  "createdAt": "2026-09-11T14:02:11Z", "updatedAt": "2026-09-11T14:02:11Z",
  "references": [{ "id": "…", "url": "https://…", "contentType": "image/webp" }]
}
```

## PATCH /v1/characters/{id}

Update any field.

### Example request

```bash
curl -X PATCH https://eroq.ai/v1/characters/CHARACTER_ID \
  -H "Authorization: Bearer $EROQ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "prompt": "Sardonic starship mechanic — now chief engineer."
}'
```

```javascript
const res = await fetch('https://eroq.ai/v1/characters/CHARACTER_ID', {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${process.env.EROQ_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "prompt": "Sardonic starship mechanic — now chief engineer."
  }),
})
console.log(await res.json())
```

```python
import os, requests

res = requests.patch(
    "https://eroq.ai/v1/characters/CHARACTER_ID",
    headers={"Authorization": f"Bearer {os.environ['EROQ_API_KEY']}"},
    json={
        "prompt": "Sardonic starship mechanic — now chief engineer."
    },
)
print(res.json())
```

```go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"
)

func main() {
	body := strings.NewReader(`{
  "prompt": "Sardonic starship mechanic — now chief engineer."
}`)

	req, _ := http.NewRequest("PATCH", "https://eroq.ai/v1/characters/CHARACTER_ID", body)
	req.Header.Set("Authorization", "Bearer "+os.Getenv("EROQ_API_KEY"))
	req.Header.Set("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(string(out))
}
```

### Response


```json
{
  "id": "9c1e…", "name": "Nova", "gender": "female",
  "prompt": "Sardonic starship mechanic, dry humor, gold tooth.",
  "description": "", "avatarUrl": "https://…", "age": 29,
  "voiceId": "aria", "style": "photoreal",
  "createdAt": "2026-09-11T14:02:11Z", "updatedAt": "2026-09-11T14:02:11Z",
  "references": [{ "id": "…", "url": "https://…", "contentType": "image/webp" }]
}
```

## DELETE /v1/characters/{id}

Remove the character — past renders are untouched.

### Example request

```bash
curl -X DELETE https://eroq.ai/v1/characters/CHARACTER_ID \
  -H "Authorization: Bearer $EROQ_API_KEY"
```

```javascript
const res = await fetch('https://eroq.ai/v1/characters/CHARACTER_ID', {
  method: 'DELETE',
  headers: { Authorization: `Bearer ${process.env.EROQ_API_KEY}` },
})
console.log(await res.json())
```

```python
import os, requests

res = requests.delete("https://eroq.ai/v1/characters/CHARACTER_ID", headers={"Authorization": f"Bearer {os.environ['EROQ_API_KEY']}"})
print(res.json())
```

```go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	req, _ := http.NewRequest("DELETE", "https://eroq.ai/v1/characters/CHARACTER_ID", nil)
	req.Header.Set("Authorization", "Bearer "+os.Getenv("EROQ_API_KEY"))

	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(string(out))
}
```

### Response


```json
{ "ok": true, "referencesDeleted": 2 }
```

---
Canonical: https://eroq.ai/docs/characters · Index for agents: https://eroq.ai/llms.txt · OpenAPI: https://eroq.ai/openapi.json
