---
name: cas-tvan
description: "Integrate Cas TVAN (scopes: invoice): integration steps, the APIs to call and the pre-production checklist."
---

# Cas — TVAN

> Source: https://cas.so/en/product/tvan · Markdown: https://cas.so/en/product/tvan.md

_This skill is generated from the Cas documentation. When you need details (schemas, error codes, examples), fetch the latest Markdown from the links below instead of guessing._

## When to use this skill

When integrating, extending or debugging Cas **TVAN** in your system.

## Product summary

Send e-invoice messages to the TVAN system for processing and forwarding to the tax authority.

## Scopes

`invoice`

## Integration flow

Below are the steps to integrate TVAN into your product.
1. Create a grant [/grant/token](https://cas.so/en/general/api/grant/create.md) with `scopes` set to `invoice`.
  - **taxDeclaration** (optional): the e-invoice usage registration form details, used to pre-fill
  the X-Invoice registration form in Cas ID when the user registers. [See details](#tax-declaration-info)

2. Open the Cas Link interface using the `grantToken` returned in the previous step and select the X-Invoice service. [See details](https://cas.so/en/general/link.md)

3. After the user completes authentication, your frontend will receive a `publicToken`. Use this `publicToken` to obtain an `accessToken` for the grant.

4. You can now call the [Send Message API](https://cas.so/en/general/api/tvan-send.md).

#### Registration form details (`taxDeclaration`) {#tax-declaration-info}

`taxDeclaration` is an **optional** field when creating a grant, applicable to the X-Invoice service. If your system
already holds the customer's e-invoice usage registration details, pass them in so that Cas ID can pre-fill the
registration form (form 01/ĐKTĐ-HĐĐT), and the user does not have to re-enter them.

| Field | Type | Description |
| --- | --- | --- |
| `email` | string | Contact email |
| `registrationType` | number | Form type: `1` - New registration, `2` - Change of information |
| `invoiceType` | string[] | Invoice form: `WITH_TAX_AUTHORITY_CODE` - With tax authority code, `FROM_POS` - Invoice generated from a cash register |
| `invoiceUsageType` | string[] | Type of invoice used: `VAT` - Value-added tax invoice, `SALE` - Sales invoice |

:::note
For any field you do not pass, Cas ID uses the default value or leaves it blank for the user to fill in.
:::

## APIs used in this flow

- [Create grant token](https://cas.so/en/general/api/grant/create.md)
- [TVAN send message](https://cas.so/en/general/api/tvan-send.md)
- [Exchange public token for an access token](https://cas.so/en/general/api/grant/exchange.md)

## Read before writing code

- [Cas core](https://cas.so/en/skills/cas-core/SKILL.md)
- [Cas Link](https://cas.so/en/general/link.md)
- [Webhook](https://cas.so/en/general/api/webhook.md)
- [Errors](https://cas.so/en/errors.md)

## Rules you must follow when writing code

- `clientId` / `secretKey` live on the server in environment variables only — never ship them to a client, never commit them.
- Request only the `scopes` the product needs; extra scopes mean extra cost and risk.
- Avoid duplicate grants: check your database for a live grant before opening Cas Link again.
- Store `accessToken` and `grantId` encrypted and linked to your user; one user may hold several grants. Never surface these values in the UI.
- Log `requestId` (on every response) and `grantId` (on grant-related responses) for every call — this is what Cas support needs to trace an issue.
- Every API call needs a timeout and backoff retry for transient failures; never blindly retry money-moving calls (use your own idempotency key).
- Webhooks: accept them only from Cas IPs, return 2xx fast and process asynchronously, and make handling idempotent — deliveries can repeat or arrive out of order.
- Handle `GRANT_LOGIN_REQUIRED` by reopening Cas Link in Update mode instead of making the user relink from scratch.
- Handle `GRANT` webhooks: `USER_PERMISSION_REVOKED`, `GRANT_DELETED`, `GRANT_PAUSED`, `DEFAULT_UPDATE` — reflect the link state in your system.
- Call `/grant/remove` when a user unlinks in your app, and handle the OTP-verification branch.
- Run the whole flow on `https://sandbox.bankhub.dev` first; switch to `https://production.bankhub.dev` together with the production secrets.

## Before going to production

Verify against the **entire** production checklist: https://cas.so/en/launch-checklist.md

For every checklist item, point at the code (file path + line) that proves it is handled, or state why it does not apply. Never tick an item without evidence.

## Other Cas skills

Full catalogue (use it to add more Cas products later):

https://cas.so/en/skills/index.json
