Expenses & Documents
This guide covers expense reports and documents. Every parameter and field is in the API Reference.
Scopes for this area
| Task | Scope | Lowest owner role |
|---|---|---|
| Read expense reports | expenses:read | Employee |
| Approve and reject expense reports | expenses:approve | Department Head |
| Read document metadata and signers | documents:read | Employee |
| Download document files | documents.content:read | Administrator |
Expense reports
403 MODULE_DISABLED, and no expense events are sent by webhook.Whose reports a token can see
- An Employee's token lists the reports they submitted.
- A Department Head's token lists reports submitted by people in the departments they head or manage.
- Administrators and Executives list every report in the organization.
GET /expense-reports/{id} also opens a report the owner is the assigned approver of. A report the owner cannot see answers 404 NOT_FOUND. Filters narrow the view and never widen it.
Export approved reports
curl "https://app.bookyourpto.com/api/v1/expense-reports?status=APPROVED&from=2026-09-01&to=2026-09-30&limit=100" \
-H "Authorization: Bearer $BOOKYOURPTO_TOKEN"
The list returns each report's header: number, title, submitter, approver, dates, status and totals (total_expenses, total_per_diems, total_mileage, total_tax, grand_total, currency), with counts of line items, per diems, mileage entries and receipts. Results are newest first. Filter with status, report_type (REIMBURSEMENT or COMPANY_CARD), user_id, and from / to, which match the trip's departure and return days.
For the lines, read each report:
curl "https://app.bookyourpto.com/api/v1/expense-reports/cmexp0000000000000000042" \
-H "Authorization: Bearer $BOOKYOURPTO_TOKEN"
{
"data": {
"id": "cmexp0000000000000000042",
"report_number": "EXP-2026-0042",
"status": "APPROVED",
"currency": "CAD",
"grand_total": 605.58,
"line_items": [
{ "id": "cmeli0000000000000000001", "date": "2026-09-14", "vendor": "Harbourfront Suites", "expense_type": "ACCOMMODATION", "amount_before_tax": 412, "gst": 20.6, "total": 432.6, "receipt_id": "cmerc0000000000000000001", "...": "more fields" }
],
"per_diems": [ { "date": "2026-09-15", "per_diem_type": "FULL_DAY", "rate": 112.5, "total": 112.5, "...": "more fields" } ],
"mileage": [ { "date": "2026-09-16", "distance": 84, "unit": "KILOMETERS", "rate_per_unit": 0.72, "total": 60.48, "...": "more fields" } ],
"receipts": [ { "id": "cmerc0000000000000000001", "file_name": "harbourfront-folio.pdf", "mime_type": "application/pdf", "size_bytes": 184220 } ],
"...": "the header fields"
},
"meta": { "request_id": "..." }
}
- Amounts are numbers in the currency named next to them; each line also has
total_in_base_currencyfor the organization's currency. - Line dates are calendar days (
YYYY-MM-DD). receiptslists each receipt's metadata. Receipt images and files are not available through the API.
To pick up reports as they are approved or paid, rather than polling, subscribe to expense_report.approved and expense_report.paid (see Events).
Reference: List expense reports, Get an expense report.
Approve or reject a report
curl -X POST https://app.bookyourpto.com/api/v1/expense-reports/cmexp0000000000000000042/reject \
-H "Authorization: Bearer $BOOKYOURPTO_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "reason": "Hotel folio is missing the second night." }'
/approvetakes optionalnotes;/rejectrequires areason. Both are shown to the submitter, who is notified.- Only a report awaiting a decision (
SUBMITTEDorPENDING_APPROVAL) can be decided. Any other state answers409 CONFLICT. - Administrators and Executives decide any report; a Department Head only reports from their department scope. A decision the owner may not make answers
403 FORBIDDEN. - Nobody decides their own report through the API, including Administrators and Executives, who can in the app. A token is automation acting for its owner, and approving the owner's own spending automatically would defeat the separation of duties the approval exists for.
- The events are
expense_report.approvedandexpense_report.rejected. Marking a report paid is done in the app, and raisesexpense_report.paid.
Documents
Whose documents a token can see
The token sees what its owner's document list shows in the app:
- Administrators and Executives see every document in the organization.
- A Department Head sees their own documents and documents assigned to them for signature, plus documents they sent to people in their department scope.
- An Employee sees their own documents and documents assigned to them for signature.
- In sequential signing, a signer whose turn has not come yet does not see the document.
A document the owner cannot see answers 404 NOT_FOUND.
List documents and their signing status
curl "https://app.bookyourpto.com/api/v1/documents?signature_status=PENDING" \
-H "Authorization: Bearer $BOOKYOURPTO_TOKEN"
- Filter with
signature_status(NOT_REQUIRED,PENDING,SIGNED,DECLINED,EXPIRED),categoryanduser_id(documents in that person's folder: owned by them or assigned to them to sign). Results are newest first. - Per-person copies of onboarding documents are left out unless you add
include_copies=true. GET /documents/{id}addssigners: each signer's status, signing order, due date and when they viewed, signed or declined.
Subscribe to document.signed and document.declined to follow signing without polling. document.signed is sent each time a signer signs; the document's signature_status becomes SIGNED when the last signer has signed.
Reference: Documents.
Download a file
curl "https://app.bookyourpto.com/api/v1/documents/cmdoc0000000000000000007/content" \
-H "Authorization: Bearer $BOOKYOURPTO_TOKEN" \
| jq -r '.data.content_base64' | base64 --decode > employment-agreement.pdf
- Needs
documents.content:read, which only Administrator and Executive owners can hold, and the document must be visible to the owner. - The file comes back base64 encoded in the JSON envelope, with
file_name,mime_typeandsize_bytes. Files up to 10 MB can be downloaded; larger files answer422 VALIDATION_FAILEDand must be downloaded in the app. - Each download counts as 10 requests against the rate limits.
- Every download is written to the audit log and the sensitive-data access log, with the token that made it.
Reference: Download a document.
Gotchas
- Signing is not available through the API. A signature is a legal act bound to a person, so documents are signed in the app.
- Expense reports are read-only apart from decisions. Reports, receipts and payments are created and changed in the app.
- Every page of an expense or document list is recorded as an export in the audit log, with the record count.
- Decode files as bytes. Write the decoded
content_base64straight to a file; do not pass it through a text encoding.
Time
Export time entries and timesheets for payroll, record and correct hours, approve time, and read projects, tasks, clients and shift schedules through the API.
Webhooks Overview
How BookYourPTO webhooks push events to your HTTPS endpoint, who can create and own endpoints, what a payload contains and the limits that apply.