Custom objects
Read your site's custom object definitions and their instances as JSON from a theme
Custom objects let a site define its own content types — sponsors, instruments, donor tiers, anything the built-in types don't cover. These endpoints expose those definitions and their instances as read-only JSON so a theme can render custom data in the browser.
Each custom object type has a handle — a stable identifier you set when you create the type. The endpoints below are addressed by that handle.
Custom object types also have an Expose in public API option in Basker. When it is off, the instance endpoints for that handle return 404. The definition endpoints can still return the type's public structure, such as label, handle, and field definitions.
List object definitions
GET {your-domain}/api/custom-object-definitions.jsonReturns every custom object type defined on your site, including each type's handle, label, and the fields it defines.
{
"docs": [
{
"id": "67be2c1cb1d3f...",
"handle": "sponsor",
"label": "Sponsor",
"icon": "Award",
"description": "Partner organizations that support our season",
"fieldDefinitions": [
{ "name": "tier", "label": "Tier", "type": "text" },
{ "name": "logo", "label": "Logo", "type": "upload", "publicApiPopulation": "summary" },
{ "name": "website", "label": "Website", "type": "text" }
]
}
],
"totalDocs": 1,
"limit": 100,
"totalPages": 1,
"page": 1,
"pagingCounter": 1,
"hasPrevPage": false,
"hasNextPage": false,
"prevPage": null,
"nextPage": null
}Get one object definition
GET {your-domain}/api/custom-object-definitions/{handle}Returns a single definition by its handle, wrapped in a doc object — useful for reading the field list before rendering instances.
{
"doc": {
"id": "67be2c1cb1d3f...",
"handle": "sponsor",
"label": "Sponsor",
"icon": "Award",
"description": "Partner organizations that support our season",
"fieldDefinitions": [
{ "name": "tier", "label": "Tier", "type": "text" },
{ "name": "logo", "label": "Logo", "type": "upload", "publicApiPopulation": "summary" }
]
}
}List instances of an object type
GET {your-domain}/api/custom-objects/{handle}Returns the published instances of the custom object type identified by {handle}.
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number to return. |
limit | integer | 100 | Page size. |
sort | string | title | Field to sort by. Prefix with - to reverse. |
Response
A standard paginated list. Each instance carries a title plus the values for the fields defined on its type, keyed by field name directly on the instance.
{
"docs": [
{
"id": "5f9a1b2c3d4e5...",
"title": "Acme Corporation",
"tier": "Principal",
"website": "https://acme.example",
"logo": { "url": "https://..." }
}
],
"totalDocs": 8,
"limit": 100,
"totalPages": 1,
"page": 1,
"pagingCounter": 1,
"hasPrevPage": false,
"hasNextPage": false,
"prevPage": null,
"nextPage": null
}The keys match the field names from the type's definition. Read the definition first if you need the field list and labels.
Relationship response controls
Relationship, media, and file fields on a custom object can choose their Public API response shape.
| Setting | Response shape |
|---|---|
| Full record | Returns the expanded related record. |
| Summary | Returns a compact object with identifying fields such as id, title, name, label, slug, or url. |
| Reference only | Returns only the related record ID, or an array of IDs for fields that allow multiple values. |
For example, a transportation group might link to many transportation records. If the group endpoint only needs the IDs for a map lookup, set that relationship field to Reference only. If it only needs a title and URL, set it to Summary.
Get one instance by ID
GET {your-domain}/api/custom-objects/{handle}/{id}Returns a single instance, wrapped in a doc object, with the same field shape as items in the list response.
Errors
| Status | Meaning |
|---|---|
400 | The instance ID is malformed. |
404 | No object type with that handle exists, the type is not exposed in the public API, or no instance with that ID exists for it. |
500 | Server error. |
Examples
Render a sponsor wall:
const res = await fetch('/api/custom-objects/sponsor?limit=100');
const { docs } = await res.json();
for (const sponsor of docs) {
const { title, tier, website, logo } = sponsor;
// tier, website, logo?.url
}Caching
Responses are cacheable at the edge and refresh when an editor publishes a change to a definition or an instance. Keep query parameters stable across visitors so responses stay cacheable.
See also
- Custom objects — define custom content types from the admin.
- Custom data — when to reach for custom objects versus custom attributes.
- Content endpoints — read the built-in content types.