> ## Documentation Index
> Fetch the complete documentation index at: https://docs.enfinitos.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Run a DSAR job

> Drive a REQUESTED job through the worker pipeline synchronously: REQUESTED → COLLECTING → PACKAGING → READY, materialising the export artifact between COLLECTING and PACKAGING and persisting it to the artifact store before READY. One request walks the full state machine (the edge sandbox has no background compute; the production worker replaces this route's body without changing the state machine, events, or artifact shape). Only REQUESTED jobs can be run — anything else returns 409; two racing runs cannot both win. A storage failure transitions the job to FAILED with a structured `PACKAGE_WRITE_FAILED` payload and returns 500 with the failed job as context. On success the delivery link expires 7 days out. Requires scope `audit:read`. Request body is ignored.



## OpenAPI

````yaml /openapi-v1.yaml post /v1/compliance/dsar/{jobId}/run
openapi: 3.1.0
info:
  title: EnfinitOS API
  version: v1.0
  description: >-
    The governed-execution `/v1` developer API for EnfinitOS — rights, delivery,
    proof, and settlement.


    Use this API to register the legal **bases** a right rests on, **issue** and
    lifecycle-manage rights across delivery substrates (DOOH, CTV, spatial/AR,
    mobile, audio, and more), negotiate **offers**, raise and resolve
    **challenges**, observe constraint-gated **deliveries**, seal signed **proof
    packs**, read **metering** + **settlement** projections, configure
    settlement **rules** and **counterparties**, fulfil GDPR **compliance**
    requests, and subscribe to **webhooks**.


    Every state-changing action is appended to an immutable, signable audit log;
    delivery and proof artefacts are Ed25519-signed so a downstream auditor can
    verify them offline.


    ## Response envelope

    Every response wraps its payload in a canonical envelope.


    Success (HTTP 200):

    ```json { "ok": true, "data": { ... }, "contractVersion": "v1.0" } ```


    Error (4xx / 5xx):

    ```json { "ok": false, "error": "VALIDATION_FAILED", "message": "human
    text", "contractVersion": "v1.0" } ```

    Some error responses carry additional context fields alongside `error` and
    `message` (for example `field`, `validationErrors`, `requiredScopes`,
    `keyScopes`).


    ## Authentication

    All endpoints except `GET /v1` and `GET /v1/healthz` require an API key sent
    as `Authorization: Bearer <api-key>`. Keys carry a set of named scopes; each
    operation documents the scope it requires. A key carrying the `*` wildcard
    scope passes every scope check.

    Pre-launch, sandbox keys are issued through the apply flow: request access
    at `/apply`, receive an activation email on approval, and exchange it for a
    `/v1` sandbox key in the integration playground at `/developers/playground`.
    Self-service key issuance from the developer dashboard at
    `/developers/dashboard` lands at the April 2027 production launch.


    ## Identifiers

    Resource ids are prefixed: bases `bas_…`, rights `rgh_…`, offers `ofr_…`
    (passed as `rightId`/`offerId`), settlement rules `rule_…`, counterparties
    `cp_…`, webhook subscriptions, and webhook deliveries `dlv_…`. All
    timestamps are ISO-8601 strings.
  contact:
    name: EnfinitOS Developer Support
    url: https://docs.enfinitos.com
    email: developers@enfinitos.com
servers:
  - url: https://sandbox.api.enfinitos.com
    description: Sandbox — live today
  - url: https://api.enfinitos.com
    description: Production — at the April 2027 launch
security:
  - bearerAuth: []
tags:
  - name: Discovery
    description: Unauthenticated contract + health probes.
  - name: Tenant
    description: Read the caller's sandbox tenant snapshot.
  - name: Rights
    description: Bases and the right lifecycle (issue, suspend, resume, revoke).
  - name: Offers
    description: Propose, accept, reject, counter, and withdraw offers.
  - name: Challenges
    description: Open, resolve, and withdraw challenges against rights.
  - name: Delivery
    description: Observe constraint-gated delivery events.
  - name: Audit
    description: The append-only event log.
  - name: Proof
    description: Signed proof packs.
  - name: Metering & Settlement
    description: Metering and settlement projections.
  - name: Settlement config
    description: Settlement rules and counterparties.
  - name: Compliance
    description: GDPR Article 15 export and Article 17 erasure.
  - name: Webhooks
    description: Webhook subscriptions and delivery history.
  - name: Disputes
    description: Delivery disputes — open, investigate, respond, resolve.
paths:
  /v1/compliance/dsar/{jobId}/run:
    post:
      tags:
        - Compliance
      summary: Run a DSAR job
      description: >-
        Drive a REQUESTED job through the worker pipeline synchronously:
        REQUESTED → COLLECTING → PACKAGING → READY, materialising the export
        artifact between COLLECTING and PACKAGING and persisting it to the
        artifact store before READY. One request walks the full state machine
        (the edge sandbox has no background compute; the production worker
        replaces this route's body without changing the state machine, events,
        or artifact shape). Only REQUESTED jobs can be run — anything else
        returns 409; two racing runs cannot both win. A storage failure
        transitions the job to FAILED with a structured `PACKAGE_WRITE_FAILED`
        payload and returns 500 with the failed job as context. On success the
        delivery link expires 7 days out. Requires scope `audit:read`. Request
        body is ignored.
      operationId: runDsarJob
      parameters:
        - $ref: '#/components/parameters/DsarJobId'
      responses:
        '200':
          description: The READY job and the materialised audit report.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/SuccessEnvelope'
                  - type: object
                    properties:
                      data:
                        type: object
                        properties:
                          job:
                            $ref: '#/components/schemas/DsarJob'
                          auditReport:
                            $ref: '#/components/schemas/DsarAuditReport'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/StateConflict'
        '500':
          description: >-
            The artifact-store write failed (INTERNAL_ERROR). The job has been
            transitioned to FAILED; the error envelope carries the failed `job`
            as a context field.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
components:
  parameters:
    DsarJobId:
      name: jobId
      in: path
      required: true
      description: DSAR job id (prefixed `dsar:`).
      schema:
        type: string
  schemas:
    SuccessEnvelope:
      type: object
      required:
        - ok
        - data
        - contractVersion
      properties:
        ok:
          type: boolean
          const: true
        data:
          description: Route-specific payload. Operation responses refine this.
          type: object
        contractVersion:
          type: string
          const: v1.0
    DsarJob:
      type: object
      description: >-
        A DSAR / tenant-export job. Carries its scope, progress, delivery
        payload (once READY), failure payload (if FAILED), and an append-only
        transition timeline.
      properties:
        id:
          type: string
          description: Prefixed `dsar:`.
        orgId:
          type: string
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
        state:
          $ref: '#/components/schemas/DsarJobState'
        scope:
          $ref: '#/components/schemas/DsarJobScopeSpec'
        format:
          $ref: '#/components/schemas/DsarJobFormat'
        requestedBy:
          type: string
        requestNotes:
          type:
            - string
            - 'null'
        progress:
          $ref: '#/components/schemas/DsarJobProgress'
        delivery:
          oneOf:
            - $ref: '#/components/schemas/DsarJobDelivery'
            - type: 'null'
        failure:
          oneOf:
            - $ref: '#/components/schemas/DsarJobFailure'
            - type: 'null'
        timeline:
          type: array
          items:
            $ref: '#/components/schemas/DsarJobTimelineEntry'
    DsarAuditReport:
      type: object
      description: >-
        Human-readable summary attached to every artifact — who requested, when,
        what was included, and which rows were filtered out and why.
      properties:
        jobId:
          type: string
        orgId:
          type: string
        scopeKind:
          $ref: '#/components/schemas/DsarJobScope'
        requestedBy:
          type: string
        requestedAt:
          type: string
          format: date-time
        generatedAt:
          type: string
          format: date-time
        format:
          $ref: '#/components/schemas/DsarJobFormat'
        sectionCounts:
          type: object
          description: name → included count.
          additionalProperties:
            type: integer
        totalRecords:
          type: integer
        redactionNotes:
          type: array
          description: One entry per filter/redaction decision the builder made.
          items:
            type: string
    ErrorEnvelope:
      type: object
      required:
        - ok
        - error
        - message
      properties:
        ok:
          type: boolean
          const: false
        error:
          $ref: '#/components/schemas/ErrorCode'
        message:
          type: string
          description: Human-readable explanation.
        contractVersion:
          type: string
          const: v1.0
        field:
          type: string
          description: Present on some VALIDATION_FAILED errors — the offending field.
        validationErrors:
          type: array
          description: Present on settlement-rule / counterparty validation failures.
          items:
            type: object
            additionalProperties: true
        requiredScopes:
          type: array
          description: Present on SCOPE_MISSING — the scopes the operation needs.
          items:
            type: string
        keyScopes:
          type: array
          description: Present on SCOPE_MISSING — the scopes the presented key carries.
          items:
            type: string
      additionalProperties: true
    DsarJobState:
      type: string
      description: >-
        DSAR / tenant-export job lifecycle. The worker drives REQUESTED →
        COLLECTING → PACKAGING → READY; download drives READY → DELIVERED; a TTL
        sweep drives READY → EXPIRED. DELIVERED, EXPIRED and FAILED are
        terminal.
      enum:
        - REQUESTED
        - COLLECTING
        - PACKAGING
        - READY
        - DELIVERED
        - EXPIRED
        - FAILED
    DsarJobScopeSpec:
      type: object
      required:
        - kind
      properties:
        kind:
          $ref: '#/components/schemas/DsarJobScope'
        dataSubjectId:
          type:
            - string
            - 'null'
          description: Required when kind is DATA_SUBJECT.
        windowStart:
          type:
            - string
            - 'null'
          format: date-time
          description: Required when kind is TENANT_SLICE.
        windowEnd:
          type:
            - string
            - 'null'
          format: date-time
          description: Required when kind is TENANT_SLICE.
        campaignIds:
          type:
            - array
            - 'null'
          items:
            type: string
        substrates:
          type:
            - array
            - 'null'
          items:
            type: string
    DsarJobFormat:
      type: string
      enum:
        - JSON
        - CSV
        - NDJSON
        - PARQUET
    DsarJobProgress:
      type: object
      description: Live progress through COLLECTING + PACKAGING.
      properties:
        rowsCollected:
          type: integer
        rowsExpected:
          type:
            - integer
            - 'null'
        bytesPackaged:
          type: integer
        lastHeartbeatAt:
          type:
            - string
            - 'null'
          format: date-time
        workerId:
          type:
            - string
            - 'null'
    DsarJobDelivery:
      type: object
      description: >-
        Delivery payload, present once the job is READY. In the sandbox
        `bundleUrl` is the auth-gated v1 download path; production swaps it for
        a real R2-presigned URL without changing the shape.
      properties:
        bundleR2Key:
          type: string
        bundleSizeBytes:
          type: integer
        bundleSha256:
          type: string
        bundleUrl:
          type: string
        expiresAt:
          type: string
          format: date-time
        downloadedAt:
          type:
            - string
            - 'null'
          format: date-time
        downloadedBy:
          type:
            - string
            - 'null'
    DsarJobFailure:
      type: object
      properties:
        code:
          type: string
          enum:
            - SOURCE_READ_FAILED
            - PACKAGE_WRITE_FAILED
            - STORAGE_QUOTA_EXCEEDED
            - WORKER_TIMEOUT
            - UNKNOWN
        message:
          type: string
        failedAt:
          type: string
          format: date-time
        workerId:
          type:
            - string
            - 'null'
    DsarJobTimelineEntry:
      type: object
      properties:
        at:
          type: string
          format: date-time
        actor:
          type: string
        fromState:
          $ref: '#/components/schemas/DsarJobState'
        toState:
          $ref: '#/components/schemas/DsarJobState'
        notes:
          type:
            - string
            - 'null'
    DsarJobScope:
      type: string
      description: >-
        `DATA_SUBJECT` = GDPR DSAR for one subject; `TENANT_FULL` =
        operator-initiated full-tenant backup; `TENANT_SLICE` =
        operator-initiated time-windowed slice.
      enum:
        - DATA_SUBJECT
        - TENANT_FULL
        - TENANT_SLICE
    ErrorCode:
      type: string
      description: Machine-readable error code. Drives the HTTP status.
      enum:
        - AUTH_REQUIRED
        - AUTH_INVALID
        - SCOPE_MISSING
        - BAD_REQUEST
        - VALIDATION_FAILED
        - RESOURCE_NOT_FOUND
        - STATE_CONFLICT
        - PRECONDITION_FAILED
        - RATE_LIMITED
        - INTERNAL_ERROR
  responses:
    Unauthorized:
      description: >-
        Missing/malformed Authorization header (AUTH_REQUIRED) or an invalid key
        (AUTH_INVALID).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
    Forbidden:
      description: >-
        The key is valid but missing one or more required scopes
        (SCOPE_MISSING).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
    NotFound:
      description: >-
        The referenced resource does not exist in this tenant
        (RESOURCE_NOT_FOUND).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
    StateConflict:
      description: >-
        The resource is in a state that forbids this transition, or a concurrent
        write lost (STATE_CONFLICT).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: 'API key sent as `Authorization: Bearer <api-key>`.'

````