curl --request GET \
--url https://app.equated.co/api/reports/pnl \
--header 'Authorization: Bearer <token>'import requests
url = "https://app.equated.co/api/reports/pnl"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://app.equated.co/api/reports/pnl', 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://app.equated.co/api/reports/pnl",
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://app.equated.co/api/reports/pnl"
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://app.equated.co/api/reports/pnl")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.equated.co/api/reports/pnl")
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{
"report": {
"period": {
"from": "<string>",
"to": "<string>"
},
"currency": "<string>",
"basis": "accrual",
"coverage": "posted",
"compare": "none",
"project": {
"kind": "all"
},
"revenue": [
{
"accountId": 123,
"label": "<string>",
"amount": 123,
"emoji": "<string>",
"logoDomain": "<string>",
"children": "<array>",
"total": 123
}
],
"cogs": [
{
"accountId": 123,
"label": "<string>",
"amount": 123,
"emoji": "<string>",
"logoDomain": "<string>",
"children": "<array>",
"total": 123
}
],
"operatingExpenses": [
{
"accountId": 123,
"label": "<string>",
"amount": 123,
"emoji": "<string>",
"logoDomain": "<string>",
"children": "<array>",
"total": 123
}
],
"totals": {
"revenue": 123,
"cogs": 123,
"grossProfit": 123,
"operatingExpenses": 123,
"netIncome": 123
},
"comparison": {
"label": "<string>",
"period": {
"from": "<string>",
"to": "<string>"
},
"amountsByAccountId": {},
"totals": {
"revenue": 123,
"cogs": 123,
"grossProfit": 123,
"operatingExpenses": 123,
"netIncome": 123
}
},
"heroTrend": [
{
"month": "<string>",
"label": "<string>",
"revenue": 123,
"expenses": 123,
"netIncome": 123
}
]
}
}Profit & loss statement
Income statement for a date window: Revenue → COGS → Gross Profit → Operating Expenses → Net Income. Line amounts are positive magnitudes in account-tree sections; totals applies the sign convention. Counts POSTED entries only, so an organization with an unconfirmed inbox reads as zero activity — coverage=all counts fresh drafts as well, and the response echoes which coverage produced it. basis=cash excludes accrual-sourced entries so AP/AR only reflect cash that actually moved. compare adds prior-period totals keyed by account id, and heroTrend carries 12 months of section totals for charting.
curl --request GET \
--url https://app.equated.co/api/reports/pnl \
--header 'Authorization: Bearer <token>'import requests
url = "https://app.equated.co/api/reports/pnl"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://app.equated.co/api/reports/pnl', 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://app.equated.co/api/reports/pnl",
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://app.equated.co/api/reports/pnl"
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://app.equated.co/api/reports/pnl")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.equated.co/api/reports/pnl")
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{
"report": {
"period": {
"from": "<string>",
"to": "<string>"
},
"currency": "<string>",
"basis": "accrual",
"coverage": "posted",
"compare": "none",
"project": {
"kind": "all"
},
"revenue": [
{
"accountId": 123,
"label": "<string>",
"amount": 123,
"emoji": "<string>",
"logoDomain": "<string>",
"children": "<array>",
"total": 123
}
],
"cogs": [
{
"accountId": 123,
"label": "<string>",
"amount": 123,
"emoji": "<string>",
"logoDomain": "<string>",
"children": "<array>",
"total": 123
}
],
"operatingExpenses": [
{
"accountId": 123,
"label": "<string>",
"amount": 123,
"emoji": "<string>",
"logoDomain": "<string>",
"children": "<array>",
"total": 123
}
],
"totals": {
"revenue": 123,
"cogs": 123,
"grossProfit": 123,
"operatingExpenses": 123,
"netIncome": 123
},
"comparison": {
"label": "<string>",
"period": {
"from": "<string>",
"to": "<string>"
},
"amountsByAccountId": {},
"totals": {
"revenue": 123,
"cogs": 123,
"grossProfit": 123,
"operatingExpenses": 123,
"netIncome": 123
}
},
"heroTrend": [
{
"month": "<string>",
"label": "<string>",
"revenue": 123,
"expenses": 123,
"netIncome": 123
}
]
}
}Authorizations
API token issued from the Equated app under Settings → API Tokens.
Query Parameters
Inclusive period start (YYYY-MM-DD). Defaults to the start of the current year.
^\d{4}-\d{2}-\d{2}$Inclusive period end (YYYY-MM-DD). Defaults to today.
^\d{4}-\d{2}-\d{2}$Report currency (ISO-4217). Defaults to the organization's base currency.
3Accounting basis; cash excludes accrual-sourced entries. Defaults to accrual.
accrual, cash none, prior_period, prior_year Which entries to count. posted (default) is the attested view, so an organization that has confirmed nothing reads as zero activity. all adds the unconfirmed inbox, the way cash flow always reports.
posted, all Scope the P&L to entries attributed to this project.
x > 0Scope to every project in this group.
x > 0When true, scope to entries with no project. Mutually exclusive with the other project filters.
true, false Response
The P&L report for the requested window
Show child attributes
Show child attributes