Integrations
Connect the Nellie API with popular platforms and services.
Overview
The Nellie API can be integrated with various platforms to automate book generation workflows. This guide covers common integration patterns and platform-specific instructions.
Zapier
Connect Nellie to 5,000+ apps without code.
Setting Up a Zap
- Create a new Zap in Zapier
- Choose your trigger (e.g., “New row in Google Sheets”)
- Add a Webhooks by Zapier action
- Action Event: POST
- URL:
https://api.nelliewriter.com/v1/book - Headers:
X-API-Key: nel_your_api_key Content-Type: application/json - Data (JSON):
{ "prompt": "{{trigger_data}}", "style": "automatic", "type": "novel", "output_format": "pdf", "webhook_url": "https://hooks.zapier.com/hooks/catch/YOUR_WEBHOOK" }
Receiving Results
- Create another Zap with trigger: Webhooks by Zapier → Catch Hook
- Copy the webhook URL and use it as your
webhook_url - Add actions to handle the completed book (save to Dropbox, email, etc.)
Example: Google Sheets → Nellie → Email
Trigger: New row in Google Sheets
↓
Action: Webhooks POST to Nellie API
↓
(Wait for webhook callback)
↓
Action: Send email with download link
Make (Integromat)
Visual automation with advanced logic.
HTTP Module Setup
- Add an HTTP > Make a request module
- Configure:
- URL:
https://api.nelliewriter.com/v1/book - Method: POST
- Headers:
X-API-Key: Your API keyContent-Type:application/json
- Body type: Raw
- Content type: JSON
- Request content:
{ "prompt": "{{1.prompt}}", "style": "{{1.style}}", "output_format": "pdf" }
- URL:
Webhook Receiver
- Add a Webhooks > Custom webhook module as a trigger
- Copy the webhook address
- Use it as your
webhook_urlin API requests
Example Scenario
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Google Form │───▶│ Nellie API │───▶│ Webhook │
│ submission │ │ POST /book │ │ receiver │
└─────────────────┘ └─────────────────┘ └────────┬────────┘
│
┌─────────────────┐ ┌───────────▼────────┐
│ Email result │◀───│ Download file │
│ to customer │ │ from resultUrl │
└─────────────────┘ └────────────────────┘
n8n
Self-hosted workflow automation.
HTTP Request Node
{
"nodes": [
{
"name": "Nellie API",
"type": "n8n-nodes-base.httpRequest",
"parameters": {
"method": "POST",
"url": "https://api.nelliewriter.com/v1/book",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"options": {},
"headerParametersUi": {
"parameter": [
{
"name": "X-API-Key",
"value": "={{ $credentials.apiKey }}"
}
]
},
"bodyParametersJson": {
"prompt": "={{ $json.prompt }}",
"style": "automatic",
"output_format": "pdf",
"webhook_url": "https://your-n8n-instance.com/webhook/nellie"
}
}
}
]
}
Webhook Trigger
- Add a Webhook node as trigger
- Set path to
/webhook/nellie - Use the full URL as your
webhook_url
AWS Lambda
Serverless book generation.
Lambda Function (Python)
import json
import os
import boto3
from nellie_api import Nellie
def handler(event, context):
client = Nellie(api_key=os.environ['NELLIE_API_KEY'])
# Parse input
body = json.loads(event.get('body', '{}'))
prompt = body.get('prompt', 'A thriller story')
# Start generation
book = client.books.create(
prompt=prompt,
style=body.get('style', 'automatic'),
output_format='pdf',
webhook_url=os.environ['WEBHOOK_URL']
)
return {
'statusCode': 202,
'body': json.dumps({
'requestId': book.request_id,
'message': 'Generation started'
})
}
Webhook Handler Lambda
import json
import boto3
from nellie_api import Webhook, WebhookSignatureError
s3 = boto3.client('s3')
ses = boto3.client('ses')
def handler(event, context):
# Verify signature
body = event.get('body', '')
sig_header = event['headers'].get('x-nellie-signature', '')
try:
book = Webhook.construct_event(
body, sig_header, os.environ['WEBHOOK_SECRET']
)
except WebhookSignatureError:
return {'statusCode': 400, 'body': 'Invalid signature'}
if book.is_successful():
# Download and store in S3
import requests
response = requests.get(book.result_url)
s3.put_object(
Bucket='my-books-bucket',
Key=f'books/{book.request_id}.pdf',
Body=response.content
)
# Send notification email
ses.send_email(
Source='noreply@example.com',
Destination={'ToAddresses': ['user@example.com']},
Message={
'Subject': {'Data': 'Your book is ready!'},
'Body': {'Text': {'Data': f'Download: {book.result_url}'}}
}
)
return {'statusCode': 200, 'body': 'OK'}
SAM Template
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Globals:
Function:
Runtime: python3.11
Environment:
Variables:
NELLIE_API_KEY: !Ref NellieApiKey
WEBHOOK_SECRET: !Ref WebhookSecret
Resources:
GenerateBookFunction:
Type: AWS::Serverless::Function
Properties:
Handler: generate.handler
Events:
Api:
Type: Api
Properties:
Path: /generate
Method: POST
WebhookFunction:
Type: AWS::Serverless::Function
Properties:
Handler: webhook.handler
Events:
Api:
Type: Api
Properties:
Path: /webhook/nellie
Method: POST
Policies:
- S3CrudPolicy:
BucketName: !Ref StoriesBucket
- SESCrudPolicy:
IdentityName: '*'
Google Cloud Functions
Function Code
import functions_framework
from flask import jsonify
from nellie_api import Nellie, Webhook, WebhookSignatureError
import os
@functions_framework.http
def generate_book(request):
"""Start a book generation."""
client = Nellie(api_key=os.environ['NELLIE_API_KEY'])
data = request.get_json(silent=True) or {}
book = client.books.create(
prompt=data.get('prompt', 'A random book'),
style=data.get('style', 'automatic'),
webhook_url=os.environ['WEBHOOK_URL']
)
return jsonify({
'requestId': book.request_id,
'status': book.status
}), 202
@functions_framework.http
def webhook_handler(request):
"""Handle Nellie webhook callbacks."""
try:
book = Webhook.construct_event(
request.data,
request.headers.get('X-Nellie-Signature'),
os.environ['WEBHOOK_SECRET']
)
except WebhookSignatureError:
return 'Invalid signature', 400
if book.is_successful():
# Store result in Firestore
from google.cloud import firestore
db = firestore.Client()
db.collection('books').document(book.request_id).set({
'status': 'completed',
'result_url': book.result_url,
'credits_used': book.credits_used
})
return 'OK', 200
Airtable
Use Airtable’s scripting extension with the API.
Script Example
// Airtable Script - Generate Book from Record
const API_KEY = 'nel_your_api_key';
const API_URL = 'https://api.nelliewriter.com/v1/book';
// Get selected record
let table = base.getTable('Stories');
let record = await input.recordAsync('Select a record', table);
if (record) {
let prompt = record.getCellValue('Prompt');
let style = record.getCellValue('Style') || 'automatic';
// Call Nellie API
let response = await remoteFetchAsync(API_URL, {
method: 'POST',
headers: {
'X-API-Key': API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
prompt: prompt,
style: style,
output_format: 'pdf'
})
});
let result = await response.json();
// Update record with request ID
await table.updateRecordAsync(record.id, {
'Request ID': result.requestId,
'Status': 'Processing'
});
output.text(`Started generation: ${result.requestId}`);
}
Slack Integration
Send book notifications to Slack.
Webhook Handler with Slack
import requests
from flask import Flask, request
from nellie_api import Webhook, WebhookSignatureError
import os
app = Flask(__name__)
SLACK_WEBHOOK_URL = os.environ['SLACK_WEBHOOK_URL']
WEBHOOK_SECRET = os.environ['NELLIE_WEBHOOK_SECRET']
@app.route('/webhooks/nellie', methods=['POST'])
def nellie_webhook():
try:
book = Webhook.construct_event(
request.data,
request.headers.get('X-Nellie-Signature'),
WEBHOOK_SECRET
)
except WebhookSignatureError:
return 'Invalid signature', 400
# Send to Slack
if book.is_successful():
slack_message = {
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": f"✅ *Book Generated!*\n`{book.request_id}`"
}
},
{
"type": "section",
"fields": [
{"type": "mrkdwn", "text": f"*Credits:* {book.credits_used}"},
{"type": "mrkdwn", "text": f"*Status:* Completed"}
]
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": {"type": "plain_text", "text": "Download"},
"url": book.result_url
}
]
}
]
}
else:
slack_message = {
"text": f"❌ Book generation failed: {book.error}"
}
requests.post(SLACK_WEBHOOK_URL, json=slack_message)
return 'OK', 200
Discord Integration
Post results to a Discord channel.
import requests
from nellie_api import Webhook, WebhookSignatureError
DISCORD_WEBHOOK_URL = os.environ['DISCORD_WEBHOOK_URL']
def send_to_discord(book):
if book.is_successful():
embed = {
"title": "📚 Book Generated!",
"color": 0x00ff00,
"fields": [
{"name": "Request ID", "value": f"`{book.request_id}`", "inline": True},
{"name": "Credits", "value": str(book.credits_used), "inline": True},
],
"description": f"[Download your book]({book.result_url})"
}
else:
embed = {
"title": "❌ Generation Failed",
"color": 0xff0000,
"description": book.error
}
requests.post(DISCORD_WEBHOOK_URL, json={"embeds": [embed]})
Notion Integration
Store generated stories in Notion.
from notion_client import Client
from nellie_api import Webhook
notion = Client(auth=os.environ['NOTION_TOKEN'])
DATABASE_ID = os.environ['NOTION_DATABASE_ID']
def save_to_notion(book):
notion.pages.create(
parent={"database_id": DATABASE_ID},
properties={
"Title": {"title": [{"text": {"content": f"Book {book.request_id[:8]}"}}]},
"Status": {"select": {"name": book.status.capitalize()}},
"Credits Used": {"number": book.credits_used},
"Request ID": {"rich_text": [{"text": {"content": book.request_id}}]},
"Download URL": {"url": book.result_url if book.is_successful() else None},
"Created": {"date": {"start": book.created_at}}
}
)
Best Practices
API Key Security
- Use environment variables: Never hardcode keys
- Rotate keys regularly: Especially if exposed
- Limit scope: Use different keys for different integrations
Webhook Reliability
- Always verify signatures: Prevent unauthorized access
- Respond quickly: Return 200 within 30 seconds
- Process asynchronously: Queue heavy work
- Handle retries: Be idempotent
Error Handling
- Implement retries: For transient failures
- Log everything: For debugging
- Alert on failures: Set up monitoring
Related Documentation
- Webhooks: Webhook setup details
- Authentication: API key management
- SDK Reference: Python SDK documentation
- Examples: More code samples