Revenue interface
Errors and rejections
Two kinds of failure, and a handful of messages that say something other than what they mean.
On this page
Two kinds of failure
| SOAP fault | Field rejection | |
|---|---|---|
| Where | Transport, signature or authentication | Revenue's business rules, after the message was understood |
| Shape | A Fault element with a faultstring | A response with Invalid entries naming fields |
| Means | Nothing reached Revenue's business layer | It did reach it, and was refused on content |
The distinction is the fastest route to a diagnosis. A fault means stop looking at your data; a field rejection means stop looking at your signing code.
A response can also carry both accepted and rejected records — read Valid and Invalid, not one or the other.
SOAP faults — the ladder
Roughly in the order you meet them while getting an integration working. Each rung means the previous one is now correct, which makes this a progress indicator as much as an error list.
| Fault string | What it actually means |
|---|---|
Header Operation is required | The Operation header is malformed or missing. You have not reached authentication yet. |
An error occured during authentication | Revenue's spelling. Rejected before the signature was checked — see below, because this one has two very different causes. |
Invalid signature | The signature verified and failed, which means authentication passed. Usually the wrong nodes were signed: this profile signs the Operation header and the Body, and has no Timestamp. |
… not registered for this tax | Through to Revenue's business rules — the transport is entirely working. The registration number is not registered for RCT. |
Reaching “not registered for this tax” is good news
It means the envelope, the signature, the certificate and the operation routing are all correct, and you are arguing about data. That is a much better position than it reads like.
The misleading ones
Three messages point away from their cause. Each cost real time.
An error occured during authentication
Two entirely different causes produce this identical fault:
- A signature algorithm the endpoint refuses. It accepts
RSA-SHA1only, and rejects SHA-256 and SHA-512. - A certificate Revenue does not recognise for that registration.
Naming only the first sends someone hunting through signing code when the certificate is the problem, and vice versa. Check both.
112006 — Unable to connect to the required web service
Reads as an outage on Revenue’s side. It is sometimes exactly that — and it is also returned for some malformed submissions.
How to tell the difference
If other submissions succeed while one keeps returning it, the submission is the problem, not Revenue. For us it was an omitted SiteAddresses element — marked minOccurs="0" in the schema and required in practice. We retried three times assuming PIT3 was down before diffing against a payload that had worked.
Cannot find details for contractId
Usually not a wrong contract id. A freshly accepted contract is not immediately usable for payment notifications — Revenue’s systems take a variable, undocumented time to catch up.
Retry rather than treating the first rejection as final, and notify contracts before the day you need to pay against them.
Field rejections
Each names a field and a message. The common ones, in the order they actually occur:
| Message | Cause |
|---|---|
This is a required field | Often on all eleven employment-status fields at once, which means SubHasNoticeOfExclusion is 0 and they became mandatory. Nothing in the message indicates the condition. |
Permitted characters are: … | The restricted character set. Almost always a pasted em-dash, a comma, or an accented character outside the five Irish vowels. |
This is not a valid value for this field | An enumeration violation. ContractUpdateType must be NEW/AMEND/CANCEL, not an initial; RctType is upper case with underscores; indicators are 0 or 1 and nothing else. |
| A date field named with no explanation | Almost certainly ISO format. ros:date is DD/MM/YYYY and is a string pattern, not xsd:date. |
Finding the record that failed
With up to 100 records per submission and a rejection failing the entire batch, identifying which record was at fault matters.
The rejection carries an ordinal — the field is given as something like PaymentNotification[4], which is the position of the record in the submission you sent. Map it back through your own ExternalId to the row it came from.
Brickie sorts a batch response into four outcomes: accepted, rejected, not filed (valid records that never processed because a sibling failed) and unmatched. The third is the one an integration is most likely to get wrong, by reporting valid records as successful when the batch never landed.
What to validate before submitting
The round trip is the expensive part, and a batch rejection tells you little. Worth checking locally:
- The character set, on every free-text field. This is the single most common rejection and the easiest to catch.
- Date format — enforce
DD/MM/YYYYat the type level so an ISO string cannot reach a request. - The employment-status condition — if
SubHasNoticeOfExclusionis 0, all eleven must be present. Failing locally gives one clear message instead of eleven opaque ones. - Element order, which is worth an assertion in a test rather than trust.
- SiteAddresses is present, given what its absence returns.