Zum Hauptinhalt springen
Echtzeit-Radar & Feeds
Alle RSS Feeds ➔
👥 Community & Social
•
IT Security NachrichtenBetrüger phishen mit vermeintlicher Reisebestätigung - IT-Markt(24.09.2026 um 23:41 Uhr)
••
Sicherheitslücken (CVE)IT Security News Daily Summary 2026-09-24(24.09.2026 um 23:55 Uhr)
•
Sicherheitslücken (CVE)IT Security News Roundup: 2026-09-24(24.09.2026 um 23:57 Uhr)
•
Sicherheitslücken (CVE)IT Security News Hourly Summary 2026-09-25 00h : 9 posts(25.09.2026 um 00:00 Uhr)
•••
IT NachrichtenMicrosoft puts Brad Smith in charge of communications(25.09.2026 um 00:08 Uhr)
•••
IT Security NachrichtenBetrüger phishen mit vermeintlicher Reisebestätigung - IT-Markt(24.09.2026 um 23:41 Uhr)
••
Sicherheitslücken (CVE)IT Security News Daily Summary 2026-09-24(24.09.2026 um 23:55 Uhr)
•
Sicherheitslücken (CVE)IT Security News Roundup: 2026-09-24(24.09.2026 um 23:57 Uhr)
•
Sicherheitslücken (CVE)IT Security News Hourly Summary 2026-09-25 00h : 9 posts(25.09.2026 um 00:00 Uhr)
•••
IT NachrichtenMicrosoft puts Brad Smith in charge of communications(25.09.2026 um 00:08 Uhr)
••
Intelligence View
⚡ tsecurity.de Intelligence

5 things that surprised me building on HMRC's Making Tax Digital API

I spent the last while building the HMRC integration for TapTax, a Making Tax Digital (MTD) app for UK sole traders. MTD is the UK government's programme that pushes tax filing out of paper and spreadsheets and into software talking…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!

I spent the last while building the HMRC integration for TapTax, a Making Tax Digital (MTD) app for UK sole traders. MTD is the UK government's programme that pushes tax filing out of paper and spreadsheets and into software talking directly to HMRC's APIs.



I have integrated with a fair few third-party APIs. Stripe, Plaid-style banking, the usual. HMRC is its own animal. Some of it is genuinely well designed, some of it caught me completely off guard, and a couple of things cost me a full day each before the penny dropped.



So here are the five things that surprised me most. Each one is the surprise, then the fix, with a short snippet from our actual TypeScript backend. Not tax advice, just engineering notes from someone who has now stepped on the rakes so you do not have to.






1. The API version lives in the Accept header, and getting it wrong is a 406



Most APIs version in the URL: /v2/thing. HMRC versions through content negotiation. You ask for a version in the Accept header, like application/vnd.hmrc.5.0+json, and if you ask for a version that endpoint does not serve, you get a 406 Not Acceptable. No helpful "did you mean v3" message. Just 406.



The part that bit me: different endpoints are on completely different versions at the same time. Obligations is on v3.0, the self-employment cumulative summary is on v5.0, calculations are on v8.0, ITSA status is on v2.0. There is no single "current" version to pin.



The fix was to make the version a required argument on the request wrapper so you can never forget it, and set it per call:




// src/services/hmrcApi.ts
const headers = {
Authorization: `Bearer ${accessToken}`,
Accept: `application/vnd.hmrc.${apiVersion}+json`, // e.g. "5.0"
...hmrcConfig.getFraudHeaders(req),
};






One more trap: versions get withdrawn. Obligations used to answer on v2.0; that now returns a 404, not a 406, so it looks like a missing resource rather than a stale version. When an HMRC call 404s, check the version before you go hunting for a bad path.






2. You have to send HMRC a fingerprint of the device on every call



This one is wild the first time you read the docs. HMRC requires a set of "fraud prevention headers" on every API call: a couple of dozen Gov-Client-* and Gov-Vendor-* headers describing the device, the network, the screen, the timezone, and your own server. It is anti-fraud telemetry, and it is mandatory.



The surprise inside the surprise: the connection method decides which headers are legal. A server-mediated web app and a server-mediated mobile app send different sets, and sending the wrong one is an error, not a nice-to-have. So I branch on it:




// src/config/hmrc.ts
const connectionMethod =
req.platform === 'mobile' ? 'MOBILE_APP_VIA_SERVER' : 'WEB_APP_VIA_SERVER';

if (isMobile) {
// mobile REQUIRES the device user-agent, and must NOT send browser headers
headers['Gov-Client-User-Agent'] = mobileUa;
} else {
// web sends the browser JS user-agent, and must NOT send Gov-Client-User-Agent
headers['Gov-Client-Browser-JS-User-Agent'] = browserUa;
}






There is a great free tool that saves you here: HMRC's Test Fraud Prevention Headers API. It tells you exactly which header is missing or malformed. Build against it from day one.






3. Quarterly updates are cumulative, not "this quarter"



You file four times a year, so the obvious model is "four quarters, four payloads, each holding that quarter's numbers." That is wrong, and it is the kind of wrong that passes your first test and then quietly corrupts everything.



Each quarterly update is cumulative: year-to-date from 6 April, not the delta for the quarter that just closed (gov.uk guidance). The clue is in the HTTP method and the path. You do not POST a quarter. You PUT a summary keyed by the tax year:




// PUT /individuals/business/self-employment/{nino}/{businessId}/cumulative/{taxYear}
// turnover/expenses are running totals since 6 April, NOT just this quarter
await hmrcApi.submitQuarterlyUpdate(nino, businessId, '2026-27', token, req, {
periodDates: { periodStartDate: '2026-04-06', periodEndDate: '2027-01-05' },
periodIncome: { turnover: 42000, other: 0 },
periodExpenses: { costOfGoods: 11000 /* ... */ },
});






Because it is a PUT keyed by the year, it is idempotent. Resending the same snapshot is a no-op, and a correction is just a fresh snapshot of the whole year. The practical rule I landed on: never keep a running counter you increment each quarter. Recompute the year-to-date total from your transaction ledger every time. Derive, do not accumulate.






4. The OAuth state token is single-use, and the redirect URI has to match to the character



The OAuth flow itself is standard Authorization Code, but two details are stricter than I expected.



First, the state token. I treat it as single-use and delete it the moment it comes back, then check it has not expired. This is normal CSRF hygiene, but HMRC's sandbox is unforgiving about replays, so a "works once, fails on refresh/back-button" bug is easy to create if you leave the state lying around:




// src/routes/auth.ts
await deleteStateToken(state); // single-use: delete immediately
if (Date.now() - stateToken.createdAt > 10 * 60 * 1000) {
redirectError(platform, 'Authorization request has expired. Please try again.');
return;
}






Second, the redirect_uri. It has to match what you registered on the HMRC Developer Hub exactly. Same scheme, same host, same path, trailing slash and all. A mismatch does not warn you, it just fails the token exchange. I keep mine in one config value and reuse it for both the authorize URL and the token POST so the two can never drift apart.






5. The sandbox is fussy in ways production never warns you about



Two sandbox gotchas ate hours, and both are about request shape rather than data.



A GET with Content-Type: application/json and no body gets rejected by HMRC's CloudFront edge as a 403 Bad request. Every read endpoint broke at once. The fix is to only set the JSON content type when there is actually a body:




// src/services/hmrcApi.ts
if (data !== null && data !== undefined) {
headers['Content-Type'] = 'application/json'; // never on a bodyless GET
}






The mirror image: some POSTs that take no meaningful body 500 if you send null, but accept an empty object. Triggering a calculation is the classic one:




// {} not null: a null-bodied POST 500s on HMRC's calc backend, {} is accepted
await hmrcApi.triggerCalculation(nino, taxYear, token, req); // sends {}






While you are in the sandbox, two more things worth knowing. Use the Gov-Test-Scenario header to drive deterministic responses, because the no-scenario defaults can hand you stale data from old tax years that newer endpoints then reject. And wrap your calls in a retry with backoff: the sandbox throws transient 429s and 5xxs that have nothing to do with your code.




// retry on 429 + 500/502/503/504 + network errors, exponential backoff
return [429, 500, 502, 503, 504].includes(status);









The takeaway



None of this is unreasonable once you see why it exists. HMRC is moving the entire UK tax base onto software, and the friction is mostly anti-fraud and backwards-compatibility showing through the API surface. The trick is to stop reasoning by analogy with friendlier APIs: read the version off each endpoint, lean on the header validator, model state instead of events, and treat the sandbox as a strict reviewer rather than a forgiving toy.



If you are about to start an MTD integration: pin versions per endpoint, build against the fraud-header validator on commit one, make your submissions idempotent, and budget a day for the sandbox to teach you its quirks. That is most of the pain, paid down up front.



Happy to answer questions in the comments if you are wrangling MTD too.






Solomon Amos is the founder of TapTax, a Making Tax Digital app for UK sole traders. He built TapTax's HMRC integration, spent two years embedded at HMRC's digital programmes, and holds a PhD in machine learning. The code above is from TapTax's own integration; this is an engineering write-up, not tax advice. linkedin.com/in/solomonudoh

CTI Threat Relationship Graph2 Knoten / 1 Relationen
CVE / Incident Software MITRE ATT&CK CWE Weakness IoC
SOC Incident Playbook: Remote Code Execution (RCE) Defense
1 Warnungen
title: Detect Exploitation - 5 things that surprised me building on HMRC's Making Tax Digital API
id: fb13da59-6197-433f-9051-52dcaef70b35
status: experimental
description: Automatisch generierte SIEM-Erkennungsregel basierend auf CTI Intelligence
references:
  - https://tsecurity.de/
author: iShareStuff CTI Automated Detection Engine
date: 2026-09-25
logsource:
  category: network_connection
  product: any
detection:
  selection:
      CommandLine|contains:
        - 'exploit'
  condition: selection
falsepositives:
  - Legitime administrative Zugriffe oder Penetrationstests
level: high
tags:
  - attack.initial_access
Syntax validiert (0 Fehler)
rule CTI_Threat_Indicator {
    meta:
        author = "iShareStuff CTI Automated Detection Engine"
        date = "2026-09-25"
        description = "YARA Signature for "
    strings:
        $str = "5 things that surprised me bui" ascii wide
    condition:
        any of them
}
Syntax validiert (0 Fehler)
index=security sourcetype IN ("cisco:asa", "pan:traffic", "zeek_conn", "suricata", "WinEventLog:Security")
("5 things that surprised me building on H")
| stats count earliest(_time) as first_seen latest(_time) as last_seen by src_ip, dest_ip, dest_host, signature
| eval first_seen=strftime(first_seen, "%Y-%m-%d %H:%M:%S"), last_seen=strftime(last_seen, "%Y-%m-%d %H:%M:%S")
| sort - count
Syntax validiert (0 Fehler)
message: "*5 things that surprised me building on H*"
Syntax validiert (0 Fehler)
CommonSecurityLog
| where Message has "5 things that surprised me building on H"
| summarize EventCount = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated) by SourceIP, DestinationIP, DestinationPort, Activity
| extend DetectionRule = "iShareStuff-CTI-Compiled"
| sort by EventCount desc
🎯
MITRE ATT&CK Matrix Navigator 14 Taktiken
Reconnaissance
-
Resource Development
-
Initial Access
Execution
Persistence
-
Privilege Escalation
Defense Evasion
Credential Access
-
Discovery
-
Lateral Movement
-
Collection
-
Command and Control
Exfiltration
-
Impact
tsecurity.de Cognitive Threat RAG
Fokus-Vektor:

Kognitive Analyse für identifizierte Bedrohung: Erhöhte Bedrohungslage im Bereich 5 things that surprised me building on H.... Basierend auf 368k Vektor-Korrelationen werden sofortige Isolationsmaßnahmen für betroffene Endpunkte empfohlen.

🛡️ Angriffsfläche & Exposure

Netzwerk/Remote-Zugriff ohne Vorauthentifizierung möglich.

⚡ Empfohlene Sofortmaßnahmen
  • 1. Perimeter-Inspektion: Relevante Portfreigaben und exponierte Endpunkte unverzüglich scannen.
  • 2. Patch-Applikation: Hersteller-Hotfix einspielen oder betroffene Daemons in isolierte DMZ-Segmente überführen.
  • 3. Telemetrie & EDR-Alerts: Prozessaufrufe und Child-Processes auf anomale Shell-Spawns überwachen.
🔗 Semantisch verwandte Zero-Days MariaDB 11.7 VEC
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten 5 things that surprised me building on HMRC's Making Tax Digital API

Thematisch verwandte Begriffe: things, that, surprised, building · 6 Treffer

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-87722 | Uncontrolled Resource Consumption (CWE-400 / CWE-1333) in regex search q…
Advisory →
tsecurity.de Icon
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel • Rechts: nächster Artikel • unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel TTP ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...
↗ Original-Quelle