Skip to content

Notes and documents API

Read, search and write every Markdown document in an organization, and the personalization document of the member a key acts as.

3 min read

Every organization, project, campaign, creator, video, payout method, payout structure and payout payment has a Markdown document (readme), and so does every member. These endpoints read and write all of them in one way. Over MCP the same endpoints are the list_notes, get_notes, update_notes, get_my_profile, update_my_readme and list_members tools. See Notes and documents for how people and agents use them.

entity_type is one of organization, project, campaign, creator, video, payout_method, payout_structure, payout_payment or member. For member, the id is a user id, and me means the member the key acts as.

GET/api/v2/notes#

Lists documents that have text, newest first within each type, with a preview.

ParameterTypeDescription
entity_typestringOnly this kind of document.
project_iduuidThe project and the documents inside it. Org-wide documents (organization, members, payout methods) are left out.
qstringCase-insensitive text that must appear in the document.
limitintegerItems per type, 1 to 100. Default 20.
offsetintegerRows to skip. Needs entity_type.

Without entity_type, every type is searched and each returns up to limit items. meta.totals has the number of matches per type and meta.has_more names the types with more; page through one of them with entity_type and offset.

bash
curl -H "Authorization: Bearer tga_<key>" \
  "https://www.trackagoat.com/api/v2/notes?q=launch"
JSON
{
  "data": [
    {
      "entity_type": "project",
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "name": "Spring Launch",
      "project_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "readme_preview": "## Goal 2M views by May 31. Creators post 3 times a week...",
      "readme_length": 1204,
      "readme_version": "9f2c4e1a7b3d5f60"
    }
  ],
  "error": null,
  "meta": { "totals": { "organization": 0, "project": 1, "campaign": 0 }, "has_more": [], "limit": 20, "offset": 0 }
}

GET/api/v2/notes/{entity_type}/{id}#

Returns one document in full.

FieldDescription
readmeThe Markdown text, or null.
readme_versionA hash of the text. Pass it as expected_readme_version to replace the document.
can_editWhether the member the key acts as may change it (scopes aside).
edit_ruleWho may change it, in words.
app_pathWhere people edit it in the app.

Returns 404 not_found for anything outside the key's organization, including members of other organizations.

POST/api/v2/notes/{entity_type}/{id}#

Appends to or replaces a document. Needs the write scope. Honours Idempotency-Key.

JSON
{ "mode": "append", "content": "Views dropped 40% week over week." }
JSON
{ "mode": "replace", "content": "# Spring Launch\n\n...", "expected_readme_version": "9f2c4e1a7b3d5f60" }
  • append adds content as a new section at the end, followed by *Added by <key name> via API, YYYY-MM-DD* (via MCP from the MCP server). If someone edits the document at the same moment, the section is added on top of their edit.
  • replace overwrites the whole document. If it changed since you read expected_readme_version, nothing is written and the response is 409 notes_conflict with meta.current_readme_version. An empty content clears it.

Who can write follows the app:

DocumentWho can change it
organization, project, payout_method, payout_structure, payout_paymentA key that acts as an org admin. Otherwise 403 insufficient_role.
campaign, creator, videoAny key with write.
memberOnly the member's own key or sign-in. Otherwise 403 not_your_document.

POST /api/v2/creators/{id}/notes and POST /api/v2/videos/{id}/notes keep working and behave the same.

PATCH /api/v2/campaigns/{id} and PATCH /api/v2/organizations/{orgId}/projects/{projectId} also take a readme, which replaces the document. Send expected_readme_version with it to get the same 409 notes_conflict instead of overwriting a newer edit. See Campaigns and Projects.

GET/api/v2/me#

Who the key acts as, and their personalization document.

JSON
{
  "data": {
    "id": "8d1c2f0e-1b2a-4c3d-9e8f-7a6b5c4d3e2f",
    "display_name": "Sam Lee",
    "organization": { "id": "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed", "name": "Acme", "role": "admin" },
    "connection": { "via": "api_key", "scopes": ["read", "write"] },
    "readme": "## About me\nPartnerships lead...",
    "readme_version": "0c4f1d2e3a5b6c7d",
    "readme_length": 412,
    "readme_visibility": "Everyone in the organization, and their agents, can read this document."
  },
  "error": null,
  "meta": null
}

PATCH/api/v2/me#

Replaces the personalization document of the member the key acts as. Needs the write scope.

JSON
{ "readme": "## About me\n...", "expected_readme_version": "0c4f1d2e3a5b6c7d" }

With expected_readme_version, an edit made in the app since your read returns 409 notes_conflict and nothing is written. Without it, the write replaces whatever is there.

GET/api/v2/members#

The organization's members: user_id, display_name, role, joined_at, is_you, and whether each has a personalization document (has_readme, readme_length, readme_preview). Read one with GET /api/v2/notes/member/{user_id}.

Errors#

Statusmeta.codeWhen
400invalid_entity_typeentity_type isn't one of the types above.
400notes_too_longThe document would be longer than 50,000 characters.
403insufficient_scopeA write without the write scope.
403insufficient_roleAn org-admin document and the key acts as a member who isn't an org admin.
403not_your_documentWriting another member's personalization document.
404not_foundNot in the key's organization.
409notes_conflictThe document changed since expected_readme_version.
409notes_busyThe record kept changing while saving. Retry.