API Guide
Pagination, Filtering & Fields
Keyset pagination, the fail-closed parameter policy, and trimming responses with fields.
Keyset pagination
List endpoints are keyset-paginated and return newest first. Pass limit, then follow the cursor:
curl "https://api.moveitpro.com/v1/jobs?limit=100" \
-H "Authorization: Bearer mip_live_..."
{
"success": true,
"data": [ … ],
"next_cursor": "eyJpZCI6…"
}
When next_cursor is present, request the next page with ?cursor=… and the same filters. When it is absent or null, you have reached the end. Keyset cursors are stable under concurrent inserts — unlike offset paging, rows are neither skipped nor duplicated while you walk a list.
limit accepts 1–100. An out-of-range or non-integer value is rejected with 400 invalid_limit — values are never silently clamped. A corrupted cursor is 400 invalid_cursor.
Fail-closed parameters
Each route declares the exact parameters it accepts. Anything else — including a typo of a real parameter — is rejected:
{
"success": false,
"error": "Unknown query parameter: statuss",
"error_code": "unknown_param"
}
This is deliberate. A misspelled filter cannot quietly return the unfiltered set and send you a much larger, wrong answer. Sending the same parameter twice is also rejected (400 invalid_param) rather than silently answering for one of the two values.
By-id routes accept only fields. Filters and pagination parameters on a by-id route are rejected the same way.
Trimming responses with fields
Pass a comma-separated allowlist to shrink each object:
curl "https://api.moveitpro.com/v1/customers?fields=id,first_name,last_name,email" \
-H "Authorization: Bearer mip_live_..."
An unknown field name returns 400 invalid_fields. Field names per resource are listed in the reference, which stays in lockstep with the live gateway through parity tests.
Caching with ETags
Every GET returns a strong ETag header. Send it back in If-None-Match on your next poll; an unchanged response is 304 Not Modified with no body — much cheaper for everyone than re-downloading unchanged pages:
curl "https://api.moveitpro.com/v1/customers/{id}" \
-H "Authorization: Bearer mip_live_..." \
-H 'If-None-Match: "…"'
The ETag is a content hash for caching only — it is not the version token that write requests send in If-Match (that token is the record's updated_at; see Idempotency). Do not feed an ETag into If-Match.
Common filters
created_after/created_before— ISO-8601 timestamps, for incremental syncs.status— resource-specific status enums.branch_id— available on branch-attributed resources for company-scoped keys.
The route-by-route list of accepted parameters is authoritative in the reference; because parameters are fail-closed, guessing is never necessary.