Acceso a la API
VoiceBooker ofrece acceso programático a la API para integrar otras aplicaciones y automatizar flujos, como la recuperación de uso, el despliegue de bots y la integración con pipelines de CI/CD.
URL base
https://voicebooker.de/app/api/v1Autenticación
Envíe un token API en cada solicitud mediante este header:
X-API-TOKEN: <su-token-api>El token determina el contexto de empresa de la solicitud. Manténgalo seguro.
Exportar un bot
GET /exportBots/{botId} exporta un bot de la empresa asociada al token API. Use pretty=true para obtener HJSON legible.
curl --get 'https://voicebooker.de/app/api/v1/exportBots/<bot-id>' \
--header 'X-API-TOKEN: <su-token-api>' \
--data-urlencode 'pretty=true'Ejemplo de respuesta:
{
"name": "Asistente de recepción",
"id": "kqrmxaveli",
"stages": [
{
"name": "Welcome",
"id": "mavotirenu",
"linkId": "qeluzanopi",
"template": false,
"prompt": "Saluda a la persona que llama.",
"tools": [],
"functions": [],
"settings": {},
"stageConfig": [],
"x": 0,
"y": 0,
"order": 0,
"instanceSettings": {}
}
],
"settings": {},
"wizard": {}
}Importar un bot
POST /importBots importa una definición de bot en la empresa asociada al token. Envíe la definición exportada en contents. Para HJSON, filename debe terminar en .hjson. overwriteBotStages, overwriteTemplates y replaceBotStages son parámetros booleanos opcionales.
curl --request POST \
--url https://voicebooker.de/app/api/v1/importBots \
--header 'X-API-TOKEN: <su-token-api>' \
--header 'Content-Type: application/json' \
--data '{"filename":"bot.json","contents":{"name":"Asistente de recepción","settings":{},"stages":[]},"overwriteBotStages":false,"overwriteTemplates":false,"replaceBotStages":false}'Ejemplo de respuesta:
{
"id": "vexorimaku",
"name": "Asistente de recepción",
"settings": {},
"invisible": false
}Realizar llamadas salientes
Para realizar una llamada saliente, envíe una solicitud POST a:
https://voicebooker.de/app/api/v1/makeCallContent-Type: application/json
X-API-TOKEN: <su-token-api>Ejemplo de solicitud:
{
"dest": "+49-351-123456789",
"botId": "kqrmxaveli",
"sipAccountId": "lupenakori",
"ringTimeout": 25,
"startTimeout": 10,
"state": {
"customerId": "zpjwletodo"
}
}| Parámetro | Descripción |
|---|---|
dest | Número de destino en formato E.164. |
botId | Bot utilizado para la llamada. |
sipAccountId | Cuenta SIP utilizada; su número aparece al destinatario. |
ringTimeout | Segundos que sonará antes de cancelar si nadie responde. Por defecto: 30 segundos. |
startTimeout | Segundos que espera el bot antes de empezar a hablar. |
state | Datos para webhooks o llamadas API durante la llamada, como un ID de cliente. |
La API devuelve un callId:
{
"callId": "xavurimeto"
}Gestionar pruebas de bots
Las pruebas de bots comparan un bot de origen/llamada con un bot de destino/respuesta. Las solicitudes con clave API están limitadas a la empresa asociada al token; ambos bots deben pertenecer a esa empresa.
| Método | Endpoint | Función |
|---|---|---|
GET | /bot_test_setups | Listar pruebas. |
POST | /bot_test_setups | Crear una prueba. |
PUT | /bot_test_setups/{id} | Actualizar una prueba. |
DELETE | /bot_test_setups/{id} | Eliminar una prueba. |
La respuesta pública contiene únicamente id, name, settings, srcBotId y destBotId. settings puede incluir
convInitBot, maxConvTurns, asCall, startTimeout y stateUpdate. Al actualizar, los campos omitidos se conservan.
Obtener una grabación de llamada
GET /getRecording/{id} devuelve la grabación MP3 de una sesión de llamada. Usa como id el ID de sesión de llamada devuelto por /usage. La grabación debe haberse activado para la llamada.
La respuesta se transmite como audio/mpeg y puede guardarse directamente como archivo .mp3:
curl --request GET \
--url https://voicebooker.de/app/api/v1/getRecording/<id-de-sesion> \
--header 'X-API-TOKEN: <su-token-api>' \
--output grabacion.mp3El endpoint devuelve 404 Not Found cuando la sesión o su grabación no están disponibles para el token de API. Devuelve 401 Unauthorized si el token de API falta o no es válido.
Obtener uso
GET /usage devuelve sesiones telefónicas y de chat de la empresa autenticada y de sus empresas asociadas disponibles.
Sin businessId se incluyen todas las empresas disponibles. Use businessId para seleccionar una empresa y start y end para filtrar por la fecha de creación de la sesión.
curl --get https://voicebooker.de/app/api/v1/usage \
--header 'X-API-TOKEN: <su-token-api>' \
--data-urlencode 'businessId=zpjwletodo' \
--data-urlencode 'start=2026-01-01T00:00:00Z' \
--data-urlencode 'end=2026-02-01T00:00:00Z'start y end son inclusivos. Use fechas ISO 8601 que puedan analizarse. Una empresa fuera del alcance del token produce 403 Forbidden.
Ejemplo de respuesta:
[
{
"id": "xavurimeto", "businessId": "zpjwletodo", "botId": "kqrmxaveli",
"isCall": true, "direction": "inbound", "phoneNumberCaller": "+341701234567",
"phoneNumberCallee": "+34911234567", "duration": 184, "costs": 0.46,
"start": "2026-01-15T10:30:00.000Z"
}
]Listar empresas asociadas
Para integraciones de socios y revendedores, GET /partnerClients devuelve las empresas visibles conectadas con la empresa autenticada. Sus IDs pueden utilizarse como filtro businessId en el endpoint de uso.
curl --request GET \
--url https://voicebooker.de/app/api/v1/partnerClients \
--header 'X-API-TOKEN: <su-token-api>'Ejemplo de respuesta:
[
{
"id": "zpjwletodo",
"name": "Empresa de ejemplo",
"city": "Madrid",
"country": "ES"
}
]Gestionar archivos de la base de conocimientos y archivos multimedia
Las claves API pueden listar, cargar y eliminar archivos de la empresa asociada al token. Los ID de archivo están ofuscados, pero los nombres de los atributos de respuesta no lo están.
Listar archivos de la base de conocimientos
GET /knowledgeBase devuelve id, name, fileSize y tokens.
curl --request GET \
--url https://voicebooker.de/app/api/v1/knowledgeBase \
--header 'X-API-TOKEN: <su-token-api>'Cargar un archivo de la base de conocimientos
POST /knowledgeBase acepta una carga multipart con los campos file y name.
curl --request POST \
--url https://voicebooker.de/app/api/v1/knowledgeBase \
--header 'X-API-TOKEN: <su-token-api>' \
--form 'name=manual.pdf' \
--form 'file=@manual.pdf'Eliminar un archivo de la base de conocimientos
curl --request DELETE \
--url https://voicebooker.de/app/api/v1/knowledgeBase/<id-archivo> \
--header 'X-API-TOKEN: <su-token-api>'Listar y cargar archivos multimedia
GET /mediaFiles devuelve id, name y fileSize. POST /mediaFiles utiliza los mismos campos multipart.
curl --request GET \
--url https://voicebooker.de/app/api/v1/mediaFiles \
--header 'X-API-TOKEN: <su-token-api>'
curl --request POST \
--url https://voicebooker.de/app/api/v1/mediaFiles \
--header 'X-API-TOKEN: <su-token-api>' \
--form 'name=musica.mp3' \
--form 'file=@musica.mp3'Eliminar un archivo multimedia
curl --request DELETE \
--url https://voicebooker.de/app/api/v1/mediaFiles/<id-archivo> \
--header 'X-API-TOKEN: <su-token-api>'Especificación OpenAPI
openapi: 3.1.0
info:
title: VoiceBooker Partner API
version: 1.0.0
description: API para consultar empresas asociadas y datos de uso.
servers: [{url: https://voicebooker.de/app/api/v1}]
paths:
/exportBots/{botId}:
get:
summary: Exportar un bot
operationId: exportBot
security: [{apiToken: []}]
parameters:
- {name: botId, in: path, required: true, schema: {type: string}}
- {name: pretty, in: query, schema: {type: boolean, default: false}}
responses:
'200': {description: Definición del bot exportado., content: {application/json: {schema: {type: object, properties: {id: {type: string}, name: {type: string}, stages: {type: array, items: {type: object}}, settings: {type: object}, wizard: {type: object}}}}}}
'401': {$ref: '#/components/responses/Unauthorized'}
'403': {description: El bot no pertenece a la empresa del token.}
/importBots:
post:
summary: Importar un bot
operationId: importBot
security: [{apiToken: []}]
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [contents]
properties:
filename: {type: string}
contents: {oneOf: [{type: object}, {type: string}]}
overwriteBotStages: {type: boolean, default: false}
overwriteTemplates: {type: boolean, default: false}
replaceBotStages: {type: boolean, default: false}
responses:
'200': {description: Bot importado., content: {application/json: {schema: {type: object, properties: {id: {type: string}, name: {type: string}}}}}}
'401': {$ref: '#/components/responses/Unauthorized'}
/makeCall:
post:
summary: Realizar una llamada saliente
operationId: makeOutboundCall
security: [{apiToken: []}]
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [dest, botId, sipAccountId]
properties:
dest: {type: string}
botId: {type: string}
sipAccountId: {type: string}
ringTimeout: {type: integer, default: 30}
startTimeout: {type: integer, default: 0}
state: {type: object, additionalProperties: true}
responses:
'200': {description: Llamada saliente iniciada., content: {application/json: {schema: {type: object, properties: {callId: {type: string}}}}}}
'401': {$ref: '#/components/responses/Unauthorized'}
/getRecording/{id}:
get:
summary: Obtener una grabación de llamada
operationId: getCallRecording
security: [{apiToken: []}]
parameters:
- {name: id, in: path, required: true, schema: {type: string}, description: ID de la sesión de llamada.}
responses:
'200': {description: Grabación de llamada., content: {audio/mpeg: {schema: {type: string, format: binary}}}}
'401': {$ref: '#/components/responses/Unauthorized'}
'404': {description: La sesión o grabación no está disponible para este token de API.}
/usage:
get:
summary: Obtener uso
operationId: listUsage
security: [{apiToken: []}]
parameters:
- {name: businessId, in: query, schema: {type: string}, description: Empresa que se desea consultar.}
- {name: start, in: query, schema: {type: string, format: date-time}, description: Inicio inclusivo.}
- {name: end, in: query, schema: {type: string, format: date-time}, description: Fin inclusivo.}
responses:
'200': {description: Registros de uso., content: {application/json: {schema: {type: array, items: {$ref: '#/components/schemas/UsageRecord'}}}}}
'401': {$ref: '#/components/responses/Unauthorized'}
'403': {description: La empresa no está disponible para este token.}
/partnerClients:
get:
summary: Listar empresas asociadas
operationId: listPartnerClients
security: [{apiToken: []}]
responses:
'200': {description: Lista de empresas., content: {application/json: {schema: {type: array, items: {$ref: '#/components/schemas/PartnerBusiness'}}}}}
'401': {$ref: '#/components/responses/Unauthorized'}
/knowledgeBase:
get:
operationId: listKnowledgeBaseFiles
security: [{apiToken: []}]
responses:
'200': {description: Archivos de la base de conocimientos., content: {application/json: {schema: {type: array, items: {$ref: '#/components/schemas/KnowledgeBaseFile'}}}}}
'401': {$ref: '#/components/responses/Unauthorized'}
post:
operationId: uploadKnowledgeBaseFile
security: [{apiToken: []}]
requestBody: {required: true, content: {multipart/form-data: {schema: {type: object, required: [file, name], properties: {file: {type: string, format: binary}, name: {type: string}}}}}}
responses:
'200': {description: ID del archivo cargado., content: {application/json: {schema: {type: object, properties: {id: {type: string}}}}}}
'401': {$ref: '#/components/responses/Unauthorized'}
/knowledgeBase/{fileId}:
delete:
operationId: deleteKnowledgeBaseFile
security: [{apiToken: []}]
parameters: [{name: fileId, in: path, required: true, schema: {type: string}}]
responses: {'200': {description: Archivo eliminado.}, '401': {$ref: '#/components/responses/Unauthorized'}, '403': {description: Archivo fuera del alcance del token.}}
/mediaFiles:
get:
operationId: listMediaFiles
security: [{apiToken: []}]
responses: {'200': {description: Archivos multimedia., content: {application/json: {schema: {type: array, items: {$ref: '#/components/schemas/MediaFile'}}}}}, '401': {$ref: '#/components/responses/Unauthorized'}}
post:
operationId: uploadMediaFile
security: [{apiToken: []}]
requestBody: {required: true, content: {multipart/form-data: {schema: {type: object, required: [file, name], properties: {file: {type: string, format: binary}, name: {type: string}}}}}}
responses: {'200': {description: ID del archivo cargado., content: {application/json: {schema: {type: object, properties: {id: {type: string}}}}}}, '401': {$ref: '#/components/responses/Unauthorized'}}
/mediaFiles/{fileId}:
delete:
operationId: deleteMediaFile
security: [{apiToken: []}]
parameters: [{name: fileId, in: path, required: true, schema: {type: string}}]
responses: {'200': {description: Archivo eliminado.}, '401': {$ref: '#/components/responses/Unauthorized'}, '403': {description: Archivo fuera del alcance del token.}}
/bot_test_setups:
get:
operationId: listBotTests
security: [{apiToken: []}]
responses: {'200': {description: Pruebas de bots., content: {application/json: {schema: {type: array, items: {$ref: '#/components/schemas/BotTestSetup'}}}}}, '401': {$ref: '#/components/responses/Unauthorized'}}
post:
operationId: createBotTest
security: [{apiToken: []}]
requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/BotTestSetupInput'}}}}
responses: {'200': {description: Prueba creada., content: {application/json: {schema: {$ref: '#/components/schemas/BotTestSetup'}}}}, '401': {$ref: '#/components/responses/Unauthorized'}, '403': {description: Bot fuera del alcance o bots idénticos.}}
/bot_test_setups/{id}:
put:
operationId: updateBotTest
security: [{apiToken: []}]
parameters: [{name: id, in: path, required: true, schema: {type: string}}]
requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/BotTestSetupUpdate'}}}}
responses: {'200': {description: Prueba actualizada., content: {application/json: {schema: {$ref: '#/components/schemas/BotTestSetup'}}}}, '401': {$ref: '#/components/responses/Unauthorized'}, '403': {description: Bot fuera del alcance o bots idénticos.}, '404': {description: Prueba no encontrada.}}
delete:
operationId: deleteBotTest
security: [{apiToken: []}]
parameters: [{name: id, in: path, required: true, schema: {type: string}}]
responses: {'200': {description: Prueba eliminada.}, '401': {$ref: '#/components/responses/Unauthorized'}, '404': {description: Prueba no encontrada.}}
components:
securitySchemes:
apiToken: {type: apiKey, in: header, name: X-API-TOKEN}
schemas:
PartnerBusiness: {type: object, properties: {id: {type: string}, name: {type: string}}}
UsageRecord:
type: object
properties:
id: {type: string}
businessId: {type: string}
botId: {type: string, nullable: true}
isCall: {type: boolean}
direction: {type: string, enum: [inbound, outbound]}
phoneNumberCaller: {type: string, nullable: true}
phoneNumberCallee: {type: string, nullable: true}
duration: {type: integer}
costs: {type: number}
start: {type: string, format: date-time}
KnowledgeBaseFile:
type: object
properties: {id: {type: string}, name: {type: string}, fileSize: {type: integer}, tokens: {type: integer}}
MediaFile:
type: object
properties: {id: {type: string}, name: {type: string}, fileSize: {type: integer}}
BotTestSetup:
type: object
properties: {id: {type: string}, name: {type: string}, settings: {type: object, additionalProperties: true}, srcBotId: {type: string}, destBotId: {type: string}}
BotTestSetupInput:
type: object
required: [name, srcBotId, destBotId]
properties: {name: {type: string}, settings: {type: object, additionalProperties: true}, srcBotId: {type: string}, destBotId: {type: string}}
BotTestSetupUpdate:
type: object
properties: {name: {type: string}, settings: {type: object, additionalProperties: true}, srcBotId: {type: string}, destBotId: {type: string}}
responses:
Unauthorized: {description: El token falta o no es válido.}Errores HTTP
401 Unauthorized: falta el token API o no es válido.403 Forbidden: la empresa solicitada no está disponible para el token.