Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: Didlogic Com Calls API
version: 1.0.0
description: 'Operations tagged Calls across 2 of this provider''s published API definitions: didlogic-com-public-api-openapi.yaml, didlogic-com-openapi.yml. Each path carries the servers of the definition it was published in.'
servers:
- url: https://app.didlogic.com
description: Production
tags:
- name: Calls
x-version: v1
paths:
/api/v1/calls:
get:
summary: Retrieve call detail records
operationId: calls_show
description: 'Retrieve a list of call detail records (CDR) with filtering and pagination options.
**Important notes:**
- Results can be filtered by date range, call type, phone numbers, SIP account, AMD status and hangup cause
- Supports both JSON and CSV export formats
- Use pagination for large result sets
- Statistics include total count, duration, and cost
**When to use:**
- Generating call history reports
- Analyzing call patterns and costs
- Exporting billing data
- Monitoring SIP account usage
See also: calls_statistics, totals for the same filters.'
tags:
- Calls
security:
- BearerAuth: []
parameters:
- name: type
in: query
description: Filter by call type (sip = outbound SIP calls, web = outbound web calls, api = outbound API calls, incoming = received calls)
required: false
schema:
type: string
enum:
- sip
- web
- incoming
- api
example: sip
- name: missed
in: query
description: Include missed calls in results (0 = exclude, 1 = include)
required: false
schema:
type: string
enum:
- '0'
- '1'
example: '1'
- name: from_search
in: query
description: Filter by caller phone number (partial match supported)
required: false
schema:
type: string
example: '1221'
- name: to_search
in: query
description: Filter by destination phone number (partial match supported)
required: false
schema:
type: string
example: '1800'
- name: amd_status
in: query
description: 'Return only calls with this answering machine detection (AMD) verdict, matched ignoring case:
- `machine` — AMD detected an answering machine
- `human` — AMD detected a person
- `notsure` — AMD ran but could not tell a machine from a person, for example on silence, unclear audio or a timeout
Only outbound calls carry a verdict, so `type=incoming` with this filter returns no calls.
A value that no call has returns no calls.
A malformed value, for example one with `|` or non-ASCII characters, is ignored, as if the parameter were not sent.
'
required: false
schema:
type: string
example: machine
- name: hangup_cause
in: query
description: 'Return only calls that ended this way, matched ignoring case:
- `AMD_MACHINE` — AMD detected an answering machine; takes precedence over the other values
- `NORMAL_CLEARING` — the call was answered
- `NO_ANSWER` — nobody answered, including calls the caller cancelled before an answer
- `BUSY` — the called party was busy
- `FAILED` — the call could not be connected
A value that no call has returns no calls.
A malformed value, for example one with `|` or non-ASCII characters, is ignored, as if the parameter were not sent.
'
required: false
schema:
type: string
enum:
- AMD_MACHINE
- NORMAL_CLEARING
- NO_ANSWER
- BUSY
- FAILED
example: AMD_MACHINE
- name: filter
in: query
description: Filter by phone number (alphanumeric, spaces, hyphens, underscores)
required: false
schema:
type: string
pattern: ^[a-zA-Z0-9 \-_]+$
example: '+14155551234'
- name: sip_account
in: query
description: SIP account name from sipaccounts_index
required: false
schema:
type: string
example: '36465'
- name: from
in: query
description: Start date for filtering (inclusive). Format YYYY-MM-DD
required: false
schema:
type: string
format: date
example: '2025-01-01'
- name: to
in: query
description: End date for filtering (inclusive). Format YYYY-MM-DD
required: false
schema:
type: string
format: date
example: '2025-01-31'
- name: all
in: query
description: Return all records (ignores pagination). Use with caution for large datasets.
required: false
schema:
type: boolean
default: false
example: false
- name: page
in: query
description: Page number to retrieve (1-based)
required: false
schema:
type: integer
minimum: 1
default: 1
example: 1
- name: per_page
in: query
description: Number of records per page (max 1000)
required: false
schema:
type: integer
minimum: 1
maximum: 1000
default: 100
example: 100
responses:
'200':
description: Successfully retrieved CDR records
content:
application/json:
schema:
$ref: '#/components/schemas/CdrListResponse'
example:
calls:
- timestamp: '2024-01-15T10:30:00Z'
type: sip
amount: 0.05
duration: 120
from: '100'
to: '+14155551234'
destination_name: United States
sip_account: john@sip.provider.com
per_minute: 0.025
amd_status: machine
amd_score: 93
hangup_cause: AMD_MACHINE
- timestamp: '2024-01-15T10:30:00Z'
type: incoming
amount: 0.02
duration: 90
from: '+14155551234'
to: '100'
did_number: '+18005551234'
amd_status: null
amd_score: null
hangup_cause: NORMAL_CLEARING
- timestamp: '2024-01-15T10:35:00Z'
type: incoming
amount: 0.0
duration: 0
from: '+14155559999'
to: '100'
did_number: '+18005551234'
amd_status: null
amd_score: null
hangup_cause: NO_ANSWER
- timestamp: '2024-01-15T10:30:00Z'
type: web
amount: 0.03
duration: 60
from: web_user_123
to: '+14155551234'
amd_status: null
amd_score: null
hangup_cause: NORMAL_CLEARING
pagination:
page: 1
per_page: 10
total_pages: 325
total_records: 3248
text/csv:
schema:
type: string
description: 'CSV formatted call detail records.
Columns: Date, Time, SIP ID, Type, From, To, Destination name, Duration, DID inc. fee, Termination, Charge, Balance, AMD Status, AMD Score, Hangup Cause
`AMD Status` and `AMD Score` are omitted when `type=incoming`. `AMD Status`, `AMD Score` and `Hangup Cause` carry the values of `amd_status`, `amd_score` and `hangup_cause` in the JSON response; an empty cell stands for `null`.
'
example: 'Date,Time,SIP ID,Type,From,To,Destination name,Duration,DID inc. fee,Termination,Charge,Balance,AMD Status,AMD Score,Hangup Cause
01/15/24,10:30:00 am,john@sip.com,SIP TERM,100,+14155551234,United States,120,0.00000,0.02500,0.05000,99.95000,machine,93,AMD_MACHINE
'
'401':
description: Unauthorized - Invalid or missing authentication token
content:
application/json:
schema:
type: object
properties:
error:
type: string
required:
- error
example:
error: Unauthorized
'403':
description: Forbidden - Valid token but user is blocked or inactive
content:
application/json:
schema:
type: object
properties:
error:
type: string
required:
- error
example:
error: Access denied
servers:
- url: https://app.didlogic.com
description: Production
/api/v1/calls/statistics:
get:
summary: Get call statistics
description: 'Retrieve aggregated call statistics including totals and counts.
**Response includes:**
- Placed calls: total cost and count
- Received calls: total cost and count
- Missed calls: count only
- All calls: combined total cost and count
Rows: calls_show.'
tags:
- Calls
operationId: calls_statistics
security:
- BearerAuth: []
parameters:
- name: from
in: query
required: false
schema:
type: string
example: '2024-01-01'
description: Start date for filtering (YYYY-MM-DD)
- name: to
in: query
required: false
schema:
type: string
example: '2024-12-31'
description: End date for filtering (YYYY-MM-DD)
- name: sipfriend
in: query
required: false
schema:
type: string
example: '39452'
example: '39452'
description: SIP account name from sipaccounts_index
- name: search
in: query
required: false
schema:
type: integer
example: 1234567890
description: Search term for filtering calls
- name: amd_status
in: query
required: false
schema:
type: string
example: human
description: "Count only calls with this answering machine detection (AMD) verdict, matched ignoring case:\n- `machine` — AMD detected an answering machine\n- `human` — AMD detected a person\n- `notsure` — AMD ran but could not tell a machine from a person, for example on silence,\n unclear audio or a timeout\n\nOnly outbound calls carry a verdict, so under this filter the received and missed counts\nand the received total are 0. A value that no call has gives zero counts and totals.\nA malformed value, for example one with `|` or non-ASCII characters, is ignored,\nas if the parameter were not sent.\n"
- name: hangup_cause
in: query
required: false
schema:
type: string
enum:
- AMD_MACHINE
- NORMAL_CLEARING
- NO_ANSWER
- BUSY
- FAILED
example: NORMAL_CLEARING
description: 'Count only calls that ended this way, matched ignoring case:
- `AMD_MACHINE` — AMD detected an answering machine; takes precedence over the other values
- `NORMAL_CLEARING` — the call was answered
- `NO_ANSWER` — nobody answered, including calls the caller cancelled before an answer
- `BUSY` — the called party was busy
- `FAILED` — the call could not be connected
A value that no call has gives zero counts and totals.
A malformed value, for example one with `|` or non-ASCII characters, is ignored,
as if the parameter were not sent.
'
responses:
'200':
description: returns call statistics
content:
application/json:
schema:
type: object
properties:
placed:
type: object
properties:
total:
type: string
example: $15.0000
description: Total cost of placed calls
count:
type: integer
example: 0
description: Number of placed calls
required:
- total
- count
description: Statistics for placed (outgoing) calls
received:
type: object
properties:
total:
type: string
example: $20.0000
description: Total cost of received calls
count:
type: integer
example: 0
description: Number of received calls
required:
- total
- count
description: Statistics for received (incoming) calls
missed:
type: object
properties:
count:
type: integer
example: 0
description: Number of missed calls
required:
- count
description: Statistics for missed calls
all:
type: object
properties:
total:
type: string
example: $35.0000
description: Total cost of all calls
count:
type: integer
example: 0
description: Total number of all calls
required:
- total
- count
description: Combined statistics for all calls
required:
- placed
- received
- missed
- all
example:
placed:
total: $15.0000
count: 0
received:
total: $20.0000
count: 0
missed:
count: 0
all:
total: $35.0000
count: 0
'403':
description: returns forbidden error
content:
application/json:
schema:
type: object
properties:
error:
type: string
required:
- error
example:
error: Unauthorized
servers:
- url: https://app.didlogic.com
description: Production
/api/v1/calls/recording/{callid}:
get:
summary: Download call recordings
description: 'Retrieves a single call recording file by its Call ID.
> ⚠️ **Important:** this endpoint is a fallback mechanism designed for
> recovering missing recordings when a delivery webhook failed or its
> short-lived URL expired. For production workflows, always use
> Call Recording Webhooks
> instead of polling this API.
The Call ID is all you need — the recording is searched for across the
whole period your account retains recordings, so a client that stored only
the Call ID can download the file.
### Rate limits & quotas
To prevent system overload, strict limits are enforced per user:
- **Request frequency:** max 1 request per second.
- **Recording lookups:** max 1 lookup per minute.
The per-minute quota is consumed by every search query, regardless of
whether a recording is found or the request returns `404 Not Found` —
searching for the file is the operation that costs resources.'
tags:
- Calls
operationId: calls_recording
security:
- BearerAuth: []
parameters:
- name: callid
in: path
required: true
schema:
type: string
example: raw.call-id-1@example.com
description: Call ID of the recording (required). Inbound callids are the encrypted webhook value.
responses:
'302':
description: Redirects to a short-lived AWS S3 pre-signed URL for the recording (`.mp3`). Follow the redirect — for example with `curl -L` — to download the file.
content:
text/html:
schema:
type: string
example: ''
'403':
description: The API token is missing or invalid, or call recording is not enabled for this account.
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/Error'
- type: object
properties:
error:
type: string
required:
- error
examples:
Unauthorized:
value:
error: Unauthorized
Recording disabled:
value:
errors:
base:
- call recording is not enabled for your account
'404':
description: No recording matches this Call ID. The call does not exist, belongs to another account, or is older than the account's recording retention period.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
errors:
base:
- data not found
'429':
description: A rate limit was exceeded — either the one-request-per-second frequency limit or the one-lookup-per-minute quota. Carries `Retry-After` with the seconds to wait, alongside `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset`.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
examples:
Lookup quota exceeded:
value:
errors:
base:
- Recording lookup limit reached. Maximum 1 lookup per minute is allowed. Please use a webhook for production workflows.
Too many requests:
value:
errors:
base:
- Recording lookup limit reached. Maximum 1 request per second is allowed.
servers:
- url: https://app.didlogic.com
description: Production
/api/v1/call_price:
get:
summary: Quote the price of an outbound call
description: 'What a call from one of your SIP accounts to `b_number`, presenting `a_number` as the caller ID,
will be billed: the destination name, the per-minute price and the billing increment.
The quote replays what the platform does to the call before it is billed: the SIP account''s
destination rewrite, its caller-ID restrictions, routing rules and caller-ID overrides. It then
rates the call with the same code billing uses: exact prices, origin-based rates and markup
included.
**Not modelled:**
- the carrier (trunk) chosen for the call, which can change the increment and, through the
caller ID it presents, the price;
- blocklists and allowlists: a destination that would be refused is still quoted;
- where the platform picks a caller ID at random, the first candidate is used.
Send `b_number` in E.164 (country code first). A national number is quoted only when the SIP
account has a rewrite rule that turns it into E.164.'
tags:
- Calls
operationId: call_price_show
security:
- BearerAuth: []
parameters:
- name: a_number
in: query
required: true
schema:
type: string
example: '+13125550100'
example: '+13125550100'
description: Caller ID the call presents; up to 5 digits means anonymous
- name: b_number
in: query
required: true
schema:
type: string
example: '+447911123456'
example: '+447911123456'
description: Number to call, E.164 (a leading + is accepted)
- name: sipaccount
in: query
required: true
schema:
type: string
example: '100001'
example: '100001'
description: SIP account name from sipaccounts_index, the account placing the call
responses:
'200':
description: The price and increment the call will be billed at
content:
application/json:
schema:
type: object
properties:
destination_name:
type:
- string
- 'null'
example: United Kingdom - O2
description: Destination as listed in your price list; null for an exact price only
price:
type: number
format: float
example: 0.056
description: Price per minute in USD
increment:
type: object
properties:
initial:
type: integer
example: 30
description: Seconds billed for the first block
unit:
type: integer
example: 1
description: Seconds per block after the first
required:
- initial
- unit
required:
- destination_name
- price
- increment
example:
destination_name: United Kingdom - O2
price: 0.056
increment:
initial: 30
unit: 1
'404':
description: No SIP account of yours has that name
content:
application/json:
schema:
type: object
properties:
error:
type: object
properties:
code:
type: string
message:
type: string
details:
type: array
items: {}
required:
- code
- message
- details
required:
- error
example:
error:
code: sipaccount_not_found
message: no SIP account with that name
details: []
'422':
description: The destination has no price for this SIP account
content:
application/json:
schema:
type: object
properties:
error:
type: object
properties:
code:
type: string
message:
type: string
details:
type: array
items:
type: object
properties:
code:
type: string
message:
type: string
field:
type: string
required:
- code
- message
- field
required:
- code
- message
- details
required:
- error
example:
error:
code: validation_failed
message: The request contains invalid parameters
details:
- code: destination_not_priced
message: the destination has no price
field: b_number
servers:
- url: https://app.didlogic.com
description: Production
components:
schemas:
Error:
type: object
description: Standard error response. `errors` maps a field name (or `base` for errors not tied to a specific field) to an array of human-readable messages.
required:
- errors
properties:
errors:
type: object
additionalProperties:
type: array
items:
type: string
example:
base:
- data not found
BaseCdr:
type: object
description: Base call detail record with common fields
required:
- timestamp
- type
- amount
- duration
- from
- to
- amd_status
- amd_score
- hangup_cause
properties:
timestamp:
type: string
format: date-time
description: Call start time in ISO 8601 format (UTC)
example: '2024-01-15T10:30:00Z'
type:
type: string
description: Call type
enum:
- sip
- incoming
- web
- api
example: sip
amount:
type: number
format: float
description: Call cost (charged/credited amount)
example: 0.05
duration:
type: integer
description: Call duration in seconds. 0 = missed call
minimum: 0
example: 120
from:
type: string
description: Caller number/identifier
example: '100'
to:
type: string
description: Destination number/identifier
example: '+14155551234'
amd_status:
type:
- string
- 'null'
description: 'Answering machine detection (AMD) verdict of an outbound call:
- `machine` — AMD detected an answering machine
- `human` — AMD detected a person
- `notsure` — AMD ran but could not tell a machine from a person, for example on silence, unclear audio or a timeout
`null` when no AMD result was recorded for the call, which is always the case for incoming calls.
'
example: machine
amd_score:
type:
- integer
- 'null'
description: 'Probability that an answering machine picked up, as a percentage from 0 to 100, as reported by the AMD detector.
It is not a confidence in `amd_status`, and it carries no meaning when `amd_status` is `notsure`.
`null` whenever `amd_status` is `null`.
'
example: 93
hangup_cause:
type:
- string
- 'null'
enum:
- AMD_MACHINE
- NORMAL_CLEARING
- NO_ANSWER
- BUSY
- FAILED
- null
description: 'How the call ended:
- `AMD_MACHINE` — AMD detected an answering machine; takes precedence over the other values
- `NORMAL_CLEARING` — the call was answered
- `NO_ANSWER` — nobody answered, including calls the caller cancelled before an answer
- `BUSY` — the called party was busy
- `FAILED` — the call could not be connected
`null` for calls made before hangup causes were recorded, for calls whose outcome the platform did not recognise,
and for API calls that never reached the destination number.
'
example: NORMAL_CLEARING
SipCdr:
allOf:
- $ref: '#/components/schemas/BaseCdr'
- type: object
description: Outbound SIP call detail record
properties:
destination_name:
type: string
description: Destination country/region name
example: United States
sip_account:
type:
- string
- 'null'
description: SIP account used for the call
example: john@sip.provider.com
per_minute:
type:
- number
- 'null'
format: float
description: Per-minute rate. null = unknown, 0 = free
example: 0.025
Pagination:
type: object
description: Pagination metadata for list responses
required:
- page
- per_page
- total_pages
- total_records
properties:
page:
type: integer
description: Current page number (1-based)
minimum: 1
example: 1
per_page:
type: integer
description: Number of records per page
minimum: 1
example: 10
total_pages:
type: integer
description: Total number of pages available
minimum: 0
example: 325
total_records:
type: integer
description: Total number of records
minimum: 0
example: 3248
WebCdr:
allOf:
- $ref: '#/components/schemas/BaseCdr'
- type: object
description: Web call detail record (no additional fields)
CdrListResponse:
type: object
description: Paginated list of CDR records
required:
- calls
- pagination
properties:
calls:
type: array
description: Array of call detail records
items:
oneOf:
- $ref: '#/components/schemas/SipCdr'
- $ref: '#/components/schemas/IncomingCdr'
- $ref: '#/components/schemas/WebCdr'
pagination:
$ref: '#/components/schemas/Pagination'
IncomingCdr:
allOf:
- $ref: '#/components/schemas/BaseCdr'
- type: object
description: Incoming call detail record
properties:
did_number:
type:
- string
- 'null'
description: DID number that received the call (purchased virtual number)
example: '+18005551234'
securitySchemes:
BearerAuth:
type: http
scheme: bearer
description: Authenticate API requests via API key like "Bearer YOUR_TOKEN"
x-refined-from:
- didlogic-com-public-api-openapi.yaml
- didlogic-com-openapi.yml