# SexyGen API integration instructions for local LLMs

Use the following API surface to integrate SexyGen into an external system.

## Authentication

- Base URL: https://sexygen.io/api
- Authentication header for product endpoints:




  X-API-Key: sk_live_your_key_here

- Content-Type for JSON requests:




  Content-Type: application/json

## Recommended integration flow

1. Create a real creator or an AI creator.
2. If it is a real creator, upload onboarding photos before generating content.
3. Generate photo or video content for the creator.
4. Optionally create dating profiles and generate profile content.
5. Optionally create dating-profile batches.

---

## 1) Create a real creator

### Endpoint
- Method: POST
- Path: /creators

### Request body
```json
{
  "name": "Sophia Rose",
  "plan": "Starter"
}
```

### Fields
- name: string, required. Creator display name.
- plan: string, optional. Allowed values: Starter, Pro, Agency. If omitted, the creator inherits your account's current billing tier — plan is no longer user-selectable per-creator.

### Example response
```json
{
  "creator": {
    "id": "creator_id",
    "name": "Sophia Rose",
    "plan": "Starter"
  }
}
```

---

## 2) Upload real creator photos

### Endpoint
- Method: POST
- Path: /creators/:id/photos
- Content-Type: multipart/form-data

### Form fields
- files: one or more image files, required.
- slot_start: optional integer. Starting slot index for uploaded files.

### Validation rules
- At least one file is required.
- Allowed mime types: JPG, PNG, WEBP.
- Maximum size per file: 5MB.
- If this is the first upload or slot_start is 0, the first file must contain a clearly detectable close-up face.

### Example response
```json
{
  "photos": [
    {
      "id": "photo_id",
      "slotPosition": 0,
      "contentUrl": "/api/creator-assets/photo_id"
    }
  ]
}
```

---

## 3) Generate photos for a real creator

### Endpoint
- Method: POST
- Path: /creators/:id/generate/photos

### Request body
```json
{
  "count": 3,
  "theme": "casual",
  "prompt": "Luxury hotel balcony, warm golden light, confident pose"
}
```

### Fields
- count: number, optional. Clamped to an integer between 1 and 4. Default: 1.
- theme: string, optional. Allowed values: professional, casual, adventure, romantic, lifestyle.
- prompt: string, optional. Trimmed and capped at 500 characters.
- promptType: do not send this field. The backend classifies the prompt as sfw, sexy, or nsfw before it calls the generation service.

### Example response
```json
{
  "job": {
    "id": "job_id",
    "status": "queued"
  },
  "profileId": "profile_id"
}
```

---

## 4) Generate a video for a real creator

### Endpoint
- Method: POST
- Path: /creators/:id/videos/generate

### Request body
```json
{
  "presetKey": "dildo-riding",
  "videoType": "nsfw",
  "variableValues": {
    "duration": "30s",
    "quality": "1080p"
  },
  "referenceImages": {
    "dildo_base": "https://cdn.example.com/dildo-reference.png"
  }
}
```

### Fields
- presetKey: string, required. Scenario/preset identifier.
- videoType: string, required. Currently only nsfw is accepted.
- variableValues: object of string-to-string pairs, optional. Supported duration values are currently 10s, 30s, and 1m.
- referenceImages: object of string-to-string pairs, optional. Empty strings are dropped.

### Example response
```json
{
  "video": {
    "id": "video_id",
    "status": "queued_image"
  }
}
```

---

## 5) Create an AI creator

### Endpoint
- Method: POST
- Path: /ai-creators

### Request body
```json
{
  "name": "Luna Vale",
  "plan": "Starter",
  "gender": "female",
  "ethnicity": "latina",
  "hairColor": "black",
  "bodyType": "slim",
  "minAge": 24,
  "maxAge": 30,
  "personalityDescription": "Playful, luxurious, and slightly mysterious"
}
```

### Fields
- name: string, required.
- plan: string, optional. Allowed values: Starter, Pro, Agency. If omitted, the AI creator inherits your account's current billing tier — plan is no longer user-selectable per-creator.
- gender: optional. Allowed values: male, female.
- ethnicity: optional. Allowed values: white, latina, asian, black.
- hairColor: optional string.
- bodyType: optional. Allowed values: slim, medium, big.
- minAge: optional number.
- maxAge: optional number.
- personalityDescription: optional string.

### Example response
```json
{
  "creator": {
    "publicId": "ai_creator_id",
    "name": "Luna Vale",
    "plan": "Starter"
  }
}
```

---

## 6) Generate images for an AI creator

### Endpoint
- Method: POST
- Path: /ai-creators/:id/generate

### Request body
```json
{
  "purpose": "content_generation",
  "count": 2,
  "prompt": "Silk robe, penthouse suite, high-contrast editorial lighting"
}
```

### Fields
- purpose: optional. Allowed values: training_reference, content_generation. Default: training_reference.
- count: optional number. Clamped to an integer between 1 and 4. Default: 1.
- prompt: optional string. Trimmed and capped at 500 characters.
- promptType: do not send this field for content generation. The backend classifies the prompt as sfw, sexy, or nsfw before generation.

### Special behavior
- If purpose is training_reference and no prompt is provided, the route auto-builds a training prompt and forces one NSFW full-body image.

### Example response
```json
{
  "job": {
    "id": "job_id",
    "status": "queued"
  },
  "profileId": "profile_id"
}
```

---

## 7) Generate a video for an AI creator

### Endpoint
- Method: POST
- Path: /ai-creators/:id/videos/generate

### Request body
```json
{
  "presetKey": "dildo-riding",
  "videoType": "nsfw",
  "variableValues": {
    "duration": "30s",
    "quality": "1080p"
  },
  "referenceImages": {
    "dildo_base": "https://cdn.example.com/dildo-reference.png"
  }
}
```

### Fields
- Same contract as the real creator video generation route.

### Example response
```json
{
  "video": {
    "id": "video_id",
    "status": "queued_image"
  }
}
```

---

## 8) Create a dating profile

### Endpoint
- Method: POST
- Path: /dating-profiles/generate-pack

This is the real "create profile" endpoint — the same one the dashboard's
own "Create Profile" button calls. It picks a stock reference face matching
your filters, then generates a batch of images for it. Billed 50 tokens per
image (sfwCount + sexyCount).

### Request body
```json
{
  "gender": "female",
  "ethnicity": "white",
  "hairColor": "blonde",
  "bodyType": "slim",
  "minAge": 22,
  "maxAge": 29,
  "personalityDescription": "High-energy, glamorous, and flirty",
  "sfwCount": 6,
  "sexyCount": 3
}
```

### Fields
- gender: optional. Allowed value: female. (Only value the dashboard's own create form offers today.)
- ethnicity: optional. Allowed values: white, latina, asian, black.
- hairColor: optional string.
- bodyType: optional. Allowed value: slim. (Only value the dashboard's own create form offers today.)
- minAge: optional number.
- maxAge: optional number.
- personalityDescription: optional string.
- sfwCount: optional number. Default: 6.
- sexyCount: optional number. Default: 3.

### Example response
```json
{
  "success": true,
  "pack": {
    "id": "profile_id",
    "profileId": "profile_id",
    "generationJobId": null,
    "status": "generating",
    "sfwImageCount": 6,
    "sexyImageCount": 3,
    "nsfwImageCount": 0,
    "creditsCharged": 450
  }
}
```

---

## 9) Generate content for an existing dating profile

### Endpoint
- Method: POST
- Path: /dating-profiles/:id/generate

### Request body
```json
{
  "count": 4,
  "theme": "romantic",
  "prompt": "Rooftop dinner date, soft candlelight, city skyline in the background"
}
```

### Fields
- count: optional number. Clamped to an integer between 1 and 10. Default: 4.
- theme: optional. Allowed values: professional, casual, adventure, romantic, lifestyle.
- prompt: optional string. Trimmed and capped at 500 characters.

### Example response
```json
{
  "job": {
    "id": "job_id",
    "status": "queued"
  }
}
```

---

## 10) Create a dating-profile batch

### Endpoint
- Method: POST
- Path: /dating-profiles/batch

Creates up to 50 independent dating profiles in one call. Every profile uses
the same appearance filters and the same per-profile image split.

### Request body
```json
{
  "count": 20,
  "gender": "female",
  "ethnicity": "latina",
  "bodyType": "slim",
  "minAge": 22,
  "maxAge": 29,
  "sfwCount": 6,
  "sexyCount": 3,
  "nsfwCount": 0
}
```

### Fields
- count: optional number. Clamped to an integer between 1 and 50. Default: 1.
- gender, ethnicity, hairColor, bodyType, minAge, maxAge, personalityDescription: same
  appearance filters as generate-pack.
- sfwCount / sexyCount / nsfwCount: images per profile. Defaults: 6 / 3 / 0.

### Billing
- (sfwCount + sexyCount + nsfwCount) × 50 tokens per billed profile.
- Free profiles per batch: 10–19 → 1, 20–29 → 3, 30–39 → 5, 40–49 → 8, 50 → 12.
- The full amount is checked up front. Returns 402 with code
  insufficient_tokens (plus required / available) when the balance is short.

### Delivery
- Batch profiles go through human QA review before they are released.
- The batch is delivered once every member profile has cleared review:
  notifiedAt is set on the batch and one "batch ready" email/notification is sent.
- Until then the member profiles are hidden from GET /dating-profiles, and
  GET /dating-profiles/:id/images lists their photos under reviewQueue.
- Poll GET /dating-profiles/batches (or GET /dating-profiles/batches/:id) and
  treat notifiedAt !== null as delivered. Expect hours, not minutes.
- Returns 503 while dating-profile generation is in maintenance mode.

### Example response
```json
{
  "success": true,
  "batch": {
    "id": "batch_id",
    "requestedCount": 20,
    "createdCount": 20,
    "failedCount": 0,
    "creditsCharged": 7650,
    "notifiedAt": null,
    "members": [{ "profileId": "profile_id", "error": null }]
  }
}
```

---

## 11) Order a batch (batch request)

### Endpoint
- Method: POST
- Path: /dating-profiles/batch-requests

Orders of 1–50 profiles run immediately as a real batch — identical to
section 10, tokens charged, QA review, delivery via notifiedAt. Orders of
51–100 profiles, or orders the account cannot currently afford, are filed for
the team and handled manually. Check "executed" in the response to know which
happened; never assume a request generated anything unless "executed" is true.
Optional sfwCount / sexyCount / nsfwCount set the per-profile image split
(defaults 6 / 3 / 0).

### Request body
```json
{
  "count": 40,
  "gender": "female",
  "ethnicity": "latina",
  "bodyType": "slim",
  "sfwCount": 1,
  "sexyCount": 0,
  "nsfwCount": 0,
  "notes": "Prefer upscale nightlife / travel aesthetic"
}
```

### Fields
- count: optional number. Clamped to an integer between 1 and 100. Default: 1. 1–50 runs automatically, 51–100 is manual.
- gender: optional. Allowed value: female.
- ethnicity: optional. Allowed values: white, latina, asian, black.
- hairColor: optional string.
- bodyType: optional. Allowed value: slim.
- minAge, maxAge: optional numbers.
- personalityDescription: optional string.
- sfwCount / sexyCount / nsfwCount: optional numbers, images per profile. Defaults: 6 / 3 / 0.
- notes: optional string.

### Example response (auto-run)
```json
{
  "success": true,
  "executed": true,
  "request": { "id": "request_id", "requestedCount": 40, "status": "executed", "batchId": "batch_id" },
  "batch": { "id": "batch_id", "requestedCount": 40, "createdCount": 40, "failedCount": 0, "notifiedAt": null }
}
```
Poll GET /dating-profiles/batches/:id with batch.id; notifiedAt marks delivery.

### Example response (filed for the team)
```json
{
  "success": true,
  "executed": false,
  "reason": "insufficient_tokens",
  "required": 450,
  "available": 100,
  "request": { "id": "request_id", "requestedCount": 10, "status": "pending", "batchId": null },
  "batch": null
}
```
reason is one of above_self_serve_cap, insufficient_tokens, error. Nothing was
generated; the team has been notified. For insufficient_tokens, top up and
resubmit, or wait for the team to run the request.

---

## Useful read/list endpoints

- GET /creators
- GET /creators/:id
- GET /creators/:id/images
- GET /creators/:id/videos?videoType=sfw|nsfw
- GET /creators/:id/active-job
- GET /creators/:id/jobs/:jobId
- GET /ai-creators
- GET /ai-creators/:id
- GET /ai-creators/:id/images
- GET /ai-creators/:id/videos?videoType=sfw|nsfw
- GET /dating-profiles?limit=24&offset=0&search=query
- GET /dating-profiles/:id
- GET /dating-profiles/:id/images
- GET /dating-profiles/:id/active-job
- GET /dating-profiles/:id/jobs/:jobId
- GET /dating-profiles/batches
- GET /dating-profiles/batches/:id

## Implementation instructions for the local LLM

- Use the base URL https://sexygen.io/api.
- For external product integration, send X-API-Key on all product requests.
- Prefer JSON request bodies unless the endpoint explicitly requires multipart/form-data.
- For real creator onboarding, create the creator first, then upload photos, then start generation.
- For AI creators, create the AI creator first, then generate training-reference or content images.
- Use returned creator ids, profile ids, job ids, and batch ids as primary foreign keys in your system.
- Poll the job/status endpoints after generation requests instead of assuming synchronous completion.
- Preserve request validation rules exactly, especially clamped count values and allowed enums.
