Telephony
Connect your Plivo, Twilio, Vonage, or Telnyx account to use for outbound and inbound PSTN legs. Rymi encrypts provider credentials before storage.
Self-serve BYOC carrier costs are not bundled into Rymi's platform minute price. Your carrier bills PSTN minutes, number rental, taxes, and add-ons directly. Rymi bills at the agent's per-minute rate: its managed SKU price, or for a custom agent the stack's component cost plus the flat $0.02/min platform fee. Enterprise plans can bundle telecom under a custom agreement.
List Available Providers
Returns the full carrier catalog with the credential field shapes the dashboard uses to render dynamic connect forms. No auth required, since field metadata is not sensitive.
Response 200
{
"providers": [
{
"id": "twilio",
"displayName": "Twilio",
"credentialFields": [
{ "key": "auth_id", "label": "Account SID", "type": "text", "required": true },
{ "key": "auth_token", "label": "Auth Token", "type": "secret", "required": true }
]
}
]
}Validate Without Saving
Pings the carrier's API and returns whether the credentials authenticate, without storing them. Rate-limited to 3 attempts per 5 minutes per tenant.
Request Body
Same shape as Connect Provider.
Response 200
{ "valid": true, "accountName": "Acme Twilio" }{ "valid": false, "error": "Invalid credentials — could not authenticate with the provider" }Errors
| Status | Meaning |
|---|---|
400 | Unsupported provider |
401 | Missing Rymi auth context |
429 | Too many validation attempts; wait and retry |
Connect Provider
Only one active telephony carrier is used per tenant at a time. Connecting a new provider deactivates the previous active carrier.
Request Body
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
provider | string | Yes | — | plivo, twilio, vonage, or telnyx |
auth_id | string | Yes (Plivo/Twilio/Telnyx) | — | Plivo Auth ID, Twilio Account SID, or Telnyx API Key |
auth_token | string | Yes (Plivo/Twilio) | — | Provider auth token. For Telnyx this is the Connection ID and is optional — Rymi auto-creates a TeXML app when omitted |
api_key | string | Yes (Vonage) | — | Vonage API key |
api_secret | string | Yes (Vonage) | — | Vonage API secret |
application_id | string | Yes (Vonage) | — | Vonage Voice Application ID |
private_key | string | Yes (Vonage) | — | Vonage Voice private key (PEM) |
auth_secret | string | No | — | Optional webhook signing secret (Telnyx Ed25519 verification) |
signature_secret | string | No | — | Optional Vonage signature secret for webhook verification (required to receive inbound calls) |
Example: Twilio
curl -X POST https://api.rymi.live/v1/telephony/connect \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"provider": "twilio",
"auth_id": "ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"auth_token": "your_twilio_auth_token"
}'const result = await rymi.telephony.connect({
provider: "twilio",
auth_id: "ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
auth_token: "your_twilio_auth_token",
});result = rymi.telephony.connect(
provider="twilio",
auth_id="ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
auth_token="your_twilio_auth_token",
)Example: Plivo
curl -X POST https://api.rymi.live/v1/telephony/connect \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"provider": "plivo",
"auth_id": "your_plivo_auth_id",
"auth_token": "your_plivo_auth_token"
}'const result = await rymi.telephony.connect({
provider: "plivo",
auth_id: "your_plivo_auth_id",
auth_token: "your_plivo_auth_token",
});result = rymi.telephony.connect(
provider="plivo",
auth_id="your_plivo_auth_id",
auth_token="your_plivo_auth_token",
)Example: Vonage
curl -X POST https://api.rymi.live/v1/telephony/connect \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"provider": "vonage",
"api_key": "your_vonage_api_key",
"api_secret": "your_vonage_api_secret",
"application_id": "your_vonage_voice_application_id",
"private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----",
"signature_secret": "your_vonage_signature_secret"
}'const result = await rymi.telephony.connect({
provider: "vonage",
api_key: "your_vonage_api_key",
api_secret: "your_vonage_api_secret",
application_id: "your_vonage_voice_application_id",
private_key: "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----",
signature_secret: "your_vonage_signature_secret",
});result = rymi.telephony.connect(
provider="vonage",
api_key="your_vonage_api_key",
api_secret="your_vonage_api_secret",
application_id="your_vonage_voice_application_id",
private_key="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----",
signature_secret="your_vonage_signature_secret",
)Example: Telnyx
curl -X POST https://api.rymi.live/v1/telephony/connect \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"provider": "telnyx",
"auth_id": "your_telnyx_api_key",
"auth_token": "your_telnyx_connection_id",
"auth_secret": "your_telnyx_webhook_signing_secret"
}'Response 200
{
"status": "connected",
"provider": "twilio",
"account_name": "Acme Twilio",
"message": "twilio account connected successfully"
}Errors
| Status | Meaning |
|---|---|
400 | Missing or unsupported provider, missing provider-specific credentials, or invalid carrier credentials (validation failed) |
401 | Missing Rymi auth context |
429 | Too many credential connection attempts in a short window |
500 | Credential storage failed |
Status
Returns the current telephony connection state for the authenticated tenant. No query parameters.
Example Request
curl https://api.rymi.live/v1/telephony/status \
-H "Authorization: Bearer YOUR_API_KEY"const status = await rymi.telephony.status();status = rymi.telephony.status()Response 200
{
"connected": true,
"provider": "twilio",
"account_name": "Acme Twilio",
"test_pool": { "enabled": true, "countries": ["US", "IN"] }
}test_pool is always present, on both the connected and disconnected branches, and reports the shared test-number pool for the tenant.
| Field | Type | Description |
|---|---|---|
connected | boolean | Whether a telephony provider is currently connected |
provider | string or null | Active provider: plivo, twilio, vonage, or telnyx |
account_name | string or null | Display name from the provider account |
test_pool | object | Shared test-number pool status: { enabled: boolean, countries: string[] } |
Errors
| Status | Meaning |
|---|---|
401 | Missing or invalid API key |
500 | Provider status lookup failed |
Provider Numbers
Returns carrier-owned numbers synced into Rymi for the connected provider. Read-only: it does not search, buy, release, assign, or unassign carrier numbers.
Example Request
curl https://api.rymi.live/v1/telephony/numbers \
-H "Authorization: Bearer YOUR_API_KEY"const { numbers } = await rymi.telephony.numbers();result = rymi.telephony.numbers()Response 200
{
"numbers": [
{
"id": "num_123",
"provider": "twilio",
"phone_number": "+15551234567",
"number_type": "local",
"number_status": "active",
"assigned_app_id": null,
"backend_agent_id": "550e8400-e29b-41d4-a716-446655440000",
"synced_at": "2026-04-01T10:00:00Z",
"agents": { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "Support Bot" }
}
]
}| Field | Type | Description |
|---|---|---|
id | string | Internal number record ID |
provider | string | Carrier provider name |
phone_number | string | Phone number in E.164 format |
number_type | string or null | Carrier-reported number type (e.g. local, tollfree) |
number_status | string | active or inactive |
assigned_app_id | string or null | Carrier application/connection the number is bound to, if any |
backend_agent_id | uuid or null | Agent attached to this number, if any |
synced_at | string or null | Timestamp of the last carrier sync for this number |
agents | object or null | Attached agent { id, name }, joined from backend_agent_id |
Errors
| Status | Meaning |
|---|---|
401 | Missing or invalid API key |
500 | Provider number lookup failed |
Disconnect
Deactivates the current telephony provider. No request body required.
Example Request
curl -X POST https://api.rymi.live/v1/telephony/disconnect \
-H "Authorization: Bearer YOUR_API_KEY"const result = await rymi.telephony.disconnect();result = rymi.telephony.disconnect()Response 200
{
"status": "disconnected",
"message": "Telephony disconnected."
}Errors
| Status | Meaning |
|---|---|
401 | Missing or invalid API key |
500 | Disconnect operation failed |
Sync Numbers from Carrier
Pulls phone-number inventory from the connected carrier and upserts it into provider_numbers. Numbers no longer present in the carrier inventory are removed locally. Rate-limited to one sync per 2 minutes per tenant.
Example Request
curl -X POST https://api.rymi.live/v1/telephony/sync-numbers \
-H "Authorization: Bearer YOUR_API_KEY"Response 200
{
"numbers": [
{
"phone_number": "+15551234567",
"number_type": "local",
"provider": "twilio"
}
],
"synced_at": "2026-04-01T10:00:00Z"
}Errors
| Status | Meaning |
|---|---|
400 | No active telephony provider connected, or provider doesn't support sync |
429 | Sync rate-limited; wait 2 minutes between syncs |
500 | Carrier API call failed |
Number Management
Rymi does not search or purchase carrier numbers. Provision numbers in your carrier account, sync them via POST /v1/telephony/sync-numbers, then use the Numbers API to attach them to agents.

