Skip to main content
The HMRC DPS API manages the notifications HMRC sends employers through the Data Provisioning Service (DPS) — the outbound channel HMRC uses to issue instructions such as tax code changes and student loan starts and stops. You use this API to pull those notifications into Flow Payroll, review them, and apply the ones that should update an employee’s record — one at a time or in bulk. Applied changes feed directly into the payroll you report through RTI — see the HMRC RTI guide for the wider compliance picture. All endpoints sit under the /v1/hmrc-dps base path, relative to the environment base URLs documented on the API reference introduction.

Key concepts

  • Notification — a single DPS message stored for your organisation. Each notification carries a data type, a status, issue and effective dates, the employee details HMRC supplied, the parsed content, and the raw XML received from HMRC.
  • Data type — the kind of notice: P6 and P9 tax code notices, SL1 and SL2 student loan start and stop notices, PGL1 and PGL2 postgraduate loan start and stop notices, plus other message types such as RTI, CIS, P35, AR, NOT, and CISINFO29.
  • Status — where a notification is in its lifecycle: Due (awaiting action), Applied (its change has been written to the employee record), or Dismissed (deliberately not applied).
  • Matching — the service matches each notification to an employee using the identifying data HMRC supplied (National Insurance number, works number, name). Unmatched notifications need an employee assigned before they can be applied.
  • Applying — writing a notification’s change (for example, a new tax code or week 1/month 1 basis) to the matched employee’s record. The service captures an applied-changes snapshot recording the previous value, the new value, and when the change was made.
  • Async job — bulk retrieval, bulk apply, and bulk dismiss run as background jobs (RetrieveAll, BulkApplyNotifications, BulkDismissNotifications) that move through Pending, Running, and then Completed, Failed, or Cancelled.
  • Pagination state — the per-data-type high-water mark that tracks how far retrieval has progressed through HMRC’s feed for the PAYE and CIS services, so each retrieval run only fetches what is new.

API structure

Notifications

List and inspect stored notifications, then act on them individually. GET /notifications lists notifications with dataType and status filters and cursor paging via limit and lastEvaluatedKey; GET /notifications/counts returns headline totals (ready to apply, unmatched, applied, dismissed, generic). Retrieve one notification with GET /notifications/{notificationId}, apply it with POST /notifications/{notificationId}/apply, dismiss it with POST /notifications/{notificationId}/ignore (with an optional reason), set its status directly with PUT /notifications/{notificationId}/status, or assign it to a different employee with PUT /notifications/{notificationId}/employee.

Bulk actions

Work across many notifications at once. POST /notifications/retrieve-all starts an asynchronous job that pulls new notifications down from HMRC. POST /notifications/bulk-apply-async and POST /notifications/bulk-dismiss-async each take a list of notification ids and process them as a background job. POST /notifications/retry-matching re-runs employee matching for every unmatched notification and reports how many matched or failed.

Jobs

Track the background jobs the bulk actions create. GET /notifications/jobs lists jobs with status and limit filters, GET /notifications/jobs/{jobId}/status polls a single job’s status and progress, and GET /notifications/jobs/last/{jobType} returns the most recent job of a given type. Cancel a job with POST /notifications/jobs/{jobId}/cancel.

Pagination

Manage the retrieval high-water marks. POST /notifications/pagination/initialise sets up pagination state for the chosen data types and service (PAYE, CIS, or both) from a given date, with an overwriteExisting flag to replace state that already exists. GET /notifications/pagination returns the state for every supported data type, including data types not yet initialised (shown with a high-water mark of 0).
Two different things are called pagination here: the Pagination endpoints manage how far retrieval has progressed through HMRC’s feed, while the notification list pages its own results with limit and lastEvaluatedKey.

Typical workflow

  1. Initialise pagination with POST /notifications/pagination/initialise, choosing the start date and service you want to retrieve from.
  2. Start a retrieval job with POST /notifications/retrieve-all.
  3. Poll GET /notifications/jobs/{jobId}/status (or GET /notifications/jobs/last/RetrieveAll) until the job completes.
  4. Check GET /notifications/counts, then list what needs action with GET /notifications?status=Due.
  5. Resolve any unmatched notifications: re-run matching with POST /notifications/retry-matching, or assign an employee directly with PUT /notifications/{notificationId}/employee.
  6. Apply or dismiss each notification — individually, or in bulk with POST /notifications/bulk-apply-async and POST /notifications/bulk-dismiss-async — and poll the resulting job to confirm the outcome.
  7. Run retrieval on a regular schedule; the stored pagination state means each run only brings down new notifications.

Notes and best practices

  • Bulk apply and dismiss are asynchronous. The initial response identifies the job — poll its status rather than assuming the work finished.
  • Applying a notification changes the employee’s record, so review unmatched and due notifications before bulk-applying. See Managing people for where those changes surface in the product.
  • Each applied notification keeps a snapshot of the previous value (for example, the prior tax code and week 1/month 1 basis), so you can audit what changed and when.
  • Use overwriteExisting on pagination initialisation deliberately — replacing an existing state resets where retrieval resumes from.
  • When listing notifications, follow the returned pagination token while hasMorePages is true to read the full set.

Authentication

Every request must carry a valid token in the X-Auth-Token header, and multi-organisation credentials must also send X-Org-Id to state which organisation the request applies to — see Authentication. Responses use the shared envelope described in Response format.