Reference guide

Read the reference guide for actions you need to take to make sure your application integrates with HMRC.

See the development practices for how to avoid your application failing without warning when HMRC make changes.

API access

The base URL for sandbox APIs is:

The base URL for production APIs is:

Browser support for OAuth 2.0

The OAuth 2.0 authorisation journey is designed to work with most modern browsers as per the list specified on Designing for different browsers and devices, including mobile devices and tablets.

If you are using the Microsoft Web Browser Control embedded browser for the authorisation journey, be aware that by default this will operate in IE7 compatibility mode which we do not formally support. For details of one way to handle this, see Controlling WebBrowser Control Compatibility (opens in a new tab) .

Coding in the open

The HMRC Developer Hub, the underlying API Platform and some of the APIs are coded in the open, as per the GOV.UK Digital Service Standard (opens in a new tab).

The source code is available at (opens in a new tab). For more details, please contact us.

Common data types

Our APIs use consistent formats for common data types. We use ISO standards including:

Some examples of common data types include:

Examples of common data types
Type Example Description
date 2015-09-08 Dates will be represented in the format YYYY-MM-DD.
timestamp 2015-09-08T01:55:28+00:00 Timestamps will be represented in the format YYYY-MM-DDThh:mm:ss±hh:mm.
money 123.45 Unless expressly documented, money will be represented with two decimal places and GBP currency.
NINO QQ123456A A National Insurance number is made up of 2 letters, 6 numbers and a letter (A, B, C, or D).

Cross-origin resource sharing (CORS)

The API Platform does not support cross-origin resource sharing (CORS) (opens in a new tab). It is therefore not possible to call our APIs from client-side code within a web browser, for example using Ajax.


Errors during the authorisation process use the format specified in the OAuth 2.0 RFC.

Errors from APIs have a 4xx or 5xx HTTP status code and a consistently formed JSON or XML body, including:

Name Type Description
code string A machine-readable error code. This is unique for each error scenario.
message string A human-readable explanation for the error.

There might be other error-specific information (such as a list of fields that are in error). For example:

  "code" : "ACCOUNT_SUSPENDEDSA-100201",
  "message" : "Account is temporarily suspended",
  "reactivationTimestamp" : 1431448640718

Multiple errors can also be returned in a single field called errors. For example:

  "code": "BAD_REQUEST",
  "message": "Bad request",
  "errors": [
      "code": "MISSING_FIELD",
      "message": "This field is required",
      "path": "/firstName"
      "code": "INVALID_DATE",
      "message": "Date is invalid",
      "path": "/dateOfBirth"

Here is an example error response in XML format

  <message>Account is temporarily suspended</message>

These error responses are common across all APIs:

401 (Unauthorized)

Scenario Code
No OAuth token supplied for user-restricted or application-restricted endpoint MISSING_CREDENTIALS
Invalid OAuth token supplied for user-restricted or application-restricted endpoint (including expired token) INVALID_CREDENTIALS
Other issue with authentication of the supplied OAuth token UNAUTHORIZED
User-restricted API is being accessed with a server token INCORRECT_ACCESS_TOKEN_TYPE

403 (Forbidden)

Scenario Code
Request done with HTTP HTTPS_REQUIRED
The OAuth token's application is not subscribed to the API RESOURCE_FORBIDDEN
The scope of the OAuth token is not sufficient to access the API INVALID_SCOPE
Supplied OAuth token not authorised to access data for given tax identifier(s) FORBIDDEN

404 (Not Found)

Scenario Code
No endpoint could be found in the API for the request path MATCHING_RESOURCE_NOT_FOUND

405 (Method Not Allowed)

Scenario Code

406 (Not Acceptable)

Scenario Code
Missing or invalid Accept header ACCEPT_HEADER_INVALID

429 (Too Many Requests)

Scenario Code
The application has reached its maximum rate limit in-page link MESSAGE_THROTTLED_OUT

500 (Internal Server Error)

Scenario Code
Internal server error INTERNAL_SERVER_ERROR

501 (Not Implemented)

Scenario Code
API not implemented/deployed NOT_IMPLEMENTED

503 (Service Unavailable)

Scenario Code
Service unavailable SERVER_ERROR
Scheduled maintenance SCHEDULED_MAINTENANCE

504 (Gateway Timeout)

Scenario Code
Request timed out GATEWAY_TIMEOUT

Send fraud prevention data

You must help us protect our users’ confidential data by sending us particular types of user audit data which we will record. Check what you need to send.

It is mandatory to provide header data for the VAT (MTD) API.

Soon, you'll need to send user audit data in fraud prevention headers for all of our APIs. We recommend designing this into your applications now.

HTTP redirection

Our API Platform uses HTTP redirection if endpoints move permanently or temporarily.

Redirection responses have a Location header with the endpoint's new URI.

IP allow list

The IP allow list is a security feature that lets you control which IP addresses are allowed to make API requests to HMRC.

The IP allow list is optional and is only suitable if you have a static set of IP addresses where your software is hosted.

If you have dynamic IP addresses, consider switching to static IP addresses to use the IP allow list.

The IP allow list limits access to HMRC services to approved IP addresses associated with your application.

Allowed IP addresses

We allow IP address ranges represented in CIDR notation, made up of an IP address and a netmask: 

<IP Address>/<netmask>

Which looks like:

The netmask identifies how large the network is: 

  • allows access from only one IP address, for example
  • allows access from 254 IP addresses, for example to

Use /32 if you are unsure about CIDR notation but know the individual IP addresses your traffic comes from.

The largest netmask we allow is /24.

Adding IP addresses to the allow list

You will need a sandbox or production application to use the IP allow list.

When you set up a sandbox or production application, decide which IP addresses are allowed to make API requests to HMRC and add to the IP allow list.

It is important that you check the IP addresses you want to use are correct before making the IP allow list active.

While the allow list is active, only approved IP addresses associated with your application can make API requests to HMRC.

Rate limiting

We limit the number of requests each application can make. This protects our service against excessive use and Denial-of-Service attacks, and also encourages you to use our APIs efficiently.

We set limits based on anticipated loads and peaks. Our standard limit is 3 requests per second per application.

If you reach this limit you’ll get a response with an HTTP status of 429 (Too Many Requests). If a 429 response is received we recommend that your code should stop making additional API requests for a short period of time before retrying.

Our rate limits are designed to encourage real-time interactions. As such we advise software developers to avoid batching requests if they wish to avoid being rate limited.

If you continually hit this rate limit, contact us to discuss your application design and whether it’s appropriate to raise your rate limit.

Redirect URIs

We use redirect URIs to send the user back to your application after successful (or unsuccessful) authorisation, prior to your application accessing user-restricted endpoints.

You must specify one or more redirect URIs when you create your application, and also specify one redirect URI when you send your user to our authorisation endpoint.

To protect your application from phishing attacks, the redirect URI you use for authorisation (in your call to /oauth/authorize) must match one of those you specified when you created your application.

Also, you must use the same redirect URI when exchanging your authorisation code for an access token (in your call to /oauth/token) that you used for authorisation (in your call to /oauth/authorize).

You can specify a maximum of five redirect URIs.


Examples of valid (and invalid) redirect URIs are:

Redirect Uris
Redirect URI Comments Valid - when creating your application, you can use the full redirect URI or a partial URI, for example:

When calling our authorisation endpoint, your redirect URI must be percent-encoded, for example: Valid - includes a port number Invalid - uses HTTP, not HTTPS (HTTP is OK for installed applications - see example below)
/auth-redirect Invalid - is a relative URI, not an absolute URI Invalid - uses an IP address, not a DNS name Valid - includes a query component Invalid - includes a fragment component
http://localhost:8080 Valid - as explained in OAuth 2.0 for installed applications
urn:ietf:wg:oauth:2.0:oob Valid - as explained in OAuth 2.0 for installed applications
urn:ietf:wg:oauth:2.0:oob:auto Valid - as explained in OAuth 2.0 for installed applications


When your application needs to access API endpoints on behalf of a user, the Developer Hub uses the OAuth 2.0 framework to grant and manage such an authority.

This authority is granted in terms of OAuth 2.0 'scopes'. Each 'scope' relates to one or more endpoints.

When your application requests an OAuth 2.0 Bearer token, it must specify the scope(s) which the token should be granted for.

These are translated to human-readable descriptions that are shown to the user before they grant authority. This makes sure the user understands and gives access to your application.

The scope for each user-restricted endpoint is defined in the API documentation.

For details about OAuth 2.0 and scopes, see authorisation.

TLS standards

HMRC APIs are only accessible over Transport Layer Security (TLS). For example, URLs that begin with https://.

Applications must support TLS 1.2 or higher to avoid known weaknesses in previous versions.


Request the version of the API you want to use by including an Accept header with a media type of:


For example:


We release backwards-compatible changes in the same version, so you don't need to change your Accept header. We release backwards-incompatible changes in a new version, and you must change your Accept header to use it.