api ORINODE DEVELOPER API v1

API Documentation

Nigerian AI voice APIs — speech-to-text, text-to-speech, language detection.
Billed in Naira. Separate from your call center subscription.

person_addGet Free API Key open_in_newOpenAPI Spec

linkBase URL

All v1 endpoints are under:

https://api.orinode.ai/api/developer/v1/

Unversioned paths (/api/developer/stt/ etc.) are still accepted and redirect permanently (301) to their v1 equivalents. New integrations should use the versioned path.

keyAuthentication

Pass your API key in the X-API-Key header.

curl https://api.orinode.ai/api/developer/v1/stt/ \ -H "X-API-Key: ori_live_your_key_here" \ -F "audio=@call.wav"
import requests headers = {"X-API-Key": "ori_live_your_key_here"} with open("call.wav", "rb") as f: resp = requests.post( "https://api.orinode.ai/api/developer/v1/stt/", headers=headers, files={"audio": f}, ) print(resp.json())
const FormData = require('form-data'); const fs = require('fs'); const axios = require('axios'); const form = new FormData(); form.append('audio', fs.createReadStream('call.wav')); const resp = await axios.post( 'https://api.orinode.ai/api/developer/v1/stt/', form, { headers: { 'X-API-Key': 'ori_live_your_key_here', ...form.getHeaders() } } ); console.log(resp.data);
Get your API key from the Developer Portal → Keys. Two key types exist: ori_test_ for development (free, mock responses) and ori_live_ for production (billed).

scienceTest Mode

Every endpoint returns a deterministic mock response when called with a ori_test_ key — no credit is deducted and no real AI inference runs.

EndpointTest response
stt"Ina son abinci. I want food please." (Hausa-English, code-switching)
ttsEmpty audio, cost_ngn: "0.00"
langdetectha, confidence 0.94, code-switching detected

All test responses include "mode": "test". Sandbox keys are rate-limited to 5 requests/min and 200 requests/day.

replayIdempotency Keys

On any POST that bills credits, include the Idempotency-Key header with a UUID you generate. If the server already processed a request with that key for your account, it returns the original result without re-billing.

curl -X POST https://api.orinode.ai/api/developer/v1/stt/ \ -H "X-API-Key: ori_live_…" \ -H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \ -F "audio=@call.wav"

When the server replays an idempotent response it includes "idempotent_replay": true in the body. Keys expire after 24 hours.

Always use idempotency keys if you retry on timeout or connection error. Without them, a request that reaches the server before failing on the network will charge you again on retry.

fingerprintRequest IDs

Every response — success or error — includes a unique request_id UUID in the JSON body and as the X-Request-Id response header.

{ "transcript": "...", "request_id": "7f3e1b20-c841-4f0a-9d3a-2b5e6f1c0e82" }

Log the request_id in your application and quote it when contacting support. We can trace any request in our system from this ID.

errorError Responses

All errors return JSON with error (human-readable message), code (machine-readable), request_id, and optional detail.

{ "error": "Insufficient API credit balance.", "code": "insufficient_balance", "request_id": "7f3e1b20-c841-4f0a-9d3a-2b5e6f1c0e82", "detail": { "balance_ngn": "4.50", "required_ngn": "5.00" } }
HTTPcodeMeaningAction
401auth_requiredNo API key suppliedAdd X-API-Key header
403invalid_keyKey not found or revokedCheck your key in the portal
402insufficient_balanceNot enough API creditTop up at /developer/billing/
429rate_limitedToo many requests/minuteRetry after Retry-After header seconds
400validation_errorBad request parametersCheck detail for field errors
400invalid_audioUnsupported file type or too largeUpload WAV/MP3/OGG ≤50 MB
500internal_errorServer faultRetry with exponential backoff; quote request_id in support

speedRate Limits

Limits are enforced per API key, per minute. When exceeded the server returns HTTP 429 with a Retry-After value in seconds.

TierRequests / minSandbox daily cap
Sandbox (test keys)5200 / day
Developer60
Business300
EnterpriseUnlimited
Upgrade your developer tier in the portal or contact us for enterprise limits.

micSpeech-to-Text

POST v1 /api/developer/v1/stt/

Transcribe audio to text. Supports English (Nigerian accent), Hausa, Igbo, and Yoruba — including mid-sentence code-switching where the speaker mixes a native language with English.

Request — multipart/form-data

FieldTypeDescription
audiofileRequiredAudio file — WAV, MP3, or OGG. Max 50 MB. 16 kHz mono WAV recommended for best accuracy.
languagestringOptionalen, ha, ig, yo, or auto (default). Auto runs language detection first and adds ~80ms. Providing a hint is faster.

Request Headers

HeaderDescription
X-API-KeyRequiredYour API key
Idempotency-KeyRecommendedUUID to prevent double-billing on retry

Response — 200 OK

{ "transcript": "Mo fẹ́ mọ bóyá ẹ ṣi ń gbà — do you still deliver to the mainland?", "language_detected": "yo", "is_code_switching": true, "duration_seconds": 4.2, "cost_ngn": "0.35", "mode": "live", "request_id": "7f3e1b20-c841-4f0a-9d3a-2b5e6f1c0e82" }

Code examples

curl -X POST https://api.orinode.ai/api/developer/v1/stt/ \ -H "X-API-Key: ori_live_…" \ -H "Idempotency-Key: $(uuidgen)" \ -F "audio=@recording.wav" \ -F "language=yo"
import uuid, requests resp = requests.post( "https://api.orinode.ai/api/developer/v1/stt/", headers={ "X-API-Key": "ori_live_…", "Idempotency-Key": str(uuid.uuid4()), }, files={"audio": open("recording.wav", "rb")}, data={"language": "auto"}, ) data = resp.json() print(data["transcript"]) print("Language:", data["language_detected"]) print("Cost: ₦", data["cost_ngn"])
const { v4: uuidv4 } = require('uuid'); const FormData = require('form-data'); const fs = require('fs'); const axios = require('axios'); const form = new FormData(); form.append('audio', fs.createReadStream('recording.wav')); form.append('language', 'auto'); const { data } = await axios.post( 'https://api.orinode.ai/api/developer/v1/stt/', form, { headers: { 'X-API-Key': 'ori_live_…', 'Idempotency-Key': uuidv4(), ...form.getHeaders() }} ); console.log(data.transcript);

Pricing note

Billed at ₦5.00/minute based on the actual measured audio duration. A 30-second clip costs ₦5.00 / 2.

volume_upText-to-Speech

POST v1 /api/developer/v1/tts/

Convert text to speech using Orinode's Nigerian-accent AI voices. Returns base64-encoded WAV audio. Tone and language are configurable.

Request — application/json

FieldTypeDescription
textstringRequiredText to synthesize. Max 5,000 characters.
languagestringRequireden, ha, ig, or yo. Selects the voice model.
voice_tonestringOptionalfriendly (default), formal, or neutral.

Response — 200 OK

{ "audio_base64": "UklGRiQAAABXQVZFZm10IBAAAA…", "format": "wav", "sample_rate": 22050, "characters": 148, "cost_ngn": "0.44", "mode": "live", "request_id": "a3b1c2d4-…" }
curl -X POST https://api.orinode.ai/api/developer/v1/tts/ \ -H "X-API-Key: ori_live_…" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: $(uuidgen)" \ -d '{"text":"Ẹ káàbọ̀ sí ile iṣẹ́ wa.","language":"yo","voice_tone":"friendly"}'
import uuid, base64, requests resp = requests.post( "https://api.orinode.ai/api/developer/v1/tts/", headers={ "X-API-Key": "ori_live_…", "Idempotency-Key": str(uuid.uuid4()), }, json={ "text": "Welcome to our service.", "language": "en", "voice_tone": "formal", }, ) data = resp.json() audio_bytes = base64.b64decode(data["audio_base64"]) with open("output.wav", "wb") as f: f.write(audio_bytes)
const axios = require('axios'); const fs = require('fs'); const { v4: uuidv4 } = require('uuid'); const { data } = await axios.post( 'https://api.orinode.ai/api/developer/v1/tts/', { text: 'Hello from Orinode', language: 'en' }, { headers: { 'X-API-Key': 'ori_live_…', 'Idempotency-Key': uuidv4() } } ); fs.writeFileSync('output.wav', Buffer.from(data.audio_base64, 'base64'));

translateLanguage Detection

POST v1 /api/developer/v1/langdetect/

Detect the spoken language in audio without running a full transcription. Only the first 10 seconds are analyzed. Useful for routing callers to the right handler before investing in a full STT request.

Request — multipart/form-data

FieldTypeDescription
audiofileRequiredAudio file (WAV, MP3, OGG). Max 50 MB. Only the first 10s are read.

Response — 200 OK

{ "language": "yo", "is_code_switching": true, "secondary_language": "en", "confidence": 0.91, "all_scores": { "yo": 0.91, "en": 0.07, "ha": 0.02 }, "cost_ngn": "2.00", "mode": "live", "request_id": "…" }

secondary_language is null when code-switching is not detected. Use is_code_switching: true as a hint to run STT in multilingual mode.

bar_chartUsage Statistics

GET v1 /api/developer/v1/usage/

Returns aggregated usage for the current calendar month. Test key calls are excluded from cost totals.

curl https://api.orinode.ai/api/developer/v1/usage/ \ -H "X-API-Key: ori_live_…"
{ "period": { "start": "2026-04-01", "end": "2026-04-09" }, "total_cost_ngn": "812.50", "total_calls": 142, "balance_ngn": "4187.50", "monthly_call_minutes": 56, "effective_call_rate_ngn": "8.00", "by_endpoint": [ { "endpoint": "stt", "calls": 98, "cost": "490.00" }, { "endpoint": "tts", "calls": 44, "cost": "322.50" } ], "request_id": "…" }

attach_moneyCall Rate

GET v1 /api/developer/v1/call-rate/

Returns your effective per-minute AI Call Agent rate given this month's cumulative usage. Use this to display pricing to your own users or to estimate costs before a call.

{ "monthly_minutes_used": 843, "effective_rate_per_minute_ngn": "8.00", "tiers": [ { "from_minutes": 0, "to_minutes": 1000, "rate_ngn": "8.00" }, { "from_minutes": 1000, "to_minutes": 10000, "rate_ngn": "6.00" }, { "from_minutes": 10000, "to_minutes": 100000, "rate_ngn": "4.50" }, { "from_minutes": 100000, "to_minutes": null, "rate_ngn": "3.00" } ], "request_id": "…" }

receiptPricing

EndpointRate (NGN)UnitNotes
stt₦5.00per minute of audioBilled on actual duration
tts₦3.00per 1,000 characters
langdetect₦2.00per requestOnly first 10s analyzed
agent_call₦8.00–₦3.00per minuteVolume discounts apply (see below)
summary₦10.00per callPost-call AI summary

All ori_test_ sandbox keys are always free. Prices shown are defaults; contact us for custom enterprise rates.

discountVolume Discounts

The AI Call Agent endpoint uses tiered pricing based on your cumulative call minutes within a calendar month. Rates step down automatically — no action required.

Minutes / monthRate (NGN/min)Example (100 min)
0 – 1,000₦8.00₦800
1,001 – 10,000₦6.00₦600
10,001 – 100,000₦4.50₦450
100,000+₦3.00₦300

Use GET /api/developer/v1/call-rate/ to query your effective rate at any time.

webhookWebhooks

Configure webhook endpoints in the Developer Portal → Webhooks. Orinode signs each delivery with HMAC-SHA256 using your webhook secret so you can verify authenticity.

Signature Verification

import hmac, hashlib def verify_signature(body: bytes, signature: str, secret: str) -> bool: expected = hmac.new( secret.encode(), body, hashlib.sha256 ).hexdigest() return hmac.compare_digest(f"sha256={expected}", signature) # In your request handler: sig = request.headers.get("X-Orinode-Signature", "") if not verify_signature(request.body, sig, "your_webhook_secret"): # return 403 / abort ... # process event ...
const crypto = require('crypto'); app.post('/webhook', (req, res) => { const sig = req.headers['x-orinode-signature'] || ''; const expected = 'sha256=' + crypto .createHmac('sha256', process.env.WEBHOOK_SECRET) .update(req.rawBody) .digest('hex'); if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) return res.sendStatus(403); // process event ... res.sendStatus(200); });

Events

EventTriggered whenKey payload fields
call.completedAn AI call agent call finishesrequest_id, duration_seconds, cost_ngn
call.transcribedSTT transcript is ready (after /stt/)request_id, duration_seconds, cost_ngn
balance.lowAPI credit drops below your alert thresholdbalance_ngn, threshold_ngn
key.createdA new API key is generated on your accountkey_name, is_test

Webhook payload structure

{ "event": "call.transcribed", "request_id": "7f3e1b20-c841-4f0a-9d3a-2b5e6f1c0e82", "duration_seconds": 4.2, "cost_ngn": "0.35" }
Orinode retries failed webhook deliveries up to 3 times with exponential backoff. Your endpoint should respond with HTTP 200 within 10 seconds.

languageSupported Languages

CodeLanguageSTTTTSCode-switching
enEnglish (Nigerian)With ha, ig, yo
haHausaWith en
igIgboWith en
yoYorubaWith en

Code-switching means a caller can mix a native language with English mid-sentence. When is_code_switching: true is returned by /langdetect/ or /stt/, both languages are preserved exactly as spoken in the transcript.

Diacritics are preserved. Yoruba (ẹ, ọ, ṣ), Hausa (ƙ, ɗ, ɓ), and Igbo (ị, ọ, ụ) tonal markers are kept intact. Never strip them — they change the meaning of words.

account_balanceAPI Credit vs. Plan Billing

Your Orinode subscription (Free / Starter / Pro / Enterprise) covers inbound call handling on your dashboard. The Developer API uses a completely separate credit balance that you top up independently from the billing section of your developer portal.

  • Making API calls will never touch your call center plan balance or monthly call count.
  • Plan upgrades and downgrades have no effect on your API credit.
  • You can hold both a subscription and API credit simultaneously.

Top up API credit at /developer/billing/. Set a low-balance alert threshold so you receive an email before calls start failing.

Ready to integrate?

Get a free sandbox key in 30 seconds — no credit card required.

person_addCreate Free Account Sign In