Send a document API
The Send a document API should be used to attach documents to your application. There are two steps for sending a document:
- A request to generate an upload URL
- A request to upload the document
The request to generate an upload URL will respond with a land registry URL that can be used to upload the document to. This URL is only active for 10 minutes after creation. The generate an upload URL endpoint will also return a document ID, that can be used when using the Submit an application API. Documents uploaded via this process will be subject to HMLR security scanning.
Documents that have been uploaded can be used for up to 180 days, after which point they will be removed.
View the API specification
See the API Specification here
How the service API works
How to test this service API
HMLR does not currently provide a test environment for integrators using our Business Gateway APIs. Instead, we’ve provided example code to demonstrate what you should expect to see when developing your own services.
This information is coming soon.
Technical guide
How to use the Send a document service API
This API consists of two endpoints that must be used together to upload a single document.
POST /v0/documents/url
- The generate an upload URL endpoint. The HTTP body of the request contains information about the file being uploadedPUT documentcapture.landregistry.gov.uk/...
- The upload a document endpoint. The HTTP body of the request is the bytes of the document.
Generate an upload URL
Making a POST request to the create upload URL endpoint will result in the following items being returned:
upload_url
- This is the URL to make the PUT request to. This URL will only be valid for ten minutes after generation. Five minutes is timed from the generation of the URL to the start of the upload. Neither the size of the document nor the speed of internet connection will cause the upload to timeoutdocument_id
- This is a unique ID for this document, and must be included in the application submission payload
Upload a document
To upload a document, make a PUT request to the URL returned from the ‘Create an upload URL’ POST request above. This request should contain the document as the body content. A 200 HTTP code will be returned if the upload was successful. Documents will asynchronously be virus scanned and validated. Issues found during this process will be surfaced via the Application information API. Do not modify the URL received in the response.
Validation rules
File types
Only four file types are supported by HMLR document upload:
- PDFs - PDFs must not be password protected
- TIFFs
- GIFs
- PNGs
Any other file types are not supported, and will cause application submission to fail.
File length/SHA-256
As part of the API to generate an upload URL, the API expects file_length
and file_sha256
parameters. These parameters refer to the file that will be uploaded to the URL.
These values must also be provided when making the PUT request to the upload URL, as headers:
Content-Length : <value of file_length>
X-Amz-Checksum-Sha256 : <value of file_sha256>
Where <value of x>
are the values that were given to the request to generate the upload URL and
match the file that is included in the body of the request. If either of these values do not match
or are not provided, you will receive a signature verification failure (HTTP 403).
The maximum size permitted for a single document upload is 40MiB (41943040 bytes).
File length
The file_length
should be the size of the file in bytes.
See below for code examples in several languages:
Python:
with open("test.pdf", "rb") as f:
file_bytes = f.read()
file_length = len(file_bytes)
Bash:
du -b test.pdf
Java:
File f = new File("test.pdf");
long fileLength = f.length();
JavaScript (Node):
const fs = require("fs");
const stats = fs.statSync("test.pdf");
const fileLength = stats.size;
File Sha256
The file_sha256 is the base64 encoded 256-bit binary digest of the bytes of the file. This should be exactly 44 characters long, regardless of the length of the file. See below for code examples in several languages:
Python:
with open("test.pdf", "rb") as f:
file_bytes = f.read()
hash = sha256(file_bytes)
file_sha256 = b64encode(hash.digest())
Bash:
cat test.pdf | openssl sha256 -binary | openssl enc -base64
Java:
File f = new File("test.pdf");
byte[] data = Files.readAllBytes(f);
MessageDigest digester = MessageDigest.getInstance("SHA-256");
digester.update(data);
String fileSha256 = Base64.getEncoder().encodeToString(digester.digest());
JavaScript (Node):
const fs = require("fs");
const crypto = require("crypto");
const shasum = crypto.createHash("sha256");
shasum.update(fs.getBytes());
shasum.digest("base64");
Example requests and responses
POST /v0/documents/url
- Request
{
"data": {
"document_type": "TR1",
"file_length": 6362,
"file_sha256": "XHepSrLEhDPShYnPJwWArZERIvLcpvn8f8pyCS7crQA="
}
}
POST /v0/documents/url
- Response
{
"data": {
"upload_url": "documentcapture.landregistry.gov.uk/04c5c3fe-aa08-473b-9944-64ef5506f8e2",
"document_id": "04c5c3fe-aa08-473b-9944-64ef5506f8e2"
}
}
Note: The URL in the example may not be representative of the actual URL received.
PUT document - Request
- URL matches upload_url in
/v0/documents/url
response - Body content is the document to upload
PUT document - Response
- HTTP 200 on successful upload
- HTTP 4xx on failure
Test Stubs
Due to technical limitations, these stubs will only allow you to get an upload url. The URL won’t work and the PUT
endpoint is not stubbed.
Base URL: https://bgtest.landregistry.gov.uk/bg2test/api
1. Success
Request
Method: POST
Endpoint: /v0/documents/url
Headers:
Authorization: <any-value>
Body:
{
"data": {
"document_type": "CHARGE",
"additional_provider_filter": "string",
"file_length": 123123,
"file_sha256": "This is a 44 character string. blah blah bla"
}
}
Response
Status: 200
Body:
{
"data": {
"upload_url": "https://www.your-upload-url-would-be-here.com",
"document_id": "12345678-1234-1234-1234-1234-123456789abc"
}
}
NOTE - This response body may contain any random UUID in the document_id
field.
2. Invalid Document Type
Request
Method: POST
Endpoint: /v0/documents/url
Headers:
Authorization: <any-value>
Body:
{
"data": {
"document_type": "INVALID",
"additional_provider_filter": "string",
"file_length": 123123,
"file_sha256": "This is a 44 character string. blah blah bla"
}
}
Response
Status: 400
Body:
{
"type": "https://landregistry.github.io/bgtechdoc/problems/global#bad-request",
"title": "Bad Request",
"detail": "The request is invalid or malformed.",
"status": "400",
"errors": [{
"type": "L1A_JSON_PARSE_ERROR",
"detail": "Invalid document_type: 'INVALID'"
}]
}
3. Invalid File Length (too small)
Request
Method: POST
Endpoint: /v0/documents/url
Headers:
Authorization: <any-value>
Body:
{
"data": {
"document_type": "CHARGE",
"additional_provider_filter": "string",
"file_length": 0,
"file_sha256": "This is a 44 character string. blah blah bla"
}
}
Response
Status: 400
Body:
{
"type": "https://landregistry.github.io/bgtechdoc/problems/global#bad-request",
"title": "Bad Request",
"detail": "The request is invalid or malformed.",
"status": "400",
"errors": [{
"type": "L1A_SCHEMA_VALIDATION_ERROR",
"detail": "There are problems with the JSON provided [must be greater than or equal to 1]"
}]
}
4. Invalid File Length (too large)
Request
Method: POST
Endpoint: /v0/documents/url
Headers:
Authorization: <any-value>
Body:
{
"data": {
"document_type": "CHARGE",
"additional_provider_filter": "string",
"file_length": 419430401,
"file_sha256": "This is a 44 character string. blah blah bla"
}
}
Response
Status: 400
Body:
{
"type": "https://landregistry.github.io/bgtechdoc/problems/global#bad-request",
"title": "Bad Request",
"detail": "The request is invalid or malformed.",
"status": "400",
"errors": [{
"type": "L1A_SCHEMA_VALIDATION_ERROR",
"detail": "There are problems with the JSON provided [must be less than or equal to 41943040]"
}]
}
5. Invalid SHA
Request
Method: POST
Endpoint: /v0/documents/url
Headers:
Authorization: <any-value>
Body:
{
"data": {
"document_type": "CHARGE",
"additional_provider_filter": "string",
"file_length": 123123,
"file_sha256": "This is less than 44 characters."
}
}
Response
Status: 400
Body:
{
"type": "https://landregistry.github.io/bgtechdoc/problems/global#bad-request",
"title": "Bad Request",
"detail": "The request is invalid or malformed.",
"status": "400",
"errors": [{
"type": "L1A_SCHEMA_VALIDATION_ERROR",
"detail": "There are problems with the JSON provided [size must be between 44 and 44]"
}]
}