This page covers errors from two sources: the authorisation server, when obtaining or refreshing a token, and the Partner API, when making requests.
Errors from the token endpoint return a JSON object with an error value and, usually, an error_description:
{
"error": "invalid_grant",
"error_description": "The refresh token is invalid."
}Errors from the authorisation endpoint are returned as an error parameter appended to your redirect URI.
These values are defined by the OAuth 2.0 specification (Section 4.1.2.1 for authorisation, Section 5.2 for tokens).
| Error | Meaning |
|---|---|
invalid_request | The request is missing a required parameter, repeats one, or is otherwise malformed. |
invalid_client | Client authentication failed. |
invalid_grant | The authorisation code or refresh token is invalid, expired, already used, revoked, or does not match the redirect URI used to obtain it. |
unauthorized_client | Your client is not permitted to use this grant type. |
unsupported_grant_type | The grant type is not supported. |
invalid_scope | The requested scope is invalid, unknown, or outside the set your client is configured for. |
access_denied | The user declined to grant access. |
invalid_client — usually a credentials mismatch rather than a malformed request. Check that you are using the credentials for the environment you are calling: Test credentials sent to the production host, or the reverse, produce this error. If you are using a Basic header, check the Base64 encoding and that the word Basic is capitalised.
invalid_grant when refreshing — refresh tokens are single-use. Once exchanged, the old one is dead. Confirm you are storing and using the new refresh token from each response, and that only one process refreshes at a time. See Managing Access and Refresh Tokens.
invalid_grant when exchanging a code — authorisation codes are single-use and short-lived. This also occurs when the redirect_uri in your token request does not exactly match the one used in the authorisation request.
invalid_scope — you requested a scope your client is not configured for. Check Authorisation Scopes and, if you need a scope you do not have, contact us.
access_denied — the customer declined on the consent screen. This is a normal outcome, not a fault. Handle it gracefully and let them try again.
Errors from the Partner API return a JSON body with a Message:
{
"Message": "Authorization has been denied for this request."
}A 400 from an endpoint that accepts a body also includes ModelState, mapping each invalid field to its error messages:
{
"Message": "The request is invalid.",
"ModelState": {
"Trustee.Individuals[0].LastName": [
"'Last Name' must not be empty."
],
"AllocationDetails.PrimaryBeneficiaries": [
"Primary Beneficiary percentage total must equal 100."
]
}
}Keys use dotted and indexed paths mirroring your request body, so they can be mapped back to fields in your own form. Note that ModelState carries both field-level validation and cross-field business rules — the second example above is a rule about a group of values, not a single property.
Surface these messages to your users rather than a generic failure. They are specific enough to be actionable.
| Status | Cause | What to do |
|---|---|---|
400 | Invalid request body. | Read ModelState and correct the fields identified. |
401 | Missing, expired or invalid access token. | Refresh the token and retry. If refresh fails, start a new authorisation. |
403 | Valid token, insufficient access. | Check your granted scopes, and whether the resource belongs to an account you can reach. |
404 | Resource not found. | Check the identifier, and check that X-NI-AccountID targets the account the record belongs to. |
202 | Not an error. Files are still generating. | Retry later, backing off between attempts. |
204 | Not an error. Files do not exist because the document is still in draft. | Submit the form to /forms/process first. |
- API structure — status codes in context.
- Managing Access and Refresh Tokens — avoiding
invalid_grant. - Authorisation Scopes — avoiding
invalid_scope.