NUACOM API

Calls

Call Logs

Call logs are the account's call history: one row per call leg with direction, numbers, extensions, queue, duration, cost, whether a recording exists, and the notes and tags attached to it. This group is the list itself; recordings, notes, tags and reports have their own groups and are described here because the portal always uses them together.

Workflow (what the portal does)

  1. The list: GET /v2/call-log is the call history grid. Filters (all optional, comma-separated where several values are allowed):
    • from_date / to_date as Y-m-d or Y-m-d H:i:s, read in the X-Timezone you send (or the user's profile timezone). Send both; with only one, the last month is used.
    • type: incoming, outgoing, missed, unanswered, plus include_voicemail, include_playback, include_internal, group_missed_calls.
    • numbers, incoming_number, outgoing_number, extensions, queues, tags (tag ids), notes (substring), search_for (contact or extension name, or a number), duration_above / duration_under, billsec_above / billsec_under (seconds), has_transcriptions, transcription.
    • page, per_page (default 25, no maximum), sort_by (call_date, from, from_ext, to, to_ext), sort_dir (DESC by default).
    • The response is {"_embedded": [rows], "_links": {…}, "page_count": <current page>, "page_size", "total_items"}. Lists of selectable extensions, numbers and queues for the user come with it in _selectable.
  2. One call: GET /v2/call-logs/{callId} by call_id (or call_unique_id) returns the legs of that call as an array.
  3. Recording: build the URL yourself from the row, GET /v3/call-recording/{callId} with the row's call_id; format picks MP3 (default), OGG or WAV, start/end trim it. Deleting is admin-only: DELETE /v2/call-recording/{callUniqueId}.
  4. Notes and tags on a call: read them with GET /v2/call-notes?callIDs[]=… and GET /v2/call-tags?callIDs[]=…, passing the row's call_id, sip_call_id and original_sip_call_id together. Add a note with POST /v3/call-notes (callId, note), assign a tag with POST /v2/add-call-tag (call_id, tag_info_id); the tag catalogue is GET /v3/call-tags.
  5. Transcript: GET /v2/speech-to-text/{callUniqueId} when the account has transcription enabled.
  6. Export: GET /v2/call-log-export takes the same filters as the list and answers 204: the CSV is built in the background and emailed to the requesting user, normally within minutes. The job is allowed 15 minutes; past that it is abandoned, not retried, and the user receives a failure email instead, so request again with a narrower range. An export holds at most 100,000 rows: above that the request answers 422 with the row count and the limit in message, and nothing is queued. The six-month limit on the date range is a portal rule, not an API one. Dates in the file are in the X-Timezone you send, or the user's profile timezone without it.
  7. Reports (their own group): missed calls (paginated, with an export), top callers, busy hours by hour, day or month, and extension usage by direction or duration. All take from_date, to_date and, where it applies, extensions or type.

Reading a row

  • call_unique_id is the row's own id; call_id is the telephony id shared by every leg of the same call (transfers, queue legs). Key your data on call_unique_id, look recordings up by call_id.
  • direction is inbound, outbound or internal; type adds missed, unanswered, voicemail, playback; status is ANSWERED, NO ANSWER, BUSY or FAILED.
  • Who is who depends on direction. Every number comes twice, from / to as stored and from_local / to_local in local format; pick one and show it consistently.
    • inbound: the caller is from (or from_local), named by from_name (from_contact_id is the matched phonebook contact, from_name_source says where the name came from); the number they dialled is to (or to_local) with to_name; the extension that took the call is to_ext with to_ext_name. On a missed call to_ext is empty.
    • outbound: the agent is from_ext with from_ext_name; the caller ID presented to the other side is from (or from_local) with from_name; the person called is to (or to_local) with to_name (to_contact_id).
    • internal: both sides are extensions, from_ext / from_ext_name and to_ext / to_ext_name.
    • For one user, a row whose from_ext is their extension is a call they made and a row whose to_ext is their extension is a call they received.
  • billsec is the connected time, duration the total time including ringing.
  • recording is true only when a recording exists and the user may listen to it.
  • extra.call_tags and extra.call_notes are included in the row; transferred_child lists the ids of the legs a transfer created (fetch them with cdr_id=<ids>).

Roles and access

  • Any authenticated user. An account admin, or a user whose call-log permission is "all", sees every call; everyone else sees only calls on their own extension and on the numbers, extensions and queues granted to them. With no grants the list is simply empty, not 403.
  • Recording playback needs the same visibility and recording access (the account's recording add-on or subscription); otherwise 403.
  • Deleting a recording and the admin missed-call export are admin-only.
  • The ISO dates option (per account) switches call_date and note timestamps to ISO 8601 in the requested timezone (UTC by default). Without it dates are Y-m-d H:i:s in the user's timezone.

Pitfalls

  • The generated reference does not list the list's filters, because they are read from the raw query string. Use the parameters described above.
  • call_id is not unique: transfer and queue legs share it. Use call_unique_id as the row key, and pass all three ids when reading notes and tags.
  • page_count is the current page, not the number of pages; paginate on total_items and page_size.
  • Choosing a direction in type excludes voicemail and playback rows unless you add include_voicemail / include_playback.
  • Send filters as comma-separated strings, not as extensions[] arrays.
  • Dates: an unparsable value silently becomes 1970-01-01; a value with a UTC offset is shifted. Send wall-clock times and set X-Timezone.
  • There is no server-side cap on the date range or per_page; the portals cap the range at six months. Recordings are kept for six months by default (longer with a retention add-on), so an older row with recording: true can still answer 404.
  • Exports are asynchronous and arrive by email; the request itself returns no job id.