curl --request GET \
--url https://api.wave.sa/v1/usage \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.wave.sa/v1/usage"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.wave.sa/v1/usage', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.wave.sa/v1/usage",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.wave.sa/v1/usage"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.wave.sa/v1/usage")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.wave.sa/v1/usage")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"data": {
"total_calls": 120,
"calls_answered": 84,
"calls_missed": 21,
"total_minutes": 312.5,
"estimated_cost_sar": 45.2,
"currency": "SAR"
},
"period": {
"from": "2023-11-07T05:31:56Z",
"to": "2023-11-07T05:31:56Z"
},
"groups": [
{
"key": "2026-09-01T00:00:00+03:00",
"total_calls": 120,
"calls_answered": 84,
"calls_missed": 21,
"total_minutes": 312.5,
"estimated_cost_sar": 45.2
}
]
}{
"error_code": "INVALID_API_KEY",
"message": "<string>",
"message_ar": "<string>",
"request_id": "<string>",
"docs_url": "<string>"
}{
"error_code": "INVALID_API_KEY",
"message": "<string>",
"message_ar": "<string>",
"request_id": "<string>",
"docs_url": "<string>"
}{
"error_code": "INVALID_API_KEY",
"message": "<string>",
"message_ar": "<string>",
"request_id": "<string>",
"docs_url": "<string>"
}Get usage
Returns the usage of one project for a period: total calls, answered calls, missed calls, call minutes, and an estimated cost in SAR. Requires the usage:read scope.
Counts. total_calls counts every call that matches the filters. calls_answered counts calls that connected (a finished answered call is still an answered call). calls_missed counts calls nobody picked up. Failed, cancelled and timed-out calls count only in total_calls, so answered plus missed can be lower than the total.
Period. from and to are inclusive and filter on the time the call was created. With neither, the period is all time and period shows null. from must not be later than to.
Queue. queue_id matches calls that carry a queue id. Only callback calls carry one; web-calling and inbound calls never match.
Estimated cost. The price of the answered minutes under your rate plan, in SAR with two decimals. It is an estimate and can differ from a later invoice. It is always 0.00 for a sandbox account. In a production account, calls made with a sandbox key are left out of the cost (they still count in the totals). If your plan has no price for a direction, that part is 0.00.
Grouping. Add group_by to also get a groups list with the same metrics per group. day and hour use the Saudi calendar (Asia/Riyadh, UTC+03:00): each key is the start of the day or hour with a +03:00 offset, oldest first, and a day or hour with no calls is not listed. They need both from and to; the range can be at most 31 days for hour and 366 days for day. status groups by the raw call status and needs no range. queue lists the queues that have calls in the period (one group per queue id; calls without a queue are not listed) and needs no range; use it to fill a queue picker. The totals in data always cover the whole period.
curl --request GET \
--url https://api.wave.sa/v1/usage \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.wave.sa/v1/usage"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.wave.sa/v1/usage', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.wave.sa/v1/usage",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.wave.sa/v1/usage"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.wave.sa/v1/usage")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.wave.sa/v1/usage")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"data": {
"total_calls": 120,
"calls_answered": 84,
"calls_missed": 21,
"total_minutes": 312.5,
"estimated_cost_sar": 45.2,
"currency": "SAR"
},
"period": {
"from": "2023-11-07T05:31:56Z",
"to": "2023-11-07T05:31:56Z"
},
"groups": [
{
"key": "2026-09-01T00:00:00+03:00",
"total_calls": 120,
"calls_answered": 84,
"calls_missed": 21,
"total_minutes": 312.5,
"estimated_cost_sar": 45.2
}
]
}{
"error_code": "INVALID_API_KEY",
"message": "<string>",
"message_ar": "<string>",
"request_id": "<string>",
"docs_url": "<string>"
}{
"error_code": "INVALID_API_KEY",
"message": "<string>",
"message_ar": "<string>",
"request_id": "<string>",
"docs_url": "<string>"
}{
"error_code": "INVALID_API_KEY",
"message": "<string>",
"message_ar": "<string>",
"request_id": "<string>",
"docs_url": "<string>"
}Authorizations
Your API key from the Wave dashboard. Sandbox keys start sk_sandbox_; production keys start sk_live_. Send as Authorization: Bearer <key>. Some endpoints require a production key and specific scopes.
Query Parameters
Start of the period (ISO 8601 date-time), inclusive. Needed with group_by=day or hour.
End of the period (ISO 8601 date-time), inclusive. Needed with group_by=day or hour.
Only calls from this queue. Only callback calls carry a queue id.
Also return groups: day or hour (Asia/Riyadh buckets), status (raw call status) or queue (the queues that have calls).
day, hour, status, queue 
