Skip to main content

POST /api/email/generate

Enqueue a background task to generate a personalized email using the multi-step AI pipeline. This endpoint returns immediately with a task ID for status polling.
Email generation typically takes 10-30 seconds depending on web scraping and AI processing time.

Authentication

Requires valid JWT token from Supabase Auth in the Authorization header.

Request Body

email_template
string
required
Email template with placeholders for personalization. Must be 10-5000 characters and contain placeholder syntax (e.g., {{name}}, {{research}}).
recipient_name
string
required
Full name of the email recipient (e.g., “Dr. Jane Smith”). Must be 2-255 characters.
recipient_interest
string
required
Research area or interest for personalization (e.g., “machine learning for healthcare”). Must be 2-500 characters.

Request Example

curl -X POST https://scribeapi.manitmishra.com/api/email/generate \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "email_template": "Hey {{name}}, I loved your work on {{research}}! I have experience in...",
    "recipient_name": "Dr. Jane Smith",
    "recipient_interest": "machine learning for medical diagnosis"
  }'

Response

task_id
string
Celery task ID for polling generation status via GET /api/email/status/{task_id}

Response Example

{
  "task_id": "abc-123-def-456-ghi-789"
}

Status Code

202 Accepted - Task has been queued successfully

Error Responses

401 Unauthorized
Invalid or missing JWT token
422 Validation Error
Invalid request parameters (template too short/long, missing fields, etc.)
{
  "detail": [
    {
      "loc": ["body", "email_template"],
      "msg": "ensure this value has at least 10 characters",
      "type": "value_error.any_str.min_length"
    }
  ]
}

GET /api/email/status/

Check the status of an asynchronous email generation task. Poll this endpoint every 2 seconds until status is SUCCESS or FAILURE.
Task results expire after 1 hour in Redis. After expiration, the task status will show as PENDING.

Authentication

Requires valid JWT token from Supabase Auth in the Authorization header.

Path Parameters

task_id
string
required
The Celery task ID returned from POST /api/email/generate

Request Example

curl -X GET https://scribeapi.manitmishra.com/api/email/status/abc-123-def-456 \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

Response

task_id
string
The task ID being queried
status
string
Current task state: PENDING, STARTED, SUCCESS, or FAILURE
result
object | null
Task result data. Contains different information based on status:
  • SUCCESS: Contains email_id and generation metadata
  • STARTED: Contains current_step and progress information
  • PENDING/FAILURE: null
error
string | object | null
Error details if status is FAILURE. Can be a string or structured error object with message, type, and failed_step.

Response Examples

Task Queued (PENDING)
{
  "task_id": "abc-123-def-456",
  "status": "PENDING",
  "result": null,
  "error": null
}
Task Running (STARTED)
{
  "task_id": "abc-123-def-456",
  "status": "STARTED",
  "result": {
    "current_step": "web_scraper",
    "step_status": "Searching for professor information...",
    "step_timings": {
      "template_parser": 1.2
    }
  },
  "error": null
}
Task Completed (SUCCESS)
{
  "task_id": "abc-123-def-456",
  "status": "SUCCESS",
  "result": {
    "email_id": "550e8400-e29b-41d4-a716-446655440000",
    "generation_time": 12.4,
    "step_timings": {
      "template_parser": 1.2,
      "web_scraper": 6.8,
      "arxiv_helper": 1.1,
      "email_composer": 3.3
    }
  },
  "error": null
}
Task Failed (FAILURE)
{
  "task_id": "abc-123-def-456",
  "status": "FAILURE",
  "result": null,
  "error": {
    "message": "Connection timeout while scraping web content",
    "type": "TimeoutError",
    "failed_step": "web_scraper"
  }
}

Error Responses

401 Unauthorized
Invalid or missing JWT token
404 Not Found
Task ID not found or result expired (>1 hour old)

GET /api/email/

Retrieve a generated email by its ID. Only the email owner can access their emails.

Authentication

Requires valid JWT token from Supabase Auth in the Authorization header.

Path Parameters

email_id
string (UUID)
required
The unique identifier of the email to retrieve

Request Example

curl -X GET https://scribeapi.manitmishra.com/api/email/550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

Response

id
string (UUID)
Email’s unique identifier
user_id
string (UUID)
ID of the user who generated this email
recipient_name
string
Name of the email recipient
recipient_interest
string
Research interest used for personalization
email_message
string
The generated email content (full text)
template_type
string
Template type detected by the AI: research, book, or general
metadata
object
Generation metadata including:
  • papers_used: Array of academic papers referenced (for research emails)
  • sources: Array of URLs scraped
  • generation_time: Total time in seconds
  • step_timings: Time spent in each pipeline step
is_confident
boolean
Whether the AI had sufficient context for high-quality personalization
displayed
boolean
Whether this email is visible in the user’s history (false = discarded)
created_at
string (ISO 8601)
Timestamp when email was generated

Response Example

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "user_id": "660e8400-e29b-41d4-a716-446655440001",
  "recipient_name": "Dr. Jane Smith",
  "recipient_interest": "machine learning for medical diagnosis",
  "email_message": "Hey Dr. Smith,\n\nI'm fascinated by your recent work on neural networks for medical imaging. Your paper 'Deep Learning for Radiology' really inspired me...\n\nBest regards",
  "template_type": "research",
  "metadata": {
    "papers_used": [
      "Deep Learning for Radiology: A Systematic Review (2023)",
      "Neural Networks in Medical Diagnosis (2024)"
    ],
    "sources": [
      "https://university.edu/faculty/jane-smith",
      "https://scholar.google.com/citations?user=abc123"
    ],
    "generation_time": 12.4,
    "step_timings": {
      "template_parser": 1.2,
      "web_scraper": 6.8,
      "arxiv_helper": 1.1,
      "email_composer": 3.3
    }
  },
  "is_confident": true,
  "displayed": true,
  "created_at": "2025-01-24T10:35:42Z"
}

Error Responses

400 Bad Request
Invalid email ID format (not a valid UUID)
{
  "detail": "Invalid email ID format: badly formed hexadecimal UUID string"
}
401 Unauthorized
Invalid or missing JWT token
404 Not Found
Email not found or user doesn’t have permission to access it
{
  "detail": "Email not found or you don't have permission to access it"
}

GET /api/email/

Get the user’s email generation history, paginated and sorted by newest first.

Authentication

Requires valid JWT token from Supabase Auth in the Authorization header.

Query Parameters

limit
integer
default:"20"
Maximum number of emails to return (1-100)
offset
integer
default:"0"
Number of emails to skip for pagination
include_discarded
boolean
default:"false"
Include emails marked as discarded (displayed=false) in results

Request Example

# Get first 20 emails (default)
curl -X GET https://scribeapi.manitmishra.com/api/email/ \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

# Get next 20 emails with pagination
curl -X GET "https://scribeapi.manitmishra.com/api/email/?limit=20&offset=20" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

# Include discarded emails
curl -X GET "https://scribeapi.manitmishra.com/api/email/?include_discarded=true" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

Response

Returns an array of EmailResponse objects (same schema as GET /api/email/{email_id}).

Response Example

[
  {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "user_id": "660e8400-e29b-41d4-a716-446655440001",
    "recipient_name": "Dr. Jane Smith",
    "recipient_interest": "machine learning",
    "email_message": "Hey Dr. Smith...",
    "template_type": "research",
    "metadata": { /* ... */ },
    "is_confident": true,
    "displayed": true,
    "created_at": "2025-01-24T12:00:00Z"
  },
  {
    "id": "550e8400-e29b-41d4-a716-446655440001",
    "user_id": "660e8400-e29b-41d4-a716-446655440001",
    "recipient_name": "Prof. John Doe",
    "recipient_interest": "computer vision",
    "email_message": "Dear Prof. Doe...",
    "template_type": "general",
    "metadata": { /* ... */ },
    "is_confident": false,
    "displayed": true,
    "created_at": "2025-01-24T11:30:00Z"
  }
]

Error Responses

401 Unauthorized
Invalid or missing JWT token
422 Validation Error
Invalid query parameters (e.g., limit > 100)

PATCH /api/email/

Update email properties. Currently supports updating the displayed field to hide/show emails in history (soft delete).

Authentication

Requires valid JWT token from Supabase Auth in the Authorization header.

Path Parameters

email_id
string (UUID)
required
The unique identifier of the email to update

Request Body

displayed
boolean
required
Whether to display the email in history:
  • true: Show in email history
  • false: Hide from email history (soft delete)

Request Example

# Discard an email (soft delete)
curl -X PATCH https://scribeapi.manitmishra.com/api/email/550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "displayed": false
  }'

# Restore a discarded email
curl -X PATCH https://scribeapi.manitmishra.com/api/email/550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "displayed": true
  }'

Response

Returns the updated EmailResponse object.

Response Example

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "user_id": "660e8400-e29b-41d4-a716-446655440001",
  "recipient_name": "Dr. Jane Smith",
  "recipient_interest": "machine learning",
  "email_message": "Hey Dr. Smith...",
  "template_type": "research",
  "metadata": { /* ... */ },
  "is_confident": true,
  "displayed": false,
  "created_at": "2025-01-24T10:35:42Z"
}

Error Responses

400 Bad Request
Invalid email ID format (not a valid UUID)
401 Unauthorized
Invalid or missing JWT token
404 Not Found
Email not found or user doesn’t have permission to access it
422 Validation Error
Invalid request body (missing or invalid displayed field)

Build docs developers (and LLMs) love