---
title: Delivery API
description: Transition a request from in_progress to fulfilled. This marks the
  DSAR as complete and triggers a request_fulfilled notification to the data
  subject.
group: reference-api
---
> ⚠️ **Warning:** **Alpha**
> DSAR is currently in alpha. APIs, package surfaces, configuration, and documentation may change as the project evolves.

## POST /requests/:id/fulfilment

Transition a request from `in_progress` to `fulfilled`. This marks the DSAR as complete and triggers a `request_fulfilled` notification to the data subject.

**Prerequisites:**

* The request must be in `in_progress` status.
* If a fulfilment manifest exists, its `validationState` must be `"approved"`. For request types that do not produce artifacts (e.g. deletion, rectification), no manifest is required.

**Request body:** None required.

**Response (202):**

```json
{
	"id": "req-123",
	"status": "fulfilled",
	"dueAt": "2026-04-04T13:58:00.000Z"
}
```

**Error codes:**

* `FULFILMENT_MANIFEST_NOT_APPROVED` (DSAR-BE-1209): A manifest exists but has not been approved yet
* `LIFECYCLE_TRANSITION_DISALLOWED` (DSAR-BE-1401): Request is not in `in_progress` status

**CLI:**

```sh
dsar requests fulfilment create <request-id>
```

## POST /requests/:id/fulfilment/callback

Accept a fulfilment callback payload that carries the generated artifact
manifest back into the request workflow.

`POST /requests/:id/fulfilment/callback` does **not** finalize the request.
The current implementation records the callback payload, creates or updates a
pending manifest record, appends audit and notification events, and returns a
`"recorded"` status. Call `POST /requests/:id/fulfilment` separately when the
request is ready to transition to `fulfilled`.

**Request body:**

* `manifest` (object, required)
* `manifest.artifacts` (array, required)
* `manifest.supplementaryInfoInline` (string, optional)
* `manifest.supplementaryInfoRef` (string, optional)

**Response (202):**

```json
{
	"requestId": "req-123",
	"status": "recorded"
}
```

After `POST /requests/:id/fulfilment/callback`, use
`POST /requests/:id/manifest/validate` if manifest review is enabled, then call
`POST /requests/:id/fulfilment` to complete fulfilment and emit the final
fulfilment notification.

## POST /requests/:id/delivery/prepare

Prepare delivery of fulfilled data. Requires a fulfilment artifact to exist.

**Request body:**

* `channel` (string): "portal" | "email" | "secure\_remote\_access"
* `securityLevel` (string): "standard" | "token"

**Response (202):**

```json
{
	"requestId": "req-123",
	"artifactId": "art-456",
	"deliveryPrepare": {
		"channel": "portal",
		"preparedAt": "...",
		"preparedBy": "..."
	},
	"surface": "delivery_prepare"
}
```

## POST /requests/:id/delivery/address/verify

Verify a delivery address.

**Request body:**

* `email` (string, optional)

**Response (200):**

```json
{
	"requestId": "req-123",
	"email": "user@example.com",
	"verified": true
}
```

## POST /requests/:id/delivery/step-up/challenge

Issue a step-up verification challenge. Returns a token valid for 24 hours.

**Response (202):**

```json
{
	"requestId": "req-123",
	"token": "challenge-token-uuid",
	"expiresAt": "2026-02-26T00:00:00.000Z"
}
```

> The `expiresAt` value is always 24 hours from issuance.

## POST /requests/:id/delivery/step-up/complete

Complete a step-up challenge by submitting the token.

**Request body:**

* `token` (string, required)

**Response (202):**

```json
{
	"requestId": "req-123",
	"status": "completed"
}
```

## GET /requests/:id/artifacts/:artifactId/download

Download a delivery artifact.

**Request headers:**

* `x-delivery-token` (string, required): Opaque token obtained from the step-up challenge flow. Issue a challenge via `POST /requests/:id/delivery/step-up/challenge`, then complete it via `POST /requests/:id/delivery/step-up/complete`. The token from the challenge response must be passed here. Tokens expire 24 hours after issuance; the gate must be in `completed` status.

**Response (200):**

```json
{
	"requestId": "req-123",
	"artifactId": "art-456",
	"artifact": {}
}
```

## GET /requests/:id/delivery/logs

Get delivery attempt logs.

**Response (200):**

```text
{
  "requestId": "req-123",
  "logs": [
    {
      "eventId": "evt-1",
      "eventType": "delivery_prepared",
      "attempts": [...]
    }
  ]
}
```
