Place and track certified document‑translation orders programmatically. A REST API over HTTPS, authenticated with a bearer token and returning JSON — with signed webhooks for every event.
curl -X POST https://www.rapidtranslate.org/api/v1/orders \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "reference=APO-10432" \
-F "source_language=Spanish" \
-F "target_language=English (US)" \
-F "translation_type=certified" \
-F "files[]=@document.pdf"
→ {
"id": "9b1c2d3e-…",
"status": "pending",
"livemode": true
}
The RapidTranslate API lets your application submit documents for certified translation, retrieve up‑to‑date status and pricing, and receive the finished files — without your team touching our checkout. It is designed for businesses that place translation orders on behalf of their own customers.
All requests are made to https://staging.rapidtranslate.org/api/v1 over HTTPS. Requests and responses are JSON, except order creation, which uploads files as multipart/form-data. All amounts are returned as integer cents in USD, and all timestamps are UTC ISO‑8601.
Authenticate every request with your secret API key as a bearer token, and ask for a JSON response. Both headers are required:
Authorization: Bearer YOUR_API_KEY
Accept: application/json
Generate and rotate keys in your dashboard under Business Settings → API Keys. Keys are shown once at creation and stored hashed — if you lose a key, rotate it. Each key belongs to one mode (Live or Sandbox) and carries a fixed set of scopes.
Each endpoint requires a specific ability on the key. A key missing the required scope returns 403 forbidden_scope.
| Scope | Grants |
|---|---|
orders:write | Create and approve orders |
orders:read | Retrieve and list orders |
price:read | Read the price list |
Test mode is a property of the key, not your account. A Sandbox key runs against a fully simulated environment; a Live key places real, billable orders. You can use both at the same time.
Sandbox orders use the same validation, field mapping, and real pricing, but skip file storage, OCR, and fulfillment. On creation, a sandbox order automatically walks through its lifecycle (processing → completed), firing the same webhooks as a live order and finally delivering a static sample document.
Every response and webhook carries a livemode flag so your integration can branch without inspecting the key:
livemode: true — real, billable orderlivemode: false — sandbox / test orderRequests are rate‑limited per organization. The default allowance is 120 requests per minute. Exceeding it returns 429 rate_limited; retry after a short back‑off. If your integration needs a higher limit, contact support@rapidtranslate.org.
Every successful response wraps its payload in a data key. List endpoints add a meta block with pagination.
{
"data": {
"id": "9b1c...-uuid",
"reference": "APO-10432",
"status": "processing",
"total": 11270,
"currency": "USD"
}
}
{
"data": [ ... ],
"meta": {
"current_page": 1,
"per_page": 25,
"total": 134,
"last_page": 6
}
}
Errors use standard HTTP status codes and return a stable, machine‑readable error_code alongside a human message. Validation errors add a field‑keyed errors object.
{
"message": "The given data was invalid.",
"error_code": "validation_failed",
"errors": {
"source_language": ["The selected source language is invalid."]
}
}
| HTTP | error_code | Meaning |
|---|---|---|
| 400 | bad_request | Malformed request body |
| 401 | unauthenticated | Missing, invalid, or revoked key |
| 402 | payment_failed | Order approved but payment could not be collected |
| 402 | credit_hold | Order exceeds your credit limit |
| 403 | forbidden_scope | Key lacks the required scope |
| 403 | account_suspended | Organization suspended for unpaid invoices |
| 404 | not_found | No such order for this organization |
| 409 | duplicate_reference | Reference reused for a different order |
| 409 | not_awaiting_approval | Order is not awaiting your approval |
| 422 | validation_failed | Missing or invalid fields |
| 429 | rate_limited | Rate limit exceeded |
| 500 | server_error | Unexpected server error |
| 503 | processing_failed | Downstream processing (OCR / pricing) failed |
An order's status follows a stable lifecycle. These five values are also the ones accepted by the status filter on List orders:
| Status | Meaning |
|---|---|
pending | Received; pricing not yet finished. total may be null. |
awaiting_approval | Priced and waiting for you to approve the total (only when approval is required). |
processing | Approved and active; translation underway. |
completed | Finished; translated documents are available. |
cancelled | Order was cancelled. |
While an order is in progress, more granular labels (for example Assigned To Translator, Translating, Shipped) may also appear. When approval is required, an order may briefly report payment_failed or credit_hold if a charge could not be collected — resolve the payment method and approve again.
GET /languages
Returns every supported language. Use the name value verbatim as source_language / target_language when creating an order — orders are matched on the language name, not the code.
Requires an authenticated key.
curl https://www.rapidtranslate.org/api/v1/languages \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"
{
"data": [
{ "code": "english-uk", "name": "English (UK)", "active": true },
{ "code": "spanish", "name": "Spanish", "active": true }
]
}
GET /prices
Returns the US‑baseline rate card, in USD, that your orders are billed against. Amounts are decimal strings. Prices are grouped by translation type (each with a regular and rapid per‑unit price), delivery method, and apostille — the same values you send when creating an order.
Scope: price:read
{
"data": {
"country": { "code": "US", "name": "United States" },
"currency": { "code": "USD", "symbol": "$" },
"translation": {
"certified": { "unit": "page", "regular": "27.99", "rapid": "37.99" },
"standard": { "unit": "word", "regular": "0.11", "rapid": "0.15" },
"specialized": { "unit": "page", "regular": "47.99", "rapid": "57.99" },
"naati": { "unit": "page", "regular": "42.99", "rapid": "52.99" },
"sworn": {
"unit": "page",
"note": "Sworn pricing depends on the language pair.",
"language_pairs": [
{ "languages": ["Spanish","English"], "unit": "page", "regular": "57.99", "rapid": "67.99" },
{ "languages": ["Polish","English"], "unit": "page", "regular": "46.99", "rapid": "56.99" }
]
}
},
"delivery": {
"email": "0.00", "notarized_email": "19.99",
"mail_standard": "29.99", "mail_next_day": "55.00"
},
"apostille": { "base": "79.00", "additional_document": "15.00" }
}
}
Sworn pricing. Sworn translation is priced per language pair. language_pairs lists every sworn‑eligible pair with its own regular/rapid price. Any English variant (English (US/UK/AU/CA)) is accepted, and each pair works in both directions unless it carries "bidirectional": false.
POST /orders
Creates a translation order and uploads the source files. Because it carries files, this endpoint uses multipart/form-data (not JSON). Nested fields use bracket notation, e.g. customer[name].
Scope: orders:write
| Field | Type | Notes |
|---|---|---|
reference | string required | Your own unique order reference. Reusing it returns the existing order (see idempotency). |
customer[name] | string required | End customer's full name. |
customer[email] | string required | End customer's email. |
source_language | string required | Exact language name from List languages. |
target_language | string required | Exact language name from List languages. |
translation_type | string required | One of certified, standard, specialized, sworn, naati. |
turnaround | string required | regular or rapid. |
delivery[method] | string required | One of email, notarized_email, mail_standard, mail_next_day. |
delivery[address][...] | object | Required for mail_standard / mail_next_day: street, city, postal_code, country (state optional). country is an ISO code, e.g. US. |
apostille[enabled] | boolean | Add apostille processing. See rules below. |
apostille[documents] | integer | Number of documents to apostille. Required when enabled. |
apostille[destination_country] | string | Country the apostille is for. |
notes | string | Free‑text instructions. |
coupon_code | string | A discount code to apply. |
files[] | file[] required | 1–20 files. Allowed: pdf, jpg, jpeg, png, doc, docx, tiff, heic. Max 20 MB each. |
reference is unique per organization. Repeating a create with the same reference returns the existing order with 200 instead of creating a duplicate (a new order returns 201).
mail_standard delivery method. mail_next_day is US‑addresses only.
curl -X POST https://www.rapidtranslate.org/api/v1/orders \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json" \
-F "reference=APO-10432" \
-F "customer[name]=Jane Doe" \
-F "customer[email]=jane@example.com" \
-F "source_language=Spanish" \
-F "target_language=English (US)" \
-F "translation_type=certified" \
-F "turnaround=regular" \
-F "delivery[method]=email" \
-F "files[]=@/path/to/birth-certificate.pdf"
{
"data": {
"id": "9b1c2d3e-...-uuid",
"reference": "APO-10432",
"livemode": true,
"status": "pending",
"source_language": "Spanish",
"target_language": "English (US)",
"translation_type": "certified",
"turnaround": "regular",
"total": null,
"currency": "USD",
"created_at": "2026-08-28T10:15:00+00:00"
}
}
A freshly created order starts as pending with a null total while pricing is calculated. Poll Retrieve an order or listen for the order_status webhook to see the price and status update.
GET /orders/{id}
Fetches a single order by its id (the UUID returned on creation). Returns 404 not_found if the order doesn't belong to your organization.
Scope: orders:read
curl https://www.rapidtranslate.org/api/v1/orders/9b1c2d3e-...-uuid \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"
GET /orders
Returns your organization's orders, newest first, with pagination in meta. All query parameters are optional.
Scope: orders:read
| Query | Notes |
|---|---|
status | One of pending, awaiting_approval, processing, completed, cancelled. |
reference | Filter by your reference. |
source_language / target_language | Filter by language name. |
created_from / created_to | Date range (inclusive). |
sort | -created_at (default, newest first) or created_at (oldest first). |
per_page | 1–100. Defaults to the standard page size. |
page | Page number. |
curl "https://www.rapidtranslate.org/api/v1/orders?status=completed&per_page=50" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"
POST /orders/{id}/approve
Approves the calculated total for an order that is awaiting_approval, activating it into fulfillment. This is only needed when your account requires approval before work begins. The call is idempotent.
Scope: orders:write
curl -X POST https://www.rapidtranslate.org/api/v1/orders/9b1c2d3e-...-uuid/approve \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"
On success the updated order is returned. If the order is not awaiting approval you get 409 not_awaiting_approval; if a charge is required but fails you get 402 payment_failed or 402 credit_hold.
The fixed sets accepted when creating an order.
| Value | Description |
|---|---|
certified | Certified translation (priced per page). |
standard | Standard translation (priced per word). |
specialized | Specialized / expert translation (per page). |
sworn | Sworn translation (per page). |
naati | NAATI‑certified translation (per page). |
| Value | Description |
|---|---|
regular | Standard turnaround. |
rapid | Expedited turnaround. |
| Value | Address | Description |
|---|---|---|
email | No | Digital delivery by email (free). |
notarized_email | No | Notarized digital delivery. |
mail_standard | Yes | Physical mail; ships to supported countries. |
mail_next_day | Yes | Next‑business‑day mail (US addresses only). |
Instead of polling, configure a webhook endpoint to receive events as they happen. Set your URL and view your signing secret in Business Settings → Webhooks. Webhooks are a convenience — Retrieve an order is always authoritative.
| Event | Sent when |
|---|---|
order_status | An order changes status. |
client_review | An order is priced and awaiting your approval (approval mode only). |
document_delivery | Translated documents are ready, with download URLs. |
payment_failed | An approved order's charge could not be collected — carries a failure block (reason, message). Update the wallet card and approve again. |
credit_hold | An approved order would exceed your credit limit — carries a credit_hold block (message). Settle invoices or request a higher limit. |
Every delivery has the same envelope: an event block (including livemode) and an event‑specific data block.
{
"event": {
"type": "order_status",
"id": "evt_9b1c...",
"livemode": true,
"sent_at": "2026-08-28T10:20:00+00:00"
},
"data": {
"order": {
"id": "9b1c2d3e-...-uuid",
"reference": "APO-10432",
"status": "completed"
}
}
}
The document_delivery event adds a documents array (each with name, download_url, version, status) and a portal link. The client_review event adds an itemized pricing block and an actions.approve object with the URL to call.
Each request is signed so you can confirm it came from RapidTranslate. We send three headers:
| Header | Value |
|---|---|
X-RapidTranslate-Signature | sha256=<hmac> |
X-RapidTranslate-Timestamp | Unix timestamp used in the signature |
X-RapidTranslate-Event | The unique event id |
Compute the expected signature as an HMAC‑SHA256 of the string "{timestamp}.{raw_request_body}" using your webhook signing secret, then compare it to the header value:
// PHP
$expected = 'sha256=' . hash_hmac(
'sha256',
$timestamp . '.' . $rawBody,
$webhookSecret
);
$valid = hash_equals($expected, $signatureHeader);
Failed deliveries are retried with exponential back‑off (up to 5 attempts). Respond with a 2xx status to acknowledge receipt.