API reference
Every endpoint, parameter and report column of the PortyLink API. Paths are under /api/v1 on your app's address. For a walkthrough with examples, see the REST API guide; for tools, import openapi.json.
Authentication#
Every request needs Authorization: Bearer <key>. An API key such as plk_live_.... All endpoints are read-only GET requests that return JSON.
Endpoints#
Sites this key can read#
GET/api/v1/sites
| Status | Response |
|---|---|
| 200 | Sites with the providers each has linked. |
| 401 | Missing, invalid, revoked or expired API key. |
Available reports#
GET/api/v1/reports
| Status | Response |
|---|---|
| 200 | The report catalog. |
| 401 | Missing, invalid, revoked or expired API key. |
Run a report for a site#
GET/api/v1/sites/{siteId}/reports/{report}
| Parameter | In | Type | Description |
|---|---|---|---|
siteIdrequired | path | string, uuid | |
reportrequired | path | string, one of 10 | See reports |
range | query | last_7_days | last_28_days | last_90_days | last_365_days | A preset ending yesterday in the source's time zone. Ignored when start and end are given. Default last_28_days. |
start | query | string, date | YYYY-MM-DD, with end. |
end | query | string, date | YYYY-MM-DD, with start. |
limit | query | integer | Rows per page; each report has its own maximum. |
offset | query | integer | Use meta.paging.nextOffset from the previous page. |
| Status | Response |
|---|---|
| 200 | Rows as objects keyed by column, totals for by-day reports, and metadata on the date range, freshness and paging. |
| 400 | The request is invalid, e.g. a bad date range. |
| 401 | Missing, invalid, revoked or expired API key. |
| 403 | The key may not read this provider. |
| 404 | Unknown site, or the site has no source linked for this report. |
| 429 | Rate limited by PortyLink or by Google's quota. Retry after retryAfter seconds. |
| 503 | Google couldn't be reached or the connected account lost access. |
Reports#
Each row in data.rows is an object keyed by these columns: the dimension first, then the metrics. Rates are fractions (0.0452 means 4.52%).
gsc.overview
Search ConsoleOne row per day, with totalsSearch performance by day. Clicks, impressions, CTR and average position from Google Search, per day, with totals.
| Column | Kind | Meaning |
|---|---|---|
date | dimension | Day, YYYY-MM-DD |
clicks | metric | Clicks from Google Search |
impressions | metric | Times shown in results |
ctr | metric | Click-through rate, a fraction |
position | metric | Average position, one decimal |
gsc.queries
Search Console25 rows by default, up to 1000Top search queries. The searches the site appeared for, by clicks.
| Column | Kind | Meaning |
|---|---|---|
query | dimension | Search query |
clicks | metric | Clicks from Google Search |
impressions | metric | Times shown in results |
ctr | metric | Click-through rate, a fraction |
position | metric | Average position, one decimal |
gsc.pages
Search Console25 rows by default, up to 1000Top pages in search. The site's pages that appeared in Google Search, by clicks.
| Column | Kind | Meaning |
|---|---|---|
page | dimension | Page URL |
clicks | metric | Clicks from Google Search |
impressions | metric | Times shown in results |
ctr | metric | Click-through rate, a fraction |
position | metric | Average position, one decimal |
gsc.countries
Search Console25 rows by default, up to 250Search performance by country. Clicks and impressions by searcher country (ISO 3166-1 alpha-3).
| Column | Kind | Meaning |
|---|---|---|
country | dimension | Country, ISO 3166-1 alpha-3 |
clicks | metric | Clicks from Google Search |
impressions | metric | Times shown in results |
ctr | metric | Click-through rate, a fraction |
position | metric | Average position, one decimal |
gsc.devices
Search Console10 rows by default, up to 10Search performance by device. Clicks and impressions on desktop, mobile and tablet.
| Column | Kind | Meaning |
|---|---|---|
device | dimension | DESKTOP, MOBILE or TABLET |
clicks | metric | Clicks from Google Search |
impressions | metric | Times shown in results |
ctr | metric | Click-through rate, a fraction |
position | metric | Average position, one decimal |
ga4.overview
AnalyticsOne row per day, with totalsTraffic by day. Active users, sessions, engaged sessions, engagement rate, views and key events, per day, with totals.
| Column | Kind | Meaning |
|---|---|---|
date | dimension | Day, YYYY-MM-DD |
activeUsers | metric | Active users |
sessions | metric | Sessions |
engagedSessions | metric | Engaged sessions |
engagementRate | metric | Engaged sessions ÷ sessions, a fraction |
screenPageViews | metric | Views |
keyEvents | metric | Key events (conversions) |
ga4.channels
Analytics25 rows by default, up to 100Traffic by channel. Sessions and users by default channel group (Organic Search, Direct, Paid Search, ...).
| Column | Kind | Meaning |
|---|---|---|
sessionDefaultChannelGroup | dimension | Default channel group |
sessions | metric | Sessions |
activeUsers | metric | Active users |
engagementRate | metric | Engaged sessions ÷ sessions, a fraction |
keyEvents | metric | Key events (conversions) |
ga4.sources
Analytics25 rows by default, up to 1000Traffic by source / medium. Sessions and users by source and medium, e.g. google / organic.
| Column | Kind | Meaning |
|---|---|---|
sessionSourceMedium | dimension | Source / medium |
sessions | metric | Sessions |
activeUsers | metric | Active users |
engagementRate | metric | Engaged sessions ÷ sessions, a fraction |
keyEvents | metric | Key events (conversions) |
ga4.landing_pages
Analytics25 rows by default, up to 1000Top landing pages. Pages where sessions started, by sessions.
| Column | Kind | Meaning |
|---|---|---|
landingPagePlusQueryString | dimension | Landing page with query string |
sessions | metric | Sessions |
activeUsers | metric | Active users |
engagementRate | metric | Engaged sessions ÷ sessions, a fraction |
keyEvents | metric | Key events (conversions) |
ga4.pages
Analytics25 rows by default, up to 1000Top pages. Pages by views, with users and total engagement time (seconds).
| Column | Kind | Meaning |
|---|---|---|
pagePath | dimension | Page path |
screenPageViews | metric | Views |
activeUsers | metric | Active users |
userEngagementDuration | metric | Total engagement time, seconds |
Errors#
Errors return { "error": { "code", "message", "retryAfter"? } }. Branch on code, one of:
invalidunauthenticatedforbiddennot_foundconflictrate_limitedunavailableinternal
retryAfter (also sent as the Retry-After header) says how many seconds to wait. Status codes and their causes are in the guide.