curl --request GET \
--url https://api.ryvo.so/v1/pricing/voice-minute \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.ryvo.so/v1/pricing/voice-minute"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.ryvo.so/v1/pricing/voice-minute', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.ryvo.so/v1/pricing/voice-minute",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.ryvo.so/v1/pricing/voice-minute"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.ryvo.so/v1/pricing/voice-minute")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.ryvo.so/v1/pricing/voice-minute")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"plan": "pro",
"base_credits_per_minute": 100,
"multiplier": 1.75,
"credits_per_minute": 175,
"usd_per_minute": 0.175,
"available_on_plan": true,
"components": {
"stt": {
"id": "deepgram:nova-3-general",
"name": "Nova-3",
"multiplier": null,
"available_on_plan": true
},
"llm": {
"id": "anthropic:claude-haiku-4-5",
"name": "Claude Haiku 4.5",
"multiplier": 1.75,
"byok": false,
"available_on_plan": true
},
"tts": {
"id": "elevenlabs:eleven_flash_v2_5",
"name": "Flash v2.5",
"multiplier": 1.75,
"available_on_plan": true
}
}
}{
"error": "invalid_query",
"message": "limit must be an integer between 1 and 100.",
"request_id": "f0c0a9d2-8b1e-4d8a-9c2f-6e5b7a1d2c3b"
}{
"error": "unauthorized",
"message": "Invalid or revoked API key.",
"request_id": "f0c0a9d2-8b1e-4d8a-9c2f-6e5b7a1d2c3b"
}{
"error": "insufficient_scope",
"message": "This API key does not have the agents:write scope.",
"request_id": "f0c0a9d2-8b1e-4d8a-9c2f-6e5b7a1d2c3b"
}{
"error": "invalid_query",
"message": "tts openai:gpt-4o-mini-tts is not an enabled model. See GET /v1/models and GET /v1/voices.",
"request_id": "f0c0a9d2-8b1e-4d8a-9c2f-6e5b7a1d2c3b"
}{
"error": "rate_limit_exceeded",
"message": "Rate limit exceeded. Retry in 32s (see the Retry-After header).",
"request_id": "f0c0a9d2-8b1e-4d8a-9c2f-6e5b7a1d2c3b"
}Price a voice minute
What one minute of a voice call costs on your plan with a given combination of transcription (STT), language model (LLM) and voice (TTS), in credits and USD.
The minute is your plan’s base (base_credits_per_minute) times the
multiplier of the pricier piece between the language model and the
voice. The published steps are 1x, 1.75x, 3x and 5x. Transcription is
included in the base and never multiplies. With your own model
(llm=custom) the language model counts as 1x, because you pay for
it; the voice is still billed. Calls are billed per second at this
rate.
Pass the same provider:model identities an agent saves in llm,
voice and stt (see GET /v1/models and GET /v1/voices).
curl --request GET \
--url https://api.ryvo.so/v1/pricing/voice-minute \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.ryvo.so/v1/pricing/voice-minute"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.ryvo.so/v1/pricing/voice-minute', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.ryvo.so/v1/pricing/voice-minute",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.ryvo.so/v1/pricing/voice-minute"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.ryvo.so/v1/pricing/voice-minute")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.ryvo.so/v1/pricing/voice-minute")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"plan": "pro",
"base_credits_per_minute": 100,
"multiplier": 1.75,
"credits_per_minute": 175,
"usd_per_minute": 0.175,
"available_on_plan": true,
"components": {
"stt": {
"id": "deepgram:nova-3-general",
"name": "Nova-3",
"multiplier": null,
"available_on_plan": true
},
"llm": {
"id": "anthropic:claude-haiku-4-5",
"name": "Claude Haiku 4.5",
"multiplier": 1.75,
"byok": false,
"available_on_plan": true
},
"tts": {
"id": "elevenlabs:eleven_flash_v2_5",
"name": "Flash v2.5",
"multiplier": 1.75,
"available_on_plan": true
}
}
}{
"error": "invalid_query",
"message": "limit must be an integer between 1 and 100.",
"request_id": "f0c0a9d2-8b1e-4d8a-9c2f-6e5b7a1d2c3b"
}{
"error": "unauthorized",
"message": "Invalid or revoked API key.",
"request_id": "f0c0a9d2-8b1e-4d8a-9c2f-6e5b7a1d2c3b"
}{
"error": "insufficient_scope",
"message": "This API key does not have the agents:write scope.",
"request_id": "f0c0a9d2-8b1e-4d8a-9c2f-6e5b7a1d2c3b"
}{
"error": "invalid_query",
"message": "tts openai:gpt-4o-mini-tts is not an enabled model. See GET /v1/models and GET /v1/voices.",
"request_id": "f0c0a9d2-8b1e-4d8a-9c2f-6e5b7a1d2c3b"
}{
"error": "rate_limit_exceeded",
"message": "Rate limit exceeded. Retry in 32s (see the Retry-After header).",
"request_id": "f0c0a9d2-8b1e-4d8a-9c2f-6e5b7a1d2c3b"
}Authorizations
A Bearer token. Create keys in the portal under Settings > API keys
(https://app.ryvo.so/developers). The token has the form
ryvo_live_<64 hex characters> and is shown once.
Header: Authorization: Bearer ryvo_live_...
Query Parameters
The voice model, as provider:model.
"elevenlabs:eleven_flash_v2_5"
The language model, as provider:model, or custom for your own model (BYOK).
"anthropic:claude-haiku-4-5"
The transcription model, as provider:model. Optional; it is validated but does not change the price.
"deepgram:nova-3-general"
Response
The price of one minute with that combination.
The plan the price is computed for.
"pro"
Your plan's voice minute at 1x.
100
The larger of the language model and voice multipliers.
1.75
base_credits_per_minute times multiplier, rounded.
175
credits_per_minute / 1000.
0.175
Whether your plan can use every piece of the combination. When false, the price is what it would cost, but an agent cannot be saved with it until you upgrade.
true
Show child attributes
Show child attributes

