Appearance
Projects
GET /projects
List all projects your token has access to. Results are paginated (100 per page).
Query parameters
| Parameter | Type | Description |
|---|---|---|
status | string | Filter by project status (see Enums) |
search | string | Partial match on project name or domain |
agency_id | integer | Filter by agency ID - super-admin tokens only |
page | integer | Page number (default: 1) |
per_page | integer | Results per page (default: 100, max: 100) |
Unknown query parameters return a 400 error listing the allowed parameter names.
Request
sh
curl -H "Authorization: Bearer YOUR_API_TOKEN" \
"https://admin.trakk.ai/api/v1/projects?status=active&page=1"Response
json
{
"data": [
{
"id": 42,
"name": "Digipartner Website",
"status": "active",
"keyword_count": 18,
"latest_report_generated_at": "2026-03-01T10:00:00.000000Z",
"latest_report_id": 1081,
"latest_report_number": 14,
"latest_report_status": "completed",
"links": {
"latest_report": "/api/v1/projects/42/reports/latest",
"last_generated_report": "/api/v1/projects/42/reports/last-generated"
}
}
],
"meta": { "current_page": 1, "per_page": 100, "total": 3, "last_page": 1 },
"links": { "first": "…", "last": "…", "prev": null, "next": null },
"cache_refreshed_at": "2026-03-30T12:00:00.000000Z"
}Fields
| Field | Type | Nullable | Description |
|---|---|---|---|
id | integer | No | Project ID |
name | string | No | Project name |
status | string | No | See Enums |
keyword_count | integer | No | Number of keywords tracked |
latest_report_generated_at | datetime | Yes | created_at of the row returned by /reports/latest |
latest_report_id | integer | Yes | id of the row returned by /reports/latest |
latest_report_number | integer | Yes | report_number of the row returned by /reports/latest |
latest_report_status | string | Yes | status of the row returned by /reports/latest (see Enums) |
links.latest_report | string | No | Relative URL path to /reports/latest for this project |
links.last_generated_report | string | No | Relative URL path to /reports/last-generated for this project |
latest_report_* semantics
These four fields mirror whatever row /reports/latest selects, which is calendar-aware and may return a non-completed row. Consequences:
- All four are
nullwhen/reports/latestwould404. latest_report_idandlatest_report_numberno longer monotonically increase across polls — a pending row's values stay the same while itslatest_report_statustransitions.- For "has a new report finished?" comparisons, prefer
/reports/last-generated.
GET /projects/{project}
Full metadata for a single project.
Path parameters
| Parameter | Type | Description |
|---|---|---|
project | integer | Project ID - the same id returned by GET /projects. No slugs or UUIDs are accepted; non-existent IDs return 404. |
Request
sh
curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://admin.trakk.ai/api/v1/projects/42Response
json
{
"data": {
"id": 42,
"name": "Digipartner Website",
"company_name": "Digipartner Corp",
"domain": "https://digipartner.se",
"created_at": "2024-01-15T09:00:00.000000Z",
"country": { "id": 1, "label": "Sweden" },
"text_language": { "id": 3, "label": "Swedish" },
"report_language": { "id": 3, "label": "Swedish" },
"managing_user": {
"id": 7,
"name": "Jane Smith",
"role": "Account Manager",
"agency": { "id": 12, "name": "Digipartner Agency" }
},
"created_by": { "id": 2, "name": "Admin", "role": "Admin", "agency": null },
"contact_email": "contact@digipartner.se",
"client_emails": ["contact@digipartner.se", "cto@digipartner.se"],
"cc_email": "reports@digipartner-agency.se",
"receives_monthly_reports": true,
"agency": "Digipartner Agency",
"plan": "Growth",
"keyword_count": 18,
"gsc_status": "connected",
"latest_report_generated_at": "2026-03-01T10:00:00.000000Z",
"latest_report_id": 1081,
"latest_report_number": 14,
"latest_report_status": "completed",
"links": {
"latest_report": "/api/v1/projects/42/reports/latest",
"last_generated_report": "/api/v1/projects/42/reports/last-generated"
}
},
"cache_refreshed_at": "2026-03-30T12:00:00.000000Z"
}Fields
| Field | Type | Nullable | Description |
|---|---|---|---|
id | integer | No | Project ID |
name | string | No | Project name |
company_name | string | Yes | Client company name |
domain | string | Yes | Project website URL |
created_at | datetime | No | When the project was created |
country | {id, label} | Yes | Target country |
text_language | {id, label} | Yes | Language used for generated content |
report_language | {id, label} | Yes | Language used for the monthly report document |
managing_user | user object | Yes | Account manager |
created_by | user object | Yes | Who created the project |
contact_email | string | Yes | Primary contact email |
client_emails | array of strings | No | All notification email addresses |
cc_email | string | Yes | CC address automatically added to every report email for this project. Sourced from the agency-level report_cc_email setting, so all projects under the same agency share this value. null if the agency has not configured one. |
receives_monthly_reports | boolean | No | Whether the project's managing_user is emailed the auto-generated monthly report. When false, monthly reports are still generated but the managing user is not notified. |
agency | string | Yes | Name of the managing agency (plain string - see note below) |
plan | string | Yes | Subscription plan name |
keyword_count | integer | No | Number of keywords tracked |
gsc_status | string | Yes | Google Search Console connection status |
latest_report_* | - | Yes | Same fields and selection rules as in the project list - see the latest_report_* warning above |
links.latest_report | string | No | Relative URL path to /reports/latest for this project |
links.last_generated_report | string | No | Relative URL path to /reports/last-generated for this project |
Agency field shape
project.agency is a plain string (agency name only). This differs from the agency field inside embedded user objects (like managing_user.agency), which is { "id": ..., "name": ... }.
Embedded user object shape (used in managing_user, created_by, approved_by, managed_by):
json
{ "id": 7, "name": "Jane Smith", "role": "Account Manager", "agency": { "id": 12, "name": "Digipartner Agency" } }agency inside a user object is null when the user has no agency.