Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Swagger integration
{
  "openapi": "3.0.0",
  "info": {
    "title": "Certificates Endpoint",
    "version": "1.0",
    "description": "# Certificates API\n\nThis documentation contains the API description that is expected from a source of certifcatescertificates that is supplying certificates to the Burgerprofiel platform of the Flemish Government.\n\n## Reasoning for an API definition\n\nFrom the point of view of the Burgerprofiel platform, we can easily onboard new sources of certificates to the platform. All partners which comply to this API definition merely require a little bit of configuration, after which all certificates can easily flow in the platform.\n\n# API specifications\n\n## JSON\nWe standardize on ```application/hal+json```. This specific form of JSON flags that the payload is HATEOAS compliant.\n\n## Layout\n\n### URL's and versioning\nWe advise you to follow our example, and put a version in the URL. Debates are going on strongly about whether or not to use a ```v1``` in your URL, but it is a pragmatic choice we implement in our API's. \nThe version parameter is always a natural number, ie ```v1```, ```v2```, ...\nWithin a certain version, breaking changes **can never occur**. If you introduce breaking changes, the next version should be released.\n\nA typical URL for your endpoint would look like: ```https://<hostname>/v1/certificates/<ssn>?limit=10&page=0``` \n\n### Required fields\nWe have carefully documented which fields are optional, and which are not. Please refer to the OpenAPI documentation of the API for more information. \n\nIf you want, more fields can be added. We will not interpret them, however. We only interpret the fields that we have specified in the specification. \n\n### Certificates listing\nThis is the most important endpoint you need to provide. It needs to return a list of certificates which are relevant for the user. The user can be identified via his/her social security number (ssn) (= INSZ/NISS).\nThe list is essentially a list of Certificate Detail items. Refer to the OpenAPI documentation of the API for more information. \n\nLinks have to be provided for the client to be able to navigate through the different pages of the certificates. For more information, refer to the HATEOAS section and the examples.\n\nThe response needs to be paginated at all times. Page metadata should be delivered in the payload, so the client knows how many certificates there are, which page it is on, etc. Please refer to the examples. \n\n**_Notes_**\n\n* The URL has a ```page``` parameter, which should be 0-based. If 0 is passed, the first page should be returned.\n* In the page metadata, nothing is 0-based, but everything is 1-based. So, for example, the ```number``` parameter should have the value 1 on the first page. \n\n#### Model specifics\n\n* **certificates (required)**: list of certificates. Essentially, a list of Certificate Detail items (see below). \n\nIf no certificates can be found for the provided SSN, this should be an empty list. \n\n#### Request (example)\n\n**_Headers_**: ```Authorization: Bearer XyZAbCd1234```\n\n**_Method_**: GET\n\n**_URL_** ```https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302?limit=10&page=0``` \n\n#### Response (example)\n\n```\n{\n  \"certificates\": [\n    {\n      \"id\": \"85144567-7043-4469-9e79-279f4eb31e27\",\n      \"language\" : \"nl\",\n      \"name\": \"Dienstencheques 2019\",\n      \"year\": 2019,\n      \"links\": [\n        {\n          \"rel\": \"self\",\n          \"href\": \"https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/85144567-7043-4469-9e79-279f4eb31e27/nl\"\n        },\n        {\n          \"rel\": \"download\",\n          \"href\": \"https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/85144567-7043-4469-9e79-279f4eb31e27/nl/download\"\n        }\n      ]\n    }\n  ],\n  \"pageMetadata\": {\n    \"number\": 1,\n    \"size\": 10,\n    \"totalElements\": 40,\n    \"totalPages\": 4\n  },\n  \"links\": [\n    {\n      \"rel\": \"self\",\n      \"href\": \"https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302?limit=10&page=0\"\n    },\n    {\n      \"rel\": \"next\",\n      \"href\": \"https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302?limit=10&page=1\"\n    },\n    {\n      \"rel\": \"start\",\n      \"href\": \"https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302?limit=10&page=0\"\n    },\n    {\n      \"rel\": \"last\",\n      \"href\": \"https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302?limit=10&page=3\"\n    }\n  ]\n}\n```\n\n#### Paging and limits\n\n**_Paging required_**\n\nAs stated above, we require that the response is paginated **when you return a collection**. In the URL's, this is shown by the presence of two parameters:\n* ```page```: defines the page number (0-based)\n* ```limit```: defines the number of items on a single page (evidently, 1-based)\n\n**Paged returns are, evidently, only required when you return a collection. A detail of a single certificate does not require a paged return.**\n\n**_Limit can be chosen by the client of the API_**\n\nThe page and limit parameters are present in the URL: ```https://<hostname>/v1/certificates/<ssn>?limit=10&page=0```.\nThe limit parameter can be directed by the client of the API. If the client asks for 10 items, 10 should be returned. If the client wants 50 results, 50 should be returned. \n\nThis can have a sensible upper limit, however. **Our suggestion would be to use 100 results as the upper limit.** That means that if a client asks for more than the upper limit, you default back to the upper limit you defined. \n\n**_Defaults when not defined_**\n\nThe API should fall back to sensible defaults if a client does not provide the ```page``` and ```limit``` parameters. \n\nThat means that these requests are all perfectly valid:\n* ```https://<hostname>/v1/certificates/<ssn>?limit=10&page=0``` \n* ```https://<hostname>/v1/certificates/<ssn>?limit=10```\n* ```https://<hostname>/v1/certificates/<ssn>?page=0```\n\nWhen the parameters are not provided, we suggest to use these defaults:\n* ```page```: when the page parameter is not present, the most logic choice is to return the first page.\n* ```limit```: when the limit parameter is not present, you can fall back to a sensible default - **we suggest you use 10**.    \n\n**_PageMetadata_**\n\nYou are required to provide metadata on the paging. This is done via a ```pageMetadata``` object in the response:\n\n```\n\"pageMetadata\": {\n    \"number\": 1,\n    \"size\": 10,\n    \"totalElements\": 40,\n    \"totalPages\": 4\n}\n```\n\nWe expect the object to contain 4 parameters:\n\n* ```number``` (**required**) the number of the page. This is a **1-based parameter**.\n* ```size``` (**required**) the number of the page in the total number of pages. This is a **1-based parameter**.\n* ```totalElements``` (**required**) the total number of elements in the collection. This is a **1-based parameter**.\n* ```totalPages``` (**required**) the total number of pages in the collection. This is a **1-based parameter**. \n\n#### No certificates found\n\nWhen no certificates can be found for a certain SSN, **we expect an empty collection as a return, _not an error 404_** (for more details, refer to Error Messages).  \n\n### Certificate detail\nBehind this link, more information about a certain certificate can be found. \n\nLinks have to be provided for the client to be able to discover specific functionalities, for example: downloading the certificate. For more information, refer to the HATEOAS section and the examples.\n\nAs said, you can add more fields here to the response, if you like. We will not interpret them, however. \n\n#### Primary key\n\nImportant to note here are the parameters that define a certificate. **The primary key of a certificate is its ID + its language**. That means that both have to be in the URL. It depends on your own design whether these are path parameters or query parameters. \n\nOur examples define them as path parameters. The choice is yours, however. Since we expect a HATEOAS design, we will simply discover the URL via your API. \n\n#### Model specifics\n\n* **id (_required_)**: the ID of the certificate.\n* **language (_required_)**: the language of the certificate. Should be in ISO639-1 format. More information: [https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes). Expected 1 of these 4: ```nl```, ```fr```, ```de```, ```en```. \n* **name (_required_)**: name of the certificate\n* **year** (_optional_): year when the certificate was handed out (if applicable)\n* **community** (_optional_): community where the certificate handed out (if applicable). Should be a NIS code. More information [https://statbel.fgov.be/nl/over-statbel/methodologie/classificaties/geografie](https://statbel.fgov.be/nl/over-statbel/methodologie/classificaties/geografie)   \n\n#### Request (example)\n\n**_Headers_**: ```Authorization: Bearer XyZAbCd1234```\n\n**_Method_**: GET\n\n**_URL_** ```https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/85144567-7043-4469-9e79-279f4eb31e27/nl``` \n\n#### Response (example)\n\n```\n{\n  \"id\": \"85144567-7043-4469-9e79-279f4eb31e27\",\n  \"language\" : \"nl\",\n  \"name\": \"certificate-1234\",\n  \"links\": [\n    {\n      \"rel\": \"self\",\n      \"href\": \"https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/85144567-7043-4469-9e79-279f4eb31e27/nl\"\n    },\n    {\n      \"rel\": \"download\",\n      \"href\": \"https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/85144567-7043-4469-9e79-279f4eb31e27/nl/download\"\n    }\n  ]\n}\n```\n\n## HATEOAS \n\n### Introduction\nIf the specification is followed, all API's will be HATEOAS (Hypermedia As The Engine Of Application State) compliant. Why is this compliancy so important? \n\nWithout going into too much detail about HATEOAS, this architectural component allows a REST client to fully discover an API, without any prior knowledge about it. It only needs to know the entrypoint of the API, and the client can crawl across the API using the relations (or ```rel```s) and corresponding references (or ```href```s). \n\nSpecifically for this case, it allows us to completely discover your API, without having to write a client with specific knowledge about your API. \n\n### How to implement\nYou can simply follow the examples to fully implement the compliancy. HATEOAS is added to your API, by specifying the ```links``` section. We expect the links section to be present in 2 situations: the certifications list; and the detail of a specific certificate.\n\n#### Links - Certificate list\nA typical links section in the certificates list will look like this:\n\n```\n\"links\": [\n    {\n      \"rel\": \"self\",\n      \"href\": \"https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302?limit=10&page=0\"\n    },\n    {\n      \"rel\": \"next\",\n      \"href\": \"https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302?limit=10&page=1\"\n    }\n    {\n      \"rel\": \"start\",\n      \"href\": \"https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302?limit=10&page=0\"\n    },\n    {\n      \"rel\": \"last\",\n      \"href\": \"https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302?limit=10&page=1\"\n    }\n]\n```\n\nWe expect 4 different relations:\n\n* ```self``` (**required**) the href specified points to the current page.\n* ```next``` (**required _only_ if there is a next page**) the href points to the next page in the paginated collection. Only needs to be present if there actually is a next page. **Should not be present if there is no next page.**\n* ```start``` (**required**) the href specified points to the start page of the collection.\n* ```last``` (**required**) the href specified points to the last page of the collection.\n\n#### Links - Certificate Detail\n\nA typical links section in a detail of a certificate will look like this: \n\n```\n\"links\": [\n    {\n      \"rel\": \"self\",\n      \"href\": \"https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/85144567-7043-4469-9e79-279f4eb31e27/nl\"\n    },\n    {\n      \"rel\": \"download\",\n      \"href\": \"https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/85144567-7043-4469-9e79-279f4eb31e27/nl/download\"\n    }\n]\n```\n\nWe expect 2 different relations:\n\n* ```self``` (**required**) the href specified points to the detail of the certificate.\n* ```download``` (**required**) the href contains the download link for the certificate. It needs to be a direct link, which can be streamed to the user.\n\n## Error messages\n\n### Introduction\n\nWhen an error occurs, we expect the API to return a correct HTTP response code, and a payload stating what the problem is. The problem detail should not reveal too much information, as this can be insecure.\n\nWe suggest to keep the return codes limited. Generally, 3 codes suffice: ```403 Access Denied```, ```404 Not Found```, ```500 Internal Server Error```. \n\nGenerally speaking, we expect a payload that contains:\n```\n{\n    \"title\": <Error title>,\n    \"detail\": <Error detail>,\n    \"status\": <HTTP error code>\n}\n```   \n\n### 403 Access Denied\n\n#### Context\n\nHas to be returned when the provided authentication fails. \n\n#### Examples\n\n* The provided token is incorrect.\n* The token provided was not for the SSN for which the certificates were requested.\n\n### Response (example)\n\n**_HTTP status code:_** 403\n\n**_Payload:_**\n```\n{\n    \"title\": \"An error occurred!\",\n    \"detail\": \"Access Denied\",\n    \"status\": 403\n}\n```\n\n### 404 Not Found\n\n#### Context\n\nHas to be returned when the specified certificate cannot be found. \n\n**Very important**: this can only occur for a _single certificate_.\nFor a collection, an empty list should be returned with **an empty collection**.  \n\n#### Examples\n\n* The detail link is not known. \n* The download link is not known. \n\n### Response (example)\n\n**_HTTP status code:_** 404\n\n**_Payload:_**\n```\n{\n    \"title\": \"An error occurred!\",\n    \"detail\": \"Could not find the certificate you are looking for.\",\n    \"status\": 404\n}\n```\n\n### 500 Internal Server Error\n\n#### Context\n\nHas to be returned when an internal server error occurs.   \n\n#### Examples\n\n* Any runtime exception in the platform. \n\n### Response (example)\n\n**_HTTP status code:_** 500\n\n**_Payload:_**\n```\n{\n    \"title\": \"An error occurred!\",\n    \"detail\": \"<description of the internal server error>\",\n    \"status\": 500\n}\n```\n\n## Security\n\n### ACM/IDM and OpenID Connect\nAt the Flemish Government, we make use of ACM/IDM for Access Control Management and Identity Management. It is a service, provided by the agency Het Facilitair Bedrijf, which manages most, if not all, of the identification and course grained authorization needs within the Flemish Government.\n\nWhen accessing the Burgerprofiel platform, a citizen logs in with his/her eID (or any of the approved alternatives, like ItsMe). An OAuth2 flow is triggered, and an id token is passed on to the backend to ensure those backends that it is the actual citizen who is accessing his/her own information. All systems are very firmly secured that a person can only access his/her own information.\n\n### Tokens and validation\nOur certificate service will pass on this token to your API, as a Bearer token in the Authorization header. More information about Bearer tokens can be found [here](https://tools.ietf.org/html/rfc6750). \n\nThe general layout of the header is: \n\n```Authorization: Bearer <token>```\n\nValidation of this token is very important. You need to implement validation for **all** of these items:\n* The token provided is actually an ID token. You should always verify if it is valid. Verification has 2 parts: getting the public keys of the JWKS endpoint; and doing the actual validation.\n    * You can cache these keys temporarily, if you don't want to collect them all the time. The JWKS endpoint can be found on this address:\n        * TNI: ```https://authenticatie-ti.vlaanderen.be/op/.well-known/openid-configuration```\n        * PRD: ```https://authenticatie.vlaanderen.be/op/.well-known/openid-configuration```\n    * Validation of the ID token itself (in casu: checking its signature) can be best done with any JOSE compliant library. You can find different libraries for different languages [here](https://jwt.io/#libraries-io).  \n* The audience for the token should be:\n    * For TNI: ```80689076-8c4a-4bef-abc4-82805e17988d``` \n    * For production: ```88f04968-d331-4ae0-99d9-c6efb845841f```.\n* The issuer for the token should be:\n    * For TNI: ```https://authenticatie-ti.vlaanderen.be/op```\n    * For production: ```https://authenticatie.vlaanderen.be/op```\n* Social security number: in the claims inside the token, you will find the ```rrn``` claim. That claim contains the social security number of the user. It needs to match **exactly** with the path parameter containing the social security number in your URI. If not, users could potentially retrieve certificates of other users.\n\n### Wait - did you say an ID token?\n\nYes, the implementation at this point relies on an ID token rather than access tokens. \nThat means that this is implicit authorization: you are guaranteed that the actual citizen started the flow, not of the actual authorization of the citizen in question. The authorization is granted, however, since a citizen can access all information about him/her.   \n"
  },
  "servers": [
    {
      "url": "https://burgerprofiel.vlaanderen.be/v1",
      "description": "Burgerprofiel"
    }
  ],
  "paths": {
    "/certificates/{ssn}": {
      "get": {
        "tags": [
          "Certificates"
        ],
        "summary": "Certificates List",
        "parameters": [
          {
            "name": "ssn",
            "in": "path",
            "description": "Social security number",
            "required": true,
            "style": "simple",
            "explode": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/hal+json": {
                "schema": {
                  "$ref": "#/components/schemas/List-Certificates"
                },
                "examples": {
                  "Full Example": {
                    "value": {
                      "certificates": [
                        {
                          "id": "85144567-7043-4469-9e79-279f4eb31e27",
                          "language": "nl",
                          "name": "Dienstencheques 2019",
                          "year": 2019,
                          "links": [
                            {
                              "rel": "self",
                              "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/85144567-7043-4469-9e79-279f4eb31e27/nl"
                            },
                            {
                              "rel": "download",
                              "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/85144567-7043-4469-9e79-279f4eb31e27/nl/download"
                            }
                          ]
                        },
                        {
                          "id": "85144567-7043-4469-9e79-279f4eb31e27",
                          "language": "en",
                          "name": "Dienstencheques 2019",
                          "year": 2019,
                          "links": [
                            {
                              "rel": "self",
                              "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/85144567-7043-4469-9e79-279f4eb31e27/en"
                            },
                            {
                              "rel": "download",
                              "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/85144567-7043-4469-9e79-279f4eb31e27/en/download"
                            }
                          ]
                        },
                        {
                          "id": "8a4faf91-300e-46f0-8dad-0e1e572dbca1",
                          "language": "nl",
                          "name": "Sportkamp Tennis",
                          "community": 23088,
                          "year": 2018,
                          "links": [
                            {
                              "rel": "self",
                              "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/8a4faf91-300e-46f0-8dad-0e1e572dbca1"
                            },
                            {
                              "rel": "download",
                              "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/8a4faf91-300e-46f0-8dad-0e1e572dbca1/download"
                            }
                          ]
                        },
                        {
                          "id": "25da5b3c-4de4-457c-a803-cea5cafbfff5",
                          "language": "nl",
                          "name": "Dienstencheques 2018",
                          "year": 2018,
                          "links": [
                            {
                              "rel": "self",
                              "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/25da5b3c-4de4-457c-a803-cea5cafbfff5"
                            },
                            {
                              "rel": "download",
                              "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/25da5b3c-4de4-457c-a803-cea5cafbfff5/download"
                            }
                          ]
                        },
                        {
                          "id": "8e3405ea-ef23-4d8a-b5b4-9cb645ac312b",
                          "language": "nl",
                          "name": "Deelname opleiding recreatiemedewerker",
                          "year": 2019,
                          "links": [
                            {
                              "rel": "self",
                              "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/8e3405ea-ef23-4d8a-b5b4-9cb645ac312b"
                            },
                            {
                              "rel": "download",
                              "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/8e3405ea-ef23-4d8a-b5b4-9cb645ac312b/download"
                            }
                          ]
                        },
                        {
                          "id": "8df1a0b0-1278-46a7-a3dc-cce7f593d02c",
                          "language": "nl",
                          "name": "Sportkamp tennis",
                          "community": 11002,
                          "year": 2012,
                          "links": [
                            {
                              "rel": "self",
                              "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/8df1a0b0-1278-46a7-a3dc-cce7f593d02c"
                            },
                            {
                              "rel": "download",
                              "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/8df1a0b0-1278-46a7-a3dc-cce7f593d02c/download"
                            }
                          ]
                        },
                        {
                          "id": "34492c86-7bf8-4d96-9e61-e3c2f51d172a",
                          "language": "nl",
                          "name": "Dienstencheques 2015",
                          "year": 2015,
                          "links": [
                            {
                              "rel": "self",
                              "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/34492c86-7bf8-4d96-9e61-e3c2f51d172a"
                            },
                            {
                              "rel": "download",
                              "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/34492c86-7bf8-4d96-9e61-e3c2f51d172a/download"
                            }
                          ]
                        },
                        {
                          "id": "a681c382-8e99-4757-9fdb-487b9b6aeb78",
                          "language": "nl",
                          "name": "Trainersopleiding voetbal",
                          "community": 71053,
                          "year": 2013,
                          "links": [
                            {
                              "rel": "self",
                              "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/a681c382-8e99-4757-9fdb-487b9b6aeb78"
                            },
                            {
                              "rel": "download",
                              "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/a681c382-8e99-4757-9fdb-487b9b6aeb78/download"
                            }
                          ]
                        },
                        {
                          "id": "6973ab14-15c6-4ee7-944c-9d1162d9de71",
                          "language": "nl",
                          "name": "Dienstencheques 2014",
                          "year": 2014,
                          "links": [
                            {
                              "rel": "self",
                              "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/6973ab14-15c6-4ee7-944c-9d1162d9de71"
                            },
                            {
                              "rel": "download",
                              "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/6973ab14-15c6-4ee7-944c-9d1162d9de71/download"
                            }
                          ]
                        },
                        {
                          "id": "d61fdf2e-8099-4757-93d9-2709f1ce1ae2",
                          "language": "nl",
                          "name": "Vlaamse kinderbijslag",
                          "year": 2019,
                          "links": [
                            {
                              "rel": "self",
                              "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/d61fdf2e-8099-4757-93d9-2709f1ce1ae2"
                            },
                            {
                              "rel": "download",
                              "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/d61fdf2e-8099-4757-93d9-2709f1ce1ae2/download"
                            }
                          ]
                        }
                      ],
                      "pageMetadata": {
                        "number": 1,
                        "size": 10,
                        "totalElements": 40,
                        "totalPages": 4
                      },
                      "links": [
                        {
                          "rel": "self",
                          "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302?limit=10&page=0"
                        },
                        {
                          "rel": "next",
                          "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302?limit=10&page=1"
                        },
                        {
                          "rel": "start",
                          "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302?limit=10&page=0"
                        },
                        {
                          "rel": "last",
                          "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302?limit=10&page=3"
                        }
                      ]
                    }
                  },
                  "Last page, no more next page": {
                    "value": {
                      "certificates": [
                        {
                          "id": "85144567-7043-4469-9e79-279f4eb31e27",
                          "language": "nl",
                          "name": "Dienstencheques 2019",
                          "year": 2019,
                          "links": [
                            {
                              "rel": "self",
                              "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/85144567-7043-4469-9e79-279f4eb31e27"
                            },
                            {
                              "rel": "download",
                              "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/85144567-7043-4469-9e79-279f4eb31e27/download"
                            }
                          ]
                        },
                        {
                          "id": "57faeea1-ff3b-4c65-989c-e2175610c2b0",
                          "language": "nl",
                          "name": "Sportkamp Volleybal",
                          "community": 21004,
                          "year": 2019,
                          "links": [
                            {
                              "rel": "self",
                              "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/57faeea1-ff3b-4c65-989c-e2175610c2b0"
                            },
                            {
                              "rel": "download",
                              "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/57faeea1-ff3b-4c65-989c-e2175610c2b0/download"
                            }
                          ]
                        },
                        {
                          "id": "8a4faf91-300e-46f0-8dad-0e1e572dbca1",
                          "language": "nl",
                          "name": "Sportkamp Tennis",
                          "community": 23088,
                          "year": 2018,
                          "links": [
                            {
                              "rel": "self",
                              "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/8a4faf91-300e-46f0-8dad-0e1e572dbca1"
                            },
                            {
                              "rel": "download",
                              "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/8a4faf91-300e-46f0-8dad-0e1e572dbca1/download"
                            }
                          ]
                        }
                      ],
                      "pageMetadata": {
                        "number": 3,
                        "size": 10,
                        "totalElements": 23,
                        "totalPages": 3
                      },
                      "links": [
                        {
                          "rel": "self",
                          "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302?limit=10&page=2"
                        },
                        {
                          "rel": "start",
                          "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302?limit=10&page=0"
                        },
                        {
                          "rel": "last",
                          "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302?limit=10&page=2"
                        }
                      ]
                    }
                  },
                  "First page is last page": {
                    "value": {
                      "certificates": [
                        {
                          "id": "85144567-7043-4469-9e79-279f4eb31e27",
                          "language": "nl",
                          "name": "Dienstencheques 2019",
                          "year": 2019,
                          "links": [
                            {
                              "rel": "self",
                              "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/85144567-7043-4469-9e79-279f4eb31e27"
                            },
                            {
                              "rel": "download",
                              "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/85144567-7043-4469-9e79-279f4eb31e27/download"
                            }
                          ]
                        },
                        {
                          "id": "57faeea1-ff3b-4c65-989c-e2175610c2b0",
                          "language": "nl",
                          "name": "Sportkamp Volleybal",
                          "community": 21004,
                          "year": 2019,
                          "links": [
                            {
                              "rel": "self",
                              "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/57faeea1-ff3b-4c65-989c-e2175610c2b0"
                            },
                            {
                              "rel": "download",
                              "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/57faeea1-ff3b-4c65-989c-e2175610c2b0/download"
                            }
                          ]
                        },
                        {
                          "id": "8a4faf91-300e-46f0-8dad-0e1e572dbca1",
                          "language": "nl",
                          "name": "Sportkamp Tennis",
                          "community": 23088,
                          "year": 2018,
                          "links": [
                            {
                              "rel": "self",
                              "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/8a4faf91-300e-46f0-8dad-0e1e572dbca1"
                            },
                            {
                              "rel": "download",
                              "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/8a4faf91-300e-46f0-8dad-0e1e572dbca1/download"
                            }
                          ]
                        }
                      ],
                      "pageMetadata": {
                        "number": 1,
                        "size": 10,
                        "totalElements": 3,
                        "totalPages": 1
                      },
                      "links": [
                        {
                          "rel": "self",
                          "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302?limit=10&page=0"
                        },
                        {
                          "rel": "start",
                          "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302?limit=10&page=0"
                        },
                        {
                          "rel": "last",
                          "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302?limit=10&page=0"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Access Denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "Example": {
                    "value": {
                      "title": "An error occurred!",
                      "detail": "Access Denied",
                      "status": 403
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "Example": {
                    "value": {
                      "title": "An error occurred!",
                      "detail": "Could not find the certificate you are looking for.",
                      "status": 404
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "Example": {
                    "value": {
                      "title": "An error occurred!",
                      "detail": "<description of the internal server error>",
                      "status": 500
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/certificates/{ssn}/{certificateId}/{language}": {
      "get": {
        "tags": [
          "Certificates"
        ],
        "summary": "Certificate Details",
        "description": "",
        "parameters": [
          {
            "name": "ssn",
            "in": "path",
            "description": "Social security number",
            "required": true,
            "style": "simple",
            "explode": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "certificateId",
            "in": "path",
            "description": "ID of the certificate, defined as path parameter here (can be query parameter too)",
            "required": true,
            "style": "simple",
            "explode": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "language",
            "in": "path",
            "description": "Language of the certificate, defined as path parameter here (can be query parameter too)",
            "required": true,
            "style": "simple",
            "explode": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/hal+json": {
                "schema": {
                  "$ref": "#/components/schemas/Item-Certificate"
                },
                "examples": {
                  "only-required": {
                    "value": {
                      "id": "85144567-7043-4469-9e79-279f4eb31e27",
                      "language": "nl",
                      "name": "certificate-1234",
                      "links": [
                        {
                          "rel": "self",
                          "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/85144567-7043-4469-9e79-279f4eb31e27/nl"
                        },
                        {
                          "rel": "download",
                          "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/85144567-7043-4469-9e79-279f4eb31e27/nl/download"
                        }
                      ]
                    }
                  },
                  "only-year": {
                    "value": {
                      "id": "85144567-7043-4469-9e79-279f4eb31e27",
                      "language": "nl",
                      "name": "certificate-1234",
                      "year": 2019,
                      "links": [
                        {
                          "rel": "self",
                          "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/85144567-7043-4469-9e79-279f4eb31e27/nl"
                        },
                        {
                          "rel": "download",
                          "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/85144567-7043-4469-9e79-279f4eb31e27/nl/download"
                        }
                      ]
                    }
                  },
                  "only-community": {
                    "value": {
                      "id": "85144567-7043-4469-9e79-279f4eb31e27",
                      "language": "nl",
                      "name": "certificate-1234",
                      "community": 21004,
                      "links": [
                        {
                          "rel": "self",
                          "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/85144567-7043-4469-9e79-279f4eb31e27/nl"
                        },
                        {
                          "rel": "download",
                          "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/85144567-7043-4469-9e79-279f4eb31e27/nl/download"
                        }
                      ]
                    }
                  },
                  "full-certificate": {
                    "value": {
                      "id": "85144567-7043-4469-9e79-279f4eb31e27",
                      "language": "nl",
                      "name": "certificate-1234",
                      "community": 21004,
                      "year": 2019,
                      "links": [
                        {
                          "rel": "self",
                          "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/85144567-7043-4469-9e79-279f4eb31e27/nl"
                        },
                        {
                          "rel": "download",
                          "href": "https://burgerprofiel.vlaanderen.be/v1/certificates/90061638302/85144567-7043-4469-9e79-279f4eb31e27/nl/download"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Access Denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "Example": {
                    "value": {
                      "title": "An error occurred!",
                      "detail": "Access Denied",
                      "status": 403
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "Example": {
                    "value": {
                      "title": "An error occurred!",
                      "detail": "Could not find the certificate you are looking for.",
                      "status": 404
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "Example": {
                    "value": {
                      "title": "An error occurred!",
                      "detail": "<description of the internal server error>",
                      "status": 500
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ProblemDetails": {
        "title": "Problem details",
        "required": [
          "type",
          "title",
          "detail",
          "status"
        ],
        "type": "object",
        "properties": {
          "title": {
            "type": "string"
          },
          "detail": {
            "type": "string"
          },
          "status": {
            "format": "int32",
            "type": "integer"
          }
        },
        "example": {
          "title": "Er heeft zich een fout voorgedaan!",
          "detail": "",
          "status": 400
        }
      },
      "Item-Certificate": {
        "title": "Certificate",
        "required": [
          "id",
          "links",
          "name"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "language": {
            "type": "string"
          },
          "year": {
            "type": "integer"
          },
          "community": {
            "type": "integer"
          },
          "links": {
            "$ref": "#/components/schemas/Common-Item-Links"
          }
        }
      },
      "Common-General-Link": {
        "title": "Link",
        "required": [
          "href",
          "rel"
        ],
        "type": "object",
        "properties": {
          "rel": {
            "type": "string"
          },
          "href": {
            "type": "string"
          }
        }
      },
      "Common-Item-Links": {
        "title": "Links For Item",
        "type": "array",
        "items": {
          "$ref": "#/components/schemas/Common-General-Link"
        }
      },
      "Common-List-Links": {
        "title": "Links For List",
        "type": "array",
        "items": {
          "$ref": "#/components/schemas/Common-General-Link"
        }
      },
      "Common-List-PageMetadata": {
        "title": "PageMetadata",
        "required": [
          "number",
          "size",
          "totalElements",
          "totalPages"
        ],
        "type": "object",
        "properties": {
          "size": {
            "type": "integer"
          },
          "totalElements": {
            "type": "integer"
          },
          "totalPages": {
            "type": "number"
          },
          "number": {
            "type": "number"
          }
        }
      },
      "List-Certificates": {
        "required": [
          "certificates",
          "links",
          "pageMetaData"
        ],
        "type": "object",
        "properties": {
          "certificates": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Item-Certificate"
            }
          },
          "links": {
            "$ref": "#/components/schemas/Common-List-Links"
          },
          "pageMetaData": {
            "$ref": "#/components/schemas/Common-List-PageMetadata"
          }
        }
      }
    }
  }
}

...