---
updatedAt: 2026-08-13T15:08:37.000Z
agentTools:
  siteIndex: https://developers.pismo.io/llms.txt
  projectIndex: https://developers.pismo.io/pismo-docs/llms.txt
---

# Cancel BACS mandate [beta]

Cancel a BACS direct debit mandate.

Cancel of an existing mandate, applied asynchronously through the BACS scheme.

**Notes:**

  * The cancel is persisted with `status` = `CANCEL_PENDING` under the payer account, and enqueued for the asynchronous submission worker, which submits it to Form3 through the PSP gateway.

  * Allowed only when the mandate is in `SUBMITTED` or `CONFIRMED`; any other state is rejected with a **409 Conflict** (`EBACS0103`).

  * `version` is a Form3 optimistic-concurrency passthrough that must equal the stored version; a mismatch is rejected with a **409 Conflict** (`EBACS0104`). This call does not increment it.

  * The optional `status_reason` records why the mandate is being cancelled; it is persisted on the mandate and forwarded on the generated event.

  * This endpoint moves the mandate to `status` = `CANCEL_PENDING` and generates a [BACS mandate status changed](https://developers.pismo.io/events/docs/bacs-mandate-status-change-1) event. Subsequent status transitions generate further events (for example `CANCELLED`, `FAILED`).


# OpenAPI definition

```json
{
  "openapi": "3.1.0",
  "info": {
    "title": "Payment rails - BACS payments",
    "description": "BACS payments system API",
    "contact": {
      "name": "API Support",
      "url": "https://developers.pismo.io/support/"
    },
    "license": {
      "name": "Copyright Pismo"
    },
    "version": "1.0"
  },
  "servers": [
    {
      "url": "https://sandbox.pismolabs.io/bacs",
      "description": "Sandbox API server for testing."
    }
  ],
  "tags": [
    {
      "name": "BACS direct debit"
    }
  ],
  "components": {
    "parameters": {
      "authHeader": {
        "name": "Authorization",
        "in": "header",
        "schema": {
          "type": "string"
        },
        "description": "Account token - access token encoded with a Pismo account ID. Tokens can expire quickly, which can result in a <b>401 Unauthorized</b> message\n",
        "required": true
      },
      "mandateIdPath": {
        "name": "id",
        "in": "path",
        "description": "Mandate ID (the Form3-assigned ID returned at creation).",
        "required": true,
        "schema": {
          "type": "string",
          "maxLength": 36
        }
      }
    },
    "schemas": {
      "customer.DetailMessage": {
        "type": "object",
        "properties": {
          "external": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/customer.ExternalMessage"
            }
          },
          "parameters": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/customer.ParameterMessage"
            }
          },
          "payload": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/customer.PayloadMessage"
            }
          }
        }
      },
      "customer.Error": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "description": "Error's code.",
            "example": "EPT0001"
          },
          "details": {
            "$ref": "#/components/schemas/customer.DetailMessage"
          },
          "message": {
            "type": "string",
            "description": "Error's message.",
            "example": "User not found"
          }
        }
      },
      "customer.ExternalMessage": {
        "type": "object",
        "required": [
          "code",
          "message"
        ],
        "properties": {
          "code": {
            "type": "string",
            "description": "Code",
            "example": "PBE315"
          },
          "message": {
            "type": "string",
            "description": "Message",
            "example": "Generic error"
          }
        }
      },
      "customer.ParameterMessage": {
        "type": "object",
        "required": [
          "field",
          "message"
        ],
        "properties": {
          "field": {
            "type": "string",
            "description": "Field",
            "example": "Query parameter"
          },
          "message": {
            "type": "string",
            "description": "Message",
            "example": "Generic error"
          }
        }
      },
      "customer.PayloadMessage": {
        "type": "object",
        "required": [
          "field",
          "message"
        ],
        "properties": {
          "field": {
            "type": "string",
            "description": "Field",
            "example": "Entity.field"
          },
          "message": {
            "type": "string",
            "description": "Message",
            "example": "Generic error"
          }
        }
      },
      "mandateId": {
        "type": "string",
        "description": "Form3-assigned mandate ID",
        "example": "b254bb5e-6f1a-4c2b-9c1e-2f0a6d3e8c11"
      },
      "mandate.CancellationReason": {
        "type": "string",
        "description": "Reason code for the cancellation (mirrors Form3's mandate cancellation reasons). The client sends only the code; the human-readable description is derived server-side.\n  * `account_closed` - Account closed\n  * `account_transferred_to_new_psp` - Account transferred to a new PSP\n  * `cancelled_by_originator` - Cancelled by originator\n  * `cancelled_by_payer` - Cancelled by payer\n  * `payer_deceased` - Payer deceased\n  * `paying_bank_cancellation` - Paying bank cancellation\n",
        "enum": [
          "account_closed",
          "account_transferred_to_new_psp",
          "cancelled_by_originator",
          "cancelled_by_payer",
          "payer_deceased",
          "paying_bank_cancellation"
        ],
        "example": "account_closed"
      },
      "mandate.CancelRequest": {
        "type": "object",
        "description": "Payload to cancel an existing mandate. `version` is required for optimistic concurrency; `status_reason` optionally records why the mandate is being cancelled.",
        "required": [
          "version"
        ],
        "properties": {
          "version": {
            "type": "integer",
            "description": "Caller's expected current mandate version. A Form3 optimistic-concurrency passthrough that must match the stored version. This call does not increment this.",
            "example": 0
          },
          "status_reason": {
            "$ref": "#/components/schemas/mandate.CancellationReason"
          }
        }
      },
      "mandate.CancelResponse": {
        "type": "object",
        "description": "Returned by the cancel endpoint after the pending intent is persisted.",
        "properties": {
          "id": {
            "$ref": "#/components/schemas/mandateId"
          },
          "status": {
            "$ref": "#/components/schemas/mandate.CancelStatus"
          },
          "version": {
            "type": "integer",
            "description": "Mandate version. This call does not change it (Form3 passthrough — not incremented).",
            "example": 0
          }
        }
      },
      "mandate.CancelStatus": {
        "type": "string",
        "description": "Lifecycle status reachable when cancelling a mandate.\n  * `CANCEL_PENDING` - Cancel intent accepted; pending submission to Form3 via the PSP gateway\n  * `CANCELLED` - Mandate cancelled. Terminal state\n  * `FAILED` - Cancel processing failed. Terminal state\n",
        "enum": [
          "CANCEL_PENDING",
          "CANCELLED",
          "FAILED"
        ],
        "example": "CANCEL_PENDING"
      }
    }
  },
  "paths": {
    "/v1/payments/bacs/directdebit/mandates/{id}/cancel": {
      "post": {
        "summary": "Cancel BACS mandate [beta]",
        "description": "Cancel a BACS direct debit mandate.\n\nCancel of an existing mandate, applied asynchronously through the BACS scheme.\n\n**Notes:**\n\n  * The cancel is persisted with `status` = `CANCEL_PENDING` under the payer account, and enqueued for the asynchronous submission worker, which submits it to Form3 through the PSP gateway.\n\n  * Allowed only when the mandate is in `SUBMITTED` or `CONFIRMED`; any other state is rejected with a **409 Conflict** (`EBACS0103`).\n\n  * `version` is a Form3 optimistic-concurrency passthrough that must equal the stored version; a mismatch is rejected with a **409 Conflict** (`EBACS0104`). This call does not increment it.\n\n  * The optional `status_reason` records why the mandate is being cancelled; it is persisted on the mandate and forwarded on the generated event.\n\n  * This endpoint moves the mandate to `status` = `CANCEL_PENDING` and generates a [BACS mandate status changed](https://developers.pismo.io/events/docs/bacs-mandate-status-change-1) event. Subsequent status transitions generate further events (for example `CANCELLED`, `FAILED`).\n",
        "operationId": "post-cancel-mandate",
        "tags": [
          "BACS direct debit"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/authHeader"
          },
          {
            "$ref": "#/components/parameters/mandateIdPath"
          }
        ],
        "requestBody": {
          "description": "Cancel mandate request body",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/mandate.CancelRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "description": "Cancel intent accepted and enqueued",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/mandate.CancelResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/customer.Error"
                },
                "examples": {
                  "EBACS0004": {
                    "summary": "Validation Error",
                    "value": {
                      "code": "EBACS0004",
                      "message": "Validation error"
                    }
                  },
                  "EBACS0016": {
                    "summary": "Unmarshal Error",
                    "value": {
                      "code": "EBACS0016",
                      "message": "Unmarshal error"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/customer.Error"
                },
                "examples": {
                  "EBACS0002": {
                    "summary": "Missing Tenant Header",
                    "value": {
                      "code": "EBACS0002",
                      "message": "Missing required header: 'x-tenant'"
                    }
                  },
                  "EBACS0085": {
                    "summary": "Missing Account Id",
                    "value": {
                      "code": "EBACS0085",
                      "message": "Missing required account-id"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/customer.Error"
                },
                "examples": {
                  "EBACS0102": {
                    "summary": "Mandate Not Found",
                    "value": {
                      "code": "EBACS0102",
                      "message": "Mandate not found"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/customer.Error"
                },
                "examples": {
                  "EBACS0103": {
                    "summary": "Mandate Invalid State",
                    "value": {
                      "code": "EBACS0103",
                      "message": "Mandate cannot perform the requested operation in its current status"
                    }
                  },
                  "EBACS0104": {
                    "summary": "Mandate Version Conflict",
                    "value": {
                      "code": "EBACS0104",
                      "message": "Mandate version does not match the current version"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/customer.Error"
                },
                "examples": {
                  "EBACS0003": {
                    "summary": "Internal Error",
                    "value": {
                      "code": "EBACS0003",
                      "message": "Internal error"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
```