Locations
Locations belong to a project and can be assigned to scenes. Each location can have an AI-generated or manually uploaded background image. The AI endpoints help writers discover consistent settings.
Endpoints overview
| Method | Endpoint | Permission | Description |
|---|---|---|---|
GET | /api/locations/project/:projectId | authenticated | List locations by project |
GET | /api/locations/:id | authenticated | Get location by ID |
POST | /api/locations | location:create | Create a location |
PUT / PATCH | /api/locations/:id | location:edit | Update a location |
DELETE | /api/locations/:id | location:delete | Delete a location |
POST | /api/locations/:id/generate-image | location:image:generate | Generate location image (AI) |
POST | /api/locations/:id/upload-image | location:image:upload | Upload location image (base64) |
POST | /api/locations/ai/recommend | authenticated | AI location recommendation |
POST | /api/locations/ai/check-duplicate | authenticated | AI duplicate check |
Endpoints
List locations by project
GET /api/locations/project/:projectId — Auth required
Response — 200
{
"locations": [
{
"id": "loc-uuid-001",
"projectId": "proj-uuid-001",
"name": "Underground Lab",
"nameI18n": { "uk": "Підземна лабораторія", "en": "Underground Lab", "es": "Laboratorio subterráneo" },
"description": "A dimly lit research facility carved into the bedrock.",
"descriptionI18n": { "uk": "Слабо освітлена дослідницька установа.", "en": "A dimly lit research facility carved into the bedrock.", "es": "Una instalación de investigación tenuemente iluminada." },
"imageUrl": "/api/locations/file/proj-uuid/loc-uuid/background.png",
"generationParams": {
"prompt": "Underground lab, dim lighting, sci-fi",
"width": 1920,
"height": 1088,
"steps": 28,
"guidanceScale": 3.5,
"noiseLevel": 0.35,
"seed": null
},
"createdAt": "2025-02-01T10:00:00.000Z",
"updatedAt": "2025-03-01T10:00:00.000Z"
}
],
"total": 1
}
Get location by ID
GET /api/locations/:id — Auth required
Response — 200 — single location object (same shape as list item)
Create location
POST /api/locations — Auth required, Permission: location:create
Request body
{
"projectId": "proj-uuid-001",
"name": "Underground Lab",
"description": "A dimly lit research facility carved into the bedrock."
}
| Field | Required | Notes |
|---|---|---|
projectId | yes | UUID of the parent project |
name | yes | Auto-translated to all locales |
description | no | Auto-translated if provided |
Response — 201 — created location object
Update location
PUT /api/locations/:id or PATCH /api/locations/:id — Auth required, Permission: location:edit
Request body (all fields optional)
{
"name": "Deep Underground Lab",
"description": "An even more secret facility."
}
Response — 200 — updated location object
Delete location
DELETE /api/locations/:id — Auth required, Permission: location:delete
Response — 204
Generate location image (AI)
POST /api/locations/:id/generate-image — Auth required, Rate limited, Permission: location:image:generate
Request body
{
"prompt": "Underground lab, dim lighting, stone walls, sci-fi equipment",
"model": "flux",
"width": 1920,
"height": 1088,
"steps": 28,
"guidanceScale": 3.5,
"noiseLevel": 0.35,
"seed": null
}
| Field | Required | Default |
|---|---|---|
prompt | yes | — |
model | no | "flux" |
width | no | 1920 |
height | no | 1088 |
steps | no | 28 |
guidanceScale | no | 3.5 |
noiseLevel | no | 0.35 |
seed | no | null |
Response — 200 — updated location object with imageUrl and generationParams
Upload location image (base64)
POST /api/locations/:id/upload-image — Auth required, Permission: location:image:upload
Request body
{
"imageBase64": "<base64-encoded-image-data>",
"mimeType": "image/png"
}
imageBase64 may include the data:image/png;base64, prefix — it will be stripped automatically.
Response — 200 — updated location object with imageUrl set
AI location recommendation
POST /api/locations/ai/recommend — Auth required, Rate limited
Given a scene's blocks and the project's existing locations, recommends the best matching or new locations.
Request body
{
"sceneBlocks": [
{ "type": "action", "text": "The hero enters a dark tunnel" },
{ "type": "dialog", "text": "It's so cold in here…" }
],
"existingLocations": [
{ "id": "loc-uuid-001", "name": "Underground Lab", "description": "Dimly lit facility" }
]
}
Response — 200
{
"recommendation": "Underground Lab",
"confidence": "high",
"reasoning": "The scene takes place in a cold, dark space — matches the underground lab description."
}
AI duplicate check
POST /api/locations/ai/check-duplicate — Auth required, Rate limited
Checks whether a proposed new location is semantically too similar to an existing one.
Request body
{
"name": "Dark Lab",
"description": "Underground research station with stone walls.",
"existingLocations": [
{ "id": "loc-uuid-001", "name": "Underground Lab", "description": "A dimly lit research facility carved into the bedrock." }
]
}
Response — 200
{
"isDuplicate": true,
"matchedLocation": { "id": "loc-uuid-001", "name": "Underground Lab" },
"confidence": "high",
"reasoning": "Both describe a dark underground research facility — effectively the same location."
}