Acesso à API
O VoiceBooker disponibiliza acesso programático à API para integrar outras aplicações e automatizar fluxos, como obter dados de utilização, implementar bots e integrar pipelines de CI/CD.
URL base
https://voicebooker.de/app/api/v1Autenticação
Envie um token de API em cada pedido usando este header:
X-API-TOKEN: <o-seu-token-api>O token determina a empresa associada ao pedido. Mantenha-o protegido.
Exportar um bot
GET /exportBots/{botId} exporta um bot da empresa associada ao token de API. Use pretty=true para obter HJSON legível.
curl --get 'https://voicebooker.de/app/api/v1/exportBots/<bot-id>' \
--header 'X-API-TOKEN: <o-seu-token-api>' \
--data-urlencode 'pretty=true'Exemplo de resposta:
{
"name": "Assistente de receção",
"id": "kqrmxaveli",
"stages": [
{
"name": "Welcome",
"id": "mavotirenu",
"linkId": "qeluzanopi",
"template": false,
"prompt": "Cumprimente quem liga.",
"tools": [],
"functions": [],
"settings": {},
"stageConfig": [],
"x": 0,
"y": 0,
"order": 0,
"instanceSettings": {}
}
],
"settings": {},
"wizard": {}
}Importar um bot
POST /importBots importa uma definição de bot para a empresa associada ao token. Envie a definição em contents. Para HJSON, filename deve terminar em .hjson. overwriteBotStages, overwriteTemplates e replaceBotStages são parâmetros booleanos opcionais.
curl --request POST \
--url https://voicebooker.de/app/api/v1/importBots \
--header 'X-API-TOKEN: <o-seu-token-api>' \
--header 'Content-Type: application/json' \
--data '{"filename":"bot.json","contents":{"name":"Assistente de receção","settings":{},"stages":[]},"overwriteBotStages":false,"overwriteTemplates":false,"replaceBotStages":false}'Exemplo de resposta:
{
"id": "vexorimaku",
"name": "Assistente de receção",
"settings": {},
"invisible": false
}Efetuar chamadas de saída
Para efetuar uma chamada de saída, envie um pedido POST para:
https://voicebooker.de/app/api/v1/makeCallContent-Type: application/json
X-API-TOKEN: <o-seu-token-api>Exemplo de pedido:
{
"dest": "+49-351-123456789",
"botId": "kqrmxaveli",
"sipAccountId": "lupenakori",
"ringTimeout": 25,
"startTimeout": 10,
"state": {
"customerId": "zpjwletodo"
}
}| Parâmetro | Descrição |
|---|---|
dest | Número a chamar no formato E.164. |
botId | Bot utilizado na chamada. |
sipAccountId | Conta SIP utilizada; o respetivo número é mostrado ao destinatário. |
ringTimeout | Segundos durante os quais toca antes de cancelar sem resposta. Predefinição: 30 segundos. |
startTimeout | Segundos que o bot aguarda antes de começar a falar. |
state | Dados disponíveis para webhooks ou chamadas API durante a chamada, como um ID de cliente. |
A API devolve um callId:
{
"callId": "xavurimeto"
}Gerir testes de bots
Os testes de bots comparam um bot de origem/chamador com um bot de destino/respondente. Os pedidos com chave API estão limitados à empresa associada ao token; ambos os bots têm de pertencer a essa empresa.
| Método | Endpoint | Função |
|---|---|---|
GET | /bot_test_setups | Listar testes de bots. |
POST | /bot_test_setups | Criar um teste. |
PUT | /bot_test_setups/{id} | Atualizar um teste. |
DELETE | /bot_test_setups/{id} | Eliminar um teste. |
A resposta pública contém apenas id, name, settings, srcBotId e destBotId. settings pode incluir
convInitBot, maxConvTurns, asCall, startTimeout e stateUpdate. Ao atualizar, os campos omitidos são mantidos.
Obter uma gravação de chamada
GET /getRecording/{id} devolve a gravação MP3 de uma sessão de chamada. Use como id o ID da sessão de chamada devolvido por /usage. A gravação tem de ter sido ativada para a chamada.
A resposta é transmitida como audio/mpeg e pode ser guardada diretamente num ficheiro .mp3:
curl --request GET \
--url https://voicebooker.de/app/api/v1/getRecording/<id-da-sessao> \
--header 'X-API-TOKEN: <o-seu-token-api>' \
--output gravacao.mp3O endpoint devolve 404 Not Found quando a sessão ou a respetiva gravação não estão disponíveis para o token da API. Devolve 401 Unauthorized se o token da API estiver em falta ou for inválido.
Obter utilização
GET /usage devolve sessões telefónicas e de chat da empresa autenticada e das suas empresas parceiras disponíveis.
Sem businessId, são incluídas todas as empresas disponíveis. Use businessId para selecionar uma empresa e start e end para filtrar pela data de criação da sessão.
curl --get https://voicebooker.de/app/api/v1/usage \
--header 'X-API-TOKEN: <o-seu-token-api>' \
--data-urlencode 'businessId=zpjwletodo' \
--data-urlencode 'start=2026-01-01T00:00:00Z' \
--data-urlencode 'end=2026-02-01T00:00:00Z'start e end são inclusivos. Use datas ISO 8601 válidas. Uma empresa fora do âmbito do token resulta em 403 Forbidden.
Exemplo de resposta:
[
{
"id": "xavurimeto", "businessId": "zpjwletodo", "botId": "kqrmxaveli",
"isCall": true, "direction": "inbound", "phoneNumberCaller": "+351701234567",
"phoneNumberCallee": "+351211234567", "duration": 184, "costs": 0.46,
"start": "2026-01-15T10:30:00.000Z"
}
]Listar empresas parceiras
Para integrações de parceiros e revendedores, GET /partnerClients devolve as empresas visíveis ligadas à empresa autenticada. Os respetivos IDs podem ser usados com o filtro businessId do endpoint de utilização.
curl --request GET \
--url https://voicebooker.de/app/api/v1/partnerClients \
--header 'X-API-TOKEN: <o-seu-token-api>'Exemplo de resposta:
[
{
"id": "zpjwletodo",
"name": "Empresa parceira de exemplo",
"city": "Lisboa",
"country": "PT"
}
]Gerir ficheiros da base de conhecimento e ficheiros multimédia
As chaves API podem listar, carregar e eliminar ficheiros da empresa associada ao token. Os IDs dos ficheiros são ofuscados, mas os nomes dos atributos da resposta não são.
Listar ficheiros da base de conhecimento
GET /knowledgeBase devolve id, name, fileSize e tokens.
curl --request GET \
--url https://voicebooker.de/app/api/v1/knowledgeBase \
--header 'X-API-TOKEN: <o-seu-token-api>'Carregar um ficheiro da base de conhecimento
POST /knowledgeBase aceita um carregamento multipart com os campos file e name.
curl --request POST \
--url https://voicebooker.de/app/api/v1/knowledgeBase \
--header 'X-API-TOKEN: <o-seu-token-api>' \
--form 'name=manual.pdf' \
--form 'file=@manual.pdf'Eliminar um ficheiro da base de conhecimento
curl --request DELETE \
--url https://voicebooker.de/app/api/v1/knowledgeBase/<id-ficheiro> \
--header 'X-API-TOKEN: <o-seu-token-api>'Listar e carregar ficheiros multimédia
GET /mediaFiles devolve id, name e fileSize. POST /mediaFiles utiliza os mesmos campos multipart.
curl --request GET \
--url https://voicebooker.de/app/api/v1/mediaFiles \
--header 'X-API-TOKEN: <o-seu-token-api>'
curl --request POST \
--url https://voicebooker.de/app/api/v1/mediaFiles \
--header 'X-API-TOKEN: <o-seu-token-api>' \
--form 'name=musica.mp3' \
--form 'file=@musica.mp3'Eliminar um ficheiro multimédia
curl --request DELETE \
--url https://voicebooker.de/app/api/v1/mediaFiles/<id-ficheiro> \
--header 'X-API-TOKEN: <o-seu-token-api>'Especificação OpenAPI
openapi: 3.1.0
info:
title: VoiceBooker Partner API
version: 1.0.0
description: API para consultar empresas parceiras e dados de utilização.
servers: [{url: https://voicebooker.de/app/api/v1}]
paths:
/exportBots/{botId}:
get:
summary: Exportar um 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: Definição do 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: O bot não pertence à empresa do token.}
/importBots:
post:
summary: Importar um 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: Efetuar uma chamada de saída
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: Chamada de saída iniciada., content: {application/json: {schema: {type: object, properties: {callId: {type: string}}}}}}
'401': {$ref: '#/components/responses/Unauthorized'}
/getRecording/{id}:
get:
summary: Obter uma gravação de chamada
operationId: getCallRecording
security: [{apiToken: []}]
parameters:
- {name: id, in: path, required: true, schema: {type: string}, description: ID da sessão de chamada.}
responses:
'200': {description: Gravação de chamada., content: {audio/mpeg: {schema: {type: string, format: binary}}}}
'401': {$ref: '#/components/responses/Unauthorized'}
'404': {description: A sessão ou gravação não está disponível para este token da API.}
/usage:
get:
summary: Obter utilização
operationId: listUsage
security: [{apiToken: []}]
parameters:
- {name: businessId, in: query, schema: {type: string}, description: Empresa a consultar.}
- {name: start, in: query, schema: {type: string, format: date-time}, description: Início inclusivo.}
- {name: end, in: query, schema: {type: string, format: date-time}, description: Fim inclusivo.}
responses:
'200': {description: Dados de utilização., content: {application/json: {schema: {type: array, items: {$ref: '#/components/schemas/UsageRecord'}}}}}
'401': {$ref: '#/components/responses/Unauthorized'}
'403': {description: A empresa não está disponível para este token.}
/partnerClients:
get:
summary: Listar empresas parceiras
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: Ficheiros da base de conhecimento., 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 do ficheiro carregado., 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: Ficheiro eliminado.}, '401': {$ref: '#/components/responses/Unauthorized'}, '403': {description: Ficheiro fora do âmbito do token.}}
/mediaFiles:
get:
operationId: listMediaFiles
security: [{apiToken: []}]
responses: {'200': {description: Ficheiros multimédia., 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 do ficheiro carregado., 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: Ficheiro eliminado.}, '401': {$ref: '#/components/responses/Unauthorized'}, '403': {description: Ficheiro fora do âmbito do token.}}
/bot_test_setups:
get:
operationId: listBotTests
security: [{apiToken: []}]
responses: {'200': {description: Testes 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: Teste criado., content: {application/json: {schema: {$ref: '#/components/schemas/BotTestSetup'}}}}, '401': {$ref: '#/components/responses/Unauthorized'}, '403': {description: Bot fora do âmbito ou 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: Teste atualizado., content: {application/json: {schema: {$ref: '#/components/schemas/BotTestSetup'}}}}, '401': {$ref: '#/components/responses/Unauthorized'}, '403': {description: Bot fora do âmbito ou bots idênticos.}, '404': {description: Teste não encontrado.}}
delete:
operationId: deleteBotTest
security: [{apiToken: []}]
parameters: [{name: id, in: path, required: true, schema: {type: string}}]
responses: {'200': {description: Teste eliminado.}, '401': {$ref: '#/components/responses/Unauthorized'}, '404': {description: Teste não encontrado.}}
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: O token está em falta ou é inválido.}Erros HTTP
401 Unauthorized: o token de API está em falta ou é inválido.403 Forbidden: a empresa pedida não está disponível para este token.