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

# endstate.tapIntents.cancel

> Cancels a pending tap intent and sends `tap_intent.canceled`; an approved tap intent cannot be canceled.

```ts theme={null}
cancel(tapIntentId: string, options?: IdempotentRequestOptions): Promise<TapIntent>
```

| | |
| - | - |
| Endpoint | [`POST /v1/tap-intents/{tap_intent_id}/cancel`](https://docs.endstate.io/api-reference/tap-intents/cancel-a-tap-intent) |
| Credential | Secret key (`end_sk_...`) |
| Retry class | `keyed` |
| Idempotency key | Accepted |

Carries an idempotency key. Retried on network failure, timeout, `429`, and `409 idempotency.in_progress` - never on a `5xx`.

## Example

```ts theme={null}
const result = await endstate.tapIntents.cancel("tapIntentId");
```

## Parameters

**tap\_intent\_id** `string` *required*

## Returns

`200` - `TapIntent`.

**id** `string` *required*

**status** `'pending' | 'approved' | 'consumed' | 'canceled' | 'expired'` *required*

`pending` until the person confirms. `approved` once they have: consume it by `use_by`. `consumed` once you have used the approval; it is used once. `canceled` ended without an approval. `expired` means nobody approved in time, or the approval was not consumed by `use_by`. `consumed` and `canceled` are final. Approving, canceling and consuming each send a webhook; expiring sends none.

**rule** `'own'` *required*

**unit\_id** `string` *required*

**action** `object` *required*

**redirect\_url** `string | null` *required*

**display** `object` *required*

**code\_required** `boolean` *required*

Whether the person must enter the code to confirm.

**scan** `object | null` *required*

The tap the intent was approved with. Null until it is approved.

**created\_at** `string` *required*

**expires\_at** `string` *required*

A tap must arrive by this time. The person can confirm for 10 minutes after their tap.

**approved\_at** `string | null` *required*

When the person approved. Kept on an approval that expired unused.

## Errors

Branch on `error.code`, never on the HTTP status - several codes share one.

| Code | HTTP | Retry |
| - | - | - |
| `auth.forbidden` | 403 | Do not retry |
| `auth.unauthorized` | 401 | Do not retry |
| `idempotency.in_progress` | 409 | Safe to retry |
| `idempotency.key_conflict` | 409 | Do not retry |
| `internal.error` | 500 | Safe to retry |
| `rate_limit.exceeded` | 429 | Safe to retry |
| `tap_intent.already_approved` | 409 | Do not retry |
| `tap_intent.already_consumed` | 409 | Do not retry |
| `tap_intent.busy` | 503 | Safe to retry |
| `tap_intent.expired` | 409 | Do not retry |
| `tap_intent.not_found` | 404 | Do not retry |
| `validation.failed` | 400 | Do not retry |

See [Errors and retries](https://docs.endstate.io/sdks/core/errors-and-retries.md) for the error types and how to narrow them.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.