JSON:API Format¶
The Partners API follows the JSON:API specification (v1.1) for all request and response formatting.
Key Conventions¶
- Resource objects include
type,id, andattributes - Field names are dasherized (e.g.,
base-priceinstead ofbase_price) - Resource types (
type) are plural and dasherized (e.g.,listings,users,calendar-entries). Compound resource types use a singular modifier on a plural head noun —min-stay-customizations, notmin-stays-customizations— even when the endpoint path segment is plural (/customizations/min-stays/). That path-vs-type difference is intentional; treattypeas the stable identifier to match on.
Content-Type¶
Requests should use the JSON:API media type:
The API also accepts application/json for backward compatibility.
Response Format¶
Single Resource¶
Collection¶
Collections include meta with pagination info and links for navigation (see Pagination):
{
"data": [ ... ],
"meta": { "pagination": { "count": 150, "page": 1, "pages": 6 } },
"links": { "first": "...", "last": "...", "next": "...", "prev": null }
}
Error Response¶
{
"errors": [
{
"status": "404",
"title": "Not Found",
"detail": "Listing 12345 not found",
"source": {"pointer": null}
}
]
}
See Error Handling for the full list of error codes and best practices.
Request Format (POST/PATCH)¶
When creating or updating resources, wrap the payload in a data object:
{
"data": {
"type": "users",
"attributes": {
"first-name": "John",
"last-name": "Doe",
"email": "john@example.com"
}
}
}
Compound Documents (Sideloading)¶
Some endpoints support including related resources in a single request using the ?include= parameter. This eliminates the need for multiple API calls.
Related resources appear in the top-level included array, with the relationship declared in relationships:
{
"data": {
"type": "listings",
"id": "12345",
"attributes": { ... },
"relationships": {
"owner": { "data": {"type": "users", "id": "789"} }
}
},
"included": [
{
"type": "users",
"id": "789",
"attributes": { ... }
}
]
}
See each endpoint's documentation in the Swagger UI for the list of supported include values.
Pagination¶
Collection endpoints return paginated results. Use query parameters to control pagination, sorting, and filtering.
All collection endpoints use page-based pagination:
| Parameter | Description | Default |
|---|---|---|
page[number] |
Page number (1-indexed) | 1 |
page[size] |
Items per page (max 100) | 25 |
Responses include pagination info in meta and navigation links in links:
{
"meta": {
"pagination": {
"count": 150,
"page": 1,
"pages": 6
}
},
"links": {
"first": "...?page%5Bnumber%5D=1",
"last": "...?page%5Bnumber%5D=6",
"next": "...?page%5Bnumber%5D=2",
"prev": null
}
}
Use the links URLs to navigate between pages without constructing URLs manually.
Sorting¶
Use the sort parameter with field names. Prefix with - for descending order. Multiple sort fields are comma-separated.
# Newest first
?sort=-created_at
# Multiple fields: by city ascending, then by price descending
?sort=city,-base_price
Each endpoint documents its own sortable fields in the Swagger UI.
Filtering¶
Use filter[field] parameters to narrow results.
Each endpoint documents its own available filters in the Swagger UI.
Putting It All Together¶
Combine pagination, sorting, and filtering in a single request:
curl -X GET "$BASE_URL/api/v1/listings/?page[number]=1&page[size]=25&sort=-created_at&filter[enabled]=true" \
-H "Authorization: Bearer <token>" \
-H "Accept: application/vnd.api+json"
Types in Webhook Payloads¶
A webhook delivery is a JSON:API document too, and it carries two
fields named type:
{
"meta": { "type": "listing.refreshed", "...": "..." },
"data": { "type": "listing-refreshed-events", "...": "..." }
}
data.type is the ordinary JSON:API resource type — required by the spec, and the key
you deserialize on. JSON:API is deliberately agnostic about inflection (singular vs.
plural, dashes vs. underscores) but demands consistency, so event resource types follow
the same dasherized-plural convention as the rest of the API.
meta.type is a Beyond extension, and it is the field you should route on. JSON:API
reserves the meta object for exactly this: implementation-specific information the spec
itself says nothing about — and the spec says nothing at all about events or webhooks.
Why not a top-level type, as Standard Webhooks
suggests? Because that would be illegal JSON:API. The spec restricts a document's
top-level members to data, errors, meta, jsonapi, links, and included; a
top-level type is not among them. Nesting the event type under meta satisfies both
specifications at once.
Where the event id lives¶
For the same reason, the event's ULID appears in data.id rather than in meta. JSON:API
requires every resource object to carry an id, and the resource this document describes
is the event — so data.id is the event id, not the id of the listing or account the
event concerns. Standard Webhooks, meanwhile, puts the identifier in the webhook-id
header and uses it as the idempotency key. Between them the two specs already account for
the id twice; a third copy under meta would be redundant, so there is not one.