Billing Export
curl --request POST \
--url https://api.example.com/external/v1/external_billing_data_exportimport requests
url = "https://api.example.com/external/v1/external_billing_data_export"
response = requests.post(url)
print(response.text)const options = {method: 'POST'};
fetch('https://api.example.com/external/v1/external_billing_data_export', 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.example.com/external/v1/external_billing_data_export",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
]);
$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.example.com/external/v1/external_billing_data_export"
req, _ := http.NewRequest("POST", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/external/v1/external_billing_data_export")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/external/v1/external_billing_data_export")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
response = http.request(request)
puts response.read_bodyBilling Export
Export billable events to S3 and fetch export URLs
POST
/
external
/
v1
/
external_billing_data_export
Billing Export
curl --request POST \
--url https://api.example.com/external/v1/external_billing_data_exportimport requests
url = "https://api.example.com/external/v1/external_billing_data_export"
response = requests.post(url)
print(response.text)const options = {method: 'POST'};
fetch('https://api.example.com/external/v1/external_billing_data_export', 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.example.com/external/v1/external_billing_data_export",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
]);
$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.example.com/external/v1/external_billing_data_export"
req, _ := http.NewRequest("POST", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/external/v1/external_billing_data_export")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/external/v1/external_billing_data_export")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
response = http.request(request)
puts response.read_bodyExport Billing Data
Start a new export of billable events or poll the result of a previously started export.Endpoint
POST /external/v1/external_billing_data_export
Authentication
[!NOTE] Requires a valid company API key in theAuthorizationheader (format:Api-Key <key>).
Usage
- Start export: Send
company_ids,start_date,end_date, and optionalservices - Poll export: Send only
tracker_id
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
tracker_id | string (UUID) | No | If provided, returns the exported data for this tracker. No other fields required in this mode |
company_ids | array of strings (UUID) | Conditional | List of company IDs. Required when starting a new export |
start_date | string (date) | Conditional | Start date (inclusive) in YYYY-MM-DD or ISO 8601 format. Required when starting a new export |
end_date | string (date) | Conditional | End date (inclusive) in YYYY-MM-DD or ISO 8601 format. Required when starting a new export |
services | array of strings | No | Optional list of billable event service names to filter by |
Available Services
ApplicationStageTransition, DocumentAgent, BrowserAgent, LMS, and more.
Example Request - Start Export
curl -X POST "https://api.firstwork.com/external/v1/external_billing_data_export" \
-H "Authorization: Api-Key YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"company_ids": ["company-uuid-1", "company-uuid-2"],
"start_date": "2025-06-01",
"end_date": "2025-10-31",
"services": ["ApplicationStageTransition", "DocumentAgent"]
}'
Example Request - Poll Export
curl -X POST "https://api.firstwork.com/external/v1/external_billing_data_export" \
-H "Authorization: Api-Key YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"tracker_id": "tracker-uuid"
}'
Responses
200: OK
Export complete. Returns export URLs.202: Accepted
Export started. Use the returnedtracker_id to poll for results.
400: Bad Request
Missing required fields or invalid date format.404: Not Found
Tracker ID not found.500: Internal Server Error
Unexpected error during export.Notes
- Dates are interpreted in the company’s local timezone (midnight of
start_dateto 23:59:59 ofend_date) - Use the two-step flow: start the export, then poll with
tracker_iduntil the result is ready