API v1 overview
Persian language APIs built for text people actually read.
Use one server-side API for contextual Persian diacritization, Farsi-to-Pinglish transliteration, Persian-to-English translation, and pronunciation-aware Persian speech. Every endpoint has a strict, versioned contract and usage metadata you can account for.
Updated September 15, 2026 · API version 1
From approved access to your first key
- Sign in to the developer portal and submit an application. Your website account and your Developer API allowances are separate.
- After review, your organization and approved offer appear in the portal. For an approved paid offer, the organization owner selects Pay and activate API access. Check the first-month price, recurring price, and separate Basic and Premium allowances before paying.
- Return to the portal after checkout. Access activates after the payment is verified, not simply because checkout was opened. If the payment is still processing, select Refresh usage and payment; do not make another payment.
- Once your paid plan is active, select Create key, give it a recognizable name, and copy the secret into your server's secret store. It is shown only once. If you lose it, create a replacement and revoke the lost key.
Sandbox is a separately approved evaluation plan with a one-time allowance; it is not automatically included with a paid plan and does not renew monthly. Sandbox keys use vm_test_; paid keys use vm_live_. A Sandbox key is not a prerequisite for paid access. One key can access all four capabilities by default; all keys in the same organization and environment share its limits.
Key rotation gives the previous key a 24-hour replacement window. Immediate revocation stops it immediately. Owners manage billing and invitations; members can view usage and manage keys.
Quickstart
Create a server-side environment variable named VOWELMARKS_API_KEY, then send a UTF-8 JSON request. Test keys begin with vm_test_. Live keys begin withvm_live_. Never place either key in browser JavaScript, a Chrome extension bundle, a mobile application, analytics, or a public repository.
curl https://api.vowelmarks.com/v1/diacritize -H "Authorization: Bearer $VOWELMARKS_API_KEY" -H "Content-Type: application/json" -H "Idempotency-Key: reading-42-attempt-1" --data '{"text":"من فارسی میخوانم","include_ezafe":true}'A successful response includes a request_id, a stableengine_version, the endpoint result, and a usage object. Keep the request ID in your own server logs so a failed integration can be traced without logging Persian text.
Check usage and billing
The portal shows separate text, Basic speech, and Premium speech counters, remaining allowance, in-progress reservations, and the current billing period. Select Refresh usage and payment for a current snapshot. Paid allowances renew on your subscription anniversary, not on the first of every calendar month.
curl https://api.vowelmarks.com/v1/usage -H "Authorization: Bearer $VOWELMARKS_API_KEY"GET /v1/usage reports the environment, plan and access status, billing period, text units, Basic and Premium seconds, approved additional text usage, and the shared request limit. Use the OpenAPI UsageResponse schema for the complete response shape.
Diacritization and Pinglish each use one text unit per submitted Unicode code point; translation uses two. A normal successful cache hit is charged, while replaying the same successful idempotent request is not charged again. Speech is counted in generated seconds, separately from text.
There are no automatic additional-usage charges. Additional text must be approved explicitly and is billed separately by payment link; speech overage is not available in v1. An owner can cancel in the portal, retaining live access through the paid period end. Contact support@vowelmarks.com for billing help or an allowance change. For a failed API call, include its request ID, not your key or submitted text.
Choose an endpoint
Each route does one job, so your product decides which reading layer appears and when.
Request rules shared by every endpoint
| Rule | Contract |
|---|---|
| Authentication | Bearer key sent from server-side infrastructure over HTTPS |
| Body | Strict UTF-8 JSON with snake_case fields; unknown fields are rejected |
| Input size | At most 6,000 Unicode code points and a 32 KiB (32,768-byte) serialized JSON body, including spaces, ZWNJ, punctuation, and existing marks |
| Retries | Idempotency-Key uses 8–128 printable ASCII characters; optional for synchronous POST routes and required for asynchronous Basic speech jobs |
| Rate limits | Shared across keys in the same organization and environment |
| Errors | Structured JSON with a stable code, corrective action, retry flag, and request ID |
Developer generation routes do not allow browser CORS. This is intentional: a private API key belongs on infrastructure you control, not in code a visitor can inspect.
Server-side client examples
TypeScript
const response = await fetch("https://api.vowelmarks.com/v1/pinglish", {
method: "POST",
signal: AbortSignal.timeout(120_000),
headers: {
authorization: "Bearer " + process.env.VOWELMARKS_API_KEY,
"content-type": "application/json",
"idempotency-key": crypto.randomUUID(),
},
body: JSON.stringify({
text: "من فارسی میخوانم",
style: "readable",
vowel_notation: "double_a",
}),
});
const result = await response.json();
if (!response.ok) throw new Error(result.error?.code ?? "api_error");Python
import os
import uuid
import requests
response = requests.post(
"https://api.vowelmarks.com/v1/translate",
headers={
"Authorization": f"Bearer {os.environ['VOWELMARKS_API_KEY']}",
"Idempotency-Key": str(uuid.uuid4()),
},
json={"text": "من فارسی میخوانم"},
timeout=(10, 120),
)
payload = response.json()
response.raise_for_status()Plan for cold starts and complete-response time
Some VowelMarks origin services sleep while idle. The first request after an idle period can spend several extra seconds waking an origin before processing begins. Warm requests are usually faster, but input length, the selected endpoint, upstream providers, and current capacity also affect completion time. API v1 has no latency or availability SLA.
Set separate connection and complete-response deadlines in your server client. As a starting point, allow 120 seconds for text generation. Synchronous speech can take several minutes for long input; a client that sends the maximum 6,000 code points should allow up to 15 minutes or split the passage into smaller sentence or paragraph sections. These are client integration budgets, not guaranteed response times.
A client timeout means the outcome is unknown; it does not prove that VowelMarks stopped processing. Retry the exact endpoint and JSON with the original Idempotency-Key. If the first request is still running, the API returns retryable 409 request_in_progress with Retry-After. If it completed, the replay returns the stored result without a second usage charge.
Errors and safe retries
Branch on error.code and error.retryable, not on message text. If a response is retryable, honor Retry-After, add jitter, and reuse the exact request body and original idempotency key. Validation, authentication, authorization, and quota errors require a corrective action before another request.
{
"request_id": "95b…",
"error": {
"code": "service_unavailable",
"message": "The request could not be completed.",
"category": "service",
"action": "Retry the request later.",
"retryable": true
}
}Continue with authentication, limits, idempotency, and the complete error contract, or download theOpenAPI 3.1 document for generated clients and schema inspection.