Virtual PBX API — Interactive Actions (1.0)

Download OpenAPI specification:Download

INTRODUCTION

Integration of the Virtual PBX with your own server: when somebody calls one of your voice numbers, we send a POST request (signed JSON) to the URL you configure and we run on the call whatever action your server replies with: talk to the AI assistant, read out a text, transfer to a phone/extension/ring group, offer an options menu, voicemail or hang up.



This way your own business logic decides, in real time and call by call, what to do with each caller: route VIP customers, apply your own opening hours, branch on the status of an order, identify the caller against your CRM, and so on.

SETUP

In your panel: Voice → Incoming calls, pick the number and choose «Ask my server (interactive actions)». Then configure:
- Your server URL: must be https and a public host (private IPs and redirects are not accepted).
- Maximum wait time: 2 to 8 seconds. The caller is on the line while your server answers, so reply as fast as you can.
- Default action: what we do if your server does not answer in time, returns an error or sends invalid JSON (AI assistant, menu, transfer, voicemail or hang up).
- Verification key: generated when you save; we sign every request with it so you can check the request really comes from us.



The Test button in the panel sends a real test request to your URL and shows you the diagnosis (HTTP status, JSON received and the action that would be executed).

SECURITY: VERIFYING THE SIGNATURE

Every request carries the X-Mensatek-Signature header with the HMAC-SHA256 (hexadecimal) of the raw body of the request, computed with your verification key:

X-Mensatek-Signature: sha256=HMAC_SHA256(body, key)

Verification example in PHP:


      $key  = 'YOUR_VERIFICATION_KEY';
      $body = file_get_contents('php://input');
      $sign = $_SERVER['HTTP_X_MENSATEK_SIGNATURE'] ?? '';
      if (!hash_equals('sha256='.hash_hmac('sha256', $body, $key), $sign)) {
        http_response_code(401); exit;
      }
      $data = json_decode($body, true);

We recommend rejecting (401) any request whose signature does not verify.

WHAT HAPPENS WHEN SOMETHING FAILS

If your server does not answer within the configured time, replies with a status other than 2xx, or the body is not valid JSON, the call is not lost: the default action configured in your panel runs automatically. Your server must reply 2xx with Content-Type: application/json.

YOUR SERVER'S RESPONSE

Reply with a JSON object containing the accion field plus the extra fields that apply to that action (any others are ignored):

accionWhat it doesExtra fields
`ia`The caller talks to your AI assistant by voice (the same one you train for WhatsApp). This is also what happens if accion is missing or not recognised.`texto` (optional): replaces the opening greeting.
`reproducir`Reads the text out loud and hangs up.`texto` (recommended; if missing we read «Thank you for your call.»).
`desviar`Transfers the call to the given destination.`destino` (required): a Spanish national number or any international number in +E164, ext:NNN (an extension of your PBX) or grupo:N (a ring group). Premium 90x/80x numbers are blocked; an invalid destination falls back to the AI assistant.
`ivr`Offers an options menu (keypad and spoken keywords).`plantilla`: the name of a menu saved in your panel; or `menu`: an inline menu object (format below). If neither is valid, it falls back to the AI assistant.
`buzon`Announcement and voicemail (you get the audio by email).`texto` (optional): announcement before the beep.
`buzon_inteligente`Smart voicemail: asks the caller for their email by voice (transcribed, with «at/dot» normalised, and without making them confirm it: dictating an email over the phone is tiring and makes people hang up without leaving the message), asks you with the `buzon_email` event, then asks for the reason for the call —which is what really matters, together with their phone number—, transcribes it and, when saying goodbye, offers them the chance to repeat the email in case it was wrong. Everything is emailed to the account holder with the call audio attached, so the address can be checked if the transcription was not accurate.`texto` (optional): opening announcement.
`colgar`Hangs up the call.`texto` (optional): goodbye message before hanging up.


Optional common fields, valid with any action:
- idioma: TTS voice and language in the form xx-XX:n (n: 1 female, 2 male). E.g. es-ES:1, pt-PT:1, en-US:1.
- grabar: true/false, turns recording of this call on or off.



Response examples:


      // Send a VIP customer straight to their account manager
      { "accion": "desviar", "destino": "+34600000001" }

      // Send the call to ring group 2 (rings on several extensions)
      { "accion": "desviar", "destino": "grupo:2" }

      // Custom greeting and AI assistant
      { "accion": "ia", "texto": "Hello Mr Garcia, you are through to the MyCompany assistant." }

      // A menu saved in the panel
      { "accion": "ivr", "plantilla": "Main menu" }

      // Read out a notice and hang up
      { "accion": "reproducir", "texto": "Your order 1234 ships today. Thank you for calling." }

      // Voicemail with your own announcement and recording enabled
      { "accion": "buzon", "texto": "We cannot take your call right now, please leave a message.", "grabar": true }

Inline menu format (menu): the very same object produced by the visual editor in the panel. Keys: locucion (the text read out offering the options; it accepts the (MP3:file) and (PAUSA:seconds) markers), esMenuDTMF = 1, and one key per keypad digit holding the option: Accion (1 repeat · 2 notify a URL · 3 notify by email · 4 transfer to a phone · 6 hang up · 7 AI assistant · 8 transfer to an extension · 9 transfer to a ring group), Valor (the target of the action), Palabra (optional: the caller may SAY it instead of pressing the key), LocucionPrevia and LocucionFinal (optional, played before and after the action).


      {
        "accion": "ivr",
        "menu": {
          "locucion": "For sales, say sales or press 1. For support, press 2.",
          "esMenuDTMF": 1,
          "1": { "Accion": "9", "Valor": "grupo:1", "Palabra": "sales", "LocucionPrevia": "Putting you through to sales." },
          "2": { "Accion": "8", "Valor": "ext:102" }
        }
      }

EVENTS

The evento field of the request tells you at which point of the call we are asking (ignore any event you do not recognise by replying with your default action):

eventoWhen it is sentExtra request fields
`llamada_entrante`A call has just come in on your number.
`sin_respuesta`The call was sent to a ring group with a waiting queue and nobody answered after all the configured announcements. Your response decides what to do with the call; if you do not answer (or answer something invalid), the group's final destination applies.`grupo` (group id, integer) and `avisos` (waiting announcements played, integer).
`buzon_email`The smart voicemail has captured the caller's email (transcribed, not confirmed: it may contain mistakes). Your response may include `contacto` (the caller's details according to your CRM: they are added to the email the account holder receives) and `texto` (the announcement used to ask for the reason of the call). The `accion` field is ignored for this event.`email` (the captured one; the caller may correct it at the end of the call).

New events will be added to this specification keeping the same format and signature.

CONTACT DETAILS IN THE RESPONSE

Any response may include the contacto object with the caller's details according to your CRM:


      { "accion": "desviar", "destino": "grupo:2",
        "contacto": { "nombre": "Jose Munoz (VIP)", "email": "jmunoz@customer.com", "variable_1": "Order 8812" } }

The nombre field is shown on the agent's softphone when the call is transferred (taking priority over the contacts saved in the panel). The remaining fields are used by the smart voicemail and by upcoming features.

Request your server will receive on every call

https://{YourServer}/script-receptor-en-su-servidor

POST REQUEST (JSON) THAT WE SEND TO YOUR URL WHEN A CALL COMES IN.

The request is signed with the X-Mensatek-Signature: sha256=HMAC_SHA256(body, key) header (please verify it, see the Introduction). Your server must reply within the configured time (2-8 s) with a 2xx status and a JSON body holding the action to run (see «Your server's response» in the Introduction). Otherwise the default action from your panel is applied and the call carries on without your intervention.

Authorizations:
basicAuth
Request Body schema:

Parámetros recibidos en su script en petición POST con la configuración especificada en su panel de usuario/configuración API.

evento
required
string

The point of the call at which we are asking you: llamada_entrante (the call has just come in) or sin_respuesta (nobody answered the ring group after the waiting announcements; the grupo and avisos fields are sent too). See the EVENTS section. New events will be added keeping this format: ignore the ones you do not recognise by replying with your default action.

from
required
string

The CALLER's number in international +E164 format. Use it to identify the customer in your system.

to
required
string

Your voice number that was CALLED, in international +E164 format.

numero
required
string

Your called voice number WITHOUT the + sign. Handy if you have several numbers pointing at the same URL.

call_id
required
string

Unique identifier of the call. Store it if you want to correlate later events of the same call.

direccion
required
string

Direction of the call. Currently always entrante (inbound).

hora
required
string

Date and time of the call in UTC, ISO-8601 format.

Request samples

Content type
{
  • "evento": "llamada_entrante",
  • "from": "+34600000001",
  • "to": "+34910000001",
  • "numero": "34910000001",
  • "call_id": "v3:Gvpt8EiClUDCgsxRoMGUI4YsXq1nQ-pdKZRgdSdjQrOy8LQenTuq3A",
  • "direccion": "entrante",
  • "hora": "2026-07-24T10:15:30Z"
}