Version: 1.0.0
Base URL: https://api.serelo.com (Production) | http://localhost:8000 (Development)
Protocol: HTTPS (Production) | HTTP (Development)
- Authentication
- Projects
- Sources
- Posts
- Jobs
- Internal Links
- Billing
- Users
- Social Accounts
- Error Handling
- Rate Limiting
- Examples
All API requests (except registration and login) require authentication via JWT bearer tokens.
Create a new user account.
Endpoint: POST /api/v1/auth/register
Headers:
Content-Type: application/jsonRequest Body:
{
"email": "user@example.com",
"password": "SecurePassword123!",
"name": "John Doe"
}Validation:
- Email: Valid format, unique, max 255 characters
- Password: Min 8 characters, must contain uppercase, lowercase, number, special character
- Name: 1-100 characters
Response (201 Created):
{
"id": "507f1f77bcf86cd799439011",
"email": "user@example.com",
"name": "John Doe",
"subscription_tier": "free",
"created_at": "2025-10-25T10:00:00Z"
}Errors:
400 BAD_REQUEST- Validation error409 CONFLICT- Email already exists
Authenticate and receive access tokens.
Endpoint: POST /api/v1/auth/login
Headers:
Content-Type: application/jsonRequest Body:
{
"email": "user@example.com",
"password": "SecurePassword123!"
}Response (200 OK):
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "bearer",
"user": {
"id": "507f1f77bcf86cd799439011",
"email": "user@example.com",
"name": "John Doe",
"subscription_tier": "free"
}
}Token Expiration:
- Access Token: 24 hours
- Refresh Token: 30 days
Errors:
401 UNAUTHORIZED- Invalid credentials400 BAD_REQUEST- Missing fields
Get a new access token using refresh token.
Endpoint: POST /api/v1/auth/refresh
Headers:
Content-Type: application/jsonRequest Body:
{
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}Response (200 OK):
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "bearer"
}Errors:
401 UNAUTHORIZED- Invalid or expired refresh token
Retrieve authenticated user profile.
Endpoint: GET /api/v1/users/me
Headers:
Authorization: Bearer {access_token}Response (200 OK):
{
"id": "507f1f77bcf86cd799439011",
"email": "user@example.com",
"name": "John Doe",
"subscription_tier": "pro",
"quota": {
"posts_used": 32,
"posts_limit": 200,
"reset_date": "2025-11-01T00:00:00Z"
},
"created_at": "2025-10-01T10:00:00Z"
}Errors:
401 UNAUTHORIZED- Invalid or missing token
Projects organize your content generation work by topic, client, or campaign.
Create a new project.
Endpoint: POST /api/v1/projects
Headers:
Authorization: Bearer {access_token}
Content-Type: application/jsonRequest Body:
{
"name": "Tech Blog Q4 2025",
"description": "Blog posts for technology audience"
}Validation:
- Name: Required, 1-200 characters
- Description: Optional, max 1000 characters
Response (201 Created):
{
"id": "507f1f77bcf86cd799439012",
"user_id": "507f1f77bcf86cd799439011",
"name": "Tech Blog Q4 2025",
"description": "Blog posts for technology audience",
"created_at": "2025-10-25T10:30:00Z",
"updated_at": "2025-10-25T10:30:00Z"
}Errors:
400 BAD_REQUEST- Validation error (name too long, etc.)401 UNAUTHORIZED- Not authenticated
Get all projects for authenticated user.
Endpoint: GET /api/v1/projects
Headers:
Authorization: Bearer {access_token}Query Parameters:
limit(optional): Number of results (default: 100, max: 100)offset(optional): Pagination offset (default: 0)
Response (200 OK):
{
"projects": [
{
"id": "507f1f77bcf86cd799439012",
"user_id": "507f1f77bcf86cd799439011",
"name": "Tech Blog Q4 2025",
"description": "Blog posts for technology audience",
"created_at": "2025-10-25T10:30:00Z",
"updated_at": "2025-10-25T10:30:00Z"
}
],
"total": 1
}Notes:
- Results sorted by
created_atdescending (newest first) - Empty array if no projects
Retrieve single project by ID.
Endpoint: GET /api/v1/projects/{project_id}
Headers:
Authorization: Bearer {access_token}Response (200 OK):
{
"id": "507f1f77bcf86cd799439012",
"user_id": "507f1f77bcf86cd799439011",
"name": "Tech Blog Q4 2025",
"description": "Blog posts for technology audience",
"created_at": "2025-10-25T10:30:00Z",
"updated_at": "2025-10-25T10:30:00Z"
}Errors:
404 NOT_FOUND- Project not found or unauthorized401 UNAUTHORIZED- Not authenticated
Security: Returns 404 (not 403) for unauthorized access to prevent information leakage.
Update project name and/or description.
Endpoint: PUT /api/v1/projects/{project_id}
Headers:
Authorization: Bearer {access_token}
Content-Type: application/jsonRequest Body:
{
"name": "Tech Blog Q4 2025 - Updated",
"description": "Updated description"
}Response (200 OK):
{
"id": "507f1f77bcf86cd799439012",
"user_id": "507f1f77bcf86cd799439011",
"name": "Tech Blog Q4 2025 - Updated",
"description": "Updated description",
"created_at": "2025-10-25T10:30:00Z",
"updated_at": "2025-10-25T11:00:00Z"
}Errors:
404 NOT_FOUND- Project not found or unauthorized400 BAD_REQUEST- Validation error
Delete a project and all associated content.
Endpoint: DELETE /api/v1/projects/{project_id}
Headers:
Authorization: Bearer {access_token}Response (204 No Content)
Behavior:
- Deletes project permanently
- Deletes all sources in project
- Deletes all posts in project
- Deletes all jobs related to project
- Cannot be undone
Errors:
404 NOT_FOUND- Project not found or unauthorized
Source files provide reference material for content generation.
Upload a source file to a project.
Endpoint: POST /api/v1/sources/projects/{project_id}/sources
Headers:
Authorization: Bearer {access_token}
Content-Type: multipart/form-dataRequest Body (multipart/form-data):
file: [binary file data]
Supported File Types:
- DOCX (Microsoft Word)
- PDF (text-based, not scanned images)
- MD (Markdown)
- CSV (for bulk generation only)
File Size Limit: 20MB
Response (201 Created):
{
"id": "507f1f77bcf86cd799439013",
"project_id": "507f1f77bcf86cd799439012",
"user_id": "507f1f77bcf86cd799439011",
"filename": "research-paper.pdf",
"file_type": "pdf",
"file_size": 1048576,
"s3_key": "sources/507f.../abc123-research-paper.pdf",
"status": "uploaded",
"created_at": "2025-10-25T11:00:00Z"
}Status Values:
uploaded: File uploaded, queued for parsingparsing: Currently being parsedparsed: Successfully parsed, ready for usefailed: Parsing failed (see error_message)
Errors:
400 BAD_REQUEST- File too large or unsupported type404 NOT_FOUND- Project not found or unauthorized
Asynchronous Processing:
- File uploads are asynchronous
- After upload, status is
uploaded - Poll the source endpoint to check parsing status
- Parsing typically takes 5-30 seconds
Get all sources for a project.
Endpoint: GET /api/v1/sources/projects/{project_id}/sources
Headers:
Authorization: Bearer {access_token}Query Parameters:
status(optional): Filter by status (uploaded, parsing, parsed, failed)file_type(optional): Filter by type (pdf, docx, md, csv)limit(optional): Number of results (default: 100, max: 100)offset(optional): Pagination offset (default: 0)
Response (200 OK):
{
"sources": [
{
"id": "507f1f77bcf86cd799439013",
"project_id": "507f1f77bcf86cd799439012",
"user_id": "507f1f77bcf86cd799439011",
"filename": "research-paper.pdf",
"file_type": "pdf",
"file_size": 1048576,
"s3_key": "sources/507f.../abc123-research-paper.pdf",
"status": "parsed",
"parsed_text": "Full extracted text here...",
"error_message": null,
"created_at": "2025-10-25T11:00:00Z"
}
],
"total": 1
}Retrieve single source by ID.
Endpoint: GET /api/v1/sources/sources/{source_id}
Headers:
Authorization: Bearer {access_token}Response (200 OK):
{
"id": "507f1f77bcf86cd799439013",
"project_id": "507f1f77bcf86cd799439012",
"user_id": "507f1f77bcf86cd799439011",
"filename": "research-paper.pdf",
"file_type": "pdf",
"file_size": 1048576,
"s3_key": "sources/507f.../abc123-research-paper.pdf",
"status": "parsed",
"parsed_text": "Full extracted text content from the document...",
"error_message": null,
"created_at": "2025-10-25T11:00:00Z"
}Errors:
404 NOT_FOUND- Source not found or unauthorized
Update source filename.
Endpoint: PUT /api/v1/sources/sources/{source_id}
Headers:
Authorization: Bearer {access_token}
Content-Type: application/jsonRequest Body:
{
"filename": "updated-research-paper.pdf"
}Response (200 OK):
{
"id": "507f1f77bcf86cd799439013",
"filename": "updated-research-paper.pdf",
"file_type": "pdf",
"file_size": 1048576,
"status": "parsed",
"created_at": "2025-10-25T11:00:00Z"
}Delete a source file.
Endpoint: DELETE /api/v1/sources/sources/{source_id}
Headers:
Authorization: Bearer {access_token}Response (204 No Content)
Behavior:
- Deletes source record from database
- Deletes file from S3/MinIO storage
- Cannot be undone
Errors:
404 NOT_FOUND- Source not found or unauthorized
Generate and manage content.
Create a new content post (asynchronous).
Endpoint: POST /api/v1/posts/generate
Headers:
Authorization: Bearer {access_token}
Content-Type: application/jsonRequest Body:
{
"project_id": "507f1f77bcf86cd799439012",
"topic": "How to Build a REST API with FastAPI",
"voice": "professional",
"target_length": "medium",
"custom_instructions": "Include code examples and focus on async patterns",
"source_ids": [
"507f1f77bcf86cd799439013",
"507f1f77bcf86cd799439014"
],
"channel": "blog"
}Field Details:
topic (required):
- 1-200 characters
- What to write about
voice (required):
- FREE:
professional,casual,witty,technical - STARTER+:
gen_z,academic,corporate,storytelling,humorous,inspirational,conversational
target_length (optional):
short: 800-1,200 wordsmedium: 1,500-2,000 words (default)long: 2,500-3,500 words
custom_instructions (optional):
- Max 2,000 characters
- Specific requirements for generation
source_ids (optional):
- Array of source IDs to use as reference
- Recommended: 2-3 sources per post
channel (optional):
blog,social,email, etc.
Response (202 Accepted):
{
"job_id": "507f1f77bcf86cd799439015",
"status": "queued",
"message": "Content generation started. Poll /api/v1/jobs/{job_id} for status."
}Errors:
400 BAD_REQUEST- Validation error403 FORBIDDEN- Quota exceeded or voice not available on plan404 NOT_FOUND- Project or source not found
Quota Usage:
- Each generation consumes 1 post from monthly quota
- Check quota before generating:
GET /api/v1/users/me
Generation Time: Typically 45-90 seconds
Retrieve generated post.
Endpoint: GET /api/v1/posts/{post_id}
Headers:
Authorization: Bearer {access_token}Response (200 OK):
{
"id": "507f1f77bcf86cd799439016",
"project_id": "507f1f77bcf86cd799439012",
"user_id": "507f1f77bcf86cd799439011",
"topic": "How to Build a REST API with FastAPI",
"voice": "professional",
"content": {
"title": "How to Build a REST API with FastAPI: A Complete Guide",
"introduction": "FastAPI has emerged as...",
"sections": [
{
"heading": "What is FastAPI?",
"content": "FastAPI is a modern..."
}
],
"conclusion": "In this guide we covered...",
"meta_description": "Learn how to build production-ready REST APIs...",
"meta_keywords": ["FastAPI", "REST API", "Python"],
"markdown": "# How to Build a REST API with FastAPI...",
"word_count": 1847
},
"status": "completed",
"created_at": "2025-10-25T11:15:00Z"
}Errors:
404 NOT_FOUND- Post not found or unauthorized
Get all posts for a project.
Endpoint: GET /api/v1/posts/projects/{project_id}/posts
Headers:
Authorization: Bearer {access_token}Query Parameters:
status(optional): Filter by status (completed, failed, generating)limit(optional): Number of results (default: 50, max: 100)offset(optional): Pagination offset (default: 0)
Response (200 OK):
{
"posts": [
{
"id": "507f1f77bcf86cd799439016",
"project_id": "507f1f77bcf86cd799439012",
"topic": "How to Build a REST API with FastAPI",
"voice": "professional",
"status": "completed",
"word_count": 1847,
"created_at": "2025-10-25T11:15:00Z"
}
],
"total": 1
}Delete a generated post.
Endpoint: DELETE /api/v1/posts/{post_id}
Headers:
Authorization: Bearer {access_token}Response (204 No Content)
Note: Deleting a post does NOT refund quota.
Errors:
404 NOT_FOUND- Post not found or unauthorized
Track asynchronous operations (generation, parsing, etc.).
Poll job status to track progress.
Endpoint: GET /api/v1/jobs/{job_id}
Headers:
Authorization: Bearer {access_token}Response (200 OK):
{
"id": "507f1f77bcf86cd799439015",
"user_id": "507f1f77bcf86cd799439011",
"project_id": "507f1f77bcf86cd799439012",
"job_type": "content_generation",
"status": "completed",
"progress": 100,
"total_items": 1,
"result": {
"post_id": "507f1f77bcf86cd799439016"
},
"error_message": null,
"created_at": "2025-10-25T11:15:00Z",
"updated_at": "2025-10-25T11:16:30Z"
}Status Values:
queued: Job queued, not startedprocessing: Currently runningcompleted: Successfully finishedfailed: Error occurred (see error_message)
Job Types:
content_generation: Post generationdocument_parsing: Source file parsingbulk_generation: CSV bulk generation
Polling Recommendation:
- Poll every 2-5 seconds during generation
- Stop polling when status is
completedorfailed
Errors:
404 NOT_FOUND- Job not found or unauthorized
Manage internal linking opportunities for SEO.
Add a URL to link to from generated content.
Endpoint: POST /api/v1/links/projects/{project_id}/opportunities
Headers:
Authorization: Bearer {access_token}
Content-Type: application/jsonRequest Body:
{
"target_url": "https://yourblog.com/seo-guide",
"keywords": ["SEO", "search engine optimization", "search rankings"],
"anchor_text": "our complete SEO guide"
}Field Details:
target_url (required):
- Full URL including https://
- Where the link should point
keywords (required):
- Array of keywords that trigger this link
- Not case-sensitive
- Minimum 1 keyword
anchor_text (optional):
- Preferred link text
- If empty, AI generates contextual anchor
Response (201 Created):
{
"id": "507f1f77bcf86cd799439017",
"project_id": "507f1f77bcf86cd799439012",
"target_url": "https://yourblog.com/seo-guide",
"keywords": ["SEO", "search engine optimization", "search rankings"],
"anchor_text": "our complete SEO guide",
"created_at": "2025-10-25T12:00:00Z"
}Errors:
400 BAD_REQUEST- Invalid URL or missing keywords404 NOT_FOUND- Project not found
Get all link opportunities for a project.
Endpoint: GET /api/v1/links/projects/{project_id}/opportunities
Headers:
Authorization: Bearer {access_token}Response (200 OK):
{
"opportunities": [
{
"id": "507f1f77bcf86cd799439017",
"project_id": "507f1f77bcf86cd799439012",
"target_url": "https://yourblog.com/seo-guide",
"keywords": ["SEO", "search engine optimization"],
"anchor_text": "our complete SEO guide",
"created_at": "2025-10-25T12:00:00Z"
}
],
"total": 1
}Remove a link opportunity.
Endpoint: DELETE /api/v1/links/opportunities/{opportunity_id}
Headers:
Authorization: Bearer {access_token}Response (204 No Content)
Note: Removing opportunity doesn't affect already-generated posts.
Manage subscriptions and payments.
Retrieve current subscription details.
Endpoint: GET /api/v1/billing/subscription
Headers:
Authorization: Bearer {access_token}Response (200 OK):
{
"user_id": "507f1f77bcf86cd799439011",
"plan": "pro",
"status": "active",
"billing_cycle_start": "2025-10-01T00:00:00Z",
"billing_cycle_end": "2025-10-31T23:59:59Z",
"quota": {
"posts_limit": 200,
"posts_used": 32,
"bulk_limit": 500,
"concurrent_limit": 10
},
"paystack_subscription_id": "sub_abc123def456",
"next_billing_date": "2025-11-01T00:00:00Z"
}Plan Tiers:
free: R0/month, 10 postsstarter: R399/month, 50 postspro: R999/month, 200 postsbusiness: R1999/month, 500 postsenterprise: R3999/month, unlimited
Start a new paid subscription.
Endpoint: POST /api/v1/billing/subscriptions
Headers:
Authorization: Bearer {access_token}
Content-Type: application/jsonRequest Body:
{
"plan": "pro",
"payment_method": "card"
}Response (201 Created):
{
"subscription_id": "sub_abc123def456",
"plan": "pro",
"status": "active",
"authorization_url": "https://paystack.com/checkout/abc123",
"reference": "ref_abc123"
}Next Steps:
- Redirect user to
authorization_url - User completes payment on PayStack
- PayStack redirects back with payment status
- Verify payment with callback
Cancel active subscription.
Endpoint: POST /api/v1/billing/subscriptions/cancel
Headers:
Authorization: Bearer {access_token}Response (200 OK):
{
"subscription_id": "sub_abc123def456",
"status": "cancelled",
"end_date": "2025-10-31T23:59:59Z",
"message": "Subscription will end on 2025-10-31. You'll keep access until then."
}Behavior:
- Subscription continues until end of billing period
- No refunds for partial months
- Automatically downgrades to FREE plan after period ends
Manage user profile and settings.
Update user name or settings.
Endpoint: PATCH /api/v1/users/me
Headers:
Authorization: Bearer {access_token}
Content-Type: application/jsonRequest Body:
{
"name": "John Updated"
}Response (200 OK):
{
"id": "507f1f77bcf86cd799439011",
"email": "user@example.com",
"name": "John Updated",
"subscription_tier": "pro",
"updated_at": "2025-10-25T12:30:00Z"
}Update user password.
Endpoint: POST /api/v1/users/change-password
Headers:
Authorization: Bearer {access_token}
Content-Type: application/jsonRequest Body:
{
"current_password": "OldPassword123!",
"new_password": "NewPassword456!"
}Response (200 OK):
{
"message": "Password updated successfully"
}Errors:
400 BAD_REQUEST- Current password incorrect400 BAD_REQUEST- New password doesn't meet requirements
Connect and manage social media accounts for publishing.
Initiate Facebook OAuth flow.
Endpoint: GET /api/v1/social/facebook/connect
Headers:
Authorization: Bearer {access_token}Response (302 Redirect)
Redirects to Facebook OAuth authorization page.
OAuth Flow:
- Call this endpoint
- User redirected to Facebook
- User grants permissions
- Facebook redirects to callback URL
- Connection established
Get all connected social accounts.
Endpoint: GET /api/v1/social/accounts
Headers:
Authorization: Bearer {access_token}Response (200 OK):
{
"accounts": [
{
"id": "507f1f77bcf86cd799439018",
"user_id": "507f1f77bcf86cd799439011",
"platform": "facebook",
"platform_user_id": "fb_user_123",
"platform_username": "john.doe",
"access_token": "encrypted_token",
"token_expires_at": "2026-01-25T00:00:00Z",
"pages": [
{
"page_id": "page_456",
"page_name": "My Business Page",
"access_token": "encrypted_page_token"
}
],
"created_at": "2025-10-25T13:00:00Z"
}
],
"total": 1
}Remove social account connection.
Endpoint: DELETE /api/v1/social/accounts/{account_id}
Headers:
Authorization: Bearer {access_token}Response (204 No Content)
Note: Scheduled posts for this account will fail to publish.
All errors follow this format:
{
"detail": {
"code": "ERROR_CODE",
"message": "Human-readable error message"
}
}| Code | Meaning | Common Causes |
|---|---|---|
| 400 | Bad Request | Validation error, invalid input |
| 401 | Unauthorized | Missing or invalid auth token |
| 403 | Forbidden | Insufficient permissions, quota exceeded |
| 404 | Not Found | Resource doesn't exist or unauthorized |
| 409 | Conflict | Email already exists, duplicate resource |
| 422 | Unprocessable Entity | Request validation failed |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Server-side error |
| 503 | Service Unavailable | Maintenance or overload |
Authentication Errors:
INVALID_CREDENTIALS- Wrong email or passwordTOKEN_EXPIRED- Access token expired, use refresh tokenTOKEN_INVALID- Malformed or invalid tokenEMAIL_EXISTS- Email already registered
Validation Errors:
VALIDATION_ERROR- Input validation failedTOPIC_TOO_LONG- Topic exceeds 200 charactersINSTRUCTIONS_TOO_LONG- Custom instructions exceed 2000 charactersFILE_TOO_LARGE- File exceeds 20MB limitUNSUPPORTED_FILE_TYPE- File type not supported
Authorization Errors:
QUOTA_EXCEEDED- Monthly post limit reachedFEATURE_NOT_AVAILABLE- Feature not available on current planPROJECT_NOT_FOUND- Project doesn't exist or unauthorizedVOICE_NOT_AVAILABLE- Voice preset not on current plan
Business Logic Errors:
ALREADY_GENERATING- Generation in progress for same topicPARSING_FAILED- Source file parsing failedINVALID_SOURCE- Source not ready (still parsing)
Authentication Endpoints:
- Login: 5 requests per minute per IP
- Register: 3 requests per minute per IP
- Refresh: 10 requests per minute per user
Content Generation:
- Generate: Concurrent limit based on plan
- FREE: 1 concurrent
- STARTER: 3 concurrent
- PRO: 10 concurrent
- BUSINESS: 20 concurrent
API Endpoints (General):
- 100 requests per minute per user
- 1000 requests per hour per user
Responses include rate limit information:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1635174000Status: 429 Too Many Requests
{
"detail": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Too many requests. Try again in 30 seconds.",
"retry_after": 30
}
}Step 1: Create Project
curl -X POST https://api.serelo.com/api/v1/projects \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"name": "Tech Blog",
"description": "Technical tutorials and guides"
}'Step 2: Upload Source File
curl -X POST https://api.serelo.com/api/v1/sources/projects/${PROJECT_ID}/sources \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-F "file=@research-paper.pdf"Step 3: Wait for Parsing (Poll Source)
curl -X GET https://api.serelo.com/api/v1/sources/sources/${SOURCE_ID} \
-H "Authorization: Bearer ${ACCESS_TOKEN}"Step 4: Generate Post
curl -X POST https://api.serelo.com/api/v1/posts/generate \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"project_id": "'${PROJECT_ID}'",
"topic": "How to Build a REST API with FastAPI",
"voice": "technical",
"target_length": "medium",
"source_ids": ["'${SOURCE_ID}'"]
}'Step 5: Poll Job Status
curl -X GET https://api.serelo.com/api/v1/jobs/${JOB_ID} \
-H "Authorization: Bearer ${ACCESS_TOKEN}"Step 6: Retrieve Generated Post
curl -X GET https://api.serelo.com/api/v1/posts/${POST_ID} \
-H "Authorization: Bearer ${ACCESS_TOKEN}"Step 1: Prepare CSV
topic,voice,custom_instructions
"SEO Best Practices for 2025","professional","Include examples"
"Content Marketing Strategy Guide","professional","Focus on B2B"
"Social Media Optimization Tips","casual","Keep it practical"Step 2: Upload CSV as Source
curl -X POST https://api.serelo.com/api/v1/sources/projects/${PROJECT_ID}/sources \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-F "file=@topics.csv"Step 3: Initiate Bulk Generation
curl -X POST https://api.serelo.com/api/v1/posts/bulk-generate \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"project_id": "'${PROJECT_ID}'",
"csv_source_id": "'${CSV_SOURCE_ID}'"
}'Step 4: Monitor Progress
curl -X GET https://api.serelo.com/api/v1/jobs/${BULK_JOB_ID} \
-H "Authorization: Bearer ${ACCESS_TOKEN}"Coming Soon:
- Python SDK
- Node.js SDK
- PHP SDK
Current: Use any HTTP client with the endpoints documented above.
import requests
BASE_URL = "https://api.serelo.com"
ACCESS_TOKEN = "your_access_token"
headers = {
"Authorization": f"Bearer {ACCESS_TOKEN}",
"Content-Type": "application/json"
}
# Create project
response = requests.post(
f"{BASE_URL}/api/v1/projects",
headers=headers,
json={
"name": "My Project",
"description": "Project description"
}
)
project = response.json()
print(f"Created project: {project['id']}")
# Generate post
response = requests.post(
f"{BASE_URL}/api/v1/posts/generate",
headers=headers,
json={
"project_id": project['id'],
"topic": "How to Use the Serelo API",
"voice": "technical"
}
)
job = response.json()
print(f"Generation started: {job['job_id']}")Technical Support: support@artemisinnovations.co.za Documentation: https://docs.serelo.com Status Page: https://status.serelo.com (coming soon)
Last Updated: October 25, 2025 API Version: 1.0.0