{"openapi":"3.1.0","info":{"title":"Bolrach Calling API","version":"1.0.0","description":"Internet calls to a verified business, with one queue, callbacks and signed webhooks.","contact":{"url":"https://docs.bolrach.com/calling"}},"servers":[{"url":"https://calling.bolrach.com"}],"security":[{"authvio":[]}],"components":{"securitySchemes":{"authvio":{"type":"oauth2","description":"An Authvio access token from the client-credentials grant, for the audience https://calling.bolrach.com. The client must be registered with Bolrach Calling for your organisation.","flows":{"clientCredentials":{"tokenUrl":"https://id.authv.io/oauth2/token","scopes":{"calls:read":"Read calls, queues, settings and usage","calls:admin":"Change settings and queues","webhooks:manage":"Manage webhook endpoints"}}}}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"string","description":"A stable, lower snake case code."},"message":{"type":"string"},"statusCode":{"type":"integer"},"details":{"type":"object"},"request_id":{"type":"string"}},"required":["error","message","statusCode"]},"Call":{"type":"object","properties":{"call_id":{"type":"string","format":"uuid"},"org_id":{"type":"string","format":"uuid"},"state":{"type":"string","enum":["queued","offered","connected","ended","abandoned","rejected","callback_missed"]},"mode":{"type":"string","enum":["wait","callback"]},"channel":{"type":"string","enum":["internet","pstn"]},"created_at":{"type":"string","format":"date-time"},"connected_at":{"type":["string","null"],"format":"date-time"},"ended_at":{"type":["string","null"],"format":"date-time"},"end_reason":{"type":["string","null"]},"caller":{"type":["string","null"],"description":"Your stable reference for this caller (cr_…). The same person has a different reference for every client."}}},"CallerPolicy":{"type":"object","properties":{"min_level":{"type":"string","enum":["account","phone","identity","customers","custom"]},"calls_per_hour":{"type":"integer","minimum":1,"maximum":3},"calls_per_day":{"type":"integer","minimum":1,"maximum":10},"rule":{"type":"object","description":"For min_level custom: an AND/OR tree of conditions on verified attributes."}},"required":["min_level"]}}},"paths":{"/v1/orgs/{org}/public":{"get":{"operationId":"publicCard","summary":"What a visitor sees before calling (no sign-in)","security":[],"parameters":[{"name":"org","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Your organisation’s id. A client can act only on its own."}],"responses":{"200":{"description":"Display name, minimum caller level, open now and next opening, the recording notice, whether the business is Authvio-verified (`verified`; an unverified business never takes calls), whether the line is taking calls, and `help` ({ request_url, chat_url }, or null when the business does not answer through Help)."},"404":{"description":"No such resource, or it belongs to another organisation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/whoami":{"get":{"operationId":"whoami","summary":"Who the API thinks you are","responses":{"200":{"description":"Your client id, organisation, scopes and rate tier."},"401":{"description":"No token, or one Authvio did not issue for this audience.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The client is not registered, is disabled, or lacks the scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/orgs/{org}/settings":{"get":{"operationId":"getSettings","summary":"Your organisation’s call settings","parameters":[{"name":"org","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Your organisation’s id. A client can act only on its own."}],"security":[{"authvio":["calls:read"]}],"responses":{"200":{"description":"Settings."},"401":{"description":"No token, or one Authvio did not issue for this audience.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The client is not registered, is disabled, or lacks the scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another organisation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"operationId":"patchSettings","summary":"Change some settings","parameters":[{"name":"org","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Your organisation’s id. A client can act only on its own."}],"security":[{"authvio":["calls:admin"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"caller_policy":{"$ref":"#/components/schemas/CallerPolicy"},"hours":{"type":["object","null"],"description":"A time zone and weekly windows, e.g. { tz: \"Africa/Lagos\", windows: [{ days: [1,2,3,4,5], from: \"08:00\", to: \"17:00\" }] }. Null means always open."},"recording_mode":{"type":"string","enum":["off","ask","always"]},"transcription_mode":{"type":"string","enum":["openai","on_box"]},"notice_text":{"type":["string","null"],"maxLength":300},"retention_days":{"type":"integer","minimum":30,"maximum":365},"max_queue":{"type":"integer","minimum":1,"maximum":1000},"mask_ip_addresses":{"type":"boolean","description":"Always route calls through Bolrach, so callers never see each other’s IP address."}}}}}},"responses":{"200":{"description":"The settings after the change."},"400":{"description":"A field is missing or out of range; details.field names it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No token, or one Authvio did not issue for this audience.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The client is not registered, is disabled, or lacks the scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another organisation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/orgs/{org}/queues":{"get":{"operationId":"listQueues","summary":"Your queues, with how many people answer and wait","parameters":[{"name":"org","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Your organisation’s id. A client can act only on its own."}],"security":[{"authvio":["calls:read"]}],"responses":{"200":{"description":"Queues."},"401":{"description":"No token, or one Authvio did not issue for this audience.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The client is not registered, is disabled, or lacks the scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another organisation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/orgs/{org}/queues/{name}":{"put":{"operationId":"putQueue","summary":"Create or change a queue","security":[{"authvio":["calls:admin"]}],"parameters":[{"name":"org","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Your organisation’s id. A client can act only on its own."},{"name":"name","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z0-9][a-z0-9-]{0,39}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"label":{"type":"string","maxLength":80},"priority":{"type":"integer"},"caller_policy":{"$ref":"#/components/schemas/CallerPolicy"}},"required":["label"]}}}},"responses":{"200":{"description":"The queue."},"400":{"description":"A field is missing or out of range; details.field names it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No token, or one Authvio did not issue for this audience.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The client is not registered, is disabled, or lacks the scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another organisation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/orgs/{org}/calls":{"get":{"operationId":"listCalls","summary":"Your calls, newest first","security":[{"authvio":["calls:read"]}],"parameters":[{"name":"org","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Your organisation’s id. A client can act only on its own."},{"name":"from","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","schema":{"type":"string","format":"date-time"},"description":"At most 31 days after from."},{"name":"state","in":"query","schema":{"type":"string","enum":["queued","offered","connected","ended","abandoned","rejected","callback_missed"]}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}},{"name":"before","in":"query","schema":{"type":"string","format":"date-time"},"description":"next_before from the previous page."}],"responses":{"200":{"description":"A page of calls.","content":{"application/json":{"schema":{"type":"object","properties":{"calls":{"type":"array","items":{"$ref":"#/components/schemas/Call"}},"next_before":{"type":["string","null"]}}}}}},"400":{"description":"A field is missing or out of range; details.field names it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No token, or one Authvio did not issue for this audience.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The client is not registered, is disabled, or lacks the scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another organisation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/orgs/{org}/calls/{id}":{"get":{"operationId":"getCall","summary":"One call","security":[{"authvio":["calls:read"]}],"parameters":[{"name":"org","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Your organisation’s id. A client can act only on its own."},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Call"}}}},"401":{"description":"No token, or one Authvio did not issue for this audience.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The client is not registered, is disabled, or lacks the scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another organisation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/orgs/{org}/usage":{"get":{"operationId":"usage","summary":"Metered use by day","security":[{"authvio":["calls:read"]}],"parameters":[{"name":"org","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Your organisation’s id. A client can act only on its own."},{"name":"from","in":"query","schema":{"type":"string","format":"date"}},{"name":"to","in":"query","schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Calls, talk, recording and transcript seconds, summaries and ring-out seconds per day."},"400":{"description":"A field is missing or out of range; details.field names it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No token, or one Authvio did not issue for this audience.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The client is not registered, is disabled, or lacks the scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another organisation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/webhook-endpoints":{"get":{"operationId":"listEndpoints","summary":"Your webhook endpoints","security":[{"authvio":["webhooks:manage"]}],"responses":{"200":{"description":"Endpoints, without their secrets."},"401":{"description":"No token, or one Authvio did not issue for this audience.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The client is not registered, is disabled, or lacks the scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"createEndpoint","summary":"Add an endpoint; the signing secret is shown once","security":[{"authvio":["webhooks:manage"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri","description":"A public https address."},"events":{"type":"array","items":{"type":"string","enum":["call.queued","call.offered","call.answered","call.transferred","call.participant_added","call.participant_left","call.ended","call.abandoned","call.rejected","callback.requested","callback.rang","callback.missed","recording.started","recording.ready","transcript.ready","summary.ready","ringout.completed"]}},"description":{"type":"string","maxLength":200}},"required":["url","events"]}}}},"responses":{"201":{"description":"The endpoint and its secret (whsec_…)."},"400":{"description":"A field is missing or out of range; details.field names it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No token, or one Authvio did not issue for this audience.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The client is not registered, is disabled, or lacks the scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The resource is in a state that does not allow this.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/webhook-endpoints/{id}":{"delete":{"operationId":"deleteEndpoint","summary":"Stop sending to an endpoint","security":[{"authvio":["webhooks:manage"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Deleted."},"401":{"description":"No token, or one Authvio did not issue for this audience.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The client is not registered, is disabled, or lacks the scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another organisation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/webhook-endpoints/{id}/rotate":{"post":{"operationId":"rotateEndpoint","summary":"A new signing secret; the old one also signs for 24 hours","security":[{"authvio":["webhooks:manage"]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The new secret."},"401":{"description":"No token, or one Authvio did not issue for this audience.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The client is not registered, is disabled, or lacks the scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such resource, or it belongs to another organisation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"webhooks":{"call.queued":{"post":{"summary":"call.queued, signed in the calling-signature header","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"type":{"const":"call.queued"},"created":{"type":"integer"},"data":{"type":"object","properties":{"call_id":{"type":"string"},"state":{"type":"string"},"caller":{"type":["string","null"]}}}}}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"call.offered":{"post":{"summary":"call.offered, signed in the calling-signature header","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"type":{"const":"call.offered"},"created":{"type":"integer"},"data":{"type":"object","properties":{"call_id":{"type":"string"},"state":{"type":"string"},"caller":{"type":["string","null"]}}}}}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"call.answered":{"post":{"summary":"call.answered, signed in the calling-signature header","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"type":{"const":"call.answered"},"created":{"type":"integer"},"data":{"type":"object","properties":{"call_id":{"type":"string"},"state":{"type":"string"},"caller":{"type":["string","null"]}}}}}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"call.transferred":{"post":{"summary":"call.transferred, signed in the calling-signature header","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"type":{"const":"call.transferred"},"created":{"type":"integer"},"data":{"type":"object","properties":{"call_id":{"type":"string"},"state":{"type":"string"},"caller":{"type":["string","null"]}}}}}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"call.participant_added":{"post":{"summary":"call.participant_added, signed in the calling-signature header","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"type":{"const":"call.participant_added"},"created":{"type":"integer"},"data":{"type":"object","properties":{"call_id":{"type":"string"},"state":{"type":"string"},"caller":{"type":["string","null"]}}}}}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"call.participant_left":{"post":{"summary":"call.participant_left, signed in the calling-signature header","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"type":{"const":"call.participant_left"},"created":{"type":"integer"},"data":{"type":"object","properties":{"call_id":{"type":"string"},"state":{"type":"string"},"caller":{"type":["string","null"]}}}}}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"call.ended":{"post":{"summary":"call.ended, signed in the calling-signature header","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"type":{"const":"call.ended"},"created":{"type":"integer"},"data":{"type":"object","properties":{"call_id":{"type":"string"},"state":{"type":"string"},"caller":{"type":["string","null"]}}}}}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"call.abandoned":{"post":{"summary":"call.abandoned, signed in the calling-signature header","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"type":{"const":"call.abandoned"},"created":{"type":"integer"},"data":{"type":"object","properties":{"call_id":{"type":"string"},"state":{"type":"string"},"caller":{"type":["string","null"]}}}}}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"call.rejected":{"post":{"summary":"call.rejected, signed in the calling-signature header","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"type":{"const":"call.rejected"},"created":{"type":"integer"},"data":{"type":"object","properties":{"call_id":{"type":"string"},"state":{"type":"string"},"caller":{"type":["string","null"]}}}}}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"callback.requested":{"post":{"summary":"callback.requested, signed in the calling-signature header","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"type":{"const":"callback.requested"},"created":{"type":"integer"},"data":{"type":"object","properties":{"call_id":{"type":"string"},"state":{"type":"string"},"caller":{"type":["string","null"]}}}}}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"callback.rang":{"post":{"summary":"callback.rang, signed in the calling-signature header","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"type":{"const":"callback.rang"},"created":{"type":"integer"},"data":{"type":"object","properties":{"call_id":{"type":"string"},"state":{"type":"string"},"caller":{"type":["string","null"]}}}}}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"callback.missed":{"post":{"summary":"callback.missed, signed in the calling-signature header","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"type":{"const":"callback.missed"},"created":{"type":"integer"},"data":{"type":"object","properties":{"call_id":{"type":"string"},"state":{"type":"string"},"caller":{"type":["string","null"]}}}}}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"recording.started":{"post":{"summary":"recording.started, signed in the calling-signature header","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"type":{"const":"recording.started"},"created":{"type":"integer"},"data":{"type":"object","properties":{"call_id":{"type":"string"},"state":{"type":"string"},"caller":{"type":["string","null"]}}}}}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"recording.ready":{"post":{"summary":"recording.ready, signed in the calling-signature header","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"type":{"const":"recording.ready"},"created":{"type":"integer"},"data":{"type":"object","properties":{"call_id":{"type":"string"},"state":{"type":"string"},"caller":{"type":["string","null"]}}}}}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"transcript.ready":{"post":{"summary":"transcript.ready, signed in the calling-signature header","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"type":{"const":"transcript.ready"},"created":{"type":"integer"},"data":{"type":"object","properties":{"call_id":{"type":"string"},"state":{"type":"string"},"caller":{"type":["string","null"]}}}}}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"summary.ready":{"post":{"summary":"summary.ready, signed in the calling-signature header","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"type":{"const":"summary.ready"},"created":{"type":"integer"},"data":{"type":"object","properties":{"call_id":{"type":"string"},"state":{"type":"string"},"caller":{"type":["string","null"]}}}}}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}},"ringout.completed":{"post":{"summary":"ringout.completed, signed in the calling-signature header","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"type":{"const":"ringout.completed"},"created":{"type":"integer"},"data":{"type":"object","properties":{"call_id":{"type":"string"},"state":{"type":"string"},"caller":{"type":["string","null"]}}}}}}}},"responses":{"200":{"description":"Any 2xx acknowledges the delivery."}}}}}}