API Referencev1

Platform API Reference

Complete reference for the MSJ Oratio platform REST API — every endpoint, request/response schema, parameter, and error code from the actual implementations.

Quick Start
1

Create an account

Sign up free to get started

2

Get your API key

Generate a key in API Keys

3

Make your first call

POST to /api/tts with text & voiceId

Base URL
https://msjoratio.com/api

All platform API requests use this base URL. The standalone Voice API uses https://api.msjoratio.com — see Voice API docs.

Authentication

Most endpoints require authentication. Include your API key using either header format:

Authorization: Bearer orat_YOUR_API_KEY
X-API-Key: orat_YOUR_API_KEY
API keys are prefixed with orat_. Create keys in API Keys.
Rate Limits & Credits
PlanCharacters / monthMax per requestVoice qualitiesAPI rate
Free1,000500Standard only10 req/min
Pro ($29/mo)500,0005,000Standard, Premium, Ultra100 req/min
Credits auto-reset on the first request of each new calendar month. When credits are exhausted, POST /api/tts returns 429 with remaining balance details.
Code Examples
cURL
curl -X POST https://msjoratio.com/api/tts \
  -H "Authorization: Bearer orat_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Hello from MSJ Oratio!",
    "voiceId": "aria"
  }'
JavaScript / TypeScript
const response = await fetch("https://msjoratio.com/api/tts", {
  method: "POST",
  headers: {
    "Authorization": "Bearer orat_YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    text: "Hello from MSJ Oratio!",
    voiceId: "aria",
  }),
});

const { generation, credits } = await response.json();
console.log(generation.audioUrl);     // "/api/tts/audio/clx1abc..."
console.log(credits.remaining);       // 499870
Python
import requests

response = requests.post(
    "https://msjoratio.com/api/tts",
    headers={"Authorization": "Bearer orat_YOUR_API_KEY"},
    json={
        "text": "Hello from MSJ Oratio!",
        "voiceId": "aria",
    },
)

data = response.json()
print(data["generation"]["audioUrl"])
print(data["credits"]["remaining"])

Speech Generation

POST/api/tts Auth Required
Generate Speech

Convert text to speech using a selected voice. Deducts credits based on character count. Audio is generated and stored server-side.

Parameters

NameTypeRequiredDescription
textstringRequiredText to convert to speech. Max 500 chars (Free) or 5,000 chars (Pro).
voiceIdstringRequiredVoice identifier from the catalog (e.g. "aria", "marcus", "luna").
stylestringOptionalOverride the voice default style. Falls back to the voice built-in style.

Request Body

{
  "text": "Hello, welcome to MSJ Oratio.",
  "voiceId": "aria",
  "style": "Warm & Expressive"
}

Response

{
  "generation": {
    "id": "clx1abc...",
    "text": "Hello, welcome to MSJ Oratio.",
    "voiceName": "Aria",
    "style": "Warm & Expressive",
    "characterCount": 30,
    "duration": 2.0,
    "quality": 96.3,
    "status": "completed",
    "audioUrl": "/api/tts/audio/clx1abc...",
    "createdAt": "2026-03-18T10:00:00Z"
  },
  "credits": {
    "used": 130,
    "limit": 500000,
    "remaining": 499870
  }
}

Error Codes

400Invalid input — missing text, empty string, or invalid voiceId
401Unauthorized — missing or invalid session
403Voice quality tier not available on current plan (e.g. "Ultra" requires Pro)
429Credit limit exceeded — insufficient characters remaining this month
GET/api/ttsPublic
List Voices

Returns the platform voice catalog with metadata. No authentication required. Returns the 5 built-in platform voices with quality tier, accent, gender, and category.

Response

{
  "voices": [
    {
      "id": "aria",
      "name": "Aria",
      "accent": "American English",
      "gender": "Female",
      "quality": "Ultra",
      "style": "Warm & Expressive",
      "category": "Professional",
      "languages": ["English"]
    },
    {
      "id": "marcus",
      "name": "Marcus",
      "accent": "British English",
      "gender": "Male",
      "quality": "Premium",
      "style": "Authoritative",
      "category": "Professional",
      "languages": ["English"]
    },
    {
      "id": "luna",
      "name": "Luna",
      "accent": "Australian English",
      "gender": "Female",
      "quality": "Premium",
      "style": "Calm",
      "category": "Creative",
      "languages": ["English"]
    },
    {
      "id": "kai",
      "name": "Kai",
      "accent": "American English",
      "gender": "Non-binary",
      "quality": "Premium",
      "style": "Dynamic",
      "category": "Creative",
      "languages": ["English"]
    },
    {
      "id": "elena",
      "name": "Elena",
      "accent": "Spanish (ES)",
      "gender": "Female",
      "quality": "Premium",
      "style": "Passionate",
      "category": "Multilingual",
      "languages": ["Spanish", "English"]
    }
  ]
}

Generations & Dashboard

GET/api/generations Auth Required
List Generations

Retrieve all past voice generations for the authenticated user, ordered by most recent first.

Response

{
  "generations": [
    {
      "id": "clx1abc...",
      "text": "Hello world",
      "voiceName": "Aria",
      "style": "Warm & Expressive",
      "duration": 1.3,
      "status": "completed",
      "quality": 94.2,
      "createdAt": "2026-03-18T10:00:00Z"
    }
  ]
}

Error Codes

401Unauthorized — missing or invalid session/API key
DELETE/api/generations/:id Auth Required
Delete Generation

Permanently delete a specific generation by ID. Only the owner can delete their own generations.

Parameters

NameTypeRequiredDescription
idstringRequiredGeneration ID (path parameter)

Response

{ "success": true }

Error Codes

401Unauthorized
404Generation not found or not owned by the authenticated user
GET/api/dashboard Auth Required
Dashboard Stats

Get real-time credit usage, subscription status, aggregate stats, weekly activity chart data, and the 5 most recent generations.

Response

{
  "user": { "name": "John", "email": "john@example.com" },
  "credits": {
    "used": 1250,
    "limit": 500000,
    "remaining": 498750,
    "resetAt": "2026-03-01T00:00:00Z",
    "percentUsed": 0
  },
  "subscription": {
    "plan": "pro",
    "isActive": true,
    "periodEnd": "2026-04-18T00:00:00Z"
  },
  "stats": {
    "totalGenerations": 47,
    "thisMonthGenerations": 12,
    "totalMinutes": 23.4,
    "avgQuality": 93.7
  },
  "weeklyUsage": [
    { "day": "Mon", "count": 3, "characters": 450 }
  ],
  "recentGenerations": [...]
}

Error Codes

401Unauthorized

API Keys

GET/api/keys Auth Required
List API Keys

Retrieve all API keys for the authenticated user, ordered by most recently created.

Response

{
  "keys": [
    {
      "id": "clx2def...",
      "name": "Production",
      "key": "orat_a1b2c3d4e5...",
      "createdAt": "2026-03-18T10:00:00Z"
    }
  ]
}

Error Codes

401Unauthorized
POST/api/keys Auth Required
Create API Key

Generate a new API key with a descriptive name. Keys are prefixed with orat_ and are 48 hex characters long.

Parameters

NameTypeRequiredDescription
namestringRequiredDescriptive label for the key (max 100 characters)

Request Body

{
  "name": "Production Backend"
}

Response

{
  "key": {
    "id": "clx2def...",
    "name": "Production Backend",
    "key": "orat_a1b2c3d4e5f6...",
    "createdAt": "2026-03-18T10:00:00Z"
  }
}

Error Codes

400Name is required or not a valid string
401Unauthorized
DELETE/api/keys/:id Auth Required
Delete API Key

Permanently revoke and delete an API key. Only the key owner can delete.

Parameters

NameTypeRequiredDescription
idstringRequiredAPI key ID (path parameter)

Response

{ "deleted": true }

Error Codes

401Unauthorized
404Key not found or not owned by user

Billing & Subscription

POST/api/stripe/checkout Auth Required
Create Checkout Session

Initiate a Stripe checkout session for the Pro plan. If the user already has an active subscription, returns a billing portal URL instead.

Response

{ "url": "https://checkout.stripe.com/c/pay_..." }

Error Codes

401Unauthorized
404User not found
POST/api/stripe/portal Auth Required
Billing Portal

Create a Stripe billing portal session for managing subscription, payment methods, and invoices.

Response

{ "url": "https://billing.stripe.com/p/session/..." }

Error Codes

400No billing account found (user has no stripeCustomerId)
401Unauthorized

Authentication

POST/api/registerPublic
Register User

Create a new user account with email and password. Password is hashed with bcrypt (12 rounds). Returns a clean user object without the password hash.

Parameters

NameTypeRequiredDescription
namestringOptionalUser display name
emailstringRequiredUnique email address
passwordstringRequiredPassword (minimum 8 characters)

Request Body

{
  "name": "John Doe",
  "email": "john@example.com",
  "password": "secureP@ss123"
}

Response

{
  "user": {
    "id": "clx3ghi...",
    "email": "john@example.com",
    "name": "John Doe"
  }
}

Error Codes

400Missing email/password or password shorter than 8 characters
409An account with this email already exists
Voice Catalog

12 built-in voices across 3 quality tiers. Free plan has access to Standard quality only; Pro unlocks Premium and Ultra.

IDNameQualityAccentCategory
ariaAriaUltraAmerican EnglishProfessional
marcusMarcusPremiumBritish EnglishProfessional
lunaLunaUltraAustralian EnglishCreative
kaiKaiPremiumAmerican EnglishCreative
elenaElenaPremiumSpanishMultilingual
omarOmarPremiumMiddle EasternCreative
yukiYukiPremiumJapaneseMultilingual
hansHansStandardGermanProfessional
sofiaSofiaPremiumItalianCreative
chenChen WeiPremiumMandarinMultilingual
priyaPriyaPremiumIndian EnglishProfessional
rafaelRafaelStandardBrazilian PortugueseCreative

Ready to get started?

Create a free account and start generating speech in minutes.