UK payments & ecommerce

Building HMRC MTD for Income Tax Software: A UK API Architecture

Choose the production-access route before writing filing code, then make authority, submission and reconciliation separate operational controls.

Guide cover: building the right HMRC Making Tax Digital software boundary
By Ritesh Agarwal15 min read

Direct answer

A UK accountancy firm should not begin an MTD for Income Tax project by coding a quarterly-submission screen. First decide whether the product will file directly, integrate an approved filing product, or remain a workflow and eligibility layer. As of 7 November 2026, HMRC says it is no longer accepting new production credential requests for 2026–27 quarterly-update products. A new product can still prototype in the sandbox, but it should not promise live filing until HMRC confirms its production route. If direct filing is viable, treat OAuth authority, fraud-prevention headers, business sources, obligations, write attempts and post-submission reconciliation as separate records.

RouteProve production accessSandbox availability is not permission to launch a filing product.
AuthorityBind the right taxpayerCustomer, main agent and supporting agent access are not interchangeable.
ClosureReconcile the obligationAn accepted request can remain pending before HMRC marks the obligation fulfilled.

Executive summary

  1. Production eligibility is a commercial gate; check it before estimating a direct-filing roadmap.
  2. A planner, bookkeeping system and HMRC filing product have different assurance and access requirements.
  3. HMRC requires OAuth user authority and compliant fraud-prevention headers for the MTD Income Tax APIs.
  4. Close a submission only after the corresponding obligation is refreshed or an owned exception is raised.

The Appycodes MTD build that deliberately stops before filing

In September 2026, Appycodes designed and shipped a public Making Tax Digital for Income Tax checker for UK sole traders and landlords. The repository contains the original product brief, the 302-line rules engine, the user interface and the release commit. A user enters gross self-employment and property income for the relevant tax years; the tool applies the phased thresholds, chooses the earliest qualifying band, builds the standard quarterly dates and exports an .ics calendar.

The difficult decision was the product boundary. A live HMRC connection would have made the page look more authoritative, but it would also have changed a low-risk planning tool into an authenticated tax-software product. The team kept the calculation in the browser, stored no income figures, used published rules and stated that the checker does not access HMRC or confirm whether an obligation has been met. That reduced capability is intentional: it avoids pretending that a threshold calculation is a filing status.

There is also a real limitation. The checker can explain a likely start date from the figures supplied, but it cannot discover the customer's HMRC business sources, agent relationship, exemption, enrolment state or live obligations. It cannot submit or retrieve a tax calculation. Those gaps are why the next step is not “add an API key”; it is a different architecture and approval programme.

Evidence boundary. The Appycodes project repository and commit history verify the planner's scope, rules engine, calendar export and explicit no-HMRC boundary. They do not verify a production MTD filing integration, a client filing outcome or approval from HMRC. Appycodes also receives HMRC Software Developer Support updates through its connected developer context, but no private subscriber, credential or customer information is used here.

You can inspect the live MTD for Income Tax checker. Its narrow scope is a useful design pattern for UK firms: separate the customer-help feature you can safely deliver now from the regulated or approval-dependent transaction you may need to source elsewhere.

Choose direct filing, an approved integration or a workflow layer

HMRC's current Business Details and Individual Calculations API pages both warn that the market window for new 2026–27 quarterly-update products has closed. The APIs remain visible in sandbox and existing production products may use supported versions, but a new supplier must confirm what later production route is open before making a sales promise. HMRC: Business Details (MTD) API · HMRC: Individual Calculations (MTD) API

RouteBest fitYou ownHard constraint
Build direct HMRC filingEstablished UK tax-software vendor with a long product horizon and tax-domain teamOAuth, API versions, headers, tax journeys, approval evidence, support and reconciliationProduction route, minimum functionality and approval must be confirmed first
Integrate an approved filing productAccountancy practice, vertical SaaS or landlord platform that owns the workflow but not every tax journeyCustomer experience, digital links, consent, data mapping, exception handling and supplier exitThe partner's API and contract must support your exact agent and filing journey
Build a workflow layer onlyPractice portal or lightweight bookkeeping product needing records, reminders and handoffDigital records, task state, evidence export and a clear transfer to filing softwareNever describe a local status as HMRC acceptance or fulfilment
Buy end-to-end softwareSmall or mid-sized practice whose differentiation is advice, not tax-platform engineeringConfiguration, staff process, data quality, access reviews and continuity planningProduct fit, migration and vendor lock-in still need testing

HMRC's integration guide sets minimum functionality across the customer journey and identifies the API families needed for in-year and end-of-year products. For in-year updates, that includes Business Details, Obligations and Self-Employment Business and/or Property Business; Individual Calculations is also needed if the software displays calculations rather than signposting the customer to HMRC. End-of-year software needs a broader set for adjustments, losses and the final declaration. HMRC: how to integrate with MTD for Income Tax APIs

That list changes the build-versus-buy calculation. A practice may only want “send quarterly totals”, but the production product must support the surrounding journey it advertises. A narrow partner integration can be more honest and cheaper than owning a tax engine, approval evidence and multi-year API lifecycle.

The Appycodes MTD Delivery Gate

Score five gates from 0 to 3: 0 unknown, 1 assumed, 2 documented but unproved, 3 tested with retained evidence. The maximum is 15. Market Access and Authority are hard gates: either at zero means no live filing commitment, regardless of the total.

Five MTD delivery gates × 0–3Maximum 15
MMarket access
A confirmed HMRC production route, supported version and approval plan.
AAuthority
Customer or agent grant, scopes, subject, refresh lifecycle and revocation.
CCoverage
Every advertised business source, period, adjustment and handoff is supported.
FFraud evidence
Connection method, header collection, validation feedback and privacy notice agree.
RReconciliation
Accepted writes close against obligations or enter an owned exception queue.
13–15 · production candidateRun HMRC approval, failure and support rehearsals before committing a launch date.
9–12 · sandbox prototypeProve the missing gates and keep the customer promise explicitly non-production.
0–8 · integrate or buyDo not make customers depend on a filing route the product cannot operate.

The gate is an architecture and product-readiness model, not tax or regulatory advice and not a statistical risk score. Apply it to the precise product variant. A workflow portal might score three for Coverage without direct filing because its documented end state is an export to approved software; a product claiming live submission cannot.

A production architecture needs a control loop, not one API call

AUTHORISE · RESOLVE · SUBMIT · RECONCILEDigital recordsbusiness sourcesperiod totalsOAuth authoritycustomer or agentscopes · expiryObligationsbusiness · periodopen · fulfilledSubmissionlocal attempt IDHMRC responseReconcilepoll obligationclose or exceptionFOUR EVIDENCE RECORDS · DIFFERENT OWNERS AND LIFECYCLESAuthority grantsubject · scopesrefresh version · expiryHeader evidenceconnection methodvalidation feedbackAttempt ledgerpayload hash · responseretry decisionException queuepending · rejectedowner · next actionOperational proofsubmission response + refreshed obligation + customer-visible receipt + support trace · secrets and raw personal data excludedA 2XX RESPONSE IS NOT A FULFILLED OBLIGATION · A SANDBOX PASS IS NOT PRODUCTION APPROVALFIG. 01MTD FILING CONTROL LOOP
Fig. 01 The product keeps customer records, HMRC authority, submission attempts and obligation evidence separate. An accepted write starts reconciliation; it does not finish it.scroll →

HMRC user-restricted endpoints use OAuth 2.0 authorisation code grants. Individuals and organisations access their own data; agents act for clients according to the relationship and endpoint rules. Access tokens last four hours, and refresh authority eventually expires, so a durable product needs a recoverable reauthorisation journey rather than a hidden token-refresh loop. HMRC: user-restricted endpoint authorisation

RecordMinimum fieldsWhy it stays separate
Authority grantTenant, HMRC subject, account/agent type, scopes, encrypted refresh-token version, expiry, revoked timeA staff session is not the taxpayer's authority; grants can expire or lose scope.
Business sourceNative business ID, type, accounting period, quarterly-period choice, retrieved timeOne taxpayer can have several self-employment and property sources with different states.
Obligation snapshotBusiness, period, due date, status, source response version, retrieved timeThe operational deadline comes from HMRC, not from a locally generated calendar alone.
Submission attemptLocal ID, obligation, payload hash, state, correlation ID, accepted time, error codeBrowser retries, uncertain responses and amended figures need an auditable history.
Header evidenceConnection method, specification version, validation state, tested device classesFraud headers are a production control with changing formats, not request decoration.
ExceptionFailure class, customer-safe explanation, owner, next action, deadline, closure evidenceTax deadlines need an operator path when authority, data or HMRC state disagrees.

HMRC says fraud-prevention headers are legally required for its MTD Income Tax APIs and that continued incorrect or missing data can lead to sanctions or blocked API access. Its validator checks individual requests and later sandbox feedback, but HMRC warns that a validator pass is not a guarantee of production compliance. HMRC: send fraud-prevention data · HMRC: Test Fraud Prevention Headers API

Design headers at the start. A browser product, installed desktop tool, server-to-server bridge and remote desktop deployment expose different signals. If the chosen stack cannot lawfully and reliably collect the required values for its connection method, that is an architecture blocker—not a task to leave until production approval.

Make the write idempotent locally, then reconcile

The TypeScript service below sits above an HMRC adapter. The adapter owns the current endpoint path, media type, OAuth token and fraud headers; the domain service owns the business source, obligation and attempt ledger. This keeps a version change from leaking across the whole product and prevents a double click from becoming a second uncontrolled write.

Prepare one local attempt, verify the open obligation, submit once and queue reconciliationtypescript
type SubmissionState =
  | "prepared"
  | "sending"
  | "accepted_pending_obligation"
  | "fulfilled"
  | "needs_review";

type SubmitQuarterInput = {
  tenantId: string;
  authorityId: string;
  businessId: string;
  obligationId: string;
  periodEnd: string;
  totals: Record<string, number>;
};

export async function submitQuarter(input: SubmitQuarterInput) {
  const payloadHash = stableHash(input.totals);
  const attempt = await db.mtdSubmission.upsert({
    where: {
      obligationId_payloadHash: {
        obligationId: input.obligationId,
        payloadHash,
      },
    },
    create: {
      ...input,
      payloadHash,
      state: "prepared",
    },
    update: {},
  });

  if (["accepted_pending_obligation", "fulfilled"].includes(attempt.state)) {
    return attempt; // a browser retry cannot create a second local write
  }

  const authority = await authorityVault.getUsableGrant(input.authorityId);
  const obligation = await hmrc.getObligation({
    authority,
    businessId: input.businessId,
    obligationId: input.obligationId,
  });
  if (obligation.status !== "open" || obligation.periodEnd !== input.periodEnd) {
    return db.mtdSubmission.update({
      where: { id: attempt.id },
      data: { state: "needs_review", errorCode: "obligation_mismatch" },
    });
  }

  await db.mtdSubmission.update({
    where: { id: attempt.id },
    data: { state: "sending", sentAt: new Date() },
  });

  const response = await hmrc.submitQuarterlyUpdate({
    authority,
    businessId: input.businessId,
    periodEnd: input.periodEnd,
    totals: input.totals,
    // The adapter adds the API version and the fraud-prevention headers for
    // this product's documented connection method.
  });

  await db.mtdSubmission.update({
    where: { id: attempt.id },
    data: {
      state: "accepted_pending_obligation",
      hmrcCorrelationId: response.correlationId,
      acceptedAt: new Date(),
    },
  });

  await jobs.enqueue("reconcile-mtd-obligation", {
    submissionId: attempt.id,
    notBefore: addMinutes(new Date(), 10),
  });

  return { ...attempt, state: "accepted_pending_obligation" as const };
}

The unique key is local because this guide does not assume that every HMRC endpoint offers a provider idempotency key. For a timeout after the request leaves your server, do not blindly repeat the write. Preserve the attempt as uncertain, retrieve the latest obligation or supported summary state, and let an operator or endpoint-specific retry rule decide whether resubmission is safe.

HMRC says a submitted quarterly update or annual return can take up to an hour to appear as a fulfilled obligation. Its guidance also says software should continue to show the latest obligations and notes that changing from standard to calendar quarters requires a refresh before submitting against the new periods. Model accepted_pending_obligation as a normal state, poll with sensible backoff, and show the customer a receipt plus the fact that confirmation is pending. HMRC: updates, obligations and processing latency

  1. Prepare. Freeze the business source, obligation, period and totals under a payload hash; require a fresh customer or agent confirmation for material changes.
  2. Authorise. Resolve the correct grant and scopes. Refresh server-side; if authority has expired or been revoked, stop with a customer-safe reauthorisation path.
  3. Submit. Send the documented API version and connection-method headers. Store the HTTP result and correlation identifier without logging tokens or unnecessary personal data.
  4. Reconcile. Refresh the obligation after the documented delay. Close only when HMRC state and the local attempt agree; otherwise create an owned exception.
  5. Support. Give staff the attempt ID, business source, period, safe error class and next action—not a screen of raw API data.

Seven failure modes to rehearse before a tax deadline

1. The sandbox works, but the product has no production route

This is the most expensive failure because it can appear after a polished prototype. Record written confirmation of the applicable production process, target cohort, API versions and approval evidence before a fixed launch commitment. The 2026–27 market-window warning makes this a current risk, not a theoretical one.

2. One OAuth grant is treated as office-wide authority

Keep grants per subject and agent context. Re-check access when staff move teams or a client ends the engagement. HMRC's integration guide distinguishes main and supporting agents; supporting agents can use only specified endpoints. A 403 may be an authority-model error, not a transient outage.

3. Fraud headers are assembled from server defaults

A cloud server's IP address and user agent do not automatically describe the originating user environment. Select the documented connection method, capture the required values at the correct boundary, encode them correctly and test across representative devices and network paths.

4. A 2xx response marks the quarter complete

Keep acceptance and fulfilment separate. Poll the relevant obligation, allow the documented processing delay and escalate a stale pending state. This prevents a customer dashboard from declaring success while HMRC still shows an open obligation.

5. Quarterly dates are generated instead of retrieved

A calendar is useful for planning, as Appycodes' checker demonstrates. Filing software must work from HMRC business-source and obligation state, including calendar-quarter elections, new businesses and changes. Local dates should support reminders, never replace live obligation identity.

6. API errors are shown directly to the customer

Map provider errors into stable product classes such as reauthorise, amend records, wait for HMRC, contact support or manual review. Retain the original code and correlation ID for operators. Do not expose tokens, National Insurance numbers or raw payloads in analytics, support chat or browser logs.

7. API versions change without an owned upgrade path

Pin the media type in one adapter, monitor deprecation and sunset headers, run contract tests against the sandbox and inventory which customer journeys use each version. A tax deadline is the wrong time to discover that one endpoint moved and another changed validation.

Recommendations for UK firms

UK accountancy practiceOwn workflow, not necessarily filing infrastructure

If advice and client service are the differentiators, integrate approved software or buy end to end. Build the portal, evidence, reminders and exception routing around a tested filing handoff.

Accounting software vendorGate the roadmap on HMRC access

Confirm the future production route, map minimum functionality, budget for fraud-header evidence and operate version upgrades and deadline support as product capabilities.

Landlord or vertical SaaSKeep property operations separate from tax filing

Maintain digital records and source-level totals, then integrate an approved tax route. Do not make a rent ledger responsible for tax calculation or authority it cannot prove.

Bookkeeping or receipt appMake the handoff auditable

Preserve digital links, mapping versions and export receipts. State clearly whether the product records, prepares or files; those verbs carry different customer expectations.

After building the public MTD planner and reviewing the current HMRC production constraints, Appycodes recommends a two-week discovery before a direct-filing estimate: confirm production eligibility with HMRC, choose the supported customer and agent journeys, prototype OAuth and fraud headers on representative devices, submit sandbox scenarios, and rehearse one accepted-but-not-yet-fulfilled obligation. If any hard gate remains unknown, price an approved-product integration instead.

Our API and integration service covers product-boundary discovery, HMRC or partner adapters, secure authority storage, reconciliation, observability and operational handover. The Professional Energy case study shows the wider Appycodes approach to replacing disconnected business workflows with a central, supportable operational system; it is related delivery evidence, not a claim that the project used HMRC's MTD APIs.

Our ruleDo not promise a filing button until production access, taxpayer authority, fraud evidence and obligation reconciliation all have named owners and test evidence.

Frequently asked questions

Can a UK software company still build a new MTD for Income Tax filing product?
It can build and test in HMRC's sandbox, but it must confirm the applicable production-access route before committing to a launch date. On 7 November 2026, HMRC's Business Details and Individual Calculations API pages said new production credential requests for 2026–27 quarterly-update products were no longer being accepted because that market window had closed. That does not prohibit every future product, but it makes production access a first-stage commercial gate.
Does an MTD eligibility checker need HMRC API access?
No. A planner can apply published income thresholds and dates to figures entered by the user without accessing HMRC. It must say that it cannot confirm enrolment, obligations or filings. Filing software is a different product: it needs HMRC user authorisation, the relevant APIs, compliant fraud-prevention headers, sandbox evidence and production approval.
Which APIs does MTD for Income Tax software need?
The set depends on the supported journey. HMRC's current integration guide identifies Business Details, Obligations, Self-Employment Business and/or Property Business for in-year updates, with Individual Calculations when the product displays calculations rather than sending the user to HMRC. End-of-year products require additional calculation, adjustment and loss APIs. Treat that list as a versioned product dependency, not a one-off integration checklist.
Can an accountancy firm use one HMRC OAuth connection for every client?
No. The authority must represent the relevant customer or authorised agent and the scopes the product needs. HMRC distinguishes individual, organisation and agent accounts, and supporting agents have more restricted endpoint access. Store each grant, subject, scopes, expiry and refresh state separately; never treat an office login as universal client authority.
Are HMRC fraud-prevention headers optional telemetry?
No. HMRC states that compliant fraud-prevention headers are legally required for Income Tax Self Assessment MTD APIs and must be evidenced before production access. Header design is therefore an architecture requirement: the product must know its connection method, collect the permitted device and network signals, validate their format and keep privacy information accurate.

Primary sources

Published 7 Nov 2026Reviewed 7 Nov 2026Reviewer Appycodes Editorial Team

Technical and operational guidance, not tax, legal, accounting, regulatory or financial advice. HMRC API access, versions and product windows can change; confirm the current position with HMRC and qualified advisers before committing a filing product.

Our clients

UK · Europe · Worldwide

Selected case studies

What we built, how it works and the results for our clients.

Creoate product interface01
B2B commerce

Eight years behind a wholesale marketplace

Next.js storefront, Python ingestion pipelines, DynamoDB data layer and AWS infrastructure.

8+ yearsdevelopment and support
Ontick product interface02
Event technology

Ticketing owned by the event team

Multi-organiser commerce, Stripe instalments and two native apps in one connected platform.

£2M+ticket sales processed
Easyship product interface03
Global logistics

Helping shippers compare their options

Rate, tax and duty calculators, server-rendered courier pages and a custom MongoDB CMS.

550+couriers in the calculator
TEFL.ie product interface04
Education & training

Connecting course sales to the classroom

WordPress and WooCommerce, a Moodle LMS, Stripe deposits and Zoho CRM, tied together with Zapier automation.

Since 2017development and support
All White Laser product interface05
Medical aesthetics

From equipment finance to clinic support

A lead-to-billing system on GoCardless Direct Debit, provider certification, and a React Native app for machine owners.

9 yrsdevelopment and support
Decofetch product interface06
Luxury commerce

A custom home for designer furniture

Server-rendered Next.js commerce over a Laravel API, bespoke operations tooling and re-architected AWS infrastructure.

0→livemarketplace development
BA Engine Room product interface07
AI operations

Connecting discovery, contracts and delivery

Discovery briefs, e-signed contracts, Stripe deposits, delivery milestones and time tracking in one operational system.

0→1custom platform development
PlusHeat product interface08
Home services

Helping customers choose their boiler cover

Custom plan configuration, postcode-qualified lead journeys, CRM synchronisation and campaign landing pages.

5 yrswebsite development and support
Léonia product interface09
Beauty commerce

Shopify shaped around a beauty brand

Custom theme, customer accounts, loyalty rewards, referrals and gift-with-purchase offers.

5 yrsShopify development and support
Shutters 365 product interface10
Home improvement

From window measurements to a priced order

A seven-step product builder with live previews, sample orders and supplier tools.

7-stepproduct configurator
Bloc Ads Manager product interface11
Advertising

From targeted ads to venue check-ins

Campaign creation, audience targeting, in-app ads and reporting linked to venue check-ins.

check-inscampaign attribution
Bloc product interface12
Social events

Four years across the app and operations

Mobile app, backend, advertising tools, a digital marketplace and website.

4+ yrssupport across five codebases
Zonely product interface13
Social mobile

Two apps, one real-time conversation marketplace

Customer and buddy apps with per-minute billing, wallets, moderation and admin tools.

2 appsfor iOS and Android
Player Profile Hub product interface14
Grassroots football

Helping grassroots players get discovered

Verified profiles, video highlights, coach discovery and safeguarding on web and mobile.

0→1custom platform development
DeepSpatial product interface15
Geospatial AI

Connecting clients, investors and emerging talent

Corporate and investor pages, the Xploor talent platform and ongoing releases on AWS Amplify.

2 yrsdevelopment and support
Yippee Malta product interface16
Travel

A booking journey the tour team owns

A multilingual website connected to the booking API, with deposits, coupons and affiliate tracking.

6languages across the booking journey
Professional Energy product interface17
Energy brokerage

Tenders, contracts and accounts brought together

Supplier tenders, contract management, brokerage accounting and client records.

100+suppliers per tender

Tell us what you are trying to build.

A thirty-minute call with the engineer who would run it.