Nellie API Documentation #
Generate professional novels, comics, manga, and more using the Nellie AI generation API.
API Version: v1
Base URL:https://api.nelliewriter.com/v1
Quick Links #
| Getting Started | Reference | Guides |
|---|---|---|
| Quick Start | Endpoint Reference | Webhooks |
| Authentication | Error Codes | SDK Reference |
| FAQ | Rate Limits | Examples |
Table of Contents #
- Authentication
- Endpoints
- Request Format
- Response Format
- Code Examples
- Rate Limits and Credits
- API Versioning
- Related Documentation
Authentication #
All API requests require an API key obtained from your Nellie account.
π See also: Authentication Guide for detailed security best practices and key management.
Getting Your API Key #
- Log into the Nellie app
- Navigate to Settings β API Management on mobile, or https://app.nelliewriter.com/api on web
- Click “Create Key” and save it securely
- Include the key in all requests via the
X-API-Keyheader - Treat the key like a password, only embed it in trusted backend services. If you must call the API directly from a browser or desktop app you control, keep the key in local secure storage and rotate it frequently.
Authentication Example #
curl -X POST https://api.nelliewriter.com/v1/book
-H "X-API-Key: nel_your_api_key_here"
-H "Content-Type: application/json"
-d '{...}'
Endpoints #
π Detailed endpoint documentation: See the endpoints/ folder for comprehensive guides on each endpoint.
1. Generate Book (Async) #
POST /v1/book — Full Reference
Starts an asynchronous book generation job. Returns immediately with a request ID that you can poll for status.
Headers:
X-API-Key: your_api_key
Content-Type: application/json
Request Body:
{
"prompt": "A thriller about a detective solving a mystery in Tokyo",
"style": "thriller",
"type": "novel",
"images": true,
"author": "Nellie",
"custom_tone": "Steady suspense, cinematic pacing",
"model": "2.0",
"output_format": "epub",
"webhook_url": "https://mysite.com/api/nellie-callback"
}
Response (202 Accepted):
{
"success": true,
"requestId": "uuid-of-request",
"status": "queued",
"statusUrl": "https://api.nelliewriter.com/v1/status/uuid-of-request",
"message": "Job queued successfully"
}
2. Check Status (Polling) #
GET /v1/status/{requestId} — Full Reference
Check the progress and results of a generation request.
Headers: None required (public endpoint)
Response (In Progress):
{
"requestId": "uuid",
"status": "processing",
"progress": 45,
"messages": [
"Processing..."
],
"createdAt": "2025-11-17T10:30:00Z",
"completedAt": null,
"creditsUsed": 0
}
Response (Completed):
{
"requestId": "uuid",
"status": "completed",
"progress": 100,
"messages": [
"Request received, starting job...",
"Generation completed successfully"
],
"createdAt": "2025-11-17T10:30:00Z",
"completedAt": "2025-11-17T10:45:00Z",
"creditsUsed": 250,
"resultUrl": "https://api.nelliewriter.com/v1/download/uuid"
}
Response (Failed):
{
"requestId": "uuid",
"status": "failed",
"progress": 34,
"messages": [
"Request received, starting job...",
"Error: Insufficient credits"
],
"createdAt": "2025-11-17T10:30:00Z",
"completedAt": "2025-11-17T10:32:00Z",
"creditsUsed": 0
}
3. Webhooks (Push Notifications) #
π See also: Webhooks Guide for complete setup instructions and framework examples.
If you provide a webhook_url in your request, Nellie will send a POST request to that URL when the job completes or fails.
Security (Recommended):
You can verify that webhooks are genuinely from Nellie by checking the X-Nellie-Signature header. You can find your unique Webhook Signing Secret in the Webhooks tab of the Developer Console.
Python Verification Example:
import hmac
import hashlib
import json
def verify_signature(request, secret):
# 1. Get header: "t=12345,v1=abcdef..."
header = request.headers.get("X-Nellie-Signature")
if not header: return False
# 2. Parse timestamp and signature
parts = dict(x.split('=') for x in header.split(','))
timestamp = parts.get('t')
signature = parts.get('v1')
# 3. Re-create the signed content string
# Note: payload must be the exact raw JSON string received
payload = request.get_data(as_text=True)
signed_content = f"{timestamp}.{payload}"
# 4. Calculate expected hash (HMAC-SHA256)
expected = hmac.new(
key=secret.encode(),
msg=signed_content.encode(),
digestmod=hashlib.sha256
).hexdigest()
# 5. Compare securely
return hmac.compare_digest(expected, signature)
Webhook Payload (Success):
{
"requestId": "uuid",
"status": "completed",
"completedAt": "2025-11-17T10:45:00Z",
"creditsUsed": 250,
"resultUrl": "https://api.nelliewriter.com/v1/download/uuid"
}
Webhook Payload (Failure):
{
"requestId": "uuid",
"status": "failed",
"completedAt": "2025-11-17T10:45:00Z",
"creditsUsed": 0,
"resultUrl": null,
"error": "Description of what went wrong"
}
4. Configuration #
GET /v1/configuration — Full Reference
Returns the valid options for styles, types, and output_formats so you can dynamically populate your UI.
Headers: None required (public endpoint)
Response:
{
"success": true,
"data": {
"styles": ["automatic", "action", "sci_fi", ...],
"types": ["automatic", "novel", "comic", ...],
"formats": ["txt", "pdf", "epub", "md", "html", "json"]
}
}
5. Models #
GET /v1/models — Full Reference
Returns the list of available AI models and their costs.
Headers: None required (public endpoint)
Response:
{
"success": true,
"data": [
{
"id": "2.0",
"name": "Nellie 2.0 (Standard)",
"description": "Balanced performance for fast standard books.",
"cost_per_book": 250
},
{
"id": "3.0",
"name": "Nellie 3.0 (Premium)",
"description": "Higher creativity and coherence for complex plots.",
"cost_per_book": 500
}
]
}
6. Usage #
GET /v1/usage — Full Reference
Returns the credit usage and recent requests for the authenticated API key.
Headers:
X-API-Key: your_api_key
Security note: Because this endpoint is secured purely by the API key (no session cookies), anyone who obtains your key can view these stats. Avoid embedding keys in public websites; use a backend proxy or environment variable injection when possible.
Response:
{
"success": true,
"totalRequests": 150,
"totalCreditsUsed": 12500,
"recentRequests": [
{
"requestId": "uuid...",
"status": "completed",
"createdAt": "2025-11-17T10:30:00Z",
"creditsUsed": 250
}
]
}
Request Format #
Required Fields #
None! All fields are optional.
Optional Fields #
| Field | Type | Description | Default | Options |
|---|---|---|---|---|
prompt |
string | Core idea, synopsis, or instructions for the book. If omitted, Nellie will generate a creative prompt for you! | Generated | Any string |
style |
string | Genre or narrative style | automatic |
automatic, action, horror, history, sci_fi, superhero, mystery, drama, romance, fantasy, adventure, crime, western, comedy, epic, thriller, mythology, folklore, fable, fairy_tale, legend, psychological, suspense, noir, paranormal, dystopian, post_apocalyptic, cyberpunk, alternate_history, gothic, tragedy, surrealism |
type |
string | Format of the output | automatic |
automatic, novel, comic, non_fiction, manga, textbook, childrens, self_help, short_story |
images |
boolean | Whether to generate companion images | false |
true, false |
author |
string | Display author credit | Nellie |
Any string |
custom_tone |
string | Extra tone/voice guidance to describe how the author writes or define a brand-specific voice | " |
Any string |
model |
string | Nellie model release to target | 2.0 |
2.0, 3.0 |
output_format |
string | Primary export format for the finished book | txt |
txt, pdf, epub, md, html, json |
webhook_url |
string | URL to call when generation finishes | null |
Any valid public HTTPS URL. Localhost, loopback IPs, and internal metadata services are not allowed. |
Response Format #
Status Values #
queued: Job has been queued but not startedprocessing: Generation in progresscompleted: Successfully generatedfailed: Generation failed (see error message)
Progress Values #
Progress is reported as a percentage (0-100).
Code Examples #
π See also: Examples & Recipes for more code patterns and use cases.
Python #
Option 1: Use the Official SDK (Recommended) — SDK Reference
pip install nellie-api
from nellie_api import Nellie
# Initialize client
client = Nellie(api_key="nel_your_api_key_here")
# Start generation
book = client.books.create(
prompt="A sci-fi story about Mars colonization",
style="sci_fi",
type="novel",
images=True,
author="Nellie",
custom_tone="Tight pacing, cinematic descriptions",
model="3.0",
output_format="epub"
)
print(f"Job started! Request ID: {book.request_id}")
# Poll for status
status = client.books.retrieve(book.request_id)
print(f"Status: {status.status} ({status.progress}%)")
if status.status == "completed":
print(f"Result URL: {status.result_url}")
Option 2: Raw Requests
import requests
import time
API_KEY = "nel_your_api_key_here"
BASE_URL = "https://api.nelliewriter.com/v1"
# Start generation
response = requests.post(
f"{BASE_URL}/book",
headers={
"X-API-Key": API_KEY,
"Content-Type": "application/json"
},
json={
"prompt": "A sci-fi story about Mars colonization",
"style": "sci_fi",
"type": "novel",
"images": True,
"author": "Nellie",
"custom_tone": "Tight pacing, cinematic descriptions",
"model": "3.0",
"output_format": "epub"
}
)
if response.status_code == 202:
data = response.json()
request_id = data["requestId"]
print(f"Job started! Request ID: {request_id}")
# Poll for completion
while True:
status_response = requests.get(f"{BASE_URL}/status/{request_id}")
status_data = status_response.json()
print(f"Progress: {status_data['progress']}% - {status_data['status']}")
if status_data['status'] in ['completed', 'failed']:
print(f"Final status: {status_data['status']}")
if status_data['status'] == 'completed':
print(f"Result URL: {status_data['resultUrl']}")
break
time.sleep(120) # Check every 2 minutes
else:
print(f"Error: {response.text}")
JavaScript/Node.js #
const axios = require('axios');
const API_KEY = 'nel_your_api_key_here';
const BASE_URL = 'https://api.nelliewriter.com/v1';
async function generateBook() {
try {
// Start generation
const response = await axios.post(
`${BASE_URL}/book`,
{
prompt: 'A mystery novel set in Victorian London',
style: 'mystery',
type: 'novel',
images: true,
author: 'Nellie',
custom_tone: 'Sherlockian wit with modern pacing',
model: '2.0',
output_format: 'pdf'
},
{
headers: {
'X-API-Key': API_KEY,
'Content-Type': 'application/json'
}
}
);
const { requestId } = response.data;
console.log(`Job started! Request ID: ${requestId}`);
// Poll for completion
const checkStatus = async () => {
const statusResponse = await axios.get(`${BASE_URL}/status/${requestId}`);
const { status, progress, resultUrl } = statusResponse.data;
console.log(`Progress: ${progress}% - ${status}`);
if (status === 'completed') {
console.log('Generation completed!');
console.log('Result URL:', resultUrl);
return true;
} else if (status === 'failed') {
console.error('Generation failed');
return true;
}
return false;
};
// Check every 120 seconds
const interval = setInterval(async () => {
const done = await checkStatus();
if (done) clearInterval(interval);
}, 120000);
} catch (error) {
console.error('Error:', error.response?.data || error.message);
}
}
generateBook();
cURL #
# Start generation
curl -X POST https://api.nelliewriter.com/v1/book
-H "X-API-Key: nel_your_api_key_here"
-H "Content-Type: application/json"
-d '{
"prompt": "A fantasy adventure in a magical forest",
"style": "fantasy",
"type": "novel",
"images": true,
"author": "Nellie",
"custom_tone": "Sophisticated and direct",
"model": "3.0",
"output_format": "epub"
}'
# Check status
curl https://api.nelliewriter.com/v1/status/YOUR_REQUEST_ID
Rate Limits and Credits #
π See also: Rate Limits & Credits for detailed explanations and code examples.
Rate Limiting #
- Minimum spacing: 1 request every 6 seconds per API key (β10/min). Requests that arrive sooner return
429 Too Many Requests. - Maximum requests per day: 15 per API key. The counter resets 24 hours after the first request of the day.
- Concurrency: Jobs run asynchronously once queued. The limits above only apply to enqueuing new work.
Rate limits are enforced transactionally in Firestore. Implement exponential backoff/retry handling for 429 responses.
Credit System #
Each generation consumes credits based on:
- Content length: More chapters = more credits
- Image generation: Enabled = additional credits
- Model selection: Premium models cost more
Typical credit costs:
- Book with Nellie 2.0: 250 credits
- Book with Nellie 3.0: 500 credits
Check your remaining credits via the Flutter app or by querying your usage endpoint.
Handling Insufficient Credits #
If you don’t have enough credits, the API will return:
{
"status": "failed",
"errorMessage": "Insufficient credits"
}
Purchase additional credits through the Nellie app.
Error Codes #
| Status Code | Meaning |
|---|---|
| 200 | Success |
| 202 | Accepted (async job started) |
| 400 | Bad Request (invalid parameters) |
| 401 | Unauthorized (invalid or missing API key) |
| 403 | Forbidden (key revoked or insufficient permissions) |
| 404 | Not Found (invalid request ID) |
| 429 | Too Many Requests (rate limit exceeded) |
| 500 | Internal Server Error |
Best Practices #
π See also: Best Practices Guide for comprehensive recommendations.
- Use Webhooks: Prefer providing a
webhook_urlover polling. It’s faster and more efficient. - Poll Responsibly: If you must poll, check status every 120 seconds.
- Store API Keys Securely: Never commit keys to source control, and prefer keeping them on the server side.
- Handle Errors Gracefully: Implement retry logic with exponential backoff.
- Monitor Usage: Track your credit consumption to avoid interruptions.
- Rotate Keys: Revoke and recreate keys if you suspect exposure or when rotating teammates.
Error Response Format #
π See also: Error Reference for complete error handling guidance.
All error responses follow a standardized format:
{
"success": false,
"error": "Human-readable error message",
"details": "Additional context (optional)",
"errorCode": "MACHINE_READABLE_CODE (optional)"
}
Error Codes #
| Error Code | HTTP Status | Description |
|---|---|---|
AUTH_REQUIRED |
401 | Authentication required (missing or invalid API key) |
AUTH_FAILED |
401 | API key verification failed |
FORBIDDEN |
403 | Permission denied (e.g., accessing another user’s resource) |
NOT_FOUND |
404 | Resource not found |
METHOD_NOT_ALLOWED |
405 | HTTP method not supported for this endpoint |
RATE_LIMIT_EXCEEDED |
429 | Too many requests |
INVALID_PARAMETER |
400 | Invalid request parameter |
INVALID_WEBHOOK_URL |
400 | Webhook URL failed validation (SSRF protection) |
MISSING_PARAMETER |
400 | Required parameter missing |
JOB_START_FAILED |
500/503 | Failed to start the generation job |
INTERNAL_ERROR |
500 | Internal server error |
Error Response Examples #
400 Bad Request (Invalid Parameter):
{
"success": false,
"error": "Field 'style' must be one of: action, adventure, automatic, ...",
"errorCode": "INVALID_PARAMETER"
}
401 Unauthorized:
{
"success": false,
"error": "Unauthorized",
"details": "Valid API key required",
"errorCode": "AUTH_REQUIRED"
}
429 Too Many Requests:
{
"success": false,
"error": "Rate limit exceeded: Please wait a few seconds between requests",
"errorCode": "RATE_LIMIT_EXCEEDED"
}
Daily Rate Limit Exceeded:
{
"success": false,
"error": "Daily rate limit exceeded (15 requests/day)",
"errorCode": "RATE_LIMIT_EXCEEDED"
}
Insufficient Credits (Job Status):
Note: Credit errors typically appear as a failed job status when polling.
{
"requestId": "uuid",
"status": "failed",
"errorMessage": "Insufficient credits",
"error": "Insufficient credits"
}
API Versioning #
π See also: Migration Guide for upgrading between versions.
The Nellie API uses URL path versioning to ensure backward compatibility.
Current Version #
All endpoints are available under the /v1 prefix:
POST /v1/book– Start generationGET /v1/status/{requestId}– Check statusGET /v1/configuration– Get optionsGET /v1/models– List modelsGET /v1/usage– View usage stats
Legacy Paths (Deprecated) #
For backward compatibility, the following unversioned paths still work but are deprecated:
POST /bookβ Use/v1/bookinsteadGET /status/{requestId}β Use/v1/status/{requestId}instead
β οΈ Deprecation Notice: Unversioned endpoints will be removed in a future release. Please migrate to
/v1/paths.
Version Lifecycle #
| Version | Status | Sunset Date |
|---|---|---|
| v1 | Current | — |
| (unversioned) | Deprecated | Q2 2026 |
Support #
For API support:
- Email: support@buzzleco.com
- Documentation: https://nelliewriter.com/docs
- Quick Start Guide — Get started in 5 minutes
- Authentication — API keys and security
- POST /v1/book — Create a book
- GET /v1/status — Check job progress
- GET /v1/configuration — Get valid options
- GET /v1/models — List available models
- GET /v1/usage — View usage statistics
- Webhooks — Real-time notifications
- SDK Reference — Python SDK documentation
- Integrations — Zapier, Make, AWS Lambda, etc.
- Examples & Recipes — Common code patterns
- Best Practices — Security, reliability, performance
- Error Reference — All error codes explained
- Rate Limits & Credits — Understanding limits
- Troubleshooting — Debug common issues
- FAQ — Frequently asked questions
- Changelog — Version history
- Migration Guide — Upgrading between versions
- Glossary — Terms and definitions