Skip to content

API Design

Subscribe Flow follows RESTful API design principles with OpenAPI 3.1 documentation.

Base URL

Text Only
https://api.subscribeflow.net/v1

Local: http://localhost:8000/api/v1

Authentication

All API requests (except Health Check) require authentication:

Bash
curl -H "Authorization: Bearer sf_live_xxxxx" \
  https://api.subscribeflow.net/v1/subscribers
Bash
curl -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
  https://api.subscribeflow.net/v1/subscribers

Request/Response Format

Content-Type

  • Request: application/json
  • Response: application/json

Response Envelope

All responses follow a consistent format:

JSON
1
2
3
4
5
6
{
  "data": {
    "id": "uuid",
    "email": "user@example.com"
  }
}
JSON
{
  "data": [
    {"id": "uuid1", "email": "user1@example.com"},
    {"id": "uuid2", "email": "user2@example.com"}
  ],
  "meta": {
    "total": 100,
    "page": 1,
    "per_page": 20
  }
}
JSON
{
  "error": {
    "code": "validation_error",
    "message": "Invalid email format",
    "details": [
      {
        "field": "email",
        "message": "Must be a valid email address"
      }
    ]
  }
}

Endpoints

Subscribers

Method Endpoint Description
GET /subscribers List all subscribers
POST /subscribers Create a new subscriber
GET /subscribers/:id Retrieve a subscriber
PATCH /subscribers/:id Update a subscriber
DELETE /subscribers/:id Delete a subscriber
GET /subscribers/:id/tags Get tags of a subscriber
PATCH /subscribers/:id/tags Update tags

Tags

Method Endpoint Description
GET /tags List all tags
POST /tags Create a new tag
GET /tags/:id Retrieve a tag
PATCH /tags/:id Update a tag
DELETE /tags/:id Delete a tag

Preference Center

Method Endpoint Description
GET /preferences/:token Preferences via magic link
PATCH /preferences/:token Update preferences

Webhooks

Method Endpoint Description
GET /webhooks List webhooks
POST /webhooks Create a webhook
DELETE /webhooks/:id Delete a webhook

Pagination

List endpoints support pagination:

Bash
GET /api/v1/subscribers?page=2&per_page=50

Response:

JSON
1
2
3
4
5
6
7
8
9
{
  "data": [...],
  "meta": {
    "total": 1000,
    "page": 2,
    "per_page": 50,
    "total_pages": 20
  }
}

Filtering

Filters are passed as query parameters:

Bash
1
2
3
4
5
6
7
8
# Filter subscribers by status
GET /api/v1/subscribers?status=active

# Filter tags by category
GET /api/v1/tags?category=newsletter

# Combined filters
GET /api/v1/subscribers?status=active&tag=product-updates

Sorting

Bash
1
2
3
4
5
6
7
8
# Ascending (default)
GET /api/v1/subscribers?sort=created_at

# Descending
GET /api/v1/subscribers?sort=-created_at

# Multiple fields
GET /api/v1/subscribers?sort=-created_at,email

Rate Limiting

Plan Rate Limit
Free 100 requests/minute
Pro 1000 requests/minute
Enterprise Custom

Rate Limit Headers:

Text Only
1
2
3
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1609459200

Error Codes

HTTP Status Error Code Description
400 validation_error Invalid request data
401 unauthorized Missing/invalid authentication
403 forbidden Insufficient permissions
404 not_found Resource not found
409 conflict Resource already exists
429 rate_limited Rate limit exceeded
500 internal_error Server error

Idempotency

POST requests can be made idempotent:

Bash
1
2
3
curl -X POST /api/v1/subscribers \
  -H "Idempotency-Key: unique-request-id" \
  -d '{"email": "user@example.com"}'

Versioning

The API version is included in the URL path:

Text Only
/api/v1/subscribers  # Version 1
/api/v2/subscribers  # Version 2 (future)

Version Policy

  • Breaking changes only in major versions
  • Deprecation warnings 6 months in advance
  • Sunset header for deprecated endpoints

OpenAPI Documentation

  • Swagger UI: /docs
  • ReDoc: /redoc
  • OpenAPI JSON: /openapi.json