Skip to content

Projects

GET /projects

List all projects your token has access to. Results are paginated (100 per page).

Query parameters

ParameterTypeDescription
statusstringFilter by project status (see Enums)
searchstringPartial match on project name or domain
agency_idintegerFilter by agency ID - super-admin tokens only
pageintegerPage number (default: 1)
per_pageintegerResults 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

FieldTypeNullableDescription
idintegerNoProject ID
namestringNoProject name
statusstringNoSee Enums
keyword_countintegerNoNumber of keywords tracked
latest_report_generated_atdatetimeYescreated_at of the row returned by /reports/latest
latest_report_idintegerYesid of the row returned by /reports/latest
latest_report_numberintegerYesreport_number of the row returned by /reports/latest
latest_report_statusstringYesstatus of the row returned by /reports/latest (see Enums)
links.latest_reportstringNoRelative URL path to /reports/latest for this project
links.last_generated_reportstringNoRelative 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 null when /reports/latest would 404.
  • latest_report_id and latest_report_number no longer monotonically increase across polls — a pending row's values stay the same while its latest_report_status transitions.
  • For "has a new report finished?" comparisons, prefer /reports/last-generated.

GET /projects/{project}

Full metadata for a single project.

Path parameters

ParameterTypeDescription
projectintegerProject 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/42

Response

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

FieldTypeNullableDescription
idintegerNoProject ID
namestringNoProject name
company_namestringYesClient company name
domainstringYesProject website URL
created_atdatetimeNoWhen the project was created
country{id, label}YesTarget country
text_language{id, label}YesLanguage used for generated content
report_language{id, label}YesLanguage used for the monthly report document
managing_useruser objectYesAccount manager
created_byuser objectYesWho created the project
contact_emailstringYesPrimary contact email
client_emailsarray of stringsNoAll notification email addresses
cc_emailstringYesCC 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_reportsbooleanNoWhether 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.
agencystringYesName of the managing agency (plain string - see note below)
planstringYesSubscription plan name
keyword_countintegerNoNumber of keywords tracked
gsc_statusstringYesGoogle Search Console connection status
latest_report_*-YesSame fields and selection rules as in the project list - see the latest_report_* warning above
links.latest_reportstringNoRelative URL path to /reports/latest for this project
links.last_generated_reportstringNoRelative 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.