# Records

Records zijn de contenthelft van de Objecten-module. Het lijst-endpoint is het enige gepagineerde endpoint op de Objecten-API en ondersteunt sortering, vrije-tekstzoeken en filteren per property op de recordwaarden. Alle drie de endpoints vereisen de scope `objects:read`, en record-`values` bevatten uitsluitend actieve (niet-gearchiveerde) propertykeys. Ze leveren alleen gepubliceerde content: op een type met publicatiestap ontbreken concepten en records die voor de toekomst zijn ingepland in de lijst en geven ze `404` wanneer je ze rechtstreeks ophaalt (zie [Publiceren en zichtbaarheid](./index#publiceren-en-zichtbaarheid)). Gelokaliseerde waarden zijn locale-maps die zijn teruggesneden tot de ingeschakelde talen van de winkel, en `media`-waarden zijn mediaobjecten (zie [Mediawaarden](./index#mediawaarden)).

## GET /v1/api/objects/types/{key}/records

Gepagineerde lijst van records van één objecttype, geadresseerd via de key van het type (uit `GET /v1/api/objects/types`).

### Path-parameters

| Naam | Type | Verplicht | Beschrijving |
| --- | --- | --- | --- |
| `key` | string | Ja | De objecttype-key, bijvoorbeeld `faq`. |

### Query-parameters

| Naam | Type | Verplicht | Beschrijving |
| --- | --- | --- | --- |
| `sort` | string | Nee | Sorteerkolom: `created_at` of een willekeurige actieve propertykey. Prefix met `-` voor aflopend. Standaard `-created_at`. `number`- en `money`-properties sorteren numeriek, `date`-properties sorteren als datums; records zonder waarde voor de property sorteren als laatste. |
| `q` | string | Nee | Hoofdletterongevoelige substring-zoekopdracht, met OR over alle `text`- en `textarea`-properties van het type. Bij een gelokaliseerde property wordt de taal van `locale` doorzocht (de standaardtaal van de winkel als die ontbreekt). Wordt genegeerd (matcht alles) wanneer het type geen tekstproperties heeft. |
| `filter[{propertyKey}]` | string | Nee | Exact-match-filter op één property. Booleans accepteren `true`, `false`, `1`, `0`. `select` matcht de optiestring. Filteren op `status` kan niet op de publieke API, omdat elk record al gepubliceerd is; `filter[status]` geeft `422`, tenzij het type een property met de key `status` heeft. Herhaalbaar voor meerdere properties; meerdere filters combineren met AND. `filter[{propertyKey}]` op een `tags`-property matcht records waarvan de lijst exact die tag bevat; op een `record_ref_list`-property records waarvan de lijst dat record-id bevat; op een `record_ref` records die naar dat id verwijzen. Een waarde die een array is geeft `422` op `filter`. Een `color`-property matcht op gelijkheid, ongeacht hoofdletters (`#1a2b3c` vindt `#1A2B3C`). |
| `filter[{propertyKey}][from]` | string | Nee | Ondergrens (inclusief). Alleen voor `number`-, `money`- en `date`-properties. Datums als `YYYY-MM-DD`, geld in centen. |
| `filter[{propertyKey}][to]` | string | Nee | Bovengrens (inclusief). Zelfde types en formaten als `from`. `from` en `to` kunnen gecombineerd of los gebruikt worden. |
| `per_page` | integer | Nee | Paginagrootte. Standaard 25, begrensd op het bereik 1 tot 100. |
| `page` | integer | Nee | Paginanummer, standaard 1. |
| `locale` | string | Nee | Een voor de winkel ingeschakelde taaltag, bijvoorbeeld `nl`. Gelokaliseerde `filter[...]`, `sort` en `q` gebruiken deze taal; de standaardtaal van de winkel als die ontbreekt. Een taal die niet is ingeschakeld valt hier terug op de standaardtaal (het by-slug-endpoint antwoordt in plaats daarvan met `422`). |
| `include` | string | Nee | `refs` klapt recordverwijzingen uit (zie [Verwijzingen uitklappen](#verwijzingen-uitklappen)). Kommalijst of `include[]=refs`; andere tokens worden genegeerd. |

```bash title="Request"
curl --globoff "https://api.borkol.com/v1/api/objects/types/faq/records?sort=-created_at&q=delivery&filter[category]=shipping&per_page=10" \
  -H "Authorization: Bearer {api_key}"
```

```javascript title="Request (JS)"
const params = new URLSearchParams({
  sort: "-created_at",
  q: "delivery",
  "filter[category]": "shipping",
  per_page: "10",
});
const res = await fetch(
  `https://api.borkol.com/v1/api/objects/types/faq/records?${params}`,
  { headers: { Authorization: `Bearer ${apiKey}` } },
);
const { data, meta } = await res.json();
```

Status: `200 OK`. Elk record is `{id, values, published_at, created_at}`, plus `slugs` (taaltag naar adres) wanneer het type adressen heeft. De response gebruikt de standaard Laravel-paginatie-envelope: `data` (de records), `links` (`first`-, `last`-, `prev`-, `next`-pagina-URL's, `null` waar afwezig) en `meta` (`current_page`, `from`, `last_page`, `links`, `path`, `per_page`, `to`, `total`).

```json title="Response"
{
  "data": [
    {
      "id": "5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9",
      "values": {
        "name": "How long does delivery take?",
        "answer": "Orders ship within 2 business days.",
        "category": "shipping"
      },
      "published_at": "2026-08-01T09:15:00.000000Z",
      "created_at": "2026-08-01T09:15:00.000000Z",
      "slugs": { "en": "how-long-does-delivery-take" }
    }
  ],
  "links": {
    "first": "https://api.borkol.com/v1/api/objects/types/faq/records?page=1",
    "last": "https://api.borkol.com/v1/api/objects/types/faq/records?page=3",
    "prev": null,
    "next": "https://api.borkol.com/v1/api/objects/types/faq/records?page=2"
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 3,
    "links": [
      { "url": null, "label": "&laquo; Previous", "active": false },
      { "url": "https://api.borkol.com/v1/api/objects/types/faq/records?page=1", "label": "1", "active": true },
      { "url": "https://api.borkol.com/v1/api/objects/types/faq/records?page=2", "label": "2", "active": false },
      { "url": "https://api.borkol.com/v1/api/objects/types/faq/records?page=3", "label": "3", "active": false },
      { "url": "https://api.borkol.com/v1/api/objects/types/faq/records?page=2", "label": "Next &raquo;", "active": false }
    ],
    "path": "https://api.borkol.com/v1/api/objects/types/faq/records",
    "per_page": 10,
    "to": 10,
    "total": 25
  }
}
```

### Verwijzingen uitklappen

Standaard is een `record_ref`-waarde de id van het gekoppelde record en een `record_ref_list`-waarde een lijst van id's. Geef `include=refs` (of `include[]=refs`) mee om de gekoppelde records inline te krijgen. Dit werkt op de lijst, op `GET /v1/api/objects/records/{id}` en op het by-slug-endpoint, en omvat verwijzingen op het hoogste niveau, in herhaalblokrijen, in sectiedata en in gelokaliseerde waarden.

Een uitgeklapt record is `{id, type_key, values, slugs?, published_at}`: `slugs` is alleen aanwezig als het type van het doel adresinstellingen (slug) heeft, en `values` heeft dezelfde vorm als bij elk publiek record (gelokaliseerde maps teruggesneden tot de ingeschakelde talen, `media` als objecten). Uitklappen gaat maar één niveau diep: verwijzingen binnen een uitgeklapt record blijven id's. Alleen publiek zichtbare doelen worden uitgeklapt; een doel dat een concept, ingepland, verwijderd of niet aanwezig is, valt weg, dus een `record_ref` wordt `null` en het item verdwijnt uit een `record_ref_list`. Onbekende `include`-tokens worden genegeerd. De gekoppelde records van een hele pagina worden samen geladen, dus de kosten van het verzoek groeien niet per record.

```bash title="Request"
curl "https://api.borkol.com/v1/api/objects/types/service/records?include=refs" \
  -H "Authorization: Bearer {api_key}"
```

```json title="Response"
{
  "data": [
    {
      "id": "7a8b9c0d-1e2f-4a3b-84c5-d6e7f8a9b0c1",
      "values": {
        "name": "Kitchen fitting",
        "author": {
          "id": "3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f",
          "type_key": "team_member",
          "values": { "name": "Sam Jansen" },
          "slugs": { "en": "sam-jansen" },
          "published_at": "2026-09-01T10:00:00.000000Z"
        },
        "related": []
      },
      "published_at": "2026-10-01T08:00:00.000000Z",
      "created_at": "2026-09-28T13:20:00.000000Z",
      "slugs": { "en": "kitchen-fitting" }
    }
  ]
}
```

### Fouten

- `404` wanneer geen objecttype die key heeft.
- `422` met `errors.sort` `["Cannot sort by {column}."]` wanneer `sort` iets noemt dat noch `created_at` noch een actieve propertykey is.
- `422` met `errors.filter` `["Cannot filter by {field}."]` wanneer een filter een onbekende of gearchiveerde property noemt (ook `status`), of een array (`from`/`to`) meegeeft aan een property die niet `number`, `money` of `date` is.
- `422` met `errors.filter` `["Invalid filter value for {field}."]` wanneer een `number`- of `money`-waarde of -grens niet numeriek is, of een `date`-waarde of -grens geen geldige `YYYY-MM-DD`-datum is.
- `403` `{"error":"Module not enabled: objects"}` en `403` `{"message":"Invalid ability provided."}` bij module- en scope-fouten.

## GET /v1/api/objects/types/{key}/records/by-slug/{slug}

Haalt één record op via zijn adres in één taal. Gebruik het om een storefront-URL op te lossen: haal het voorvoegsel van het type voor de taal van het pad af en geef de rest mee als `slug`. Alleen gepubliceerde, op dat moment zichtbare records matchen, en een adres wordt binnen de ene taal gematcht dat je opgeeft.

### Path-parameters

| Naam | Type | Verplicht | Beschrijving |
| --- | --- | --- | --- |
| `key` | string | Ja | De objecttype-key, bijvoorbeeld `service`. |
| `slug` | string | Ja | Het adres van het record in de gevraagde taal, bijvoorbeeld `keukenmontage`. |

### Query-parameters

| Naam | Type | Verplicht | Beschrijving |
| --- | --- | --- | --- |
| `locale` | string | Nee | Een voor de winkel ingeschakelde taaltag, bijvoorbeeld `nl`. Standaard de standaardtaal van de winkel. |
| `include` | string | Nee | `refs` klapt recordverwijzingen uit, net als bij de lijst. Zie [Verwijzingen uitklappen](#verwijzingen-uitklappen). |

```bash title="Request"
curl "https://api.borkol.com/v1/api/objects/types/service/records/by-slug/keukenmontage?locale=nl" \
  -H "Authorization: Bearer {api_key}"
```

Status: `200 OK`, met het record in dezelfde vorm als de items van de lijst.

```json title="Response"
{
  "data": {
    "id": "7a8b9c0d-1e2f-4a3b-84c5-d6e7f8a9b0c1",
    "values": {
      "name": { "en": "Kitchen fitting", "nl": "Keukenmontage" },
      "cover": {
        "id": "2b3c4d5e-6f7a-4b8c-9d0e-1f2a3b4c5d6e",
        "url": "https://cdn.borkol.com/t/abc/kitchen.webp",
        "alt": "A fitted oak kitchen",
        "width": 1600,
        "height": 900,
        "mime_type": "image/webp"
      }
    },
    "published_at": "2026-10-01T08:00:00.000000Z",
    "created_at": "2026-09-28T13:20:00.000000Z",
    "slugs": { "en": "kitchen-fitting", "nl": "keukenmontage" }
  }
}
```

Hernoemt een merchant een adres, dan wordt het oude adres hier niet meer geleverd. Er wordt alleen een redirect vastgelegd als het type voor die taal een niet-leeg adresvoorvoegsel heeft; los het oude pad op met [`GET /v1/api/redirects`](/nl/api/getting-started/seo) om bezoekers naar het nieuwe te sturen.

### Fouten

- `404` wanneer geen objecttype die key heeft, of geen zichtbaar record dat adres in die taal heeft (een concept of ingepland record geeft `404`).
- `422` met `errors.locale` `["This language is not enabled."]` wanneer `locale` geen ingeschakelde contenttaal van de winkel is.
- `403` module- en scope-fouten zoals hierboven.

## GET /v1/api/objects/records/{id}

Haalt één record op via zijn id. Dit werkt over alle objecttypes heen; je hoeft de typekey niet te kennen. `values` bevat alleen actieve propertykeys. Een `sections`-property bevat de sectiestapel; zie de [Objecten-conceptpagina](./index) voor de vorm van een sectie-instantie, inclusief locale-map-waarden op gelokaliseerde velden en mediaobjecten. Het record wordt alleen geleverd zolang het gepubliceerd en zichtbaar is.

### Path-parameters

| Naam | Type | Verplicht | Beschrijving |
| --- | --- | --- | --- |
| `id` | string (uuid) | Ja | Het record-id. |

### Query-parameters

| Naam | Type | Verplicht | Beschrijving |
| --- | --- | --- | --- |
| `include` | string | Nee | `refs` klapt recordverwijzingen uit, net als bij de lijst. Zie [Verwijzingen uitklappen](#verwijzingen-uitklappen). |

```bash title="Request"
curl https://api.borkol.com/v1/api/objects/records/6f7a8b9c-0d1e-4f2a-b3c4-d5e6f7a8b9c0 \
  -H "Authorization: Bearer {api_key}"
```

Status: `200 OK`.

```json title="Response"
{
  "data": {
    "id": "6f7a8b9c-0d1e-4f2a-b3c4-d5e6f7a8b9c0",
    "values": {
      "name": "About us",
      "body": [
        {
          "_key": "sec_a1b2c3d4e5f60718293a4b5c",
          "type": "hero",
          "look": "default",
          "v": 1,
          "visible": true,
          "data": {
            "title": { "en": "Welcome to our shop" },
            "image": {
              "id": "2b3c4d5e-6f7a-4b8c-9d0e-1f2a3b4c5d6e",
              "url": "https://cdn.borkol.com/t/abc/hero.webp",
              "alt": "Our shop front",
              "width": 1600,
              "height": 900,
              "mime_type": "image/webp"
            },
            "cta": { "url": "/products", "label": "Shop now" }
          }
        }
      ]
    },
    "published_at": "2026-07-20T14:05:33.000000Z",
    "created_at": "2026-07-20T14:05:33.000000Z"
  }
}
```

### Fouten

- `404` wanneer het record niet bestaat voor deze winkel, of een concept is of voor de toekomst is ingepland.
- `403` module- en scope-fouten zoals hierboven.
