Tree Inventory AI

Notes

What the arborist said on the walk. Dictated at the tree, or the conversation with the customer pasted against the site. The price and the constraints are usually in here rather than in the inventory.

gethttps://app.treeinventory.ai/api/v1/sites/{siteId}/notes

Read what was said on the walk

Every note taken at a property, the ones dictated standing at a tree included, oldest first. THIS IS WHERE THE QUOTE IS ACTUALLY DECIDED. An arborist holds a button and says what is wrong and what it will cost, and pastes the customer conversation against the site afterwards; estimatedCostCents is the number they said out loud and clientNotes is what the customer asked for. Read this BEFORE you ask an arborist anything, because most of what you were about to ask is in here, and asking for a price they already dictated is how an assistant tells somebody it was not listening. mentionedTrees carries species plus position as they said it, which is how the big oak by the driveway becomes an id. Not paginated: one visit is a handful of notes.

Scope: inventory:read

Path parameters

FieldTypeNotes
siteIdrequireduuidThe site's id.

Each item in data.items

FieldTypeNotes
iduuid
scopestringsite when it was dictated about the property, tree when it was dictated standing at one.
treeIduuid or nullThe tree it was dictated at. Null on a site note.
transcriptstringWhat was said, verbatim. Read this before the extraction.
estimatedCostCentsinteger or nullA price the arborist said out loud, in whole cents. THIS IS THE NUMBER THEY QUOTED THE CUSTOMER. Where it exists it beats the catalog, and asking for a price it already carries is the single most annoying thing an assistant can do.
clientNotesstring or nullWhat the customer said they wanted, in the arborist's retelling. This is the brief, and it is why the customer's own words are worth more than any inference from the inventory.
healthstring or null
defectsstring[]
observationsstring[]
recommendationsstring[]
mentionedTreesobject[]Trees named in the talking, as species plus where they stand. Match these against the captured records; this is how the big oak by the driveway becomes an id.
durationSecondsnumber or null
createdAtstring

Each item in data.items → mentionedTrees

FieldTypeNotes
speciesstring
locationstring

Example response 200

{
  "success": true,
  "message": "Notes retrieved",
  "data": {
    "items": [
      {
        "id": "8c7d6e5f-4a3b-4c2d-9e1f-0a9b8c7d6e5f",
        "scope": "tree",
        "treeId": "c04f8a55-1d2e-4b39-8a71-6f5c2d9e3b40",
        "transcript": "Big red oak over the driveway, deadwood through the top, included bark at the union. Told them about fifteen hundred for the crown clean and a cable. They only want the driveway side done this year.",
        "estimatedCostCents": 150000,
        "clientNotes": "Only wants the driveway side done this year.",
        "health": "fair",
        "defects": [
          "included bark",
          "deadwood"
        ],
        "observations": [
          "Deadwood concentrated over the parking pad"
        ],
        "recommendations": [
          "crown clean",
          "cable/brace"
        ],
        "mentionedTrees": [
          {
            "species": "red oak",
            "location": "over the driveway"
          }
        ],
        "durationSeconds": 22,
        "createdAt": "2026-08-20T15:42:10.000Z"
      }
    ]
  }
}

Failures

  • 401 Missing, malformed, revoked or expired credential. The WWW-Authenticate header names the scheme, which is ApiKey. Carries no RateLimit-* headers: the credential was never resolved, so there is no bucket to report.
  • 403 The key is valid but does not carry the scope this operation requires. The message names the scope, so you can ask for exactly the grant you need. Carries no RateLimit-* headers: a request refused for scope is not counted against your limit.
  • 404 No such record in your organization. A record belonging to somebody else is indistinguishable from one that does not exist.
  • 422 Validation failed. Every bad field is named, at once.
  • 429 Rate limit exceeded.
  • 500 Something failed on our side. Retry with the SAME Idempotency-Key; a 5xx is the one status where retrying is correct.