Comments

Comments are the conversation on an invoice, estimate, project, task, proposal, or contract. A comment marked staff_only is hidden from client contacts in the portal. Posting a comment notifies the people involved, as it does in the app, and a comment on subcontracted work is copied to the other side of the subcontract.

Get Comments

GET /api/v2/invoices/:invoice_id/comments
GET /api/v2/estimates/:estimate_id/comments
GET /api/v2/projects/:project_id/comments
GET /api/v2/tasks/:task_id/comments
GET /api/v2/proposals/:proposal_id/comments
GET /api/v2/contracts/:contract_id/comments

Newest first.

{
  "comments": [
    {
      "id": 41,
      "body": "Please review the revised total",
      "html": null,
      "staff_only": false,
      "user_id": 3,
      "user": { "name": "Lu Wang", "mini_avatar_url": "https://...", "staff?": true },
      "commentable_type": "Invoice",
      "commentable_id": 110,
      "created_at": "2026-09-11T16:10:59Z",
      "updated_at": "2026-09-11T16:10:59Z"
    },
    ...
  ]
}

Create A Comment

POST /api/v2/invoices/:invoice_id/comments (and the same for the other resources above)
{
  "comment": {
    "body": "Please review the revised total",
    "staff_only": false
  }
}

Required Fields: body (HTTP 422 on failure)
Optional Fields: html, the same comment as rich text, shown in place of body where the app renders HTML. staff_only defaults to false.

Update A Comment

PUT /api/v2/comments/:id

Only the comment's author may update it. Another user's comment is not found (HTTP 404).

{
  "comment": {
    "body": "Please review the revised total and due date"
  }
}

Delete A Comment

DELETE /api/v2/comments/:id

Only the comment's author may delete it. Another user's comment is not found (HTTP 404).

Deletions are permanent and not reversible.