Skip to main content
Skip table of contents

Rapportage API setup

Vooraf

Deze pagina beschrijft hoe je rapportage opzet binnen een Skryv‑applicatie via de Rapportage API. Je leert hoe je toegang verkrijgt met mutual TLS en hoe je de beschikbare endpoints (/mapping en /search, /search/scroll) correct aanspreekt. De voorbeelden zijn gebaseerd op Elasticsearch Query DSL en tonen typische rapportage‑ en exportscenario’s. De volledige OpenAPI-specificatie vind je op de rapportage API specificatie pagina.

Deze documentatie richt zich op developers die vertrouwd zijn met REST‑API’s en Elasticsearch Query DSL.

Toegang

Certificaat aanvragen

De endpoints zijn beveiligd met mutual SSL/TSL (Transport Layer Security), dus als API-consumer moet je een CSR (Certificate Signing Request) aanmaken. Deze CSR wordt naar Skryv gestuurd en in ruil ontvang je het bijbehorende certificaat, ondertekend door de Root CA (Certificate Authority) die door de API-gateway wordt vertrouwd.

Op macOS kun je de volgende commando’s uitvoeren om een CSR te genereren:

BASH
# generate a private key
openssl genrsa -out my_client.key 2048
# generate a CSR based on the private key
openssl req -new -key my_client.key -out my_client.csr

Op basis van deze CSR wordt binnen de Skryv applicatie vervolgens een certificaat aangemaakt waarmee de mutual SSL/TSL-authenticatie met de endpoints kan worden opgezet.

Certificaat vernieuwen

Een clientcertificaat voor productie is maximaal 1 jaar geldig, maar de exacte geldigheidsduur kan per implementatie worden bepaald. Dit betekent dat het clientcertificaat periodiek vernieuwd moet worden in de omgeving van de klant. Het proces is hetzelfde als bij het aanvragen van het initiële certificaat:

  1. De klant genereert een nieuwe Certificate Signing Request (CSR).

  2. De klant bezorgt deze CSR aan Skryv.

  3. Skryv levert in ruil een nieuw clientcertificaat af dat voor de Rapportage API gebruikt kan worden.

Enkele weken vóór de vervaldatum van het certificaat stuurt Skryv een e‑mail met de vraag om een nieuwe CSR aan te maken. Na ontvangst van de CSR stuurt Skryv het nieuwe certificaat terug.

De root‑CA (Root Certificate) is maximaal 5 jaar geldig. De precieze geldigheidsduur kan afgestemd worden op de beveiligingsvereisten. Opgelet: een clientcertificaat mag nooit een vervaldatum hebben die na de vervaldatum van het rootcertificaat ligt. Als het rootcertificaat vernieuwd wordt, is ook een nieuw clientcertificaat nodig.

Endpoints

Er zijn drie endpoints beschikbaar.

Endpoint

Methode

Omschrijving

/mapping

GET

Haal de index/mapping op

/search

POST

Zoek in de index

/search/scroll

POST

Volgende batch resultaten via scroll

Base URL: <https://<yourApp>>/ (afhankelijk van je omgeving: test, acceptatie, productie).

Mapping endpoint

Een GET naar het /mapping‑endpoint geeft het technische datamodel van alle velden terug.

Voorbeeld response

In dit voorbeeld is aanvraagHaltes.naamGemeente een text‑veld binnen document (een formulier).

JSON
{
  "skryv-1666003722467": {
    "mappings": {
      "document_model": {
        "properties": {
          "allTasks": { ... },
          "allUsers": { ... },
          "document": {
            "properties": {
              "aanvraagHaltes": {
                "properties": {
                  "naamGemeente": {
                    "type": "text"
                  }
                }
              }
            }
          },
          "dossier": { ... },
          "lastMilestone": { ... },
          "milestones": { ... },
          "process": { ... },
          "task": { ... }
        }
      }
    }
  }
}

Voorbeeld vervolgquery

Hiermee kan je een vervolgquery bouwen om alle dossiers te vinden waar naamGemeente “Gemeente Dilbeek” bevat. Zie /search (hieronder) voor meer info over de syntax.

JSON
{
  "query": {
    "bool": {
      "filter": [
        {
          "nested": {
            "path": "document",
            "query": {
              "match_phrase_prefix": {
                "document.aanvraagHaltes.naamGemeente": {
                  "query": "Gemeente Dilbeek"
                }
              }
            }
          }
        },
        { "bool": { "should": [{ "term": { "type": "document" } }] } }
      ]
    }
  },
  "sort": [
    {
      "document.updatedAt": {
        "order": "desc",
        "mode": "min",
        "nested": { "path": "document" }
      }
    }
  ],
  "from": 0,
  "size": 20
}

Search endpoint

Het /search‑endpoint ondersteunt POST‑requests met een ElasticSearch Query DSL‑body.

Requests

Voorbeeld curl‑request waarbij gezocht wordt op dossiers waarvan het het dossierlabel start met de string “22-”. De resultaten worden gesorteerd volgens de eigenschap latestActivity.

BASH
curl --key my_client.key --cert my_client.crt \
  --location \
  --request POST '<https://example.com/search'> \
  --header 'Content-Type: application/json' \
  --data-raw '{
    "query": {
        "bool": {
            "filter": [
                {
                    "nested": {
                        "path": "dossier",
                        "query": {
                            "match_phrase_prefix": {
                                "dossier.label": {
                                    "query": "22-"
                                }
                            }
                        }
                    }
                },
                {
                    "bool": {
                        "should": [
                            {
                                "term": {
                                    "type": "dossier"
                                }
                            }
                        ]
                    }
                }
            ]
        }
    },
    "sort": [
        {
            "dossier.latestActivity": {
                "order": "desc",
                "mode": "min",
                "nested": {
                    "path": "dossier"
                }
            }
        }
    ],
    "from": 0,
    "size": 20
}' 

Paginering

Gebruik de velden from en size in de request‑body om door de resultaten te pagineren.
Omdat de index groot kan zijn, hou je size best beperkt en vermijd je parallelle bulk‑requests.

Scroll

Voor bulkexport gebruik je de Elasticsearch Scroll API. Dit is de enige performante manier om grote hoeveelheden data te exporteren zonder de productie‑omgeving te belasten.

Voorbeeld

Eerste request met scroll-parameter. Stuur eerst je query zoals bij /search, maar voeg een scroll‑parameter toe in de URL. De waarde van scroll is een periode (time unit) die aangeeft hoelang de zoekcontext “open” moet blijven tussen twee requests. Deze periode moet langer zijn dan de tijd tussen opeenvolgende requests, anders verlies je de context. Hou de periode bij voorkeur zo kort mogelijk (bv. 10s, 30s), afgestemd op je verwerkingssnelheid.

Voorbeeld URL:

<https://reporting.example.com/search?scroll=10s>

De request‑body blijft identiek aan een normale /search‑query.

Eerste response met _scroll_id.

In de response krijg je:

  • de eerste batch resultaten (hits.hits)

  • een _scroll_id dat je nodig hebt voor de volgende batch

JSON
{
  "_scroll_id": "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAEmgWd3UwWlM3VlRRNnlfcWd4alJsTUU0dw==",
  "took": 5,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 369,
    "max_score": null,
    "hits": [
      ...
    ]
  }
}

Gebruik dit scroll_id om de volgende batch resultaten op te halen via een request naar <<https://reporting.example.com/search/scroll>> met onderstaande body.

MARKDOWN
{
  "scroll": "10s",
  "scroll_id": "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAEmkWd3UwWlM3VlRRNnlfcWd4alJsTUU0dw=="
}

De scroll‑parameter in de body is verplicht. Zonder deze parameter wordt de zoekcontext gesloten.

De response bevat opnieuw een batch resultaten én een nieuw scroll_id, dat je op dezelfde manier kan gebruiken om de volgende batch op te vragen. Herhaal dit totdat hits.hits leeg is; daarna is de volledige resultset opgehaald.

search_after

Als bijkomend alternatief voor from + size kun je search_after gebruiken. Dit is efficiënter voor diepe paginatie.

Voorbeeld

Initiële query (vereenvoudigd voorbeeld).

JSON
{
  "_source": [ "dossier" ],
  "query": {
    "bool": {
      "filter": [
        {
          "query_string": {
            "query": "dossier.label:2?-EXAMPLE-*",
            "default_operator": "AND"
          }
        },
        { "term": { "type": "dossier" } }
      ]
    }
  },
  "sort": [
    {
      "document.aanvraag.aanvraagdatum": {
        "order": "asc",
        "mode": "min",
        "nested": { "path": "document" }
      }
    },
    { "dossier.createdAt": "asc" }
  ],
  "size": 1
}

De response bevat het eerste dossier.

CODE
{
    "took": 9,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": 10954,
        "max_score": null,
        "hits": [
            {
                "_index": "skryv-1664526384453",
                "_type": "document_model",
                "_id": "938127f4-ca56-4b99-9d1c-97708ebe56ed",
                "_score": null,
                "_source": {
                },
                "sort": [
                    1664496000000,
                    1664575232000
                ]
            }
        ]
    }
}

De response hierboven bevat bovendien voor elke hit een sort‑array.

JSON
"sort": [
  1664496000000,
  1664575232000
]

Gebruik deze waarden in de volgende request via search_after.

JSON
{
  "_source": [ "dossier" ],
  "query": {
    "bool": {
      "filter": [
        {
          "query_string": {
            "query": "dossier.label:2?-EXAMPLE-*",
            "default_operator": "AND"
          }
        },
        { "term": { "type": "dossier" } }
      ]
    }
  },
  "sort": [
    {
      "document.aanvraag.aanvraagdatum": {
        "order": "asc",
        "mode": "min",
        "nested": { "path": "document" }
      }
    },
    { "dossier.createdAt": "asc" }
  ],
  "search_after": [ 1664496000000, 1664575232000 ],
  "size": 1
}

Response structuur (search endpoint)

De responses van /search en /search/scroll volgen de standaard Elasticsearch-structuur.

Een typische response ziet er (sterk vereenvoudigd) zo uit:

JSON
{
  "took": 5,
  "timed_out": false,
  "hits": {
    "total": 369,
    "max_score": null,
    "hits": [
      {
        "_index": "skryv-1666003722467",
        "_type": "document_model",
        "_id": "…",
        "_score": null,
        "_source": {
          "dossier": { ... },
          "document": { ... },
          "process": { ... }
        },
        "sort": [
          1664496000000,
          1664575232000
        ]
      }
    ]
  }
}

Enkele belangrijke velden.

  • hits.total: het totaal aantal resultaten voor je query.

  • hits.hits: array met individuele resultaten.

    • ._source bevat de Skryv-data die je doorgaans nodig hebt (bv. dossier, document, process, …).

    • sort bevat de sort-sleutel wanneer je sort in je query gebruikt. Gebruik deze sort-array als input voor search_after bij diepe paginatie.

Voor exports of integraties werk je doorgaans enkel met hits.hits[*]._source en, indien relevant, met hits.hits[*].sort (voor search_after).

Foutafhandeling en limieten

De Rapportage API hanteert voor alle endpoints (/mapping, /search, /search/scroll) dezelfde basisresponsen.

200 OK

De request werd correct verwerkt.

  • /mapping: lijst van beschikbare velden en types die je in queries kan gebruiken.

  • /search: aggregaties of een lijst van dossiers/documenten, afhankelijk van je query.

  • /search/scroll: de volgende batch resultaten op basis van de aangeleverde scroll_id

403 Forbidden

De request is geweigerd. Controleer of je het juiste clientcertificaat en de bijbehorende private key meestuurt bij de request (mutual TLS). Dit geldt voor alle endpoints: zonder geldig certificaat wordt geen enkele Rapportage API‑request aanvaard.

500 Internal Server Error

Deze fout kan om verschillende redenen optreden, maar de meest waarschijnlijke is dat de Rapportage API enkele weken niet gebruikt werd. In dat geval gaat de API in een “inactive” staat om cloud‑resources te besparen. Bij de eerstvolgende requests wordt de API automatisch gereactiveerd. Tijdens deze heractivatie (typisch 2–3 minuten) kan je tijdelijk een 500 krijgen. Als het probleem langer dan 5 minuten aanhoudt, contacteer dan het Skryv team.

Richtlijnen rond gebruik en limieten

  • Gebruik bij grote exports altijd de scroll‑API (/search met scroll‑parameter + /search/scroll), of search_after voor diepe paginatie in plaats van grote from/size‑offsets.

  • Beperk de payload. Maak gebruik van het Elasticsearch‑veld _source om enkel de nodige velden op te halen.

  • Vermijd parallelle bulk‑requests. Hou size per request redelijk en verdeel grote exports over meerdere iteraties via scroll of search_after.

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.