API reference
A small, read-only JSON API over the component catalogue. It's the shape every app in the family follows for its own API.
Base address
https://foundry.mashreeves.com/api/v1 Authentication
None. Everything here is public sample data.
Version
v1.0, in the path. A breaking change gets /v2.
Errors
application/problem+json (RFC 9457), with a title and detail.
/api/v1/components
List components, optionally filtered and paginated.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
q |
query | string | Filter by name or category (case-insensitive substring). |
page |
query | integer Default 1 | Page number, 1-based. |
per_page |
query | integer Default 8 1 to 50 | Items per page, 1-50. |
Example request
curl -H "Accept: application/json" https://foundry.mashreeves.com/api/v1/components
Try it
Responses
200 A page of components.
{
"data": [
{
"slug": "stat-card",
"name": "Stat card",
"category": "Data",
"status": "stable",
"used_in_apps": 4,
"updated_at": "2026-08-02"
}
],
"meta": {
"page": 1,
"total_pages": 3,
"total": 22,
"per_page": 8
}
}
304 Not modified - the client's If-None-Match matched.
400 per_page out of range.
/api/v1/components/{slug}
Fetch one component by its slug.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
slug Required |
path | string |
Example request
curl -H "Accept: application/json" https://foundry.mashreeves.com/api/v1/components/stat-card
Try it
Responses
200 The component.
404 No component with that slug.
Caching with ETag
Every response carries an ETag. Send it back as If-None-Match and, if nothing changed, you get 304 Not Modified with no body, so polling costs almost nothing.
Errors
Anything that goes wrong answers application/problem+json: a status, a short title and a detail written for a person.
{
"type": "about:blank",
"title": "Not Found",
"status": 404,
"detail": "No component with slug \"not-a-component\".",
"instance": "/api/v1/components/not-a-component"
}