> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ryvo.so/llms.txt
> Use this file to discover all available pages before exploring further.

# Disparar una llamada saliente

> Inicia una llamada saliente desde uno de tus agentes hacia un número en
formato E.164. La llamada se factura en tu wallet al terminar (no al
disparar) usando la tarifa estándar de $0.29 USD/min prorrateado por
segundo.

Si tu wallet está vacío, tu suscripción está vencida o el agente está
pausado, esta petición devuelve `402` o `422` y la llamada **no** se
dispara.

Para evitar duplicados en reintentos, manda el header `Idempotency-Key`.




## OpenAPI

````yaml /openapi.yaml post /v1/calls
openapi: 3.1.0
info:
  title: Ryvo API
  version: 1.0.0
  description: >
    API pública de Ryvo para disparar llamadas y recibir eventos de tus agentes

    de voz IA. Útil para conectar tu CRM, herramientas internas o
    automatizaciones

    a Ryvo sin pasar por intermediarios como n8n.


    **Base URL**: `https://api.ryvo.so`


    Toda petición requiere autenticación con un Bearer token de API key creado

    desde el portal en `https://app.ryvo.so/developers`.
  contact:
    name: Soporte Ryvo
    email: soporte@ryvo.so
    url: https://ryvo.so
servers:
  - url: https://api.ryvo.so
    description: Producción
security:
  - bearerAuth: []
tags:
  - name: Calls
    description: Disparar llamadas salientes desde tus agentes
paths:
  /v1/calls:
    post:
      tags:
        - Calls
      summary: Disparar una llamada saliente
      description: |
        Inicia una llamada saliente desde uno de tus agentes hacia un número en
        formato E.164. La llamada se factura en tu wallet al terminar (no al
        disparar) usando la tarifa estándar de $0.29 USD/min prorrateado por
        segundo.

        Si tu wallet está vacío, tu suscripción está vencida o el agente está
        pausado, esta petición devuelve `402` o `422` y la llamada **no** se
        dispara.

        Para evitar duplicados en reintentos, manda el header `Idempotency-Key`.
      operationId: createCall
      parameters:
        - name: Idempotency-Key
          in: header
          required: false
          description: |
            Identificador único (1-255 caracteres ASCII imprimibles) para que
            reintentos del mismo request devuelvan la misma respuesta sin
            disparar una segunda llamada. Cache de 24 horas. Reusar la misma
            key con un body distinto devuelve `409 idempotency_conflict`.
          schema:
            type: string
            maxLength: 255
            example: lead-abc-2026-04-30-001
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateCallRequest'
            examples:
              minimal:
                summary: Petición mínima
                value:
                  agent_id: agent_8801kpabc123
                  to: '+5215555550100'
              withMetadata:
                summary: Con metadata para el agente
                value:
                  agent_id: agent_8801kpabc123
                  to: '+5215555550100'
                  metadata:
                    lead_name: Juan García
                    deal_id: OPP-2026-0042
      responses:
        '201':
          description: Llamada disparada
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Call'
        '400':
          description: Body inválido o Idempotency-Key mal formado
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: API key faltante, inválida o revocada
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '402':
          description: Cuenta sin saldo o suscripción inactiva
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GateError'
        '403':
          description: El agente no existe o no pertenece a tu cuenta
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: Idempotency-Key reusado con body distinto
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          description: El agente no está activo
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GateError'
        '429':
          description: Rate limit excedido
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '502':
          description: Proveedor upstream rechazó o no respondió
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '503':
          description: Servicio temporalmente no disponible
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    CreateCallRequest:
      type: object
      required:
        - agent_id
        - to
      properties:
        agent_id:
          type: string
          description: |
            ID del agente de ElevenLabs (lo ves en `app.ryvo.so/agentes`).
            Debe pertenecer a tu cuenta.
          example: agent_8801kpabc123
        to:
          type: string
          pattern: ^\+[1-9]\d{6,14}$
          description: Número destino en formato E.164.
          example: '+5215555550100'
        metadata:
          type: object
          description: |
            Diccionario opcional de variables que se pasan al agente como
            `dynamic_variables`. Máximo 5KB. Las llaves deben tener ≤64 chars,
            y los valores deben ser string, número, booleano o null.
          additionalProperties:
            oneOf:
              - type: string
                maxLength: 2000
              - type: number
              - type: boolean
              - type: 'null'
          example:
            lead_name: Juan García
            deal_id: OPP-2026-0042
    Call:
      type: object
      required:
        - id
        - agent_id
        - to
        - status
        - created_at
      properties:
        id:
          type: string
          description: ID único de la llamada (`call_<conversation_id>`).
          example: call_conv_01abcdef
        agent_id:
          type: string
          example: agent_8801kpabc123
        to:
          type: string
          example: '+5215555550100'
        status:
          type: string
          enum:
            - initiated
          description: |
            Estado al disparar. Para saber cómo terminó la llamada, escucha
            los webhooks `call.completed` / `call.failed`.
        created_at:
          type: string
          format: date-time
          example: '2026-04-30T18:32:11.123Z'
    Error:
      type: object
      required:
        - error
        - message
        - request_id
      properties:
        error:
          type: string
          description: Código de error estable (no cambia entre versiones).
          example: unauthorized
        message:
          type: string
          description: Descripción humana del error.
          example: Invalid or revoked API key.
        request_id:
          type: string
          format: uuid
          description: ID de la petición — incluye este valor cuando reportes un problema.
          example: f0c0a9d2-8b1e-4d8a-9c2f-6e5b7a1d2c3b
    GateError:
      allOf:
        - $ref: '#/components/schemas/Error'
        - type: object
          properties:
            primary_reason:
              type: string
              description: Razón principal — útil para mostrar UX específica.
              example: wallet
            reasons:
              type: array
              description: Lista completa de razones de denegación.
              items:
                type: string
              example:
                - wallet
                - agent:pausado
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API key (formato ryvo_live_…)
      description: >
        Autenticación con un token Bearer. El token se obtiene desde

        `https://app.ryvo.so/developers` y tiene el formato `ryvo_live_<64
        hex>`.


        **Header:** `Authorization: Bearer ryvo_live_…`

````