Life Event Verification (LEV) API Guide ======================================= :toc: :numbered: [role=hideable] NOTE: This documentation is limited by GitHub's version of ASCII Docs, the full version may be viewed in the docs repo: https://ukhomeoffice.github.io/lev-api-docs [IMPORTANT,role=unhideable] ==== The contents of this repo are automatically generated; to make changes follow these steps: . `git clone https://gitlab.digital.homeoffice.gov.uk/lev/lev-api-scala` . edit the `lev-api-scala/docs/README.adoc` file . `commit` and `push` your changes (to a new branch) . create a *merge request* detailing the changes . upon successful approval of the merge request the changes will be automatically added to the `lev-api-docs` repo ==== == Mock API It is possible to run a mock version of the API as follows: === Running a mock API with docker (from Quay.io) The latest version of the mock API can be run straight from the `quay.io` hosted image: ``` docker pull quay.io/ukhomeofficedigital/lev-api-mock docker run -p 8080:8080 quay.io/ukhomeofficedigital/lev-api-mock ``` === Running a mock API with docker (from this repo) [role=hideable] NOTE: The paths in this section refer to the root of the docs project: https://github.com/UKHomeOffice/lev-api-docs The easiest way to run the mock API is with Docker ``` ./mock/build_mock_api_docker.sh ./mock/run_mock_api_docker.sh ``` === Running a mock API without docker It is also possible to run it without docker if you have the *wiremock* jar file: ``` cd mock java -jar wiremock.jar --port=8080 ``` == Authenticating with the API To use the API you will need to provide 2 forms of authentication: . A client certificate . An auth token, which must be obtained by hitting the `/oauth/login` endpoint [IMPORTANT] ==== *The client certificate must be included in every request to the API, but is NOT shown in this documentation for simplicity.* Adding a client certificate to a `curl` request can easily be achieved by adding the following arguments: [source,bash] ---- curl --cert-type pem --key client.key --cert client.crt ... ---- ==== NOTE: The client certificate is not needed when sending requests to the _mock API_. The rest of this section contains examples which have been provided to help troubleshoot issues with authentication. === A successful request with valid credentials +++
+++ *Example `curl` request* with dummy credentials +++
+++ include::snippets/auth/valid-auth/curl-request.adoc[] +++
+++ +++
+++ *Example `HTTP` request* with dummy credentials +++
+++ include::snippets/auth/valid-auth/http-request.adoc[] +++
+++ +++
+++ *Example response* containing the *access token* +++
+++ include::snippets/auth/valid-auth/http-response.adoc[] +++
+++ === Authentication problems Generally authentication problems are reported as `401 Unauthorized` errors. ==== A request with invalid credentials +++
+++ *Example `curl` request* with invalid credentials +++
+++ include::snippets/auth/invalid-credentials/curl-request.adoc[] +++
+++ +++
+++ *Example `HTTP` request* with invalid credentials +++
+++ include::snippets/auth/invalid-credentials/http-request.adoc[] +++
+++ +++
+++ *Example response* detailing the error +++
+++ include::snippets/auth/invalid-credentials/http-response.adoc[] +++
+++ ==== An unauthorised request +++
+++ *Example `curl` request* without the required `Authorization` header +++
+++ include::snippets/auth/unauthorized/curl-request.adoc[] +++
+++ +++
+++ *Example `HTTP` request* without the required `Authorization` header +++
+++ include::snippets/auth/unauthorized/http-request.adoc[] +++
+++ +++
+++ *Example response* detailing the error +++
+++ include::snippets/auth/unauthorized/http-response.adoc[] +++
+++ ==== A request with missing credentials +++
+++ *Example `curl` request* without the required `password` parameter +++
+++ include::snippets/auth/invalid-post/curl-request.adoc[] +++
+++ +++
+++ *Example `HTTP` request* without the required `password` parameter +++
+++ include::snippets/auth/invalid-post/http-request.adoc[] +++
+++ +++
+++ *Example response* detailing the error +++
+++ include::snippets/auth/invalid-post/http-response.adoc[] +++
+++ ==== A request with no client certificate Whilst none of the examples here contain the required client certificate, this example has been explicitly included to show how the resulting `403 Forbidden` error would look. +++
+++ *Example `curl` request* without the required client certificate +++
+++ include::snippets/auth/no-client-cert/curl-request.adoc[] +++
+++ +++
+++ *Example `HTTP` request* without the required client certificate +++
+++ include::snippets/auth/no-client-cert/http-request.adoc[] +++
+++ +++
+++ *Example response* detailing the error +++
+++ include::snippets/auth/no-client-cert/http-response.adoc[] +++
+++ == Requesting birth record data All successful requests to the API will result in a `200 OK` HTTP status code and are described in this section. === Requesting a specific birth record using a System Number The best way to get birth data is by providing the relevant System Number, a nine digit unique identifier for the birth record. +++
+++ *Example `curl` request* specifying a *System Number* +++
+++ include::snippets/system-number/matching-record-999999901/curl-request.adoc[] +++
+++ +++
+++ *Example `HTTP` request* specifying a *System Number* +++
+++ include::snippets/system-number/matching-record-999999901/http-request.adoc[] +++
+++ +++
+++ *Example response* is a *JSON object* containing the birth record data +++
+++ include::snippets/system-number/matching-record-999999901/http-response.adoc[] +++
+++ === Searching for a birth record When the System Number of the birth record is not known, a search of the records can be made by supplying the following three parameters in the URL query string: - `forenames` : the first name is mandatory, and can be accompanied by any middle names (all separated by spaces) - `lastname` : the last name is mandatory - `dateofbirth` : the date of birth is also mandatory +++
+++ *Example `curl` request* with search parameters +++
+++ include::snippets/search/multiple-matching-record/curl-request.adoc[] +++
+++ +++
+++ *Example `HTTP` request* with search parameters +++
+++ include::snippets/search/multiple-matching-record/http-request.adoc[] +++
+++ +++
+++ *Example response* is a *JSON array* containing three matching birth records +++
+++ include::snippets/search/multiple-matching-record/http-response.adoc[] +++
+++ TIP: The API will only return at most *25* matching records. In the unlikely case where there might be more than 25 people with the same first name, last name, and date of birth; you will have to add middle names to the query to make the search more exacting. === When no matching records are found If no records matching the search terms can be found, the API will return an empty array. +++
+++ *Example `curl` request* +++
+++ include::snippets/search/no-matches/curl-request.adoc[] +++
+++ +++
+++ *Example `HTTP` request* +++
+++ include::snippets/search/no-matches/http-request.adoc[] +++
+++ +++
+++ *Example response* is an *empty JSON array* +++
+++ include::snippets/search/no-matches/http-response.adoc[] +++
+++ == Common errors and responses === Non-existent route Making a request to an invalid end point will result in the standard `404 Not Found` error. ==== Requesting an endpoint that doesn't exist +++
+++ *Example `curl` request* to an invalid endpoint +++
+++ include::snippets/invalid-endpoint/curl-request.adoc[] +++
+++ +++
+++ *Example `HTTP` request* to an invalid endpoint +++
+++ include::snippets/invalid-endpoint/http-request.adoc[] +++
+++ +++
+++ *Example response* detailing the error +++
+++ include::snippets/invalid-endpoint/http-response.adoc[] +++
+++ ==== Specifying a System Number that doesn't exist +++
+++ *Example `curl` request* with a non-existing System Number +++
+++ include::snippets/system-number/no-record/curl-request.adoc[] +++
+++ +++
+++ *Example `HTTP` request* with a non-existing System Number +++
+++ include::snippets/system-number/no-record/http-request.adoc[] +++
+++ +++
+++ *Example response* detailing the error +++
+++ include::snippets/system-number/no-record/http-response.adoc[] +++
+++ === Missing search parameters Missing search parameters will result in a standard `400 Bad Request` error. ==== Missing forenames parameter +++
+++ *Example `curl` request* without the `forenames` parameter +++
+++ include::snippets/search/no-forenames/curl-request.adoc[] +++
+++ +++
+++ *Example `HTTP` request* without the `forenames` parameter +++
+++ include::snippets/search/no-forenames/http-request.adoc[] +++
+++ +++
+++ *Example response* detailing the error +++
+++ include::snippets/search/no-forenames/http-response.adoc[] +++
+++ ==== Missing last name parameter +++
+++ *Example `curl` request* without the `lastname` parameter +++
+++ include::snippets/search/no-lastname/curl-request.adoc[] +++
+++ +++
+++ *Example `HTTP` request* without the `lastname` parameter +++
+++ include::snippets/search/no-lastname/http-request.adoc[] +++
+++ +++
+++ *Example response* detailing the error +++
+++ include::snippets/search/no-lastname/http-response.adoc[] +++
+++ ==== Missing date of birth parameter +++
+++ *Example `curl` request* without the required `dateofbirth` parameter +++
+++ include::snippets/search/no-dob/curl-request.adoc[] +++
+++ +++
+++ *Example `HTTP` request* without the required `dateofbirth` parameter +++
+++ include::snippets/search/no-dob/http-request.adoc[] +++
+++ +++
+++ *Example response* detailing the error +++
+++ include::snippets/search/no-dob/http-response.adoc[] +++
+++ === Other request errors ==== Invalid date of birth provided +++
+++ *Example `curl` request* with an incorrect `dateofbirth` parameter +++
+++ include::snippets/search/invalid-dob/curl-request.adoc[] +++
+++ +++
+++ *Example `HTTP` request* with an incorrect `dateofbirth` parameter +++
+++ include::snippets/search/invalid-dob/http-request.adoc[] +++
+++ +++
+++ *Example response* detailing the error +++
+++ include::snippets/search/invalid-dob/http-response.adoc[] +++
+++ NOTE: Currently the response status is `500 Internal Server Error`; this is not the intention and will be fixed in a future release to show the proper `400 Bad Request` instead. ==== Incorrectly providing forenames The easiest way to provide forenames is using the `forenames` parameter, however forenames may alternatively be provided using the numbered version: `forename1`, `forename2`, `forename3`, and `forenames4`. Providing a mix of the forename parameters will result in a standard `400 Bad Request` error. +++
+++ *Example `curl` request* with both `forenames` and `forename1` parameters +++
+++ include::snippets/search/forenames-and-forename1/curl-request.adoc[] +++
+++ +++
+++ *Example `HTTP` request* with both `forenames` and `forename1` parameters +++
+++ include::snippets/search/forenames-and-forename1/http-request.adoc[] +++
+++ +++
+++ *Example response* detailing the error +++
+++ include::snippets/search/forenames-and-forename1/http-response.adoc[] +++
+++ NOTE: The use of `forename1`, `forename2`, `forename3`, and `forename4` is strongly discouraged and should be considered deprecated in favour of the `forenames` parameter. ++++ ++++ == Retrieving audit information For certain users with special permissions, it is possible to retrieve an aggregated count of system users' search activity. === Auditor level access All requests to the audit information end points must be made by a user with auditor level permissions, otherwise the request will fail with the standard `401 Unauthorised` error. +++
+++ *Example `curl` request* by an API user without the special auditor permissions +++
+++ include::snippets/audit/invalid-permissions/curl-request.adoc[] +++
+++ +++
+++ *Example `HTTP` request* by an API user without the special auditor permissions +++
+++ include::snippets/audit/invalid-permissions/http-request.adoc[] +++
+++ +++
+++ *Example response* detailing the error +++
+++ include::snippets/audit/invalid-permissions/http-response.adoc[] +++
+++ === Audit record filters The audit record data returned can be filtered by providing the following parameters. ==== A date range The date range is optional. It can be omitted entirely, only one part specified, or fully specified by providing the `from` and `to` date parameters. +++
+++ *Example `curl` request* filtering out records except those made between yesterday and one minute ago +++
+++ include::snippets/audit/from-yesterday-until-a-minute-ago/curl-request.adoc[] +++
+++ +++
+++ *Example `HTTP` request* filtering out records except those made between yesterday and one minute ago +++
+++ include::snippets/audit/from-yesterday-until-a-minute-ago/http-request.adoc[] +++
+++ +++
+++ *Example response* detailing the error +++
+++ include::snippets/audit/from-yesterday-until-a-minute-ago/http-response.adoc[] +++
+++