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

# POST Cancel Subscription

> Cancels a subscription given its identifier. The operation is idempotent: if the subscription is already cancelled, the system returns the `ALREADY_CANCELLED` status.

Cancel an existing subscription. The operation is idempotent: if the subscription is already cancelled, the system returns the `ALREADY_CANCELLED` status without generating an error.

<RequestExample>
  ```bash theme={null}
  curl --request POST 'https://tumipay-card-payments.staging.topup.com.co/production/api/subscription/card/cancel' \
  --header 'Token-Top: your_auth_token' \
  --header 'Authorization: Basic your_auth_key' \
  --header 'X-Merchant-ID: your_merchant_id' \
  --header 'X-Request-ID: your-request-id' \
  --header 'Content-Type: application/json' \
  --data-raw '{
      "subscription_id": "sub_93af8f63-97d1-4be0-9e0d-f6fd8c2d92a0"
  }'
  ```
</RequestExample>

<ResponseExample>
  ```json Success - Subscription Cancelled (200) theme={null}
  {
      "code": "SUCCESS",
      "status": true,
      "message": "Suscripción cancelada exitosamente",
      "data": {
          "subscription_id": "550e8400-e29b-41d4-a716-446655440000",
          "cancellation_date": "2025-12-23T10:30:45.123Z"
      }
  }
  ```

  ```json Already Cancelled - Idempotency (200) theme={null}
  {
      "code": "ALREADY_CANCELLED",
      "status": true,
      "message": "La suscripción ya estaba cancelada",
      "data": {
          "subscription_id": "550e8400-e29b-41d4-a716-446655440000",
          "cancellation_date": "2025-12-23T10:30:45.123Z"
      }
  }
  ```

  ```json Validation Error (422) theme={null}
  {
      "code": "VALIDATION_ERROR",
      "status": false,
      "message": "subscription_id is required."
  }
  ```

  ```json Missing Required Header - X-Merchant-ID (400) theme={null}
  {
      "message": "Missing required header: X-Merchant-ID"
  }
  ```

  ```json Missing Required Header - X-Request-ID (400) theme={null}
  {
      "message": "Missing required header: X-Request-ID"
  }
  ```

  ```json Internal Authentication Failed (401) theme={null}
  {
      "code": "UNAUTHORIZED",
      "status": false,
      "message": "Unauthorized."
  }
  ```

  ```json Subscription Not Found (404) theme={null}
  {
      "code": "NOT_FOUND",
      "status": false,
      "message": "No se pudo localizar la suscripción solicitada con UUID: 550e8400-e29b-41d4-a716-446655440000"
  }
  ```

  ```json Cannot Cancel Subscription - Invalid State (409) theme={null}
  {
      "code": "INVALID_STATE",
      "status": false,
      "message": "Esta operación de suscripción no se puede realizar. Estado actual: FAILED"
  }
  ```

  ```json Service Error (500) theme={null}
  {
      "code": "SERVICE_ERROR",
      "status": false,
      "message": "Ocurrió un error inesperado"
  }
  ```
</ResponseExample>

## Required Headers

<ParamField header="Token-Top" type="string" required>
  Merchant authentication token
</ParamField>

<ParamField header="Authorization" type="string" required>
  Basic authentication (Basic Auth)
</ParamField>

<ParamField header="X-Merchant-ID" type="string" required>
  Unique identifier of the merchant invoking Card Payment services
</ParamField>

<ParamField header="X-Request-ID" type="string" required>
  Unique tracking identifier for the request
</ParamField>

<ParamField header="Content-Type" type="string" required>
  Must be "application/json"
</ParamField>

## Request Body Parameters

<ParamField body="subscription_id" type="string" required>
  Unique identifier of the subscription to cancel. This ID is obtained when creating the subscription.
</ParamField>

## Validation Rules

### Required Fields

| Field             | Type   | Rules            | Description                        |
| ----------------- | ------ | ---------------- | ---------------------------------- |
| `subscription_id` | string | required, max:36 | UUID of the subscription to cancel |

### Common Validation Error Messages

The following are common validation error messages returned by the API (in Spanish):

* `:attribute es obligatorio.` - Required field missing
* `:attribute debe ser una cadena de texto.` - Invalid data type (expected string)
* `:attribute no puede tener más de :max caracteres.` - Maximum length exceeded
* `:attribute no es válido.` - Invalid value

## Response Fields

### Success Response (200 OK)

<ResponseField name="code" type="string" required>
  Response code. Possible values:

  * `"SUCCESS"`: Subscription cancelled successfully
  * `"ALREADY_CANCELLED"`: The subscription was already cancelled (idempotent operation)
</ResponseField>

<ResponseField name="status" type="boolean" required>
  Operation status. `true` when successful (even if already cancelled)
</ResponseField>

<ResponseField name="message" type="string" required>
  Descriptive message about the cancellation result
</ResponseField>

<ResponseField name="data" type="object" required>
  <Expandable title="Cancellation data">
    <ResponseField name="subscription_id" type="string" format="uuid" required>
      Unique identifier of the cancelled subscription
    </ResponseField>

    <ResponseField name="cancellation_date" type="string" format="date-time" required>
      Cancellation date and time in ISO 8601 format with UTC timezone (format: `Y-m-d\TH:i:s.v\Z`)
    </ResponseField>
  </Expandable>
</ResponseField>

## HTTP Status Codes

| Status Code                 | Description                                                    | Response Body                                              |
| --------------------------- | -------------------------------------------------------------- | ---------------------------------------------------------- |
| `200 OK`                    | Successful operation (cancelled or already cancelled)          | `status: true`, `code: "SUCCESS"` or `"ALREADY_CANCELLED"` |
| `400 Bad Request`           | Missing required header (`X-Merchant-ID` or `X-Request-ID`)    | Simple error message                                       |
| `401 Unauthorized`          | Authentication failed (invalid `Token-Top` or `Authorization`) | `code: "UNAUTHORIZED"`                                     |
| `404 Not Found`             | Subscription not found                                         | `code: "NOT_FOUND"`                                        |
| `409 Conflict`              | Invalid state (subscription cannot be cancelled)               | `code: "INVALID_STATE"`                                    |
| `422 Unprocessable Entity`  | Validation error in request data                               | `code: "VALIDATION_ERROR"`                                 |
| `500 Internal Server Error` | Internal server error                                          | `code: "SERVICE_ERROR"`                                    |

## Response Codes

| Code                | Description                                                   |
| ------------------- | ------------------------------------------------------------- |
| `SUCCESS`           | Subscription cancelled successfully                           |
| `ALREADY_CANCELLED` | The subscription was already cancelled (idempotency)          |
| `VALIDATION_ERROR`  | Validation error in sent data                                 |
| `UNAUTHORIZED`      | Authentication error                                          |
| `NOT_FOUND`         | Subscription not found                                        |
| `INVALID_STATE`     | The subscription cannot be cancelled due to its current state |
| `SERVICE_ERROR`     | Internal server error                                         |


## OpenAPI

````yaml post /api/subscription/card/cancel
openapi: 3.0.0
info:
  title: Payment Platform - Card Payment API
  version: 1.0.0
  description: API for managing subscriptions with credit and debit cards.
  contact:
    url: https://docs.tumipay.co
    name: Payment Platform Card Payment
    email: it@tumipay.co
  license:
    name: Proprietary License
    url: https://tumipay.com/license
servers:
  - url: https://tumipay-card-payments.staging.topup.com.co/production
    description: Staging server
security: []
tags:
  - name: CardPayment
    description: Operations related to subscription creation, authorization, and capture.
paths:
  /api/subscription/card/cancel:
    post:
      tags:
        - CardPayment
      summary: Cancel subscription
      description: >-
        Cancels a subscription given its identifier. The operation is
        idempotent: if the subscription is already cancelled, the system returns
        the `ALREADY_CANCELLED` status.
      operationId: cancelSubscription
      parameters:
        - $ref: '#/components/parameters/MerchantId'
        - $ref: '#/components/parameters/RequestId'
        - $ref: '#/components/parameters/TokenTop'
        - $ref: '#/components/parameters/BasicAuth'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - subscription_id
              properties:
                subscription_id:
                  type: string
                  example: sub_93af8f63-97d1-4be0-9e0d-f6fd8c2d92a0
      responses:
        '200':
          description: >-
            Subscription cancelled successfully or was already cancelled
            (idempotency). Check 'code' field to distinguish between 'SUCCESS'
            and 'ALREADY_CANCELLED'.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CancelSubscriptionResponse'
              examples:
                success:
                  summary: Subscription cancelled successfully
                  value:
                    code: SUCCESS
                    status: true
                    message: Suscripción cancelada exitosamente
                    data:
                      subscription_id: 550e8400-e29b-41d4-a716-446655440000
                      cancellation_date: '2025-12-23T10:30:45.123Z'
                already_cancelled:
                  summary: Subscription was already cancelled (idempotency)
                  value:
                    code: ALREADY_CANCELLED
                    status: true
                    message: La suscripción ya estaba cancelada
                    data:
                      subscription_id: 550e8400-e29b-41d4-a716-446655440000
                      cancellation_date: '2025-12-23T10:30:45.123Z'
        '400':
          description: Missing required header (X-Merchant-ID or X-Request-ID).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Authentication failed (invalid Token-Top or Authorization).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Subscription not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: >-
            The subscription cannot be cancelled due to its current state. Only
            ACTIVE or PAUSED subscriptions can be cancelled. States that do not
            allow cancellation: FAILED, PENDING.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                invalid_state:
                  summary: Estado inválido para cancelación
                  value:
                    code: INVALID_STATE
                    status: false
                    message: >-
                      This subscription operation cannot be performed. Current
                      status: FAILED
        '422':
          description: Validation error in request data (e.g., missing subscription_id).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
components:
  parameters:
    MerchantId:
      name: X-Merchant-ID
      in: header
      required: true
      description: >-
        Unique identifier of the Merchant invoking Card Payment services. Should
        not be used to authenticate end users.
      schema:
        type: string
    RequestId:
      name: X-Request-ID
      in: header
      required: true
      description: >-
        Tracking identifier associated with the request, used to establish a
        correlation_id between ecosystem components.
      schema:
        type: string
    TokenTop:
      name: Token-Top
      in: header
      required: true
      description: Token for authentication.
      schema:
        type: string
    BasicAuth:
      name: Authorization
      in: header
      required: true
      description: Basic authentication.
      schema:
        type: string
  schemas:
    CancelSubscriptionResponse:
      type: object
      description: >-
        Response to the cancellation process. The 'status' field is always true
        (even for ALREADY_CANCELLED) due to idempotency.
      properties:
        code:
          type: string
          description: >-
            Response code. Values: 'SUCCESS' (cancelled successfully),
            'ALREADY_CANCELLED' (was already cancelled)
          enum:
            - SUCCESS
            - ALREADY_CANCELLED
          example: SUCCESS
        status:
          type: boolean
          description: >-
            Operation status. Always true for successful responses (even if
            already cancelled)
          example: true
        message:
          type: string
          description: Descriptive message about the cancellation result
          example: Suscripción cancelada exitosamente
        data:
          type: object
          properties:
            subscription_id:
              type: string
              format: uuid
              description: Unique identifier of the cancelled subscription
              example: 550e8400-e29b-41d4-a716-446655440000
            cancellation_date:
              type: string
              format: date-time
              description: >-
                Cancellation date and time in ISO 8601 format with UTC timezone
                (format: Y-m-d\TH:i:s.v\Z)
              example: '2025-12-23T10:30:45.123Z'
          required:
            - subscription_id
            - cancellation_date
      required:
        - code
        - status
        - message
        - data
    ErrorResponse:
      type: object
      description: >-
        Standard structure for error responses. For 400 errors (missing
        headers), it only contains 'message'.
      oneOf:
        - type: object
          properties:
            code:
              type: string
              description: >-
                Error code. Possible values: 'VALIDATION_ERROR', 'UNAUTHORIZED',
                'NOT_FOUND', 'ACCESS_DENIED', 'SUBSCRIPTION_CREATION_FAILED',
                'SERVICE_ERROR'
              example: VALIDATION_ERROR
            status:
              type: boolean
              description: Always false for error responses
              example: false
            message:
              type: string
              description: Descriptive error message
              example: The given data was invalid.
            details:
              type: object
              additionalProperties: true
              description: Additional error details (optional)
        - type: object
          properties:
            message:
              type: string
              description: Error message for missing headers
              example: 'Missing required header: X-Merchant-ID'
          required:
            - message

````