Making requests
How to target an organization, choose a format, read identifiers and dates, and get content in the right language.
Target an organization
Loupe hosts many libraries. Most requests say which one they are about, in one of three ways depending on the endpoint.
Collections take an organization.slug (or organization.id) query parameter. Without it, the API answers 400 Missing organization filter.
curl "https://api.loupe.ch/api/public/cms-events?organization.slug=riveville"Single items are fetched by slug with the /item endpoint of the collection:
curl "https://api.loupe.ch/api/public/cms-events/item?organization.slug=riveville&slug=story-time"Some endpoints take the organization in the path or in the request body instead, for example /api/public/organizations/{slug} or the organization field of a catalogue search. Each guide shows the exact form.
When a manager endpoint takes no organization parameter, it works on the organization of the key's owner.
Choose a format
The API speaks JSON in two flavours, selected with the Accept header:
Accept | Response |
|---|---|
application/ld+json | JSON-LD: objects carry @id and @type, and collections are wrapped with member, totalItems and pagination links in view |
application/json | Plain JSON: objects only, and collections are plain arrays |
Use JSON-LD when you need totals and pagination links; use plain JSON when you just want the data. Send bodies as application/json. For PATCH, use application/merge-patch+json: only the fields you send are changed.
A JSON-LD collection looks like this:
{ "@context": "/api/contexts/CmsEvent", "@id": "/api/public/cms-events", "@type": "Collection", "totalItems": 124, "member": [ { "@id": "/api/public/cms-events/0199…", "@type": "CmsEvent", "id": "0199…", "title": "Story time" } ], "view": { "@id": "/api/public/cms-events?organization.slug=riveville&page=1", "next": "/api/public/cms-events?organization.slug=riveville&page=2" }}Identifiers
Resources are identified by UUIDs (id). In JSON-LD, related resources may appear as IRIs, the path of the resource, such as /api/files/0199…. Slugs are stable, human-readable identifiers you can use in URLs; they are unique within an organization.
Fields with no value are returned as null rather than omitted, so your code can rely on the shape of an object.
Dates and times
Timestamps such as createdAt are ISO 8601 with a time zone offset. A few fields use simpler, local formats because they describe the library's calendar rather than an instant:
| Field | Format | Example |
|---|---|---|
| Most timestamps | ISO 8601 | 2026-10-12T09:30:00+02:00 |
Event startAt, endAt | Y-m-d H:i | 2026-10-17 14:00 |
Reservation startAt, endAt | Y-m-d H:i:s | 2026-10-17 14:00:00 |
publishedAt | Y-m-d | 2026-10-01 |
Local times are in the library's time zone.
Languages
Content that a library translates (titles, descriptions, pages) comes back in one language per request. Choose it with the locale query parameter, using a two-letter code:
curl "https://api.loupe.ch/api/public/cms-events?organization.slug=riveville&locale=de"Without locale, you get the organization's default language. A language the organization does not publish falls back to that default, and an unknown code returns 400. The response tells you which language you received in its Content-Language header. The Accept-Language header is not used.
Conditional requests
Map definitions carry an ETag. Send it back in If-None-Match and the API answers 304 Not Modified when nothing changed, which saves you from downloading a large document again.