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

# Cancel a bulk request

> Sets `cancellation_requested_at` so the running job exits cleanly to `cancelled` on its next heartbeat. Idempotent — re-cancelling just bumps the timestamp.



## OpenAPI

````yaml /openapi.json post /bulk_requests/{id}/cancel
openapi: 3.1.0
info:
  title: End Close API
  description: REST API is used to interact with the End Close platform.
  license:
    name: MIT
  version: 1.0.0
servers:
  - url: https://api.endclose.com/v1
security:
  - ApiKeyAuth: []
paths:
  /bulk_requests/{id}/cancel:
    post:
      summary: Cancel a bulk request
      description: >-
        Sets `cancellation_requested_at` so the running job exits cleanly to
        `cancelled` on its next heartbeat. Idempotent — re-cancelling just bumps
        the timestamp.
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
      responses:
        '202':
          description: Cancellation requested
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BulkRequest'
        '401':
          description: Unauthorized
        '404':
          description: Bulk request not found
        '409':
          description: >-
            Bulk request is not in a cancellable status (must be `pending` or
            `processing`)
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
components:
  schemas:
    BulkRequest:
      type: object
      description: >-
        Full bulk request payload, returned by show, list, cancel, and retry
        endpoints.
      properties:
        id:
          type: integer
        status:
          type: string
          enum:
            - pending
            - processing
            - completed
            - failed
            - cancelled
          description: >-
            pending = queued, processing = records being inserted, completed =
            all rows processed, failed = job errored, cancelled = cancellation
            honored on a heartbeat
        source:
          type: string
          nullable: true
          description: Origin of the request (e.g. `bulk_api`, `csv`, `nacha`)
        total_items:
          type: integer
        processed_items:
          type: integer
        successful_items:
          type: integer
        failed_items:
          type: integer
        skipped_items:
          type: integer
          description: >-
            Records skipped due to `on_conflict: skip` matching an existing
            `external_id`
        progress:
          type: integer
          description: processed_items / total_items as a percentage (0-100)
        filename:
          type: string
          nullable: true
          description: >-
            Original filename for CSV/NACHA uploads. Null for API-submitted
            requests.
        created_at:
          type: string
          format: date-time
        started_at:
          type: string
          format: date-time
          nullable: true
        completed_at:
          type: string
          format: date-time
          nullable: true
        last_progress_at:
          type: string
          format: date-time
          nullable: true
          description: Heartbeat timestamp from the worker; used to detect stuck jobs
        cancellation_requested_at:
          type: string
          format: date-time
          nullable: true
          description: >-
            Set by POST /bulk_requests/{id}/cancel; the worker exits at its next
            heartbeat
        parsing:
          type: boolean
          description: >-
            True while a CSV/NACHA upload is still being parsed (before rows are
            enqueued)
        stuck:
          type: boolean
          description: >-
            True if the request has been `processing` for more than 5 minutes
            without a heartbeat
        error_message:
          type: string
          nullable: true
        error_details:
          type: object
          additionalProperties: true
          description: >-
            Free-form structured error context (e.g. row indices, validation
            errors)
        parent_bulk_request_id:
          type: integer
          nullable: true
          description: >-
            If this request is a retry, the ID of the original (parent) bulk
            request
        on_conflict:
          type: string
          enum:
            - skip
            - error
          description: >-
            Conflict policy applied when an `external_id` already exists in the
            stream
        data_stream_id:
          type: integer
          nullable: true
          description: Data stream the request targets, when applicable
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-KEY

````