---
url: /guide/wallets/balances.md
description: >-
Retrieve the Balances of the Wallet. Balances include the funds currently
available in the Wallet, the pending operations amount, and the authorized
balance.
---
# Balances
The Balance object provides the amount available on a given Wallet. Each time the balance of the Wallet is updated as a result of a Payin, Payout, or Card Transaction, Treezor sends a [`balance.update`](./events#balance-update) webhook.
There are different kinds of Balances to consider:
* **Current Balance** – The amount of money currently available on the wallet without considering pending operations.
* **Authorizations** – Refers to the pending operations amount.
* **Authorized Balance** – The simulated balance, which amount takes into account pending operations (i.e., authorizations amount is deducted from the balance). This is usually the balance exposed to end users.
In other words, Current Balance = Authorized Balance + Authorizations
You can fetch the Balances value using the [`/v1/balances`](/api-reference/api-endpoints.html#tag/Balances/getBalances){target="\_self"} request.
Consider a current balance of €500.00 and an authorized payment of €100.00 (i.e., authorizations) that is not yet settled.
In this case, the values will be as follows:
* Current Balance – €500.00
* Authorized Balance – €400.00 (i.e., the balance minus the pending operation).
* Authorizations – €100.00
## Balance of a specific Wallet
This checks the current Balance of the [Wallet](introduction) (how much money there is), making sure the funds have arrived. Note that the `walletId` is expected as a query parameter.
Endpoint: [`/v1/balances`](/api-reference/api-endpoints.html#tag/Balances/getBalances){target="\_self"}
```bash [CURL]
curl -X GET '{baseUrl}/v1/balances?walletId={walletId}' \
--header 'Authorization: Bearer {accessToken}'
```
Returns the Balance object, with both the [Authorized Balance](/guide/wallets/balances) (`authorizedBalance`) and [Balance](/guide/wallets/balances) (`currentBalance`).
```json [JSON]
{
"balances": [
{
"walletId": 1317558,
"currentBalance": 280, // Actual Balance
"authorizations": 0, // Currently pending authorizations
"authorizedBalance": 280, // Balance, minus pending authorizations
"currency": "EUR", // Currency of the balance
"calculationDate": "2022-03-01 15:52:40" // When the Balance was last actualized
}
]
}
```
## Balances of all Wallets
You can retrieve the Balances of multiple Wallets related to the same [User](/guide/users/introduction). In this case, you provide a `userId` instead of a `walletId` in the query parameters.
Endpoint: [`/v1/balances`](/api-reference/api-endpoints.html#tag/Balances/getBalances){target="\_self"}
```bash [CURL]
curl -X GET '{baseUrl}/v1/balances?userId={userId}' \
--header 'Authorization: Bearer {accessToken}'
```
Returns the list of Balance of each Wallet belonging to the [User](/guide/users/introduction).
```json [JSON]
{
"balances": [
{
"walletId": 3645800,
"currentBalance": 4002.5,
"authorizations": 0,
"authorizedBalance": 4002.5,
"currency": "EUR",
"calculationDate": "2024-12-11 11:06:08"
},
{
"walletId": 3645801,
"currentBalance": 100,
"authorizations": 50,
"authorizedBalance": 50,
"currency": "EUR",
"calculationDate": "2024-12-11 11:06:08"
},
{
"walletId": 3645802,
"currentBalance": 302.5,
"authorizations": 0,
"authorizedBalance": 302.5,
"currency": "EUR",
"calculationDate": "2024-12-11 11:06:08"
}
]
}
```
## Check the balance history
This checks the evolution of the balance over time. Only the `walletId` is mandatory, it is expected in the URL. You can optionally restrict the search time frame using the `dateFrom` and `dateTo` parameters.
Endpoint: [`/core-connect/balances/{walletId}`](/api-reference/api-endpoints.html#tag/Balances/getWalletBalanceHistory){target="\_self"}
```bash [CURL]
curl -X GET '{baseUrl}/core-connect/balances/{walletId}?dateFrom=2021-11-01&dateTo=2022-10-01' \
--header 'Authorization: Bearer {accessToken}'
```
```json [JSON]
{
"2021-03-31T09:50:02+00:00": {
"solde": 51.25, // currentBalance
"authorizedBalance": 51.25,
"currency": "EUR"
},
"2021-02-04T13:20:02+00:00": {
"solde": 170.00, // currentBalance
"authorizedBalance": 170.00,
"currency": "EUR"
},
// [...] more items are hidden
}
```
**Caution – Date expected format is `YYYY-MM-DD`**
The time frame dates do not follow the [standard format](/guide/api-basics/data-format#dates) and are instead expected as `YYYY-MM-DD`.
---
---
url: /guide/overview/api-atlas.md
description: >-
Get an overview of the various Treezor API objects and their relationships
with an extensive flowchart. Each node links to the relevant section of the
documentation.
---
# API Atlas
The following diagram shows a general overview of the API, allowing you to **click any node to access the relevant documentation**.
```mermaid
flowchart LR
User
Wallet
Card
CardProgram
CardTransaction
CardTransactionExternalAuthorization[External Authorization]
CardTransactionRuleEngine[Rule Engine]
CardTransactionStrongCustomerAuthentication[Strong Customer Authentication]
CardTransactionAuthorization[Authorization]
CardTransactionRefund[Refund]
CardTransactionSettlement[Settlement]
CardTransactionReversal[Reversal]
CardTopUp[Top Up by Card]
CardRestrictions[Restrictions]
CardLimits[Limits]
CardOptions[Options]
CardStatus[Status]
CardGroupLimits[Group Limits]
CardPINCode[PIN Code]
CardRenew[Renewal]
SCTE
SCTERecall[SCTE Recall]
SCTEInst[SCTE Inst]
SCTEInstRecall[SCTE Inst Recall]
SDDE
SDDR
SCTR
SCTRRecall[SCTR Recall]
SCTRInst[SCTR Inst]
SCTRInstRecall[SCTR Inst Recall]
MassSCTE[Mass SCTE]
IntTransferR[Internal Transfer R]
Check
Beneficiary
Mandate
Transfer["Wallet-to-Wallet (P2P)"]
Document
KYC
KYCPreReview[Pre-Review]
KYCLiveness[Live verification]
ExternalAccount
%% Base relations
User --- Wallet
User --- Document
User -.- KYC
Document -.- KYC
KYC -.- KYCPreReview
KYC -.- KYCLiveness
%% Cards Relations
User --- Card
Wallet --- Card
Card --- CardTransaction
CardTransaction --- CardTransactionAuthorization
CardTransactionAuthorization -.- CardTransactionStrongCustomerAuthentication
CardTransactionAuthorization -.- CardTransactionExternalAuthorization
CardTransactionAuthorization -.- CardTransactionRuleEngine
CardTransaction --- CardTransactionRefund
CardTransaction --- CardTransactionSettlement
CardTransaction --- CardTransactionReversal
Wallet -- Payin --- CardTopUp
Card -.- CardRestrictions
Card -.- CardLimits
Card -.- CardOptions
Card -.- CardStatus
Card -.- CardGroupLimits
Card -.- CardPINCode
Card -.- CardRenew
Card --- CardProgram
%% SEPA Relations
Wallet -- Payout --- SCTE
Wallet -- Payin --- SCTR
Wallet -- Payout --- SCTEInst
Wallet -- Payin --- SCTRInst
Wallet -- Payin --- SDDE
Wallet -- Payout --- SDDR
Wallet -- Payout --- MassSCTE
Wallet -- Payin --- IntTransferR
SCTE --- Beneficiary
SDDR --- Beneficiary
SDDE --- Mandate
MassSCTE --- SCTE
Beneficiary -.- ExternalAccount
%% Check Relations
Wallet -- Payin --- Check
%% Transfers Relations
Wallet -- Transfer --- Transfer
%% Sepa Recalls relations
SCTE --- SCTERecall
SCTEInst --- SCTEInstRecall
SCTR --- SCTRRecall
SCTRInst --- SCTRInstRecall
%% Stuff that don't link to anything
%% StrongCustomerAuthentication
%% Webhook
%% Dashboard
%% Operations
%% Styling
class User MermaidUser
class Card MermaidCard
class Wallet MermaidWallet
class Beneficiary MermaidBeneficiary
class Mandate MermaidMandate
class KYC MermaidKYC
class CardTransactionExternalAuthorization MermaidNeutral
class CardTransactionRuleEngine MermaidNeutral
class CardTransactionStrongCustomerAuthentication MermaidNeutral
class ExternalAccount MermaidNeutralAlternate
class KYCPreReview MermaidNeutral
class KYCLiveness MermaidNeutral
%% Links
click KYCLiveness "/guide/user-verification/live-verification.html"
click KYCPreReview "/guide/user-verification/documents-prereview.html"
click User "/guide/users/introduction.html"
click Wallet "/guide/wallets/introduction.html"
click Card "/guide/cards/introduction.html"
click CardProgram "/guide/cards/introduction.html#card-program"
click CardTransaction "/guide/cards/transactions.html"
click CardTransactionExternalAuthorization "/guide/cards/transactions-external-validation.html"
click CardTransactionRuleEngine "/guide/cards/transactions-rules-engine.html"
click CardTransactionStrongCustomerAuthentication "/guide/cards/transactions-authentication.html"
click CardTransactionAuthorization "/guide/cards/transactions-lifecycle.html#authorization"
click CardTransactionRefund "/guide/cards/transactions-lifecycle.html#refunds"
click CardTransactionSettlement "/guide/cards/transactions-lifecycle.html#settlement"
click CardTransactionReversal "/guide/cards/transactions-lifecycle.html#reversal"
click CardTopUp "/guide/cards/acquisition.html"
click CardRestrictions "/guide/cards/restrictions-limits.html#mcc-restrictions"
click CardLimits "/guide/cards/restrictions-limits.html#payment-withdrawal-limits"
click CardOptions "/guide/cards/restrictions-limits.html#options-permission-groups"
click CardStatus "/guide/cards/introduction.html#card-status-statuscode"
click CardGroupLimits "/guide/cards/restrictions-limits.html#group-limits"
click CardPINCode "/guide/cards/modification.html#change-pin"
click CardRenew "/guide/cards/renewal.html"
click SCTE "/guide/transfers/credit-transfer.html#emitted-credit-transfers-scte"
click SCTR "/guide/transfers/credit-transfer.html#received-credit-transfers-sctr"
click SCTEInst "/guide/transfers/credit-transfer-inst.html#emitted-instant-credit-transfers-scte-inst"
click SCTRInst "/guide/transfers/credit-transfer-inst.html#received-instant-credit-transfers-sctr-inst"
click SDDE "/guide/transfers/direct-debit.html#emitted-direct-debits-sdde"
click SDDR "/guide/transfers/direct-debit.html#received-direct-debits-sddr"
click SCTRRecall "/guide/transfers/sepa-recalls.html#sctr-recalls"
click SCTRInstRecall "/guide/transfers/sepa-recalls.html#sctr-inst-recalls"
click MassSCTE "/guide/transfers/credit-transfer.html#mass-scte-mass-payout"
click SCTERecall "/guide/transfers/sepa-recalls.html#scte-recalls"
click SCTEInstRecall "/guide/transfers/sepa-recalls.html#scte-inst-recalls"
click Check "/guide/cheques/introduction.html"
click Beneficiary "/guide/transfers/beneficiaries.html"
click Mandate "/guide/transfers/mandates.html"
click Transfer "/guide/transfers/wallet-to-wallet.html"
click Document "/guide/user-verification/documents.html"
click KYC "/guide/user-verification/introduction.html"
```
---
---
url: /guide/api-basics/templates.md
description: >-
Implement API templates to customize Treezor API outputs. This guide details
Twig 3.x templating, including API calls to list, upload, test, access, and
delete templates, and how to manage variables and handle errors.
---
# Templates
Treezor uses the [Twig 3.x templating engine](https://twig.symfony.com/doc/3.x/). Like other files, [templates should be base64-encoded](/guide/api-basics/data-format#files).
## Twig Basics
A template is a file that contains **both structure (sometimes also styling) and instructions to inject content within**. Such as: "display this variable or something else if the variable is unavailable", "iterate on this array", etc.
**Information – Limitations of Treezor Twig implementation**
* Layouts and Blocks are unavailable
* Variables are limited to [those Treezor provides](#to-design-and-test-templates)
* CSS styling must be *inlined* (`my link` or within a `` in the page's `
`)
## Email templates
**Your Email templates must produce HTML; an additional template producing TXT is also required**. This TXT alternative is dedicated to clients that don't support HTML such as screen readers for the visually impaired.
### Example
```html
Confirm your account
Welcome, you are one step away from activating your account!
Validate my account
```
**Reading – More information on how to format templates**
* [Twig's official documentation](https://twig.symfony.com/doc/3.x/).
## Checking supported endpoints
Not all Treezor endpoints support templates. To check which endpoints can be templated, you can use the following request.
```bash [CURL]
curl -X GET '{baseUrl}/customization/templates' \
-H 'Authorization: Bearer {accessToken}' \
-H 'Content-Type: application/json'
```
Returns the list of customizable templates.
```json [JSON]
{
"templates":[
"email.user.onboarding_confirmation_html",
"email.user.onboarding_confirmation_text",
"wallet.address_details",
"wallet.balance_certificate",
"wallet.closure_certificate",
"wallet.confirmationLetter",
"wallet.domiciliation_certificate",
"wallet.statement",
"email.user.password_forgot_html",
"email.user.password_forgot_text",
"payout.proof_of_payout"
]
}
```
## Listing available variables
To retrieve the list of variables available within a template, you can use the following request.
```bash [CURL]
curl -X GET '{baseUrl}/customization/templates/{templateName}' \
-H 'Authorization: Bearer {accessToken}' \
-H 'Content-Type: application/json'
```
Returns the details about the template, including a list of accessible variables (`variables`).
```json [JSON]
{
"name": "payout.proof_of_payout",
"description": "Proof of Payout",
"mimeType": "text/html",
"variables": {
"wallet": {
"name": "wallet",
"type": "model",
"description": "Wallet model",
"children": [],
"parentName": null
},
"user": {
"name": "user",
"type": "model",
"description": "User model",
"children": [],
"parentName": null
},
"payout": {
"name": "payout",
"type": "model",
"description": "Payout model",
"children": [],
"parentName": null
},
"beneficiarie": {
"name": "beneficiarie",
"type": "model",
"description": "Beneficiary model",
"children": [],
"parentName": null
}
}
}
```
If you attempt to use a non-existent variable, an [error](#errors) is returned.
## Uploading a template
All templates must be uploaded to the following endpoint `{baseUrl}/customization/templates/{templateName}/template`, where the `endpointName` URL parameter corresponds to the endpoint to which you want to apply this template.
**Your base64-encoded template should not contain line breaks (`\n`)**
### Example
```bash [CURL]
curl -X PUT '{baseUrl}/customization/templates/{templateName}/template' \
-H 'Authorization: Bearer {accessToken}' \
-H 'Content-Type: application/json' \
-d '{
"template": "ewogInRvdG8iOiAiQSBtYWduaWZpY2VudCB0ZW1wbGF0ZSAhIiAsCiAiZm9vIjoiYmFyIgp9"
}'
```
**Caution – Replacing a Template:**
* Takes effect immediately.
* Cannot be undone.
## Testing a template
To test a template with dummy values, you can use the following request.
```bash [CURL]
curl -X GET '{baseUrl}/customization/templates/{templateName}/example' \
-H 'Authorization: Bearer {accessToken}' \
-H 'Content-Type: application/json'
```
Returns an object containing a populated version of your template in the `template` attribute.
```json [JSON]
{
"template": "PGh0bWw+Cjxib2R5Pgo8aDE+V2VsY29tZTwvaDE+CjxwPlBsZWFzZSA8Yj5jdXJyZW50IHVzZXIgPC9iPmNsaWNrIG9uIHRoZSBsaW5rIHRvIHZhbGlkYXRlIHlvdXIgYWNjb3VudDI6IDxhIGhyZWY9Imh0dHA6Ly9nb29nbGUuZnIiPmhlcmU8L2E+PC9wPgo8L2JvZHk+CjwvaHRtbD4="
}
```
## Accessing a template
To retrieve a template that you have already uploaded, you can use the following request.
```bash [CURL]
curl -X GET '{baseUrl}/customization/templates/{templateName}/template' \
-H 'Authorization: Bearer {accessToken}' \
-H 'Content-Type: application/json'
```
Returns an object containing your template in the `template` attribute.
```json [JSON]
{
"template": "ewogInRvdG8iOiAiUmVuZGVyIG5ldyB0ZW1wbGF0aW5nICEiIAp9"
}
```
## Deleting a template
If you want to remove a template altogether, you can use the following request. The endpoint will immediately revert the indicated template to Treezor's default template.
```bash [CURL]
curl -X DELETE '{baseUrl}/customization/templates/{templateName}' \
-H 'Authorization: Bearer {accessToken}'
```
## Using a template
To enable your template in a response, add the following header `X-TrzConnect-Custom-Template` with a value of `1`.
```bash [CURL]
curl -X GET '{baseUrl}/v1/users' \
-H 'Authorization: Bearer {accessToken}' \
-H 'Content-Type: application/json' \
-H 'X-TrzConnect-Custom-Template: 1' \ # <--- this header enables your template for this response only
# [...] parameters hidden for clarity
```
## Errors
If something goes wrong while uploading a template, you can expect an [Error object](/guide/api-basics/response-codes#error-attributes). Its `message` attribute will contain useful debugging details.
### Examples of errors
#### The twig template cannot be compiled
```json [JSON]
{
"errors": [
{
"type": "invalid_request",
"code": "input_validation_error",
"message": "Your template syntax is an invalid twig syntax : \"Unexpected character \"'\" in \"5eeb7991d1cd4\" at line 18.\"",
"docUrl": "https://developers.treezor.co"
}
]
}
```
#### A variable used is not available
```json [JSON]
{
"errors": [
{
"type": "invalid_request",
"code": "input_validation_error",
"message": "Your template is invalid : \"Variable \"my_variable\" does not exist in \"5eeb7a689e62c\" at line 12.\"",
"docUrl": "https://developers.treezor.co"
}
]
}
```
---
---
url: /guide/api-basics/authentication.md
description: >-
Master Treezor API authentication. This comprehensive guide covers essential
authentication methods, how to use your provided API credentials, and defining
scopes and permissions to control API access.
---
# Authentication
Treezor leverages the [OAuth2 framework](https://en.wikipedia.org/wiki/OAuth) and [JSON Web Token (JWT)](/guide/overview/glossary#json-web-token-jwt) which allows for a wide range of authentication flows. Treezor also relies on [Mutual TLS](mutual-tls) authentication as an additional security layer.
**Authenticating is a two-step process:**
1. [Obtaining your token](#obtaining-an-access-token-jwt) – Call the [`/oauth/token`](/api-reference/api-endpoints.html#tag/Authentication/postAuth){target="\_self"} endpoint to get a [JWT](/guide/overview/glossary#json-web-token-jwt).
2. [Using the token](#using-the-token) – For each subsequent request, include this JWT in an `Authorization` header.
## Credentials
Your credentials are highly sensitive information and are provided to you in an encrypted form.
Your `client_id` (integer) and `client_secret` (string) allow you to initiate the [authentication request](#obtaining-an-access-token-jwt), so you can send JWT-enabled requests to the Treezor Connect API. There is a dedicated set of credentials for each [environment](./environments).
If you are in need of credentials, please contact your *Treezor Account Manager*.
**Best practice – Safe storage recommendations**
* Use a `secureString` type in [AWS SSM services](https://docs.aws.amazon.com/en_en/systems-manager/latest/userguide/ssm-agent.html) *(or any robust Vault system)*
* Inject them in your application environment variables at the deployment phase.
## Obtaining an access token (JWT)
As part of your onboarding process, your *Treezor Account Manager* has provided you with your [credentials](#credentials) including `client_id` and `client_secret`.
**Security – Securely store your credentials; it is strictly forbidden to:**
* **Hard-code** them *(as a constant, etc.)*
* **Commit** them in a version control system *(i.e., configuration file)*
* **Store, display, or use** them on the client side *(mobile app, front end, etc.)*
If compromised, please contact Treezor immediately to revoke them.
Use the following request to get your JWT, using the relevant `{baseUrl}` and credentials depending on the [environment](./environments).
Endpoint: [`/oauth/token`](/api-reference/api-endpoints.html#tag/Authentication/postAuth){target="\_self"}
```bash [CURL]
curl -X POST '{baseUrl}/oauth/token' \
--form 'grant_type="client_credentials"' \ # required
--form 'client_id="{yourClientId}"' \ # required
--form 'client_secret="{yourClientSecret}"' # required
# --form 'scope="{scope}"' # optional, to specify scope
```
```php [PHP]
// composer require php-curl-class/php-curl-class
echo (new Curl\Curl)
->post('{baseUrl}/oauth/token', [
'grant_type' =>'client_credentials', // required
'client_id' =>'{yourClientId}', // required
'client_secret' =>'{yourClientSecret}', // required
// 'scope' =>'{scope}', // optional, to specify scope
])
->access_token;
```
```js [Node.JS]
const axios = require('axios');
async function authenticate() {
try {
const baseUrl = '{baseUrl}/'; // replace with your Treezor API base URL
const yourClientId = 'your_client_id'; // replace with your client id
const yourClientSecret = 'your_client_secret'; // replace with your client secret
const response = await axios.post(`${baseUrl}oauth/token`, {
grant_type: 'client_credentials',
client_id: yourClientId,
client_secret: yourClientSecret,
});
console.log('Authentication successful!');
console.log('Access token:', response.data.access_token);
} catch (error) {
if (!error.response) {
console.log('Error during network request');
} else {
console.log(`Authentication failed with error code ${error.response.status}`);
}
}
}
authenticate();
```
The following JSON object is returned if successful, your JWT being the `access_token`:
```json [JSON]
{
"token_type": "Bearer",
"expires_in": 3600,
"access_token": "{accessToken}",
"refresh_token": "{refreshToken}" // If refresh feature activated
}
```
You are now authenticated to the Treezor API. Keep your `access_token` at hand, since it will be used during the next steps.
**Note – The access token expires after 1 hour, so you need to:**
* Cache the token (avoiding unnecessary hits to the authentication endpoint)
* Renew or [refresh](#refreshing-the-token) the token before it expires (not applicable to all situations)
## Using the token
You can now use your JWT in the `Authorization` header to make your API calls as follows:
* `Bearer ` – The type of your token. Make sure to keep the capitalization and space.
* `{accessToken}` – The JSON Web Token, referred to as the `accessToken` in the documentation examples.
The following example illustrates how a typical request to the API is structured.
```bash [CURL]
curl -X GET '{baseUrl}/example/of/endpoint' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json'
```
```php [PHP]
// composer require php-curl-class/php-curl-class
use Curl\Curl;
$curl = (new Curl)
->setHeader('Authorization', 'Bearer {accessToken}');
echo $curl->get('{baseUrl}/example/of/endpoint');
```
## Refreshing the token
A token can be refreshed up to a month after the initial authentication. After a month, you will have to start the authentication process again.
**Availability – Refresh is limited to *password grant* and *authorization code* flows**
If the `grant_type` is `client_credentials`, you cannot refresh a token.
### Request
The following example asks for a refreshed token:
```bash [CURL]
curl -X POST '{baseUrl}/oauth/token' \
--form 'grant_type="refresh_token"' \ # required
--form 'client_id="{yourClientId}"' \ # required
--form 'scope="user admin"' \ # optional, can contain multiple scopes
--form 'refresh_token="{yourRefreshToken}"' # required, your previously issued refreshToken
```
### Response
```json [JSON]
{
"token_type": "Bearer",
"expires_in": 3600,
"access_token": "{accessToken}",
"refresh_token": "{accessTokenAllowingForJwtRefresh}"
}
```
You are now able to use the newly provided token.
**Tip – Open-source libraries may help abstract token management**
Treezor doesn't provide client libraries or SDKs to consume Treezor API, but some open-source tools are available to help you.
## Scopes & Permissions
A Scope is similar to a permission; depending on the scope, you may or may not be able to view and alter certain data.
Each [user](/guide/users/introduction) can have one or multiple scopes.
**All endpoints are scope-restricted, you need to use an appropriate scope to access an endpoint.**
### Available scopes
| Scope | Granted access |
|--- |--- |
| `read_only` | All **`GET`** endpoints (except `legal` and `admin`) |
| `read_write` | All **`PUT`**, **`POST`**, and **`DELETE`** endpoints (except `legal` and `admin`) |
| `admin` | **API Configuration** endpoints |
| `legal` | **[KYC](/guide/user-verification/introduction), [users](/guide/users/introduction) and [end user documents](/guide/user-verification/documents)** endpoints |
**Best practice – Align your Scopes with the default Roles**
The [Dashboard](/guide/dashboard/introduction#features) comes with a set of [Roles](/guide/dashboard/dashboard-users#dashboard-user-roles), which are a concatenation of the existing Scopes. Treezor advises you create Roles in the same way for specific developments.
### Scope selection
The scope selection happens when [you authenticate](/guide/api-basics/authentication), scopes get embedded in the JWT used for subsequent requests to the API.
During authentication, you have the choice to either:
* [A) Specify the desired scopes](#a-specify-the-desired-scopes)
* [B) Don't specify anything](#b-dont-specify-anything)
#### A) Specify the desired scopes
In this case, you are provided with the intersection of the **desired scopes** and the **user's available scopes**.
The requested scopes are expected in the `scope` request parameter. If more than one scope is requested, they should be space separated (e.g., `admin read_write`).
Consider the following **desired scopes** and **user scopes**.
```js
user_scopes = ['A', 'B', 'C'];
desired_scopes = ['A', 'B', 'D'];
```
The returned token will cover scopes that are present in both: user scopes **and** desired scopes
```js
returned_scopes = ['A', 'B'];
```
**Example**
```bash [CURL]
curl -X POST '{baseUrl}/oauth/token' \
--form 'grant_type="client_credentials"' \
--form 'client_id="{yourClientId}"' \
--form 'client_secret="{yourClientSecret}"' \
--form 'scope="admin"' # optional, for specific scope
```
#### B) Don't specify anything
In this case, you are provided with **all the user's scopes**.
Consider the following **user scopes** and **no desired scopes**.
```js
user_scopes = ['A', 'B', 'C'];
```
The returned token will cover **all the user's scopes.**
```js
returned_scopes = ['A', 'B', 'C'];
```
### Scopes behavior
When using end user-oriented scopes (`read_only` or `read_write` without other scopes), the API only returns information related to the authenticated user.
For the following requests made with the `read_only` scope, the API returns:
* `GET /wallets` – The wallets of the authenticated User (and their children's).
* `GET /documents` – The documents of the authenticated User (and their children's).
---
---
url: /guide/dashboard/beneficiaries.md
description: >-
Let your team provide support regarding your end users beneficiaries using the
Treezor Dashboard.
---
# Beneficiaries
Beneficiaries are bank accounts that are outside your Treezor ecosystem (as opposed to [Wallets](/guide/dashboard/wallets#wallets)). They are therefore the target of Payouts (SEPA Direct Debit and SEPA Credit Transfers).
## Accessing Beneficiaries
You may access beneficiaries information by:
* Taking advantage of the main [*Search field*](#search-field).
* Navigating the [*Beneficiaries*](#beneficiaries) view.
* Navigating the *User details* view, [*Beneficiaries*](#user-details-view-beneficiaries-tab) tab once a user is selected.
### Search field
The Dashboard main toolbar provides a search field, whose searchable attribute becomes dynamically available depending on what you enter.
Here are the attributes for you to search beneficiaries: `beneficiaryId`, `iban`, and `name`.
After validating your search for a given beneficiary, the [*Beneficiaries*](#beneficiaries) view is displayed, filtered on the corresponding Beneficiary for you to select.
### Beneficiaries view
The *Beneficiaries* view provides the list of all the beneficiaries by type. Up to 2 tabs can be available depending on your model:
* **SEPA Credit Transfer** – Bank accounts to which to make an [SCTE payout](/guide/transfers/credit-transfer#emitted-credit-transfers-scte).
* **SEPA Direct Debit** – Bank accounts from which to make an [SDDR payout](/guide/transfers/direct-debit#received-direct-debits-sddr).
The Search field allows you to search beneficiaries by `beneficiaryId`, `iban`, `bic` or by `name`.
Clicking on arrow icon for a beneficiary switches the view to the [*Beneficiaries*](#user-details-view-beneficiaries-tab) tab of the corresponding *User details* view, filtered on the selected Beneficiary.
### User details view, Beneficiaries tab
The view is broken down into 2 sub-tabs:
* **[SEPA Credit Transfer](#sepa-credit-transfer-sub-tab)** – Bank accounts to which to make an [SCTE payout](/guide/transfers/credit-transfer#emitted-credit-transfers-scte).
* **[SEPA Direct Debit](#sepa-direct-debit-sub-tab)** – Bank accounts from which to make an [SDDR payout](/guide/transfers/direct-debit#received-direct-debits-sddr).
## Navigating the Beneficiaries information
### SEPA Credit Transfer sub-tab
The *SEPA Credit Transfer* tab displays all the bank accounts to which funds can be sent with a SEPA Credit Transfer. This operation is referred to as an [SCTE payout](/guide/transfers/credit-transfer#emitted-credit-transfers-scte) and can be made from the [Dashboard](transfers#transfers-from-wallet-to-external-bank-account).
You can initiate such Payouts in the Dashboard from the *Wallets* tab.
The following commands are available:
| | Action | Description |
| :---: | --- | --- |
| | **Edit** | Displays the *Edit Beneficiary* popup. |
| | **View** | Displays the *Beneficiary details* popup. |
### SEPA Direct Debit sub-tab
The *SEPA Direct Debit* tab displays all the bank accounts from which Wallets can be debited, using a SEPA Direct Debit. This operation is referred to as an [SDDR payout](/guide/transfers/direct-debit#received-direct-debits-sddr).
Beneficiaries for SDD are created differently depending on the type of SDD.
| Created | Context | Description |
| --- | --- | --- |
| **Automatically** | **B2C** (Core) | This occurs when debiting a Wallet using a SEPA Direct Debit (SDDR). |
| **Manually** | **B2B** | This is a prerequisite before the SDDR in B2B context. Indeed, the unique mandate reference is necessary for the reception of a SEPA Direct Debit. |
The following commands are available:
| | Action | Description |
| :---: | --- | --- |
| | **Edit** | Displays the *Edit Beneficiary* popup. |
| | **View** | Displays the *Beneficiary details* popup. |
## Creating Beneficiaries
To create a new Beneficiary, click on the "Create Beneficiary" button located in the upper right-corner of the *Beneficiaries* tab.
The *Add Beneficiary* popup is displayed and provides different fields to fill in depending on the kind of beneficiary you wish to create (SEPA Credit Transfer, SEPA Direct Credit, or B2B SEPA Direct Debit).
In the specific case of B2B SEPA Direct Debit, you need to fill in information about the Mandate for the SDDR to be processed.
* **Mandate reference** – The [Unique Mandate Reference (UMR)](/guide/overview/glossary#unique-mandate-reference-umr).
* **Recurrent** – Toggle the option if the mandate is a recurring payment.
* **Wallet ID** – When specified, the SDD will only be accepted if the targeted wallet is the indicated one.
---
---
url: /guide/acquiring/preauthorized.md
description: >-
Technical guide for capturing a preauthorized amount from a tokenized
third-party card. Includes required parameters, request structure, and
response examples.
---
# Advanced capture
This approach is often useful when the amount to capture is not accurately known at the time the authorization is issued.
In such situations, you:
1. **Authorize an amount** to capture within 7 days.
2. **Create one or more payins** against that authorization without exceeding the total authorized amount.
Any remaining funds are automatically freed up after 7 days.
This feature is only available with some [paymentProducts](/guide/acquiring/introduction#payment-products-specificities).
**Prerequisites – Steps to complete before the authorization:**
* [Tokenize the card](/guide/acquiring/card-tokenization)
* [Create a Topup Card](/guide/acquiring/card-tokenization#associate-the-card-to-a-user) to associate with the user (if needed)
## Authorize an amount
To authorize an amount, use the following endpoint, which accepts the same payload as the [direct capture](./direct-capture).
```bash [CURL]
curl -X POST '{baseUrl}/v1/topups/cards/authorizations' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is a `{payload}` example:
```json [JSON]
{
"amount": 20,
"currency": "EUR",
"walletId": "{walletId}",
"userId": "{userId}",
"paymentProduct": "visa",
"topupCardId": "{topupCardId}",
"messageToUser": "string",
"acceptUrl": "acceptURL",
"declineUrl": "declineURL",
"pendingUrl": "pendingURL",
"exceptionUrl": "exceptionURL",
"cancelUrl": "cancelURL",
"eci": "9",
"authenticationIndicator": "2",
"orderId": "{order_Id}", // According to best practices
"description": "string",
"deviceChannel": 0,
"browserInfo": {
"javaEnabled": true,
"javascriptEnabled": true,
"ipaddr": "0.0.0.0",
"httpAccept": "string",
"httpUserAgent": "string",
"language": "string",
"colorDepth": 8, // Can be: 1, 4, 8, 15, 16, 32, 48
"screenHeight": 0,
"screenWidth": 0,
"timezone": "string",
"deviceFingerprint": "string"
},
"firstname": "Alex",
"lastname": "Oak",
"email": "aoak@example.com",
"phone": "string",
"streetAddress": "string",
"city": "string",
"zipCode": "string",
"country": "string",
"cardHolder": "A Oak"
}
```
Returns the Authorization and sends an [`authorization.create`](./events#authorization-create) webhook which contains the authorization UUID necessary to create payin(s) in the next step.
```json [JSON]
{
"authorizations": [
{
"authorizationId": "6de434ff-d2c5-511f-820c-6748385f2b42",
"userId": "100655503",
"walletId": "3152544",
"userFirstname": "Alex",
"walletEventName": "Main Account",
"walletAlias": "main-account-669f5b8e1e9cf",
"userLastname": "Oak",
"messageToUser": "The financial institution has approved the payment.",
"authorizationStatus": "PENDING",
"paymentMethodId": "25",
"amount": 20,
"currency": "EUR",
"createdDate": "",
"codeStatus": "150116",
"informationStatus": "Authorized",
"refundAmount": 0,
"profile": "00001342501",
"DbtrIBAN": null,
"clientId": "998423",
"createdIp": "0.0.0.0",
"authorizationTag": "",
"cartId": 0,
"subtotalItems": "0.00",
"subtotalServices": "0.00",
"subtotalTax": "0.00",
"distributorFee": null,
"paymentHtml": null,
"paymentLanguage": null,
"paymentPostUrl": null,
"paymentPostDataUrl": null,
"paymentAcceptedUrl": null,
"paymentWaitingUrl": null,
"paymentCanceledUrl": null,
"paymentRefusedUrl": null,
"paymentExceptionUrl": null,
"ibanFullname": null,
"ibanId": null,
"ibanBic": null,
"ibanTxEndToEndId": null,
"ibanTxId": null,
"forwardUrl": "",
"authorizationDate": "0000-00-00",
"mandateId": "0",
"creditorName": null,
"creditorAddressLine": null,
"creditorCountry": null,
"creditorIban": null,
"creditorBIC": null,
"virtualIbanId": null,
"virtualIbanReference": null,
"additionalData": "{\"card\":{\"externalProvider\":{\"state\":\"completed\",\"reason\":\"\",\"forwardUrl\":\"\",\"test\":\"true\",\"mid\":\"00001342501\",\"attemptId\":\"1\",\"authorizationCode\":\"no_code\",\"transactionReference\":\"800312407023\",\"dateCreated\":\"2024-07-23T07:30:10+0000\",\"dateUpdated\":\"2024-07-23T07:30:14+0000\",\"dateAuthorized\":\"2024-07-23T07:30:14+0000\",\"status\":\"116\",\"message\":\"Authorized\",\"authorizedAmount\":\"10.00\",\"capturedAmount\":\"0.00\",\"refundedAmount\":\"0.00\",\"creditedAmount\":\"0.00\",\"decimals\":\"2\",\"currency\":\"EUR\",\"ipAddress\":\"0.0.0.0\",\"ipCountry\":\"\",\"deviceId\":\"\",\"cdata1\":\"998423\",\"cdata2\":\"3152544\",\"cdata3\":\"100655503\",\"cdata4\":\"\",\"cdata5\":\"\",\"cdata6\":\"\",\"cdata7\":\"\",\"cdata8\":\"\",\"cdata9\":\"\",\"cdata10\":\"\",\"avsResult\":\"\",\"eci\":\"9\",\"paymentProduct\":\"visa\",\"paymentMethod\":{\"token\":\"f1bed3b91285747c2e5d332a41580e710b726880e4149fb999f271618b8d03c3\",\"cardId\":\"9fd81707-8f41-4a01-b6ed-279954336ada\",\"brand\":\"VISA\",\"pan\":\"411111******1111\",\"cardHolder\":\"M FRAY\",\"cardExpiryMonth\":\"08\",\"cardExpiryYear\":\"2029\",\"issuer\":\"CONOTOXIA SP. Z O.O\",\"country\":\"PL\"},\"threeDSecure\":\"\",\"fraudScreening\":{\"scoring\":\"0\",\"result\":\"NOT_LAUNCHED\",\"review\":\"\"},\"order\":{\"id\":\"order_1234567890\",\"dateCreated\":\"2024-07-23T07:30:10+0000\",\"attempts\":\"1\",\"amount\":\"10.00\",\"shipping\":\"0.00\",\"tax\":\"0.00\",\"decimals\":\"2\",\"currency\":\"EUR\",\"customerId\":\"\",\"language\":\"en_US\",\"email\":\"\"},\"debitAgreement\":{\"id\":\"11209240\",\"status\":\"available\"}}}}"
}
]
}
```
## Capture the funds
To capture funds after an authorization, use the following request.
```bash [CURL]
curl -X POST '{baseUrl}/v1/topups/cards/authorizations/{authorizationId}/payins' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"amount": 10,
"currency": "EUR"
}
```
Returns the Payin and sends [`payin.create`](./events#payin-create) and [`payin.update`](/guide/acquiring/events#payin-update) webhooks.
```json [JSON]
{
"payins": [
{
"payinId": "89f82b27-be27-527c-9b93-eab65fb7a0e4",
"userId": "100655503",
"walletId": "3152544",
"userFirstname": "John",
"walletEventName": "Event_test",
"walletAlias": "event-test-669f5b8e1e9cf",
"userLastname": "Smith",
"messageToUser": "The financial institution has processed the payment.",
"payinStatus": "VALIDATED",
"paymentMethodId": "25",
"amount": 10,
"currency": "EUR",
"createdDate": "",
"codeStatus": "150118",
"informationStatus": "Captured",
"refundAmount": 0,
"profile": "00001342501",
"DbtrIBAN": null,
"createdIp": "0.0.0.0",
"payinTag": "",
"cartId": 0,
"subtotalItems": "0.00",
"subtotalServices": "0.00",
"subtotalTax": "0.00",
"distributorFee": null,
"paymentHtml": null,
"paymentLanguage": null,
"paymentPostUrl": null,
"paymentPostDataUrl": null,
"paymentAcceptedUrl": null,
"paymentWaitingUrl": null,
"paymentCanceledUrl": null,
"paymentRefusedUrl": null,
"paymentExceptionUrl": null,
"ibanFullname": null,
"ibanId": null,
"ibanBic": null,
"ibanTxEndToEndId": null,
"ibanTxId": null,
"forwardUrl": null,
"payinDate": "0000-00-00",
"mandateId": "0",
"creditorName": null,
"creditorAddressLine": null,
"creditorCountry": null,
"creditorIban": null,
"creditorBIC": null,
"virtualIbanId": null,
"virtualIbanReference": null,
"additionalData": "{\"card\":{\"externalProvider\":{\"operation\":\"capture\",\"test\":\"true\",\"mid\":\"00001342501\",\"authorizationCode\":\"no_code\",\"transactionReference\":\"800312407520\",\"dateCreated\":\"2024-07-23T08:59:40+0000\",\"dateUpdated\":\"2024-07-23T09:06:49+0000\",\"dateAuthorized\":\"2024-07-23T08:59:44+0000\",\"status\":\"118\",\"message\":\"Captured\",\"authorizedAmount\":\"10.00\",\"capturedAmount\":\"10.00\",\"refundedAmount\":\"0.00\",\"decimals\":\"2\",\"currency\":\"EUR\"}}}"
}
]
}
```
**Note – You can create several captures for an authorization if both:**
* The total amount doesn't exceed the initial authorization amount.
* The capture occurs within 7 days of the authorization.
---
---
url: /guide/acquiring/direct-capture.md
description: >-
Technical guide for capturing funds from a tokenized third-party card
directly, without going through the authorization step first. Includes
required parameters, request structure, and response examples.
---
# Direct capture
You can request a capture of funds using either the Topup Card or an alternate means of payment (specified in the `paymentProduct` parameter). This doesn't require an authorization first.
**Prerequisites – Steps to complete before the capture:**
* [Tokenize the card](/guide/acquiring/card-tokenization)
* [Create a Topup Card](/guide/acquiring/card-tokenization#associate-the-card-to-a-user) to associate with the user (if needed)
You can then use the usual [`/v1/payins`](/api-reference/api-endpoints.html#tag/Payins/postPayin){target="\_self"} request with attributes specific to the Card Acquiring feature as described in this article.
## Parameters
| Attribute | Type | Description |
| --- | --- | --- |
| `walletId` | string | The unique identifier of the Wallet to be credited. |
| `userId` | string | The unique identifier of the User requesting the topup. |
| `topupCardId` | string | The unique identifier of the Topup Card, if any. |
| `profile` | string | Your HiPay Merchant ID. Required if you have multiple MIDs, otherwise empty. |
| `orderId` | string | The unique identifier of the order, ensuring the uniqueness of the transaction. Must be unique (so different from tokenization) and abide by the following rules: Length: min. 32 charactersStructure: `_order_` |
| `amount` | number | The amount of the operation. |
| `currency` | string | Currency of the operation. Format: [ISO-4217](/guide/api-basics/data-format). |
| `acceptUrl` | string | The URL to which the user is returned when the payment process is successfully completed. |
| `declineUrl` | string | The URL to which the user is returned when the acquirer declines the payment. |
| `pendingUrl` | string | The URL to which the user is returned when the payment request was submitted to the acquirer, but the response is not available yet. |
| `exceptionUrl` | string | The URL to which the user is returned when there is an error or a system failure. |
| `cancelUrl` | string | The URL to which the user is returned when the payment is canceled. |
| `eci` | string | The security level at which the payment information is processed. `7` – **One-time** payment (allowing for 3DS)`9` – **Recurring** payments (following an `eci=7`) Any capture made with `9` must have a previous successful authorization or transaction with an `eci` valued to `7` that enforced 3DS. |
| `authenticationIndicator` | string | Whether 3DS should be performed for the transaction. Set the value to `2` for 3DS. |
| `description` | string | The description of the operation. |
| `paymentProduct` | string | Can be: `cb`, `visa`, `mastercard`, `ideal`, `sofort-uberweisung`. |
| `issuerBankId` | string | The Bank Identifier Code of the end user's issuing bank. Only used if the `paymentProduct` is `ideal`. |
| `ipaddr` | string | The IP address of the end user's device. |
| `browserInfo` | object | Object containing information regarding the end user's browser. |
| `firstname` | string | The first name of the user. |
| `lastname` | string | The last name of the user. |
| `email` | string | The email of the user. |
| `phone` | string | The phone number of the user. |
| `streetAddress` | string | The residence street name and number of the user. |
| `city` | string | The residence city of the user. |
| `zipCode` | string | The residence city zipcode of the user. |
| `country` | string | The residence country of the user. Format: ISO 3166 alpha-2 |
| `cardHolder` | string | The name associated to the card. |
| `deviceChannel` | integer | The PSD2 Channel through which the transaction is being processed. |
## Request
Here is an example of `{payload}`:
```json [JSON]
{
"amount": 10,
"currency": "EUR",
"walletId": "3152544",
"userId": "100655503",
"paymentProduct": "visa",
"topupCardId": "3252046c-6138-44f1-a24d-8807974c7ec3",
"messageToUser": "string",
"acceptUrl": "acceptURL",
"declineUrl": "declineURL",
"pendingUrl": "pendingURL",
"exceptionUrl": "exceptionURL",
"cancelUrl": "cancelURL",
"eci": "9",
"authenticationIndicator": "2",
"orderId": "order_test_1234567878911",
"description": "string",
"deviceChannel": 0,
"browserInfo": {
"javaEnabled": true,
"javascriptEnabled": true,
"ipaddr": "0.0.0.0",
"httpAccept": "string",
"httpUserAgent": "string",
"language": "string",
"colorDepth": 8, // Can be: 1, 4, 8, 15, 16, 32, 48
"screenHeight": 0,
"screenWidth": 0,
"timezone": "string",
"deviceFingerprint": "string"
},
"firstname": "Alex",
"lastname": "Oak",
"email": "aoak@example.com",
"phone": "string",
"streetAddress": "string",
"city": "string",
"zipCode": "string",
"country": "string",
"cardHolder": "A Oak"
}
```
Returns the following object and sends the [`authorization.create`](./events#authorization-create), [`payin.create`](./events#payin-create), and [`payin.udpate`](./events#payin-update) webhooks.
```json [JSON]
{
"state": "completed",
"reason": "",
"forwardUrl": "", // Redirect the user to this URL if populated
"test": "true",
"mid": "00001340255",
"attemptId": "1",
"authorizationCode": "test123",
"transactionReference": "800150032845",
"referenceToPay": "",
"dateCreated": "2022-01-26T13:45:11+0000",
"dateUpdated": "2022-01-26T13:45:17+0000",
"dateAuthorized": "2022-01-26T13:45:17+0000",
"status": "118",
"message": "Captured",
"authorizedAmount": "40.99",
"capturedAmount": "40.99",
"refundedAmount": "0.00",
"creditedAmount": "0.00",
"decimals": "2",
"currency": "EUR",
"ipAddress": "0.0.0.0",
"ipCountry": "",
"deviceId": "",
"cdata1": "212707",
"cdata2": "878744",
"cdata3": "1656177",
"cdata4": "",
"cdata5": "",
"cdata6": "",
"cdata7": "",
"cdata8": "",
"cdata9": "",
"cdata10": "",
"avsResult": "",
"eci": "9",
"paymentProduct": "visa",
"paymentMethod": {
"token": "48d8ad7f642bff96387b14f0b060ad6a6194e91debc30aa0b31bdcd5a0a6680a",
"cardId": "9fd81707-8f41-4a01-b6ed-279954336ada",
"brand": "VISA",
"pan": "411111******1111",
"cardHolder": "TOM PES",
"cardExpiryMonth": "12",
"cardExpiryYear": "2025",
"issuer": "JPMORGAN CHASE BANK, N.A.",
"country": "US"
},
"threeDSecure": "",
"fraudScreening": {
"scoring": "0",
"result": "NOT_LAUNCHED",
"review": ""
},
"order": {
"id": "order_test1643204709",
"dateCreated": "2022-01-26T13:45:11+0000",
"attempts": "1",
"amount": "40.00",
"shipping": "0.00",
"tax": "0.00",
"decimals": "2",
"currency": "EUR",
"customerId": "",
"language": "en_US",
"email": ""
},
"debitAgreement": {
"id": "10347296",
"status": "available"
}
}
```
**To know the actual payment status, please see the Payin `status` attribute of the `authorization.create`, [`payin.create`](./events#payin-create) and `payin.update` webhooks**.
## Forwarding
If the `forwardUrl` attribute is populated in the response, you must redirect the end user to this URL for them to complete the funds capture process. See the list of [payment products](/guide/acquiring/introduction#payment-products-specificities) to know when redirection is necessary.
When a forwarding occurs, Treezor won't send any webhook until the end user has completed the steps available at the `forwardUrl`.
## Payin status (`codeStatus`)
Below the list of payin `codeStatus` values specific to the Card Acquiring feature.
| `codeStatus` | Description |
|--- |--- |
| `150109` | Authentication Failed |
| `150110` | Blocked |
| `150111` | Denied |
| `150112` | Authorized and Pending |
| `150113` | Refused |
| `150114` | Expired |
| `150115` | Canceled |
| `150116` | Authorized |
| `150117` | Capture Requested |
| `150118` | Captured |
| `150119` | Partially Captured |
| `150126` | Partially Refunded |
| `150142` | Authorization Requested |
| `150143` | Authorization Cancelled |
| `151116` | Authorized - Direct Validation at Authorization |
| `151117` | Capture Requested - Direct Validation at Authorization |
| `151118` | Captured - Direct Validation at Authorization |
---
---
url: /guide/acquiring/errors.md
description: >-
Troubleshoot and handle card acquiring-related issues using the Treezor API's
complete list of error codes, messages, and their corresponding meanings.
---
# Errors
**Caution – Only the legacy API sends the error code in HTTP errors**
When handling errors with Connect, only the `message` attribute is returned.
## Refunds
| Code | Type | `message` |
|---------|---------------------|-----------------------------------------------------------------------------------|
| 0001 | missingFieldError | `This field is missing. : [user]` |
| 0002 | invalidRequestError | `This payin is not refundable: payin not validated` |
| 0002 | invalidRequestError | `This payin is not refundable: balance not impacted yet` |
| 0002 | invalidRequestError | `This payin is not refundable` |
| 0002 | invalidRequestError | `Requested refund is higher than the remaining refundable amount for this payin` |
| 0002 | invalidRequestError | `A refund for a payin in this transaction is ongoing. Please retry in few minutes.` |
| 0002 | invalidRequestError | `Wallet not found` |
| 0002 | invalidRequestError | `Wallet is not validated` |
| 0002 | invalidRequestError | `User not found` |
| 0002 | invalidRequestError | `User is frozen` |
| 0002 | invalidRequestError | `User is not in valid status (8)` |
| 0003 | internalServerError | `Internal server error` |
| 0005 | notFoundError | `Payin not found` |
| 0005 | notFoundError | `Wallet not found` |
| 00010 | unauthorizedError | `Access to this payin is forbidden for the provided clientId` |
| {anyHipayErrorCode} | hipayError | `Amount Limit Exceeded` |
---
---
url: /guide/acquiring/legacy-v1.md
description: >-
A quick guide to the first version of Treezor Card Acquiring feature to help
you migrate to the enhanced and optimized card top-ups.
---
# Legacy flow
This article focuses on the first version of the Acquiring feature provided by Treezor. It doesn't offer as many features as the newest services. If you have any doubt, don't hesitate to contact Treezor.
Payments received using HiPay's API create **Payin** objects with a `paymentMethodId` attribute set to `25` and send [`payin.create`](events#payin-create) webhooks.
**Feature activation – Contact Treezor to activate the supported cards**
The Card Acquiring V1 feature supports the following cards: CB, Visa, Mastercard, and Maestro.
**Best practice – Store Payin Ids as 36-character-long strings**
It will facilitate your migration to acquiring v2, in which Ids are [UUIDv4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_\(random\)).
## Step 1, Tokenize the card
Tokenization is the process of converting the [PAN](/guide/overview/glossary#pan-primary-account-number), expiration date and [CVC](/guide/overview/glossary#cvc-card-verification-number) of a card into a token.
The tokenization request must be sent from the end user's device (for example using Javascript), as the [PAN](/guide/overview/glossary#pan-primary-account-number) cannot transit or be stored on your servers.
You may generate the token either:
* **If you're not PCI DSS certified** – Generate the token [using the secure form](#process-if-you-re-not-pci-dss-certified) ([HiPay’s Hosted Page](https://developer.hipay.com/api-explorer/hpayment-api#/payments/post_v1_hpayment)), or relying on secure fields ([HiPay’s Hosted Fields](https://developer.hipay.com/online-payments/payment/hosted-fields)).
* **If you're PCI DSS certified** – Generate the token directly [using the dedicated endpoint](#process-if-you-re-pci-dss-certified).
### Process if you're not PCI DSS certified
If you are not PCI DSS certified, HiPay provides two endpoints so you can:
1. Generate the token of the card using a secure form.
2. Retrieve the generated token.
#### 1. Generate token through secure form
You can make the following HiPay request to generate the form that will then be used by the end user to tokenize the card.
```bash [CURL]
# encode your private credentials in base64
hipayPrivateCredentials=`echo "myprivateuser:myprivatepassword" | base64 -`
# tokenize the card
curl -X POST '{hiPayTokenizationFormBaseUrl}/v1/hpayment' \
--header 'Authorization: Basic {hipayPrivateCredentials}' \ # as encoded above
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`.
Please bear in mind that the choice of `operation` impacts the capture mode, which depends on your configuration. Contact Treezor if you're unsure of which one to use.
```json [JSON]
{
"orderid": "order_xxxxx", // Must be unique
"operation": "Authorization", // Authorization || Sale
// custom_data error will result in the funds being debited from external account,
// but not credited on the Treezor Wallet of the real beneficiary of the capture.
"custom_data" : {
"1": "{clientId}",
"2": "{walletId}",
"3": "{userId}"
},
// Please don't use other custom_data than the ones indicated above.
"payment_product_list": "visa, mastercard, cb",
"template": "basic-js",
"merchant_display_name": "Merchant name",
"display_selector": "1",
"description": "description",
"email": "a.oak@example.com",
"card_holder": "Alex Oak",
"currency": "EUR",
"amount": "1.00",
"ipaddr": "", // IP of the device from which the capture is made
"accept_url": "",
"decline_url": "",
"pending_url": "",
"exception_url": "",
"cancel_url": "",
"language": "FR_fr",
// Cardholder authentication
"eci" : "7", // single-use mode
"authentication_indicator": "2", // forces 3DS
"device_channel" : "2",
"multi_use" : 1
}
```
Returns an object containing the `forwardUrl` you need to provide to your end user.
```json [JSON]
{
"forwardUrl": "https://stage-secure-gateway.hipay-tpp.com/0000-133-2882/payment/web/pay/50b6814c-27fd-49e2-adea-33bba7150c9c",
"test": "true",
"mid": "00001332882",
"cdata1": "39625",
"cdata2": "2220766",
"cdata3": "4064148",
"cdata4": "", // Deprecated, please ignore
"cdata5": "", // Deprecated, please ignore
"cdata6": "", // Deprecated, please ignore
"cdata7": "", // Deprecated, please ignore
"cdata8": "", // Deprecated, please ignore
"cdata9": "", // Deprecated, please ignore
"cdata10": "", // Deprecated, please ignore
"order": {
"id": "order_1685549327",
"dateCreated": "2023-05-31T16:08:47+0000",
"attempts": "0",
"amount": "1.00",
"shipping": "0.00",
"tax": "0.00",
"decimals": "2",
"currency": "EUR",
"customerId": "",
"language": "FR",
"email": "aoak@example.com"
}
}
```
By using the `forwardUrl`, your end user accesses the form to enter their card information, which will in turn generate the token.
**Reading – Full parameters & customization documentation available**
Please refer to HiPay's documentation:
* [API Explorer](https://developer.hipay.com/api-explorer/api-online-payments#/payments/generateHostedPaymentPage) for all the parameters.
* [Hosted Payments](https://developer.hipay.com/online-payments/payment/hosted-payments#customize) to learn how to customize your hosted payment form.
**Tip – Direct capture scenario**
Your configuration may allow you to use the secure form for a direct capture by setting the `multi_use` parameter to `0` and the `operation` parameter to `Sale`.
#### 2. Retrieve the token
The token generation step being an authorization (hence no funds are moved), Treezor doesn't send any payin webhook.
Here is how to retrieve the `token` and `paymentProduct` for the payment.
```bash [CURL]
# encode your private credentials in base64
hipayPrivateCredentials=`echo "myprivateuser:myprivatepassword" | base64 -`
# retrieve the token
curl -X GET '{hiPayTokenizationBaseUrl}/rest/v1/transaction?orderid={orderid}' \
--header 'Authorization: Basic {hipayPrivateCredentials}' \ # as encoded above
--header 'Accept: application/json'
```
Returns the following:
```json [JSON] {37,39}
{
"transaction": {
"state": "completed",
"reason": "",
"forwardUrl": "",
"test": "true",
"mid": "00001332882",
"attemptId": "1",
"authorizationCode": "",
"transaction_reference": "800242932739",
"dateCreated": "2023-06-30T09:07:41+0000",
"dateUpdated": "2023-06-30T09:07:52+0000",
"dateAuthorized": "2023-06-30T09:07:52+0000",
"status": "116",
"message": "Authorized",
"authorizedAmount": "1.00",
"capturedAmount": "0.00",
"refundedAmount": "0.00",
"decimals": "2",
"currency": "EUR",
"ipAddress": "212.114.31.26",
"ipCountry": "FR",
"deviceId": "",
"cdata1": "client_id",
"cdata2": "wallet_id",
"cdata3": "user_id",
"cdata4": "",
"cdata5": "",
"cdata6": "",
"cdata7": "",
"cdata8": "",
"cdata9": "",
"cdata10": "",
"avsResult": "",
"cvcResult": "",
"eci": "7",
"paymentProduct": "visa",
"paymentMethod": {
"token": "ba3dd3760142bd6fc715b99429839b06d6de6bd1c6f1eaf36a788668396d011d",
"cardId": "b1113d3b-5140-4616-abf7-49aeec3f4414",
"brand": "VISA",
"pan": "424242******4242",
"cardHolder": "ALEX OAK",
"cardExpiryMonth": "05",
"cardExpiryYear": "2024",
"issuer": "",
"country": "GB"
},
"threeDSecure": {
"eci": "5",
"authenticationStatus": "Y",
"authenticationMessage": "Authentication Successful",
"authenticationToken": "",
"xid": ""
},
"fraudScreening": {
"scoring": "0",
"result": "ACCEPTED",
"review": ""
},
"order": {
"id": "order_1688116033",
"dateCreated": "2023-06-30T09:07:12+0000",
"gender": "U",
"firstname": "",
"lastname": "",
"streetAddress": "",
"locality": "",
"postalCode": "",
"country": "",
"attempts": "1",
"amount": "1.00",
"shipping": "0.00",
"tax": "0.00",
"decimals": "2",
"currency": "EUR",
"customerId": "",
"language": "FR",
"msisdn": "",
"phone": "",
"phoneOperator": "",
"shippingAddress": {
"firstname": "",
"lastname": "",
"streetAddress": "",
"locality": "",
"postalCode": "",
"country": ""
},
"email": "teamimplem@test.com"
},
"debitAgreement": {
"id": "10520843",
"status": "available"
}
}
}
```
**Reading – Full parameters documentation available**
Refer to [HiPay's Documentation](https://developer.hipay.com/api-explorer/api-online-payments#/transaction/getTransactionsByReference) to learn everything there is to know about the parameters.
### Process if you're PCI DSS certified
#### Parameters
| Attribute | Type | Description |
| --- | --- | --- |
| `card_number` | string | The [primary account number (PAN)](/guide/overview/glossary#pan-primary-account-number) of the card. |
| `card_expiry_month` | integer | The month on which the card expires. |
| `card_expiry_year` | integer | The year on which the card expires. |
| `card_holder` | string | The name of the cardholder, embossed or etched on the card. |
| `cvc` | integer | The [CVC](/guide/overview/glossary#cvc-card-verification-number) of the card. |
| `multi_use` | integer | Indicates whether the card can be used multiple times. Either: `0` – The card can only be used once, and the token expires after a month if not used.`1` – The card can be used multiple times and the token expires at the card expiry date. |
In addition, you'll need your `hipayPublicCredentials` in the request Authorization header. It is a concatenation of `hipay_public_user` `:` `hipay_public_password` credentials, without spaces and encoded in base64.
#### Request example
```bash [CURL]
# encode your public credentials in base64
hipayPublicCredentials=`echo "mypublicuser:mypublicpassword" | base64 -`
# tokenize the card
curl -X POST '{hiPayTokenizationBaseUrl}/rest/v2/token/create' \
--header 'Authorization: Basic {hipayPublicCredentials}' \ # as encoded above
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"card_number": "5300000000000006",
"card_expiry_month": 12,
"card_expiry_year": 2025,
"card_holder": "Alex Oak",
"cvc": 123,
"multi_use": 1
}
```
Returns the `token` of the card.
```json [JSON]
{
"token": "ee9ac2901f4c0d651143664659f206bb6e34ee552ab4e693fa21616b0ef69a57",
"request_id": "0",
"card_id": "9fd81707-8f41-4a01-b6ed-279954336ada",
"multi_use": 1,
"brand": "VISA",
"pan": "411111xxxxxx1111",
"card_holder": "Alex Oak",
"card_expiry_month": "12",
"card_expiry_year": "2025",
"issuer": "JPMORGAN CHASE BANK, N.A.",
"country": "US",
"card_type": "CREDIT",
"forbidden_issuer_country": false
}
```
**Warning – Authorize tokenized cards first with `eci`=`7` payment to enforce 3DS**
You must receive a successful payment before you can either use it with `eci` = `9` or store the `cardtoken` in your database.
If you're encountering an error, please check out the [HiPay's error codes](https://developer.hipay.com/payment-fundamentals/essentials/error-messages) documentation.
## Step 2, Create the payment
After you have tokenized the card, you can use this token to request a payment, crediting the [Wallet](/guide/wallets/introduction) of your choice.
### Parameters
| Attribute | Type | Description |
| --- | --- | --- |
| `custom_data` | object | Allows you to associate the payment with the Wallet and User. `custom_data[1]` – **Your [client\_id](/guide/api-basics/authentication#credentials)**`custom_data[2]` – **The recipient's [Wallet](/guide/wallets/introduction) id**`custom_data[3]` – **The recipient's [User](/guide/users/introduction) id** |
| `cardtoken` | string | The token of the card, as obtained in the tokenization step. |
| `accept_url` | string | The URL to which the user is to be redirected in case of an authorized payment. |
| `decline_url` | string | The URL to which the user is to be redirected in case of a declined payment. |
| `pending_url` | string | The URL to which the user is to be redirected in case of the payment is left pending. |
| `exception_url` | string | The URL to which the user is to be redirected in case an exception occurs. |
| `cancel_url` | string | The URL to which the user is to be redirected in case of a canceled payment. |
| `eci` | string | The security level at which the payment information is processed. `7` – **One-time** payment (allowing for 3DS)`9` – **Recurring** payments (following an `eci=7`) Any capture made with `9` must have a previous successful authorization or transaction with an `eci` valued to `7` that enforced 3DS. |
| `authentication_indicator` | string | Indicates how to handle 3DS. Can be: `0` – Bypasses 3DS `1` – 3DS will be used if the card allows it`2` – Forces the use of 3DS |
| `hipayPrivateCredentials` | string | The concatenation of `hipay_private_user` `:` `hipay_private_password` [HiPay credentials](/guide/acquiring/introduction#hipay-environments-credentials), without spaces and encoded in base64. |
**Warning – Authorize tokenized cards first with `eci`=`7` payment to enforce 3DS**
You must receive a successful payment before you can either use it with `eci` = `9` or store the `cardtoken` in your database.
### Request
```bash [CURL]
# encode your private credentials in base64
hipayPrivateCredentials=`echo "myprivateuser:myprivatepassword" | base64 -`
# receive the payment
curl -X POST '{hiPayBaseUrl}/rest/v1/order' \
--header 'Authorization: Basic {hipayPrivateCredentials}' \ # as encoded above
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`.
```json [JSON]
{
"orderid": "Order_yyyyy", // Must be unique (so different from step 1)
"operation": "Sale",
"description": "IMP1639671746",
"currency": "EUR",
"amount": "100",
"ipaddr": "192.154.28.65",
"custom_data": {
"1": "123456", // your client_id
"2": "234567", // the walletId to credit
"3": "345678" // the userId to credit
},
// Please don't use other custom_data than the ones indicated above.
"eci": "9", // or 7 if no eci in used in step 1
"authentication_indicator": "2", // see list above
"email": "teamimplem@test.com", // the cardholders email
"card_holder": "Tom Pes", // the cardholders name as embossed or etched on the card
"cardtoken": "{HiPayToken}",
"payment_product": "visa",
"accept_url": "https://dictionary.cambridge.org/fr/dictionnaire/anglais/accept", // redirection URL in case of authorized payment
"decline_url": "https://dictionary.cambridge.org/fr/dictionnaire/anglais/decline", // redirection URL in case of declined payment
"pending_url": "https://dictionary.cambridge.org/fr/dictionnaire/anglais/pending", // redirection URL in case the payment is left pending
"exception_url": "https://dictionary.cambridge.org/fr/dictionnaire/anglais/exception", // redirection URL in case of fatal error
"cancel_url": "https://dictionary.cambridge.org/fr/dictionnaire/anglais/cancel", // redirection URL in case the end user cancels the payment
"device_channel": "1"
}
```
**Reading – Full parameters documentation available**
Refer to [HiPay's Documentation](https://support.hipay.com/hc/en-us/articles/360010582280-HiPay-Enterprise-Hosted-Fields-with-JavaScript-SDK-and-order-API) to learn everything there is to know about the parameters.
Returns the details regarding the capture.
```json [JSON]
{
"state": "completed",
"reason": "",
"forwardUrl": "",
"test": "true",
"mid": "00001332882",
"attemptId": "1",
"authorizationCode": "test123",
"transaction_reference": "800143609738",
"referenceToPay": "",
"dateCreated": "2021-12-21T13:42:15+0000",
"dateUpdated": "2021-12-21T13:42:20+0000",
"dateAuthorized": "2021-12-21T13:42:19+0000",
"status": "118",
"message": "Captured",
"authorizedAmount": "100.00",
"capturedAmount": "100.00",
"refundedAmount": "0.00",
"creditedAmount": "0.00",
"decimals": "2",
"currency": "EUR",
"ipAddress": "192.154.28.65",
"ipCountry": "CA",
"deviceId": "",
"cdata1": "212707", // is your client_id as provided previously
"cdata2": "1174278", // is the recipients walletId as provided previously
"cdata3": "2189821", // is the recipients userId as provided previously
"cdata4": "",
"cdata5": "",
"cdata6": "",
"cdata7": "",
"cdata8": "",
"cdata9": "",
"cdata10": "",
"avsResult": "",
"eci": "9",
"paymentProduct": "visa",
"paymentMethod": {
"token": "3b1a89dfd033307f7a9fbf8757025f2226766e125b84e1cd616de9d7b7e4ebe4",
"cardId": "9fd81707-8f41-4a01-b6ed-279954336ada",
"brand": "VISA",
"pan": "411111******1111",
"cardHolder": "TOM PES",
"cardExpiryMonth": "12",
"cardExpiryYear": "2025",
"issuer": "JPMORGAN CHASE BANK, N.A.",
"country": "US"
},
"threeDSecure": "",
"fraudScreening": {
"scoring": "0",
"result": "ACCEPTED",
"review": ""
},
"order": {
"id": "Order_1639671746",
"dateCreated": "2021-12-21T13:42:15+0000",
"attempts": "1",
"amount": "100.00",
"shipping": "0.00",
"tax": "0.00",
"decimals": "2",
"currency": "EUR",
"customerId": "",
"language": "en_US",
"email": "teamimplem@test.com"
},
"debitAgreement": {
"id": "10337627",
"status": "available"
}
}
```
**Information**
* The `custom_data` attribute that you provided is absent from this response, this is on purpose.
* The `cdata{n}` attributes will be removed from the responses in the future.
You should not rely on this response but [**on the Webhooks**](#step-3-receive-the-webhooks) instead.
## Step 3, Receive the webhooks
Once the payment has been made by the end user, you will receive a [`payin.update`](events) webhook.
This webhook informs you whether the payment is:
* **Accepted** – With a `payinStatus` attribute set to `VALIDATED`
* **Refused** or **impossible** – With a `payinStatus` attribute set to `CANCELED`
### Legacy `payin.update` event
```json [JSON (new)]
{
"webhook": "payin.update",
"object": "payin",
"object_id": "103700",
"object_payload": {
"payins": [
{
"payinId": "103700",
"payinTag": "",
"walletId": "878744",
"userId": "1656177",
"payinStatus": "PENDING",
"paymentMethodId": "25",
"messageToUser": "",
"subtotalItems": "0.00",
"subtotalServices": "0.00",
"subtotalTax": "0.00",
"amount": "12.34",
"currency": "EUR",
"createdDate": "2024-09-09 14:04:32",
"walletEventName": "reset",
"walletAlias": "alias878744",
"userFirstname": "Alex",
"userLastname": "Oak",
"codeStatus": "150117",
"informationStatus": "A capture request has been sent to the financial institution.",
"refundAmount": null,
"DbtrIBAN": null,
"forwardUrl": null,
"paymentAcceptedUrl": null,
"paymentRefusedUrl": null,
"paymentWaitingUrl": null,
"paymentExceptionUrl": null,
"paymentCanceledUrl": null,
"payinDate": "0000-00-00",
"mandateId": "0",
"creditorName": null,
"creditorAddressLine": null,
"creditorCountry": null,
"creditorIban": null,
"creditorBIC": null,
"virtualIbanId": null,
"virtualIbanReference": null,
"additionalData": {
"card": {
"externalProvider": {
"state": "completed",
"mid": "00001341804",
"authorizationCode": "no_code",
"transaction_reference": "800320947416",
"dateCreated": "2024-09-09T12:04:24+0000",
"dateUpdated": "2024-09-09T12:04:29+0000",
"status": 118,
"message": "Captured",
"authorizedAmount": 12.34,
"capturedAmount": 12.34,
"refundedAmount": 0,
"currency": "EUR",
"ipAddress": "0.0.0.0",
"ipCountry": "",
"cdata1": "212707",
"cdata2": "878744",
"cdata3": "1656177",
"cdata4": "",
"cdata5": "",
"cdata6": "",
"cdata7": "",
"cdata8": "",
"cdata9": "",
"cdata10": "",
"eci": "9",
"paymentProduct": "mastercard",
"paymentMethod": {
"pan": "514414******1246",
"cardHolder": "ALEX OAK",
"token": "d0******78",
"issuer": "TREE BANK, INC.",
"brand": "MASTERCARD",
"country": "US",
"cardExpiryMonth": "12",
"cardExpiryYear": "2025"
},
"fraudScreening": {
"scoring": "0",
"result": "not_launched",
"review": ""
}
}
}
},
"totalRows": 1
}
]
},
"webhook_created_at": 17258834731609,
"webhook_id": "49383fa6-f72e-43de-a288-506dcxxx9ca6",
"object_payload_signature": "IO5v1nKaQorSeqsC4dWS2G3wq32ecLZY5xxxxyYFE9c=",
"auth_key": "true"
}
```
```json [JSON (before)]
{
"webhook": "payin.update",
"object": "payin",
"object_id": "103711",
"object_payload": {
"payins": [
{
"payinId": "103711",
"payinTag": "",
"walletId": "878744",
"userId": "1656177",
"payinStatus": "PENDING",
"paymentMethodId": "25",
"messageToUser": "",
"subtotalItems": "0.00",
"subtotalServices": "0.00",
"subtotalTax": "0.00",
"amount": "12.34",
"currency": "EUR",
"createdDate": "2024-09-09 14:48:10",
"walletEventName": "reset",
"walletAlias": "alias878744",
"userFirstname": "Alex",
"userLastname": "Oak",
"codeStatus": "150116",
"informationStatus": "The financial institution has approved the payment. In the case of a credit card payment, funds are held and deducted from the customer s credit limit (or bank balance, in the case of a debit card), but are not yet transferred to the merchant. In the cas",
"refundAmount": null,
"DbtrIBAN": null,
"forwardUrl": null,
"paymentAcceptedUrl": null,
"paymentRefusedUrl": null,
"paymentWaitingUrl": null,
"paymentExceptionUrl": null,
"paymentCanceledUrl": null,
"payinDate": "0000-00-00",
"mandateId": "0",
"creditorName": null,
"creditorAddressLine": null,
"creditorCountry": null,
"creditorIban": null,
"creditorBIC": null,
"virtualIbanId": null,
"virtualIbanReference": null,
"additionalData": {
"card": {
"externalProvider": {
"transaction_reference": "800320947755"
}
}
},
"totalRows": 1
}
]
},
"webhook_created_at": 17258860905593,
"webhook_id": "13800071-738c-4f08-be82-09f75cf88a67",
"object_payload_signature": "WffEOrVEjcw0W4AKkfUFh19\/ROcqaw9XpGiVrg2\/DuU=",
"auth_key": "true"
}
```
You may also retrieve the payin by using the [`/v1/payins/{payinId}`](/api-reference/api-endpoints.html#tag/Payins/getPayin){target="\_self"} request.
### Webhooks flow
```mermaid
flowchart TD
id1(Payment creation) --> id2("payin.create payinStatus:PENDING" ) --> id3("payin.update payinStatus:VALIDATED");
id2 --> id4("payin.update payinStatus:CANCELED")
class id1 neutral;
```
## Disputes
When a card acquisition payin is disputed by the cardholder, you receive:
* A [`card.acquiring.chargeback.create`](./events#card-acquiring-chargeback-create) webhook informing you of the dispute.
* A [`payinrefund.create`](./events#payinrefund-create) and a [`payinrefund.update`](./events#payingrefund-update) webhook sending back the fund or locking the funds on the Wallet for future refund.
## Legacy emulation
You can emulate a [Card Acquisition](./introduction) using the following request. Please note emulated payins can't be refunded.
### Parameters
| Attribute | Type | Description |
| --- | --- | --- |
| `user_id` | string | The unique identifier of the user. |
| `wallet_id` | string | The unique identifier of the Wallet to top up. |
| `amount` | number | The amount to credit. |
| `currency` | string | Must be `EUR`. |
| `status` | integer | Can be the following: 109 for an authentication failure110 for a rejection due to fraud suspicion113 for a refusal by the payment institution115 for a payment timeout116 for an authorization request117 for a capture request118 for a successful Card Acquisition129 for a chargeback173 for a refused capture |
| `transaction_reference` | integer | Arbitrary reference, generated by HiPay. You need this value to emulate the complete flow composed of multiple requests. |
| `payment_product` | string | The type of card: `visa`, `mastercard`, `cb`, `maestro`.|
### Request
To emulate a complete flow, you can set a `status` = `117` followed by a `118` while specifying the same `transaction_reference` for both requests.
```bash [CURL]
curl -X POST '{baseUrl}/simulation/acquiring/payin' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is a `{payload}` example:
```json [JSON]
{
"status": "117",
"amount": 34.56,
"user_id": "{userId}",
"wallet_id": "{walletId}",
"currency": "EUR",
"payment_product": "mastercard"
}
```
Returns the following:
```json [JSON]
{
"transaction_reference": 1725547253
}
```
---
---
url: /guide/acquiring/refunds.md
description: >-
Learn how to create refunds and handle chargebacks for card top-up payins, for
a seamless integration in your application.
---
# Refunds & chargebacks
## Refunds
Refunds are only available for certain [paymentProducts](/guide/acquiring/introduction#payment-products-specificities). They are always associated with Payins, you may create multiple Refunds for a single Payin (just like there can be multiple Payins for a single Authorization).
### Parameters
You can optionally use the following parameters when creating a refund.
| Attribute | Type | Description |
| --- | --- | --- |
| `currency` | string | The currency of the refund, in ISO-4217 format. |
| `amount` | number | The amount of the refund. Can be specified to partially refund a payin. If omitted, the payin is entirely refunded. |
| `profile` | string | The MID. Required if you have multiple Merchant IDs (MIDs). |
### Request
```bash [CURL]
curl -X POST '{baseUrl}/v1/payinrefunds' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"payinId": "00b9cde9-0aa5-44ba-8e3a-f91fc4c29e39",
"amount": 19.99, // If not specified, the whole payin is refunded
"currency": "EUR"
}
```
Returns the Payin Refund object and sends [`payinrefund.create`](./events#payinrefund-create) and [`payinrefund.update`](./events#payinrefund-update) webhooks.
```json [JSON]
{
"payinRefunds": [
{
"payinrefundId": "string",
"payinrefundTag": "null",
"payinrefundStatus": "string",
"walletId": "string",
"payinId": "string",
"amount": 19.99,
"currency": "EUR",
"createdDate": "string",
"modifiedDate": "string",
"payinrefundDate": "string",
"profile": "string"
}
]
}
```
## Chargebacks
When a [chargeback](/guide/overview/glossary#chargeback) is received, Treezor sends:
* A [`card.acquiring.chargeback.create`](./events#card-acquiring-chargeback-create) webhook.
* As many [`payinrefund.create`](./events#payinrefund-create) and [`payinrefund.update`](./events#payinrefund-update) webhooks as necessary (if multiple captures occurred for a single authorization)
The chargeback is automatically accepted, and the Wallet debited (even if insufficiently provisioned). You do not have the ability to refuse it.
---
---
url: /guide/acquiring/faking-operations.md
description: >-
Learn how to simulate card acquiring authorization, payins, refunds, and
chargeback within the Sandbox environment for development and API integration
testing.
---
# Emulation
Emulation features are only available in the `Sandbox` [environment](/guide/api-basics/environments) (which is paired with HiPay's [staging environment](/guide/acquiring/introduction#hipay-environments-credentials)).
## Authorization
To emulate an Authorization, you may use the following request with the `status` corresponding to the behavior you wish to emulate.
| Value | Emulated behavior |
| --- | --- |
| `109` | Authentication failed |
| `110` | Blocked |
| `111` | Denied |
| `112` | Authorized and Pending |
| `113` | Refused |
| `114` | Expired |
| `115` | Canceled |
| `116` | Authorized **(Default)** |
| `142` | Authorization Requested |
| `143` | Authorization Cancelled |
| `175` | Authorization Cancellation Requested |
```bash [CURL]
curl -X POST '{baseUrl}/simulation/topups/cards/notification/authorizations' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is a `{payload}` example:
```json [JSON]
{
"amount": {amount},
"currency": "EUR",
"walletId": "{walletId}",
"userId": "{userId}", // Optional
"cardPaymentMethod": { // Mandatory for 116 status only. Omit otherwise.
"brand": "string",
"cardExpiryMonth": "string",
"cardExpiryYear": "string",
"cardHolder": "string",
"country": "string",
"issuer": "string",
"maskedPan": "string",
"token": "string"
},
"status": {statusOfTheSimulatedNotification}, // optional
"transactionReference": "{transactionReference}", // Mandatory for all statuses except 116
"profile": "{profile}" // Mandatory for multi-MID
}
```
Returns the following.
```json [JSON]
{
"transactionReference": "string",
"authorizationId": "string"
}
```
## Payin
To emulate a Payin, you may use the following request with the `status` corresponding to the behavior you wish to emulate.
| Value | Emulated behavior |
| --- | --- |
| `117` | Capture Requested |
| `118` | Captured **(Default)** |
| `173` | Capture Refused |
```bash [CURL]
curl -X POST '{baseUrl}/simulation/topups/cards/notification/payins' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is a `{payload}` example:
```json [JSON]
{
"amount": {amount},
"currency": "EUR",
"walletId": "{walletId}",
"userId": "{userId}", // Optional
// "cardPaymentMethod": "{cardPaymentMethod}", // Omit, for status 116 only
"status": {statusOfTheSimulatedNotification}, // optional
"transactionReference": "{transactionReference}", // Mandatory (except 116)
"profile": "{profile}" // Mandatory for multi-MID
}
```
Returns the following:
```json [JSON]
{
"transactionReference": "string",
"payinId": "string"
}
```
## Refund
To emulate a Refund, you may use the following request with the `status` corresponding to the behavior you wish to emulate.
| Value | Emulated behavior |
| --- | --- |
| `124` | Refund Requested |
| `125` | Refunded **(Default)** |
| `126` | Partially Refunded |
| `165` | Refund Refused |
```bash [CURL]
curl -X POST '{baseUrl}/simulation/topups/cards/notification/refunds' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is a `{payload}` example:
```json [JSON]
{
"amount": {amount},
"currency": "EUR",
"walletId": "{walletId}",
"userId": "{userId}", // Optional
// "cardPaymentMethod": "{cardPaymentMethod}", // Omit, for status 116 only
"status": {statusOfTheSimulatedNotification}, // optional
"transactionReference": "{transactionReference}", // Mandatory (except 116)
"profile": "{profile}" // Mandatory for multi-MID
}
```
Returns the following.
```json [JSON]
{
"transactionReference": "string",
"refundId": "string"
}
```
## Chargeback
To emulate a Chargeback, you only need the `transactionReference`.
The transaction reference is provided in response to the [authorization step](./preauthorized), or in response to the payin creation step if you have skipped the authorization step.
The following request emulates a Chargeback for the full amount of the transaction.
```bash [CURL]
curl -X POST '{baseUrl}/simulation/topups/cards/notification/chargebacks' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is a `{payload}` example:
```json [JSON]
{
"transactionReference": "{transactionReference}"
}
```
Returns an object containing the `chargebackId`:
```json [JSON]
{
"transactionReference": "string",
"chargebackId": "string"
}
```
## Endpoints
| Endpoint | [Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/simulation/topups/cards/notification/authorizations`](/api-reference/api-endpoints.html#tag/Acquiring%20\(Simulation\)/acquiringv2-topup-cards-simulation-notification-autorization){target="\_self"} Simulate an HiPay authorization notification | `admin` |
| [`/simulation/topups/cards/notification/payins`](/api-reference/api-endpoints.html#tag/Acquiring%20\(Simulation\)/acquiringv2-topup-cards-simulation-notification-payins){target="\_self"} Simulate an HiPay payin notification | `admin` |
| [`/simulation/topups/cards/notification/refunds`](/api-reference/api-endpoints.html#tag/Acquiring%20\(Simulation\)/acquiringv2-topup-cards-simulation-notification-refunds){target="\_self"} Simulate an HiPay refund notification | `admin` |
| [`/simulation/topups/cards/notification/chargebacks`](/api-reference/api-endpoints.html#tag/Acquiring%20\(Simulation\)/acquiringv2-topup-cards-simulation-notification-chargebacks){target="\_self"} Simulate an HiPay chargeback notification | `admin` |
---
---
url: /guide/acquiring/card-tokenization.md
description: >-
Technical guide for tokenizing cards in order to process third-party card
payments. The card secure token can be generated either with a hosted form or
directly with a dedicated endpoint if you're PCI DSS-certified.
---
# Card Tokenization
Tokenization is the process of converting the [PAN](/guide/overview/glossary#pan-primary-account-number), expiration date, and [CVC](/guide/overview/glossary#cvc-card-verification-number) of a card into a token.
The tokenization request must be sent from the end user's device (for example using JavaScript), as the [PAN](/guide/overview/glossary#pan-primary-account-number) cannot transit or be stored on your servers.
You may generate the token either:
* **If you're not PCI DSS certified** – [Using the secure form](#process-if-you-re-not-pci-dss-certified) ([HiPay’s Hosted Page](https://developer.hipay.com/api-explorer/hpayment-api#/payments/post_v1_hpayment)), or relying on secure fields ([HiPay’s Hosted Fields](https://developer.hipay.com/online-payments/payment/hosted-fields)).
* **If you're PCI DSS certified** – Directly [using the dedicated endpoint](#process-if-you-re-pci-dss-certified).
**Information – These are the only HiPay endpoints allowed**
Any other actions must be carried out using the Treezor API.
## Tokenize with the secure form
If you're **not PCI DSS-certified**, HiPay provides 2 endpoints, so you can:
1. Generate the token of the card using a secure form.
2. Retrieve the generated token.
### 1. Generate token through secure form
You can make the following HiPay request to generate the form that will then be used by the end user to tokenize the card.
```bash [CURL]
# encode your private credentials in base64
hipayPrivateCredentials=`echo "myprivateuser:myprivatepassword" | base64 -`
# tokenize the card
curl -X POST '{hiPayTokenizationFormBaseUrl}/v1/hpayment' \
--header 'Authorization: Basic {hipayPrivateCredentials}' \ # as encoded above
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`.
Please bear in mind that the choice of `operation` impacts the capture mode, which depends on your configuration. Contact Treezor if you're unsure of which one to use.
```json [JSON]
{
"orderid": "order_xxxxx", // Must be unique
"operation": "Authorization", // Authorization || Sale
// custom_data error will result in the funds being debited from external account,
// but not credited on the Treezor Wallet of the real beneficiary of the capture.
"custom_data" : {
"1": "{clientId}",
"2": "{walletId}",
"3": "{userId}"
},
// Please don't use other custom_data than the ones indicated above.
"payment_product_list": "visa, mastercard, cb",
"template": "basic-js",
"merchant_display_name": "Merchant name",
"display_selector": "1",
"description": "description",
"email": "aokm@example.com",
"card_holder": "Alex Oak",
"currency": "EUR",
"amount": "1.00",
"ipaddr": "", // IP of the device from which the capture is made
"accept_url": "",
"decline_url": "",
"pending_url": "",
"exception_url": "",
"cancel_url": "",
"language": "FR_fr",
// Cardholder authentification
"eci" : "7", // single-use mode
"authentication_indicator": "2", // forces 3DS
"device_channel" : "2",
"multi_use" : 1
}
```
Returns an object containing the `forwardUrl` you need to provide to your end user.
```json [JSON]
{
"forwardUrl": "https://stage-secure-gateway.hipay-tpp.com/0000-133-2882/payment/web/pay/50b6814c-27fd-49e2-adea-33bba7150c9c",
"test": "true",
"mid": "00001332882",
"cdata1": "39625",
"cdata2": "2220766",
"cdata3": "4064148",
"cdata4": "", // Deprecated, please ignore
"cdata5": "", // Deprecated, please ignore
"cdata6": "", // Deprecated, please ignore
"cdata7": "", // Deprecated, please ignore
"cdata8": "", // Deprecated, please ignore
"cdata9": "", // Deprecated, please ignore
"cdata10": "", // Deprecated, please ignore
"order": {
"id": "order_1685549327",
"dateCreated": "2023-05-31T16:08:47+0000",
"attempts": "0",
"amount": "1.00",
"shipping": "0.00",
"tax": "0.00",
"decimals": "2",
"currency": "EUR",
"customerId": "",
"language": "FR_fr",
"email": "aoak@example.com"
}
}
```
By using the `forwardUrl`, your end user accesses the form to enter their card information, which will in turn generate the token.
**Reading – Full parameters documentation available**
Refer to [HiPay's Documentation](https://developer.hipay.com/api-explorer/api-online-payments#/payments/generateHostedPaymentPage) to learn everything there is to know about the parameters.
**Reading – Customize your hosted payment form**
Refer to the [Hosted Payments](https://developer.hipay.com/api-explorer/hpayment-api#/payments/post_v1_hpayment) section of HiPay's documentation to learn how to customize your hosted payment form.
### 2. Retrieve the token
Once the user has generated the token, you may retrieve it.
```bash [CURL]
# encode your private credentials in base64
hipayPrivateCredentials=`echo "myprivateuser:myprivatepassword" | base64 -`
# retrieve the token
curl -X GET '{hiPayBaseUrl}/rest/v1/transaction?orderid={orderid}' \
--header 'Authorization: Basic {hipayPrivateCredentials}' \ # as encoded above
--header 'Accept: application/json'
```
Returns the following Transaction, with the `token` available in the `paymentMethod` object.
```json [JSON] {39}
{
"transaction": {
"state": "completed",
"reason": "",
"forwardUrl": "",
"test": "true",
"mid": "00001332882",
"attemptId": "1",
"authorizationCode": "",
"transactionReference": "800242932739",
"dateCreated": "2023-06-30T09:07:41+0000",
"dateUpdated": "2023-06-30T09:07:52+0000",
"dateAuthorized": "2023-06-30T09:07:52+0000",
"status": "116",
"message": "Authorized",
"authorizedAmount": "1.00",
"capturedAmount": "0.00",
"refundedAmount": "0.00",
"decimals": "2",
"currency": "EUR",
"ipAddress": "212.114.31.26",
"ipCountry": "FR",
"deviceId": "",
"cdata1": "client_id",
"cdata2": "wallet_id",
"cdata3": "user_id",
"cdata4": "",
"cdata5": "",
"cdata6": "",
"cdata7": "",
"cdata8": "",
"cdata9": "",
"cdata10": "",
"avsResult": "",
"cvcResult": "",
"eci": "7",
"paymentProduct": "visa",
"paymentMethod": {
"token": "ba3dd3760142bd6fc715b99429839b06d6de6bd1c6f1eaf36a788668396d011d",
"cardId": "b1113d3b-5140-4616-abf7-49aeec3f4414",
"brand": "VISA",
"pan": "424242******4242",
"cardHolder": "ALEX OAK",
"cardExpiryMonth": "05",
"cardExpiryYear": "2024",
"issuer": "",
"country": "GB"
},
"threeDSecure": {
"eci": "5",
"authenticationStatus": "Y",
"authenticationMessage": "Authentication Successful",
"authenticationToken": "",
"xid": ""
},
"fraudScreening": {
"scoring": "0",
"result": "ACCEPTED",
"review": ""
},
"order": {
"id": "order_1688116033",
"dateCreated": "2023-06-30T09:07:12+0000",
"gender": "U",
"firstname": "",
"lastname": "",
"streetAddress": "",
"locality": "",
"postalCode": "",
"country": "",
"attempts": "1",
"amount": "1.00",
"shipping": "0.00",
"tax": "0.00",
"decimals": "2",
"currency": "EUR",
"customerId": "",
"language": "FR_fr",
"msisdn": "",
"phone": "",
"phoneOperator": "",
"shippingAddress": {
"firstname": "",
"lastname": "",
"streetAddress": "",
"locality": "",
"postalCode": "",
"country": ""
},
"email": "teamimplem@test.com"
},
"debitAgreement": {
"id": "10520843",
"status": "available"
}
}
}
```
**Reading – Full parameters documentation available**
Refer to [HiPay's Documentation](https://developer.hipay.com/api-explorer/api-online-payments#/transaction/getTransactionsByReference) to learn everything there is to know about the parameters.
## Tokenize with the create token request
If you are **PCI DSS-certified**, you can directly use the dedicated endpoint to generate the card token.
### Parameters
| Attribute | Type | Description |
| --- | --- | --- |
| `card_number` | string | The [primary account number (PAN)](/guide/overview/glossary#pan-primary-account-number) of the card. |
| `card_expiry_month` | integer | The month on which the card expires. |
| `card_expiry_year` | integer | The year on which the card expires. |
| `card_holder` | string | The name of the cardholder, embossed or etched on the card. |
| `cvc` | integer | The [CVC](/guide/overview/glossary#cvc-card-verification-number) of the card. |
| `multi_use` | integer | Indicates whether the card can be used multiple times. Either: `0` – The card can only be used once, and the token expires after a month if not used. `1` – The card can be used multiple times and the token expires at the card expiry date. |
In addition, you'll need your `hipayPublicCredentials` in the request Authorization header. It is a concatenation of `hipay_public_user` `:` `hipay_public_password` [credentials](/guide/acquiring/introduction##hipay-environments-credentials), without spaces and encoded in base64.
### Request example
```bash [CURL]
# encode your public credentials in base64
hipayPublicCredentials=`echo "mypublicuser:mypublicpassword" | base64 -`
# tokenize the card
curl -X POST '{hiPayTokenizationBaseUrl}/rest/v2/token/create' \
--header 'Authorization: Basic {hipayPublicCredentials}' \ # as encoded above
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"card_number": "5300000000000006",
"card_expiry_month": 12,
"card_expiry_year": 2025,
"card_holder": "Alex Oak",
"cvc": 123,
"multi_use": 1
}
```
Returns the `token` of the card.
```json [JSON]
{
"token": "ee9ac2901f4c0d651143664659f206bb6e34ee552ab4e693fa21616b0ef69a57",
"request_id": "0",
"card_id": "9fd81707-8f41-4a01-b6ed-279954336ada",
"multi_use": 1,
"brand": "VISA",
"pan": "411111xxxxxx1111",
"card_holder": "Alex Oak",
"card_expiry_month": "12",
"card_expiry_year": "2025",
"issuer": "JPMORGAN CHASE BANK, N.A.",
"country": "US",
"card_type": "CREDIT",
"forbidden_issuer_country": false
}
```
**Warning – Authorize tokenized cards first with `eci`=`7` payment to enforce 3DS**
You must receive a successful payment before you can either use it with `eci` = `9` or store the `cardtoken` in your database.
If you're encountering an error, please check out the [HiPay's error codes](https://developer.hipay.com/payment-fundamentals/essentials/error-messages) documentation.
## Associate the card to a User
To acquire funds using the tokenized card, you need to create the corresponding Topup Card object in the Treezor API for a given user.
To do so, use the following request with the `token` provided by HiPay during the tokenization step.
```bash [CURL]
curl -X POST '{baseUrl}/v1/topups/cards/users/{userId}/topupCards' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{
"token": "{temporaryHiPayToken}"
}'
```
Returns the Topup Card object, and sends a [`topupCard.validate`](./events#topupcard-validate) webhook.
```json [JSON]
{
"topupCards": [
{
"topupCardId": "d88fa963-2cd1-4409-9adc-a06f77b11291",
"token": "9741899a3e6c109f0f0162117fce703be273e56eaac2f269f9f6304f7474c07c",
"userId": "1656177",
"brand": "VISA",
"maskedPan": "411111xxxxxx1111",
"cardHolder": "Alex Oak",
"cardExpiryMonth": "12",
"cardExpiryYear": "2025",
"issuer": "JPMORGAN CHASE BANK, N.A.",
"country": "US",
"domesticNetwork": null,
"cardType": "CREDIT",
"createdDate": "2022-01-26 14:32:17",
"updatedDate": "2022-01-26 14:32:17",
"status": "VALIDATED",
"providerName": "HiPay",
"clientId": "212707"
}
]
}
```
To prevent abuse and misuse, there is a maximum of 10 active cards associated to a single User at any given time. You may [revoke Topup Cards](#revoke-a-topup-card) if necessary.
## Revoke a Topup Card
The following request permanently revokes a Topup Card. This action revokes the token and sets the Topup Card status to `CANCELED` permanently.
Revoking cards is highly recommended to prevent any kind of misuse. Please also note that there is a limit of 10 active cards associated to a single User at any given time.
You can still [tokenize the card](#card-tokenization) again if necessary.
### Request
```bash [CURL]
curl -X DELETE '{baseUrl}/v1/topups/cards/users/userId}/topupCards/{topupCardId}' \
--header 'Authorization: Bearer {accessToken}'
```
Returns the disabled Tokenized Card and sends a [`topupCard.cancel`](./events#usertokenizedcard-cancel) webhook.
```json [JSON]
{
"topupCards": [
{
"topupCardId": "d88fa963-xxxx-xxxx-xxxx-a06f77b11291",
"token": "9741899[...]7474c07c",
"userId": "1656177",
"brand": "VISA",
"maskedPan": "411111xxxxxx1111",
"cardHolder": "Alex Oak",
"cardExpiryMonth": "12",
"cardExpiryYear": "2025",
"issuer": "JPMORGAN CHASE BANK, N.A.",
"country": "US",
"domesticNetwork": null,
"cardType": "CREDIT",
"createdDate": "2022-01-26 14:32:17",
"updatedDate": "2022-01-26 14:32:17",
"status": "CANCELED",
"providerName": "HiPay",
"clientId": "212707"
}
]
}
```
---
---
url: /guide/cards/x-pay-google-apple.md
description: >-
Tokenize your cards for wallet providers such as Google Pay and Apple Pay.
Includes integration paths for both In-App and In-House provisioning, as well
as merchant-initiated tokenization.
---
# X-Pay
The digitization of a Card is the act of tokenizing an existing [Card](/guide/cards/introduction) and storing it in a Google Pay or Apple Pay wallet, also referred to as X-Pay.
**Note – X-Pay wallets are different from Treezor Wallets**
In the context of X-Pay, the term “wallet” refers to digital wallet holding cards (DPANs), such as Apple Pay (iOS), or Google Pay (android) mobile applications.
## Introduction to digitization
Treezor allows you to digitize the cards so that your end users can add them to their Apple Pay or Google Pay wallets, hence facilitating payments with their devices.
When digitized, the card’s sensitive information is substituted by a tokenized version of the Card ([DPAN](/guide/overview/glossary#device-primary-account-number-dpan)). As a result, the [wallet providers](/guide/overview/glossary#wallet-provider) can offer the cards as a means of payment without holding the card’s [PAN](/guide/overview/glossary#primary-account-number-pan).
Similarly to your issued cards, the X-Pay feature relies on your [Card Program](/guide/cards/introduction#card-program) both in terms of design and functionality.
There is a limit of 10 active (or suspended) digitization per card, and a digitized Card can be temporarily or permanently disabled using the Treezor API.
## Integrating your X-Pay solution
The Treezor API only handles card digitization. Your Apple Pay and Google Pay integration and certification are independent of Treezor services.
Here are the main steps to integrate X-Pay:
Contact your *Treezor Implementation Manager* to activate the X-Pay feature. They will help you meet the prerequisites and provide the relevant information to the card schemes.
Implement the card digitization process that fits your project; the endpoints you use differ depending on whether you have already enrolled to [PCI DSS services](/guide/cards/pci-dss).
There are 2 ways of digitizing Cards. [Wallet providers](/guide/overview/glossary#wallet-provider) usually require the implementation of both:
* **[In-House](#in-house-provisioning)** – The end user enters card data into their wallet provider application.
* **[In-App](#in-app-provisioning)** – The end user clicks on the “Add to wallet” button in your application.
You must get certified by the Wallet providers for your X-Pay integration to be up and running.
Google requires you to screen-record the process to ensure it follows their guidelines. Apple subcontracts the certification to a specialized company that enforces stricter controls.
Please note that Treezor:
* Isn’t involved with Google Pay for your certification.
* Does exchange with the certifying organization for your Apple Pay certification.
This article only focuses on card digitization with the Treezor API. For Card digitization to work, the [Online option](./restrictions-limits#options-permission-groups) of the issued card must be activated.
**Alert – Wallet providers' privacy policies & requirements**
Integration guides are not provided due to wallet provider policies. You must sign a non-disclosure agreement for your Apple Pay integration and be onboarded with Google Pay. These steps provide you with access to their documentation.
## In-house provisioning
With the in-house provisioning method, the end user initiates the card digitization from the wallet application of their device.
To tokenize the card and generate the [DPAN](/guide/overview/glossary#device-primary-account-number-dpan), the end user enters the card details in the app. Therefore, there is no development on your part.
In addition, in-house provisioning supports wearable devices (e.g., smartwatches) as well as Samsung Pay as a wallet provider.
### In-house process
The in-house provisioning process goes as follows.
| Step | Description |
|:----:|-------------|
| 1 | The cardholder enters the card details on their device application (Apple Pay, Google Pay, Samsung Pay). |
| 2 | Treezor handles the authorization messages before the tokenization:[Account Status Inquiry (ASI)](/guide/overview/glossary#account-status-inquiry-asi) – Ensures the card exists.[Tokenization Authorization Request (TAR)](/guide/overview/glossary#tokenization-authorization-request-tar) – Ensures the card is compatible with X-Pay.Treezor sends a [`cardDigitalizalitation.request`](./events#carddigitalization-request) notifying you that the digitization process started. |
| 3 | The card details are tokenized by the token provider (Mastercard or Visa). |
| 4 | The token provider sends back the token (DPAN) to the wallet application. |
| 5 | Treezor ensures the authentication by sending a one-time password (OTP) to the cardholder via email or SMS, and sends you the following webhooks:[`cardDigitalization.activation`](./events#carddigitalization-activation) – The OTP was sent to the cardholder, starting the authentication process. Corresponds to the [Activation Code Notification (ACN)](/guide/overview/glossary#activation-complete-notification-acn).[`cardDigitalization.complete`](./events#carddigitalization-complete) – The card was successfully digitized and added to the wallet provider application. Corresponds to the [Tokenization Complete Notification (TCN)](/guide/overview/glossary#tokenization-complete-notification-tcn). |
**Tip – The language of the SMS is inherited from the user**
The SMS sent for the OTP step is sent in the same language as the value defined in the `language` field of the User object.
If the digitized card status is updated (suspension or deactivation), the wallet provider sends a Tokenization Event Notification (TVN), and Treezor notifies you with the [`cardDigitalization.update`](./events#carddigitalization-update) webhook.
For more information about token updates, please refer to the [Token lifecycle](#token-lifecycle) section.
## In-app provisioning
The in-app provisioning is initiated from your application. In such cases, your end users click on the “Add to Wallet” button in your interface.
Please note the buttons must strictly follow the best practices of the wallet providers.
Once the user requests the card to be added to their Apple or Google Wallet, the following steps occur to complete the digitization.
Please remember that your Wallet Provider integration must be certified by Apple Pay and Google Pay, and that Treezor isn’t involved in those steps.
### Flow
The flow can be simplified into 3 main steps:
1. [**Requesting credentials**](#requesting-credentials) – Request your credentials from Treezor
2. [**Requesting cryptogram**](#requesting-cryptogram) – Use the credentials to request your cryptogram from Treezor
3. [**Digitization request**](#digitization-request) – Use the cryptogram to request tokenization from the Wallet Provider
Here is a more detailed sequence diagram.
```mermaid
sequenceDiagram
participant You
participant Token Provider
participant Treezor
You->>Treezor: Requests Digitization Credentials from server POST /v1/issuerInitiatedDigitizationDatas
Treezor->>Treezor: Generates IssuerInitiatedDigitizationData
Treezor->>You: IssuerInitiatedDigitizationData (with credentials)
You->>Treezor: Request cryptogram (TAV) from mobile application using credentials (uuid)
Treezor->>You: Sends cryptogram (TAV)
You->>Token Provider: Requests digitization using TAV from mobile application
Token Provider->>Treezor: Sends TAR
Treezor-->>You: Sends `cardDigitalization.request` webhook
Token Provider->>Token Provider: Digitizes the card (DPAN) and sends it to the Wallet Provider
Token Provider->>Treezor: Sends TCN
Treezor-->>You: Sends `cardDigitalizations.complete` webhook
```
### Authorization messages & webhooks
Treezor handles the following authorization messages during the tokenization process.
| Message | Description | Webhook |
|------------------|-------------|---------|
| [Account Status Inquiry (ASI)](/guide/overview/glossary#account-status-inquiry-asi) | Ensures the card exists. | N/A |
| [Tokenization Authorization Request (TAR)](/guide/overview/glossary#tokenization-authorization-request-tar) | Ensures the card is compatible with X-Pay. | [`cardDigitalization.request`](./events#carddigitalization-request) |
| [Tokenization Complete Notification (TCN)](/guide/overview/glossary#tokenization-complete-notification-tcn) | Confirms the digitization of the card. | [`cardDigitalization.complete`](./events#carddigitalization-complete) |
### Requesting credentials
The credentials request requires at least the `cardId` and `tokenRequestor` parameters.
Please note the card musn't be in a [permanent locked status](./introduction#card-status-statuscode), and that additional information may be necessary for Apple Pay.
Endpoint: [`/issuerInitiatedDigitizationDatas`](/api-reference/api-endpoints.html#tag/issuerInitiatedDigitizationData/tavRequestPOST){target="\_self"}
```bash [CURL]
curl -X POST '{baseUrl}/v1/issuerInitiatedDigitizationDatas' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
If you have migrated to the [PCI DSS services](./pci-dss), then you must use the following endpoints instead:
* [`/cards/{cardId}/inappcryptogram/mastercard/apple-pay`](/api-reference/pci-dss-dev.html#tag/Cards/postInappApple){target="\_self"}
* [`/cards/{cardId}/inappcryptogram/mastercard/google-pay`](/api-reference/pci-dss-dev.html#tag/Cards/postInappGpay){target="\_self"}
* [`/cards/{cardId}/inappcryptogram/visa/apple-pay`](/api-reference/pci-dss-dev.html#tag/Cards/postVisaInappApple){target="\_self"}
* [`/cards/{cardId}/inappcryptogram/visa/google-pay`](/api-reference/pci-dss-dev.html#tag/Cards/postVisaInappGpay){target="\_self"}
Here is a `{payload}` example:
```json [JSON]
{
"cardId": 0,
"tokenRequestor": "APPLE", // or GOOGLE
"additionnalData": // required for Apple Pay only
{
"certificates": [
"string"
],
"nonce": "string",
"nonceSignature": "string"
}
}
```
Returns the `issuerInitiatedDigitizationDatas` object, along with the `credential` necessary for the next step.
```json [JSON] {7}
{
"issuerInitiatedDigitizationDatas": [
{
"id": 0,
"cardId": 0,
"statusId": 0,
"credential": "string",
"additionnalData": [
"string"
],
"tokenRequestor": "string",
"createdDate": "string",
"modifiedDate": "string"
}
]
}
```
### Requesting cryptogram
To retrieve your cryptogram ([TAV](/guide/overview/glossary#tokenization-authentication-value-tav)), the following request is sent from the end user's device. Contact your *Treezor Implementation Manager* for the `{specificURL}`.
```bash [CURL]
curl -X GET '{specificURL}/issuerInitiatedDigitizationData' \
-d '"credential"="{credential}"'
```
Returns the base64-encoded TAV.
### Digitization request
The digitization request is made with the obtained [TAV](/guide/overview/glossary#tokenization-authentication-value-tav), from the end user's device. This request isn't made with Treezor API but the Wallet Provider.
Depending on the Wallet Provider, you may need to either send the [TAV](/guide/overview/glossary#tokenization-authentication-value-tav) as received (base64 encoded) or decoded in the form of a JSON object. Please refer to the documentation shared with you by your *Treezor Implementation Manager* for more information.
## Merchant-initiated tokenization
It is not uncommon for merchants to tokenize their customers’ card on their websites, hence saving the card information securely for future payments.
The merchant-initiated request to tokenize the PAN of their consumers results in a token that can only be used by the merchant who initiated the request.
**Information – Mandatory feature for all X-Pay subscribers**
While Merchant-initiated tokenization isn’t directly related to X-Pay, it is a mandatory functionality set by the Token Providers.
* While the transaction is made
* When a new card is added to the customer’s profile
* Per customer request, for any card attached to their profile
When such a tokenization scenario occurs, Treezor informs you with the [`cardDigitalization.complete`](./events#carddigitalization-complete) webhook, which also contains information about the Merchant who digitized the card.
The token created can be used for the transaction and any transaction that might occur in the future, as long as the same PAN is used.
### Flow
```mermaid
sequenceDiagram
participant Merchant
participant Treezor
participant You
Merchant->>Merchant: Initiates Tokenization process with Token Provider
Merchant->>Treezor: Sends ASI
Merchant->>Treezor: Sends TAR
Treezor->>You: `cardDigitalization.request` webhook
Merchant->>Treezor: Sends TCN
Treezor->>Treezor: Stores token-related information
Treezor->>You: Sends `cardDigitalization.complete` webhook Which includes the merchant who initiated the digitization
```
### Authorization messages & webhooks
Treezor handles the following authorization messages from the merchant during the tokenization process.
| Merchant message | Description | Webhook |
|------------------|-------------|---------|
| [Account Status Inquiry (ASI)](/guide/overview/glossary#account-status-inquiry-asi) | Ensures the card exists. | N/A |
| [Tokenization Authorization Request (TAR)](/guide/overview/glossary#tokenization-authorization-request-tar) | Ensures the card is compatible with X-Pay. | [`cardDigitalization.request`](./events#carddigitalization-request) |
| [Tokenization Complete Notification (TCN)](/guide/overview/glossary#tokenization-complete-notification-tcn) | Confirms the digitization of the card. | [`cardDigitalization.complete`](./events#carddigitalization-complete) |
## Token lifecycle
Once the digitization complete and the token active, the [DPAN](/guide/overview/glossary#device-primary-account-number-dpan) can be suspended if need be, and deactivated once no longer in use.
Please note that the digitized card [`statuses`](#statuses-status) are independent of the card's. When [blocking a card](./modification#block-a-card), it is your responsibility to ensure the card token is deactivated as well.
However, if you're using the most recent services for card digitization, when the card status is set to `DESTROYED` or `EXPIRED`, Treezor automatically sets the corresponding card tokens to deactivated (`X`).
### Updating the Card Token
You can suspend and unsuspend the digitized card token with the dedicated endpoint.
#### Parameters
| Attribute | Type | Description |
| --- | --- | --- |
| `id` | query | The unique identifier of a digitized card. You can find this value in: [`/v1/cards/{cardId}/digitalizedCards`](/api-reference/api-endpoints.html#tag/Digitized%20Cards){target="\_self"}, `id` field, or[`cardDigitalization.complete`](/guide/cards/events.html#carddigitalization-complete) webhook, `object_id` field. |
| `status` | string | Can take the following values: `unsuspend` – Removes the suspension`suspend` – Suspends the payment token |
| `reasonCode` | string | Can take the following values with `suspend`: `L` – Cardholder suspects token **device lost**`S` – Cardholder suspects token **device stolen**`T` – Issuer or cardholder suspects **fraudulent** token transactions`Z` – OtherCan take the following values with `unsuspend`: `F` – Cardholder reported token **device found or not stolen**`T` – Issuer or cardholder confirmed **no fraudulent** token transactions`Z` – Other|
#### Request example
Endpoint: [`/v1/cards/digitalizedCards/{id}`](/api-reference/api-endpoints.html#tag/Digitized%20Cards/putDigitalized){target="\_self"}
```bash [CURL]
curl -X PUT '{baseUrl}/v1/cards/digitalizedCards/{id}' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON] {6}
{
"status": "suspend",
"reasonCode": "L"
}
```
Returns the digitized card object, with the `status` set to `S`.
```json [JSON] {6}
{
"cardId": "12345",
"createdDate": "2025-01-19 14:30:45",
"id": "1234567",
"modifiedDate": "2025-02-19 14:30:45",
"status": "S"
}
```
Treezor also sends the [`cardDigitalization.update`](./events#carddigitalization-update) webhook.
### Deactivating the Card Token
The token must be deactivated if the cardholder is `CANCELED` and/or the card is in a [permanent locked status](./introduction#card-status-statuscode).
If you're using the most recent services for card digitization, token deactivation is triggered:
* **By Treezor** – When the card reaches the `EXPIRED` or `DESTROYED` status.
* **By you** – If the card is declared `LOST` or `STOLEN`. This allows you to let the cardholder use their digitized card until they receive their new one for instance.
Use the following request to deactivate the token, with the [`reasonCode`](#reason-codes-reasoncode) as a query parameter (for the Mastercard scheme only).
#### Request example
Endpoint: [`/v1/cards/digitalizedCards/{id}`](/api-reference/api-endpoints.html#tag/Digitized%20Cards/deleteDigitalized){target="\_self"}
```bash [CURL]
curl -X DELETE '{baseUrl}/v1/cards/digitalizedCards/{id}?reasonCode={C}' \
--header 'Authorization: Bearer {accessToken}'
```
Returns the digitized card object, with the `status` set to `X`.
```json [JSON] {6}
{
"cardId": "12345",
"createdDate": "2025-01-19 14:30:45",
"id": "1234567",
"modifiedDate": "2025-02-19 14:30:45",
"status": "X"
}
```
Treezor also sends the [`cardDigitalization.deactivated`](./events#carddigitalization-deactivated) webhook.
## Digitized card object
```json [JSON]
{
"activationMethod": "TEXT_TO_CARDHOLDER_NUMBER",
"cardDigitalizationExternalId": "12345",
"cardId": "12345",
"createdDate": "2025-02-19 14:30:45",
"deviceId": "987654",
"deviceName": "Chris' iPhone",
"deviceType": "M",
"expirationDate": "2025-02-19 14:30:45",
"id": "1234567",
"merchantName": "…",
"modifiedDate": "2025-02-19 14:30:45",
"status": "A",
"tokenRequestor": "APPLE",
"tokenUniqueReference": "…"
}
```
### Statuses (`status`)
| Value | Status | Description |
| :---: | ------ | ----- |
| `A` | Active | Initial status of your DPAN upon card digitization. |
| `S` | Suspended | DPAN suspended (card stolen, lost, or declared fraudulent). |
| `X` | Deactivated | DPAN deactivated (e.g., card expired). |
| `I` | Inactive | This is for Visa Scheme only. |
**Information – You can't suspend/unsuspend tokens with a `U` legacy status**
Such attempts generate an HTTP `400` error. Please note that you can deactivate such tokens with the [`/v1/cards/digitalizedCards/{id}`](/api-reference/api-endpoints.html#tag/Digitized%20Cards/deleteDigitalized){target="\_self"} request.
### Reason codes (`reasonCode`)
| Reason code | Description |
| :----: | ----------- |
| `C` | Account closed |
| `D` | Issuer consumer deleted |
| `F` | Cardholder reported token device found or not stolen |
| `L` | Cardholder confirmed token device lost |
| `S` | Cardholder confirmed token device stolen |
| `T` | Issuer or cardholder confirmed fraudulent token transactions |
| `Z` | Other |
### Device types (`deviceType`)
| Value | Description |
|:---:|---|
| `A` | Clothing or apparel |
| `B` | Media or Gaming device, e.g., Xbox, TV, set-top box |
| `C` | Card |
| `D` | Domestic application, e.g., fridge, washing machine |
| `F` | Fob or key-fob |
| `G` | Mobile tag, case, or sleeve |
| `H` | Fashion accessory, e.g., purse, glasses |
| `J` | Jewelry, e.g., necklace, rings, bracelets |
| `M` | Mobile phone |
| `P` | Personal computer or laptop |
| `R` | Wristband (no further detail.). Possibly includes rings too |
| `S` | Sticker |
| `T` | Tablet |
| `U` | Unknown |
| `V` | Vehicle |
| `W` | Watch |
| `X` | Mobile phone or tablet (sender unclear) |
### Activation methods (`activationMethod`)
| Value | Description |
|- |- |
| `TEXT_TO_CARDHOLDER_NUMBER` | Text message to the cardholder’s mobile phone number. |
| `EMAIL_TO_CARDHOLDER_ADDRESS` | Email to cardholder’s email address. |
| `CARDHOLDER_TO_CALL_AUTOMATED_NUMBER` | Cardholder-initiated call to automated call center phone number. |
| `CARDHOLDER_TO_CALL_MANNED_NUMBER` | Cardholder-initiated call to manned call center phone number. |
| `CARDHOLDER_TO_VISIT_WEBSITE` | Cardholder to visit a website. |
| `CARDHOLDER_TO_USE_MOBILE_APP` | Cardholder to use a specific mobile app to activate token. |
| `ISSUER_TO_CALL_CARDHOLDER_NUMBER` | Issuer-initiated voice call to cardholder’s phone. |
## Endpoints
**Information – Connection to services in Production only**
There is no connection to Google Pay or Apple Pay services in Sandbox. Endpoints are available for technical testing only.
| Endpoint | [Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/issuerInitiatedDigitizationDatas`](/api-reference/api-endpoints.html#tag/issuerInitiatedDigitizationData/tavRequestPOST){target="\_self"} Request the issuerInitiatedDigitizationDatas | `read_write` |
| [`/v1/cards/{cardId}/digitalizedCards`](/api-reference/api-endpoints.html#tag/Digitized%20Cards){target="\_self"} List digitalized cards for a given `cardId` | `read_only` |
| [`/v1/cards/digitalizedCards/{id}`](/api-reference/api-endpoints.html#tag/Digitized%20Cards/getPaymentToken){target="\_self"} Retrieve a payment token | `read_only` |
| [`/v1/cards/digitalizedCards/{id}`](/api-reference/api-endpoints.html#tag/Digitized%20Cards/putDigitalized){target="\_self"} Update a payment token status | `read_write` |
| [`/v1/cards/digitalizedCards/{id}`](/api-reference/api-endpoints.html#tag/Digitized%20Cards/deleteDigitalized){target="\_self"} Deactivate a payment token | `read_write` |
| Endpoint | [Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/cardDigitalizations`](/api-reference/api-endpoints.html#tag/cardDigitalizations/readcardDigitalizations){target="\_self"} Search for Card Digitalizations | `read_only` |
| [`/cardDigitalizations/{cardDigitalizationId}`](/api-reference/api-endpoints.html#tag/cardDigitalizations/cardDigitalizationsId){target="\_self"} Retrieve a Card Digitalization | `read_only` |
| [`/cardDigitalizations/{cardDigitalizationId}`](/api-reference/api-endpoints.html#tag/cardDigitalizations/putcardDigitalizationsId){target="\_self"} Update the status of a payment Token | `read_write` |
| [`/cardDigitalizations/{cardDigitalizationId}`](/api-reference/api-endpoints.html#tag/cardDigitalizations/deletecardDigitalizationsId){target="\_self"} Delete a payment Token | `read_write` |
---
---
url: /guide/cards/events.md
description: >-
Reference a comprehensive list of card events for Treezor API webhooks,
detailing each event's structure and payload for integration.
---
# Events
This article lists the [Webhooks](/guide/webhooks/introduction) you may receive when issuing Cards.
## Card events
### `card.requestphysical`
```json [JSON]
{
"webhook": "card.requestphysical",
"object": "card",
"object_id": "999990081",
"object_payload": {
"cards": [
{
"cardId": "999990081",
"userId": "100642533",
"walletId": "3135941",
"walletCardtransactionId": "3143087",
"mccRestrictionGroupId": null,
"merchantRestrictionGroupId": null,
"countryRestrictionGroupId": null,
"eventName": "Main account",
"eventAlias": "main-account-669697986861c",
"publicToken": "110662949",
"cardTag": "",
"statusCode": "UNLOCK",
"isLive": "0",
"pinTryExceeds": "0",
"maskedPan": "548821******3691",
"embossedName": "ALEX OAK",
"expiryDate": "2027-07-31",
"CVV": "971",
"startDate": "2024-07-24",
"endDate": "0000-00-00",
"countryCode": "FR",
"currencyCode": "EUR",
"deliveryTitle": "M",
"deliveryLastname": "OAK",
"deliveryFirstname": "ALEX",
"deliveryAddress1": "07323 cedar hills",
"deliveryAddress2": "",
"deliveryAddress3": "",
"deliveryCity": "PARIS",
"deliveryPostcode": "75000",
"deliveryCountry": "FR",
"mobileSent": "+33123456789",
"limitsGroup": "TRZ-VL-001",
"permsGroup": "TRZ-CU-016",
"cardDesign": "14708",
"virtualConverted": "0",
"optionAtm": "1",
"optionForeign": "1",
"optionOnline": "1",
"optionNfc": "1",
"limitAtmYear": "0",
"limitAtmMonth": "0",
"limitAtmWeek": "2000",
"limitAtmDay": "1000",
"limitAtmAll": "0",
"limitPaymentYear": "0",
"limitPaymentMonth": "0",
"limitPaymentWeek": "3000",
"limitPaymentDay": "2000",
"paymentDailyLimit": "0.00",
"restrictionGroupLimits": null,
"limitPaymentAll": "0",
"totalAtmYear": "0",
"totalAtmMonth": "0",
"totalAtmWeek": null,
"totalAtmDay": null,
"totalAtmAll": "0",
"totalPaymentYear": "0",
"totalPaymentMonth": "0",
"totalPaymentWeek": null,
"totalPaymentDay": null,
"totalPaymentAll": "0",
"createdBy": "929252",
"createdDate": "2024-07-18 12:54:28",
"modifiedBy": "0",
"modifiedDate": "0000-00-00 00:00:00",
"cancellationNumber": null,
"physical": "1",
"logoId": "",
"logoBackId": "",
"packageId": "",
"customizedInfo": null,
"letterCustomizedInfo": "",
"freeCustomizedInfo": "",
"deliveryMethod": "1",
"pinMailer": "1",
"batchDeliveryId": "1",
"sendToParent": "1",
"isTemporary": false
}
]
},
"webhook_created_at": 17213000682093,
"webhook_id": "056b1e6d-17b3-4796-89e0-653f3cxxxx03",
"object_payload_signature": "wqGsyqDmHOnkrkyY/mjf+AuWeTlaxhraUxxxxxwMGs="
}
```
### `card.createvirtual`
### `card.convertvirtual`
### `card.changepin`
### `card.activate`
### `card.renew`
```json [JSON]
{
"webhook": "card.renew",
"webhook_id": "2xxxxxx8",
"object": "card",
"object_id": "6xxx6",
"object_payload": {
"cards": [
{
"cardId": "100003123",
"userId": "3075987",
"walletId": "3397876",
"walletCardtransactionId": "123456",
"mccRestrictionGroupId": null,
"merchantRestrictionGroupId": null,
"countryRestrictionGroupId": null,
"eventName": "Wallet",
"eventAlias": "xxxxxx-wallet-5fe1208c2d47e",
"publicToken": "332945545",
"cardTag": "d42d0082-7bac-47be-b219-2975aed12345",
"statusCode": "UNLOCK",
"isLive": "0",
"pinTryExceeds": "0",
"maskedPan": "123456******1234",
"embossedName": "Alex Oak",
"expiryDate": "2026-12-31",
"CVV": "123",
"startDate": "2020-12-20",
"endDate": "0000-00-00",
"countryCode": "FR",
"currencyCode": "EUR",
"deliveryTitle": "M",
"deliveryLastname": "ALEX",
"deliveryFirstname": "OAK",
"deliveryAddress1": "12 Rosewood Road",
"deliveryAddress2": "",
"deliveryAddress3": "",
"deliveryCity": "PARIS",
"deliveryPostcode": "75000",
"deliveryCountry": "FRA",
"mobileSent": "0033333333333",
"limitsGroup": "TRZ-VL-001",
"permsGroup": "TRZ-CU-015",
"cardDesign": "5996",
"virtualConverted": "1",
"optionAtm": "1",
"optionForeign": "0",
"optionOnline": "1",
"optionNfc": "1",
"limitAtmYear": "0",
"limitAtmMonth": "1000",
"limitAtmWeek": "300",
"limitAtmDay": "1000",
"limitAtmAll": "0",
"limitPaymentYear": "0",
"limitPaymentMonth": "1600",
"limitPaymentWeek": "1000",
"limitPaymentDay": "2000",
"paymentDailyLimit": "0.00",
"restrictionGroupLimits": null,
"limitPaymentAll": "0",
"totalAtmYear": "0",
"totalAtmMonth": null,
"totalAtmWeek": null,
"totalAtmDay": null,
"totalAtmAll": "0",
"totalPaymentYear": "0",
"totalPaymentMonth": null,
"totalPaymentWeek": null,
"totalPaymentDay": null,
"totalPaymentAll": "0",
"createdBy": "372837",
"createdDate": "2023-12-18 00:00:00",
"modifiedBy": "0",
"modifiedDate": "0000-00-00 00:00:00",
"cancellationNumber": null,
"physical": "0",
"logoId": "",
"logoBackId": "",
"packageId": "",
"customizedInfo": null,
"letterCustomizedInfo": "",
"freeCustomizedInfo": "",
"deliveryMethod": "1",
"pinMailer": "1",
"batchDeliveryId": "1",
"sendToParent": "1",
"isTemporary": false
}
]
},
"object_payload_signature": "o4tf+JC0PbJ1t9kjg2PRr2xE7xh3Am/12345678abcA="
}
```
### `card.update`
Treezor sends this webhook when:
* The card is updated using the dedicated endpoint or
* When one of the following cardholder's field is updated at the User object level: `title`, `firstname`, `lastname`, `email`, `address1`, `address2`, `postcode`, `city`, `country`, `phone`, `mobile`, or `language`.
```json [JSON]
{
"webhook": "card.update",
"object": "card",
"object_id": "999925786",
"object_payload": {
"cards": [
{
"cardId": "999925786",
"userId": "100549108",
"walletId": "3011794",
"walletCardtransactionId": "3012053",
"mccRestrictionGroupId": "48203",
"merchantRestrictionGroupId": "107454",
"countryRestrictionGroupId": "183120",
"eventName": "Main account",
"eventAlias": "main-account-6670280a28c2c",
"publicToken": "105618829",
"cardTag": "Updated cardTag",
"statusCode": "UNLOCK",
"isLive": "1",
"pinTryExceeds": "0",
"maskedPan": "548821******0226",
"embossedName": "ALEX OAK",
"expiryDate": "2024-06-18",
"CVV": "740",
"startDate": "2024-06-24",
"endDate": "2024-06-17",
"countryCode": "FR",
"currencyCode": "EUR",
"deliveryTitle": "M",
"deliveryLastname": "OAK",
"deliveryFirstname": "ALEX",
"deliveryAddress1": "30217 CRUICKSHANK SPRINGS",
"deliveryAddress2": "",
"deliveryAddress3": "",
"deliveryCity": "VERSAILLES",
"deliveryPostcode": "78000",
"deliveryCountry": "FR",
"mobileSent": "+33141358530",
"limitsGroup": "TRZ-VL-001",
"permsGroup": "TRZ-CU-016",
"cardDesign": "8529",
"virtualConverted": "1",
"optionAtm": "1",
"optionForeign": "1",
"optionOnline": "1",
"optionNfc": "1",
"limitAtmYear": "2000",
"limitAtmMonth": "2000",
"limitAtmWeek": "2000",
"limitAtmDay": "1000",
"limitAtmAll": "0",
"limitPaymentYear": "5000",
"limitPaymentMonth": "0",
"limitPaymentWeek": "3000",
"limitPaymentDay": "2000",
"paymentDailyLimit": "500.00",
"restrictionGroupLimits": null,
"limitPaymentAll": "0",
"totalAtmYear": null,
"totalAtmMonth": null,
"totalAtmWeek": null,
"totalAtmDay": null,
"totalAtmAll": "0",
"totalPaymentYear": "0.00",
"totalPaymentMonth": "0",
"totalPaymentWeek": null,
"totalPaymentDay": null,
"totalPaymentAll": "0",
"createdBy": "929252",
"createdDate": "2024-06-17 14:43:54",
"modifiedBy": "929252",
"modifiedDate": "2024-07-18 14:07:33",
"cancellationNumber": null,
"physical": "0",
"logoId": "",
"logoBackId": "",
"packageId": "",
"customizedInfo": null,
"letterCustomizedInfo": "",
"freeCustomizedInfo": "",
"deliveryMethod": "1",
"pinMailer": "1",
"batchDeliveryId": "1",
"sendToParent": "1",
"isTemporary": false
}
]
},
"webhook_created_at": 17213044534278,
"webhook_id": "6b0aee69-87c8-45df-a0d9-42xxxx9f38b",
"object_payload_signature": "WTFf7nbDnCoT6EVMRaTTTSHkA87BxxxxxdPCU30Usmo="
}
```
### `card.limits`
```json [JSON]
{
"webhook": "card.limits",
"object": "card",
"object_id": "999990082",
"object_payload": {
"cards": [
{
"cardId": "999990082",
"userId": "100642533",
"walletId": "3135941",
"walletCardtransactionId": "3143122",
"mccRestrictionGroupId": null,
"merchantRestrictionGroupId": null,
"countryRestrictionGroupId": null,
"eventName": "Main account",
"eventAlias": "main-account-669697986861c",
"publicToken": "105603885",
"cardTag": "sky blue",
"statusCode": "UNLOCK",
"isLive": "1",
"pinTryExceeds": "0",
"maskedPan": "548821******6470",
"embossedName": "ALEX OAK",
"expiryDate": "2027-07-31",
"CVV": "582",
"startDate": "2024-07-24",
"endDate": "0000-00-00",
"countryCode": "FR",
"currencyCode": "EUR",
"deliveryTitle": "M",
"deliveryLastname": "OAK",
"deliveryFirstname": "ALEX",
"deliveryAddress1": "07323 SIPES SHOALS",
"deliveryAddress2": "",
"deliveryAddress3": "",
"deliveryCity": "PARIS",
"deliveryPostcode": "75017",
"deliveryCountry": "FR",
"mobileSent": "+33141358530",
"limitsGroup": "TRZ-VL-001",
"permsGroup": "TRZ-CU-012",
"cardDesign": "8529",
"virtualConverted": "0",
"optionAtm": "0",
"optionForeign": "1",
"optionOnline": "1",
"optionNfc": "1",
"limitAtmYear": "2000",
"limitAtmMonth": "2000",
"limitAtmWeek": "2000",
"limitAtmDay": "1000",
"limitAtmAll": "0",
"limitPaymentYear": "5000",
"limitPaymentMonth": "0",
"limitPaymentWeek": "3000",
"limitPaymentDay": "2000",
"paymentDailyLimit": "500.00",
"restrictionGroupLimits": null,
"limitPaymentAll": "0",
"totalAtmYear": null,
"totalAtmMonth": null,
"totalAtmWeek": null,
"totalAtmDay": null,
"totalAtmAll": "0",
"totalPaymentYear": null,
"totalPaymentMonth": "0",
"totalPaymentWeek": null,
"totalPaymentDay": null,
"totalPaymentAll": "0",
"createdBy": "929252",
"createdDate": "2024-07-18 14:10:51",
"modifiedBy": "929252",
"modifiedDate": "2024-07-18 14:10:57",
"cancellationNumber": null,
"physical": "0",
"logoId": "",
"logoBackId": "",
"packageId": "",
"customizedInfo": null,
"letterCustomizedInfo": "",
"freeCustomizedInfo": "",
"deliveryMethod": "1",
"pinMailer": "1",
"batchDeliveryId": "1",
"sendToParent": "1",
"isTemporary": false
}
]
},
"webhook_created_at": 17213046655230,
"webhook_id": "09cc975d-d9f8-4a61-a85d-c027022xx9e5",
"object_payload_signature": "zXK+EMoIk88fQ4xxxxxJaMhS9RPDteRAifLZxF8fd8="
}
```
### `card.options`
```json [JSON]
{
"webhook": "card.options",
"object": "card",
"object_id": "999990082",
"object_payload": {
"cards": [
{
"cardId": "999990082",
"userId": "100642533",
"walletId": "3135941",
"walletCardtransactionId": "3143122",
"mccRestrictionGroupId": null,
"merchantRestrictionGroupId": null,
"countryRestrictionGroupId": null,
"eventName": "Main account",
"eventAlias": "name-of-the-wallet-669697986861c",
"publicToken": "105603885",
"cardTag": "sky blue",
"statusCode": "UNLOCK",
"isLive": "1",
"pinTryExceeds": "0",
"maskedPan": "548821******6470",
"embossedName": "ALEX OAK",
"expiryDate": "2027-07-31",
"CVV": "582",
"startDate": "2024-07-24",
"endDate": "0000-00-00",
"countryCode": "FR",
"currencyCode": "EUR",
"deliveryTitle": "M",
"deliveryLastname": "OAK",
"deliveryFirstname": "ALEX",
"deliveryAddress1": "07323 SIPES SHOALS",
"deliveryAddress2": "",
"deliveryAddress3": "",
"deliveryCity": "PARIS",
"deliveryPostcode": "75017",
"deliveryCountry": "FR",
"mobileSent": "+33141358530",
"limitsGroup": "TRZ-VL-001",
"permsGroup": "TRZ-CU-016",
"cardDesign": "8529",
"virtualConverted": "0",
"optionAtm": "1",
"optionForeign": "1",
"optionOnline": "1",
"optionNfc": "1",
"limitAtmYear": "2000",
"limitAtmMonth": "2000",
"limitAtmWeek": "2000",
"limitAtmDay": "1000",
"limitAtmAll": "0",
"limitPaymentYear": "5000",
"limitPaymentMonth": "0",
"limitPaymentWeek": "3000",
"limitPaymentDay": "2000",
"paymentDailyLimit": "500.00",
"restrictionGroupLimits": null,
"limitPaymentAll": "0",
"totalAtmYear": null,
"totalAtmMonth": null,
"totalAtmWeek": null,
"totalAtmDay": null,
"totalAtmAll": "0",
"totalPaymentYear": null,
"totalPaymentMonth": "0",
"totalPaymentWeek": null,
"totalPaymentDay": null,
"totalPaymentAll": "0",
"createdBy": "929252",
"createdDate": "2024-07-18 14:10:51",
"modifiedBy": "929252",
"modifiedDate": "2024-07-18 14:13:03",
"cancellationNumber": null,
"physical": "0",
"logoId": "",
"logoBackId": "",
"packageId": "",
"customizedInfo": null,
"letterCustomizedInfo": "",
"freeCustomizedInfo": "",
"deliveryMethod": "1",
"pinMailer": "1",
"batchDeliveryId": "1",
"sendToParent": "1",
"isTemporary": false
}
]
},
"webhook_created_at": 17213047836871,
"webhook_id": "54517817-3ec9-4c65-8f56-0a9xxb2e68c",
"object_payload_signature": "6/pvFUoCdhyrhidvC2j+YihNZF9E0exxxxpEiDu72E="
}
```
### `card.assignwallet`
```json [JSON]
{
"webhook": "card.assignwallet",
"object": "card",
"object_id": "999925786",
"object_payload": {
"cards": [
{
"cardId": "999925786",
"userId": "100549108",
"walletId": "3011794",
"walletCardtransactionId": "3012053",
"mccRestrictionGroupId": "48203",
"merchantRestrictionGroupId": "107454",
"countryRestrictionGroupId": "183120",
"eventName": "Main account",
"eventAlias": "main-account-6670280a28c2c",
"publicToken": "105618829",
"cardTag": "Updated cardTag",
"statusCode": "UNLOCK",
"isLive": "1",
"pinTryExceeds": "0",
"maskedPan": "548821******0226",
"embossedName": "ALEX OAK",
"expiryDate": "2024-06-18",
"CVV": "740",
"startDate": "2024-06-24",
"endDate": "2024-06-17",
"countryCode": "FR",
"currencyCode": "EUR",
"deliveryTitle": "M",
"deliveryLastname": "OAK",
"deliveryFirstname": "ALEX",
"deliveryAddress1": "30217 CRUICKSHANK SPRINGS",
"deliveryAddress2": "",
"deliveryAddress3": "",
"deliveryCity": "VERSAILLES",
"deliveryPostcode": "78000",
"deliveryCountry": "FR",
"mobileSent": "+33141358530",
"limitsGroup": "TRZ-VL-001",
"permsGroup": "TRZ-CU-016",
"cardDesign": "8529",
"virtualConverted": "1",
"optionAtm": "1",
"optionForeign": "1",
"optionOnline": "1",
"optionNfc": "1",
"limitAtmYear": "2000",
"limitAtmMonth": "2000",
"limitAtmWeek": "2000",
"limitAtmDay": "1000",
"limitAtmAll": "0",
"limitPaymentYear": "5000",
"limitPaymentMonth": "0",
"limitPaymentWeek": "3000",
"limitPaymentDay": "2000",
"paymentDailyLimit": "500.00",
"restrictionGroupLimits": null,
"limitPaymentAll": "0",
"totalAtmYear": null,
"totalAtmMonth": null,
"totalAtmWeek": null,
"totalAtmDay": null,
"totalAtmAll": "0",
"totalPaymentYear": "0.00",
"totalPaymentMonth": "0",
"totalPaymentWeek": null,
"totalPaymentDay": null,
"totalPaymentAll": "0",
"createdBy": "929252",
"createdDate": "2024-06-17 14:43:54",
"modifiedBy": "929252",
"modifiedDate": "2024-07-18 14:07:33",
"cancellationNumber": null,
"physical": "0",
"logoId": "",
"logoBackId": "",
"packageId": "",
"customizedInfo": null,
"letterCustomizedInfo": "",
"freeCustomizedInfo": "",
"deliveryMethod": "1",
"pinMailer": "1",
"batchDeliveryId": "1",
"sendToParent": "1",
"isTemporary": false
}
]
},
"webhook_created_at": 17213044534278,
"webhook_id": "6b0aee69-87c8-45df-a0d9-42xxxx9f38b",
"object_payload_signature": "WTFf7nbDnCoT6EVMRaTTTSHkA87BxxxxxdPCU30Usmo="
}
```
### `card.setpin`
### `card.unblockpin`
```json [JSON]
{
"webhook": "card.unblockpin",
"webhook_id": "2xxxxxx0",
"object": "card",
"object_id": "6xxx3",
"object_payload": {
"cards": [
{
"cardId": "6xxx3",
"userId": "1xxxxx3",
"walletId": "8xxxx5",
"walletCardtransactionId": "8xxxx2",
"pinTryExceeds": "0",
// [...] some attributes are hidden
}
]
},
"object_payload_signature": "LnYAh2rE9DMTbDqjkM/p5Ks05cck85Vk8j05xfvLGBc="
}
```
### `card.unblockcvc2`
```json [JSON]
{
"webhook": "card.unblockcvc2",
"object": "card",
"object_id": "999988610",
"object_payload": {
"cards": [
{
"cardId": "999988610",
"userId": "100640138",
"walletId": "3137125",
"walletCardtransactionId": "3137126",
"mccRestrictionGroupId": null,
"merchantRestrictionGroupId": null,
"countryRestrictionGroupId": null,
"eventName": "Main account",
"eventAlias": "main-account-669754fea40f1",
"publicToken": "105592812",
"cardTag": "",
"statusCode": "UNLOCK",
"isLive": "1",
"pinTryExceeds": "0",
"maskedPan": "548821******2232",
"embossedName": "ALEX OAK",
"expiryDate": "2027-07-31",
"CVV": "790",
"startDate": "2024-07-24",
"endDate": "0000-00-00",
"countryCode": "FR",
"currencyCode": "EUR",
"deliveryTitle": "M",
"deliveryLastname": "ALEX",
"deliveryFirstname": "OAK",
"deliveryAddress1": "TES23 cedar hills",
"deliveryAddress2": "",
"deliveryAddress3": "",
"deliveryCity": "PARIS",
"deliveryPostcode": "75000",
"deliveryCountry": "FR",
"mobileSent": "+33612345678",
"limitsGroup": "TRZ-VL-001",
"permsGroup": "TRZ-CU-015",
"cardDesign": "8529",
"virtualConverted": "0",
"optionAtm": "1",
"optionForeign": "0",
"optionOnline": "1",
"optionNfc": "1",
"limitAtmYear": "2000",
"limitAtmMonth": "2000",
"limitAtmWeek": "1000",
"limitAtmDay": "500",
"limitAtmAll": "5000",
"limitPaymentYear": "10000",
"limitPaymentMonth": "5000",
"limitPaymentWeek": "3000",
"limitPaymentDay": "1000",
"paymentDailyLimit": "2000.00",
"restrictionGroupLimits": [
{
"merchantIdRestrictionGroups": 94748,
"paymentDailyLimit": 0.01
}
],
"limitPaymentAll": "30000",
"totalAtmYear": null,
"totalAtmMonth": null,
"totalAtmWeek": null,
"totalAtmDay": null,
"totalAtmAll": null,
"totalPaymentYear": null,
"totalPaymentMonth": null,
"totalPaymentWeek": null,
"totalPaymentDay": null,
"totalPaymentAll": null,
"createdBy": "929252",
"createdDate": "2024-07-17 07:22:08",
"modifiedBy": "929252",
"modifiedDate": "2024-07-18 13:15:21",
"cancellationNumber": null,
"physical": "0",
"logoId": "",
"logoBackId": "",
"packageId": "",
"customizedInfo": null,
"letterCustomizedInfo": "",
"freeCustomizedInfo": "",
"deliveryMethod": "1",
"pinMailer": "1",
"batchDeliveryId": "1",
"sendToParent": "1",
"isTemporary": false
}
]
},
"webhook_created_at": 17213013210351,
"webhook_id": "755c4496-ad53-4a29-9d27-2d9xxxx5b0f",
"object_payload_signature": "5hPGRs+h6eF+Un2VIUJ/V5KFlN4CxxxcjmDHxh0gLQU="
}
```
### `card.lockunlock`
```json [JSON]
{
"webhook": "card.lockunlock",
"object": "card",
"object_id": "999988610",
"object_payload": {
"cards": [
{
"cardId": "999988610",
"userId": "100640138",
"walletId": "3137125",
"walletCardtransactionId": "3137126",
"mccRestrictionGroupId": null,
"merchantRestrictionGroupId": null,
"countryRestrictionGroupId": null,
"eventName": "Main account",
"eventAlias": "main-account-669754fea40f1",
"publicToken": "105592812",
"cardTag": "",
"statusCode": "LOCK",
"isLive": "1",
"pinTryExceeds": "0",
"maskedPan": "548821******2232",
"embossedName": "ALEX OAK",
"expiryDate": "2027-07-31",
"CVV": "790",
"startDate": "2024-07-24",
"endDate": "0000-00-00",
"countryCode": "FR",
"currencyCode": "EUR",
"deliveryTitle": "M",
"deliveryLastname": "ALEX",
"deliveryFirstname": "OAK",
"deliveryAddress1": "TES23 cedar hills",
"deliveryAddress2": "",
"deliveryAddress3": "",
"deliveryCity": "PARIS",
"deliveryPostcode": "75000",
"deliveryCountry": "FR",
"mobileSent": "+33612345678",
"limitsGroup": "TRZ-VL-001",
"permsGroup": "TRZ-CU-015",
"cardDesign": "8529",
"virtualConverted": "0",
"optionAtm": "1",
"optionForeign": "0",
"optionOnline": "1",
"optionNfc": "1",
"limitAtmYear": "2000",
"limitAtmMonth": "2000",
"limitAtmWeek": "1000",
"limitAtmDay": "500",
"limitAtmAll": "5000",
"limitPaymentYear": "10000",
"limitPaymentMonth": "5000",
"limitPaymentWeek": "3000",
"limitPaymentDay": "1000",
"paymentDailyLimit": "2000.00",
"restrictionGroupLimits": [
{
"merchantIdRestrictionGroups": 94748,
"paymentDailyLimit": 0.01
}
],
"limitPaymentAll": "30000",
"totalAtmYear": null,
"totalAtmMonth": null,
"totalAtmWeek": null,
"totalAtmDay": null,
"totalAtmAll": null,
"totalPaymentYear": null,
"totalPaymentMonth": null,
"totalPaymentWeek": null,
"totalPaymentDay": null,
"totalPaymentAll": null,
"createdBy": "929252",
"createdDate": "2024-07-17 07:22:08",
"modifiedBy": "929252",
"modifiedDate": "2024-07-18 13:15:21",
"cancellationNumber": null,
"physical": "0",
"logoId": "",
"logoBackId": "",
"packageId": "",
"customizedInfo": null,
"letterCustomizedInfo": "",
"freeCustomizedInfo": "",
"deliveryMethod": "1",
"pinMailer": "1",
"batchDeliveryId": "1",
"sendToParent": "1",
"isTemporary": false
}
]
},
"webhook_created_at": 17213013210351,
"webhook_id": "755c4496-ad53-4a29-9d27-2d9xxxx5b0f",
"object_payload_signature": "5hPGRs+h6eF+Un2VIUJ/V5KFlN4CxxxcjmDHxh0gLQU="
}
```
### `card.regenerate`
```json [JSON]
{
"webhook": "card.regenerate",
"webhook_id": "2xxxxxx4",
"object": "card",
"object_id": "6xxx6",
"object_payload": {
"cards": [
{
"cardId": "6xxx6",
"userId": "1xxxxx3",
"walletId": "8xxxx5",
"walletCardtransactionId": "8xxxx3",
"expiryDate": "2024-04-30",
"CVV": "724",
"physical": "0"
// [...] some attributes are hidden
}
]
},
"object_payload_signature": "aAd1gmssgfKiyWZ16njB/b/rk0qQ0NL19CSwOLXLhvY="
}
```
### `card.register3DS`
```json [JSON]
{
"webhook": "card.register3DS",
"object": "card",
"object_id": "9999886XX",
"object_payload": {
"cards": [
{
"cardId": "999988610",
"userId": "100640138",
"walletId": "3137125",
"walletCardtransactionId": "3137126",
"mccRestrictionGroupId": null,
"merchantRestrictionGroupId": null,
"countryRestrictionGroupId": null,
"eventName": "Main account",
"eventAlias": "main-account-669754fea40f1",
"publicToken": "105511111",
"cardTag": "",
"statusCode": "UNLOCK",
"isLive": "1",
"pinTryExceeds": "0",
"maskedPan": "548821******2232",
"embossedName": "ALEX OAK",
"expiryDate": "2027-07-31",
"CVV": "790",
"startDate": "2024-07-24",
"endDate": "0000-00-00",
"countryCode": "FR",
"currencyCode": "EUR",
"deliveryTitle": "M",
"deliveryLastname": "ALEX",
"deliveryFirstname": "OAK",
"deliveryAddress1": "15 rosewood lane",
"deliveryAddress2": "",
"deliveryAddress3": "",
"deliveryCity": "PARIS",
"deliveryPostcode": "75000",
"deliveryCountry": "FR",
"mobileSent": "+33612345678",
"limitsGroup": "TRZ-VL-001",
"permsGroup": "TRZ-CU-015",
"cardDesign": "8529",
"virtualConverted": "0",
"optionAtm": "1",
"optionForeign": "0",
"optionOnline": "1",
"optionNfc": "1",
"limitAtmYear": "2000",
"limitAtmMonth": "2000",
"limitAtmWeek": "1000",
"limitAtmDay": "500",
"limitAtmAll": "5000",
"limitPaymentYear": "10000",
"limitPaymentMonth": "5000",
"limitPaymentWeek": "3000",
"limitPaymentDay": "1000",
"paymentDailyLimit": "2000.00",
"restrictionGroupLimits": "[{\"merchantIdRestrictionGroups\":94748,\"paymentDailyLimit\":0.01}]",
"limitPaymentAll": "30000",
"totalAtmYear": null,
"totalAtmMonth": null,
"totalAtmWeek": null,
"totalAtmDay": null,
"totalAtmAll": null,
"totalPaymentYear": null,
"totalPaymentMonth": null,
"totalPaymentWeek": null,
"totalPaymentDay": null,
"totalPaymentAll": null,
"createdBy": "929252",
"createdDate": "2024-07-17 07:22:08",
"modifiedBy": "929252",
"modifiedDate": "2024-07-17 07:22:09",
"cancellationNumber": null,
"physical": "0",
"logoId": "",
"logoBackId": "",
"packageId": "",
"customizedInfo": null,
"letterCustomizedInfo": "",
"freeCustomizedInfo": "",
"deliveryMethod": "1",
"pinMailer": "1",
"batchDeliveryId": "1",
"sendToParent": "1",
"isTemporary": false
}
]
},
"webhook_created_at": 17212967948092,
"webhook_id": "7a4796f4-5ca7-478a-b5fd-3d5831xxxxxx",
"object_payload_signature": "QpoPfubfnsDYCVT+iEzxxxxxAvTm7h13ieDLY5UvIA="
}
```
### `card.expiryAlert`
You receive this webhook a month before the expiry date of an active or temporarily blocked card (i.e., `statusCode` is either `UNLOCK` or `LOCK`). For example, for an active card expiring on July 31st 2024, Treezor sends a `card.expiryAlert` webhook on June 1st 2024.
```json
{
"webhook": "card.expiryAlert",
"object_payload": {
"cards": [
{
"cardId": "2111143",
"expiryDate": "YYYY-MM-DD",
"renewalType": "A",
"userId": "1234",
"publicToken": "111111682",
"maskedPan": "545923****21321",
"cardDesign": "555",
"designCode": "01",
"cardTag": "custom",
"isLive": "1",
"statusCode": "UNLOCK",
"physical": "1"
}
]
},
"object_id": "2312343",
"object": "card",
"webhook_created_at": 17251498098864,
"webhook_id": "4e4fad5b-78b5-4d7a-a8ac-bed3xxxxd66a",
"object_payload_signature": "DSzhfXH4CJjCCdx5ducs/WB3vqADAvGwxxxxx6VbNz0="
}
```
**Information – Expiry alert and renewal are uncorrelated**
Please note there is no correlation between the [`card.expiryAlert`](/guide/cards/events#card-expiryalert) webhook and the renewal process.
### `card.expeditionTracking`
You receive this webhook when the card manufacturer mails the physical card (if the [corresponding feature](/guide/cards/creation#expedition-tracking) is activated).
```json [JSON]
{
"webhook": "card.expeditionTracking",
"object": "card",
"object_id": "reconciliation_id",
"object_payload": {
"publicToken": "1234",
"deliveryDate": "2024-07-17 07:22:09",
"deliveryMethod": "",
"batchDeliveryId": 0,
"trackingNumber": 0,
"requestType": "CREATION", // CREATION (new cards) or RENEWAL (replacement)
},
"object_payload_signature": "++++++++++++++++++++++++++++++++++++++++++++"
}
```
## Card Bulk Update events
### `cardBulkUpdate.create`
```json [JSON]
{
"webhook": "cardBulkUpdate.create",
"object_payload": {
"createdDate": "2025-12-16 16:01:17",
"updatedDate": "2025-12-16 16:01:17",
"bulkUpdateTag": "tag",
"bulkUpdateId": "0eb6a619-cdc6-4896-a7fd-479d51d46876",
"bulkUpdateProgressStatus": "IN_PROGRESS",
"bulkUpdateType": "CARD_LIMITS",
"cardAttributes": {
"paymentDailyLimit": 1.5,
"limitAtmYear": 1,
"limitAtmMonth": 2,
"limitAtmWeek": 3,
"limitAtmDay": 4,
"limitAtmAll": 5,
"limitPaymentYear": 6,
"limitPaymentMonth": 7,
"limitPaymentWeek": 8,
"limitPaymentDay": 9,
"limitPaymentAll": 10,
"restrictionGroupLimits": [
{
"mccRestrictionGroups": 2780,
"merchantIdRestrictionGroups": 557,
"countryRestrictionGroups": 1228,
"paymentDailyLimit": 0.75
}
]
},
"totalObjects": 11
},
"object_id": "31974243-4be4-47e5-ba73-9fbd7c57a940",
"object": "cardBulkUpdate",
"webhook_created_at": 17455072946744
}
```
### `cardBulkUpdate.update`
```json [JSON]
{
"webhook": "cardBulkUpdate.update",
"object_payload": {
"createdDate": "2025-12-16 16:01:17",
"updatedDate": "2025-12-16 21:01:17",
"bulkUpdateTag": "tag",
"bulkUpdateId": "0eb6a619-cdc6-4896-a7fd-479d51d46876",
"bulkUpdateProgressStatus": "DONE",
"bulkUpdateType": "CARD_LIMITS",
"cardAttributes": {
"paymentDailyLimit": 1.5,
"limitAtmYear": 1,
"limitAtmMonth": 2,
"limitAtmWeek": 3,
"limitAtmDay": 4,
"limitAtmAll": 5,
"limitPaymentYear": 6,
"limitPaymentMonth": 7,
"limitPaymentWeek": 8,
"limitPaymentDay": 9,
"limitPaymentAll": 10,
"restrictionGroupLimits": [
{
"mccRestrictionGroups": 2780,
"merchantIdRestrictionGroups": 557,
"countryRestrictionGroups": 1228,
"paymentDailyLimit": 0.75
}
]
},
"totalObjects": 11
},
"object_id": "31974243-4be4-47e5-ba73-9fbd7c57a940",
"object": "cardBulkUpdate",
"webhook_created_at": 17455072946744
}
```
## Card Digitization events
### `cardDigitalization.request`
Webhook [TAR](x-pay-google-apple#glossary).
```json [JSON]
{
"webhook": "cardDigitalization.request",
"object": "cardDigitalization",
"object_id": "11",
"object_payload": {
"deviceType": "PHONE", // PaymentToken_deviceType
"deviceName": "",
"tokenRequestor": "APPLE", // can also be "GOOGLE", "SAMSUNG", "MerchToken"
"tokenServiceProvider": "Visa",
"cardDigitizationExternalId": "21498",
"tokenizationDecision": "ACCEPTED", // can also be "DECLINED",
"reasonDecision": "", // empty when "ACCEPTED", populated when "DECLINED"
"cardId": 6127,
"correlationId": ""
},
"object_payload_signature": "++++++++++++++++++++++++++++++++++++++++++++"
}
```
### `cardDigitalization.update`
```json [JSON]
{
"messageId": "f0bc929f-627f-58c8-aaac-xxxxx",
"webhookId": "4ff7bb10-807c-4bb7-b14d-xxxxx",
"webhook":{
"webhook": "cardDigitalization.update",
"object_payload": {
"deviceType": "M",
"deviceName": "Oak's iPhone",
"tokenRequestor": "APPLE",
"tokenServiceProvider": "Mastercard",
"cardDigitalizationExternalId": "95699221",
"status": "S",
"creationDate": "2025-09-08",
"modifiedDate": "2025-09-08",
"updateType": "Status change",
"cardId": 101553138,
"correlationId": 0
},
"object_id": "c7f303ae-d28b-4c70-9cf8-3c1dcxxx5c52",
"object": "cardDigitalization",
"webhook_created_at": 17573296306123,
"webhook_id": "4ff7bb10-807c-4bb7-b14d-824xxxc383cd",
"object_payload_signature": "Mws1V8zH22a+7evlxdqTmJ4oPkoCfgxxx8xMCDhoEI0="
},
"clientId": "123456"
}
```
### `cardDigitalization.activation`
```json [JSON]
{
"webhook": " cardDigitalization.activation ",
"webhook_id": "3788548",
"object": " cardDigitalization ",
"object_id": "11",
"object_payload": {
"deviceType": "UNDEFINED",
"deviceName": "",
"tokenRequestor": "APPLE",
"tokenServiceProvider": "Visa",
"cardDigitizationExternalId": "21498",
"activationCode": "123456",
"activationCodeExpiry": "Dec 31 2016 11:11AM",
"activationMethod": "EMAIL_TO_CARDHOLDER_ADDRESS",
"cardId": 6127
},
"object_payload_signature": "++++++++++++++++++++++++++++++++++++++++++++"
}
```
### `cardDigitalization.complete`
```json [JSON]
{
"webhook": " cardDigitalization.complete",
"webhook_id": "3788546",
"object": " cardDigitalization ",
"object_id": "11",
"object_payload": {
"deviceType": "",
"deviceName": "",
"tokenRequestor": "APPLE",
"tokenServiceProvider": "Visa",
"cardDigitalizationExternalId": "21498",
"cardId": 6127,
"tokenId": "48 Chars ANS - Token Unique Reference",
"merchantRequestorName": "",// up to 40 chars. identifies the M4M merchant requestor
"correlationId" : 4815162342
},
"object_payload_signature": "++++++++++++++++++++++++++++++++++++++++++++"
}
```
### `cardDigitalization.deactivated`
```json [JSON]
{
"messageId": "9c829aa0-93ef-5870-bd70-xxxxxxxx",
"webhookId": "c22588a5-a2a9-49c8-8b46-xxxxxxx",
"webhook": {
"webhook": "cardDigitalization.deactivated",
"object_payload": {
"deviceType": "M",
"deviceName": "Oak's iPhone",
"tokenRequestor": "APPLE",
"tokenServiceProvider": "Mastercard",
"cardDigitalizationExternalId": "95839600",
"status": "A",
"creationDate": "2025-09-10",
"modifiedDate": "2025-09-10",
"cardId": 101553138,
"correlationId": 0
},
"object_id": "5d18da3f-23ec-4415-a5fd-xxxxxx",
"object": "cardDigitalization",
"webhook_created_at": 17575142315430,
"webhook_id": "c22588a5-a2a9-49c8-8b46-xxxxxx",
"object_payload_signature": "8MDKP99YWgr7hNYs7xSGClk2f\/Xju62esiZxxx350iI="
},
"clientId": "12345"
}
```
## MID Group events
### `merchantIdGroup.create`
```json [JSON]
{
"webhook": "merchantIdGroup.create",
"webhook_id": "2xxxxx9",
"object": "merchantIdGroup",
"object_id": "4xx1",
"object_payload": {
"merchantIdRestrictionGroups": [
{
"id": 4xx1,
"name": "Merchant Test",
"isWhitelist": true,
"status": "VALIDATED",
"startDate": "2017-12-19 16:03:55",
"createdDate": "2021-04-20 16:11:10",
"modifiedDate": null
}
]
},
"object_payload_signature": "K5hea0NO9hBVwIenmZBlvV1ay85XxKWFzgvS5mRH2tI="
}
```
### `merchantIdGroup.update`
```json [JSON]
{
"webhook": "merchantIdGroup.update",
"webhook_id": "2xxxxxx5",
"object": "merchantIdGroup",
"object_id": "4xx3",
"object_payload": {
"merchantIdRestrictionGroups": [
{
"id": 4xx3,
"name": "Merchant Test",
"isWhitelist": true,
"status": "VALIDATED",
"startDate": "2017-12-19 16:03:55",
"createdDate": "2021-04-20 16:30:22",
"modifiedDate": "2021-04-21 10:02:39"
}
]
},
"object_payload_signature": "k46KsOCHLNXf0mc+S3+DAp71UMmHIAr00GxKxpLDL8E="
}
```
### `merchantIdGroup.cancel`
```json [JSON]
{
"webhook": "merchantIdGroup.cancel",
"webhook_id": "2xxxxxx7",
"object": "merchantIdGroup",
"object_id": "4xx5",
"object_payload": {
"merchantIdRestrictionGroups": [
{
"id": 4xx5,
"name": "Merchant Test",
"isWhitelist": true,
"status": "CANCELED",
"startDate": "2017-12-19 16:03:55",
"createdDate": "2021-04-21 08:03:05",
"modifiedDate": "2021-04-21 08:30:45"
}
]
},
"object_payload_signature": "NDakNFLjBVpl+b3skAfg1EO+B+SGRe81ZVpV0cYlVqk="
}
```
## MCC Group events
### `mccGroup.create`
```json [JSON]
{
"webhook": "mccGroup.create",
"webhook_id": "2xxxxxx8",
"object": "mccGroup",
"object_id": "5xx4",
"object_payload": {
"mccRestrictionGroups": [
{
"id": 5xx4,
"name": "MCC Group Test",
"isWhitelist": true,
"mcc": [
8911,
763
],
"status": "VALIDATED",
"startDate": "2017-11-01 10:00:00",
"createdDate": "2021-04-20 15:47:26",
"modifiedDate": null
}
]
},
"object_payload_signature": "Swx2bnNeYo0gKO+LaD1+lw6sS+ue2M7+sI5HAc6U5fU="
}
```
### `mccGroup.update`
```json [JSON]
{
"webhook": "mccGroup.update",
"webhook_id": "2xxxxxx2",
"object": "mccGroup",
"object_id": "5xx4",
"object_payload": {
"mccRestrictionGroups": [
{
"id": 5xx4,
"name": "MCC Group Test",
"isWhitelist": true,
"mcc": [
8911,
763
],
"status": "VALIDATED",
"startDate": "2017-11-01 10:00:00",
"createdDate": "2021-04-20 15:47:26",
"modifiedDate": "2021-04-20 15:58:37"
}
]
},
"object_payload_signature": "L0AsXqQAEzVPITCWgXVbBd7QVeqS0VED+7Cks6JL68g="
}
```
### `mccGroup.cancel`
```json [JSON]
{
"webhook": "mccGroup.cancel",
"webhook_id": "2xxxxxx9",
"object": "mccGroup",
"object_id": "5xx4",
"object_payload": {
"mccRestrictionGroups": [
{
"id": 5xx4,
"name": "MCC Group Test",
"isWhitelist": true,
"mcc": [
8911,
763
],
"status": "CANCELED",
"startDate": "2017-11-01 10:00:00",
"createdDate": "2021-04-20 15:47:26",
"modifiedDate": "2021-04-20 16:00:44"
}
]
},
"object_payload_signature": "A8/on0tyGHkPWnoRzUCIH9nahq/H1HRt1iwHehTbRjo="
}
```
## Country Group events
### `countryGroup.create`
```json [JSON]
{
"webhook": "countryGroup.create",
"webhook_id": "2xxxxx8",
"object": "countryGroup",
"object_id": "2xx8",
"object_payload": {
"countryRestrictionGroups": [
{
"id": 2xx8,
"name": "Test Country Group",
"isWhitelist": true,
"countries": [
"250"
],
"status": "VALIDATED",
"startDate": "2021-04-20 00:00:00",
"createdDate": "2021-04-20 13:48:49",
"modifiedDate": null
}
]
},
"object_payload_signature": "KHlM6UudrM/t6IHlQMUO0fxklueJJrpOt66HE/+6Pns="
}
```
### `countryGroup.update`
```json [JSON]
{
"webhook": "countryGroup.update",
"webhook_id": "2xxxxx3",
"object": "countryGroup",
"object_id": "2xx9",
"object_payload": {
"countryRestrictionGroups": [
{
"id": 2xx9,
"name": "Test Country Group",
"isWhitelist": true,
"countries": [
"250"
],
"status": "VALIDATED",
"startDate": "2021-04-20 00:00:00",
"createdDate": "2021-04-20 13:52:04",
"modifiedDate": "2021-04-20 13:57:29"
}
]
},
"object_payload_signature": "pmVAqdJUlbreSgYth9fkq2WhOKM8wrTQxF6HM6bpGLQ="
}
```
### `countryGroup.cancel`
```json [JSON]
{
"webhook": "countryGroup.cancel",
"webhook_id": "2xxxxx5",
"object": "countryGroup",
"object_id": "2xx9",
"object_payload": {
"countryRestrictionGroups": [
{
"id": 2xx9,
"name": "Test Country Group",
"isWhitelist": true,
"countries": [
"250"
],
"status": "CANCELED",
"startDate": "2021-04-20 00:00:00",
"createdDate": "2021-04-20 13:52:04",
"modifiedDate": "2021-04-20 14:08:30"
}
]
},
"object_payload_signature": "CDsjDd4QcEd9Kig8hzOuJuUZP/yWnRMl3MZTcgZxwg8="
}
```
---
---
url: /guide/cards/errors.md
description: >-
Troubleshoot and handle card-related issues using the Treezor API's complete
list of error codes, messages, and their corresponding meanings.
---
# Errors
The following API errors can be encountered when issuing cards.
**Caution – Only the legacy API sends the error code in HTTP errors**
When handling errors with Connect, only the `message` attribute is returned.
## Card errors
| Code | Message |
|:--------:|-------------------------------------------------------------------------------------------------|
| `32000` | Impossible to create card. SQL error |
| `32001` | WSDI required |
| `32002` | ItemSrc required |
| `32003` | SecId required |
| `32004` | SecValPos required |
| `32005` | Apply\_Fee required |
| `32006` | PublicToken required |
| `32007` | IsLive required |
| `32008` | IssCode required |
| `32009` | Tile, LastName, FirstName, Addrl1, City, Postcode, Country are required |
| `32010` | LocDate(YYYY-MM-JJ) and LocTime(HHMMSS) are required |
| `32011` | CreateImage is required (0 OR 1) |
| `32012` | CreateType is required (0 OR 1) |
| `32013` | ActivateNow is required (0 OR 1) |
| `32014` | The StartDate format is MM/YY |
| `32015` | The CardDesign is mandatory |
| `32016` | PERMSGroup is mandatory |
| `32017` | Replacement must have only 0 or 1 values |
| `32018` | Delv\_AddrL1, Delv\_City, Delv\_PostCode, Delv\_County and Delv\_Country are mandatory |
| `32019` | IsLive must have only 0 or 1 values |
| `32020` | CardManufacturer must have only TCT, AllPay, GNC, Gemalto, Nitecrest, Exceet, Thames values |
| `32021` | ExternalAuth must have only 0 OR 1 values |
| `32022` | Email is mandatory |
| `32023` | Email is not valid |
| `32024` | MailOrSMS must have only 0, 1 or 2 values |
| `32025` | TxnCode required |
| `32026` | ActMethod required |
| `32027` | PAN required if Track2 and PublicToken are not present |
| `32028` | Track2 required if ActivMethod is '4' |
| `32029` | Track2 required if PAN and PublicToken are not present |
| `32030` | PublicToken required if PAN and Track2 are not present |
| `32031` | LocDate is mandatory |
| `32032` | LocTime is mandatory |
| `32033` | SmsBalance is mandatory: Possible Values: 0 OR False - Desactivate, 1 OR True - Activate, 2 OR No - Do not change current value |
| `32034` | DOB is mandatory |
| `32035` | ItemSrc is mandatory |
| `32036` | AuthType required |
| `32037` | CVV required |
| `32038` | AccCode required |
| `32039` | PAN required if AuthType == '1', '2', '3', '4' or '6' and PublicToken not present |
| `32040` | PublicToken is null or not present. Impossible to convert the card |
| `32041` | userId is mandatory |
| `32042` | CardDesign is mandatory |
| `32044` | expiryDate is mandatory |
| `32045` | expiryDate is not a valid date |
| `32046` | expiryDate must have this form YYYY-MM-DD |
| `32047` | cardId is required |
| `32048` | Error impossible to convert card |
| `32049` | Error impossible to change PIN |
| `32050` | newPin is mandatory |
| `32051` | Impossible to activate card |
| `32052` | Impossible to read the card |
| `32053` | Impossible to create the card |
| `32054` | Impossible to modify the card |
| `32055` | Impossible to convert the card |
| `32056` | Impossible to change the card's PIN |
| `32057` | confirmPin is mandatory |
| `32058` | Impossible to renew the card |
| `32059` | Impossible to lock/unlock the card |
| `32060` | lockStatus is required |
| `32061` | permsGroup is required |
| `32062` | cardDesign is required |
| `32064` | User informations are incomplete: lastname, firstname, address1 and phone (or mobile) is required |
| `32065` | Country code is invalid |
| `32066` | Internal error. Impossible to create physical card |
| `32067` | Impossible to create physical card: insertion impossible in database | |
| `32068` | User's phone or user's mobile required | |
| `32070` | Internal error. Impossible to create virtual card | |
| `32071` | limitPeriod is mandatory | |
| `32072` | limitType is mandatory | |
| `32073` | The cardId provided does not exist | |
| `32074` | The foreign option is mandatory. 0 or 1 | |
| `32075` | The online option is mandatory. 0 or 1 | |
| `32076` | The atm option is mandatory. 0 or 1 | | |
| `32077` | The nfc option is mandatory. 0 or 1 |
| `32078` | No perms group corresponds to the options provided |
| `32079` | walletId is mandatory |
| `32080` | The wallet does not exist |
| `32081` | There is no product in the database. Impossible to create the card |
| `32082` | The currency of the wallet must be the same as the product |
| `32083` | The permsGroup does not exist |
| `32084` | The card is already physical. |
| `32085` | The card has been already converted. |
| `32086` | Impossible to insert Card image. |
| `32087` | Impossible to create card. The PIN is invalid |
| `32088` | Impossible to change PIN. The current PIN is mandatory |
| `32089` | Impossible to change PIN. The newPIN must be the same as the confirmPin |
| `32090` | Impossible to create card. The cardPrint is mandatory |
| `32091` | Impossible to create card. The cardPrint is invalid |
| `32092` | Impossible to update card options (GPS) |
| `32093` | Impossible to regenerate card (GPS) |
| `32094` | Impossible to update card image |
| `32095` | Card status can not be changed, current status of the card is not reversible Code. Card lost. |
| `32096` | Card status can not be changed, current status of the card is not reversible Code. Card stolen. |
| `32097` | Impossible to create card. sendToParent value 1, but there is no parent user id for the main user|
| `32098` | Impossible to create card. Delivery address not complete. The parent user must have delivery address informations provided. (legalName, address1, address2, postcode, city and country) |
| `32099` | Impossible to create card. Delivery address not complete. The user must have delivery address informations provided. (address1, address2, postcode, city and country) |
| `32100` | Impossible to create card. Delivery address not complete in user's informations. The user must have full address informations provided. (address1, postcode, city and country) |
| `32101` | Card limit exceeded |
| `32102` | Erreur lors du cardUpdateDeliveryInfo (GPS) |
| `32103` | Erreur lors du cardUpdateDeliveryInfo (GPS) |
| `32104` | GPS Error happened when attempting to get all DPAN |
| `32105` | GPS Error happened when attempting to get all DPAN WRONG Status code in Return |
| `32106` | GPS Error happened when attempting to change status of Payment token |
| `32107` | GPS Error happened when attempting to change status of Payment token - empty response |
| `32108` | GPS Error happened when attempting to change status of Payment token - wrong action code returned|
| `32109` | Exception raised while attempting to reactivate all DPAN linked to card |
| `32111` | Card blocked. | The card is blocked either due to the `statusCode` or the `pinTryExceeded` = `1` |
| `32112` | mccRestrictionGroupId provided does not exist. |
| `32113` | merchantRestrictionGroupId provided does not exist. |
| `32114` | EmbossedName value is empty after sanitized, the characters accepted are : a-z, A-Z, 0-9, '-' and 'espace'|
| `32113` | countryRestrictionGroupId provided does not exist. |
| `32115` | batchDeliveryId must be an integer between 1 and 238323 |
| `32116` | batchDeliveryId can not be used. Not operational yet. |
| `32117` | Delivery address is missing or incomplete. Impossible to convert the card. address1, city, postcode and country are mandatory|
| `32118` | Wallet has a CANCELED status. |
| `32119` | User has a CANCELED status. |
| `32120` | User does not exist |
| `32121` | Exception raised when a language is not in the Languages list |
| `32122` | Missing program id in database |
| `32123` | Invalid program id in database |
| `32124` | The parentUserId does not exist |
| `32125` | Missing Public Token |
| `32126` | Missing clientId |
| `32228` | Missing Public phone |
| `32229` | Card status can not be changed, current status of the card is not reversible Code. Card locked internally.|
| `32230` | Card status can not be changed, current status of the card is not reversible Code. Card is expired.|
| `32231` | Card status is invalid |
| `32232` | Invalid payment timeframe |
| `34000` | The card must be already activated |
| `34001` | The request is refused because the card has expired |
| `34002` | Fail to renew card |
| `34003` | The card must not be stolen or lost or destroyed |
| `34004` | The card must be physical |
| `34005` | Fail to replace card |
| `34006` | The request is refused because it cannot be made during the month the card expires |
| `32127` | Card is already activated |
| `32128` | Please set card information in object |
| `32129` | Impossible de renew\_cards chez GPS |
| `32130` | Please set card information in object |
| `32131` | Impossible to create the card, the length of an address line must be less than 38 characters |
| `32131` | Parent user not found, impossible to update card information |
| `32132` | Impossible to create the card, user's assets are frozen |
| `32133` | Impossible to create the card, parent user's assets are frozen |
| `32134` | RestrictionGroupLimits value is invalid |
| `32135` | Please fill in at least one limit among these: limitPaymentDay / paymentDailyLimit / limitPaymentWeek / limitPaymentMonth for this card. |
| `32136` | Please fill in at least one limit among these: limitAtmDay / limitAtmWeek / limitAtmMonth for this card. |
| `32137` | Please fill in at least one limit among these: limitPaymentDay / paymentDailyLimit / limitPaymentWeek / limitPaymentMonth for this card. |
| `32138` | Please fill in at least one limit among these: limitAtmDay / limitAtmWeek / limitAtmMonth for this card. |
| `32139` | Impossible to create card, the product is not activated. |
| `32140` | Please provide at least one argument among these: userId / walletId to reassign this card. |
| `32141` | The provided card is already activated and cannot be reassigned. |
| `32142` | The provided card is lost or stolen and cannot be reassigned. |
| `32143` | The provided card is not anonymous and cannot be reassigned. |
| `32144` | Wallet does not exist. |
| `32145` | The provided user's assets are frozen, the card cannot be reassigned. |
| `32146` | The provided wallet has a user with frozen assets and cannot be reassigned. |
| `32147` | This wallet type cannot be assigned. |
| `32148` | Impossible to create card. The customizedInfo is invalid |
| `32149` | Impossible to create card. The embossLegalName and the customizedInfo cannot both be specified |
| `32150` | Impossible to create card, cardLanguages has a wrong format (alphabetic, 8 char. max, format ISO 639-1) |
| `32151` | Unrecognized card renewOption |
| `32152` | Invalid card renewOption given the card status |
| `32153` | Card status cannot be changed, current status of the card is not reversible Code. Card destroyed|
| `32154` | Card expiry date failed to update |
| `32155` | Card not found |
| `32156` | Unable to create card. The letterCustomizedInfo is invalid |
| `32157` | Unable to create card. The card type is missing |
| `32158` | Unable to create card. The freeCustomizedInfo is invalid |
| `32159` | Unable to create card. DeliveryMethod value must be 0, 1 or 2 |
| `32160` | Unable to create card. The pinMailer is invalid |
| `32161` | Unable to create card. The pinMailer is not supported by this product |
| `32162` | Unable to create card. The logoBackId is invalid |
| `32163` | Unable to create card. The logoId is invalid |
| `32164` | Unable to save card. The maskedPan is mandatory |
| `32165` | Unable to save card. The startDate is mandatory |
| `32166` | Unable to save card. The expiryDate is mandatory |
| `32167` | The request is refused because the value of the renewalType field must be A or N |
| `32168` | CardTag exceeds 50 characters |
| `32169` | The provided card is lost and cannot be reassigned. |
| `32170` | The provided card is stolen and cannot be reassigned. |
| `32171` | The provided card is expired and cannot be reassigned. |
| `32172` | The provided card is destroyed and cannot be reassigned. |
| `32173` | The provided card is locked by Treezor and cannot be reassigned. |
| `32174` | Wallet assignment is not allowed on this card |
| `107000` | Impossible to reach server, please try again later |
| `107001` | An error occurred, please try again later |
| `107002` | Missing argument. You should provide cardId or publicToken |
| `107003` | Invalid argument |
| `107004` | No card found |
| `107005` | Duplicated record |
| `107006` | Invalid argument lockStatus |
| `107007` | Impossible to change the card status |
| `107008` | Impossible to read the card |
| `107009` | Impossible to activate card |
| `107010` | Impossible to convert virtual card |
| `107011` | Impossible to update card's options |
| `107012` | Impossible to get cardImage |
| `107013` | Impossible to unblock card's PIN code |
| `109001` | cardProduct Id does not exist |
| `109002` | The currencyCode format must follow the norm : Code ISO 4217 |
| `109003` | The countryCode format must follow the norm : ISO-3166-1 alpha-2 |
| `109004` | cardPrint print\_reference does not exist |
| `109005` | cardProduct Id already used |
| `109006` | clientId does not exist |
| `109007` | The network can only be mastercard or visa |
| `109008` | The status should be active, blocked and canceled |
| `120100` | Impossible to modify limits |
## Card image errors
| Code | Message |
|:----------:|--------------------------------------------------------------------------------------------------------------|
| `62000` | The cardId does not exist. |
| `62001` | No card image found |
| `62002` | cardId mandatory |
| `62003` | cardimage mandatory (not empty) |
| `62004` | Connection socket error |
| `62005` | Writing in socket error |
| `62006` | The response image is empty |
| `62007` | Internal error socket |
| `62008` | The card has a LOST or STOLEN status |
| `62009` | Missing argument encryptionMethod (encryptionPublicKey provided) |
| `62010` | Missing argument encryptionPublicKey (encryptionMethod provided) |
| `62011` | Invalid encryption method |
## Card digitalization errors
| Code | Message |
|:----------:|--------------------------------------------------------------------------------------------------------------|
| `77000` | cardDigitalization Id does not exist |
| `77001` | No linked card retrieved |
| `77002` | The new status that you want to apply to this card is not authorized |
| `77003` | The status change has failed due to a technical error. |
| `77004` | This service is not available; only GET and PUT are implemented. |
| `77005` | Card\_id is mandatory to perform the Update of the Status |
| `77006` | Get the Payment Token Information at provider failed - Status Code is not valid |
| `77007` | The Get Payment Token Failed due to the presence of two objects instead of one |
| `77008` | The Get Payment Token Failed due to the fact that the first object retrieved is empty |
| `77009` | PaymentToken\_id is missing. |
| `77010` | Proc\_Code is missing. |
| `77011` | Unknown proc code. |
| `77012` | The provided status is invalid |
| `77013` | The provided reason code is invalid |
| `77014` | The DPAN is deactivated, unable to update |
| `77015` | Error, The SMS has not been sent |
| `77016` | The Provided Card is already suspended. |
| `77017` | The provided card is already deactivated. |
| `77018` | The provided card is already activated. |
| `99001` | Impossible to reach server, please try again later |
| `99002` | Service response is KO, please try again later |
## Restriction group errors
| Code | Message |
|----------|------------------------------------------------------------------------------------------------------|
| `82000` | MCC restriction group Id does not exist |
| `82001` | MCC restriction group array validation failed |
| `82002` | Status provided is not correct |
| `82003` | MCC restriction group Id does not exist |
| `81004` | Error appending MCC restriction group |
| `83000` | Merchant restriction group Id does not exist |
| `83001` | Merchant restriction group array validation failed |
| `83002` | Status provided is not correct |
| `83003` | Merchant restriction group Id does not exist |
| `82004` | Error appending Merchant Id restriction group |
| `82005` | Start date provided is incorrect |
| `82006` | MerchantsOperation can be only add or remove |
| `82007` | You have no merchants deleted |
| `82008` | The number of merchants exceeded the max authorized, please try again with a smaller number |
| `84000` | Country restriction group Id does not exist |
| `84001` | Country restriction group array validation failed |
| `84002` | Status provided is not correct |
| `84003` | Country restriction group Id does not exist |
| `84004` | Error appending Country restriction group |
| `94000` | The type does not exist |
| `94001` | The ID does not exist |
| `94002` | Impossible to reach server, please try again later |
| `94003` | Service response is KO, please try again later |
| `94004` | Error using restriction groups |
| `94005` | Service response is empty, please try again later |
| `94006` | Impossible to format response, please try again later |
| `94007` | Duplicated Record |
| `94008` | More than 100,000 records have been found, please refine your request |
| `94009` | Invalid Data |
| `94010` | Missing Data |
| `94011` | No Record Found |
| `94012` | An error occurred, please try again later |
---
---
url: /guide/cards/pci-dss.md
description: >-
Learn how to set up your certificates and sign your requests to migrate to
Treezor PCI DSS services, hence offering the highest level of security for
sensitive card data.
---
# PCI DSS integration
Treezor complies with the [**Payment Card Industry Data Security Standard (PCI DSS)**](/guide/overview/glossary#payment-card-industry-data-security-standards-pci-dss) to secure sensitive data (e.g., PAN, PIN, CVV) of payment cards.
**Configuration – Migrating to PCI DSS services**
If you have been working with Treezor since before PCI DSS became available, you must migrate to these new services. Please contact Treezor for more information.
The implementation of PCI DSS at Treezor relies on the [**Mutual Transport Layer Security (mTLS)**](/guide/api-basics/mutual-tls) protocol, which guarantees mutual authentication and encrypted communication, and prevents interception or identity theft between systems. This protocol applies to all endpoints.
In addition, all your requests transit through the following URL:
* **Sandbox** – `https://.preprod.secure.treezor.co`
* **Production** – `https://.secure.treezor.co`
This article takes you through the steps to implement mTLS, focusing on your Sandbox environment. Please bear in mind you'll have to repeat the same procedure for your Production environment.
## Setting up your certificates
To use mTLS, you first need to send a CSR (Certificate Signing Request) to Treezor for your **mTLS certificate** (to set up, with your private key, the TLS negotiation).
In return, Treezor provides the signed certificate for you to configure your client and authenticate your requests.
You need to provide a certificate for each of your Treezor environments (Sandbox and Production), which means you’ll have to send 2 CSR files.
### 1. Create your RSA keys
You need a private key to create your certificate signing request (CSR).
These keys must have the following attributes:
* **Type**: RSA
* **Format**: PKCS1
* **Size**: 2048
Here is the command to run for your Sandbox, please keep in mind you'll have to do the same for your Production environment.
```[Linux / macOS]
openssl genrsa -out _privatekey_mtls.pem 2048
```
**Security – Protect your private key**
Don’t share your private keys with anyone and make sure they are securely stored (e.g., secure vault, key management system).
### 2. Create your CSR files
The Certificate Signing Request (CSR) is the request you send to a Certificate Authority (or CA, in this case, Treezor) to apply for a digital identity certificate. The CSR includes the public key and additional information, such as the entity requesting the certificate's common name (CN).
Here is the command to run:
```[Linux / macOS]
openssl req -new -key _privatekey_mtls.pem -out _csr_mtls.pem
```
Then use the information in the table below to complete the CSR information.
| Information | Description |
|---------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Country | The two-letter country code representing the country where the organization is located. |
| State / Province | The state or province where the organization is located (e.g., Brittany, IdF). |
| Locality | The locality or city where the organization is located. |
| Organization Name | The legal name of the organization to which the entity belongs. This could be the company, department, or other organizational unit. |
| Organizational Unit | (optional) The specific unit within the organization. For example, "IT Department" or "Marketing". |
| Common Name | Usually, the fully qualified domain name (FQDN) for which the certificate is being requested. For example, if the certificate is for a website, the CN might be the domain name (e.g., https://yourcompany.com). |
| Email | The email address of the organization. |
### 3. Ask Treezor to generate your certificates
CSR files and certificates aren't considered sensitive data. This is why you can exchange them by email.
1. Send your CSR files to your *Treezor Technical Account Manager*.
2. Treezor will send you back the signed certificates.
**Security – Don't send your private keys, only the CSR files**
If you were to send us your private key, you would have to generate new ones and start the process from scratch.
You now have the necessary certificates for mTLS authentication.
**Reading – More information available on mTLS**
Learn more about certificates, including when to [renew](/guide/api-basics/mutual-tls#renewing-your-certificates) or [revoke](/guide/api-basics/mutual-tls#revoking-your-certificates) them.
## Make your requests
Now that you have your certificates, you can make PCI DSS-specific requests (see [PCI DSS API Reference](/api-reference/pci-dss-dev.html)).
```go [Golang]
package main
import (
"crypto/tls"
_ "embed"
"fmt"
"io"
"net/http"
)
var (
//go:embed _csr_mtls.pem
pemCertificateMTLS []byte
//go:embed _privatekey_mtls.pem
pemPrivateKeyMTLS []byte
)
func GenerateRequest(httpMethod, requestURL string, queryParams map[string]string,
jwtToken, scaProof string, body io.Reader) (*http.Request, error) {
if jwtToken == "" {
return nil, fmt.Errorf("missing JWT Token")
}
request, err := http.NewRequest(httpMethod, requestURL, body)
if err != nil {
return nil, fmt.Errorf("failed to create request: %w", err)
}
request.Header["Authorization"] = []string{"Bearer " + jwtToken}
if scaProof != "" {
request.Header["X-Trz-SCA"] = []string{scaProof}
}
return request, nil
}
// SendUsingMTLS sends the given HTTP request using mTLS protocol.
func SendUsingMTLS(request *http.Request) (*http.Response, error) {
clientCertificate, err := tls.X509KeyPair(pemCertificateMTLS, pemPrivateKeyMTLS)
if err != nil {
return nil, fmt.Errorf("failed to load x509 key pair: %w", err)
}
httpClient := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
Certificates: []tls.Certificate{clientCertificate},
},
},
}
return httpClient.Do(request)
}
```
```php [PHP]
_csr_mtls.pem';
const MTLS_KEY_FILE = '_privatekey_mtls.pem';
function generateRequest(string $httpVerb, string $url, array $queryParams, string $jwtToken, string $scaProof, string $body): Request
{
if ($jwtToken === '') {
throw new RuntimeException('missing JWT Token');
}
$headers = [
'X-Trz-SCA' => $scaProof,
'Authorization' => "Bearer $jwtToken",
'Content-Type' => 'application/json',
];
return new Request($httpVerb, $url . '?' . http_build_query($queryParams), $headers, $body);
}
/**
* @throws \Psr\Http\Client\ClientExceptionInterface
*/
function sendUsingMTLS(Request $request)
{
$client = new Client([
GuzzleHttp\RequestOptions::CERT => [MTLS_CERT_FILE, ''],
GuzzleHttp\RequestOptions::SSL_KEY => [MTLS_KEY_FILE, ''],
]);
return $client->sendRequest($request);
}
```
## PCI DSS Endpoints
The PCI DSS endpoints are the ones for which you need to add the certificate. They can only be used for cards created or migrated to PCI DSS services, and replace their equivalent in the main [API Reference](/api-reference/api-endpoints).
Please keep in mind that all your requests transit through the following URL:
* **Sandbox** – `https://.preprod.secure.treezor.co`
* **Production** – `https://.secure.treezor.co`
| PCI DSS endpoint | Replaced endpoints |
| --- | --- |
| [`/cards`](/api-reference/pci-dss-dev.html#tag/Cards/createCard){target="\_self"} Create a Card. Use the `medium` field to create Virtual or Physical cards. | [Create Virtual Card](/api-reference/api-endpoints.html#tag/Cards/postCardVirtual){target="\_self"} [Create Physical Card](/api-reference/api-endpoints.html#tag/Cards/postCardPhysical){target="\_self"} |
| [`/cards/{cardId}/tokenize`](/api-reference/pci-dss-dev.html#tag/Cards/cardTokenize){target="\_self"} Tokenize the card. | |
| [`/cards/{cardId}/cardImage`](/api-reference/pci-dss-dev.html#tag/Cards/postCardImage){target="\_self"} Rebuild the card image when changing card design, company name, or when retrieving the image results in a 404. Not necessary when initially creating a Virtual Card. | [Regenerate Card](/api-reference/api-endpoints.html#tag/Cards/regenerateCard){target="\_self"} |
| [`/cards/{cardId}/renew`](/api-reference/pci-dss-dev.html#tag/Cards/postRenew){target="\_self"} Renew the card manually. | [Renew Card](/api-reference/api-endpoints.html#tag/Cards/putRenew){target="\_self"} |
| [`/cards/{cardId}/cardImage`](/api-reference/pci-dss-dev.html#tag/Cards/getCardImage){target="\_self"} Download the card encrypted image. Requires encryption, see [Display sensitive data](/guide/cards/sensitive-data) article. | [Retrieve Image](/api-reference/api-endpoints.html#tag/Cards/getCardImage){target="\_self"} |
| [`/cards/{cardId}/pan`](/api-reference/pci-dss-dev.html#tag/Cards/getPAN){target="\_self"} Retrieve the card PAN & CVV. Use the `withCVV` field to get the encrypted CVV too. Requires encryption, see [Display sensitive data](/guide/cards/sensitive-data) article. | |
| [`/cards/{cardId}/pin`](/api-reference/pci-dss-dev.html#tag/Cards/getPIN){target="\_self"} Retrieve the PIN code of the card. Requires encryption, see [Display sensitive data](/guide/cards/sensitive-data) article. | |
| [`/cards/{cardId}/assignUser`](/api-reference/pci-dss-dev.html#tag/Cards/putAssignUser){target="\_self"} Assign the card to another user. | [Reassign Card](/api-reference/api-endpoints.html#tag/Cards/reassignCard){target="\_self"} (partial replacement) |
| [`/cards/{cardId}/changePIN`](/api-reference/pci-dss-dev.html#tag/Cards/putChangePin){target="\_self"} Change the PIN code knowing the current one. | [Change PIN](/api-reference/api-endpoints.html#tag/Cards/changePin){target="\_self"} |
| [`/cards/{cardId}/setPIN`](/api-reference/pci-dss-dev.html#tag/Cards/putSetPin){target="\_self"} Overwrite the PIN code. | [Set PIN](/api-reference/api-endpoints.html#tag/Cards/setPin){target="\_self"} |
| [`/cards/{cardId}/inappcryptogram/mastercard/apple-pay`](/api-reference/pci-dss-dev.html#tag/Cards/postInappApple){target="\_self"} Generate an Apple Pay cryptogram for Mastercard digitization process. | [Request issuerInitiatedDigitizationData ](/api-reference/api-endpoints.html#tag/Digitized%20Cards/tavRequestPOST){target="\_self"} |
| [`/cards/{cardId}/inappcryptogram/mastercard/google-pay`](/api-reference/pci-dss-dev.html#tag/Cards/postInappGpay){target="\_self"} Generate a Google Pay cryptogram for Mastercard digitization process. | [Request issuerInitiatedDigitizationData ](/api-reference/api-endpoints.html#tag/Digitized%20Cards/tavRequestPOST){target="\_self"} |
| [`/cards/{cardId}/inappcryptogram/visa/apple-pay`](/api-reference/pci-dss-dev.html#tag/Cards/postVisaInappApple){target="\_self"} Generate an Apple Pay cryptogram for Visa digitization process. | |
| [`/cards/{cardId}/inappcryptogram/visa/google-pay`](/api-reference/pci-dss-dev.html#tag/Cards/postVisaInappGpay){target="\_self"} Generate a Google Pay cryptogram for Visa digitization process. | |
| [`/inappcryptogram/{credentials}`](/api-reference/pci-dss-dev.html#tag/Cards/getInapp){target="\_self"} Retrieve digitization cryptogram. | |
| [`/users`](/api-reference/pci-dss-dev.html#tag/Users/postUsers){target="\_self"} Create a user. | [Create User](/api-reference/api-endpoints.html#tag/Users/postUsers){target="\_self"} |
**API – API Reference available**
For a complete list of attributes for these endpoints, check the [PCI DSS API Reference](/api-reference/pci-dss-dev).
---
---
url: /guide/cards/renewal.md
description: >-
Technical guide for renewing soon-to-expire cards via the Treezor API.
Includes required parameters, request structure, and response examples.
---
# Renewal
Renewing a Card consists of issuing a new card before the original one expires. This new card has the same attributes as the previous one.
Card renewal is tied to your [Card Program](/guide/cards/introduction#card-program) and the kind of product issued. Issuing services can be adjusted to optimize the costs and adapt the renewal experience (e.g., packaging).
**Feature activation – Renewal is not activated by default**
Please contact your *Treezor Account Manager* if you're interested in this feature.
## Renewed card specificities
When a card is renewed, some attributes remain identical to the original one while others have new values. This ensures continuity of services (e.g., X-Pay and 3DS enrollments) and a smoother experience (identical PIN code) for cardholders.
### Inherited attributes
* Card design
* Limits and restrictions
* [Card authentication methods](/guide/strong-customer-authentication/securing-endpoints#card-authentication-methods-enrollment) (OOB, SMS OTP)
* X-Pay enrollments
* PIN code
* `cardTag`
* Type of card (i.e., Virtual or Physical)
### New attributes
* `cardId`
* `PAN`
* `expiryDate`
* `publicToken`
* `cvv`
* The outstanding spending limits, which are reset (i.e., if €90 out of €100 were spent on the previous card, €100 will still be usable on the renewed one).
**Information – Virtual Converted Cards are automatically produced**
Renewing a virtual converted card results in a new virtual converted card. You don't need to go through the conversion process again.
**Caution – PIN not automatically changed on both cards during Renewal**
If the PIN code of the card being renewed changes during the renewal procedure, then the PIN code must also be changed manually for the renewed card.
## Renewal process
The renewal process follows these steps:
1. The card renewal process is triggered (manually or automatically)
2. The `card.renew` webhook is sent
3. The cardholder receives the new card (inactive)
4. The cardholder activates the new card
5. The original card `status` is set to `EXPIRED`
**Information – Expiry alert and renewal are uncorrelated**
While the [`card.expiryAlert`](/guide/cards/events#card-expiryalert) webhook is convenient to anticipate the card expiration, please note there is no correlation with the renewal process.
### Automatic renewal
The automatic card renewal process is triggered at the beginning of each month. A request for renewal is sent to the card processor to renew all cards meeting the following conditions:
* **Expire within the current month** – `expiryDate` in the current month minus 1 day.
* **Are active** – `isLive` attribute is set to `1`.
* **Are unlocked** – `cardStatus` value is `UNLOCK`.
* **Are renewable** – Attached to a product code with the automatic renewal attribute, or the renewal type set to automatic (`“renewalType”: “A”`).
Won’t be renewed cards which:
* `renewalType` value is `N`.
* Have already been renewed (i.e., `renewalDate` value is other than `null`).
### Manual renewal
In case you need to renew a card before its expiration month, you can trigger the card renewal manually. This is only possible for active cards that haven't been renewed yet, and whose status is `UNLOCK`.
Use the following request with the `cardId` as a path parameter to renew a card manually.
Endpoint: [`/v1/cards/{cardId}/renew`](/api-reference/api-endpoints.html#tag/Cards/putRenew){target="\_self"}
```bash [CURL]
curl -X PUT '{baseUrl}/v1/cards/{cardId}/renew' \
--header 'Authorization: Bearer {accessToken}'
```
If successful, the [`card.renew`](/guide/cards/events#card-renew) event is sent, and the Card object is returned:
```json [JSON]
{
"cards": [
{
"cardId": 241709,
"userId": 8290083,
"walletId": 2464676,
"walletCardtransactionId": 2473310,
"mccRestrictionGroupId": 95447,
"merchantRestrictionGroupId": 45599,
"countryRestrictionGroupId": 165327,
"publicToken": "107277882",
"cardTag": "",
"statusCode": "UNLOCK",
"isLive": 0,
"pinTryExceeds": 0,
"maskedPan": "519872******4839",
"embossedName": "ALEX OAK",
"expiryDate": "2026-10-31",
"CVV": "260",
"startDate": "2023-10-23",
"endDate": "0000-00-00",
"countryCode": "FR",
"currencyCode": "EUR",
"lang": null,
"deliveryTitle": "M",
"deliveryLastname": "OAK",
"deliveryFirstname": "ALEX",
"deliveryAddress1": "15 EDGEWOOD ROAD",
"deliveryAddress2": "",
"deliveryAddress3": "",
"deliveryCity": "ROSEWOOD",
"deliveryPostcode": "12365",
"deliveryCountry": "FR",
"mobileSent": "+33633333333",
"limitsGroup": "TRZ-VL-001",
"permsGroup": "TRZ-CU-011",
"cardDesign": "13664",
"virtualConverted": 0,
"physical": 0,
"optionAtm": 0,
"optionForeign": 0,
"optionOnline": 1,
"optionNfc": 1,
"limitAtmYear": 0,
"limitAtmMonth": 0,
"limitAtmWeek": 0,
"limitAtmDay": 1,
"limitAtmAll": 1,
"limitPaymentYear": 0,
"limitPaymentMonth": 0,
"limitPaymentWeek": 0,
"limitPaymentDay": 25,
"limitPaymentAll": 25,
"paymentDailyLimit": 0.0,
"totalAtmYear": null,
"totalAtmMonth": null,
"totalAtmWeek": null,
"totalAtmDay": null,
"totalAtmAll": null,
"totalPaymentYear": null,
"totalPaymentMonth": null,
"totalPaymentWeek": null,
"totalPaymentDay": null,
"totalPaymentAll": null,
"createdBy": 945198,
"createdDate": "2023-10-31 10:37:04",
"modifiedBy": 0,
"modifiedDate": "0000-00-00 00:00:00",
"renewalType": null,
"renewalDate": "2024-04-01",
"originalCardId": null,
"totalRows": null,
"designCode": null,
"cardLanguages": "",
"eventName": "Master Wallet",
"eventAlias": "master-wallet-6537b83040735",
"restrictionGroupLimits": null,
"cancellationNumber": "",
"metadata": null,
"renewalDate": null,
"renewalType": null,
"originalCardId": null,
"logoId": "",
"logoBackId": "",
"packageId": "",
"customizeInfo": "",
"letterCustomizedInfo": "",
"freeCustomizedInfo": "",
"deliveryMethod": null,
"pinMailer": null,
"batchDeliveryId": null,
"sendToParent": 0
}
]
}
```
Endpoint: [`/cards/{cardId}/renew`](/api-reference/pci-dss-dev.html#tag/Cards/postRenew){target="\_self"}
```bash [CURL]
curl -X PUT '{pciBaseUrl}/cards/{cardId}/renew' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"userId": "100642533",
"pinRenewOption": 1 // To keep the previous PIN code
}
```
If successful, the [`card.renew`](/guide/cards/events#card-renew) event is sent, and the Card object is returned:
```json [JSON]
{
"cards": [
{
"cardId": 241709,
"userId": 8290083,
"walletId": 2464676,
"walletCardtransactionId": 2473310,
"mccRestrictionGroupId": 95447,
"merchantRestrictionGroupId": 45599,
"countryRestrictionGroupId": 165327,
"publicToken": "107277882",
"cardTag": "",
"statusCode": "UNLOCK",
"isLive": 0,
"pinTryExceeds": 0,
"maskedPan": "519872******4839",
"embossedName": "ALEX OAK",
"expiryDate": "2026-10-31",
"CVV": "260",
"startDate": "2023-10-23",
"endDate": "0000-00-00",
"countryCode": "FR",
"currencyCode": "EUR",
"lang": null,
"deliveryTitle": "M",
"deliveryLastname": "OAK",
"deliveryFirstname": "ALEX",
"deliveryAddress1": "15 EDGEWOOD ROAD",
"deliveryAddress2": "",
"deliveryAddress3": "",
"deliveryCity": "ROSEWOOD",
"deliveryPostcode": "12365",
"deliveryCountry": "FR",
"mobileSent": "+33633333333",
"limitsGroup": "TRZ-VL-001",
"permsGroup": "TRZ-CU-011",
"cardDesign": "13664",
"virtualConverted": 0,
"physical": 0,
"optionAtm": 0,
"optionForeign": 0,
"optionOnline": 1,
"optionNfc": 1,
"limitAtmYear": 0,
"limitAtmMonth": 0,
"limitAtmWeek": 0,
"limitAtmDay": 1,
"limitAtmAll": 1,
"limitPaymentYear": 0,
"limitPaymentMonth": 0,
"limitPaymentWeek": 0,
"limitPaymentDay": 25,
"limitPaymentAll": 25,
"paymentDailyLimit": 0.0,
"totalAtmYear": null,
"totalAtmMonth": null,
"totalAtmWeek": null,
"totalAtmDay": null,
"totalAtmAll": null,
"totalPaymentYear": null,
"totalPaymentMonth": null,
"totalPaymentWeek": null,
"totalPaymentDay": null,
"totalPaymentAll": null,
"createdBy": 945198,
"createdDate": "2023-10-31 10:37:04",
"modifiedBy": 0,
"modifiedDate": "0000-00-00 00:00:00",
"renewalType": null,
"renewalDate": "2024-04-01",
"originalCardId": null,
"totalRows": null,
"designCode": null,
"cardLanguages": "",
"eventName": "Master Wallet",
"eventAlias": "master-wallet-6537b83040735",
"restrictionGroupLimits": null,
"cancellationNumber": "",
"metadata": null,
"renewalDate": null,
"renewalType": null,
"originalCardId": null,
"logoId": "",
"logoBackId": "",
"packageId": "",
"customizeInfo": "",
"letterCustomizedInfo": "",
"freeCustomizedInfo": "",
"deliveryMethod": null,
"pinMailer": null,
"batchDeliveryId": null,
"sendToParent": 0,
"isTemporary": true
}
]
}
```
#### Renewal failed responses
The following HTTP 400 errors may occur when failing to renew a Card.
| `errorCode` | `errorMessage` |
| :---: | --- |
| `34000` | The card must be already activated. |
| `34001` | The request is refused because the card has expired. |
| `34003` | The card must not be stolen or lost or destroyed. |
### Activation of a renewed card
As a security measure, the new card is issued in an `inactive` state to ensure that a Card is not usable before the cardholder receives it.
Once received, the card can be activated, and the previous card status will be automatically set as `EXPIRED`. Expired cards can no longer be used, and this status is permanent.
## Renewal Type (`renewalType`)
When creating a Card, the card renewal type (automatic or not) is defined by your [Card Program](/guide/cards/introduction#card-program). If `renewalType` is set to `null` and the product is auto-renewing, the card will be renewed.
The renewal type allows you to:
* Set automatic renewal on a card-by-card basis if this is not set at product level.
* Exclude a card from automatic renewal (for a user who closes their account, for example).
A dedicated endpoint allows you to update the renewal type as needed: [`/v1/cards/{cardId}/renewalDetails`](/api-reference/api-endpoints.html#tag/Cards/updateRenewalDetails){target="\_self"}.
**Note – Can’t update `renewalType` for cards expiring within the month**
You may use the [`/v1/cards/{cardId}/renew`](/api-reference/api-endpoints.html#tag/Cards/putRenew){target="\_self"} request to renew the card manually.
### Parameters
| Attribute | Type | Description |
|--- |--- |--- |
| `renewalType` | string | Define how the Card is to be renewed. Values can be the following: `A` – Automatic renewal. `N` – Non-automatic renewal. |
Use the following request with the `cardId` as a path parameter to update the card renewal type.
```bash [CURL]
curl -X PUT '{baseUrl}/v1/cards/{cardId}/renewalDetails' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"renewalType": "A"
}
```
Returns the Card Renewal Details object if successful:
```json [JSON]
{
"cardRenewalDetails": {
"renewalType": "A"
}
}
```
## Endpoints
| Endpoint |[Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/v1/cards/{cardId}/renewalDetails`](/api-reference/api-endpoints.html#tag/Cards/getRenewalDetails){target="\_self"} Retrieve the card renewal options. | `admin`, `legal`, `read_write` |
| [`/v1/cards/{cardId}/renewalDetails`](/api-reference/api-endpoints.html#tag/Cards/updateRenewalDetails){target="\_self"} Update the card renewal options. | `admin`, `legal`, `read_write` |
| [`/v1/cards/{cardId}/renew`](/api-reference/api-endpoints.html#tag/Cards/putRenew){target="\_self"} Renew a Card manually. | `admin`, `legal`, `read_write` |
---
---
url: /guide/dashboard/card-restrictions.md
description: >-
Manage card restriction groups, by creating whitelists and blacklists of
specific countries, merchant ids, and merchant category codes.
---
# Card restriction lists
As an [Administrator](./dashboard-users#accessible-views-per-role), you can add countries, merchant category codes, and merchant ID restriction groups to the Dashboard that can later be associated to the cards. Groups can be either whitelists or blacklists.
## Predef Restriction Groups view
The *Predef Restriction Groups* Administration view provides 3 tabs:
* **MCC Groups** – Create and manage lists for specific [Merchant Category Codes](/guide/overview/glossary#merchant-category-code-mcc).
* **Country Groups** – Create and manage lists for specific countries.
* **Merchant Id Groups** – Create and manage lists for specific [Merchant IDs](/guide/overview/glossary#merchant-identifier-number-mid).
All the tabs are very similar in structure and actions.
## Creating restriction groups
You can add as many restriction groups as you need; you must ensure they are clear for your teams to assign to the cards afterwards (see [Manage Card restrictions](./cards#manage-card-restrictions)).
To create a restriction group, select the tab for the type of restriction and click on the "Add a new restriction" button in the upper right corner.
Then, in the prompted dialog box, enter the name, start date, and type of restriction.
To add elements to the whitelist or blacklist, enter them manually or upload a CSV file.
## Managing restriction groups
For any group, click on the update button in the list to open the *Update a restriction* dialog box, where you can modify all information.
In addition, clicking on the download button allows you to export the list in CSV format. You can then modify the CSV file as you see fit and upload the updated version for easier management of long or complex lists.
Clicking on the "DELETE" command at the end of the table sets the status to "Canceled". This action is irreversible.
---
---
url: /guide/cards/restrictions-limits.md
description: >-
Technical guide to define the card options, permissions, restrictions, and
spending limits. Includes required parameters, request structure, and response
examples.
---
# Restrictions & Limits
Following your [Card Program](/guide/cards/introduction#card-program) and your agreement with Treezor, you can configure the issued cards with options, restrictions, and limits to best suit your use case.
## Options & Permission groups
Card options refer to how a given card can be used. They are preset at the Card Program level with the dedicated [`permsGroup`](#permission-groups-permsgroup) attribute.
The following features are available to the cardholders if authorized at the Card Program level and activated in your Card object:
You can customize each option on a card-by-card basis, as long as you keep in mind that:
* You can’t bypass options blocked by your Card Program.
* Updating the card options automatically updates the permission group value.
### Permission groups (`permsGroup`)
Below is the list of permission group values along with the options they enable.
| `permsGroup` | NFC | ATM | Online | Foreign |
|- |:-: |:-: |:-: |:-: |
| `TRZ-CU-001` | | | | |
| `TRZ-CU-002` | | | | |
| `TRZ-CU-003` | | | | |
| `TRZ-CU-004` | | | | |
| `TRZ-CU-005` | | | | |
| `TRZ-CU-006` | | | | |
| `TRZ-CU-007` | | | | |
| `TRZ-CU-008` | | | | |
| `TRZ-CU-009` | | | | |
| `TRZ-CU-010` | | | | |
| `TRZ-CU-011` | | | | |
| `TRZ-CU-012` | | | | |
| `TRZ-CU-013` | | | | |
| `TRZ-CU-014` | | | | |
| `TRZ-CU-015` | | | | |
| `TRZ-CU-016` | | | | |
### Update card options
Regardless of the card type (virtual or physical), all options must be specified. This aims to smoothly handle the conversion of the card to physical if need be.
#### Parameters
The following parameters are required (`1` for enabled, `0` for disabled).
| Attribute | Type | Description |
| --- | --- | --- |
| `atm` | integer | Defines whether the card can be used for ATM withdrawals. |
| `online` | integer | Defines whether the card can be used for online payments (this also applies to Mail Order, Telephone Order payments). |
| `nfc` | integer | Defines whether the card can be used for contactless payments (NFC). |
| `foreign` | integer | Defines whether the card can be used outside of the cardholder's country. |
#### Request
Use the following request to update the card options.
```bash [CURL]
curl -X PUT '{baseUrl}/v1/cards/{cardId}/Options' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"atm":1,
"online":1,
"nfc":1,
"foreign":0
}
```
Returns the Card object, with the updated options and [`permsGroup`](#permission-groups-permsgroup):
```json [JSON] {8,12-15}
{
"cardId": integer,
"userId": integer,
"walletId": integer,
"publicToken": "string",
"statusCode": "string",
"isLive": integer,
"permsGroup": "TRZ-CU-015",
"cardDesign": "string",
"virtualConverted": integer,
"physical": integer,
"optionAtm": 1,
"optionForeign": 0,
"optionOnline": 1,
"optionNfc": 1,
// [...] some attributes are hidden
}
```
Treezor also sends a [`card.options`](/guide/cards/events#card-options) webhook.
## Payment & Withdrawal limits
Card limits are configurable maximum payment and withdrawal amounts enforced by Treezor servers. They can therefore be updated at any time while abiding by your agreement with Treezor.
### Limit rules and functionalities
Limits can be defined when creating the card, or later on using the dedicated endpoint.
When creating a card, you must define at least one `limitPayment{period}` and one `limitAtm{period}`. Limits that you don't specify automaticaly default to the values set by your *Treezor Account Manager*.
#### Payment limits
| Attribute | Type | Description |
| --- | --- | --- |
| `limitPaymentAll` | integer | Lifetime payment limit |
| `limitPaymentYear` | integer | Yearly payment limit |
| `limitPaymentMonth` | integer | Monthly payment limit |
| `limitPaymentWeek` | integer | Weekly payment limit |
| `limitPaymentDay` | integer | Daily payment limit |
#### Withdrawal limits
| Attribute | Type | Description |
| --- | --- | --- |
| `limitAtmAll` | integer | Lifetime withdrawal limit |
| `limitAtmYear` | integer | Yearly withdrawal limit |
| `limitAtmMonth` | integer | Monthly withdrawal limit |
| `limitAtmWeek` | integer | Weekly withdrawal limit |
| `limitAtmDay` | integer | Daily withdrawal limit |
**Limits are based on Paris timezone by default.**
Meaning that daily limits may not be obvious to your end users if they live under a different timezone.
**You can remove a specific limit, hence not restricting the amount for this limit.**
You can do so by setting the value of the limits you don't need to `0`. However, at least:
* One of the ATM daily, weekly, or monthly limit but be greater than `0`
* One of the Payment daily, weekly, or monthly limit must be greater than `0`
**No consistency checks are made between each period limits.**
The API allows you to define a higher daily than weekly limit, in which case, the lower of the two takes over. Consistency checks should be enforced by your application to avoid confusing end users.
**Prefer the use of `limitPaymentDay`.**
To set the daily payment limit, only one of the 2 following fields should be populated.
| Attribute | Type | Usage |
| --- | --- | --- |
| `paymentDailyLimit` | number | The option dedicated to food vouchers use cases. This is the only limit based on the cardholder's timezone, which can be changed using the `timezone` attribute of the [User](/guide/users/introduction#key-attributes). |
| `limitPaymentDay` | integer | The preferred option, applicable to all other use cases. |
**Limits are sliding limits.**
For example, to evaluate a monthly limit for a transaction made February 15th, Treezor considers all transactions from January 15th (excluded) until February 15th (included).
### Update limits
To update the card limits, you can use the following request with the `cardId` as a path parameter.
Ensure you fill in all the limits below by setting:
* All values you don't need to `0` to deactivate them
* At least one ATM daily, weekly, or monthly limit to another value than `0`
* At least one Payment daily, weekly, or monthly limit to another value than `0`
**Information – Limits can't be expressed in cents**
Limits only accept integer values, which means you can't have limits with decimals (except for `paymentDailyLimit`).
| Attribute | Type | Description |
| --- | --- | --- |
| `limitPaymentAll` | integer | Lifetime payment limit |
| `limitPaymentYear` | integer | Yearly payment limit |
| `limitPaymentMonth` | integer | Monthly payment limit |
| `limitPaymentWeek` | integer | Weekly payment limit |
| `limitPaymentDay` | integer | Daily payment limit |
| `paymentDailyLimit` | number | Daily payment limit (for food vouchers use cases) |
| `limitAtmAll` | integer | Lifetime withdrawal limit |
| `limitAtmYear` | integer | Yearly withdrawal limit |
| `limitAtmMonth` | integer | Monthly withdrawal limit |
| `limitAtmWeek` | integer | Weekly withdrawal limit |
| `limitAtmDay` | integer | Daily withdrawal limit |
```bash [CURL]
curl -X PUT '{baseUrl}/v1/cards/{cardId}/Limits' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"limitPaymentAll":25,
"limitPaymentYear":0,
"limitPaymentMonth":0,
"limitPaymentWeek":10,
"limitPaymentDay":0,
"limitAtmAll":0,
"limitAtmYear":0,
"limitAtmMonth":0,
"limitAtmWeek":10,
"limitAtmDay":0
}
```
Returns the Card object with the updated limit attributes.
```json [JSON] {14-23}
{
"cardId": integer,
"userId": integer,
"walletId": integer,
"publicToken": "string",
"cardTag": "string",
"statusCode": "UNLOCK",
"isLive": 1,
"pinTryExceeds": 0,
"optionAtm": 1,
"optionForeign": 0,
"optionOnline": 1,
"optionNfc": 1,
"limitAtmYear": 0,
"limitAtmMonth": 0,
"limitAtmWeek": 10,
"limitAtmDay": 0,
"limitAtmAll": 0,
"limitPaymentYear": 0,
"limitPaymentMonth": 0,
"limitPaymentWeek": 10,
"limitPaymentDay": 0,
"limitPaymentAll": 25,
// [...] some attributes are hidden
}
```
Treezor also sends a [`card.limits`](/guide/cards/events#card-limits) webhook.
### Update limits in bulk
You may need to update the limits of all your cards at once, as part of a change in daily spendable amount, for instance. Treezor offers dedicated endpoints to update cards in bulk, hence optimizing your processes and offering better performance.
**Information – You can update up to 100,000 cards at once**
The Card Bulk Updates feature processes in average 6,000 cards per minute.
#### Parameters
Below are the necessary parameters to update card limits in bulk.
| Attribute | Type | Description |
| --- | --- | --- |
| `cardIds` | array | The list of cards to update. Each card is an integer, and the API accepts up to 100,000 cards. |
| `bulkUpdateTag` | string | Custom attribute for you to use as you see fit. Can be used to name your bulk update, for instance. |
| `cardAttributes` | object |The limits you can set, according to the rules below. |
Ensure you fill in all the limits below by setting:
* All values you don't need to `0` to deactivate them
* At least one ATM daily, weekly, or monthly limit to another value than `0`
* At least one Payment daily, weekly, or monthly limit to another value than `0`
**Information – Limits can't be expressed in cents**
Limits only accept integer values, which means you can't have limits with decimals (except for `paymentDailyLimit`).
| Attribute | Type | Description |
| --- | --- | --- |
| `limitPaymentAll` | integer | Lifetime payment limit |
| `limitPaymentYear` | integer | Yearly payment limit |
| `limitPaymentMonth` | integer | Monthly payment limit |
| `limitPaymentWeek` | integer | Weekly payment limit |
| `limitPaymentDay` | integer | Daily payment limit |
| `paymentDailyLimit` | number | Daily payment limit (for food vouchers use cases) |
| `limitAtmAll` | integer | Lifetime withdrawal limit |
| `limitAtmYear` | integer | Yearly withdrawal limit |
| `limitAtmMonth` | integer | Monthly withdrawal limit |
| `limitAtmWeek` | integer | Weekly withdrawal limit |
| `limitAtmDay` | integer | Daily withdrawal limit |
**API – API Reference available**
For a complete list of attributes, check the [Card Bulk Updates](/api-reference/api-endpoints.html#tag/Card%20Bulk%20Updates){target="\_self"} section of the API Reference.
#### Request example
Use the following request to create a bulk order.
```bash [CURL]
curl -X POST '{baseUrl}/v1/bulk-updates/cardLimits' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json'
```
Here is an example of `{payload}` for updating limits:
```json [JSON]
{
"cardIds": [12345,23456,34567],
"bulkUpdateTag": "New contract limits May 2025",
"cardAttributes": {
"limitAtmYear": 0,
"limitAtmMonth": 2000,
"limitAtmWeek": 150,
"limitAtmDay": 0,
"limitPaymentYear": 2000,
"limitPaymentMonth": 150,
"limitPaymentWeek": 0,
"limitPaymentDay": 0
}
}
```
Treezor returns the Bulk Update object, which is `IN_PROGRESS`.
```json [JSON] {8}
{
"bulkUpdateTag": "New contract limits May 2025",
"successfulUpdates": null,
"failedUpdates": null,
"createdDate": "2025-04-29 08:54:49",
"modifiedDate": "2025-04-29 08:54:49",
"bulkUpdateId": "a10bbf05-134b-4868-929d-78b12fcaa513",
"bulkUpdateProgressStatus": "IN_PROGRESS",
"bulkUpdateType": "CARD_LIMITS",
"cardAttributes": {
"limitAtmYear": 0,
"limitAtmMonth": 2000,
"limitAtmWeek": 150,
"limitAtmDay": 0,
"limitAtmAll": null,
"limitPaymentYear": 2000,
"limitPaymentMonth": 150,
"limitPaymentWeek": 0,
"limitPaymentDay": 0,
"limitPaymentAll": null,
"paymentDailyLimit": null,
"restrictionGroupLimits": null
},
"totalObjects": 3
}
```
Treezor also sends you the following webhooks:
* [`cardBulkUpdate.create`](./events#cardbulkupdate-create) – The bulk update is created and in progress.
* [`cardBulkUpdate.update`](./events#cardbulkupdate-update) – The bulk update processing is complete. This may take up to 20 minutes.
#### Manage bulk updates
Once you’ve initiated your bulk update, you can follow up on it using the following request.
```bash [CURL]
curl -X GET '{baseUrl}/v1/bulk-updates/{bulkUpdateId}' \
--header 'Authorization: Bearer {accessToken}'
```
Treezor returns the Bulk Update object, in which you can check `bulkUpdateProgressStatus`, and the details of the `successfulUpdates` and `failedUpdates`.
```json [JSON] {3,10,22}
{
"bulkUpdateTag": "New contract limits May 2025",
"successfulUpdates": {
"cardIds": [
12345,
23456
],
"count": 2
},
"failedUpdates": {
"cards": [
{
"reason": "NOT_FOUND",
"id": 12345
}
],
"count": 1
},
"createdDate": "2025-04-29 09:00:45",
"modifiedDate": "2025-04-29 09:00:48",
"bulkUpdateId": "a10bbf05-134b-4868-929d-78b12fcaa513",
"bulkUpdateProgressStatus": "DONE",
"bulkUpdateType": "CARD_LIMITS",
"cardAttributes": {
"limitAtmYear": 0,
"limitAtmMonth": 2000,
"limitAtmWeek": 150,
"limitAtmDay": 0,
"limitAtmAll": null,
"limitPaymentYear": 2000,
"limitPaymentMonth": 150,
"limitPaymentWeek": 0,
"limitPaymentDay": 0,
"limitPaymentAll": null,
"paymentDailyLimit": null,
"restrictionGroupLimits": [
]
},
"totalObjects": 3
}
```
You may also use the [`/v1/bulk-updates`](/api-reference/api-endpoints.html#tag/Card%20Bulk%20Updates/listBulkCardUpdates){target="\_self"} to list all the card bulk updates.
### Check total spent amounts
Specific attributes indicate the total amount spent periodically for ATM and card payments.
When Treezor creates a [Card Transaction](./transactions) object, these total amount spent values are updated if relevant. You can also find them in the [`cardtransaction.create`](events-tx#cardtransactions) webhook.
| Total amount spent | Description | Corresponding limit |
|-------------------------|-------------------| -------------------|
| `totalLimitAtmYear` | The card yearly withdrawal amount. | `limitAtmYear` |
| `totalLimitAtmMonth` | The card monthly withdrawal amount. | `limitAtmMonth` |
| `totalLimitAtmWeek` | The card weekly withdrawal amount. | `limitAtmWeek` |
| `totalLimitAtmDay` | The card daily withdrawal amount. | `limitAtmDay` |
| `totalLimitAtmAll` | The card total withdrawal amount. | `limitAtmAll` |
| `totalLimitPaymentYear` | The card yearly spent amount. | `limitPaymentYear` |
| `totalLimitPaymentMonth` | The card monthly spent amount. | `limitPaymentMonth` |
| `totalLimitPaymentWeek` | The card weekly spent amount. | `limitPaymentWeek` |
| `totalLimitPaymentDay` | The card dayly spent amount. | `limitPaymentDay` |
| `totalLimitPaymentAll` | The card total spent amount. | `limitPaymentAll` |
With this comparison, you can let your users know how much they have left to spend, anticipating any refused transactions due to reached limits.
Please note the total attributes are populated differently depending on the context (e.g., Card or Card Transaction, [`paymentStatus`](/guide/cards/transactions#statuses-paymentstatus)), and only when necessary for performance optimization.
#### Card Transactions total spent amount
In the Card Transaction object, the total attributes are `null` when:
* The [`paymentStatus`](/guide/cards/transactions#statuses-paymentstatus) is other than `A` (Authorized) or `I` (Declined). Authorizations declined by the Card Processor (see [authorization notes](/guide/cards/authorization-notes)) or due to card usage issue (e.g., permissions, status) also result in `null` totals.
* No corresponding limit is given (e.g., if `limitAtmDay` is `0`, then `totalLimitAtmDay` is `null`)
* The limit is a higher or equal to a limit of a higher periodicity (e.g., if `limitPaymentWeek` ≥ `limitPaymentMonth`, then `totalPaymentWeek` is `null`).
#### Cards total spent amount
The total limits are available in the Card object but are only valued when retrieving an individual Card with the [`/v1/cards/{cardId}`](/api-reference/api-endpoints.html#tag/Cards/getCard){target="\_self"} request. Contrary to card transactions, all the total limit fields are populated as long as they have a corresponding limit.
When searching for a list of cards, all the total limits are set to `null`.
Please note the name of the fields differ in the Card object compared to the Card transaction object.
| Total amount spent | Description | Corresponding limit |
|-------------------------|-------------------| -------------------|
| `totalAtmYear` | The card yearly withdrawal amount. | `limitAtmYear` |
| `totalAtmMonth` | The card monthly withdrawal amount. | `limitAtmMonth` |
| `totalAtmWeek` | The card weekly withdrawal amount. | `limitAtmWeek` |
| `totalAtmDay` | The card daily withdrawal amount. | `limitAtmDay` |
| `totalAtmAll` | The card total withdrawal amount. | `limitAtmAll` |
| `totalPaymentYear` | The card yearly spent amount. | `limitPaymentYear` |
| `totalPaymentMonth` | The card monthly spent amount. | `limitPaymentMonth` |
| `totalPaymentWeek` | The card weekly spent amount. | `limitPaymentWeek` |
| `totalPaymentDay` | The card daily spent amount. | `limitPaymentDay` |
| `totalPaymentAll` | The card total spent amount. | `limitPaymentAll` |
## MCC restrictions
[Merchant Category Codes (MCC)](/guide/overview/glossary#merchant-category-code-mcc) restrictions are list-based restrictions allowing you to limit the usage of the card to specific categories of merchants.
### Parameters
| Attribute | Type | Description |
|--- |--- |--- |
| `name` | string | The name of the restriction group. |
| `isWhitelist` | boolean | Indicates the kind of restriction: `true` (default) – Allows only a specified list of merchant categories (whitelist)`false` – Allows all merchant categories except the specified list (blacklist) |
| `mcc` | array | The list of MCCs (each MCC is an integer). |
| `status` | string | One of the following values:`VALIDATED` – The restriction is active.`PENDING` (default) – The restriction is created but not yet active.`CANCELED` – The restriction has been deactivated (this is irreversible). |
| `startDate` | string | The date and time at which the restriction starts. Defaults to the date and time of creation. |
### Request
To create MCC restrictions, you can use the following request:
```bash [CURL]
curl -X POST '{baseUrl}/v1/mccRestrictionGroups' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"name": "Restriction Restaurant, Bar, Fast-Food",
"isWhitelist": true,
"mcc": [
5812,
5813,
5814
],
"startDate": "2024-05-01 00:00:00"
}
```
Returns the Merchant ID Restriction Group object with its `id` (that you should keep on your side to apply these restrictions to Cards).
```json [JSON]
{
"mccRestrictionGroups": [
{
"id": 47597,
"name": "Restriction Restaurant, Bar, Fast-Food",
"isWhitelist": true,
"mcc": [
5812,
5813,
5814
],
"status": "PENDING",
"startDate": "2024-05-01 00:00:00",
"createdDate": "2024-04-24 09:04:38",
"modifiedDate": null
}
]
}
```
Treezor also sends a [`mccGroup.create`](/guide/cards/events#mccgroup-create) webhook.
### Apply the restriction
To apply the restriction to a card, set the `mccRestrictionGroupId` value to the previously obtained `id` when creating or updating the card:
* [`/v1/cards/CreateVirtual`](/api-reference/api-endpoints.html#tag/Cards/postCardVirtual){target="\_self"}
* [`/v1/cards/RequestPhysical`](/api-reference/api-endpoints.html#tag/Cards/postCardPhysical){target="\_self"}
* [`/v1/cards/{cardId}`](/api-reference/api-endpoints.html#tag/Cards/putCard){target="\_self"}
## Country restrictions
You may restrict a Card use in some countries only.
### Parameters
| Attribute | Type | Description |
|--- |--- |--- |
| `name` | string | The name of the restriction group |
| `isWhitelist` | boolean | Indicates the kind of restriction: `true` (default) – Allows only a specified list of countries (whitelist)`false` – Allows all countries except the specified list (blacklist) |
| `countries` | array of strings | The list of countries (each country is a string featuring a Country Code in the [ISO 3166-1 numeric format 3-digit code](https://en.wikipedia.org/wiki/ISO_3166-1_numeric)). |
| `status` | string | One of the following values:`VALIDATED` – The restriction is active.`PENDING` (default) – The restriction is created but not yet active.`CANCELED` – The restriction has been deactivated (this is irreversible). |
| `startDate` | string | The date and time at which the restriction starts. Defaults to the date and time of creation. |
**Caution – Use the ISO 3166-1 numeric format**
Contrary to other endpoints, here countries are expected in [**ISO 3166-1 numeric format** (a 3-digit code)](https://en.wikipedia.org/wiki/ISO_3166-1_numeric).
### Request
To create country restrictions, you can use the following request:
```bash [CURL]
curl -X POST '{baseUrl}/v1/countryRestrictionGroups' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"name": "Restriction Belgium, Germany, France",
"isWhitelist": true,
"countries": [
"250",
"276",
"056"
],
"startDate": "2024-05-01 00:00:00"
}
```
Returns the Country Restriction Group object with its `id` (that you should keep on your side to apply these restrictions to Cards).
```json [JSON]
{
"countryRestrictionGroups": [
{
"id": 179655,
"name": "Restriction Belgium, Germany, France",
"isWhitelist": true,
"countries": [
"250",
"276",
"056"
],
"status": "PENDING",
"startDate": "2024-05-01 00:00:00",
"createdDate": "2024-04-24 08:55:26",
"modifiedDate": null
}
]
}
```
Treezor also sends a [`countryGroup.create`](/guide/cards/events#countrygroup-create) webhook.
### Apply the restriction
To apply the restriction to a card, set the `countryRestrictionGroupId` value to the previously obtained `id` when creating or updating the card:
* [`/v1/cards/CreateVirtual`](/api-reference/api-endpoints.html#tag/Cards/postCardVirtual){target="\_self"}
* [`/v1/cards/RequestPhysical`](/api-reference/api-endpoints.html#tag/Cards/postCardPhysical){target="\_self"}
* [`/v1/cards/{cardId}`](/api-reference/api-endpoints.html#tag/Cards/putCard){target="\_self"}
## MID restrictions
[Merchant Id (MID)](/guide/overview/glossary#merchant-identification-number-mid) restrictions are list-based restrictions allowing you to limit the usage of the card to specific merchants.
You can restrict MID in one of two ways:
* **Allowing only** a specified list of merchants (whitelist)
* **Allowing all merchants except** a specified list (blacklist)
If you plan on creating more than 20 MID restriction lists, please contact Treezor.
### Parameters
| Attribute | Type | Description |
|--- |--- |--- |
| `name` | string | The name of the restriction group |
| `isWhitelist` | boolean | Indicates the kind of restriction: `true` (default) – Allows only a specified list of merchants (whitelist)`false` – Allows all merchants except the specified list (blacklist) |
| `merchants` | array of strings | The list of MIDs (each MID is a string). |
| `status` | string | One of the following values:`VALIDATED` – The restriction is active.`PENDING` (default) – The restriction is created but not yet active.`CANCELED` – The restriction has been deactivated (this is irreversible). |
| `startDate` | string | The date and time at which the restriction starts. Defaults to the date and time of creation. |
### Request
To create MID restrictions, you can use the following request:
```bash [CURL]
curl -X POST '{baseUrl}/v1/merchantIdRestrictionGroups' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"name": "Restriction merchantId 2024",
"isWhitelist": true,
"merchants": [
"44355534500019",
"ZWORT8KLOW9",
"8935467"
],
"startDate": "2024-05-01 00:00:00"
}
```
Returns the `merchantIdRestrictionGroups` object with its `id` (that you should keep on your side to apply these restrictions to Cards).
```json [JSON]
{
"merchantIdRestrictionGroups": [
{
"id": 104734,
"name": "Restriction merchantId 2024",
"isWhitelist": true,
"status": "PENDING",
"startDate": "2024-05-01 00:00:00",
"createdDate": "2024-04-24 09:09:59",
"modifiedDate": null
}
]
}
```
Treezor also sends a [`merchantIdGroup.create`](/guide/cards/events#merchantidgroup-create) webhook.
**Alert – Chain stores don't have a unique MID**
Note that each shop of a chain store has its own `merchantId`, in such a situation you may want to use [MCC](/guide/overview/glossary) instead (which could block more than expected) or explicitly list all the relevant `merchantId`.
Treezor offers the [MID Metadata endpoint](/guide/cards/restrictions-limits#mid-metadata) to help you associate metadata to MIDs.
### Apply the restriction
To apply the restriction to a card, set the `merchantRestrictionGroupId` value to the previously obtained `id` when creating or updating the card:
* [`/v1/cards/CreateVirtual`](/api-reference/api-endpoints.html#tag/Cards/postCardVirtual){target="\_self"}
* [`/v1/cards/RequestPhysical`](/api-reference/api-endpoints.html#tag/Cards/postCardPhysical){target="\_self"}
* [`/v1/cards/{cardId}`](/api-reference/api-endpoints.html#tag/Cards/putCard){target="\_self"}
## MID Metadata
In some cases, the [Merchant Id (MID)](/guide/overview/glossary#merchant-identification-number-mid) may not be up-to-date or the given information not enough for you to act on it. Treezor offers endpoints to add metadata to MIDs, hence allowing you to add human-readable information as you see fit.
### Add metadata to a MID
To add metadata to a MID, you may use the following request by populating the metadata freely in the body (except for the `mid` attribute which is reserved).
```bash [CURL]
curl -X PUT '{baseUrl}/core-connect/mid/{mid}/metadata' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`.
```json [JSON]
{
"contact": "100@example.com",
"address": "1208, Willow lane, 75000 Paris"
}
```
Returns the object you've created with a 201 Created HTTP Status code.
```json [JSON]
{
"contact": "100@example.com",
"address": "1208, Willow lane, 75000 Paris"
}
```
You can then retrieve this information by using the following request:
* [`/core-connect/mid/{mid}/metadata`](/api-reference/api-endpoints.html#tag/Merchant%20ID%20Metadata/getMidMetadata){target="\_self"}
### Manage metadata in bulk
You can use the following request to either add or update metadata in bulk.
```bash [CURL]
curl -X PUT '{baseUrl}/core-connect/mid/metadata' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`.
```json [JSON]
[
{
"mid": "100",
"contact": "100@example.com",
"address": "1208, Willow lane, 75000 Paris",
"siret": "348674XXXX067"
},
{
"mid": "200",
"contact": "200@example.com",
"address": "1208, Ashwood street, Madrid"
},
{
"mid": "300",
"contact": "300@example.com",
"address": "1208, Rosewood road, London"
}
]
```
Returns a `204` HTTP Status Code without any content.
### Retrieve all MID metadata
You may use the following request to retrieve all the MID metadata you populated.
```bash [CURL]
curl -X GET '{baseUrl}/core-connect/mid/metadata' \
--header 'Authorization: Bearer {accessToken}'
```
Returns all the MID metadata object you've created.
```json [JSON]
[
{
"mid": "100",
"contact": "100@example.com",
"address": "1208, Willow lane, 75000 Paris",
"siret": "348674XXXX067"
},
{
"mid": "200",
"contact": "200@example.com",
"address": "1208, Ashwood street, Madrid"
},
{
"mid": "300",
"contact": "300@example.com",
"address": "1208, Rosewood road, London"
}
]
```
You can also retrieve the metadata for all MIDs belonging to a previously created [MID Restriction Group](#mid-restrictions) using the following request:
* [`/core-connect/merchantIdRestrictionGroups/{groupId}/mid/metadata`](/api-reference/api-endpoints.html#tag/Merchant%20ID%20Metadata/getAllMidMetadataBYyGroup){target="\_self"}
This request returns the list of MIDs along with their metadata. The list a paginated using a [cursor](/guide/api-basics/pagination#cursor-based-pagination).
## Group limits
Group limits (or multi-loop) offers more freedom configuring limits and restrictions in some advanced cases.
**Information – Treezor offers its own [Transaction Rules Engine](/guide/cards/transactions-rules-engine)**
Historically, group limits were designed for food vouchers use cases. Treezor [Transactions Rules Engine](./transactions-rules-engine) offers an even better way to handle such cases, allowing you to define contextual rulesets, evaluated at each transaction.
Contact Treezor to find out which option works best for you.
You can create groups of limits and restrictions upon creating of updating a [Card](/guide/cards/introduction) using the `restrictionGroupLimits` attribute. This array allows you to create an object for each group of limits, and each object can contain:
* `paymentDailyLimit` – For [payment limits](#payments-withdrawals-limits)
* `mccRestrictionGroups` – For [MCC restrictions](#mcc-restrictions)
* `countryRestrictionGroups` – For [countries restrictions](#country-based-restrictions)
* `merchantIdRestrictionGroups` – For [MID restrictions](#list-based-restrictions)
In doing so, you may have a GroupLimit covering restaurants with its own daily payment limit, and a second GroupLimit covering fresh food stores with a different daily payment limit.
Your [Cards](/guide/cards/introduction) could therefore be used in both restaurant and fresh food store, but with distinct payment limits for each situation.
---
---
url: /guide/cards/sensitive-data.md
description: >-
Learn the end-to-end encryption best practices to expose the card sensitive
data such as PAN, CVV, and PIN in the context of the PCI DSS integration.
Includes code examples for private key generation and encryption.
---
# Displaying sensitive data
[PCI DSS](/guide/cards/pci-dss) allows for an enhanced experience for the cardholders. You can display sensitive information as an image or text, and instantly copy it. This applies to the card PIN, number (PAN), and verification code (CVV).
You must use asymmetric **end-to-end encryption** when it comes to exposing the following card data.
| Sensitive data | Endpoint |
| --- | --- |
| **Card Image** | [`/cards/{cardId}/cardImage`](/api-reference/pci-dss-dev.html#tag/Cards/getCardImage){target="\_self"} |
| **PAN & CVV** | [`/cards/{cardId}/pan`](/api-reference/pci-dss-dev.html#tag/Cards/getPAN){target="\_self"} |
| **PIN** | [`/cards/{cardId}/pin`](/api-reference/pci-dss-dev.html#tag/Cards/getPIN){target="\_self"} |
**API – API Reference available**
For a complete list of attributes for these endpoints, check the [PCI DSS API Reference](/api-reference/pci-dss-dev).
This article focuses on the [`/cards/{cardId}/pan`](/api-reference/pci-dss-dev.html#tag/Cards/getPAN){target="\_self"} for the examples, but the same process applies to all endpoints containing sensitive data.
## Process
Here are the steps for exposing sensitive data.
```mermaid
sequenceDiagram
participant user as Cardholder's device
participant agent as Your back end
participant trz as Treezor
autonumber
user->>user: Generates asymmetric key pair (public & private keys)
user->>agent: Sends public key
rect rgba(234, 236, 238, 0.5)
agent->>trz: Makes PCI DSS request
Note over agent,trz: with public key
end
trz->>agent: Returns base64-encrypted data
agent->>user: Returns base64-encrypted data
user->>user: Base64-decodes & decrypts data with private key and exposes it to the cardholder
user->>user: Destroys decrypted data and asymmetric key pair once consulted by cardholder
```
## 1. Generate an asymmetric key pair on the end user’s device
Asymmetric encryption consists of using a key pair, with each key fulfilling its specific role:
* **Public key** – Used to encrypt data
* **Private key** – Used to decrypt data, and cannot be shared
**Security – Generate at least 1 key pair per user**
Key pairs must be unique for each of your end users. For optimal security, you should rely on single-use key pairs (i.e., generate a key pair for each request).
Treezor PCI DSS-specific endpoints support 2 encryption methods: `OPENPGP_ARMOR` or `LIBSODIUM_HEX`.
### Example for OpenPGP
**Best practice – Formatting your keys with OpenPGP**
* **Type**: RSA
* **Size**: min. 2048, recommended 4096
Find below an extract of the [functional code](#example-for-openpgp-2) available at the end of the article.
```js [JavaScript]
/* import openpgp v5.11.2. You can find it here https://github.com/openpgpjs/openpgpjs/blob/main/README.md#getting-started */
function PgpStrategy() {
this.privateKey = ''
this.publicKey = ''
this.passphrase = ''
this.option = {
userIDs: [{ name: "your_company_name", email: "your_company_email@email.com" }], // TODO replace name and email by yours.
type:'rsa',
rsaBits: "4096",
passphrase: this.passphrase,
}
...
return {
generateKeyPair: async () => {
const keyPair = await openpgp.generateKey(this.option)
this.privateKey = keyPair.privateKey
this.publicKey = keyPair.publicKey
return this.publicKey
},
...
}
};
```
### Example for Libsodium
Find below an extract of the [functional code](#example-for-libsodium-2) available at the end of the article.
```js [JavaScript]
/* import libsodium-wrappers v0.5.4. You can find it here https://www.npmjs.com/package/libsodium-wrappers?activeTab=readme */
function LibsodiumStrategy () {
this.privateKey = ''
this.publicKey = ''
return {
...
generateKeyPair: async () => {
await sodium.ready
const keyPair = await sodium.crypto_box_keypair()
this.privateKey = sodium.to_hex(keyPair.privateKey)
this.publicKey = sodium.to_hex(keyPair.publicKey)
return this.publicKey
},
...
}
}
```
Now that the key pair has been generated on the end user's device, you can send the public key to your servers to then pass it along to Treezor in the next step.
**However, it is strictly forbidden to share the private key; only the cardholder's device can access it.**
## 2. Make your Treezor request with the cardholder's public key
Make your Treezor request with the cardholder's public key from your server using the [mTLS](/guide/api-basics/mutual-tls) mechanism described in the [PCI DSS integration](/guide/cards/pci-dss) article.
The following parameters must be used for Treezor sensitive endpoints:
* `algorithm` – The encryption method used (`OPENPGP_ARMOR` or `LIBSODIUM_HEX`)
* `userPublicKeyBase64` – The previously generated encrypted user public key (base64-encoded).
Here is an example when retrieving the card PAN and CVV ([`/cards/{cardId}/pan`](/api-reference/pci-dss-dev.html#tag/Cards/getPAN){target="\_self"} ).
```go [Golang]
package main
import (
"encoding/base64"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
)
type getEncryptedCardDataResponse struct {
EncryptedCardData string `json:"encryptedCardData,omitempty"`
}
// GetPAN sends a PCI request to retrieve the PAN.
func GetPAN() {
request, err := GenerateRequest(
http.MethodGet,
"https://client.preprod.secure.treezor.co/cards/1234/pan",
map[string]string{
"algorithm": "OPENPGP_ARMOR",
"userId": "5678",
"withCVV": "true",
"userPublicKey": base64.StdEncoding.EncodeToString([]byte("cardholder's OpenPGP public key value")),
"sca": "sca-proof-value",
},
"jwtToken",
"scaProof",
nil,
)
if err != nil {
log.Fatalf("failed to generate request: %s", err)
}
response, err := SendUsingMTLS(request)
if err != nil {
log.Fatalf("failed to send request: %s", err)
}
if response.StatusCode != http.StatusOK {
body, _ := io.ReadAll(response.Body)
log.Fatalf("unexpected status code: %d with body: %s", response.StatusCode, string(body))
}
getCardDataResponse := &getEncryptedCardDataResponse{}
err = json.NewDecoder(response.Body).Decode(&getCardDataResponse)
if err != nil {
log.Fatalf("failed to read get encrypted card data response: %s", err)
}
// Base64 encrypted content
fmt.Println(getCardDataResponse.EncryptedCardData)
}
```
```php [PHP]
'OPENPGP_ARMOR',
'userId' => '8364813',
'withCVV' => true,
'userPublicKey' => base64_encode(file_get_contents(PGP_FILE)),
'sca' => $scaProof,
];
try {
$request = generateRequest(
'GET',
'https://.preprod.secure.treezor.co/cards/1234/pan',
$queryParams,
$jwtToken,
$scaProof,
''
);
} catch (RuntimeException $exception) {
$logger->error(sprintf('Failed to generate request %s', $exception->getMessage()));
return;
}
try {
$response = sendUsingMTLS($request);
} catch (ClientExceptionInterface $exception) {
$logger->error(sprintf('Failed to send request %s', $exception->getMessage()));
return;
}
if ($response->getStatusCode() !== 200) {
throw new RuntimeException(sprintf('Unexpected status code: %d with body: %s', $response->getStatusCode(), $response->getBody()->getContents()));
}
$cardDataResponse = json_decode($response->getBody()->getContents(), true);
if (!$cardDataResponse) {
$logger->error('Failed to read get encrypted card data response');
}
// Base64 encrypted content
echo $cardDataResponse;
}
```
The Treezor returns the base64-encrypted data.
For example, the response for the [`/cards/{cardId}/pan`](/api-reference/pci-dss-dev.html#tag/Cards/getPAN){target="\_self"} request.
```json [JSON]
{
"encryptedCardData": ""
}
```
The encrypted data must be sent to the end user's device for the decryption step.
## 3. Use the private key on the end user's device for decryption
Once the cardholder's device retrieved the encrypted data, it can use the private key for decryption.
### Example for OpenPGP
Find below an extract of the [functional code](#example-for-openpgp-2) available at the end of the article.
```js [JavaScript]
/* import openpgp v5.11.2. You can find it here https://github.com/openpgpjs/openpgpjs/blob/main/README.md#getting-started */
function PgpStrategy() {
this.privateKey = ''
this.publicKey = ''
this.passphrase = ''
return {
decrypt: async (cypherText) => {
const privKey = await openpgp.decryptKey({
privateKey: await openpgp.readPrivateKey({ armoredKey: this.privateKey }),
passphrase: this.passphrase
});
return await openpgp.decrypt({
message: await openpgp.readMessage({armoredMessage:cypherText}),
decryptionKeys: privKey
});
},
...
}
};
```
### Example for Libsodium
Find below an extract of the [functional code](#example-for-libsodium-2) available at the end of the article.
```js [JavaScript]
/* import libsodium-wrappers v0.5.4. You can find it here https://www.npmjs.com/package/libsodium-wrappers?activeTab=readme */
function LibsodiumStrategy () {
this.privateKey = ''
this.publicKey = ''
return {
decrypt: async (hexCypherText) => {
let outputFormat = 'text';
return await sodium.crypto_box_seal_open(
sodium.from_hex(hexCypherText),
sodium.from_hex(this.publicKey),
sodium.from_hex(this.privateKey),
outputFormat
)
},
...
}
}
```
### Decrypted data example
Once decrypted, here is the payload you should have for the [`/cards/{cardId}/pan`](/api-reference/pci-dss-dev.html#tag/Cards/getPAN){target="\_self"} request, whether you chose to include the CVV or not.
```json [JSON (PAN & CVV)]
{
"pan": "1234567898765432",
"cvv": "123"
}
```
```json [JSON (PAN only)]
{
"pan": "1234567898765432"
}
```
**Security – Destroy sensitive data once viewed by the cardholder**
You must destroy both the decrypted data and the asymmetric key pair after usage. If the user wishes to view their card information again, you must redo the whole process.
## Full examples
### Example for OpenPGP
**Best practice – Formatting your keys with OpenPGP**
* **Type**: RSA
* **Size**: min. 2048, recommended 4096
```js [JavaScript]
/* import openpgp v5.11.2. You can find it here https://github.com/openpgpjs/openpgpjs/blob/main/README.md#getting-started */
function PgpStrategy() {
this.algoName = 'OPENPGP_ARMOR'
this.privateKey = ''
this.publicKey = ''
const generateRandomPassphrase = length => {
const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+{}[]|;:<>,.?/~";
let passphrase = "";
for (let i = 0; i < length; i++) {
const randomIndex = Math.floor(Math.random() * charset.length);
passphrase += charset[randomIndex];
}
return passphrase;
}
this.passphrase = generateRandomPassphrase(16)
this.option = {
userIDs: [{ name: "cardholder", email: "cardholder_email@example.com" }], // TODO replace name and email by yours.
type:'rsa',
rsaBits: "4096",
passphrase: this.passphrase,
}
return {
getAlgoName: () => {
return this.algoName
},
generateKeyPair: async () => {
const keyPair = await openpgp.generateKey(this.option)
this.privateKey = keyPair.privateKey
this.publicKey = keyPair.publicKey
return this.publicKey
},
// TODO remove encrypt function. needed only to simulate PCI-DSS encryption in this code snippet.
encrypt: async (textToEncrypt) => {
const pubKey = await openpgp.readKey({ armoredKey: this.publicKey})
return btoa(await openpgp.encrypt({
message: await openpgp.createMessage({ text: textToEncrypt}),
encryptionKeys: pubKey
}))
},
decrypt: async (cypherText) => {
const privKey = await openpgp.decryptKey({
privateKey: await openpgp.readPrivateKey({ armoredKey: this.privateKey }),
passphrase: this.passphrase
});
return await openpgp.decrypt({
message: await openpgp.readMessage({armoredMessage:cypherText}),
decryptionKeys: privKey
});
},
removeKeyPair: () => {
this.privateKey = ''
this.publicKey = ''
this.passphrase = ''
}
}
};
// displaySensitiveData function on cardholder application.
async function displaySensitiveData(){
let pgp= new PgpStrategy()
pgp.generateKeyPair().then((pubKey)=>{
// TODO replace the pgp.encrypt call below by the call to your back end with needed data, for example:
// call(cardId, userId, pgp.getAlgoName(), pubKey,...).then(base64EncodedEncryptedData => {...
pgp.encrypt('1234').then(base64EncodedEncryptedData => {
// keep code below
pgp.decrypt(atob(base64EncodedEncryptedData))
.then(decrypted =>{console.log('decrypted:'+decrypted.data)})
.catch(err=> {console.log(err)})
.finally(function(){
pgp.removeKeyPair();
});
}).catch(err => {console.log(err)});
}).catch(err=> {console.log(err)})
}
displaySensitiveData()
```
### Example for Libsodium
```js [JavaScript]
/* import libsodium-wrappers v0.5.4. You can find it here https://www.npmjs.com/package/libsodium-wrappers?activeTab=readme */
function LibsodiumStrategy () {
this.algoName = 'LIBSODIUM_HEX'
this.privateKey = ''
this.publicKey = ''
return {
getAlgoName: () => {
return this.algoName
},
generateKeyPair: async () => {
await sodium.ready
const keyPair = await sodium.crypto_box_keypair()
this.privateKey = sodium.to_hex(keyPair.privateKey)
this.publicKey = sodium.to_hex(keyPair.publicKey)
return this.publicKey
},
decrypt: async (hexCypherText) => {
let outputFormat = 'text';
return await sodium.crypto_box_seal_open(
sodium.from_hex(hexCypherText),
sodium.from_hex(this.publicKey),
sodium.from_hex(this.privateKey),
outputFormat
)
},
// TODO remove encrypt function. needed only to simulate PCI-DSS encryption in this code snippet.
encrypt: (plainText) => {
const cypherText = sodium.crypto_box_seal(
plainText,
sodium.from_hex(this.publicKey)
)
return btoa(sodium.to_hex(cypherText));
},
removeKeyPair: () => {
this.privateKey = ''
this.publicKey = ''
}
}
}
// displaySensitiveData function on cardholder application.
async function displaySensitiveData(){
const libso= new LibsodiumStrategy()
libso.generateKeyPair().then((pubKey) =>{
// TODO replace the libso.encrypt call below by the call to your back end with needed data, for example:
// call(cardId, userId, libso.getAlgoName(), pubKey,...).then(base64EncodedEncryptedData => {...
const base64EncodedEncryptedData = libso.encrypt('1234')
// keep code below
libso.decrypt(atob(base64EncodedEncryptedData))
.then(decrypted =>{console.log('decrypted:'+decrypted)})
.catch(err=> {console.log(err)})
.finally(function(){
libso.removeKeyPair();
});
}).catch(err=> {console.log(err)})
}
displaySensitiveData()
```
---
---
url: /guide/cards/transactions-lifecycle.md
description: >-
Explore all the steps of the card transaction life cycle, with the relevant
statuses.
---
# Transactions life cycle
You will find below details about each possible step, why they occur, and how to use them.
Most steps send a [`cardtransaction.create`](/guide/cards/events) webhook. If they are generated by the same payment, then they will share the same `paymentId` value.
## Authorization
Authorization is the first step of a card payment.
An authorization allows the [merchant](/guide/overview/glossary#merchant) to request the approval of the issuer for a transaction. When a cardholder pays or makes a withdrawal with their card, an authorization request is sent to Treezor, allowing the cardholder's spending limits and restrictions to be enforced.
A yes/no decision ([accepted](#authorization-accepted)/[declined](#authorization-declined)) is then provided to the acquirer and merchant/[ATM](/guide/overview/glossary#automated-teller-machine-atm).
### Authorization accepted
This immediately deduces the amount from the \[Authorized Balance]\(/guide/wallets/balances of the cardholder but leaves the [Balance](/guide/wallets/balances) unchanged.
When an authorization is accepted, a card transaction is created, with one of the following [payment status](/guide/cards/transactions#statuses-paymentstatus).
| [`paymentStatus`](/guide/cards/transactions#statuses-paymentstatus) | Event | Description |
| --- | --- | --- |
| `A` (Accepted) | `cardTransaction.create` | When the transaction is authorized normally. |
| `C` (Cleared) | `cardTransaction.create` | When the authorization occurred offline. |
**Information – Offline transactions are processed asynchronously**
You're notified only once the merchant's clearing is received. It may take up to several days after the cardholer's purchase for the clearing to occur.
### Authorization declined
A declined transaction is final and not followed by any other operations. It doesn't affect either the [Balance](/guide/wallets/balances) nor the [Authorized Balance](/guide/wallets/balances).
When an authorization is declined, a card transaction is created, with the following [payment status](/guide/cards/transactions#statuses-paymentstatus).
| [`paymentStatus`](/guide/cards/transactions#statuses-paymentstatus) | Event | Description |
| --- | --- | --- |
| `I` (Declined) | `cardTransaction.create` | When the transaction isn't authorized. |
Possible [reasons](/guide/cards/authorization-notes) for decline include (but are not limited to):
* An online payment is attempted, but the [Card options don't allow online payments](/guide/cards/restrictions-limits#options-permission-groups)
* The payment amount is higher than the [Card payment limit](/guide/cards/restrictions-limits#payment-withdrawal-limits)
* The `merchantId` that requests the authorization is [blacklisted](/guide/cards/restrictions-limits#mid-restrictions) in the Card options
* The cardholder has insufficient funds
* A network error occurred
**Information – The decline reason is in the [`cardtransaction`](events-tx#cardtransactions) webhook:**
* [`authorizationResponseCode`](/guide/cards/authorization-notes#authorization-response-codes) attribute
* [`authorizationNote`](/guide/cards/authorization-notes) attribute when relevant
In some situations, when an error occurred high up in the banking network (Negative Advice), you were not notified of the transaction attempt and of its decline. Producing a situation where your customer was aware of an authorization failure, but your Dashboard Users were not.
**You can now opt-in to receive these notifications. They will produce `cardtransaction.create` webhooks with a `paymentStatus` valued to `I`.**
### Authorization accepted, then declined
This is a very rare case. It can occur when Treezor accepts an authorization, but the acceptance doesn't reach the [merchant](/guide/overview/glossary#merchant) because of *card network* errors. When this happens, a declined authorization is emitted in the hours that follow.
## Partial Authorization
A partial authorization occurs when there are insufficient funds to cover the full amount of the transaction. In such cases, if the merchant handles partial authorizations and if the transaction is in euros, then only the amount available is authorized.
The partial authorization have the following attributes.
| Attribute | Value |
| --- | --- |
| [`paymentStatus`](./transactions#statuses-paymentstatus) | A (Accepted) |
| [`authorizationResponseCode`](/guide/cards/authorization-notes#authorization-response-codes) | 10 (PARTIAL\_APPROVAL) |
Let's take the example of a transaction at an automated fuel dispenser.
1. An authorization request of €150 is issued by the dispenser.
2. The cardholder account balance is €100.
3. The card transaction is partially authorized.
4. The cardholder can use the dispenser for up to €100 of fuel.
## Pre-Authorization
A pre-authorization is generally used when the final transaction amount is not yet known in order to put a hold on an amount approved by the issuer. For example, [at an automated fuel dispenser](/guide/cards/transactions-examples#gas-station-transaction).
Pre-Authorization behaves exactly like authorization. Only the [`authorizationNote`](/guide/cards/authorization-notes) attribute of a webhook may specify "pre-authorization".
**Information – Specific processing for USA and Canada AFDs**
Treezor applies a fixed pre-authorized amount of €160 for all pre-authorization requests made in the USA or Canada for automated fuel dispensers (AFD) payments. Learn more in the [automated fuel dispenser](/guide/cards/transactions-examples#gas-station-transaction) example.
## Settlement
The settlement is the step where funds are actually debited from the cardholder's wallet/account and credited to the merchant's wallet/account. It generally shows up three days after the authorization and affects the [Balance](/guide/wallets/balances).
**A settlement can be complete, partial, and even multiple**
Consider an authorization of €1,000. There could be:
* A single settlement of €1,000
* One settlement of €750 and a reversal of €250
* Two settlements of €500 each
* Three settlements of €333.33 each
* etc.
When a settlement occurs, a card transaction is created, with the following [payment status](/guide/cards/transactions#statuses-paymentstatus).
| [`paymentStatus`](/guide/cards/transactions#statuses-paymentstatus) | Event | Description |
| --- | --- | --- |
| `S` (Settled) | `cardTransaction.create` | When the transaction is settled. |
## MoneySend
**Important – Progressive feature rollout**
The MoneySend transaction feature will be rolled out progressively. Your *Account Manager* will contact you to adjust your implementation as needed.
A MoneySend card transaction credits the cardholder's account.
It occurs in 2 steps:
* **Authorization**, during which Treezor verifies the MoneySend validity (account and card).
* **Settlement**, after which the funds can be used by the cardholder. This generally the day after the authorization.
These transactions can be accepted or refused in the same way as authorizations.
**Note – The amount is not available to the cardholder until the settlement is received**
You can rely on the authorization webhook which indicates that the transaction is in progress.
In the webhooks received for MoneySend transactions, amounts are displayed as negative values. For example: `"paymentAmount": "-7.00"`
Also, MoneySend card transactions can have one of the following [MCC](/guide/overview/glossary#merchant-category-code-mcc):
* `6536` for MONEYSEND INTRACOUNTRY
* `6537` for MONEYSEND INTERCOUNTRY
When a MoneySend transaction occurs, a card transaction is created, with one of the following [payment status](/guide/cards/transactions#statuses-paymentstatus).
| [`paymentStatus`](/guide/cards/transactions#statuses-paymentstatus) | Event | Description |
| --- | --- | --- |
| `M` (MoneySend) | `cardTransaction.create` | When the MoneySend transaction is accepted. |
| `S` (Settled) | `cardTransaction.create` | When the MoneySend transaction is settled. |
| `I` (Declined) | `cardTransaction.create` | When the MoneySend transaction is refused. |
### MoneySend and external validation
When using [Transactions external validation](/guide/cards/transactions-external-validation), you can identify MoneySend transactions thanks to the [`mcc`](/guide/overview/glossary#merchant-category-code-mcc) attribute valued to `6536` or `6537`.
**Alert – MoneySend Intercountry is not available yet**
Therefore, even if you accept a MoneySend transaction with the `6537` MCC through external validation, Treezor will decline the transaction.
The webhooks sent will be exactly the same as for a regular MoneySend transaction, as described above.
## Reversal
A reversal follows an accepted authorization and cancels it at the merchant's request.
Funds have not yet been debited nor credited when a reversal occurs, so only the [**Authorized Balance**](/guide/wallets/balances) of the cardholder is affected.
**A reversal can be complete or partial.**
Consider an authorization of €1000. There could be:
* One reversal of €1,000
* One reversal of €100 and a settlement of €900
* One reversal of €900 and a settlement of €100
* etc.
When a Reversal occurs, a card transaction is created, with the following [payment status](/guide/cards/transactions#statuses-paymentstatus).
| [`paymentStatus`](/guide/cards/transactions#statuses-paymentstatus) | Event | Description |
| --- | --- | --- |
| `V` (Reversed) | `cardTransaction.create` | When the merchant cancels an accepted authorization. |
## Refunds
A refund is the act of **requesting a refund**, when **funds have effectively been debited from the cardholder's wallet** (due to a previous *settlement*).
Therefore, a refund affects the [**Balance**](/guide/wallets/balances).
They behave in a similar way as *authorizations* do:
* They can be either accepted or declined
* They can be followed by a complete or partial settlement (of negative amount value)
### Refund accepted
When a Refund is accepted, 2 card transactions are usually created, with the following [payment status](/guide/cards/transactions#statuses-paymentstatus).
| [`paymentStatus`](/guide/cards/transactions#statuses-paymentstatus) | Event | Description |
| --- | --- | --- |
| `R` (Refund) | `cardTransaction.create` | When the Refund is accepted. A negative `amount` is displayed. |
| `S` (Settled) | `cardTransaction.create` | If the Refund is settled. A negative `amount` is displayed. |
Please note however that the transaction might not be settled. In such cases, the Wallet isn't credited.
### Refund declined
When a Refund is declined, a card transaction is created, with the following [payment status](/guide/cards/transactions#statuses-paymentstatus).
| [`paymentStatus`](/guide/cards/transactions#statuses-paymentstatus) | Event | Description |
| --- | --- | --- |
| `I` (Declined) | `cardTransaction.create` | When the Refund is declined. |
## Chargeback
Chargeback is a process that happens when the cardholder disputes a card payment that has been approved and settled.
The reason for the dispute may be due to a suspected fraud or an unfulfilled order of goods/services. The chargeback is initiated by the issuer at the request of the cardholder. If accepted, the cardholder account will be credited.
## Expiration
An expiration occurs when an *Authorization* was accepted but was not followed by any settlement or reversal in the 10 following days.
On the night of the 10th to 11th day, the [Authorized Balance](/guide/wallets/balances) is freed up.
**Expirations don't create `cardTransaction` webhooks or operations.**
---
---
url: /guide/cards/transactions-authentication.md
description: >-
Learn how to handle notifications of strong customer authentication (SCA) for
card transactions. Includes required parameters, request structure, and
response examples.
---
# Transactions authentication (SCA)
Most online [Card Transactions](/guide/cards/transactions) require an [SCA](/guide/strong-customer-authentication/introduction).
When a [Card Transaction](/guide/cards/transactions) goes through SCA, the following occurs:
1. **Treezor notifies you** by sending a [`card3DSv2Authentication.create`](/guide/cards/events-tx#card3DSv2authentication-create) webhook.
2. **You authenticate your end user** using [the SDK](/guide/strong-customer-authentication/sdk) and an SCA method.
3. **You inform Treezor** of the authentication result using [the dedicated endpoint](/guide/cards/transactions-authentication#notification-of-authentication-result).
4. **Treezor notifies you** of the final transaction status by sending a [`card3DSv2Authentication.update`](/guide/cards/events-tx#card3DSv2authentication-update) webhook.
## Authentication of the end user
Upon reception of the [`card3DSv2Authentication.create`](/guide/cards/events-tx#card3DSv2authentication-create) webhook, you must **authenticate your end user** using the SDK and a strong authentication method such as `Pin Authentication` or `Device Biometric Authentication`.
## Notification of Authentication Result
Upon authentication of the end user, you must **inform Treezor** of the authentication result with the dedicated endpoint.
### Parameters
The following parameters are expected in the payload.
| Attribute | Type | Description |
| --- | --- | --- |
| `authenticationResult` | string | Whether the authentication was successful. See [Authentication result](#authentication-result) for the list of values. |
#### Authentication result
| `authenticationResult` | Description |
| --- | --- |
| `OK` | The Strong Customer Authentication of your end user was successful. |
| `KO_AUTH_FAILED` | The end user failed to strongly authenticate themselves. |
| `KO_TECHNICAL` | A technical error prevented the authentication. |
| `FALLBACK` | Allows you to request from the sever a one-time password (OTP SMS). |
### Request example
Endpoint: [`/v1/auth-requests/{authRequestId}/result`](/api-reference/api-endpoints.html#tag/Card%20Transactions%20Authentication%20\(SCA\)/putAuthRequestResult){target="\_self"}
You can find the value for the `authRequestId` query parameter in the `authenticationRequestId` of the [`card3DSv2Authentication.create`](/guide/cards/events-tx#card3DSv2authentication-create) webhook.
```bash [CURL]
curl -X PUT '{baseUrl}/v1/auth-requests/{authRequestId}/result' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is a `{payload}` example.
```json [JSON]
{
"authenticationResult": "OK", // Successful SCA
}
```
**Note – You have 5 minutes to provide the result to Treezor**
You must provide the authentication result to Treezor within 5 minutes of the webhook emission. This delay can be modified to suit your specific needs by contacting your *Treezor Account Manager*.
### Responses
Treezor may answer with the following HTTP status codes.
#### `200` HTTP Status Code
If your answer has been received and accepted by Treezor.
#### `400` HTTP Status Code
If the provided attributes are invalid or missing.
```json [JSON]
{
"errors": [
{
"type": "invalid_request",
"code": "input_validation_error",
"message": "Invalid request data : The authenticationResult field is required|invalid.",
"requestId": "request-id",
"docUrl": "https://developers.treezor.co",
}
]
}
```
```json [JSON (legacy)]
{
"authenticationResult": ["The authenticationResult field is required|invalid."],
"authenticationSignature": ["The authenticationResult field is invalid."]
}
```
If the authentication request has already been processed by Treezor.
```json [JSON]
{
"errors": [
{
"type": "invalid_grant",
"code": "authentication_error",
"message": "Authentication result already received",
"requestId": "request-id",
"docUrl": "https://developers.treezor.co",
}
]
}
```
```json [JSON (legacy)]
{
"error": "Authentication Request Already Processed"
}
```
If the authentication request cannot be found on Treezor's side.
```json [JSON]
{
"errors": [
{
"type": "invalid_request",
"code": "resource_not_found_error",
"message": "Unable to find the authenticationRequestID in our system",
"requestId": "request-id",
"docUrl": "https://developers.treezor.co",
}
]
}
```
```json [JSON (legacy)]
{
"error": "Unable to find the authenticationRequestID in our system"
}
```
#### `500` HTTP Status Code
If an internal error on our side prevented us from accepting your answer
```json [JSON]
{
"errors": [
{
"type": "unexpected_internal_server_error",
"code": "unexpected_error",
"message": "Internal server error",
"requestId": "request-id",
"docUrl": "https://developers.treezor.co",
}
]
}
```
```json [JSON (legacy)]
{
"error": "Internal server error"
}
```
## Final authentication request status
Depending on the [authentication result you sent to Treezor](#notification-of-authentication-result) and Treezor's final processing, you're notified of the [Card Transaction](/guide/cards/transactions) authentication status through the [`card3DSv2Authentication.update`](/guide/cards/events-tx#card3DSv2authentication-update) webhook.
The `authenticationFinalResult` value can be one of the following.
| Final result | Description |
| --- | --- |
| `SUCCESS` | Authentication is successful and the card transaction proceeds. |
| `UNAUTHENTICATED` | Treezor took into account that the authentication has failed. The card transaction fails. |
| `ERROR` | An error occurred during the authentication process. The card transaction fails. This may occur regardless of your response, due to an error on the card processor's side. |
| `FALLBACK` | You sent a FALLBACK response. Authentication switches to SMS\_OTP mode. |
| `TIMEOUT` | Authentication failed due to a timeout. The card transaction fails. This may occur regardless of your response, due to an error on the card processor's side. |
**Tip – Authentication simulation available**
Treezor allows you to simulate the authentication of an online card transaction. See [Simulate card transaction authentication (SCA)](./faking-operations#simulate-card-transaction-authentication-sca) for more information.
---
---
url: /guide/cards/authorization-notes.md
description: >-
Learn how to inform the cardholder of the cause of a payment incident or
status with the authorization notes.
---
# Authorization notes
The `authorizationNote` attribute allows you to inform the cardholder of the cause of a payment incident and/or status.
You should always use the `authorizationNote` **together with the [`authorizationResponseCode`](#codes-authorizationresponsecode)** to provide accurate information to the cardholder.
The [`authorizationResponseCode`](#codes-authorizationresponsecode) indicates if the transaction was Declined or Approved, while the `authorizationNote` provides more details as to why.
**Tip – Multiple messages may be contained in the `authorizationNote`**
In which case they are concatenated with the `\n` character to separate them.
**Caution – The authorization notes list isn't exhaustive**
Due to the vast number of possibilities regarding authorization notes and their variations, we document only the most common ones.
## Card processor authorization notes
Find below the list of common authorization notes sent by the card processor.
| Authorization Note | Description |
|--- |--- |
| `; DE095={amount}; DE095={amount}` | Informative message, `{amount}` is the remaining [authorized](/guide/cards/transactions-lifecycle#authorization-accepted) amount after a [partial reversal](/guide/cards/transactions-examples#gas-station-transaction) |
| `ASI.... AVS check` | Informative message, the address of the cardholder has been checked |
| `ASI.... CVC check` | Informative message, the CVC has been checked |
| `AUTOMATIC AUTHORISATION REMOVAL BillAmt - {amount} Location - {business} {country}` | An authorization from 7 days ago has been [cancelled and reversed](/guide/cards/transactions-lifecycle#reversal), as no settlement occurred (these are generally used to ensure a Card is valid by authorizing a small amount that is never actually debited) |
| `Banknet advice: APS error; unable to deliver response` | Temporary internal error, the Cardholder should retry their payment |
| `BlockedCard` | The Card is [blocked](/guide/cards/modification#block-a-card). |
| `Card CVV2 not matching with cvv2 in auth request` | The cardholder entered an erroneous [CVV2 (or CVC)](/guide/overview/glossary#card-verification-number-cvc) |
| `ChargeBack - Credit to Card` | Informative message, the cardholder has just been refunded following a chargeback | Card Processor |
| `Connection Timeout` | Temporary internal error, the Cardholder should retry their payment |
| `COUNTRY CODE NOT ALLOWED` | The [merchant's country is not allowed](/guide/cards/restrictions-limits#country-restrictions) by the Card or [Card Program](/guide/cards/introduction#card-program) |
| `CountryNotPermittedToCardHolder` | The payment country is not allowed by the Card or [Card Program](/guide/cards/introduction#card-program) |
| `DR: AF:Mag ATM attempt` | An ATM withdrawal was attempted using the magstripe, which is forbidden for security reason. The cardholder should retry using the Card Chip\&PIN method. |
| `DR: ARQC not matching` | There was a malfunction with the Card and/or the payment terminal, the cardholder may retry their payment once |
| `DR: Card expiry check failed with Emboss Expiry date (DE014)` | The cardholder entered a wrong expiration date |
| `DR: Card not found UnKnownCard` | The Card PAN is unknown or invalid but does match Treezor's range of Card numbers |
| `DR: CVC2 tries exceeded` | The cardholder entered erroneous [CVC](/guide/overview/glossary#card-verification-number-cvc) too many times. [A ticket must be open with Treezor to unlock it.](/guide/cards/modification#unlock-cvv) |
| `DR: Declined due to Card Status: Card Destroyed (Original status 83, changed to 05) ` | The Card has been [destroyed](/guide/cards/introduction#card-status-statuscode) |
| `DR: Declined due to Card Status: Expired card` | The Card has expired (expiration date is in the past) |
| `DR: Declined due to Card Status: Lost card (Capture)(Issuer will be charged if card is picked up)` | The Card has been [lost](/guide/cards/introduction#card-status-statuscode) and the merchant is allowed to keep the Card and send it to their bank for restitution to Treezor |
| `DR: Declined due to Card Status: Restricted card (Card is not active)` | The Card is [inactive](/guide/cards/modification#activation) |
| `DR: Declined due to Card Status: Short-term Debit` | The Card is [locked](/guide/cards/modification#activation) |
| `DR: Declined due to Card Status: Stolen card (Capture)(Issuer will be charged if card is picked up)` | The Card has been [stolen](/guide/cards/introduction#card-status-statuscode) and the merchant is allowed to keep the Card and send it to their bank for restitution to Treezor |
| `DR: Declined due to CardUsageGroupCheck GroupUsageID-{groupId} [additional information]` | The authorization was blocked due to restrictions on the use of the Card. More information are available in the details: `[additional information]`. |
| `DR: Declined due to Lost Card (Capture)(Original auth resp status 41, changed to 05)` | The Card has been [declared as lost](/guide/cards/introduction#card-status-statuscode) |
| `DR: Declined due to Restricted card (Card is not active)` | The Card is not activated or is disabled |
| `DR: Declined due to Stolen Card (Capture)(Original auth resp status 43, changed to 05) ` | The Card has been [declared as stolen](/guide/cards/introduction#card-status-statuscode) |
| `DR: Decline existing tokens(10) > Min_Tokens_To_Decline(10) DR: MDES/VDEP validation failed MDES check failed from Tokenisation Processing` | There are already 10 Cards tokenized with an X-Pay provider (Google Pay, Apple Pay, Samsung Pay...), no more tokenization are allowed |
| `DR: Decline as wallet_device_score (1) <= wallet_device_max_score_decline (1)` | Card tokenization has been denied by the X-Pay provider (Apple Pay, Google Pay, Samsung Pay…) due to poor end user's device scoring |
| `DR: Expiry Date missing.` | The expiration date of the Card has not been provided |
| `DR: IAV:V (checked by MC-PREVAL)` | Monetary Currency mismatch between authorization and authentication |
| `DR: iCVV does not match on EMV Track 2` | Either an issue with the merchant's terminal, or the chip of the card. Contact Support if the issue occurs with multiple merchants. |
| `DR: Incorrect PIN` | The [PIN](/guide/overview/glossary#personal-identification-number-pin) code entered was incorrect |
| `DR: MDES Invalid Card Number - payment_token not found` | The Card was properly digitized for [X-Pay](/guide/cards/x-pay-google-apple) but an incident occurred when payin with X-Pay. The cardholder should digitize their card again. |
| `DR: Offline PIN incorrect` | The cardholder entered an erroneous [PIN](/guide/overview/glossary#personal-identification-number-pin) |
| `DR: Offline PIN try limit exceeded` | The maximum number of erroneous PIN has been reached, [the PIN must be unlocked](/guide/cards/modification#unlock-pin) |
| `DR: Requires SCA` | The transaction requires a [Strong Customer Authentication](/guide/overview/glossary#strong-customer-authentication-sca) such as [3D Secure](/guide/overview/glossary#_3d-secure-3d) or [Chip & Pin](/guide/overview/glossary#personal-identification-number-pin). |
| `EH Timeout - An error occurred while sending the request.` | Temporary internal error, the Cardholder should retry their payment |
| `EH Timeout - Response status code does not indicate success: 429 (Too Many Requests).` | Temporary internal error, the Cardholder should retry their payment |
| `EH Timeout - Response status code does not indicate success: 502 (Bad Gateway).` | Temporary internal error, the Cardholder should retry their payment |
| `EH Timeout - The operation was canceled.` | Temporary internal error, the Cardholder should retry their payment |
| `EH Timeout - Unable to connect to the remote server` | Temporary internal error, the Cardholder should retry their payment |
| `EH Timeout` | Temporary internal error, the Cardholder should retry their payment |
| `Gen: Pre-Authorization Request` | Informative message, indicates a pre-authorization request (such as a deposit) which can be canceled later |
| `Issuer Time-out` | Temporary internal error, the Cardholder should retry their payment |
| `MDES FPAN Status:41` | Informative message, a payment was made with Apple Pay/Google Pay/Samsung Pay and the actual Card is lost |
| `MDES FPAN Status:62` | Informative message, a payment was made with Apple Pay/Google Pay/Samsung Pay and the actual Card is stolen or disabled |
| `Null or Empty Response received from client` | Temporary internal error, the Cardholder should retry their payment |
| `Presentment for Partial Reversal` | Informative message, following a [Gas station](/guide/cards/transactions-examples#gas-station-transaction) transaction |
| `PSD2 Counter Reset` | Informative message, the [contactless counter](/guide/overview/glossary#near-field-communication-nfc) or e-commerce counter has been reset to zero |
| `Reversal due to AFD Advice with different amount. (AFD Amount=30.0000)` | Informative message, the [reversal](/guide/cards/transactions-lifecycle#reversal) cancels a previous authorization at the merchant's request. It frees up the [Authorized Balance](/guide/wallets/balances) of the Wallet. |
| `Signature Verification - Failed` | Occurs in countries where the authentication method consists in signing the receipt. Such authentications are refused as they can't be checked online. |
The `DR:` prefix means *Decline Reason*.
## Treezor authorization notes
Find below the list of common authorization notes sent by Treezor.
| Authorization Note | Description |
|--- |--- |
| `ATM MONTHLY LEGAL LIMIT OF WALLET EXCEEDED` | The legal ATM withdrawal limit has been reached |
| `Credit Other - pre-arbitration` | Arbitration case: the cardholder has definitively won the chargeback following a dispute with the merchant. |
| `DECLINED BY GPS` | The card processor declined the transaction (this is always accompanied by a more detailed message) |
| `Electronic Money: MCC not permitted` | The law prohibits this MCC (type of business). This only occurs with [EM projects](/guide/wallets/introduction#electronic-money-wallet-type-9) |
| `Electronic Money: transaction not permitted to cardholder` | The cardholder doesn't exist or is frozen. This only occurs with [EM projects](/guide/wallets/introduction#electronic-money-wallet-type-9) |
| `Electronic Money: cumulative amount authorized exceeded` | The electronic money limit on sliding period has been reached. This only occurs with [EM projects](/guide/wallets/introduction#electronic-money-wallet-type-9) |
| `Electronic Money: amount exceeds the authorized amount` | The transaction amount exceeds the authorized amount. This only occurs with [EM projects](/guide/wallets/introduction#electronic-money-wallet-type-9) |
| `Electronic Money: payment is not permitted in this country` | The country of the wallet and the country in which the payment is done don't match. This only occurs with [EM projects](/guide/wallets/introduction#electronic-money-wallet-type-9) |
| `ErrorInternal` | Temporary internal error, the Cardholder should retry their payment |
| `Fixed amount adjustment` | The difference between the pre-authorized amount for the AFD transaction and the actually charged amount has been reversed. Learn more about this specific case in the [corresponding example](/guide/cards/transactions-examples#gas-station-transaction). |
| `Incoming transaction concern an unactive wallet` | The transaction is associated to an [inactive Wallet](/guide/wallets/modification#delete) |
| `Incoming transaction concern an unactive user` | The transaction is associated to an [inactive User](/guide/users/introduction#deletion) |
| `Incoming transaction concern an unactive card` | The transaction is associated to an [inactive Card](/guide/cards/modification#block-a-card) |
| `Incoming transaction concern an unknown PAN` | The transaction is associated to an unknown PAN (absent from our system) |
| `Insufficient funds` | The Wallet has insufficient funds |
| `Invalid card number (no such token)` | The Card PAN is invalid or unknown |
| `LIMIT ATM EXCEEDED ALL` | The lifetime [ATM withdrawal limit](/guide/cards/restrictions-limits#payment-withdrawal-limits) has been reached |
| `LIMIT ATM EXCEEDED DAY` | The daily [ATM withdrawal limit](/guide/cards/restrictions-limits#payment-withdrawal-limits) has been reached |
| `LIMIT ATM EXCEEDED MONTH` | The monthly [ATM withdrawal limit](/guide/cards/restrictions-limits#payment-withdrawal-limits) has been reached |
| `LIMIT ATM EXCEEDED WEEK` | The weekly [ATM withdrawal limit](/guide/cards/restrictions-limits#payment-withdrawal-limits) has been reached |
| `LIMIT ATM EXCEEDED YEAR` | The yearly [ATM withdrawal limit](/guide/cards/restrictions-limits#payment-withdrawal-limits) has been reached |
| `LIMIT CONTACTLESS APPLE PAY EXCEEDED` | The [Apple Pay](/guide/cards/x-pay-google-apple) contactless limit has been reached |
| `LIMIT CONTACTLESS EXCEEDED` | The [contactless](/guide/overview/glossary#near-field-communication-nfc) limit has been reached |
| `LIMIT PAYMENT EXCEEDED ALL` | The lifetime [payment limit](/guide/cards/restrictions-limits#payment-withdrawal-limits) has been reached |
| `LIMIT PAYMENT EXCEEDED DAY` | The daily [payment limit](/guide/cards/restrictions-limits#payment-withdrawal-limits) has been reached |
| `LIMIT PAYMENT EXCEEDED MONTH` | The monthly [payment limit](/guide/cards/restrictions-limits#payment-withdrawal-limits) has been reached |
| `LIMIT PAYMENT EXCEEDED WEEK` | The weekly [payment limit](/guide/cards/restrictions-limits#payment-withdrawal-limits) has been reached |
| `LIMIT PAYMENT EXCEEDED YEAR` | The yearly [payment limit](/guide/cards/restrictions-limits#payment-withdrawal-limits) has been reached |
| `MCC NOT ALLOWED` | The [Merchant Category Code (category of business) is not allowed](/guide/cards/restrictions-limits#mcc-restrictions) by the Card or [Card Program](/guide/cards/introduction#card-program) |
| `MccNotPermittedToCardHolder` | The [Merchant Category Code (category of business) is not allowed](/guide/cards/restrictions-limits#mcc-restrictions) by the Card or [Card Program](/guide/cards/introduction#card-program) |
| `MDC DECLINED - did not match: {rulesetIds}` | The transaction was refused by the [Treezor transaction rules engine](/guide/cards/transactions-rules-engine). |
| `MERCHANT ID NOT ALLOWED` | The [merchant's ID (one specific business) is not allowed](/guide/cards/restrictions-limits#mid-restrictions) |
| `MerchantIdNotPermittedToCardHolder` | The [merchant's ID (one specific business) is not allowed](/guide/cards/restrictions-limits#mid-restrictions) |
| `POSDailyLimitExceeded` | The daily [payment limit](/guide/cards/restrictions-limits#payment-withdrawal-limits) has been reached |
| `Refund` | Informative message, refund authorization |
| `REVERSAL` | Informative message, the [reversal](/guide/cards/transactions-lifecycle#reversal) cancels a previous authorization at the merchant's request. It frees up the [Authorized Balance](/guide/wallets/balances) of the Wallet. |
| `SIMULTANEOUS OPERATIONS ON THE SAME WALLET` | Multiple operations occurred at the very same time on the Wallet, the cardholder should retry their payment |
| `Specific to AFD: fixed amount authorization` | The fixed amount of €160 has been applied for a automated fuel dispenser (AFD) transaction. Learn more about this specific case in the [corresponding example](/guide/cards/transactions-examples#gas-station-transaction). |
| `System Error.` | Temporary internal error, the Cardholder should retry their payment. |
| `User's assets are freezed` | The Wallet or payment account of the User is [frozen](/guide/users/restricted-users) by an [AML-CFT](/guide/overview/glossary#anti-money-laundering-and-countering-the-financing-of-terrorism-aml-cft) sanction. |
| `{rulesetIds}` | The transaction was accepted by the [Treezor transaction rules engine](/guide/cards/transactions-rules-engine). |
## External Authorization authorization notes
Find below the list of common authorization notes sent by you in the context of the [External Authorization](/guide/cards/transactions-external-validation) feature.
| Authorization Note | Description |
|--- |--- |
| `External Authorization - DECLINED` | You declined the card transaction through the [External Authorization](/guide/cards/transactions-external-validation) feature. |
| `External Authorization - DECLINED_CARD_UNKNOW` | You declined the card transaction through the [External Authorization](/guide/cards/transactions-external-validation) feature. |
| `External Authorization - DECLINED_DATETIME_INVALID` | You declined the card transaction through the [External Authorization](/guide/cards/transactions-external-validation) feature. |
| `External Authorization - DECLINED_DUE_TO_REGULATORY_RULE` | You declined the card transaction through the [External Authorization](/guide/cards/transactions-external-validation) feature. |
| `External Authorization - DECLINED_INSUFFICIENT_FUNDS` | You declined the card transaction through the [External Authorization](/guide/cards/transactions-external-validation) feature. |
| `External Authorization - DECLINED_INSUFFICIENT_FUNDS_WITHDRAWAL_LIMIT_REACHED` | You declined the card transaction through the [External Authorization](/guide/cards/transactions-external-validation) feature. |
| `External Authorization - DECLINED_LOCAL_CURRENCY_INVALID` | You declined the card transaction through the [External Authorization](/guide/cards/transactions-external-validation) feature. |
| `External Authorization - DECLINED_MCC_INVALID` | You declined the card transaction through the [External Authorization](/guide/cards/transactions-external-validation) feature. |
| `External Authorization - DECLINED_MERCHANT_CITY_INVALID` | You declined the card transaction through the [External Authorization](/guide/cards/transactions-external-validation) feature. |
| `External Authorization - DECLINED_MERCHANT_COUNTRY_INVALID` | You declined the card transaction through the [External Authorization](/guide/cards/transactions-external-validation) feature. |
| `External Authorization - DECLINED_MERCHANTID_INVALID` | You declined the card transaction through the [External Authorization](/guide/cards/transactions-external-validation) feature. |
## Authorization response codes
This information is provided in the `authorizationResponseCode` attribute.
It provides clues as to why the transaction was accepted or refused, and pointers regarding what to do next. This information comes in addition to [the status](/guide/cards/transactions#statuses) of a transaction.
| Code | | Action | Description |
|:-: |- |- | - |
| `00` | | Approve | Approved |
| `08` | | Approve | Honor with identification. |
| `10` | | Approve | Partial approval. |
| `85` | | Approve | Approved (used for some non-financial transactions such as a PIN Unblock request). |
| `87` | | Approve | Purchase amount only. No Cashback allowed. |
| `01` | | Call issuer | Refer to card issuer. |
| `41` | | Capture | Lost card. |
| `43` | | Capture | Stolen card. |
| `03` | | Decline | Invalid merchant. |
| `04` | | Decline | Capture card. |
| `05` | | Decline | Do not honor. |
| `06` | | Decline | Unspecified error. |
| `12` | | Decline | Invalid transaction. |
| `13` | | Decline | Invalid amount. |
| `14` | | Decline | Invalid card number |
| `15` | | Decline | Unable to route at IEM (Issuer's Europay Module). Card Scheme network cannot connect to processor. |
| `17` | | Decline | Customer cancellation (Reversal) |
| `30` | | Decline | Format error. |
| `32` | | Decline | Partial reversal. |
| `34` | | Decline | Suspected fraud (reversal). Don't expose this information to end users. |
| `46` | | Decline | Account closed. |
| `51` | | Decline | Insufficient funds. |
| `54` | | Decline | Expired card. |
| `55` | | Decline | Invalid PIN. |
| `57` | | Decline | Transaction not permitted to cardholder. |
| `58` | | Decline | Transaction not permitted to acquirer terminal. |
| `59` | | Decline | Suspected fraud. Do not expose this information to end users. |
| `61` | | Decline | Exceeds withdrawal amount limit. |
| `62` | | Decline | Restricted card (e.g., card invalid in region or country). |
| `63` | | Decline | Security violation. |
| `65` | | Decline | Exceeds withdrawal frequency limit. |
| `68` | | Decline | Response received too late. |
| `70` | | Decline | Cardholder to contact issuer. |
| `71` | | Decline | PIN not changed. |
| `72` | | Decline | Account not yet activated. |
| `75` | | Decline | Allowable number of PIN tries exceeded. |
| `76` | | Decline | Wrong PIN, allowable number of PIN tries exceeded. |
| `77` | | Decline | Issuer does not participate in the service. |
| `78` | | Decline | Card is not active (including created but not yet activated). |
| `79` | | Decline | Unacceptable PIN – Transaction declined. Retry. |
| `81` | | Decline | Domestic debit transaction not allowed. |
| `82` | | Decline | Timeout from network to issuer. |
| `86` | | Decline | PIN validation not possible. |
| `88` | | Decline | Cryptographic failure. |
| `89` | | Decline | Authentication failure |
| `91` | | Decline | Issuer or switch is inoperative. |
| `92` | | Decline | Unable to Route Transaction. |
| `94` | | Decline | Duplicate transmission. |
| `96` | | Decline | System malfunction. |
---
---
url: /guide/cards/errors-tx.md
description: >-
Troubleshoot and handle card transaction-related issues using the Treezor
API's complete list of error codes, messages, and their corresponding
meanings.
---
# Errors
The following API errors can be encountered with card transactions.
**Caution – Only the legacy API sends the error code in HTTP errors**
When handling errors with Connect, only the `message` attribute is returned.
## Card Transaction errors
| Code | Message |
|:----------:|--------------------------------------------------------------------------------------------------------------|
| `61000` | Length of acceptorId must be lower than 16 characters |
| `61001` | Length of acceptorName must be lower than 23 characters |
| `61002` | Length of acceptorCity must be lower than 14 characters |
| `61003` | Length of acceptorCountry must be lower than 4 characters |
| `61004` | Length of paymentLocalTime must be lower than 6 characters |
| `61005` | Length of panToken must be lower than 2^63-1 and higher than 1. |
| `61006` | paymentAmount is mandatory |
| `61007` | Length of paymentCurrency must equal 3 numbers |
| `61008` | Length of fees must be lower than 9 numbers |
| `61009` | Length of paymentCountry must equal 3 characters |
| `61010` | paymentId is mandatory |
| `61011` | paymentStatus is mandatory |
| `61012` | posCardholderPresence length must be lower than 2 numbers |
| `61013` | posCardPresence length must be lower than 2 numbers |
| `61014` | panEntryMethod length must be lower than 3 numbers |
| `61015` | Length of authorizationResponseCode must equal 2 numbers |
| `61016` | authorizationIssuerId is mandatory |
| `61017` | authorizationMti length must be equal to 4 numbers |
| `61018` | authorizedBalance is mandatory |
| `61019` | acceptorName is mandatory |
| `61020` | acceptorCity is mandatory |
| `61021` | acceptorCountry is mandatory |
| `61022` | panToken is mandatory |
| `61023` | authorizationResponseCode is mandatory |
| `61024` | authorizationMti is mandatory |
| `61025` | paymentCurrency is mandatory |
| `61026` | Impossible to read card transactions |
| `61027` | Unable to filter card transactions by merchantId without at least one of its input parameters: id, cardId, walletId, publicToken, paymentId. |
| `61028` | Card Transaction Id is mandatory |
| `61029` | Card Transaction Id does not exist |
| `61030` | clientId is mandatory |
| `61031` | The request must contain at least one of those inputs: cardId, paymentId, publicToken, walletId |
| `61032` | cardTransactionId must be an integer |
| `61033` | cardId must be an integer |
| `61034` | walletId must be an integer |
| `61035` | publicToken must be a string |
| `61036` | paymentId must be an integer |
| `61037` | merchantId must be a string |
| `61038` | Invalid cardTransactionId format (numeric is expected) |
| `61039` | Invalid format (numeric is expected) |
| `61040` | The request must contain at least one of those inputs: cardTransactionId, cardId, paymentId, publicToken, walletId |
| `61041` | Impossible to read card transactions |
---
---
url: /guide/cards/events-tx.md
description: >-
Reference a comprehensive list of card transaction events for Treezor API
webhooks, detailing each event's structure and payload for integration.
---
# Events
This article lists the [Webhooks](/guide/webhooks/introduction) you may receive when regarding Card Transactions.
## Card Transaction events
### Authorized `cardtransaction.create`
```json [JSON] {23}
{
"webhook": "cardtransaction.create",
"object": "cardtransaction",
"object_id": "190314",
"object_payload": {
"cardtransactions": [
{
"cardtransactionId": "700013016",
"cardId": "4821765",
"walletId": "13183230",
"walletCurrency": "978",
"merchantId": "526567002078132",
"merchantName": "Action 4105",
"merchantCity": "Paris",
"merchantCountry": "FRA",
"paymentLocalTime": "72316",
"publicToken": "288316333",
"paymentAmount": "1.99",
"paymentCurrency": "978",
"fees": "0.00",
"paymentCountry": "FRA",
"paymentId": "382305888",
"paymentStatus": "A",
"paymentLocalAmount": "1.99",
"posCardholderPresence": "0",
"posPostcode": "75100",
"posCountry": "250",
"posTerminalId": "7547999",
"posCardPresence": "0",
"panEntryMethod": "7",
"authorizationNote": "",
"authorizationResponseCode": "0",
"authorizationIssuerId": "14215320554",
"authorizationIssuerTime": "2024-04-16 08:23:20", // Europe/London timezone
"authorizationMti": "100",
"authorizedBalance": "42.60",
"limitAtmYear": "0",
"limitAtmMonth": "1000",
"limitAtmWeek": "500",
"limitAtmDay": "0",
"limitAtmAll": "0",
"limitPaymentYear": "0",
"limitPaymentMonth": "5000",
"limitPaymentWeek": "5000",
"limitPaymentDay": "0",
"limitPaymentAll": "0",
"paymentDailyLimit": "0.00",
"totalLimitAtmYear": "0.00",
"totalLimitAtmMonth": "0.00",
"totalLimitAtmWeek": "0.00",
"totalLimitAtmDay": "0.00",
"totalLimitAtmAll": "0.00",
"totalLimitPaymentYear": "0.00",
"totalLimitPaymentMonth": "79.47",
"totalLimitPaymentWeek": "0.00",
"totalLimitPaymentDay": "0.00",
"totalLimitPaymentAll": "0.00",
"cardDigitalizationExternalId": "0",
"mccCode": "5310",
"acquirerId": "13445",
"is3DS": "0",
"merchantAddress": null,
"paymentLocalDate": null,
"3dsExemptionType": "5",
"receiverData": "0104ENZO0308LUVIBILA",
"senderData": "0114Capital Com SV0314Capital Com SV0450LOPHITIS BUSINESS CENTER II, Floor 6,, 28 OKTOVRIO0508Limassol0703CYP080430351106205838",
"transactionTypeIdentifier": "C07",
"localMerchantId": "12345678900001",
"transactionSubtype": "PRE",
"optimizedMerchantName": "string",
"merchantLogo": "http://yourmerchantlogo.png",
"merchantCategory": "Retail & Shopping",
"merchantCategoryGroup": "Retail & Department Stores",
"merchantCategoryType": "Furniture"
}
]
},
"webhook_created_at": 17132761057381,
"webhook_id": "32d41919-8390-4431-b74e-04f6c3xxx9a4",
"object_payload_signature": "/qTn7yr+xxx9e8Qx/DTTY+2a0mTKLnj5BQ0GT/snIvk="
}
```
### Settled `cardtransaction.create`
```json [JSON] {23}
{
"webhook": "cardtransaction.create",
"object": "cardtransaction",
"object_id": "190314",
"object_payload": {
"cardtransactions": [
{
"cardtransactionId": "700017059",
"cardId": "3658911",
"walletId": "253327",
"walletCurrency": "978",
"merchantId": "08051835 ",
"merchantName": "ELA SAINT OUEN",
"merchantCity": "L ILE SAINT D",
"merchantCountry": "FRA",
"paymentLocalTime": "183905",
"publicToken": "230647558",
"paymentAmount": "13.85",
"paymentCurrency": "978",
"fees": "0.00",
"paymentCountry": "FRA",
"paymentId": "382197633",
"paymentStatus": "S",
"paymentLocalAmount": "13.85",
"posCardholderPresence": "0",
"posPostcode": "",
"posCountry": "0",
"posTerminalId": "00000001",
"posCardPresence": "1",
"panEntryMethod": "0",
"authorizationNote": "",
"authorizationResponseCode": "0",
"authorizationIssuerId": "14214543446",
"authorizationIssuerTime": "2024-04-16 04:41:02", // Europe/London timezone
"authorizationMti": "1240",
"authorizedBalance": "10876604.71",
"limitAtmYear": "0",
"limitAtmMonth": "0",
"limitAtmWeek": "2000",
"limitAtmDay": "1000",
"limitAtmAll": "0",
"limitPaymentYear": "0",
"limitPaymentMonth": "0",
"limitPaymentWeek": "3000",
"limitPaymentDay": "2000",
"limitPaymentAll": "0",
"paymentDailyLimit": "0.01",
"totalLimitAtmYear": "0.00",
"totalLimitAtmMonth": "0.00",
"totalLimitAtmWeek": "0.00",
"totalLimitAtmDay": "0.00",
"totalLimitAtmAll": "0.00",
"totalLimitPaymentYear": "0.00",
"totalLimitPaymentMonth": "0.00",
"totalLimitPaymentWeek": "0.00",
"totalLimitPaymentDay": "0.00",
"totalLimitPaymentAll": "0.00",
"cardDigitalizationExternalId": "0",
"mccCode": "5331",
"acquirerId": "12865",
"is3DS": "0",
"merchantAddress": "7 RUE MECHIN",
"paymentLocalDate": "240415",
"3dsExemptionType": "5",
"receiverData": "0104ENZO0308LUVIBILA",
"senderData": "0114Capital Com SV0314Capital Com SV0450LOPHITIS BUSINESS CENTER II, Floor 6,, 28 OKTOVRIO0508Limassol0703CYP080430351106205838",
"transactionTypeIdentifier": "C07",
"localMerchantId": "12345678900001",
"transactionSubtype": "PRE",
"optimizedMerchantName": "string",
"merchantLogo": "http://yourmerchantlogo.png",
"merchantCategory": "Retail & Shopping",
"merchantCategoryGroup": "Retail & Department Stores",
"merchantCategoryType": "Furniture"
}
]
},
"webhook_created_at": 17132761057381,
"webhook_id": "32d41919-8390-4431-b74e-04f6c3xxx9a4",
"object_payload_signature": "/qTn7yr+xxx9e8Qx/DTTY+2a0mTKLnj5BQ0GT/snIvk="
}
```
### Declined `cardtransaction.create`
```json [JSON] {23,31}
{
"webhook": "cardtransaction.create",
"object": "cardtransaction",
"object_id": "190314",
"object_payload": {
"cardtransactions": [
{
"cardtransactionId": "700014695",
"cardId": "4504801",
"walletId": "6091295",
"walletCurrency": "978",
"merchantId": "8102132",
"merchantName": "MAMP Mobilites",
"merchantCity": "MARSEILLE",
"merchantCountry": "FRA",
"paymentLocalTime": "92636",
"publicToken": "256063690",
"paymentAmount": "1.70",
"paymentCurrency": "978",
"fees": "0.00",
"paymentCountry": "FRA",
"paymentId": "382306486",
"paymentStatus": "I",
"paymentLocalAmount": "1.70",
"posCardholderPresence": "1",
"posPostcode": "13007",
"posCountry": "250",
"posTerminalId": "13061504",
"posCardPresence": "1",
"panEntryMethod": "1",
"authorizationNote": "MERCHANT ID NOT ALLOWED",
"authorizationResponseCode": "57",
"authorizationIssuerId": "14215325375",
"authorizationIssuerTime": "2024-04-16 08:25:57", // Europe/London timezone
"authorizationMti": "100",
"authorizedBalance": "0.00",
"limitAtmYear": "0",
"limitAtmMonth": "1000",
"limitAtmWeek": "0",
"limitAtmDay": "0",
"limitAtmAll": "0",
"limitPaymentYear": "0",
"limitPaymentMonth": "5000",
"limitPaymentWeek": "0",
"limitPaymentDay": "0",
"limitPaymentAll": "0",
"paymentDailyLimit": "0.00",
"totalLimitAtmYear": "0.00",
"totalLimitAtmMonth": "0.00",
"totalLimitAtmWeek": "0.00",
"totalLimitAtmDay": "0.00",
"totalLimitAtmAll": "0.00",
"totalLimitPaymentYear": "0.00",
"totalLimitPaymentMonth": "307.48",
"totalLimitPaymentWeek": "0.00",
"totalLimitPaymentDay": "0.00",
"totalLimitPaymentAll": "0.00",
"cardDigitalizationExternalId": "0",
"mccCode": "4111",
"acquirerId": "12865",
"is3DS": "0",
"merchantAddress": null,
"paymentLocalDate": null,
"3dsExemptionType": "5",
"receiverData": "0104ENZO0308LUVIBILA",
"senderData": "0114Capital Com SV0314Capital Com SV0450LOPHITIS BUSINESS CENTER II, Floor 6,, 28 OKTOVRIO0508Limassol0703CYP080430351106205838",
"transactionTypeIdentifier": "C07",
"localMerchantId": "12345678900001",
"transactionSubtype": "PRE",
"optimizedMerchantName": "string",
"merchantLogo": "http://yourmerchantlogo.png",
"merchantCategory": "Retail & Shopping",
"merchantCategoryGroup": "Retail & Department Stores",
"merchantCategoryType": "Furniture"
}
]
},
"webhook_created_at": 17132761057381,
"webhook_id": "32d41919-8390-4431-b74e-04f6c3xxx9a4",
"object_payload_signature": "/qTn7yr+xxx9e8Qx/DTTY+2a0mTKLnj5BQ0GT/snIvk="
}
```
## 3DSecure events
### `card3DSv2Authentication.create`
```json [JSON]
{
"object_payload": {
"authenticationRequestId": "cd679525-c341-4018-92f5-594b06fec05f", // Authentication request UUID, should be returned in the URL of the auth-requests (previously authenticationRequestID)
"userId": "123456", // Unique identifier of the user
"publicToken": "123456789", // Public token of the card (previously PublicToken)
"cardId": "123456", // Unique identifier of the card
"maskedPan": "546923******1234", // Card number partially masked
"3DSVersion": "2.2.0", // 3DS Version used for the message (1.x or 2.x)
"acquirerId": "513264", // Identifier of the merchant's acquirer (previously AcquirerID)
"merchantId": "05008620641413", // Identifier of the merchant (previously MerchantID)
"merchantName": "Merchant 89111532", // Name of the merchant (previously MerchantName)
"merchantURL": "https://example.com", // Merchant URL (previously MerchantURL)
"merchantCategoryCode": "0000", // MCC of the merchant (previously MerchantCategoryCode)
"merchantCountryCode": "440", // Country code of the merchant (previously MerchantCountryCode)
"merchantAppRedirectURL": "", // Merchant app redirect URL (previously MerchantAppRedirectURL)
"paymentDate": "2024-03-25T14:26:36.482Z", // Previously transactionTimeStamp, date and time of the authentication
"paymentAmount": "1822", // Previously transactionAmount, amount in cents of the transaction
"paymentCurrency": "978" // Previously transactionCurrency, currency of the transaction
},
"webhook": "card3DSv2Authentication.create",
"webhook_id": "",
"object": "card3DSv2Authentication",
"object_id": "ID of the authentication request (uuid v4)",
"webhook_created_at": 17498062335122,
"object_payload_signature": "/qTn7yr+xxx9e8Qx/DTTY+2a0mTKLnj5BQ0GT/snIvk="
}
```
### `card3DSv2Authentication.update`
```json [JSON]
{
"object_payload": {
"publicToken": "354362410", // Public token of the card
"authenticationRequestId": "2bca40bc-f23a-4f8d-9625-8671b72b601a", // Authentication request UUID (previously authenticationRequestID)
"authenticationFinalResult": "SUCCESS", // Can be: SUCCESS|TIMEOUT|ERROR|UNAUTHENTICATED|FALLBACK
"authenticationErrorRef": null, // Error reference given by the processor
"authenticationErrorDescription": "" // Error description given by the processor
},
"webhook": "card3DSv2Authentication.update",
"webhook_id": "9a48cdf3-fe3f-484c-b8b5-c82f152f7c35",
"object": "card3DSv2Authentication",
"object_id": "2bca40bc-f23a-4f8d-9625-8671b72b601a",
"webhook_created_at": 17498062335122,
"object_payload_signature": "/qTn7yr+xxx9e8Qx/DTTY+2a0mTKLnj5BQ0GT/snIvk="
}
```
---
---
url: /guide/cards/transactions-examples.md
description: >-
Dive into various examples of card transaction life cycles, with their
subsequent statuses and the impact on the balances at each step. Covers
accepted, declined, canceled, and refunded transactions.
---
# Transaction examples
The following examples cover most of the use cases.
**Information – Assumptions about all the following examples**
* The initial transaction amount is €150 and is initiated by the cardholder
* At the transaction time, the cardholder's wallet has a balance of €1000
* At the transaction time, the cardholder has no pending transactions. Therefore, their [Balance](/guide/wallets/balances) and [Authorized Balance](/guide/wallets/balances) are identical.
## Accepted transaction
* The cardholder makes a purchase (online or in a physical shop).
* The cardholder's bank accepts the authorization.
* The payment is received by the merchant.
| # | Operation | Status | Amount | Balance | Authorized Balance |
|:-: |- |:-: |-: |-: |-: |
| | | | | 1000 | 1000 |
| 1 | [Authorization](./transactions-lifecycle#authorization) | `A` | 150 | 1000 | **850** |
| 2 | [Settlement](./transactions-lifecycle#settlement) | `S` | 150 | **850** | 850 |
## Declined transaction
* The cardholder makes a purchase (online or in a physical shop).
* The cardholder's bank declines the payment.
| # | Operation | Status | Amount | Balance | Authorized Balance |
|:-: |- |:-: |-: |-: |-: |
| | | | | 1000 | 1000 |
| 1 | [Decline](./transactions-lifecycle#authorization-declined) | `I` | 150 | 1000 | 1000 |
## Canceled transaction
* The cardholder makes a purchase (online or in a physical shop).
* The cardholder's bank accepts the authorization.
* The transaction is **canceled** by the merchant, **before the settlement**.
| # | Operation | Status | Amount | Balance | Authorized Balance |
|:-: |- |:-: |-: |-: |-: |
| | | | | 1000 | 1000 |
| 1 | [Authorization](./transactions-lifecycle#authorization) | `A` | 150 | 1000 | **850** |
| 2 | [Reversal](./transactions-lifecycle#reversal) | `V` | 150 | 1000 | **1000** |
## Gas station transaction
* The cardholder requests a €150 authorization at a gas station before refilling their vehicle.
* The cardholder's bank accepts the authorization (#1).
* The cardholder actually fills for €90 of fuel.
* The difference between the authorization amount and the actual amount (€60) is `reversed` (#2).
* The actual amount (€90) is `settled` (#3).
| # | Operation | Status | Amount | Balance | Authorized Balance |
|:-: |- |:-: |-: |-: |-: |
| | | | | 1000 | 1000 |
| 1 | [Authorization](./transactions-lifecycle#authorization) | `A` | 150 | 1000 | **850** |
| 2 | [Reversal](./transactions-lifecycle#reversal) | `V` | 60 | 1000 | **910** |
| 3 | [Settlement](./transactions-lifecycle#settlement) | `S` | 90 | **910** | 910 |
### Specific case of automated fuel dispensers in the US and Canada
Please note that Treezor applies a fixed pre-authorized amount of €160 for all pre-authorization requests made in the USA or Canada for automated fuel dispensers (AFD) payments.
This applies to transactions with the following values:
* `"mccCode": "5542"`
* `"paymentCountry": "USA"` (or `"CAN"`)
* `"paymentLocalAmount": "1"`
In such cases, additional information can be found in the `authorizationNote`:
* `Specific to AFD: fixed amount authorization` — Indicates that the fixed amount has been applied.
* `Fixed amount adjustment` — Indicates that the actual amount has been charged and the leftover, if any, is reversed.
Below is a sample of a [`cardtransaction.create`](/guide/cards/events-tx#cardtransaction-create) webhook corresponding to our example. As previously described, the `paymentLocalAmount` is $1, and the `paymentAmount` is €160.
```json [JSON]
{
"merchantName": "SHELL",
"merchantCity": "EVANSTON",
"merchantCountry": "USA",
"paymentLocalTime": "135911",
"publicToken": "999999999",
"paymentAmount": "160.00",
"paymentCurrency": "840",
"fees": "0.00",
"paymentCountry": "USA",
"paymentId": "1xxx63",
"paymentStatus": "A",
"paymentLocalAmount": "1.00"
}
```
## Multi-settlement transaction
* The cardholder purchases multiple products on an online shop.
* The cardholder's bank accepts the authorization (#1).
* The merchant does a settlement per product (#2, #3).
| # | Operation | Status | Amount | Balance | Authorized Balance |
|:-: |- |:-: |-: |-: |-: |
| | | | | 1000 | 1000 |
| 1 | [Authorization](./transactions-lifecycle#authorization) | `A` | 150 | 1000 | **850** |
| 2 | [Settlement](./transactions-lifecycle#settlement) | `S` | 75 | **925** | 850 |
| 3 | [Settlement](./transactions-lifecycle#settlement) | `S` | 75 | **850** | 850 |
## Reversal transaction
A reversal follows an accepted authorization and cancels it at the merchant's request. A reversal can be complete, partial, or multiple.
* The cardholder purchases multiple products on an online shop.
* The cardholder's bank accepts the authorization (#1).
* The merchant makes a cancellation for one of the products (#2).
| # | Operation | Status | Amount | Balance | Authorized Balance |
|:-: |- |:-: |-: |-: |-: |
| | | | | 1000 | 1000 |
| 1 | [Authorization](./transactions-lifecycle#authorization) | `A` | 150 | 1000 | **850** |
| 2 | [Reversal](./transactions-lifecycle#reversal) | `V` | 75 | 1000 | **925** |
### Multi-reversal transaction
* The cardholder purchases multiple products on an online shop.
* The cardholder's bank accepts the authorization (#1).
* The merchant makes a cancellation per product (#2, #3).
| # | Operation | Status | Amount | Balance | Authorized Balance |
|:-: |- |:-: |-: |-: |-: |
| | | | | 1000 | 1000 |
| 1 | [Authorization](./transactions-lifecycle#authorization) | `A` | 150 | 1000 | **850** |
| 2 | [Reversal](./transactions-lifecycle#reversal) | `V` | 75 | 1000 | **925** |
| 3 | [Reversal](./transactions-lifecycle#reversal) | `V` | 75 | 1000 | **1000** |
## Non-Euro transaction
* The cardholder pays for service or products **in a currency other than Euro**, in a physical or online shop.
* The cardholder's bank accepts the authorization **at the current exchange rate** (#1).
* The merchant cashes in the transaction at the **settlement-time exchange rate**.
**Information – Assumptions**
* Exchange rate of £100 = €150 at authorization time
* Exchange rate of £100 = €160 at settlement time
| # | Operation | Status | Amount | Balance | Authorized Balance |
|:-: |- |:-: |-: |-: |-: |
| | | | | 1000 | 1000 |
| 1 | [Authorization](./transactions-lifecycle#authorization) | `A` | 150 | 1000 | **850** |
| 2 | [Settlement](./transactions-lifecycle#settlement) | `S` | **160** | **840** | **840** |
## Refunded transaction
The Refund is usually requested by the cardholder after funds have effectively been debited from the cardholder's wallet (due to a previous settlement). This is the case when returning a purchased article for instance.
Please note a transaction can be partially refunded.
* The cardholder makes a purchase (online or in a physical shop).
* The cardholder's bank accepts the authorization (#1).
* The merchant settles the payment (#2).
| # | Operation | Status | Amount | Balance | Authorized Balance |
|:-: |- |:-: |-: |-: |-: |
| | | | | 1000 | 1000 |
| 1 | [Authorization](./transactions-lifecycle#authorization) | `A` | 150 | 1000 | **850** |
| 2 | [Settlement](./transactions-lifecycle#settlement) | `S` | 150 | **850** | 850 |
If the merchant decides to refund the transaction **after settlement**.
### Accepted refund
| # | Operation | Status | Amount | Balance | Authorized Balance |
|:-: |- |:-: |-: |-: |-: |
| | | | | 850 | 850 |
| 3 | [Refund](./transactions-lifecycle#refunds) | `R` | -150 | 850 | 850 |
| 4 | [Settlement](./transactions-lifecycle#settlement) | `S` | -150 | **1000** | **1000** |
### Refused refund
Refund can be refused if the account is closed or if the card expired for instance.
| # | Operation | Status | Amount | Balance | Authorized Balance |
|:-: |- |:-: |-: |-: |-: |
| | | | | 850 | 850 |
| 3 | [Decline](./transactions-lifecycle#authorization-declined) | `I` | -150 | 850 | 850 |
## Accepted transaction, without settlement nor reversal
* The cardholder makes a purchase (online or in a physical shop).
* The cardholder's bank accepts the authorization (#1).
* No settlements nor reversals occur.
The authorization remains active, and **funds are blocked on the Authorized Balance**.
| # | Operation | Status | Amount | Balance | Authorized Balance |
|:-: |- |:-: |-: |-: |-: |
| | | | | 1000 | 1000 |
| 1 | [Authorization](./transactions-lifecycle#authorization) | `A` | 150 | 1000 | **850** |
If no further action is taken, the authorization is considered as expired after 10 days (on the night of the 10th to 11th day).
The Authorized Balance is then freed of this transaction.
| # | Operation | Status | Amount | Balance | Authorized Balance |
|:-: |- |:-: |-: |-: |-: |
| 1 | - | - | - | 1000 | 1000 |
When the authorization expires:
* No [`cardtransaction.create`](./events-tx#card-transactions) webhooks are sent at all (because no additional operations are generated).
* A [`balance.update`](/guide/wallets/events#balance-update) webhook is sent.
## Accepted transaction, refused afterwards
* The cardholder makes a purchase (online or in a physical shop).
* The cardholder's bank accepts the authorization (#1).
* The transaction is then refused within one to two hours (#2).
| # | Operation | Status | Amount | Balance | Authorized Balance |
|:-: |- |:-: |-: |-: |-: |
| | | | | 1000 | 1000 |
| 1 | [Authorization](./transactions-lifecycle#authorization) | `A` | 150 | 1000 | **850** |
| 2 | [Decline](./transactions-lifecycle#authorization-declined) | `I` | 150 | 1000 | **1000** |
When an incident occurs on the scheme network, a previously approved authorization can fail to reach the acquirer. In such cases, the network catches the error and immediately triggers a transaction refusal.
Treezor is informed within 2 hours, and the transaction initially authorized (`A`) will be declined (`I`).
## Direct settlement transaction
* The merchant bypasses the authorization and proceeds to a "Direct Settlement"
| # | Operation | Status | Amount | Balance | Authorized Balance |
|:-: |- |:-: |-: |-: |-: |
| | | | | 1000 | 1000 |
| 1 | [Settlement](./transactions-lifecycle#settlement) | `S` | 150 | **850** | **850** |
## Convoluted example
Consider the following scenario:
* A user has a balance of €1,000.
* The user orders 3 products at the same time on a marketplace (#1).
* One €100 product, a second €100 product and one €300 product.
* Later that day, the user tries to order a €700 product, but their authorized balance is insufficient (#2).
* The next day, the seller of the €300 product informs him that this product is not available anymore and cannot fulfill the order (#3).
* The user tries again to order that €700 product (#4).
* The sellers of the €100 products and €700 product inform them that they shipped their respective products (#5, #6, #7).
* One week later, the user returns one of the €100 products for a refund (#8, #9).
### Associated wallet operations
| # | Operation | Status | Amount | Balance | Authorized Balance |
|:-: |- | :-: |-: |-: |-: |
| | | | | 1000 | 1000 |
| 1 | [Authorization](./transactions-lifecycle#authorization) | `A` | 500 | 1000 | **500** |
| 2 | [Decline](./transactions-lifecycle#authorization-declined) | `I` | 700 | 1000 | 500 |
| 3 | [Reversal](./transactions-lifecycle#reversal) | `V` | 300 | 1000 | **800** |
| 4 | [Authorization](./transactions-lifecycle#authorization) | `A` | 700 | 1000 | **100** |
| 5 | [Settlement](./transactions-lifecycle#settlement) | `S` | 100 | **900** | 100 |
| 6 | [Settlement](./transactions-lifecycle#settlement) | `S` | 100 | **800** | 100 |
| 7 | [Settlement](./transactions-lifecycle#settlement) | `S` | 700 | **100** | 100 |
| 8 | [Refund](./transactions-lifecycle#refunds) | `R` | -100 | 100 | 100 |
| 9 | [Settlement](./transactions-lifecycle#settlement) | `S` | -100 | **200** | **200** |
### Explanations
* \#2: Even though the user has a Balance of €1,000 at the time, their Authorized Balance is of €500, insufficient to authorize a €700 payment.
* \#3: The unavailable €300 product is reversed, freeing up the Authorized Balance from €500 to €800.
* \#4: The €700 purchase is now acceptable.
* \#5,6,7: Each merchant of the marketplace receives an independent settlement.
* \#9: Refund appears as negative-value settlements.
---
---
url: /guide/cards/transactions-rules-engine.md
description: >-
Introduction to the Multi-Criteria Dynamic Card (MDC) feature, the rule engine
that allows you to authorize or refuse card transactions based on rulesets.
---
# Multi-Criteria Dynamic Card (MDC)
The **Multi-Criteria Dynamic Card (MDC)** is a rules engine allowing you to authorize or refuse [Card Transactions](transactions) using powerful yet human-readable decision trees known as **Rulesets**.
**Configuration – MDC is not enabled by default**
Contact Treezor to request access to this feature.
## Use Cases
The Multi-Criteria Dynamic Card rules engine is extremely flexible and has many use cases that can be categorized as follows.
### Controlling Card Transactions
You can use MDC to restrict a Card usage to predefined scenarios.
For instance, in the case of meal vouchers, you may allow payments in restaurants and food outlets while denying the use of the Card to buy other goods.
### Tracking Card Transactions
MDC allows you to tag and group transactions by purpose. To do so, define Rulesets that match certain types of transactions. Once identified, you can categorize transactions and display them to your customers as you see fit.
For instance, you can display in separate virtual Wallets transportation and food-related expenses.
### Dynamic Card Account Selection
The [Card account selection](./modification#card-account-selection) feature allows you to debit a different Wallet for each transaction for a given card.
With the MDC rules engine, the selection occurs dynamically when the transaction is initiated, providing a seamless experience to your end users.
## Flow
The use of the Multi-Criteria Dynamic Card (MDC) feature can be summed up with the following diagram.
```mermaid
sequenceDiagram
autonumber
You->>Treezor: Define Rulesets
You->>Treezor: Assign Rulesets to Cards
loop For each card transaction request
Cardholder->>Treezor: Card Transaction Request
Note over Cardholder,Treezor: Everytime a Card is used, Treezor evaluates the assigned Rulesets without having to contact your servers
Treezor->>Cardholder: Immediate authorization or refusal
Treezor-->>You: Webhook
Note over Treezor,You: You are notified of the final decision
end
```
## Set up
**Reading – Restricted API Documentation**
Read all you need to know about managing Rulesets in the Support Center articles:
* [Multi-Criteria Dynamic Card](https://treezor.zendesk.com/hc/en-us/articles/13231619074844-Multi-Criteria-Dynamic-Card-MDC)
* [Managing Merchant Lists for MDC](https://treezor.zendesk.com/hc/en-us/articles/19177913508252-Managing-Merchant-Lists-for-MDC)
## Endpoints
### Rulesets
| Endpoint | Description |
|--- |--- |
| [`/v1/mdc/{cardId}/rulesets`](/api-reference/api-endpoints.html#tag/Rulesets/attach-ruleset-to-card){target="\_self"} | Assign a Ruleset to a Card |
| [`/v1/mdc/rulesets`](/api-reference/api-endpoints.html#tag/Rulesets/create-ruleset){target="\_self"} | Create a Ruleset |
| [`/v1/mdc/{cardId}/ruleset/{rulesetId}/factsBalance`](/api-reference/api-endpoints.html#/Rulesets/get_v1_mdc__cardId__ruleset__rulesetId__factsBalance) | Retrieve the virtual balance of a Ruleset |
| [`/v1/mdc/{cardId}/rulesets`](/api-reference/api-endpoints.html#tag/Rulesets/get-ruleset-from-card){target="\_self"} | Retrieve a Card Rulesets |
| [`/v1/mdc/rulesets`](/api-reference/api-endpoints.html#tag/Rulesets/get-rulesets){target="\_self"} | Retrieve all Rulesets (which supports [cursor-based pagination](/guide/api-basics/pagination#cursor-based-pagination)) |
| [`/v1/mdc/rulesets/{rulesetId}`](/api-reference/api-endpoints.html#tag/Rulesets/get-ruleset){target="\_self"} | Retrieve a Ruleset |
| [`/v1/mdc/rulesets/{rulesetId}`](/api-reference/api-endpoints.html#tag/Rulesets/put-ruleset){target="\_self"} | Update a Ruleset |
| [`/v1/mdc/rulesets/{rulesetId}`](/api-reference/api-endpoints.html#tag/Rulesets/disable-ruleset){target="\_self"} | Delete a Ruleset |
### Merchant Category Code Lists
| Endpoint | Description |
|--- |--- |
| [`/v1/mdc/mccLists`](/api-reference/api-endpoints.html#tag/MCC%20Lists%20\(MDC\)/postMdcMccList){target="\_self"} | Create MCC List |
| [`/v1/mdc/mccLists/{id}/codes`](/api-reference/api-endpoints.html#tag/MCC%20Lists%20\(MDC\)/importMdcMccListCodes){target="\_self"} | Import MCCs |
| [`/v1/mdc/mccLists`](/api-reference/api-endpoints.html#tag/MCC%20Lists%20\(MDC\)/getMdcMccLists){target="\_self"} | Get all MCC Lists |
| [`/v1/mdc/mccLists/{id}`](/api-reference/api-endpoints.html#tag/MCC%20Lists%20\(MDC\)/getMdcMccList){target="\_self"} | Get MCC List |
| [`/v1/mdc/mccLists/{id}/codes/{mcc}`](/api-reference/api-endpoints.html#tag/MCC%20Lists%20\(MDC\)/checkMdcMccListCode){target="\_self"} | Check MCC Presence |
| [`/v1/mdc/mccLists/{id}`](/api-reference/api-endpoints.html#tag/MCC%20Lists%20\(MDC\)/updateMdcMccList){target="\_self"} | Update MCC List |
| [`/v1/mdc/mccLists/{id}/codes/{mcc}`](/api-reference/api-endpoints.html#tag/MCC%20Lists%20\(MDC\)/addMdcMccListCode){target="\_self"} | Add MCC to MCC List |
| [`/v1/mdc/mccLists/{id}`](/api-reference/api-endpoints.html#tag/MCC%20Lists%20\(MDC\)/deleteMdcMccList){target="\_self"} | Delete MCC List |
| [`/v1/mdc/mccLists/{id}/codes/{mcc}`](/api-reference/api-endpoints.html#tag/MCC%20Lists%20\(MDC\)/removeMdcMccListCode){target="\_self"} | Remove MCC from List |
### Merchant Id Lists
| Endpoint | Description |
|--- |--- |
| [`/v1/mdc/midLists`](/api-reference/api-endpoints.html#tag/MID%20Lists%20\(MDC\)/postMdcMidList){target="\_self"} | Create MID List |
| [`/v1/mdc/midLists/{id}/merchantIds`](/api-reference/api-endpoints.html#tag/MID%20Lists%20\(MDC\)/importMdcMidListCodes){target="\_self"} | Import MIDs |
| [`/v1/mdc/midLists`](/api-reference/api-endpoints.html#tag/MID%20Lists%20\(MDC\)/getMdcMidLists){target="\_self"} | Get all MID Lists |
| [`/v1/mdc/midLists/{id}`](/api-reference/api-endpoints.html#tag/MID%20Lists%20\(MDC\)/getMidMccList){target="\_self"} | Get MID List |
| [`/v1/mdc/midLists/{id}/merchantIds/{mid}`](/api-reference/api-endpoints.html#tag/MID%20Lists%20\(MDC\)/checkMdcMidListCode){target="\_self"} | Check MID Presence |
| [`/v1/mdc/midLists/{id}`](/api-reference/api-endpoints.html#tag/MID%20Lists%20\(MDC\)/updateMdcMidList){target="\_self"} | Update MID List |
| [`/v1/mdc/midLists/{id}/merchantIds/{mid}`](/api-reference/api-endpoints.html#tag/MID%20Lists%20\(MDC\)/addMdcMidListCode){target="\_self"} | Add MID to MID List |
| [`/v1/mdc/midLists/{id}`](/api-reference/api-endpoints.html#tag/MID%20Lists%20\(MDC\)/deleteMdcMidList){target="\_self"} | Delete MID List |
| [`/v1/mdc/midLists/{id}/merchantIds/{mid}`](/api-reference/api-endpoints.html#tag/MID%20Lists%20\(MDC\)/removeMdcMidListCode){target="\_self"} | Remove MID from List |
---
---
url: /guide/cards/faking-operations.md
description: >-
Learn how to simulate card transactions (including complete transaction life
cycles) within the Sandbox environment for development and API integration
testing.
---
# Emulation
Emulation features are only available in the `Sandbox` [environment](/guide/api-basics/environments).
**Tip – You can also rely on webhooks**
For operations that cannot be emulated in Sandbox, [webhook examples](events) are provided.
## Card Transactions
You can emulate [Card Transactions](./transactions) using the following requests. This emulation feature is compatible with [Transactions external validation](./transactions-external-validation) and [Multi-Criteria Dynamic Card (MDC)](./transactions-rules-engine) testing.
### Simulate an Authorization
The [authorization](./transactions-lifecycle#authorization) is the first step of the card payment, which you can emulate with the following request.
**Prerequisites – For the paymentStatus to be accepted, you must ensure that:**
* The cardholder is KYC-validated & the Wallet has sufficient funds
* The card is activated and the limits are properly set
If not, the card transaction is created but refused (`paymentStatus` set to `I`), and you won't be able to emulate a settlement or reversal afterwards.
#### Parameters
Here are a few key parameters for simulation.
| Attribute | Type | Description |
| --- | --- | --- |
| `cardId` | integer | The unique identifier of the card. |
| `amount` | integer | Amount of the transaction expressed in the smallest unit of the Euro currency (e.g., `500` for "5.00"). Parameter available in the `payment` object. |
| `category` | string | The type of card transaction. Can be: `ecommerce`, `atm`, `chip`, `contactless`, `contactlessOnlinePin`. Parameter available in the `payment` object.|
| `partialApproval` | boolean | Emulates a partial approval of the card transaction. |
You can add more information regarding the desired `payment` and `merchant` information by adding the relevant parameters to the corresponding objects.
**API – API Reference available**
For a complete list of Card Transaction simulation attributes, check the [`/simulation/cardtransaction/authorization`](/api-reference/api-endpoints.html#tag//Card%20Transactions/simuTransacAuthorizations){target="\_self"} endpoint documentation.
#### Request
Endpoint: [`/simulation/cardtransaction/authorization`](/api-reference/api-endpoints.html#tag/Card%20Transactions/simuTransacAuthorization){target="\_self"}
```bash [CURL]
curl -X POST '{baseUrl}/simulation/cardtransaction/authorization' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
--data-raw '{payload}'
```
Here is a `{payload}` example:
```json [JSON]
{
"cardId": 12345,
"payment": {
"amount": 500,
"category": "ecommerce"
}
}
```
Returns the following information.
```json [JSON]
{
"paymentStatus": "A",
"cardTransactionId": 749207
}
```
Treezor also sends a [`cardtransaction.create`](./events-tx#cardtransaction-create) webhook.
Use the [`/v1/cardtransactions/{cardTransactionId}`](/api-reference/api-endpoints.html#tag/Card%20Transactions/getCardtransaction){target="\_self"} endpoint to retrieve the details of the emulated card transaction.
### Simulate a Settlement
You can then emulate the [settlement](./transactions-lifecycle#settlement) of the card transaction step, which occurs after the authorization. This emulation generates the following CardTransaction objet, which will have the same `paymentId` as the authorization, and a `paymentStatus` set to `S`.
#### Request
Endpoint: [`/simulation/cardtransaction/clearing`](/api-reference/api-endpoints.html#tag/Card%20Transactions/simuTransacClearing){target="\_self"}
```bash [CURL]
curl -X POST '{baseUrl}/simulation/cardtransaction/clearing' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
--data-raw '{payload}'
```
Here is a `{payload}` example:
```json [JSON]
{
"cardId": 12345,
"cardTransactionId": 67890
}
```
Returns an HTTP 204 No Content if successful.
Treezor also sends a [`cardtransaction.create`](./events-tx#cardtransaction-create) webhook and a [`balance.update`](/guide/wallets/events#balance-update) webhook when applicable.
After a few seconds, you can see the corresponding card transaction object with the relevant status was created by using the following request: [`/v1/cardtransactions?cardId=12345`](/api-reference/api-endpoints.html#tag/Card%20Transactions/readCardTransaction){target="\_self"}
### Simulate a Reversal
You can then emulate the [reversal](./transactions-lifecycle#reversal) of a card transaction. An authorization must have occurred first. This emulation generates the following CardTransaction objet, which will have the same `paymentId` as the authorization, and a `paymentStatus` set to `V`.
#### Request
Endpoint: [`/simulation/cardtransaction/reversal`](/api-reference/api-endpoints.html#tag/Card%20Transactions/simuTransacReversal){target="\_self"}
```bash [CURL]
curl -X POST '{baseUrl}/simulation/cardtransaction/reversal' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
--data-raw '{payload}'
```
Here is a `{payload}` example:
```json [JSON]
{
"cardId": 12345,
"cardTransactionId": 67890,
"amount": 250 // Optional, for partial reversal
}
```
Returns an HTTP 204 No Content if successful.
Treezor also sends a [`cardtransaction.create`](./events-tx#cardtransaction-create) webhook and a [`balance.update`](/guide/wallets/events#balance-update) webhook when applicable.
After a few seconds, you can see the corresponding card transaction object with the relevant status was created by using the following request: [`/v1/cardtransactions?cardId=12345`](/api-reference/api-endpoints.html#tag/Card%20Transactions/readCardTransaction){target="\_self"}.
## Simulate Card Transaction Authentication (SCA)
The Treezor API allows you to simulate the [authentication (SCA)](/guide/cards/transactions-authentication) process of an online card transaction. With these dedicated endpoints, you can trigger the relevant webhooks.
This is a 2-step process:
1. Simulate the authentication of an online card transaction for a given card.
2. Submit the result of the authentication to obtain the final result from Treezor.
Optionally, you can also simulate the cancellation of the authentication process.
```mermaid
sequenceDiagram
autonumber
participant ag as You
participant s as Treezor
participant se as Authentication Server simulator
ag->>se: Simulate authentication request: POST /simulation/auth-requests
se->>s: Sends OOB information
s->>s: Save authentication request with authenticationRequestId
s->>ag: card3DSv2Authentication.create with authenticationRequestId
alt Authentication canceled
ag->>se: POST /simulation/authrequests/{authRequestId}/cancel
se->>s: Communicate final authentication result
end
ag->>s: PUT /auth-requests/{authRequestId}/result
s->>ag: card3DSv2Authentication.update with final result
```
**Prerequisites – Enroll the user card for OOB authentication first**
The card must be enrolled for OOB in order to simulate an authentication.
[`/v1/cards/{cardId}/authentication-methods`](/api-reference/api-endpoints.html#tag/Card%203DSecure%20Enrollment%20\(SCA\)/postAuthMethods){target="\_self"}
### Simulate an authentication
This request simulates the authentication of an online card transaction for a given card.
#### Parameters
| Attribute | Type | Description |
| --- | --- | --- |
| `cardId` | integer | The unique identifier of the Card for which you want to simulate card transaction authentication. |
| `merchantName` | string | The name of the merchant processing the transaction for the simulated authentication. |
| `paymentAmount` | number | The amount of the transaction for the simulated authentication. |
| `paymentCurrency` | string | The currency of the transaction for the simulated authentication, in the ISO 4217 format. |
| `merchantAppRedirectURL` | string | As defined in the 3DS 2.2 specification, links back to the merchant application from an OOB app. |
#### Request example
Endpoint: [`/simulation/auth-requests`](/api-reference/api-endpoints.html#tag/Card%20Transactions%20Authentication%20\(SCA\)/simulateAuthRequest){target="\_self"}
```bash [CURL]
curl -X POST '{baseUrl}/simulation/auth-requests' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
--d '{payload}'
```
Here is a `{payload}` example:
```json [JSON]
{
"cardId": 12345,
"merchantName": "Tree Company",
"paymentAmount": 10.01,
"paymentCurrency": "EUR",
"merchantAppRedirectURL": "https://your.app.com/redirect"
}
```
Treezor sends a [`card3DSv2Authentication.create`](/guide/cards/events-tx#card3DSv2authentication-create) webhook.
From there, you can either:
* [Simulate a canceled authentication](#simulate-a-canceled-authentication)
* [Submit the authentication result](#submit-the-authentication-result)
### Simulate a canceled authentication
If the cardholder cancels the authentication process before it can be completed (i.e., leaves the application), the server indicates to Treezor that the authentication couldn't be carried out.
This information is available to you after you've submitted the authentication result through the [`card3DSv2Authentication.update`](/guide/cards/events-tx#card3DSv2authentication-update) webhook `authenticationFinalResult`.
Treezor provides a dedicated endpoint to simulate this situation.
#### Request example
Endpoint: [`/simulation/auth-requests/{authRequestId}/cancel`](/api-reference/api-endpoints.html#tag/Card%20Transactions%20Authentication%20\(SCA\)/simulateAuthRequest){target="\_self"}
The `authRequestId` is available in the [`card3DSv2Authentication.create`](/guide/cards/events-tx#card3DSv2authentication-create) webhook.
```bash [CURL]
curl -X POST '{baseUrl}/simulation/authrequests/{authRequestId}/cancel' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json'
```
Treezor answers with an HTTP 204.
You can now [submit the authentication result](#submit-the-authentication-result).
### Submit the authentication result
Whether you use the cancellation simulation or not, you must submit the authentication result to Treezor, so that Treezor can inform you of the final authentication result with the relevant webhook.
#### Parameters
| Attribute | Type | Description |
| --- | --- | --- |
| `authenticationResult` | integer | The result of your [end user authentication](/guide/cards/transactions-authentication.html#authentication-result), which can be: `OK`, `KO_TECHNICAL`, `KO_AUTH_FAILED`, or `FALLBACK`. |
#### Request example
Endpoint: [`/v1/auth-requests/{authRequestId}/result`](/api-reference/api-endpoints.html#tag/Card%20Transactions%20Authentication%20\(SCA\)/putAuthRequestResult){target="\_self"}
```bash [CURL]
curl -X PUT '{baseUrl}/v1/auth-requests/{authRequestId}/result' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is a `{payload}` example:
```json [JSON]
{
"authenticationResult": "OK"
}
```
Treezor sends the [`card3DSv2Authentication.update`](/guide/cards/events-tx#card3DSv2authentication-update) webhook with the `authenticationFinalResult` set as follows.
| Submitted `authenticationResult` | `authenticationFinalResult` |
| --- | --- |
| `OK` | `SUCCESS` |
| `KO_AUTH_FAILED` | `UNAUTHENTICATED` |
| `KO_TECHNICAL` | `ERROR` |
| `FALLBACK` | `FALLBACK` |
If you've simulated a cancellation by the server, the `authenticationFinalResult` is set to `ERROR`.
---
---
url: /guide/cards/transactions.md
description: >-
Get a foundational understanding of the Treezor API card transaction object.
Includes key attributes, JSON structure, and related endpoints list.
---
# Introduction
A Card Transaction represents a step of a card payment made with a Treezor-issued Card (e.g., authorization, settlement, or refund). They share the same `paymentId` value when generated by the same card payment.
## Key attributes
Below are some of the most important Card Transaction attributes.
| Attribute | Type | Description |
| --- | --- | --- |
| `cardtransactionId` | string | The unique identifier of the card transaction. |
| `cardId` | string | The unique identifier of the card used for the transaction. |
| `walletId` | string | The unique identifier of the Wallet the card is attached to. |
| `walletCurrency` | string | The currency of the Wallet, ISO 4217 3-digit code. |
| `merchantId` | string | The [MID](/guide/overview/glossary#merchant-identifier-number-mid) |
| `merchantName` | string | The name of the merchant. |
| `merchantCountry` | string | The country of the merchant. ISO 3166 3-letter code (except of the US which is a two-letter code) |
| `publicToken` | string | The token of the card (a way to identify a card without knowing or communicating its [PAN](/guide/overview/glossary#primary-account-number-pan)) |
| `paymentId` | string | The unique identifier of the card payment (or attempted payment), allowing you to follow the card transaction life cycle. |
| `paymentAmount` | string | The amount of the transaction, always expressed in Euros. |
| `paymentCurrency` | string | The local currency in which the transaction was made, ISO 4217 3-digit code. |
| `paymentLocalAmount` | string | The amount of the transaction in the local currency. |
| `paymentLocalDate` | string | The local date on which the transaction occurred. |
| `paymentLocalTime` | string | The local time at which the transaction occurred. |
| `paymentCountry` | string | Country in which the transaction occurred, ISO 3166 3-letter code. |
| `paymentStatus` | string | The general status of the transaction. **See [table](#statuses-paymentstatus) below** |
| `posCardholderPresence` | string | Describes more precisely how the card was used. **See [list](#cardholder-presence-poscardholderpresence) below** |
| `posCountry` | string | Country of the point of sale, ISO 3166 3-digit code (e.g., `250` for France). |
| `posTerminalId` | string | The id of the terminal used for the transaction. |
| `posCardPresence` | string | Indicates whether the card was physically present during the transaction: `0` – The card was **present**`1` – The card was **absent** `9` – The card presence **cannot be determined** |
| `panEntryMethod` | string | How the [PAN](/guide/overview/glossary#primary-account-number-pan) was captured by the merchant. **See [list](#pan-entry-method-panentrymethod) below** |
| `authorizationNote` | string | Contains detailed information regarding a declined card transaction. **See [Authorization notes](/guide/cards/authorization-notes)** for examples. |
| `authorizationResponseCode` | string | The precise status of the transaction. **See [Authorization response codes](/guide/cards/authorization-notes#authorization-response-codes)** |
| `authorizationIssuerId` | string | The transaction identifier as generated by the payment processor. |
| `authorizedBalance` | string | The [Authorized Balance](/guide/wallets/balances) of the wallet after the transaction. |
| `mcc` | string | The [Merchant Category Code (MCC)](/guide/overview/glossary#merchant-category-code-mcc). **A MCC valued to `6011` indicates a withdrawal**. Some MCC are prohibited for [anonymous electronic money](/guide/wallets/introduction#electronic-money-wallet-type-9), such as: money transfer, money order, foreign currency, liquid and cryptocurrency assets, lotteries, on-line gambling, betting, etc. |
| `acquirerId` | string | The identifier of the merchant's bank (acquirer) in the form of 5 to 6 digits. |
| `is3DS` | string | Indicates whether [3DSecure](/guide/overview/glossary#_3ds-3d-secure) was used for authentication: `1` – 3DS was **used**`0` – 3DS was **not used** |
| `totalLimitPaymentYear` | string | The related Card yearly spent amount. **This is used with [Cards Limits](/guide/cards/restrictions-limits#payment-withdrawal-limits)** |
| `totalLimitPaymentMonth` | string | The related Card monthly spent amount. **This is used with [Cards Limits](/guide/cards/restrictions-limits#payment-withdrawal-limits)** |
| `totalLimitPaymentWeek` | string | The related Card weekly spent amount. **This is used with [Cards Limits](/guide/cards/restrictions-limits#payment-withdrawal-limits)** |
| `totalLimitPaymentDay` | string | The related Card daily spent amount. **This is used with [Cards Limits](/guide/cards/restrictions-limits#payment-withdrawal-limits)** |
| `totalLimitPaymentAll` | string | The related Card lifetime spent amount. **This is used with [Cards Limits](/guide/cards/restrictions-limits#payment-withdrawal-limits)** |
| `totalLimitAtmWeek` | string | The related Card weekly ATM withdrawal amount. **This is used with [Cards Limits](/guide/cards/restrictions-limits#payment-withdrawal-limits)** |
| `totalLimitAtmDay` | string | The related Card daily ATM withdrawal amount. **This is used with [Cards Limits](/guide/cards/restrictions-limits#payment-withdrawal-limits)** |
| `totalLimitAtmAll` | string | The related Card lifetime ATM withdrawal amount. **This is used with [Cards Limits](/guide/cards/restrictions-limits#payment-withdrawal-limits)** |
| `cardDigitalizationExternalId` | string | The digital payment token identifier (only present if payment was made with a digital token such as Apple Pay or Google Pay for example). |
| `localMerchantId` | string | Indicates the merchant's SIREN or SIRET if available. |
Please note that when a CardTransaction produces a [Transaction](/guide/transfers/events#transaction-create) object, the `CardTransaction.id` is reflected in the `Transaction.foreignId` attribute.
**Caution – Data formats may differ**
The date, time, and country formats are different from [Treezor usual API format](/guide/api-basics/data-format) because Treezor displays the information as provided by the Card processor.
**API – API Reference available**
For a complete list of Card Transaction attributes, check the [Card Transactions](/api-reference/api-endpoints.html#tag/Card%20Transactions){target="\_self"} section of the API Reference.
### Statuses (`paymentStatus`)
This attribute allows you to identify the type of transaction, as Card payments almost always go through [many steps](./transactions-lifecycle).
| | Description | [Current Balance](/guide/wallets/balances) impact | [AuthorizedBalance](/guide/wallets/balances) impact | Note |
|:---:|---|:---:|:---:|----|
| `A` | [Authorization accepted](./transactions-lifecycle#authorization) | | | Authorization request accepted by Treezor |
| `R` | [Refund](./transactions-lifecycle#refunds) | | | Refunded authorization |
| `S` | [Settled](./transactions-lifecycle#settlement) | | Generally no | Can be:Refund is successful and the buyer has been refundedPayment is successful and the merchant has been paidMoneySend is successful and the cardholder's bank account has been credited |
| `M` | [MoneySend](./transactions-lifecycle#money-send) | | | MoneySend authorization |
| `C` | [Cleared](./transactions-lifecycle#authorization) | | | Settlement received without a previous matching authorization request. This happens when the payment terminal approves the transaction offline. The resulting asynchronous processing can take several days. |
| `I` | [Declined](./transactions-lifecycle#authorization) | | | Authorization refused |
| `V` | [Reversed](./transactions-lifecycle#reversed) | | | Authorization reversed. This may happen when an automated gas station authorized an amount greater than the actual amount of [fuel pumped](/guide/cards/transactions-examples#gas-station-transaction). |
Negative amounts and Non-Euro Settlement (`S`) can affect the Authorized Balance. See [Non-Euro example](/guide/cards/transactions-examples#non-euro-transaction) and [Negative amount settlement example](/guide/cards/transactions-examples#accepted-refund).
### PAN Entry Method (`panEntryMethod`)
This attribute informs you of how the [PAN](/guide/overview/glossary#primary-account-number-pan) was *provided to* or *accessed by* a merchant for a transaction.
| | Description |
|:-: |- |
| `0` | Unknown or no terminal |
| `1` | Manual Key Entry |
| `2` | Partial Magnetic Stripe Read |
| `3` | Barcode |
| `4` | OCR |
| `5` | Chip (contact interface) |
| `7` | Chip (contactless interface) |
| `10` | Credential-on-file (e.g., one-click purchase) |
| `79` | PAN & Expiration date entered by acquirer |
| `80` | Magnetic Stripe fallback (The terminal was not able to read the chip) |
| `81` | e-commerce |
| `91` | Contactless magstripe mod |
### Cardholder Presence (`posCardholderPresence`)
This attribute indicates whether the cardholder was present at the point of sale and provides details if they were not present.
| | | Cardholder Presence | Description |
|:---: |:---: |--- |--- |
| `0` | | Present | Cardholder present |
| `1` | | Not-present | Unspecified |
| `2` | | Not-present | Mail/facsimile order |
| `3` | | Not-present | Phone/ARU order |
| `4` | | Not-present | Standing order/recurring transactions |
| `5` | | Not-present | Electronic order (home computer, internet, mobile phone, PDA) |
| `6` | | Not-present | Installment transaction (similar to recurring but fixed number of installments) |
| `9` | | Unknown | Unknown |
### 3DS Exemption Type (`3dsExemptionType`)
| | Description |
|:---------:| ----------- |
| `0` | Transaction not exempt from SCA or unknown. |
| `1` | Transaction is exempt from SCA due to being on an exempt Merchant Category Code (MCC).(Acquirer did not provide an SCA exemption indicator.)(As of 11/02/2020, exempt MCCs are: 4111, 4112, 4131, 4784, 7523) |
| `2` | Contactless transaction under low-value limits. |
| `3` | E-commerce transaction under low-value limits. |
| `4` | Recurring/installment transaction. |
| `5` | Credit. Visa expects credit transactions to be out-of-scope. |
| `6` | Mail Order, Telephone Order or other cardholder-not-present transaction (except recurring which is above) which is excluded from SCA requirements. |
| `7` | Acquirer is exempt (located in a country outside of the EEA or UK, so do not fall under the PSD2 jurisdiction). |
| `8` | Not a transaction under PSD2 rules |
| `9` | Reserved for a possible future detected exemption |
| `A` | Acquirer transaction risk analysis. |
| `C` | Secure corporate payment. |
| `D` | SCA delegation. |
| `M` | Merchant initiated transaction. |
| `O` | Authentication outage exemption. |
| `R` | Recurring payment. |
| `T` | Trusted merchant. |
| `V` | Low value payment. |
### Card data enrichment
Merchant details in card transactions can be ambiguous. For instance, the name in the card transaction may diverge from the actual storefront name. This can lead to cardholders not understanding where the payment was made and asking their bank for a refund.
The card enrichment option helps mitigate the risks linked to ambiguous names.
**Feature Activation – Card data enrichment not available by default**
Please contact Treezor if you're interested in this feature.
#### Card transaction enriched fields
The following dedicated fields provide clearer card transaction data, when available.
| Attribute | Type | Description |
| --- | --- | --- |
| `optimizedMerchantName` | string | The name of the merchant, optimized for display and understanding. |
| `merchantLogo` | string | The URL's of the merchant's logo. |
| `merchantCategory` | string | The category of the merchant. Value may be displayed in the cardholder's language if available. |
| `merchantCategoryGroup` | string | Sub-group of the category defined in `merchantCategory`. Value may be displayed in the cardholder's language if available. |
| `merchantCategoryType` | string | Precise type of the sub-group defined in `merchantCategoryGroup`. Value may be displayed in the cardholder's language if available.|
Values may be in the cardholder's language based on the following information:
* The `language` in the User object or, if not defined
* The country of emission in the [Card program](./introduction#card-program)
Languages are progressively made available. As of today, English, French, German, Italian, and Spanish are supported.
## Card Transaction object
```json [JSON]
{
"cardtransactionId": "2xxx88",
"cardId": "1xx9",
"walletId": "9xx32",
"walletCurrency": "978",
"merchantId": "2288442AO1EOAZQ",
"merchantName": "REGULARISATION TVA",
"merchantCity": "330768976257 ",
"merchantCountry": "FRA",
"paymentLocalTime": "94902",
"publicToken": "58xxxx220",
"paymentAmount": "180.00",
"paymentCurrency": "978",
"fees": "0.00",
"paymentCountry": "FRA",
"paymentId": "1xxx63",
"paymentStatus": "A",
"paymentLocalAmount": "180.00",
"posCardholderPresence": "0",
"posPostcode": "5008",
"posCountry": "507",
"posTerminalId": "13061803",
"posCardPresence": "4",
"panEntryMethod": "1",
"authorizationNote": "",
"authorizationResponseCode": "0",
"authorizationIssuerId": "2354807787",
"authorizationIssuerTime": "2017-10-16 10:49:03",
"authorizationMti": "100",
"authorizedBalance": "18186.65",
"limitAtmYear": "0",
"limitAtmMonth": "0",
"limitAtmWeek": "100",
"limitAtmAll": "0",
"limitPaymentYear": "0",
"limitPaymentMonth": "5000",
"limitPaymentWeek": "5000",
"limitPaymentDay": "5000",
"limitPaymentAll": "0",
"totalLimitAtmWeek": "0.00",
"totalLimitAtmDay": "0.00",
"totalLimitAtmAll": "0.00",
"totalLimitPaymentYear": "0.00",
"totalLimitPaymentMonth": "1980.00",
"totalLimitPaymentWeek": "1980.00",
"totalLimitPaymentDay": "180.00",
"totalLimitPaymentAll": "0.00",
"cardDigitalizationExternalId": "0",
"mccCode": "5734",
"acquirerId": "12653",
"is3DS": null,
"merchantAddress": "",
"paymentLocalDate": "",
"3dsExemptionType": "",
"optimizedMerchantName": "",
"merchantLogo": "",
"merchantCategory": "",
"transactionSubtype": "",
"receiverData": "",
"senderData": "",
"transactionTypeIdentifier": "",
"localMerchantId": ""
}
```
## Endpoints
| Endpoint |[Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/v1/cardtransactions`](/api-reference/api-endpoints.html#tag/Card%20Transactions/readCardTransaction){target="\_self"} Search Card transactions | `read_only` |
| [`/v1/cardtransactions/{cardTransactionId}`](/api-reference/api-endpoints.html#tag/Card%20Transactions/getCardtransaction){target="\_self"} Retrieve a specific transaction, using its `id` | `read_only` |
| [`/v1/auth-requests/{authenticationRequestID}/result`](/api-reference/api-endpoints.html#/) Answer to a [Strong Customer Authentication](/guide/strong-customer-authentication/introduction) request | `read_write` |
**Reading – Find out more about Transactions**
* [Transactions lifecycle](/guide/cards/transactions-lifecycle)
* [Transactions examples](/guide/cards/transactions-examples)
* [Transactions authentication](/guide/cards/transactions-authentication)
## Object relations diagram
```mermaid
flowchart TD
CardTransaction(Card Transaction)
Authorization(Authorization)
AuthorizationExternal(External Authorization)
AuthorizationRuleEngine(Transaction Rules Engine)
Reversal(Reversal)
Settlement(Settlement)
Refund(Refund)
CardTransaction --- Authorization
CardTransaction --- Reversal
CardTransaction --- Settlement
CardTransaction --- Refund
Authorization -.- AuthorizationExternal
Authorization -.- AuthorizationRuleEngine
class CardTransaction MermaidNeutralAlternate
class AuthorizationExternal MermaidNeutral
class AuthorizationRuleEngine MermaidNeutral
click CardTransaction "/guide/cards/transactions-lifecycle.html"
click AuthorizationExternal "/guide/cards/transactions-external-validation.html"
click AuthorizationRuleEngine "/guide/cards/transactions-rules-engine.html"
click Authorization "/guide/cards/transactions-lifecycle.html#authorization"
click Reversal "/guide/cards/transactions-lifecycle.html#reversal"
click Settlement "/guide/cards/transactions-lifecycle.html#settlement"
click Refund "/guide/cards/transactions-lifecycle.html#refunds"
```
**Tip – Diagram is interactive**
Click on the diagram nodes to access the relevant documentation.
---
---
url: /guide/cards/transactions-external-validation.md
description: >-
Customize the criteria to validate or decline card payments with the external
validation feature.
---
# Transactions external validation
This feature allows you to validate or refuse end users payments, in real time and based on your custom criteria.
**Information – Treezor offers its own [Transaction Rules Engine](/guide/cards/transactions-rules-engine)**
Therefore, you no longer need to implement your criteria with the external validation. Contact Treezor to find out which option works best for you.
## General process
The external validation process works as follows.
1. **Authorization Request** – The end user makes a purchase with a [Card](creation).
2. **External Validation Request** – Treezor sends you an HTTP Request to a predefined endpoint of your own REST API.
3. **External Validation Response** – Your software makes a decision based on your own criteria and returns the decision in the HTTP Response.
* If you refuse, the transaction is **declined**.
* If you fail to answer within the allowed time frame, the transaction is **declined**.
* If you accept, Treezor handles the [Authorization](transactions-lifecycle#authorization) request like it would normally ([Authorized Balance](/guide/wallets/balances) verifications, [MID/MCC restrictions](/guide/cards/restrictions-limits#mcc-restrictions), etc.).
4. A [`cardtransaction.create`](events-tx#cardtransaction-create) webhook is sent. It includes the `requestId` of the External Validation request.
**Information – Your response must be provided within an allotted time frame**
The time frame is defined on a per-client basis. In the absence of a response in the allotted time, the Authorization is automatically declined.
## Request example
A POST request is sent to your own API endpoint, as defined during the subscription to this feature.
```json [JSON]
{
"request_id": "e03df174-ff01-571c-8677-e52af53affda", // UUIDv5
"card_public_token": "988927734", // card Public Token
"request_date": "2021-04-20T10:29:44+00:00", // Date/time of sending (RFC 3339 format)
"payment_amount": {
"value": 17.01, // Payment amount, including all fees, float. Positive for a Debit, Negative for a Credit.
"value_smallest_unit": 1701, // Payment amount, including all fees, in the smallest unit of associated currency
"currency_code": "978" // Billing currency - ISO 4217 3 digit
},
"payment_local_amount": {
"value": 7.01, // Payment amount in local currency, float
"value_smallest_unit":701, // Payment amount in local currency, in the smallest unit of associated currency
"currency_code": "978" // Local currency - ISO 4217 3 digit
},
"payment_local_time": "145958", // Local time of transaction - “hhmmss”
"payment_local_date": "20210420", // Local date of transaction - "yyyymmdd"
"local_day_of_week": 5, // local day of week: 1,2,3,4,5,6,7 with 1 being Monday
"authorization_issuer_id": "928257521", // Transaction Unique ID from the Card Processor
"merchant_data" : {
"id": "000980200909995", // Merchant ID
"name": "PAYPAL ", // Merchant Name
"city": "PARIS", // Merchant City
"country": "FRA", // Merchant Country - ISO 3-alpha country code
"mcc": "4512", // Merchant Category Code
"acquirer_id": "06004441", // Acquirer ID
}
}
```
## Response example
All requests must be answered to.
#### Approve the transaction
If you approve the card transaction, you can answer with the following JSON response.
```json [JSON]
{
"response_date": "2021-04-20T10:29:49+00:00", // Date/time of your decision (RFC 3339 format)
"response_code" : "AUTHORIZED", // Your decision
"response_id": "e03df174-ff01-571c-8677-e52af53affda" // Unique response ID that you have generated (It can be a signature of the provided requestId)
}
```
#### Refuse the transaction
If you refuse the card transaction, you can answer with the following JSON response.
```json [JSON]
{
"response_date": "2021-04-20T10:29:49+00:00", // Date/time of your decision (RFC 3339 format)
"response_code" : "DECLINED", // Your decision, other values are available in the list below
"response_id": "e03df174-ff01-571c-8677-e52af53affda" // Unique response ID that you have generated (It can be a signature of the provided requestId)
}
```
#### Dynamic account selection
If you are using [dynamic card account selection](./modification#card-account-selection), the wallets array is to be included in your response, with the following attributes.
| Attribute | Type | Description |
| --- | --- | --- |
| `id` | string | The unique identifier of the Wallet to debit. |
| `priority` | integer | The priority of the rule in case of conflict. The higher the value, the higher the priority. This field is required if the `id` is provided. Max. value: 100. |
Here is a JSON response example.
```json [JSON]
{
"response_date": "2021-04-20T10:29:49+00:00", // Date/time of your decision (RFC 3339 format)
"response_code" : "AUTHORIZED", // Your decision
"response_id": "e03df174-ff01-571c-8677-e52af53affda", // Unique response ID that you have generated (It can be a signature of the provided requestId)
"wallets" : [ // Wallet IDs / priority list // can be empty or have one or more items
{
"id": "123456",
"priority": 50
}
]
}
```
## Response Codes (`responseCode`)
You can answer to an External Validation request with the following codes:
| | Code |
| :---: | --- |
| | `AUTHORIZED` |
| | `DECLINED` |
| | `DECLINED_CARD_UNKNOW` |
| | `DECLINED_DATETIME_INVALID` |
| | `DECLINED_DUE_TO_REGULATORY_RULES` |
| | `DECLINED_INSUFFICIENT_FUNDS` |
| | `DECLINED_INSUFFICIENT_FUNDS_WITHDRAWAL_LIMIT_REACHED` |
| | `DECLINED_LOCAL_CURRENCY_INVALID` |
| | `DECLINED_MCC_INVALID` |
| | `DECLINED_MERCHANTID_INVALID` |
| | `DECLINED_MERCHANT_CITY_INVALID` |
| | `DECLINED_MERCHANT_COUNTRY_INVALID` |
**Information – Other responses may occur**
Any other response will be considered as `DECLINED`.
## Special case of Balances not managed by Treezor
In the use case where you manage the Balance and Authorized Balance yourself:
* No funds withholding will take place, as Treezor doesn't manage the funds
* At [settlement](transactions-lifecycle#settlement), the funds are debited or credited on your main Wallet (which should be provisioned accordingly).
---
---
url: /guide/dashboard/cards.md
description: >-
Let your team provide support regarding your end users cards using the Treezor
Dashboard.
---
# Cards
The Cards are the payment cards you issue for your end users, either in a virtual or physical form. They can be directly created and managed from your Dashboard.
## Accessing Cards
You may access card information by:
* Taking advantage of the main [*Search field*](#search-field).
* Navigating the [*Cards*](#cards-view) view.
* Navigating the *User details* view, [*Cards*](#user-details-view-cards-tab) tab once a user is selected.
### Search field
The Dashboard main toolbar provides a search field, whose searchable attribute becomes dynamically available depending on what you enter.
Here are the attributes for you to search cards:
* **Card ID/Public token** – Takes into account the `cardId` or the `publicToken` of the [Card](/guide/cards/introduction).
* **Embossed name** – Takes into account the name displayed on the card (`embossedName`).
After validating your search for a given card attribute, the [*Cards*](#cards-view) view is displayed, filtered on the corresponding Card for you to select.
### Cards view
The *Cards* view provides the list of all the cards with their key attributes.
To help you navigate through the list, the following filters are available:
* **Card status** – Display only cards with the selected status.
* **Card type** – Display only cards with the selected medium.
* **Creation date** – Display only cards created on, before, after, or between specific dates.
In addition, the secondary Search field allows you to search cards by `cardId`, `publicToken`, or by `embossedName`.
Clicking on arrow icon for a card switches the view to the corresponding card in the [*User details*](#user-details-view-cards-tab) view.
### User details view, Cards tab
Once you've accessed a *User details* view, click on the *Cards* tab to view all the cards attached to the user.
The view is divided into 2 sections:
* [**Cards**](#card-preview) – On the left-hand side, you can navigate and manage the user cards.
* [**Transactions**](#transactions-section) – On the right-hand side, you can view the transactions of the selected card. When the card is not activated yet, this section contains the "Activate" button.
## Navigating the Card information
### Card preview
In the *Cards* tab, *Cards* section, the card preview is displayed. When several cards are available, you can navigate by using the numbers below the card or take advantage of the *Search* field.
The following card information is available in the preview:
* Card type (whether it is virtual, physical, or converted to physical)
* Card status
* Cardholder's name
* Public token
* Partially masked [PAN](/guide/overview/glossary#primary-account-number-pan)
* Unique identifier
* Expiration date
The following card statuses can be displayed:
| Status | Description |
|--- | --- |
| **Active** | Cards that have been activated. |
| **Inactive** | Cards that have not been activated yet, or which have been locked or blocked (i.e., exceeded the number of PIN attempts). |
| **Blocked** | Cards that are either declared as lost or stolen.|
| **Expired** | Cards that are either past their expiration date or destroyed. |
| **Frozen** | Cards that have been blocked by Treezor. |
The action buttons below the card preview vary depending on the status of the card:
* **Activate** the card.
* **Lock** – Disable the card use on a temporary basis.
* **Unlock** – Unblock a locked card.
* **Other statuses** – Provides other options to update the status, including reporting the card as lost or stolen.
The **More** (ellipsis) button provides additional commands:
| | Command | Description |
| :---: | --- | --- |
| | **Manage card** | Opens the *Manage card* popup. This popup may be read-only if the card is in an inactive status. |
| | **Go to wallet** | Switches the view to the *Wallets* tab, with the wallet to which the card is attached displayed. |
| | **Reassign card** | If available, opens the *Reassign Card* popup, allowing you to change the cardholder of an inactive card belonging an anonymous user. |
### Transactions section
Once a card is selected, the corresponding transactions (if any) are displayed in the right-hand side of the view.
The list of transactions can be sorted, filtered, and customized as you see fit.
| Option | Description |
|--- |--- |
| **Search** | Search for transactions based on their Payment ID or Wallet ID. |
| **Date** | Define the date range for which the transactions are considered. Any transaction whose authorization date is not in the defined time frame is filtered out. |
| **Amount** | Define the amount range for the transactions to be considered. Any transaction outside the frame is filtered out. |
| **Status** | Select the transactions to be displayed based on their Status (e.g., Accepted, Declined, etc.) |
| **MCC** | Enter or select a Merchant Category Code (MCC). Only transactions with this MCC are then displayed. |
| **Merchant ID** | Enter a Merchant ID. Only transactions with this MID are then displayed. |
| **Payment filters** | Select which specific payment mode to display. |
| **Clear filters** | Resets all the sorting and filtering options. Only displayed if at least one filter is selected. |
| **Organize columns** | Opens a panel for you to select which columns to display and in which order (drag & drop). You may save your changes or reset to the initial display by using the corresponding buttons. Your selection is saved in the local storage for next time. |
In addition, the following elements in the table facilitate the navigation:
* **Digitized Card** – Opens the *Manage card* popup, [*Digitized cards*](#manage-digitized-cards) tab.
* **Wallet** – Switches the view to the [*Wallets*](./wallets) tab with the corresponding wallet selected.
* **Transaction details** – Clicking on the arrow on the right-most column opens a side panel with the detailed information regarding the card transaction.
## Creating a Card
You can create a new card for a user from the *User details* view, *Cards* tab.
Please note:
* You need to create a [Wallet](./wallets) beforehand.
* Options to create virtual or physical cards depend on your card program.
The *Create card* dialog box corresponding to your selection is displayed.
Once you have selected the wallet and the card program, you can click next to proceed.
In the next step, the default limits and options from your card program are displayed. You can adjust them before creating the card.
Once this done, you can click on the "Create card" button to complete the creation.
## Creating Cards in bulk
You can order Cards in bulk using the *Bulk Cards* view. At the end of the process, the Cards will be sent to a unique address.
Click on the "Create bulk cards" button in the upper right corner of the view to start the process and follow the steps.
| Step | Description |
|--- |--- |
| **Cards quantity** | Indicate the number of cards you wish to create. |
| **Card program** | Select your card program (`cardPrint`) and whether to create physical or virtual cards. Options available depend on your card program. |
| **Perms group** | Define your card options by activating the toggles:**Online** – Enables e-commerce payments**NFC** – Enables contactless payments**ATM** – Enables ATM withdrawals **International** – Enables usage outside of the cardholder's country |
| **Wallet & User Id** | Cards are always attached to a user and a wallet. Define:**The Wallet** – Either a new wallet that will be created at the same time as the card (select the type) or an existing one (enter the ID)**The User(s)** – A unique user ID (e.g., all your cards are attached to a Master Wallet) or multiple users (users will be automatically generated when the cards are created). You may need to select a [distribution country](/guide/users/introduction#distribution-country-distributioncountry) as well. |
| **Name** | Define whether the user name is displayed on the card. This is only possible if you have a unique user ID in the previous step. |
| **Options** | Define additional options for your card:**Logo ID** – If provided with your Card Program.**Package reference** – If provided with your Card Program.**Batch Delivery ID reference** – If you have the option to send cards in batch.**Design code reference** – If you have multiple card designs.**Restriction groups** – If some predefined restriction groups have been created, you can already define MCC, MID and Country restrictions for your cards.**Limits** – Define limits to apply to your set of cards. |
| **Create** | Review the bulk card creation to make sure everything is in order before validating the order. |
Once your order complete, you are redirected to the *Bulk orders list*, in which you can follow the status of the order.
### Bulk orders list
The main display of the *Bulk Cards* view lists all your previous orders, whether they have succeeded or not.
You can track the progress of a Bulk Card creation using the dedicated interface below.
For each bulk creation, key information such as the Order ID and Creation Date are available. Please note that the GPS ID stands for your Card Program card print.
The following commands are available.
| | Action | Description |
|:---: |--- |--- |
| | View error report | Downloads the error report in the CSV format. |
| | View creation details | Opens the Bulk Card creation details popup. |
| | Download creation details | Downloads the creation details in the CSV format. |
## Managing Cards
You have the ability to manage existing cards from the *User details* view, *Cards* tab for any selected user. Most options are defined in the *Manage card* popup, available upon clicking on the "More" button and selecting the "Manage card" option.
You have the ability to:
* [**Activate the Card**](#activate-a-card)
* [**Enroll the Card for 3D Secure**](#enroll-card-for-3ds)
* [**Update the Card options**](#update-card-options) and [**Limits**](#update-card-limits)
* [**Manage Card restrictions**](#manage-card-restrictions) (MCC, MID and Country)
* [**Block the Card**](#block-a-card) – Disable and enable the card use on a temporary basis or declare the card as stolen or lost
* [**Unblock PIN**](#unblock-pin-code) – Unblock a card locked due to too many PIN attempts
* [**Unblock CVC**](#unblock-cvc) – Unblock a card locked due to too many CVC attempts
* [**Convert to Physical**](#convert-a-virtual-card-to-physical) – Create a physical version or a Virtual Card
* [**Manage Digitized Cards**](#manage-digitized-cards) – Suspend, unsuspend, and delete digitized cards.
### Activate a Card
As a security measure, all Cards are issued in an inactive state to ensure that a Physical Card is not usable before the cardholder receives it. Inactive cards can’t be used to make any type of payment or withdrawal.
Cards must therefore be activated once before they can be used, this can be done using the "Activate" button available below the card preview in the *User details* view, *Cards* tab. The following confirmation popup will be displayed for you to activate the card.
**Best practice – Enhance user experience with cardholder activation**
Cardholders are usually able to activate their Card by themselves using a code (`publicToken`) printed on their Card and entering it in your App.
### Enroll Card for 3DS
[3D Secure](/guide/overview/glossary#_3d-secure-3ds) is a protocol designed to add an additional security layer to online card payments.
Cards must be registered with the following methods to accept secure online payments.
| Method | Description |
| --- | --- |
| **[Out of Band (OOB)](/guide/strong-customer-authentication/securing-endpoints#enrolling-to-out-of-band-authentication)** | The cardholder must go through a strong customer authentication through their payment application. Primary and mandatory form of enrollment. |
| **[SMS method](/guide/cards/creation#enrolling-a-card-for-3d-secure)** | The cardholder receives a code on their mobile phone when an authentication is required for the online payment. This code is unique for each payment and needs to be entered on the merchant's website or mobile application when prompted. Mandatory fallback method. |
To enable 3DS, go to the *Manage card* popup, *Security* tab, and click on the "Add OOB" button available in the 3D Secure section.
When doing so, the button "Remove OOB" is displayed and the Out of Band (OOB) indicator is set to "Enabled".
It is recommended to activate the Fallback method too. This action is irreversible.
**Caution – Users must have a mobile phone number**
If they don't, update the [User](/guide/dashboard/users) with a mobile phone number.
### Update Card options
The card options allow you to define the conditions in which a card can be used.
In the *Manage card* popup, *Settings* tab, *Options* section, the following settings are available for you to update after clicking on the "Edit" (pen) icon:
* **ATM** – Enables ATM withdrawals
* **International** – Enables usage outside the cardholder's country
* **Contactless (NFC)** – Enables contactless payments
* **Online** – Enables e-commerce payments
Make sure you click on the "Save" button to validate your modifications.
### Update Card limits
You can modify both the **Payment limits** and **Withdrawal (ATM) limits** of a Card in the *Manage card* popup, *Settings* tab, *Limits* section by clicking on the "Edit" (pen) icon.
**Tip – Rules about limit setting**
* Setting a limit value to 0 deactivates the limit.
* For each category, at least one of `Daily`, `Weekly` or `Monthly` **must** be > 0.
* If two limits conflict with each other, the lowest will always be authoritative.
#### Configurable limits
Below is the list of configurable limits.
| Limit type | Limit | Description |
|--- |--- |--- |
| Withdrawal | Limit ATM by day | Defines the maximum amount the user can withdraw on a sliding day. |
| Withdrawal | Limit ATM by week | Defines the maximum amount the user can withdraw on a sliding week. |
| Withdrawal | Limit ATM by month | Defines the maximum amount the user can withdraw on a sliding month. |
| Withdrawal | Limit ATM by year | Defines the maximum amount the user can withdraw on a sliding year. |
| Withdrawal | Global ATM limit | Defines the overall amount the user can withdraw. |
| Payment | Limit Payment by day | Defines the maximum amount the user can use on a sliding day. |
| Payment | Limit Payment by week | Defines the maximum amount the user can use on a sliding week. |
| Payment | Limit Payment by month | Defines the maximum amount the user can use on a sliding month. |
| Payment | Limit Payment by year | Defines the maximum amount the user can use on a sliding year. |
| Payment | Global Limit Payment | Defines the overall amount the user can pay. |
Make sure you click on the "Save" button to validate your modifications.
### Manage Card restrictions
Card restrictions allow you to define in which countries and for which merchants a card may be used. In the *Manage card* popup, *Restrictions* tab, you can assign the following types of whitelists and blacklists:
* **MCC** – Defines the card use for specific [Merchant Category Code(s)](/guide/overview/glossary#merchant-category-code-mcc)
* **MID** – Defines the card use for specific [Merchant Id(s)](/guide/overview/glossary#merchant-identifier-number-mid)
* **Country** – Defines the card use for specific Country(ies)
**Information – Lists are managed by the Administrator**
Dashboard Users with the Administrator role can define whitelists and blacklists for restriction groups in the [*Predef Restriction Groups*](./card-restrictions) view.
#### Adding a restriction list
In order to apply restrictions (whitelist, or blacklist) to a card, go to the *Manage card* popup, *Restrictions* tab, and select a restriction category on the right-hand side of the view.
From there, a picklist is available for you to select one of the restriction list created by your Administrator.
Once a specific list selected for a card, you must click on the "Save" button to validate your choice.
#### Updating restriction lists
When clicking on the "More" (ellipsis) button for a given restriction group, the more commands are available.
| | Command | Description |
| :---: | --- | --- |
| | **Download restriction list** | Download the list in CSV format. |
| | **Change restriction list** | Select another restriction list to replace the currently assigned one. |
| | **Remove restriction list** | Remove the list from the card restrictions. The card no longer has a whitelist of blacklist for the corresponding category. |
### Block a Card
The Dashboard allows you block a card in case of a security issue; this can be done by using directly the buttons available below the card preview. Options available depends on the current card status:
| Action | Description |
| --- | --- |
| **Lock** | Temporarily lock (or custom lock) the card, you may unblock it afterward. |
| **Report as lost or stolen** | Declare the card as stolen or lost. This action irreversibly blocks the card. |
| **Destroy card** | Block permanently the card, at the end of the relationship with the end user for instance. This action is irreversible. |
| **Unlock** | Unlock the card. Only available when the card has been temporarily locked. |
A confirmation popup prompts you to validate the action.
### Unblock PIN code
The card can be blocked when the cardholder enters 3 erroneous PIN codes in a row.
You can unblock the card by using directly the "Unblock PIN" button available below the card preview when relevant.
### Unblock CVC
The [card verification code (CVC)](/guide/overview/glossary#card-verification-number-cvc) can get locked if the cardholder enters an erroneous CVC multiple times in a row while attempting an online payment.
You can unblock a card CVC in the *Manage card* popup, *Security* tab, *Unblock CVC* section.
**Danger – You must verify the cardholder's identity**
The card verification code is a security measure, you must make sure the request for unblocking the card comes from the legitimate cardholder.
### Convert a Virtual Card to Physical
A Virtual Card can be converted to a Physical one, which will be sent to the cardholder.
To convert a card, go to the *Manage card* popup and click on the "Convert to Physical Card" button available in the top-right corner of the *Settings* tab.
A success message is displayed in the top of the screen if the operation succeeds.
### Manage Digitized Cards
Treezor offers your [Dashboard Users](/guide/dashboard/dashboard-users) the ability to suspend and delete digitized cards (i.e., cards that are tokenized in a Google Pay, Apple Pay, or Samsung Pay wallet). This way, they can swiftly handle customer requests when it comes to dealing with fraud and lost cards for instance.
To manage digitized cards, go to the *Manage card* popup, *Digitized Cards* tab.
It displays the list of digitized cards for the currently selected card.
Digitized cards may have one of the following statuses:
* **Active** – The digitized card is active and can be used as a means of payment.
* **Suspensed** – The digitized card is suspended; it can't be used, but can be reactivated.
* **Deactivated** – The digitized card is deleted, it can't be used and this status if final.
The following commands are available depending on the digitized card status.
| | Action | Description |
| :---: | --- | --- |
| | Suspend | Prompts a dialog to suspend the digitized card, with a picklist to select the reason (e.g., device is lost or stolen). |
| | Unsuspend | Prompts a dialog to unsuspend the digitized card, with a picklist to select the reason. |
| | Delete | Prompts a dialog to deactivate the digitized card, with a picklist to select the reason (e.g., device is lost or stolen). This action is irreversible. |
---
---
url: /guide/cheques/errors.md
description: >-
Troubleshoot and handle check cashing-related issues using the Treezor API's
complete list of error codes, messages, and their corresponding meanings.
---
# Errors
Find below the list of API Errors that may occur when handling checks.
| Code | Message |
|:-: |- |
| 1 | Generic Error |
| 10010 | Invalid Argument. Wallet not found |
| 14003 | Impossible to create Payin |
| 14005 | This payin does not exist |
| 14007 | Impossible to cancel the payin |
| 14008 | The userId does not exist or is not in a status VALIDATED. |
| 14009 | Unable to create payin with the provided walletId. It does not exist. |
| 14010 | The RLMCKey is not valid |
| 14011 | Unable to create payin. The wallet is not in a status VALIDATED |
| 14012 | The specified currency for payin must be the same as the currency of the wallet |
| 14015 | The provided amount must be greater than 1. |
| 14018 | Unable to cancel the payin. The payin is already in a status CANCELED |
| 14019 | Unable to cancel the payin. The payin is in a status VALIDATED |
| 14088 | Impossible to create the payin the user has a kyc Level refused |
| 50005 | Authentication failed |
| 73001 | An invalid argument was given |
| 88003 | The userId parameter is automatically set by the API in the case of a payin of type cheque. Do not set this value |
| 88004 | The additionalData field is not in a correct format. |
| 88005 | The additionalData field is mandatory |
| 88011 | The API call to our partner failed |
| 88013 | The RLMC Key is not valid |
| 88014 | This cheque has already been treated |
| 88020 | You are not set to use this type of Payin please contact your account Manager |
| 88023 | Impossible to update the status of the payin |
| 88046 | Cannot create the payin, amount exceed the maximal amount |
| 90000 | Cannot cancel the payin, treatment ongoing at the treatment center |
| 140011 | The client is already configured and can not be created again |
| 140101 | The cheque client configuration deletion failed |
| 150010 | The provided token is expired |
| 160000 | The payin was not found |
| 211000 | Impossible to create the operation, no reason code |
| 211001 | Impossible to create the operation, not enough account's funds |
| 211002 | Impossible to create the operation, the assets of the user are frozen |
| 211003 | Impossible to create the operation, the assets of the user are frozen |
| 211005 | Impossible to create the operation, the KYC Level of the parent user is not Light, Regular |
| 211006 | Impossible to create the operation, the currency of the authorization and the account's currency are different |
| 211008 | Impossible to create the operation, the authorization is a duplicate of an existing authorization |
| 211009 | Impossible to create the operation, the account's user is not found |
| 211011 | Impossible to create the operation, the account's balance is not found |
| 211012 | Impossible to create the operation, Unknown error (internal error) |
| 211013 | Impossible to create the operation, the context of the authorization is canceled (timeout or initiated by the client) |
| 211014 | Impossible to create the operation, the original authorization is not found (for reversal or cancel) |
| 211015 | Impossible to create the operation, the original authorization has an unexpected status |
| 211018 | Impossible to create the operation, the authorization is forbidden due to authorization type, user, account |
| 211019 | Impossible to create the operation, the total debit exceed the max total debit limit on sliding period |
| 211020 | Impossible to create the operation, the authorization amount exceed the max amount limit |
| 211021 | Impossible to create the operation, the authorization amount added to the account limit exceed the max account amount limit |
| 211022 | Impossible to create the operation, the transfer creditor user is invalid |
| 211023 | Impossible to create the operation, the transfer debitor user is invalid |
| 211024 | Impossible to create the operation, the transfer creditor account is not found |
| 211025 | Impossible to create the operation, the transfer creditor account's user is not found |
| 211026 | Impossible to create the operation, the total credit exceed the max total credit limit on sliding period |
| 211032 | Impossible to create the operation, the transfer creditor and debtor account are not found |
| 211033 | Impossible to create the operation, the user is legal frozen |
| 213001 | Unable to process payin authorization |
| 213002 | Unable to process payin transaction |
| 230001 | Cannot cancel the payin, its current state does not allow it |
| 300000 | Generic Internal Error |
| 300001 | A mandatory argument was not provided |
---
---
url: /guide/cheques/events.md
description: >-
Reference a comprehensive list of check acquiring events for Treezor API
webhooks, detailing each event's structure and payload for integration.
---
# Events
This article lists the [Webhooks](/guide/webhooks/introduction) you may receive when regarding Check acquiring.
## Check Payin events
### `payin.create`
```json [JSON]
{
"webhook": "payin.create",
"webhook_created_at": 17097149232358,
"object_id": "93a3a3f9-a3f2-4352-96f6-e6670cd3aa6a",
"object": "payin",
"object_payload": {
"payins": [
{
"payinId": "93a3a3f9-a3f2-4352-96f6-e6670cd3aa6a",
"payinTag": "tag-Checking Account",
"walletId": "68014791",
"userId": "865508",
"payinStatus": "PENDING",
"paymentMethodId": "26",
"messageToUser": "Message to the user",
"subtotalItems": "0.00",
"subtotalServices": "0.00",
"subtotalTax": "0.00",
"amount": "10000.00",
"currency": "EUR",
"createdDate": "2024-03-06 09:48:40",
"walletEventName": "Checking account",
"walletAlias": "checkingaccount-6593e02138fd8",
"userFirstname": "Alex",
"userLastname": "Oak",
"codeStatus": "160003",
"informationStatus": "The cheque can now be sent to the treatment center",
"refundAmount": null,
"DbtrIBAN": null,
"forwardUrl": null,
"paymentAcceptedUrl": null,
"paymentRefusedUrl": null,
"paymentWaitingUrl": null,
"paymentExceptionUrl": null,
"paymentCanceledUrl": null,
"payinDate": "0000-00-00",
"mandateId": "0",
"creditorName": null,
"creditorAddressLine": null,
"creditorCountry": null,
"creditorIban": null,
"creditorBIC": null,
"virtualIbanId": null,
"virtualIbanReference": null,
"additionalData": {
"cheque": {
"cmc7": {
"a": "0557016",
"b": "045010041908",
"c": "001071920333"
},
"drawerData": {
"firstName": "M. ALEX OAK",
"isNaturalPerson": true
},
"RLMCKey": "62"
}
},
"totalRows": 1,
"paymentHtml": null
}
]
},
"webhook_id": "498a9122-8e92-4dfe-9c76-40ebc39a6e24",
"object_payload_signature": "PPFEQwEYkQKlSNrUhhKN1V7afoOoCa225Shgh+SDqxg="
}
```
### `payin.update`
```json [JSON]
{
"webhook": "payin.update",
"webhook_created_at": 17067103308448,
"object_id": "25be7879-2fee-4080-bf45-fc93ecf97xx3",
"object": "payin",
"object_payload": {
"payins": [
{
"payinId": "25be7879-2fee-4080-bf45-fc93ecf97xx3",
"payinTag": "tag-Checking Account",
"walletId": "68009611",
"userId": "865522",
"payinStatus": "PENDING",
"paymentMethodId": "26",
"messageToUser": "Message to the user",
"subtotalItems": "0.00",
"subtotalServices": "0.00",
"subtotalTax": "0.00",
"amount": "10000.00",
"currency": "EUR",
"createdDate": "2024-01-31 15:12:07",
"walletEventName": "Checking account",
"walletAlias": "Checking account-100002428",
"userFirstname": "Alex",
"userLastname": "Oak",
"codeStatus": "151132",
"informationStatus": "The check has been received by the treatment center of our partner.",
"refundAmount": null,
"DbtrIBAN": null,
"forwardUrl": null,
"paymentAcceptedUrl": null,
"paymentRefusedUrl": null,
"paymentWaitingUrl": null,
"paymentExceptionUrl": null,
"paymentCanceledUrl": null,
"payinDate": "0000-00-00",
"mandateId": "0",
"creditorName": null,
"creditorAddressLine": null,
"creditorCountry": null,
"creditorIban": null,
"creditorBIC": null,
"virtualIbanId": null,
"virtualIbanReference": null,
"additionalData": {
"cheque": {
"cmc7": {
"a": "0557016",
"b": "045010041908",
"c": "001071920333"
},
"drawerData": {
"firstName": "M. ALEX OAK",
"isNaturalPerson": true
},
"RLMCKey": "62"
}
},
"totalRows": 1,
"paymentHtml": null
}
]
},
"webhook_id": "669911f2-3177-4655-93d4-6eaad0xx4727",
"object_payload_signature": "OSet8MKvrd8xVG6turNr3ZWHbH+T0IUPmEh8pNxxxT4="
}
```
### `payin.cancel`
```json [JSON]
{
"webhook": "payin.cancel",
"webhook_created_at": 17067103308448,
"object_id": "25be7879-2fee-4080-bf45-fc93ecf97ac3",
"object": "payin",
"object_payload": {
"payins": [
{
"payinId": "25be7879-2fee-4080-bf45-fc93ecf97xx3",
"payinTag": "Checking account",
"walletId": "68009677",
"userId": "865508",
"payinStatus": "CANCELED",
"paymentMethodId": "26",
"messageToUser": "Message to the user",
"subtotalItems": "0.00",
"subtotalServices": "0.00",
"subtotalTax": "0.00",
"amount": "10000.00",
"currency": "EUR",
"createdDate": "2024-01-31 15:12:07",
"walletEventName": "Checking Account",
"walletAlias": "checkingAccount-100002428",
"userFirstname": "Alex",
"userLastname": "Oak",
"codeStatus": "151134",
"informationStatus": "The check has not been received by the treatement center in the allowed delay of 15 calendar days",
"refundAmount": null,
"DbtrIBAN": null,
"forwardUrl": null,
"paymentAcceptedUrl": null,
"paymentRefusedUrl": null,
"paymentWaitingUrl": null,
"paymentExceptionUrl": null,
"paymentCanceledUrl": null,
"payinDate": "0000-00-00",
"mandateId": "0",
"creditorName": null,
"creditorAddressLine": null,
"creditorCountry": null,
"creditorIban": null,
"creditorBIC": null,
"virtualIbanId": null,
"virtualIbanReference": null,
"additionalData": {
"cheque": {
"cmc7": {
"a": "0557016",
"b": "045010041908",
"c": "001071920333"
},
"drawerData": {
"firstName": "M. ALEX OAK",
"isNaturalPerson": true
},
"RLMCKey": "62"
}
},
"totalRows": 1,
"paymentHtml": null
}
]
},
"webhook_id": "669911f2-3177-4655-93d4-6eaad0xx4727",
"object_payload_signature": "OSet8MKvrd8xVG6turNr3ZWHbH+T0IUPmEh8pNxxxT4="
}
```
---
---
url: /guide/cheques/cashing.md
description: >-
Learn how to cash-in checks to credit Treezor Wallets. Includes required
parameters, request structure, and response examples, as well as the Check
object life cycle.
---
# Cashing
Cashing checks implies a digital and a physical process.
1. [Payin creation](#creation) – You create a `Payin` object, with information about the Check
2. [Check mail in](#mail-in) – You send the physical check to Treezor via mail (within 14 days)
The funds are credited to the wallet when the physical check is received and approved.
When a check is physically processed, [`payin.update`](/guide/cheques/events) webhooks are sent informing you of the changes.
**Information – Checks must:**
* Be sent via mail, as no physical agencies are available
* Be received within 14 calendar days of the Payin creation (otherwise, the [Payin status](introduction#status-payinstatus) is set to `151134`)
* Bear the following information: Name, Account Number, Date, Signature
## Creation
### Parameters
| Attribute | Type | Description |
| --- | --- | --- |
| `paymentMethodId` | integer | Must be `26` for checks. |
| `amount` | number | The amount of the check. |
| `walletId` | string | The unique identifier of the Wallet to credit (recipient). |
| `currency` | string | The currency of the check. |
| `additionalData` | object | Contains the cmc7 line, the drawer data and the RLMC key of the check. |
### Request example
Use the following request to create a Payin object for your check:
```bash [CURL]
curl -X POST '{baseUrl}/payins' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"walletId": "123456",
"paymentMethodId": 26,
"amount": 991.25,
"currency": "EUR",
"additionalData":
{
"cheque": {
"cmc7" : {
"a": "000036", // required, 1st section of CMC7 line
"b": "0230021566985", // required, 2nd section of CMC7 line
"c": "00700065456" // required, 3rd section of CMC7 line
},
"RLMCKey": "22", // required, RMLC key
"drawerData": { // required object
"isNaturalPerson": true, // required, boolean, true: physical / false: legal entity
"email": "aoak@example.com", // drawer's email
"firstName": "Alex", // drawer's firstname
"lastName": "Oak", // drawer's lastname
"address": "22 Rosewood Lane", // drawer's address
"address2": "App. 12", // drawer's address continued
"zipCode": "75001", // drawer's postcode
"city": "Paris" // drawer's city
}
}
}
}
```
Returns the Payin object if successful.
```json [JSON] {8,9,21}
{
"payins": [
{
"payinId": "cf7544f4-15ef-44df-9e6b-ac50ef5xxxx",
"payinTag": null,
"walletId": "123456",
"userId": "852741",
"payinStatus": "PENDING",
"paymentMethodId": "26",
"messageToUser": "",
"subtotalItems": "100.00",
"subtotalServices": "0.00",
"subtotalTax": "0.00",
"amount": "100.00",
"currency": "EUR",
"createdDate": "2018-01-01 17:00:00",
"walletEventName": "Wallet Test",
"walletAlias": "test-wallet-abcd",
"userFirstname": "CMA",
"userLastname": "",
"codeStatus": "160001",
"informationStatus": "",
"refundAmount": null,
"ibanFullname": "",
"DbtrIBAN": "",
"ibanBic": "",
"ibanTxEndToEndId": "XXXXXXXXX",
"ibanTxId": "180799999990292",
"forwardUrl": null,
"paymentAcceptedUrl": null,
"paymentRefusedUrl": null,
"paymentWaitingUrl": null,
"paymentExceptionUrl": null,
"paymentCanceledUrl": null,
"payinDate": null,
"mandateId": null,
"creditorName": "ALEX OAK",
"creditorAddressLine": null,
"creditorCountry": null,
"creditorIban": "FR761679999999999XX9011835",
"creditorBIC": "TRZOFR21XXX",
"virtualIbanId": null,
"virtualIbanReference": null,
"ibanId": "995d69d1839999999999a6935979ea8110d8"
}
]
}
```
## Mail in
Once the Payin is created, the Check can mailed to the address indicated below. Checks must be received within **14 days** after the Payin Creation.
CENTRE DE TRAITEMENT
TSA 80007
33625 BORDEAUX CEDEX 9
## Cancellation
You can cancel the check cashing as long as the physical check has not yet been received by the treatment center, specifically when the Payin has one of the following status codes:
* `160001` – Waiting for treatment center acknowledgement
* `160003` – Waiting for check mail-in
Once the check progresses beyond status `160003`, it cannot be canceled as it has entered the interbank processing system.
You can use the following request to cancel a check cashing.
Endpoint: [`/v1/payins/{payinId}`](/api-reference/api-endpoints.html#tag/Payins/deletePayin){target="\_self"}
```bash [CURL]
curl -X DELETE '{baseUrl}/payins/{payinId}' \
--header 'Authorization: Bearer {accessToken}'
```
**Tip – You can re-represent a check from a canceled payin**
A check with a given CMC7 can only have one active payin at a time; if the previous payin is canceled, then the check can still be cashed-in with a new payin.
## Life cycle
Checks cash-in may have different outcomes, whether they are accepted or not. If the check bounces within the 11-day delay, the Payin is canceled. Otherwise, a Payin refund is created.
Here is an illustration of the check life cyle:
### Examples
Find below Check life cycle examples.
#### Accepted check
| Step | | [Status](/guide/cheques/introduction#status-payinstatus) | [Code](/guide/cheques/introduction#status-payinstatus) | Description |
|- |-: |- |- |- |
| #1 | | **PENDING** | `160001` | Waiting for treatment center akwnoldgement |
| #2 | | **PENDING** | `160003` | Waiting for check mail-in |
| #3 | | **PENDING** | `151132` | Check has been received |
| #4 | | **PENDING** | `151129` | Check has been submitted to the bank |
| #5 | | **PENDING** | `151130` | Check is awaiting validation |
| #6 | | **VALIDATED** | `140005` | **Payment validated** |
#### Error during handling
| Step | | [Status](/guide/cheques/introduction#status-payinstatus) | [Code](/guide/cheques/introduction#status-payinstatus) | Description |
|- | -: |- |- |- |
| #1 | | **PENDING** | `160001` | Waiting for treatment center akwnoldgement |
| #2 | | **PENDING** | `160003` | Waiting for check mail-in |
| #3 | | **PENDING** | `151132` | Check has been received |
| #4 | | **CANCELED** | `151125` | Payin has been canceled due to an **issue with the check** |
---
---
url: /guide/transfers/beneficiaries.md
description: >-
Technical guide for creating, verifying (VoP), and managing beneficiaries,
which are accounts outside your Treezor environment. Includes required
parameters, request structure, and response examples.
---
# Beneficiaries
Beneficiaries are bank accounts that are outside your Treezor ecosystem (as opposed to [Wallets](/guide/dashboard/wallets#wallets)). They are therefore the target of payouts (SEPA Direct Debit, SEPA Credit Transfers, and International Transfers), and are necessarily attached to a User.
## SEPA Beneficiaries
**Information – Treezor is connected to the SEPA STEP2 transfer network**
This network is used by all European banks, and a few other outside of Europe. To transfer funds in and out, both parties must be in the same network.
When making a payout (outgoing funds), Beneficiaries are created:
* **Manually** prior to emitting a [SEPA Credit Transfer](/guide/transfers/credit-transfer#emitted-credit-transfers-scte) ([`usableForSct`](#key-attributes) set to **`true`**).
* **Automatically** when paying with a [SEPA Direct Debit](/guide/transfers/direct-debit#received-direct-debits-sddr) ([`usableForSct`](#key-attributes) set to **`false`**).
**Note – Beneficiaries must be created beforehand for B2B SDDR**
The Beneficiary `sddB2bWhitelist.uniqueMandateReference` field must be populated once the User receives their UMR from their creditor. If not, the SDDR will be [declined upon reception](/guide/transfers/direct-debit#rejection-of-an-sddr).
A Beneficiary can only be associated to a single user at a time. If multiple Users need to send/receive funds to/from the same Beneficiary, it can either be duplicated or [associated with a parent user](/guide/users/parent-children).
### Beneficiary object
```json [JSON]
{
"tag": "string",
"userId": 0,
"nickName": "string",
"name": "string",
"address": "string",
"iban": "string",
"bic": "string",
"sepaCreditorIdentifier": "string",
"sddB2bWhitelist": [
{
"uniqueMandateReference": "nn888890886DGFIP2020045229KFDZBOAB",
"isRecurrent": true,
"walletId": 0
}
],
"sddCoreBlacklist": [
"string"
],
"usableForSct": false,
"sddCoreKnownUniqueMandateReference": [
"string"
],
"isActive": true,
"createdDate": "string",
"modifiedDate": "string"
}
```
### Key attributes
Below are some of the most important Beneficiary attributes.
| Attribute | Type | Description |
|--- |--- |--- |
| `nickName` | string | Field that you are free to populate to identify the Beneficiary. |
| `iban` | string | The IBAN of the Beneficiary. |
| `bic` | string | The [BIC](/guide/overview/glossary#bank-identifier-code-bic) of the Beneficiary. |
| `name` | string | The name of the Beneficiary *(see charset restrictions below)*. |
| `sepaCreditorIdentifier` | string | The [SCI](/guide/overview/glossary#sepa-creditor-identifier-sci). |
| `uniqueMandateReference` | string | The [UMR](/guide/overview/glossary#unique-mandate-reference-umr). |
| `sddCoreBlacklist` | array | List of [UMR](/guide/overview/glossary#unique-mandate-reference-umr) that are revoked. **Core scheme only**. |
| `sddCoreKnownUniqueMandateReference` | array | List of all [UMR](/guide/overview/glossary#unique-mandate-reference-umr) that have debited the User |
| `sddB2bWhitelist.uniqueMandateReference` | array | List of [UMR](/guide/overview/glossary#unique-mandate-reference-umr) that are allowed to debit the Wallet. **B2B scheme only**. |
| `sddB2bWhitelist.isRecurrent` | boolean | `true` – Allows **multiple** debits for this Beneficiary`false` – Allows a **single** debit for this Beneficiary |
| `sddB2bWhitelist.walletId` | integer | Defines which Wallet can be debited by the Beneficiary. |
| `isActive` | boolean | Toggle the Beneficiary (for both SDDR and SCTE): `true` – Enables the Beneficiary`false` – Disables the Beneficiary |
| `usableForSct` | boolean | Defines if this Beneficiary can be used to send [SCTE](/guide/transfers/credit-transfer#emitted-credit-transfers-scte) |
**Information – Rules for the `name` attribute**
* Must be **at least 1-character long**, but not a single space character.
* Can only contain the following characters: `a-z`, `A-Z`, `0-9`, `/`, `-`, `?`, `:`, `(`, `)`, `.`, `,`, `'`, `+` and ` ` (space).
#### Accepted countries
SEPA Transfers are only supported for beneficiaries domiciled in one of the SEPA Scheme countries. If the Beneficiary `bic` or `iban` country code is not a SEPA Scheme country, an HTTP error will be returned.
**Reading – EPC list of Countries in the SEPA Scheme**
You may find the list of accepted BIC and IBAN countries (and the corresponding country codes) in the [EPC list of Countries
in the SEPA Schemes](https://www.europeanpaymentscouncil.eu/sites/default/files/kb/file/2023-01/EPC409-09%20EPC%20List%20of%20SEPA%20Scheme%20Countries%20v4.0_0.pdf) document.
### Creation
| Attribute | Type | Description |
|--- |--- |--- |
| `userId` | string | The unique identifier of the User to which the Beneficiary is attached. |
| `name` | string | The name of the Beneficiary *(see charset restrictions below)*. |
| `iban` | string | The IBAN of the Beneficiary. |
| `bic` | string | The [BIC](/guide/overview/glossary#bank-identifier-code-bic) of the Beneficiary. |
**Information – Rules for the `name` attribute**
* Must be **at least 1-character long**, but not a single space character.
* Can only contain the following characters: `a-z`, `A-Z`, `0-9`, `/`, `-`, `?`, `:`, `(`, `)`, `.`, `,`, `'`, `+` and ` ` (space).
#### Request example
[`/v1/beneficiaries`](/api-reference/api-endpoints.html#tag/Beneficiaries/postBeneficiary){target="\_self"}
```bash [CURL]
curl -X POST '{baseUrl}/v1/beneficiaries' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"userId": 123456,
"name": "Alex Oak",
"tag": "aoak-1982",
"nickName": "A Oak checking",
"address": "Woods Bank",
"iban": "FR7616798000010000012345678",
"bic": "TRZOFR21XXX",
"usableForSct": true
}
```
**Tip – Make sure you use a real IBAN**
If the provided IBAN is incorrect, an error is returned and the Beneficiary is not created.
Returns a Beneficiary object, with its `beneficiaryId` (11XXXX8). It can be used to initiate an [outgoing transfer (SCTE)](/guide/transfers/credit-transfer#emitted-credit-transfers-scte) right away.
```json [JSON]
{
"id": 11XXXX8,
"tag": "aoak-1982",
"userId": 22XXXX6,
"nickName": "A Oak checking",
"name": "STE A",
"address": "Woods Bank",
"iban": "2XXXXXXXX X X 7XXXXXXXXX5 X X 75XXXXXXXX6 X X 1XXXXX4",
"bic": "BNPAFRPP",
"sepaCreditorIdentifier": "",
"sddB2bWhitelist": [],
"sddCoreBlacklist": [],
"usableForSct": true,
"sddCoreKnownUniqueMandateReference": [],
"isActive": true
}
```
Treezor also sends a [`beneficiary.create`](events#beneficiary-create) webhook.
**Tip – Useful information about the returned object**
* `usableForSct` indicates if the beneficiary can be used to [initiate outgoing transfers](/guide/transfers/introduction) (`SCTE`).
* `iban` is returned in an encoded format and cannot be read directly.
## Beneficiary validation (VoP)
The [Verification of Payee (VoP)](/guide/overview/glossary#verification-of-payee-vop) is a legal obligation for the initiator of a SEPA transfer to verify that the beneficiary’s name and IBAN match the information registered at their bank.
The beneficiary validation endpoint allows you to initiate a Verification of Payee request and must be used prior to any:
* [SEPA Credit Transfer](./credit-transfer#emitted-credit-transfers-scte)
* [SEPA Instant Credit Transfer](./credit-transfer-inst#emitted-instant-credit-transfers-scte-inst)
A given `beneficiaryValidationId` can only be used once and expires 72 hours after the validation request.
Therefore, you must request a new beneficiary validation for each payout, except in specific use cases such as scheduled and mass payouts.
**Information – Verification of Payee exemptions**
Some payouts are exempted of VoP. Contact Treezor to find out if your model is eligible and how to implement the exemption.
### Verification of Payee process
When a payout falls under the Verification of Payee obligation, you must expose to your user the result of the verification with [mandatory messages](#validation-result-result) before they decide whether they want to proceed with the payout.
```mermaid
sequenceDiagram
autonumber
participant user as End user
participant you as You
participant trz as Treezor
rect Prerequisite
note over user,trz: Prerequisite
user->>you: Needs to register an external account
you->>trz: POST /v1/beneficiaries
trz-->>you: Returns Beneficiary object
end
user->>you: Wants to make a payout (SCT)
you->>trz: POST /v1/beneficiaries/validation
trz-->>you: Returns validation response
you-->>user: Display response with mandatory messages
user->>you: Agrees to proceed with the transaction
you->>trz: POST /v1/payouts with beneficiaryValidationId
```
### Key attributes
| Attribute | Type | Description |
| --- | --- | --- |
| `beneficiaryName` | string | The complete name of the beneficiary the end user wants to reach, as defined in the Beneficiary object. This `beneficiaryName` will be compared to the name of the account holder as registered with the responding bank. |
| `beneficiaryIBAN` | string | The IBAN of the beneficiary. |
| `recurrenceType` | string | If you've put in place your own system to schedule payments at a later date (one-time or recurring), you must set the recurrence type to `scheduled`. |
**API – API Reference available**
For a complete list of Beneficiary Validation attributes, check the [Beneficiaries](/api-reference/api-endpoints.html#tag/Beneficiaries){target="\_self"} section of the API Reference.
Below is some key information returned in the `vop` object.
#### Validation result (`result`)
| Value | Result description | Mandatory message to display to the end user |
|:---:|---| --- |
| `CMTC` | **Close Match** The beneficiary details are similar to the information provided by the end user, but there are some minor discrepancies. | *”The name of the beneficiary associated with this IBAN partially matches the name you provided. The IBAN is registered under the name: `{matchedName}`. If you validate your transfer, it could be credited to the account of another beneficiary. In this case, TREEZOR, our partner payment service provider, cannot be held responsible.”* |
| `MTCH` | **Match** The beneficiary details provided by the responding bank align with the details the information provided by the end user. | *“The name of the beneficiary associated with this IBAN fully matches the name you provided.”* |
| `NMTC` | **No Match** There is a discrepancy between the beneficiary details and the information provided by the end user. | *“The name of the beneficiary associated with this IBAN is different from the name you provided. If you validate your transfer, it could be credited to the account of another beneficiary. In this case, TREEZOR, our partner payment service provider, cannot be held responsible.”* |
| `NOAP` | **Verification Not Possible** The verification of payee couldn't occur. The reason is specified in the [`reasonCode`](#reason-codes-reasoncode) field. | *“The name of the beneficiary associated with this IBAN could not be verified.If you validate your transfer, it could be credited to the account of another beneficiary.”* |
| `NOAP` | **Verification Unavailable** The verification of payee couldn't occur due to a technical error (`reasonCode`: `9009`). | *“The beneficiary name match check is unavailable. If you validate your transfer, it could be credited to the account of another beneficiary.”* |
**Tip – Mock values available in Sandbox**
You can emulate different results using the payloads available in the [Beneficiary validation result](./faking-operations#beneficiary-validation-result) article.
#### Reason codes (`reasonCode`)
| Value | Description |
| :---: | --- |
| `9001` | The bank or payment service provider is not reachable. |
| `9007` | The account does not exist. |
| `9008` | The account is closed. |
| `9009` | Technical error. |
| `9010` | Other reason. |
### Request example
Endpoint: [`/v1/beneficiaries/validation`](/api-reference/api-endpoints.html#tag/Beneficiaries/postBeneficiaryVerification){target="\_self"}
```bash [CURL]
curl -X POST '{baseUrl}/v1/beneficiaries/validation' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is a `{payload}` example:
```json [JSON]
{
"beneficiaryName": "Alex Oak",
"beneficiaryIBAN": "DE15801640509362882000"
}
```
Returns the following beneficiary validation object if successful.
```json [JSON]
{
"beneficiaryValidationId": "f8e4a7b2-c1d3-4e5a-8b0f-9c2d1e0a3b5c",
"createdDate": "2025-08-29T16:52:27.379Z",
"vop": {
"result": "CMTC",
"matchedName": "Axel Oak",
"reasonCode": "",
"recurrenceType": "default"
}
}
```
The `beneficiaryValidationId` is to be included in the [`/v1/payouts`](/api-reference/api-endpoints.html#tag/Payouts/postPayout){target="\_self"} request within 72 hours after the validation request.
**Tip – Mock values available in Sandbox**
You can emulate different results using the payloads available in the [Beneficiary validation result](./faking-operations#beneficiary-validation-result) article.
### Received Verification of Payee
In the same way that you must verify the beneficiary of an SCT payout, any bank sending funds to a Treezor Wallet through SEPA Credit Transfer must comply with the [Verification of Payee (VoP)](/guide/overview/glossary#verification-of-payee-vop).
However, Treezor doesn't manage nor host the matching mechanism. When receiving a VoP query for a given IBAN, Treezor returns the account information to its RVM (Routing and/or Verification Mechanism).
If the wallet and user both exist, Treezor checks the user [KYC Validation](/guide/user-verification/introduction) status in order to only share information for users whose:
* `kycLevel` is `REGULAR` or `STRONG`
* `kycReview` is `VALIDATED`
In that case, Treezor sends to the RVM the wallet owner's:
* `firstname` and `lastname` ([Physical Users](/guide/users/physical))
* `legalName` ([Legal Entities](/guide/users/legal-entity) and [Self-employed Users](/guide/users/physical#self-employed-users))
## Endpoints
### SEPA Beneficiaries
| Endpoint | [Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/v1/beneficiaries`](/api-reference/api-endpoints.html#tag/Beneficiaries/postBeneficiary){target="\_self"} Create a Beneficiary | `read_write` |
| [`/v1/beneficiaries`](/api-reference/api-endpoints.html#tag/Beneficiaries/getBeneficiaries){target="\_self"} Search for Beneficiaries | `read_only` |
| [`/v1/beneficiaries/{beneficiaryId}`](/api-reference/api-endpoints.html#tag/Beneficiaries/getBeneficiary){target="\_self"} Retrieve a Beneficiary | `read_only` |
| [`/v1/beneficiaries/{beneficiaryId}`](/api-reference/api-endpoints.html#tag/Beneficiaries/putBeneficiary){target="\_self"} Update a Beneficiary | `read_write` |
### Beneficiary validation
| Endpoint | [Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/v1/beneficiaries/validation`](/api-reference/api-endpoints.html#tag/Beneficiaries/postBeneficiaryVerification){target="\_self"} Request Beneficiary Validation | `read_write` |
| [`/v1/beneficiaries/validation/{beneficiaryValidationId}`](/api-reference/api-endpoints.html#tag/Beneficiaries/getBeneficiaryValidation){target="\_self"} Get Beneficiary Validation | `read_only` |
---
---
url: /guide/cards/creation.md
description: >-
Technical guide for issuing physical and virtual cards, individually or in
bulk. Includes required parameters, request structure, and response examples.
---
# Creation
This page describes the card creation, delivery, and activation processes.
**Note – Cards may be both Virtual and Physical**
If your [Card Program](/guide/cards/introduction#card-program) allows it, the same Card may exist in both [Physical](#physical-card-creation) and [Virtual](#virtual-card-creation) forms. In such cases, cannot determine which form was used for a given transaction.
## Process
### Mandatory creation steps
* **Create** a [Physical](#physical-card-creation) or [Virtual Card](#virtual-card-creation) associated with a Wallet.
* **Register for 3D Secure** using [the dedicated endpoint](#enrolling-a-card-for-3d-secure).
* **Activate** the Card (cards are created in an inactive state; you must [activate them](#activation)).
### Optional steps
* Define or [change the Card PIN code](/guide/cards/modification#change-pin)
* Modify Card [options](/guide/cards/restrictions-limits#options-permission-groups) or [limits](/guide/cards/restrictions-limits#payment-withdrawal-limits) (payment limits, NFC activation, online payment, etc.)
* Update Card [restrictions](/guide/cards/restrictions-limits#mcc-restrictions)
* [Lock or unlock the Card](/guide/cards/modification#block-a-card)
* [Convert a Virtual Card to a Physical one](#converting-to-physical)
Treezor encourages you to set all limits, options, and PIN code during the card creation to avoid additional steps.
**Tip – To create cards for a company's employees:**
Set the employee's ([Physical User](/guide/users/physical)) `parentUserId` attribute with the `userId` of the company ([Legal Entity](/guide/users/legal-entity)). The Card can be shipped to the company's address by setting `sendToParent` value to `true`. If so, the envelope bears the child's complete name and the parent's address.
### Card life cycle
Cards come with an `expiryDate`, indicating when the card expires and when it should be [renewed](./renewal). Treezor sends webhooks to better handle this situation:
* [`card.expiryAlert`](/guide/cards/events#card-expiryalert) – Indicates the card expires at the end of next month.
* [`card.update`](/guide/cards/events#card-update) with `EXPIRED` status – Indicates the card expired.
**Information – Expiry alert and renewal are uncorrelated**
Please note there is no correlation between the [`card.expiryAlert`](/guide/cards/events#card-expiryalert) webhook and the renewal process.
## Virtual Card creation
A Virtual Card is a card (with a [PAN](/guide/overview/glossary#primary-account-number-pan), [CVC](/guide/overview/glossary#card-verification-code-cvc), and expiration date) that does not exist in a physical form. **It is made available to the end user as an image** (that looks like a Card).
It can be used for online payments.
### Parameters
Here are some of the most important parameters to define when creating a Virtual Card.
| Attribute | Type | Description |
| --- | --- | --- |
| `userId` | integer | The unique identifier of the [cardholder](/guide/users/introduction). |
| `walletId` | integer | The unique identifier of the [Wallet](/guide/wallets/introduction) associated with the card. |
| `permsGroup` | string | A code for a [preset of permissions](/guide/cards/restrictions-limits#options-permission-groups). It indicates whether the card main options (contactless, online payments, withdrawals, and international payments) are activated. |
| `cardPrint` | string | The [Card Program](introduction#card-program) to associate to the Card and the options provided with it. This information is shared with you by Treezor. |
| `merchantRestrictionGroupId` | integer | The unique identifier of your MID restriction group if you’ve created one in the [previous step](#merchant-id-restrictions). |
| `mccRestrictionGroupId` | integer | The unique identifier of your MCC restriction group if you’ve created one in the [previous step](#merchant-category-restrictions). |
| `countryRestrictionGroupId` | integer | The unique identifier of your Country restriction group if you’ve created one in the [previous step](#country-restrictions). |
| `designCode` | string | [Customization code](#designs-designcode) for the card design. If missing, falls back to the default Design Code. |
| `cardTag` | string | Custom information for you to use as you see fit. See the [Object tags](/guide/api-basics/objects-tags) article. |
Ensure you fill in all the limits below by setting:
* All values you don't need to `0` to deactivate them
* At least one ATM daily, weekly, or monthly limit to another value than `0`
* At least one Payment daily, weekly, or monthly limit to another value than `0`
**Information – Limits can't be expressed in cents**
Limits only accept integer values, which means you can't have limits with decimals (except for `paymentDailyLimit`).
| Attribute | Type | Description |
| --- | --- | --- |
| `limitPaymentAll` | integer | Lifetime payment limit |
| `limitPaymentYear` | integer | Yearly payment limit |
| `limitPaymentMonth` | integer | Monthly payment limit |
| `limitPaymentWeek` | integer | Weekly payment limit |
| `limitPaymentDay` | integer | Daily payment limit |
| `paymentDailyLimit` | number | Daily payment limit (for food vouchers use cases) |
| `limitAtmAll` | integer | Lifetime withdrawal limit |
| `limitAtmYear` | integer | Yearly withdrawal limit |
| `limitAtmMonth` | integer | Monthly withdrawal limit |
| `limitAtmWeek` | integer | Weekly withdrawal limit |
| `limitAtmDay` | integer | Daily withdrawal limit |
**API – API Reference available**
For a complete list of Card attributes, check the [Cards](/api-reference/api-endpoints.html#tag/Cards){target="\_self"} section of the API Reference.
### Request example
Endpoint: [`/v1/cards/CreateVirtual`](/api-reference/api-endpoints.html#tag/Cards/postCardVirtual){target="\_self"}
Here is an example of `{payload}`:
```json [JSON]
{
"cardPrint": "{cardPrint}",
"userId": 8290083,
"walletId": 2464676,
"permsGroup": "TRZ-CU-011",
"mccRestrictionGroupId": 95447,
"merchantRestrictionGroupId": 45599,
"countryRestrictionGroupId": 165327,
"limitPaymentDaily":{limitPaymentDaily},
"limitAtmDaily":{limitAtmDaily}
}
```
Returns the Card object, with its `cardId` (present in all [CardTransactions](transactions)).
```json [JSON] {4}
{
"cards": [
{
"cardId": 241709,
"userId": 8290083,
"walletId": 2464676,
"walletCardtransactionId": 2473310,
"mccRestrictionGroupId": 95447,
"merchantRestrictionGroupId": 45599,
"countryRestrictionGroupId": 165327,
"publicToken": "107277882",
"cardTag": "",
"statusCode": "UNLOCK",
"isLive": 0,
"pinTryExceeds": 0,
"maskedPan": "519872******4839",
"embossedName": "ALEX OAK",
"expiryDate": "2026-10-31",
"CVV": "000", // Retrieve the CVV with cardImage or PCI DSS
"startDate": "2023-10-23",
"endDate": "0000-00-00",
"countryCode": "FR",
"currencyCode": "EUR",
"lang": null,
"deliveryTitle": "M",
"deliveryLastname": "OAK",
"deliveryFirstname": "ALEX",
"deliveryAddress1": "15 EDGEWOOD ROAD",
"deliveryAddress2": "",
"deliveryAddress3": "",
"deliveryCity": "ROSEWOOD",
"deliveryPostcode": "12365",
"deliveryCountry": "FR",
"mobileSent": "+33633333333",
"limitsGroup": "TRZ-VL-001",
"permsGroup": "TRZ-CU-011",
"cardDesign": "13664",
"virtualConverted": 0,
"physical": 0,
"optionAtm": 0,
"optionForeign": 0,
"optionOnline": 1,
"optionNfc": 1,
"limitAtmYear": 0,
"limitAtmMonth": 0,
"limitAtmWeek": 0,
"limitAtmDay": 1,
"limitAtmAll": 1,
"limitPaymentYear": 0,
"limitPaymentMonth": 0,
"limitPaymentWeek": 0,
"limitPaymentDay": 25,
"limitPaymentAll": 25,
"paymentDailyLimit": 0.0,
"totalAtmYear": null,
"totalAtmMonth": null,
"totalAtmWeek": null,
"totalAtmDay": null,
"totalAtmAll": null,
"totalPaymentYear": null,
"totalPaymentMonth": null,
"totalPaymentWeek": null,
"totalPaymentDay": null,
"totalPaymentAll": null,
"createdBy": 945198,
"createdDate": "2023-10-31 10:37:04",
"modifiedBy": 0,
"modifiedDate": "0000-00-00 00:00:00",
"renewalType": "A",
"renewalDate": null,
"originalCardId": null,
"totalRows": null,
"designCode": null,
"cardLanguages": "",
"eventName": "Master Wallet",
"eventAlias": "master-wallet-6537b83040735",
"restrictionGroupLimits": null,
"cancellationNumber": "",
"metadata": null,
"renewalDate": null,
"renewalType": null,
"originalCardId": null,
"logoId": "",
"logoBackId": "",
"packageId": "",
"customizeInfo": "",
"letterCustomizedInfo": "",
"freeCustomizedInfo": "",
"deliveryMethod": null,
"pinMailer": null,
"batchDeliveryId": null,
"sendToParent": 0,
"isTemporary": false
}
]
}
```
Endpoint: [`/cards`](/api-reference/pci-dss-dev.html#tag/Cards/createCard){target="\_self"}
Here is an example of `{payload}`:
```json [JSON]
{
"cardPrint": "{cardPrint}",
"userId": 8290083,
"medium": "virtual",
"walletId": 2464676,
"permsGroup": "TRZ-CU-011",
"mccRestrictionGroupId": 95447,
"merchantRestrictionGroupId": 45599,
"countryRestrictionGroupId": 165327,
"limitPaymentDaily":{limitPaymentDaily},
"limitAtmDaily":{limitAtmDaily},
"sca": "eyJh_UxfQ.nNIH_n9kA"
}
```
Returns the Card object, with its `cardId` (present in all [CardTransactions](transactions)).
```json [JSON] {4}
{
"cards": [
{
"cardId": 241709,
"userId": 8290083,
"walletId": 2464676,
"walletCardtransactionId": 2473310,
"mccRestrictionGroupId": 95447,
"merchantRestrictionGroupId": 45599,
"countryRestrictionGroupId": 165327,
"publicToken": "107277882",
"cardTag": "",
"statusCode": "UNLOCK",
"isLive": 0,
"pinTryExceeds": 0,
"maskedPan": "519872******4839",
"embossedName": "ALEX OAK",
"expiryDate": "2026-10-31",
"CVV": "000", // Retrieve the CVV with cardImage or PCI DSS
"startDate": "2023-10-23",
"endDate": "0000-00-00",
"countryCode": "FR",
"currencyCode": "EUR",
"lang": null,
"deliveryTitle": "M",
"deliveryLastname": "OAK",
"deliveryFirstname": "ALEX",
"deliveryAddress1": "15 EDGEWOOD ROAD",
"deliveryAddress2": "",
"deliveryAddress3": "",
"deliveryCity": "ROSEWOOD",
"deliveryPostcode": "12365",
"deliveryCountry": "FR",
"mobileSent": "+33633333333",
"limitsGroup": "TRZ-VL-001",
"permsGroup": "TRZ-CU-011",
"cardDesign": "13664",
"virtualConverted": 0,
"physical": 0,
"optionAtm": 0,
"optionForeign": 0,
"optionOnline": 1,
"optionNfc": 1,
"limitAtmYear": 0,
"limitAtmMonth": 0,
"limitAtmWeek": 0,
"limitAtmDay": 1,
"limitAtmAll": 1,
"limitPaymentYear": 0,
"limitPaymentMonth": 0,
"limitPaymentWeek": 0,
"limitPaymentDay": 25,
"limitPaymentAll": 25,
"paymentDailyLimit": 0.0,
"totalAtmYear": null,
"totalAtmMonth": null,
"totalAtmWeek": null,
"totalAtmDay": null,
"totalAtmAll": null,
"totalPaymentYear": null,
"totalPaymentMonth": null,
"totalPaymentWeek": null,
"totalPaymentDay": null,
"totalPaymentAll": null,
"createdBy": 945198,
"createdDate": "2023-10-31 10:37:04",
"modifiedBy": 0,
"modifiedDate": "0000-00-00 00:00:00",
"renewalType": "A",
"renewalDate": null,
"originalCardId": null,
"totalRows": null,
"designCode": null,
"cardLanguages": "",
"eventName": "Master Wallet",
"eventAlias": "master-wallet-6537b83040735",
"restrictionGroupLimits": null,
"cancellationNumber": "",
"metadata": null,
"renewalDate": null,
"renewalType": null,
"originalCardId": null,
"logoId": "",
"logoBackId": "",
"packageId": "",
"customizeInfo": "",
"letterCustomizedInfo": "",
"freeCustomizedInfo": "",
"deliveryMethod": null,
"pinMailer": null,
"batchDeliveryId": null,
"sendToParent": 0,
"isTemporary": false
}
]
}
```
Note that if your card program allows for virtual card conversion, you must use the [convert virtual card to physical](#converting-to-physical) endpoint, which is not PCI DSS-specific.
Treezor also sends a [`card.createvirtual`](./events#cardcreatevirtual) webhook.
### Retrieving a Virtual Card image
The created virtual cards are available as an image (base64 encoded format). You can retrieve a card and expose it to your users.
Endpoint: [`/v1/cardimages`](/api-reference/api-endpoints.html#tag/Cards/getCardImage){target="\_self"}
```bash [CURL]
curl -X GET '{baseUrl}/v1/cardimages?cardId={cardId}' \
--header 'Authorization: Bearer {accessToken}'
```
It returns the Card Image object if successful:
```json [JSON]
{
"cardimages": [
{
"id": "155341",
"cardId": "239391",
"file": "/xj/base64encodedfile"
}
]
}
```
Endpoint: [`/cards/{cardId}/cardImage`](/api-reference/pci-dss-dev.html#tag/Cards/getCardImage){target="\_self"}
```bash [CURL]
curl -X GET '{pciBaseUrl}/cards/{cardId}/cardImage' \
--header 'Authorization: Bearer {accessToken}'
```
It returns the Card Image object if successful:
```json [JSON]
{
"encryptedCardImage": "…"
}
```
Please refer to the [Displaying sensitive data](./sensitive-data) article for more information regarding the exposition of the card image.
**Security – Sensitive data storage is forbidden**
You are prohibited from storing card images on your servers (except if you are PCI DSS certified).
### Converting to physical
Converting a card consists of turning a virtual card into a physical one. The availability of this option depends on your Card Program. When doing so, all the card information, settings, and options remain unchanged.
**Information – Conversion requires a delivery address for the Physical Card**
If the [User](/guide/users/introduction) doesn't already have an address defined, you have to update it beforehand.
```bash [CURL]
curl -X PUT '{baseUrl}/v1/cards/{cardId}/ConvertVirtual' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json'
```
Returns the Card object, with a `virtualConverted` attribute set to `1`.
```json{38}
{
"cards": [
{
"cardId": 999894952,
"userId": 100198207,
"walletId": 2728965,
"walletCardtransactionId": 2905467,
"mccRestrictionGroupId": 0,
"merchantRestrictionGroupId": 0,
"countryRestrictionGroupId": 0,
"publicToken": "105608965",
"cardTag": "Event-test-card",
"statusCode": "UNLOCK",
"isLive": 0,
"pinTryExceeds": 0,
"maskedPan": "548821******4661",
"embossedName": "SPRINTREVIEW GRANDMA",
"expiryDate": "2027-05-31",
"CVV": "624",
"startDate": "2024-05-24",
"endDate": "0000-00-00",
"countryCode": "FR",
"currencyCode": "EUR",
"lang": null,
"deliveryTitle": "M",
"deliveryLastname": "GRANDMA",
"deliveryFirstname": "SPRINTREVIEW",
"deliveryAddress1": "12 RUE DE LA LIBERTE",
"deliveryAddress2": "",
"deliveryAddress3": "",
"deliveryCity": "PARIS",
"deliveryPostcode": "7501",
"deliveryCountry": "FR",
"mobileSent": "+33687432367",
"limitsGroup": "TRZ-VL-001",
"permsGroup": "TRZ-CU-012",
"cardDesign": "8529",
"virtualConverted": 1,
"physical": 0,
"optionAtm": 0,
"optionForeign": 1,
"optionOnline": 1,
"optionNfc": 1,
"limitAtmYear": 0,
"limitAtmMonth": 0,
"limitAtmWeek": 2000,
"limitAtmDay": 1000,
"limitAtmAll": 0,
"limitPaymentYear": 0,
"limitPaymentMonth": 0,
"limitPaymentWeek": 3000,
"limitPaymentDay": 2000,
"limitPaymentAll": 0,
"paymentDailyLimit": 500.0,
"totalAtmYear": null,
"totalAtmMonth": null,
"totalAtmWeek": null,
"totalAtmDay": null,
"totalAtmAll": null,
"totalPaymentYear": null,
"totalPaymentMonth": null,
"totalPaymentWeek": null,
"totalPaymentDay": null,
"totalPaymentAll": null,
"createdBy": 929252,
"createdDate": "2024-05-14 10:28:07",
"modifiedBy": 929252,
"modifiedDate": "2024-05-14 10:28:20",
"totalRows": null,
"designCode": null,
"cardLanguages": "",
"eventName": "Wallet transfer",
"eventAlias": "wallet-transfer-65eafdf301f56",
"restrictionGroupLimits": null,
"cancellationNumber": "",
"metadata": null,
"renewalDate": null,
"renewalType": null,
"originalCardId": null,
"logoId": "",
"logoBackId": "",
"packageId": "",
"customizeInfo": "",
"letterCustomizedInfo": "",
"freeCustomizedInfo": "",
"deliveryMethod": null,
"pinMailer": null,
"batchDeliveryId": null,
"sendToParent": 0,
"isTemporary": false
}
]
}
```
### Creating Temporary Cards
You can create virtual payment cards with a predefined lifespan and spending limit to strengthen the security of your payments and optimize the management of your cards for temporary needs.
**Configuration – Temporary cards are not activated by default**
You can request access to this feature by contacting your *Treezor Account Manager*.
#### Parameters
Below are some specificities regarding the parameters to use when creating a temporary card.
| Attribute | Type | Description |
| --- | --- | --- |
| `userId` | integer | The unique identifier of the [cardholder](/guide/users/introduction). |
| `walletId` | integer | The unique identifier of the [Wallet](/guide/wallets/introduction) associated with the card. |
| `permsGroup` | string | A code for a [preset of permissions](/guide/cards/restrictions-limits#options-permission-groups). It indicates whether the card main options (contactless, online payments, withdrawals, and international payments) are activated. Since temporary cards can only be virtual, we recommend not using permission groups that include ATM withdrawals. |
| `cardPrint` | string | The [Card Program](introduction#card-program) to associate to the Card and the options provided with it. This information is shared with you by Treezor. |
| `isTemporary` | boolean | Set to `true` in order to create a card with a predefined lifespan and spending limit. |
| `startDate` | string | Define this value for automatic activation of the card (e.g., the first day of the employee travel date). |
| `expiryDate` | string | The date at which the card expires (e.g., the end of the employee travel date). Required if `isTemporary` is set to true. |
In addition, you must define one (and only one) limit among the following: `limitPaymentAll`, `limitPaymentYear`, `limitPaymentMonth`, `limitPaymentWeek`, or `limitPaymentDay`.
**API – API Reference available**
For a complete list of Card attributes, check the [Cards](/api-reference/api-endpoints.html#tag/Cards){target="\_self"} section of the API Reference.
#### Request example
Endpoint: [`/v1/cards/CreateVirtual`](/api-reference/api-endpoints.html#tag/Cards/postCardVirtual){target="\_self"}
Here is an example of `{payload}`:
```json [JSON]
{
"cardPrint": "{cardPrint}",
"userId": 8290083,
"walletId": 2464676,
"permsGroup": "TRZ-CU-014",
"isTemporary": true,
"startDate": "2025-10-23",
"expiryDate": "2025-11-20",
"limitPaymentAll": 1200
}
```
Returns the Card object with the `isTemporary` attribute set to `true`.
```json [JSON] {93}
{
"cards": [
{
"cardId": 241709,
"userId": 8290083,
"walletId": 2464676,
"walletCardtransactionId": 2473310,
"mccRestrictionGroupId": 95447,
"merchantRestrictionGroupId": 45599,
"countryRestrictionGroupId": 165327,
"publicToken": "107277882",
"cardTag": "",
"statusCode": "UNLOCK",
"isLive": 0,
"pinTryExceeds": 0,
"maskedPan": "519872******4839",
"embossedName": "ALEX OAK",
"expiryDate": "2026-10-31",
"CVV": "000", // Retrieve the CVV with cardImage or PCI DSS
"startDate": "2025-10-23",
"endDate": "0000-00-00",
"countryCode": "FR",
"currencyCode": "EUR",
"lang": null,
"deliveryTitle": "M",
"deliveryLastname": "OAK",
"deliveryFirstname": "ALEX",
"deliveryAddress1": "15 EDGEWOOD ROAD",
"deliveryAddress2": "",
"deliveryAddress3": "",
"deliveryCity": "ROSEWOOD",
"deliveryPostcode": "12365",
"deliveryCountry": "FR",
"mobileSent": "+33633333333",
"limitsGroup": "TRZ-VL-001",
"permsGroup": "TRZ-CU-014",
"cardDesign": "13664",
"virtualConverted": 0,
"physical": 0,
"optionAtm": 0,
"optionForeign": 1,
"optionOnline": 1,
"optionNfc": 1,
"limitAtmYear": 0,
"limitAtmMonth": 0,
"limitAtmWeek": 0,
"limitAtmDay": 0,
"limitAtmAll": 1,
"limitPaymentYear": 0,
"limitPaymentMonth": 0,
"limitPaymentWeek": 0,
"limitPaymentDay": 0,
"limitPaymentAll": 1200,
"paymentDailyLimit": 0.0,
"totalAtmYear": null,
"totalAtmMonth": null,
"totalAtmWeek": null,
"totalAtmDay": null,
"totalAtmAll": null,
"totalPaymentYear": null,
"totalPaymentMonth": null,
"totalPaymentWeek": null,
"totalPaymentDay": null,
"totalPaymentAll": null,
"createdBy": 945198,
"createdDate": "2025-09-31 10:37:04",
"modifiedBy": 0,
"modifiedDate": "0000-00-00 00:00:00",
"renewalType": "A",
"renewalDate": null,
"originalCardId": null,
"totalRows": null,
"designCode": null,
"cardLanguages": "",
"eventName": "Master Wallet",
"eventAlias": "master-wallet-6537b83040735",
"restrictionGroupLimits": null,
"cancellationNumber": "",
"metadata": null,
"renewalDate": null,
"renewalType": null,
"originalCardId": null,
"logoId": "",
"logoBackId": "",
"packageId": "",
"customizeInfo": "",
"letterCustomizedInfo": "",
"freeCustomizedInfo": "",
"deliveryMethod": null,
"pinMailer": null,
"batchDeliveryId": null,
"sendToParent": 0,
"isTemporary": true
}
]
}
```
Endpoint: [`/cards`](/api-reference/pci-dss-dev.html#tag/Cards/createCard){target="\_self"}
Here is an example of `{payload}`:
```json [JSON]
{
"cardPrint": "{cardPrint}",
"userId": 8290083,
"walletId": 2464676,
"permsGroup": "TRZ-CU-014",
"isTemporary": true,
"startDate": "2025-10-23",
"expiryDate": "2025-11-20",
"limitPaymentAll": 1200,
"medium": "virtual",
"sca": "eyJh_UxfQ.nNIH_n9kA"
}
```
Returns the Card object with the `isTemporary` attribute set to `true`.
```json [JSON] {93}
{
"cards": [
{
"cardId": 241709,
"userId": 8290083,
"walletId": 2464676,
"walletCardtransactionId": 2473310,
"mccRestrictionGroupId": 95447,
"merchantRestrictionGroupId": 45599,
"countryRestrictionGroupId": 165327,
"publicToken": "107277882",
"cardTag": "",
"statusCode": "UNLOCK",
"isLive": 0,
"pinTryExceeds": 0,
"maskedPan": "519872******4839",
"embossedName": "ALEX OAK",
"expiryDate": "2025-11-20",
"CVV": "000", // Retrieve the CVV with cardImage or PCI DSS
"startDate": "2025-10-23",
"endDate": "0000-00-00",
"countryCode": "FR",
"currencyCode": "EUR",
"lang": null,
"deliveryTitle": "M",
"deliveryLastname": "OAK",
"deliveryFirstname": "ALEX",
"deliveryAddress1": "15 EDGEWOOD ROAD",
"deliveryAddress2": "",
"deliveryAddress3": "",
"deliveryCity": "ROSEWOOD",
"deliveryPostcode": "12365",
"deliveryCountry": "FR",
"mobileSent": "+33633333333",
"limitsGroup": "TRZ-VL-001",
"permsGroup": "TRZ-CU-014",
"cardDesign": "13664",
"virtualConverted": 0,
"physical": 0,
"optionAtm": 0,
"optionForeign": 1,
"optionOnline": 1,
"optionNfc": 1,
"limitAtmYear": 0,
"limitAtmMonth": 0,
"limitAtmWeek": 0,
"limitAtmDay": 1,
"limitAtmAll": 1,
"limitPaymentYear": 0,
"limitPaymentMonth": 0,
"limitPaymentWeek": 0,
"limitPaymentDay": 0,
"limitPaymentAll": 1200,
"paymentDailyLimit": 0.0,
"totalAtmYear": null,
"totalAtmMonth": null,
"totalAtmWeek": null,
"totalAtmDay": null,
"totalAtmAll": null,
"totalPaymentYear": null,
"totalPaymentMonth": null,
"totalPaymentWeek": null,
"totalPaymentDay": null,
"totalPaymentAll": null,
"createdBy": 945198,
"createdDate": "2023-10-31 10:37:04",
"modifiedBy": 0,
"modifiedDate": "0000-00-00 00:00:00",
"renewalType": "A",
"renewalDate": null,
"originalCardId": null,
"totalRows": null,
"designCode": null,
"cardLanguages": "",
"eventName": "Master Wallet",
"eventAlias": "master-wallet-6537b83040735",
"restrictionGroupLimits": null,
"cancellationNumber": "",
"metadata": null,
"renewalDate": null,
"renewalType": null,
"originalCardId": null,
"logoId": "",
"logoBackId": "",
"packageId": "",
"customizeInfo": "",
"letterCustomizedInfo": "",
"freeCustomizedInfo": "",
"deliveryMethod": null,
"pinMailer": null,
"batchDeliveryId": null,
"sendToParent": 0,
"isTemporary": true
}
]
}
```
Treezor also sends a [`card.createvirtual`](./events#cardcreatevirtual) webhook.
**Tip – Single-use cards are also available**
You can create single-use cards by using the [Multi-Criteria Dynamic Card (MDC)](./transactions-rules-engine) rules engine.
## Physical card creation
A Physical Card is a card that is shipped to the cardholder by mail and can, for example, be used in retail shops, gas stations, etc., depending on the [applied restrictions](/guide/cards/modification#applying-a-restriction-list).
If you want to display an image of a Physical Card to the end user, you must first create a Virtual Card and [convert](#converting-to-physical) it to a Physical one. This allows you to show an image of the Virtual Card which bears the same PAN, CVC and expiration date.
**Tip – Physical Cards are mailed to users**
The following [User attributes](/guide/users/introduction#key-attributes) are required to send physical cards: `title`, `firstname`, `lastname`, `address{1-3}`, `city`, `postcode` and `country`.
### Parameters
Here are some of the most important parameters to define when creating a Virtual Card.
| Attribute | Type | Description |
| --- | --- | --- |
| `userId` | integer | The unique identifier of the [cardholder](/guide/users/introduction) |
| `walletId` | integer | The unique identifier of the [Wallet](/guide/wallets/introduction) associated with the card. |
| `permsGroup` | string | A code for a [preset of permissions](/guide/cards/restrictions-limits#options-permission-groups). It indicates whether the card main options (contactless, online payments, withdrawals, and international payments) are activated. |
| `cardPrint` | string | The [Card Program](introduction#card-program) to associate to the Card and the options provided with it. This information is shared with you by Treezor. |
| `anonymous` | integer | Must be set to `1` if the Card is assigned to an [Anonymous User](/guide/users/physical#anonymous-users). |
| `merchantRestrictionGroupId` | integer | The unique identifier of your MID restriction group if you’ve created one in the [previous step](#merchant-id-restrictions). |
| `mccRestrictionGroupId` | integer | The unique identifier of your MCC restriction group if you’ve created one in the [previous step](#merchant-category-restrictions). |
| `countryRestrictionGroupId` | integer | The unique identifier of your Country restriction group if you’ve created one in the [previous step](#country-restrictions). |
| `designCode` | string | [Customization code](#designs-designcode) for the card design. If missing, falls back to the default Design Code. |
| `cardTag` | string | Custom information for you to use as you see fit. See the [Object tags](/guide/api-basics/objects-tags) article. |
| `pin` | string | The Card PIN code. Treezor recommends you set this value when creating the card, but if not, a random value is set by default. |
| `cardLanguages` | string | Specifies a maximum of 4 preferred languages used to communicate with the cardholder on [ATMs](/guide/overview/glossary#automated-teller-machine-atm). Expected as ISO 639-1 (code alpha-2) concatenated by priority (e.g., `nrfrenes` for Dutch 1st, French 2nd, English 3rd, Spanish 4th). |
| `batchDeliveryId` | integer | Allows you to [group Cards shipping together](#batch-delivery-batchdeliveryid) by specifying the same delivery ID to multiple Cards. |
| `logoId` | string | Allows you to [add a logo on the Card](#logo-logoid) by specifying the file's name. |
| `logoBackId` | string | Allows you to [add a logo on the backside of the Card](#back-logo-logobackid) by specifying the file's name. |
| `packageId` | string | Allows you to customize [the Card packaging](./introduction#card-program). |
| `customizedInfo` | string | Allows you to [add text](#customized-info-customizedinfo) on the Card. |
| `freeCustomizedInfo` | string | Allows you to [add more text](#free-customized-info-freecustomizedinfo) on the Card. |
| `letterCustomizedInfo` | string | Allows you to [add text](#customized-info-lettercustomizedinfo) on letter that accompanies the Card. |
| `embossLegalName` | boolean | Allows you to emboss the User's `legalName` on the Card in addition to the cardholder's name, if defined to `true`. |
| `sendToParent` | integer | Allows you to send the Card to the [parent User](/guide/users/parent-children), if set to `1`. |
Ensure you fill in all the limits below by setting:
* All values you don't need to `0` to deactivate them
* At least one ATM daily, weekly, or monthly limit to another value than `0`
* At least one Payment daily, weekly, or monthly limit to another value than `0`
**Information – Limits can't be expressed in cents**
Limits only accept integer values, which means you can't have limits with decimals (except for `paymentDailyLimit`).
| Attribute | Type | Description |
| --- | --- | --- |
| `limitPaymentAll` | integer | Lifetime payment limit |
| `limitPaymentYear` | integer | Yearly payment limit |
| `limitPaymentMonth` | integer | Monthly payment limit |
| `limitPaymentWeek` | integer | Weekly payment limit |
| `limitPaymentDay` | integer | Daily payment limit |
| `paymentDailyLimit` | number | Daily payment limit (for food vouchers use cases) |
| `limitAtmAll` | integer | Lifetime withdrawal limit |
| `limitAtmYear` | integer | Yearly withdrawal limit |
| `limitAtmMonth` | integer | Monthly withdrawal limit |
| `limitAtmWeek` | integer | Weekly withdrawal limit |
| `limitAtmDay` | integer | Daily withdrawal limit |
**Configuration – Some fields are not available by default**
Contact your *Treezor Account Manager* to set the `batchDeliveryId`, `customizedInfo`, `freeCustomizedInfo`, `letterCustomizedInfo`, `logoId`, `logoBackId`, and `packageId`.
### Request
Endpoint: [`/v1/cards/RequestPhysical`](/api-reference/api-endpoints.html#tag/Cards/postCardPhysical){target="\_self"}
```bash [CURL]
curl -X POST '{baseUrl}/v1/cards/RequestPhysical' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"userId": {userId},
"walletId": {walletId},
"permsGroup": "TRZ-CU-016",
"cardPrint": {cardPrint},
"cardTag": "This field can be populated as you see fit",
"limitPaymentDaily": {limitPaymentDaily},
"limitAtmDaily": {limitAtmDaily}
}
```
Returns the Card, with its `cardId` (available in [CardTransactions](transactions)).
For security reasons, cards are created in an inactive state. Once you are sure the end user has received the card, it must be [activated](#activation).
```json [JSON]
{
"cardId": 0,
"userId": 0,
"walletId": 0,
"cardTag": "string",
"statusCode": "UNLOCK",
"isLive": 0,
"pinTryExceeds": 0,
"embossedName": "string",
"expiryDate": "string",
"CVV": "string",
"limitsGroup": "string",
"permsGroup": "string",
"cardDesign": "string",
"virtualConverted": 0,
"optionAtm": 0,
"optionForeign": 0,
"optionOnline": 0,
"optionNfc": 0,
"limitAtmYear": 0,
"limitAtmMonth": 0,
"limitAtmWeek": 0,
"limitAtmDay": 0,
"limitAtmAll": 0,
"limitPaymentYear": 0,
"limitPaymentMonth": 0,
"limitPaymentWeek": 0,
"limitPaymentDay": 0,
"limitPaymentAll": 0,
"paymentDailyLimit": 0,
"restrictionGroupLimits": [
{
"paymentDailyLimit": 0,
"mccRestrictionGroups": 0,
"countryRestrictionGroups": 0,
"merchantIdRestrictionGroups": 0
}
],
"createdBy": 945198,
"createdDate": "2023-10-31 10:37:04",
"modifiedBy": 0,
"modifiedDate": "0000-00-00 00:00:00",
"renewalType": "A",
"renewalDate": null,
"originalCardId": null,
"totalRows": null,
// [...] some attributes are hidden
}
```
Endpoint: [`/cards`](/api-reference/pci-dss-dev.html#tag/Cards/createCard){target="\_self"}
Here is an example of `{payload}`:
```json [JSON]
{
"userId": {userId},
"medium": "physical",
"walletId": {walletId},
"permsGroup": "TRZ-CU-016",
"cardPrint": {cardPrint},
"cardTag": "This field can be populated as you see fit",
"limitPaymentDaily": {limitPaymentDaily},
"limitAtmDaily": {limitAtmDaily},
"sca": "eyJh_UxfQ.nNIH_n9kA"
}
```
Returns the Card, with its `cardId` (available in [CardTransactions](transactions)).
For security reasons, cards are created in an inactive state. Once you are sure the end user has received the card, it must be [activated](#activation).
```json [JSON]
{
"cardId": 0,
"userId": 0,
"walletId": 0,
"cardTag": "string",
"statusCode": "UNLOCK",
"isLive": 0,
"pinTryExceeds": 0,
"embossedName": "string",
"expiryDate": "string",
"CVV": "string",
"limitsGroup": "string",
"permsGroup": "string",
"cardDesign": "string",
"virtualConverted": 0,
"optionAtm": 0,
"optionForeign": 0,
"optionOnline": 0,
"optionNfc": 0,
"limitAtmYear": 0,
"limitAtmMonth": 0,
"limitAtmWeek": 0,
"limitAtmDay": 0,
"limitAtmAll": 0,
"limitPaymentYear": 0,
"limitPaymentMonth": 0,
"limitPaymentWeek": 0,
"limitPaymentDay": 0,
"limitPaymentAll": 0,
"paymentDailyLimit": 0,
"restrictionGroupLimits": [
{
"paymentDailyLimit": 0,
"mccRestrictionGroups": 0,
"countryRestrictionGroups": 0,
"merchantIdRestrictionGroups": 0
}
],
"createdBy": 945198,
"createdDate": "2023-10-31 10:37:04",
"modifiedBy": 0,
"modifiedDate": "0000-00-00 00:00:00",
"renewalType": "A",
"renewalDate": null,
"originalCardId": null,
"totalRows": null,
// [...] some attributes are hidden
}
```
Physical Cards can be identified by the following attributes:
* `physical` = `1` or
* `physical` = `0` along with `virtualConverted` = `1`
Treezor also sends a [`card.requestphysical`](./events#cardrequestphysical) webhook.
### Expedition tracking
Treezor sends a [`card.expeditionTracking`](/guide/cards/events#card-expeditiontracking) webhook when the card manufacturer mails the physical card, allowing you to track the expedition and inform your end users.
Expedition tracking is only available if your manufacturer is Idemia.
## Bulk Creation
Depending on your use case, it may be more suitable for you to create Cards in bulk.
Please note that Bulk Card Creation automatically complies with PCI DSS if you have migrated to the [PCI DSS services](./pci-dss).
**Configuration – Bulk Creation is not enabled by default**
You can request access to this feature by contacting your *Treezor Account Manager*.
### Creation
#### Parameters
| Attribute | Type | Description |
| --- | --- | --- |
| `number` | integer | The number of cards to be created. There may be limitations to the maximum number of cards you can create at once. |
| `medium` | integer | Defines whether the cards are to be Physical (1) or Virtual (1), or Virtual cards that can be converted into Physical ones (3). |
| `userIdOwner` | boolean | The unique identifier of the user owning the cards. Required if `createUserForEach` is set to `false` or undefined. |
| `createUserForEach` | boolean | Whether to automatically create users for each created card. Required if `userIdOwner` is set to `false`. |
| `distributionCountry` | string | The country in which the end user is using your services. Available values may vary depending on your configuration, see [Distribution Country](/guide/users/introduction#distribution-country-distributioncountry) for more information. This field is only required when you operate in multiple countries and if `createUserForEach` is set to `true`. |
| `defaultPermsGroup` | string | A code for a [preset of permissions](/guide/cards/restrictions-limits#options-permission-groups). It indicates whether the card main options (contactless, online payments, withdrawals, and international payments) are activated. |
| `createWalletForEach` | boolean | Defines whether to create one Wallet per card. |
| `walletIdAttach` | integer | The unique identifier of the Wallet the cards are going to be attached to. Required if `createWalletForEach` is set to `false`. |
| `walletTypeId` | integer | The [type of Wallets](/guide/wallets/introduction#types-of-wallets) the cards will be associated to. |
| `cardDeliveryAddress1` | string | The first line of the delivery address for physical cards. Only taken into account when the `createUserForEach` attribute is set to `true`. Otherwise, you must manage the address at the user level. |
| `cardDeliveryPostCode` | string | The postal code of the delivery address. Only taken into account when the `createUserForEach` attribute is set to `true`. Otherwise, you must manage the address at the user level. |
| `cardDeliveryCity` | string | The city of the delivery address. Only taken into account when the `createUserForEach` attribute is set to `true`. Otherwise, you must manage the address at the user level. |
| `cardDeliveryCountry` | string | The [country](/guide/api-basics/data-format#countries) of the delivery address. Only taken into account when the `createUserForEach` attribute is set to `true`. Otherwise, you must manage the address at the user level. |
| `anonymous` | integer | Defines whether the cards are to belong to [Anonymous Users](/guide/users/physical#anonymous-users). If so set the value to `1`, otherwise `0`. |
| `cardPrint` | string | The [Card Program](introduction#card-program) to associate to the Card and the options provided with it. This information is shared with you by Treezor. |
| `logoId` | string | Customizes the cards with a [logo](#logo-logoid). |
| `logoBackId` | string | Customizes the backside of the cards with a [logo](#back-logo-logobackid) by specifying the file's name. |
| `packageId` | string | Customizes the [packaging](#packaging-packageid) of the cards. |
| `customizedInfo` | string | Adds [text](#customized-info-customizedinfo) on the cards. |
| `freeCustomizedInfo` | string | Adds [more text](#additional-customized-info-freecustomizedinfo) on the cards. |
| `letterCustomizedInfo` | string | Adds [text](#customized-info-lettercustomizedinfo) on the letter that comes with the cards. |
| `defaultMccRestrictionGroupId` | integer | The unique identifier of the MCC Restriction Group to associate with the cards. |
| `defaultMerchantRestrictionGroupId` | integer | The unique identifier of the MID Restriction Group to associate with the cards. |
| `defaultCountryRestrictionGroupId` | integer | The unique identifier of the Country Restriction Group to associate with the cards. |
| `batchDeliveryId` | integer | Allows you to [group Cards shipping together](#batch-delivery-batchdeliveryid) by specifying the same delivery ID to multiple Cards. |
Ensure you fill in all the limits below by setting:
* All values you don't need to `0` to deactivate them
* At least one ATM daily, weekly, or monthly limit to another value than `0`
* At least one Payment daily, weekly, or monthly limit to another value than `0`
**Information – Limits can't be expressed in cents**
Limits only accept integer values, which means you can't have limits with decimals (except for `paymentDailyLimit`).
| Attribute | Type | Description |
| --- | --- | --- |
| `limitPaymentAll` | integer | Lifetime payment limit |
| `limitPaymentYear` | integer | Yearly payment limit |
| `limitPaymentMonth` | integer | Monthly payment limit |
| `limitPaymentWeek` | integer | Weekly payment limit |
| `limitPaymentDay` | integer | Daily payment limit |
| `paymentDailyLimit` | number | Daily payment limit (for food vouchers use cases) |
| `limitAtmAll` | integer | Lifetime withdrawal limit |
| `limitAtmYear` | integer | Yearly withdrawal limit |
| `limitAtmMonth` | integer | Monthly withdrawal limit |
| `limitAtmWeek` | integer | Weekly withdrawal limit |
| `limitAtmDay` | integer | Daily withdrawal limit |
```bash [CURL]
curl -X POST '{baseUrl}/core-connect/card/bulk' \
--header 'accept: application/json' \
--header 'authorization: Bearer {accessToken}' \
--header 'content-type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`.
```json [JSON]
{
"number": 5,
"medium": 2,
"defaultPermsGroup": "TRZ-CU-016",
"walletTypeId": 10,
"createWalletForEach": true,
"createUserForEach": true,
"cardDeliveryAddress1": "33 avenue Wagram",
"cardDeliveryPostCode": "75017",
"cardDeliveryCity": "Paris",
"cardDeliveryCountry": "FR",
"anonymous": 1,
"cardPrint": "8528",
"logoId": "",
"packageId": ""
}
```
Answers with a `201` HTTP Status Code and returns the following:
```json [JSON]
{
"number": 5,
"createUserForEach": true,
"distributionCountry": "FR",
"createWalletForEach": true,
"walletTypeId": 10,
"medium": 2,
"cardPrint": "8528",
"anonymous": 1,
"defaultPermsGroup": "TRZ-CU-016",
"packageId": "",
"logoId": "",
"cardDeliveryAddress1": "33 avenue Wagram",
"cardDeliveryPostCode": "75017",
"cardDeliveryCity": "Paris",
"cardDeliveryCountry": "FR",
"orderId": "d1fca687-9dbd-4530-8a80-336f2b56421a",
"status": "PENDING"
}
```
Bulk creations are asynchronous, therefore, you have a second endpoint to [follow their progress](#follow-bulk-creations).
### Follow Bulk Creations
To follow your [Bulk Creations progress](#bulk-creation), you can use the following request:
```bash [CURL]
curl -X GET '{baseUrl}/core-connect/card/bulk' \
--header 'accept: application/json' \
--header 'authorization: Bearer {accessToken}'
```
Returns the following.
```json [JSON]
[
// Completed Bulk Creation with some errors
// more information is contained in the "errors" attribute
{
"orderId": "0c6251ad-6b84-4e74-a926-8a193974248d",
"walletIdAttach": null,
"createWalletForEach": true,
"walletTypeId": 9,
"userIdOwner": null,
"createUserForEach": true,
"number": 1,
"defaultMccRestrictionGroupId": null,
"defaultMerchantRestrictionGroupId": null,
"defaultCountryRestrictionGroupId": null,
"defaultPermsGroup": "TRZ-CU-003",
"status": "COMPLETE_WITH_ERROR",
"createdAt": "2021-09-02T14:00:59+02:00",
"errors": [
"[{\"code\":\"unexpected_error\",\"docurl\":\"https:\/\/developers.treezor.co\",\"type\":\"unexpected_internal_server_error\",\"message\":\"An unexpected error was raised in our server. Please try again later, if same result please contact support\"}]"
],
"packageId": null,
"logoId": null,
"anonymous": 1,
"cardPrint": "8528",
"paymentDailyLimit": null,
"limitPaymentAll": null,
"limitPaymentDay": null,
"limitPaymentWeek": null,
"limitPaymentMonth": null,
"limitPaymentYear": null,
"limitAtmAll": null,
"limitAtmDay": null,
"limitAtmWeek": null,
"limitAtmMonth": null,
"limitAtmYear": null,
"medium": 2,
"cardDeliveryAddress1": "33 avenue Wagram",
"cardDeliveryAddress2": null,
"cardDeliveryAddress3": null,
"cardDeliveryPostCode": "75017",
"cardDeliveryCity": "Paris",
"cardDeliveryState": null,
"cardDeliveryCountry": "FR",
"distributionCountry": null
},
// Successful Bulk Creation without errors
{
"orderId": "11520318-6c26-4207-aebb-97280a857537",
"walletIdAttach": 922972,
"createWalletForEach": null,
"walletTypeId": null,
"userIdOwner": 1731771,
"createUserForEach": null,
"number": 50,
"defaultMccRestrictionGroupId": null,
"defaultMerchantRestrictionGroupId": null,
"defaultCountryRestrictionGroupId": null,
"defaultPermsGroup": "TRZ-CU-016",
"status": "COMPLETE",
"createdAt": "2021-08-23T10:55:28+02:00",
"errors": [],
"packageId": null,
"logoId": null,
"anonymous": 1,
"cardPrint": "8528",
"paymentDailyLimit": null,
"limitPaymentAll": null,
"limitPaymentDay": null,
"limitPaymentWeek": null,
"limitPaymentMonth": null,
"limitPaymentYear": null,
"limitAtmAll": null,
"limitAtmDay": null,
"limitAtmWeek": null,
"limitAtmMonth": null,
"limitAtmYear": null,
"medium": 1,
"cardDeliveryAddress1": null,
"cardDeliveryAddress2": null,
"cardDeliveryAddress3": null,
"cardDeliveryPostCode": null,
"cardDeliveryCity": null,
"cardDeliveryState": null,
"cardDeliveryCountry": null,
"distributionCountry": null
},
// PENDING Bulk Creation
{
"orderId": "1775d8da-2edc-46b6-87d6-948bc184511b",
"walletIdAttach": null,
"createWalletForEach": true,
"walletTypeId": 10,
"userIdOwner": null,
"createUserForEach": true,
"number": 5,
"defaultMccRestrictionGroupId": 5053,
"defaultMerchantRestrictionGroupId": 4932,
"defaultCountryRestrictionGroupId": 2410,
"defaultPermsGroup": "TRZ-CU-016",
"status": "PENDING",
"createdAt": "2021-10-26T10:54:53+02:00",
"errors": [],
"packageId": null,
"logoId": null,
"anonymous": 1,
"cardPrint": "8529",
"paymentDailyLimit": null,
"limitPaymentAll": null,
"limitPaymentDay": null,
"limitPaymentWeek": null,
"limitPaymentMonth": null,
"limitPaymentYear": null,
"limitAtmAll": null,
"limitAtmDay": null,
"limitAtmWeek": null,
"limitAtmMonth": null,
"limitAtmYear": null,
"medium": 1,
"cardDeliveryAddress1": "10 avenue Vagram",
"cardDeliveryAddress2": null,
"cardDeliveryAddress3": null,
"cardDeliveryPostCode": "75000",
"cardDeliveryCity": "Paris",
"cardDeliveryState": null,
"cardDeliveryCountry": "FR",
"distributionCountry": null
}
]
```
## Activation
As a security measure, all Cards are issued in an `inactive` state to ensure that a Physical Card is not usable before the cardholder receives it.
A Card in an `inactive` state cannot be used to make any type of payment or withdrawal.
Typically, the end user would be required to activate the card in your application by entering the `publicToken` as printed on the back of the received card.
```bash [CURL]
curl -X PUT '{baseUrl}/v1/cards/{id}/Activate' \
--header 'Authorization: Bearer {accessToken}'
```
Returns a Card object, with its `isLive` attribute set to `1`.
```json [JSON]
{
"cardId": 0,
"userId": 0,
"walletId": 0,
"walletCardtransactionId": 0,
"mccRestrictionGroupId": 0,
"merchantRestrictionGroupId": 0,
"countryRestrictionGroupId": 0,
"publicToken": "string",
"cardTag": "string",
"statusCode": "UNLOCK",
"isLive": 1, // <--- affected attribute
// [...] some attributes are hidden
}
```
Users of may also activate a Card in one step, using its `publicToken` directly.
```bash [CURL]
curl -X PUT '{baseUrl}/v1/cards/{cardToken}/public-token-activation' \
--header 'Authorization: Bearer {accessToken}'
```
Also returns a Card object, with its `isLive` attribute set to `1`.
Treezor also sends a [`card.activate`](./events#card-activate) webhook.
## Enrolling a Card for 3D Secure
3D Secure provides an enhanced level of security for online (e-commerce) [payments](/guide/cards/transactions-lifecycle) by adding the possibility to authenticate the cardholder. This a **mandatory fallback** with a one-time password (OTP) sent by SMS; the card must be enrolled for [Out of Band (OOB) authentication](/guide/strong-customer-authentication/securing-endpoints#enrolling-to-out-of-band-authentication) first.
**Registering the card for 3D Secure requires a mobile phone number**. The cardholder then receives a secure code on their mobile phone when an authentication is required for an online payment. This code is unique for each payment and needs to be entered on the merchant's website or mobile application when prompted.
**Prior to this step, your must ensure the User was created with a [mobile phone number](/guide/api-basics/data-format#phones)**. Otherwise, the [User](/guide/users/introduction) must be updated with a mobile phone number.
Endpoint: [`/v1/cards/Register3DS`](/api-reference/api-endpoints.html#tag/Cards/post3ds){target="\_self"}
```bash [CURL]
curl -X POST '{baseUrl}/v1/cards/Register3DS' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{
"cardId": 123456
}'
```
This returns a Card object, but doesn't specify the 3D Secure enrolling status. Treezor also sends a [`card.register3DS`](/guide/cards/events#cardregister3ds) webhook.
**Configuration – By default, 3DS SMS are sent under the name "Secure3DS"**
You can contact Treezor and provide a new sender name that:
* Contains only alphanumeric characters (no spaces)
* Starts with a letter
* Is less than 12-character long
## Customization
Cards can be customized with the following values.
**Configuration – There is no API endpoint to manage these features.**
If you are interested in customizing the cards, please contact your *Treezor Account Manager*.
### Logo (`logoId`)
You can add a customized logo by setting its filename (as uploaded to the manufacturer) in the `logoId` parameter. This logo overlays to your usual Card Design.
The constraints are as follows:
* **Format**: `.jpg` or `.png`.
* **Definition**: 600 PPI.
* **Maximum size**: Depends on your Card Design.
* **String**: Can't exceed 30 characters.
* **Accepted characters**: a-z, A-Z, 0-9.
* **Transparent background** is recommended. In any case, white content is not printed.
### Back Logo (`logoBackId`)
You can add a customized logo on the backside of the Card by setting its filename (as uploaded to the manufacturer) in the `logoBackId` parameter. This logo overlays to your usual Card Design.
The constraints are as follows:
* **Format**: `.jpg` or `.png`.
* **Definition**: 600 PPI.
* **Maximum size**: Depends on your Card Design.
* **String**: Can't exceed 30 characters.
* **Accepted characters**: a-z, A-Z, 0-9.
* **Transparent background** is recommended. In any case, white content is not printed.
### Card Delivery Method (`deliveryMethod`)
You can define the method the manufacturer uses to send the cards (e.g., delivery with or without tracking).
The possible options are to be defined with your *Treezor Account Manager*. They range from `0` to `9` and depend on your specific implementation with the manufacturer.
### Pin Mailer (`pinMailer`)
You can request the card manufacturer to send the card PIN code by letter.
This requires a specific configuration of the card production chain with the manufacturer by your *Treezor Account Manager*. Then, this option can be activated by your *Technical Account Manager* or *Implementation Manager*.
Once the feature activated, you can define whether to use the card PIN code by letter by setting the `pinMailer` value to `1`.
### Batch Delivery (`batchDeliveryId`)
The Batch Delivery system lets you receive physical cards in batches if enabled. Cards with the same values for the parameters below are sent together.
| Information | Description |
| --- | --- |
| **Delivery ID** | The cards must all have the same `batchDeliveryId` value (must be between `1` and `238327`). |
| **Address** | The cards must all have the same delivery address. Please keep in mind that the card's delivery parameters default to either: The address defined at the user levelThe address of the parent of the user the card belongs to if the `sendToParent` parameter is set to `1`. |
**Information – Treezor sends the batch orders to the manufacturer daily**
For cards with the same `batchDeliveryId` to be in the same batch, we advise you create them from 01:00PM UTC to 10:00 AM UTC the next day. Cards created between 10:00 AM and 01:00 PM might be sent in 2 different batches.
### Packaging (`packageId`)
The `packageId` allows you to use multiple Cards Packaging with the same [Card Program](./introduction#card-program). This feature can also be used to handle packaging in different languages.
This is set up between you and your *Treezor Account Manager*.
### Designs (`designCode`)
The `designCode` allows you to use multiple Card Designs with the same [Card Program](./introduction#card-program). This design applies to [Virtual Cards](#virtual-card-creation), [Physical Cards](#physical-card-creation), and [digitized Cards](x-pay-google-apple).
To use a specific design, you will need to specify the `designCode` along with your usual `cardPrintId`.
The final design identification code will be a concatenation of the `cardPrintId` + `z` + `designCode`. Once created, Card objects returned by the API will not specify which `designCode` was used. It is therefore recommended that you store this information in your own databases.
### Embossed name (`embossedName`)
Up to 2 names can be embossed on the card: the name of the cardholder (`embossedName`), and the name of the legal entity.
Note that some restrictions apply to the display of the names:
* **Accepted characters**: a-z, A-Z, 0-9, hyphen (`-`), and space (` `).
* **Max. length**: 20 characters. Treezor truncates the string if the limit is exceeded, starting by abbreviating the first name in the case of the `embossedName`.
Therefore, Treezor strongly advises you keep in mind these rules when populating the User object's `firstname`, `lastname`, and `legalNameEmbossed` (inherited from `legalName`) attributes.
Please note that regardless of the user type, you'll need the `firstname`, `lastname`, and `phone` (or `mobile`) User attributes in order to create a card.
#### Name of the cardholder
The name of the cardholder is embossed according to the following rules.
| User type | Embossing rules |
| --- | --- |
| **Anonymous user** | `embossedName` returns an empty string, if the card `anonymous` attribute is set to `1`. |
| **Other** | `embossedName` returns the concatenation of the `firstname` and `lastname` inherited from the User object. |
#### Name of the legal entity
The name of the legal entity is embossed according to the following rules.
| User type | Embossing rules |
| --- | --- |
| **Physical user** | `legalNameEmbossed` inherited from the parent user if available and if the card `embossLegalName` attribute is set to `true`. |
| **Legal entity** | `legalNameEmbossed` inherited from user if available and if the card `embossLegalName` attribute is set to `true`. |
Please note the Card object doesn't return the legal embossed value. It is available in the `legalNameEmbossed` attribute of the User object, which is already truncated for embossing.
**Caution – `embossLegalName` and `customizedInfo` incompatibility**
Treezor sends an error if you attempt to emboss the legal name and display customized information at the same time.
### Customized Info (`customizedInfo`)
The `customizedInfo` allows you to add specific text on each Card.
There is a maximum of 27 alphanumeric characters excluding `!"#%'(),:;<>?@[]^` and the backtick symbol.
The actual length limitation will depend on the chosen font and on the position of the text on the Card.
**Caution – `embossLegalName` and `customizedInfo` incompatibility**
Treezor sends an error if you attempt to emboss the legal name and display customized information at the same time.
### Additional Customized Info (`freeCustomizedInfo`)
The `freeCustomizedInfo` allows you to add more specific text on each Card in a similar way to `customizedInfo`.
There is a maximum of 50 alphanumeric characters excluding `!"#%'(),:;<>?@[]^` and the backtick symbol.
The actual length limitation will depend on the chosen font and on the position of the text on the Card.
### Letter Customized Info (`letterCustomizedInfo`)
The `letterCustomizedInfo` allows you to add specific text on the letter that accompanies a Card.
There is a maximum of 50 alphanumeric characters excluding `!"#%'(),:;<>?@[]^` and the backtick symbol.
---
---
url: /guide/user-verification/documents.md
description: >-
Technical guide for creating and managing KYC documents via the Treezor API.
Includes required parameters, request structure, and response examples.
---
# Documents
Documents are evidence required by Treezor to ensure Users are who they claim to be.
During the KYC/B review, Treezor compares documents to the user’s declarative data. The user is verified if the documents are in order (as well as any other verification requirement).
Users may follow different verification processes depending on their type and distribution country. Processes that result in the creation of a Document object in the Treezor API are uploads through:
* [Your application](#process) (document endpoints)
* [The Document pre-review](./documents-prereview) feature (pre-signed form)
* [The Live verification](./live-verification) features
* [The Qualified Electronic Signature](./qes) feature
This article focuses on the Document object and the upload made directly using the Treezor API Document endpoints.
**Configuration – Documents must:**
* Abide by size restrictions (encoded file < 6Mo / original file < 4.5Mo)
* Be in mime type: `application/pdf`, `image/jpg`, `image/png`, `image/tiff`, or `image/svg+xml`
* Be converted to [base64](/guide/api-basics/data-format#files)
## Process
Uploading documents through the dedicated endpoints can be done in 2 ways.
| | Method | Description |
| --- | --- | --- |
| | As application | The user first uploads documents to your application, so you can check them before uploading them to Treezor. |
| | As end user | You upload the documents in the end user’s name with the grant type `delegated_end_user` JWT. This method is only available if the SCA feature is activated for your environment. It may result in a lower success rate of the KYC review since you don’t review documents first. |
Each method has its advantages and drawbacks. If you are unsure about which to implement, don’t hesitate to contact Treezor.
If we take the first case, the steps are the following:
* [User](/guide/users/introduction) uploads documents to your application (requiring dedicated code on your side)
* You check that the documents are acceptable
* You forward the documents to the [`/v1/documents`](/api-reference/api-endpoints.html#tag/User%20Documents/createDocuments){target="\_self"} endpoint. You receive a [`document.create`](/guide/user-verification/events#document-create) webhook for each document upload.
* Once all the documents for a given user are uploaded, you request a review process using the following endpoint: [`/v1/users/{id}/Kycreview`](/api-reference/api-endpoints.html#tag/User%20KYC%20Review){target="\_self"}
* Treezor sends you a [`user.kycreview`](/guide/user-verification/events#user-kycreview) webhook upon validation or refusal.
**Note – More steps may be required**
This is a simple example of a KYC Review process. It doesn’t consider multiple methods usage, parent-children hierarchical relations, and additional vigilance measures.
## Collect documents
This is the first step if you choose to have the user upload documents to your application or website. You store documents in your cloud infrastructure before passing them on to Treezor.
Your teams should review the documents before uploading them to Treezor. Ensuring documents abide by the requirements results in a higher KYC success rate.
**Caution – Regulation**
Depending on your local regulations, you may not be allowed to keep or store KYC documents on your infrastructure.
## Upload documents
You need to upload all the documents of a given user before requesting a KYC review.
It may include the documents of the children users in the case of a parent-children hierarchical relation.
### Parameters
Below are the necessary parameters to create Documents.
| Attribute | Type | Description |
|--- |--- |--- |
| `userId` | integer | The unique identifier of the User the document belongs to. |
| `documentTypeId` | integer | The type of the document. See the [Types list](#types-documenttypeid) below. |
| `name` | string | The name of the document, including its extension. |
| `fileContentBase64` | string | The document itself. The file must be encoded in standard base64 (RFC 4648). |
| `residenceId` | integer | The unique identifier of the User's Tax Residence. Only required if the `documentTypeId` is `24` or `25`. |
**API – API Reference available**
For a complete list of Document attributes, check the [User Documents](/api-reference/api-endpoints.html#tag/User%20Documents){target="\_self"} section of the API Reference.
### Request
You can use the [`/v1/documents`](/api-reference/api-endpoints.html#tag/User%20Documents/createDocuments){target="\_self"} request for each document you need to upload.
Use an access token with the `delegated_end_user` grant type if you’re uploading the documents in the end user's name.
```bash [CURL]
curl -X POST '{baseUrl}/v1/documents' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}
```
Here is a `{payload}` example:
```json [JSON]
{
"fileContentBase64": "{base64file}",
"userId": 123456,
"documentTypeId": 9,
"name": "aoak_identity_card.pdf"
}
```
Returns the Document object.
```json [JSON]
{
"documents": [
{
"documentId": 980190,
"documentTag": null,
"clientId": 929252,
"userId": 100344292, // Associated user
"userFirstname": null,
"userLastname": null,
"name": "Test_id",
"documentStatus": "PENDING", // Document current review status
"documentTypeId": 9,
"documentType": "ID",
"fileName": "980190.pdf",
"thumbFileName": "",
"createdDate": "2024-04-30 14:13:40",
"modifiedDate": "0000-00-00 00:00:00",
"codeStatus": "600003",
"informationStatus": null,
"residenceId": 0,
"temporaryUrl": "", // Deprecated
"temporaryUrlThumb": "" // Deprecated
}
]
}
```
Treezor also sends a [`document.create`](./events#document-create) webhook.
## Upload large Documents
Treezor provides a specific endpoint for documents whose original file size exceeds 4.5Mo. Instead of directly [uploading the document](#upload-documents) in base64, you will follow 2 steps:
1. [Generate pre-signed URL](#1-generate-pre-signed-url) – Send document information to get the pre-signed URL.
2. [Upload document](#2-upload-document) – Make the request to the `uploadUrl`.
### 1. Generate pre-signed URL
#### Parameters
Below are the necessary parameters to create Documents.
| Attribute | Type | Description |
|--- |--- |--- |
| `userId` | integer | The unique identifier of the User the document belongs to. |
| `documentTypeId` | integer | The type of the document. See the [Types list](#types-documenttypeid) below. |
| `name` | string | The name of the document, including its extension. |
| `residenceId` | integer | The unique identifier of the User's Tax Residence. Only required if the `documentTypeId` is `24` or `25`. |
| `fileExtension` | string | The file extension of the document (jpg, png, svg, tif, or pdf). |
| `fileSize` | integer | The size of the document (max: 50MB). |
| `fileHash` | string | Hexadecimal hash of the document file (SHA256). |
**API – API Reference available**
For a complete list of Document attributes, check the [User Documents](/api-reference/api-endpoints.html#tag/User%20Documents){target="\_self"} section of the API Reference.
#### Request example
Use the [`/v1/documents/uploadUrl`](/api-reference/api-endpoints.html#tag/User%20Documents/createDocuments){target="\_self"} request for each document you need to upload.
```bash [CURL]
curl -X POST'{baseUrl}/v1/documents/uploadUrl' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}
```
Here is a `{payload}` example:
```json [JSON]
{
"userId":123456,
"documentTypeId":9,
"name": "alex oak identity card",
"fileExtension": "pdf",
"fileSize": 1048576,
"fileHash": "c27d4142972f30ac6ead183e54437f1b993a64994b342a7261337bc5a7a7e447"
}
```
Returns the Upload URL with all the necessary information for step 2.
```json [JSON]
{
"documentId": 1236516,
"uploadUrl": "https://test.s3.eu-central-1.amazonaws.com",
"values": {
"Content-Type": "application/pdf",
"X-Amz-Algorithm": "AWS4-HMAC-SHA256",
"X-Amz-Credential": "ASIAWTKIE63XXXYQM735/20250627/eu-central-1/s3/aws4_request",
"X-Amz-Date": "20250627T134703Z",
"X-Amz-Meta-autovalidate": "true",
"X-Amz-Meta-client": "12345",
"X-Amz-Meta-full_filename": "1236516.jpg",
"X-Amz-Security-Token": "IQoJb3JpZ2luX2VjEXxXxXXV1LW[...]heZZA==",
"X-Amz-Signature": "f06cdc708e87b2b007bcbf7a1af2df[...]c2407d594cbd452ee34b7",
"X-Amz-checksum-algorithm": "SHA256",
"X-Amz-checksum-sha256": "wn1BQpcvMKxurRg+VEN/G5k6[...]TN7xaen5Ec=",
"key": "client_12345/user_102273999/1236516.jpg",
"policy": "eyJjb25[...]AzWiJ9"
},
"expireIn": 120
}
```
The upload link expires after 2 minutes.
### 2. Upload Document
Make a POST request to the `uploadUrl` with all the relevant values within 2 minutes after the URL was generated.
```bash [CURL]
curl -X POST "https://test.s3.eu-central-1.amazonaws.com" \
--form "X-Amz-checksum-algorithm=SHA256" \
--form "X-Amz-checksum-sha256=wn1BQpcvMKxurRg+VEN/G5k6[...]TN7xaen5Ec=" \
--form "Content-Type=application/pdf" \
--form "X-Amz-Date=20250627T134703Z" \
--form "key=client_929252/user_102273999/1236516.jpg" \
--form "policy=eyJjb25[...]AzWiJ9" \
--form "X-Amz-Algorithm=AWS4-HMAC-SHA256" \
--form "X-Amz-Credential=ASIAWTKIE63XXXYQM735/20250627/eu-central-1/s3/aws4_request" \
--form "X-Amz-Security-Token=IQoJb3JpZ2luX2VjEXxXxXXV1LW[...]heZZA==" \
--form "X-Amz-Signature=f06cdc708e87b2b007bcbf7a1af2df[...]c2407d594cbd452ee34b7" \
--form "X-Amz-Meta-autovalidate=true" \
--form "X-Amz-Meta-client=12345" \
--form "X-Amz-Meta-full_filename=123456.pdf"
--form "file=@/path/to/file.pdf"
```
If the upload is successful, you receive an HTTP 204 No Content response.
Treezor also sends a [`document.create`](./events#document-create) webhook.
## Download documents
If you're eligible, you may be able to collect some of the uploaded documents whose `documentTypeId` allows for it.
**Configuration – Download is not enabled by default**
Please contact Treezor to request access to this feature.
Downloading a document is a 2-step process, in which you:
1. [Request the download URL](#request-the-download-url)
2. [Download the document within 30 seconds](#download-the-document)
### Request the download URL
To request the download URL, you need the corresponding `documentId` (available in the `document.create` webhook for instance).
```bash [CURL]
curl -X GET '{baseUrl}/v1/documents/{documentId}/download' \
--header 'Authorization: Bearer {accessToken}' \
```
Returns the URL to download the document, with all the necessary query parameters for the next step.
```json [JSON]
{
"url": "{documentDownloadUrl}"
}
```
The link expires after 5 minutes.
### Download the document
You have 5 minutes to download the document from the moment the presigned URL has been generated in the previous step.
```bash [CURL]
curl -X GET '{documentDownloadUrl}'
```
The document is returned in its initial format.
## Document key attributes
| Attribute | Type | Description |
| --- | --- | --- |
| `userId` | integer | The unique identifier of the User. |
| `documentStatus` | string | The current KYC review status of the document. See [table](#status-documentstatus) below. |
| `documentTypeId` | integer | The type of document, such as ID Card, driving license, etc. See [table](#types-documenttypeid) below. |
| `name` | string | The name of the file, including the extension. |
| `residenceId` | integer | The unique identifier of the User's [`taxResidence`](/guide/users/tax-residence), which is mandatory with `documentTypeId` set to `24` and `25`. |
| `fileContentBase64` | string | Base64-encoded [file](/guide/api-basics/data-format#files). |
### Types (`documentTypeId`)
| `documentTypeId` | `documentType` | Description |
|:---: |--- |--- |
| `2` | `Police record` | Police record |
| `4` | `KBIS` | Company Registration |
| `6` | `CV` | CV |
| `7` | `Sworn statement` | Sworn statement |
| `8` | `Prévisionnels` | Turnover |
| `9` | `ID` | Identity card |
| `11` | `RIB` | Bank Identity Statement |
| `12` | `Proof of address` | Proof of address |
| `13` | `MOBILE_BILL` | Mobile phone invoice |
| `14` | `INVOICE` | Invoice, other than Mobile phone invoice |
| `15` | `RESIDENCE_PERMIT` | Residence permit |
| `16` | `DRIVING_LICENCE` | Driving license |
| `17` | `PASSPORT` | Passport |
| `18` | `PROXY` | Proxy granting an employee |
| `19` | `COMPANY_REGISTRATION` | Company registration official paper |
| `20` | `TAX_CERTIFICATE` | Official tax certificate |
| `21` | `PAYSLIP` | Employee payment notice |
| `22` | `BANK_STATEMENT` | User bank statement |
| `23` | `LEGAL_STATUS` | Business legal status |
| `24` | `TAX_STATEMENT` | Tax Statement |
| `25` | `EXEMPTION_STATEMENT` | Exemption Statement |
| `26` | `LIVENESS_RESULT` | Liveness result |
| `27` | `HEALTH_INSURANCE_CARD` | Health insurance card |
| `28` | `SIREN` | SIREN |
| `29` | `RBE` | RBE - List of beneficial owners |
| `31` | `PEP_ASSETS_DECLARATION` | PEP - Assets Declaration |
| `32` | `PRO_REVENUE_DECLARATION` | Professional - Revenue Declaration |
| `33` | `NON_PROFIT_ORG_DECLARATION` | Non-Profit Organization - Financial Declaration |
| `34` | `CERTIFIED_LIVENESS_RESULT` | Certified Liveness Result |
| `35` | `NATURAL_REVENUE_ASSETS_REPORT` | Natural Person - Revenue and Assets Declaration |
| `36` | `REAL_ESTATE_PROOF_OF_OWN` | Real Estate - Proof of ownership |
| `37` | `PROOF_OF_SECURITIES_EXCHANGE` | Proof of Securities Exchange Listing |
| `38` | `IDENTITY_VIA_AUTH_THIRD_PARTY` | Identity Verification Form via an Authorized Third Party |
| `39` | `FINANCIAL_STATEMENT` | Financial Statement |
| `40` | `PUBLIC_ACCOUNTANT_STATEMENT` | Public Accountant Statement |
| `41` | `FAMILY_RECORD_BOOK` | Family Record Book |
| `42` | `BIRTH_CERTIFICATE` | Birth certificate |
| `43` | `POWER_OF_ATTORNEY` | Power of attorney |
| `44` | `ORG_CHART_VIA_AUTH_THIRD_PARTY` | Organizational Chart via an Authorized Third Party |
| `45` | `COMPANY_REPORT_VIA_INDEP_PARTY` | Official Company Declaration via an Independent Third Party |
| `46` | `DECLARATION_ACTIVITY_REVENUES` | Declaration of activity and revenues |
| `47` | `QES_CERTIFICATE` | Certificate of the qualified e-signature. |
| `48` | `QES_RESULT` | Result of the qualified e-signature |
| `49` | `VIDEO_CONFERENCE_RESULT` | Result of the Video Conference |
| `50` | `CAPITALIZATION_TABLE` | Capitalization table |
| `51` | `W9_FORM` | W-9 Form |
### Status (`documentStatus`)
| `codeStatus` | |`documentStatus` | Description |
|:---: |:---: | --- |--- |
| `600001` | | **PENDING** | Initial status before upload into the container |
| `600002` | | **PENDING** | Suspected fraud or [AML/CFT](/guide/overview/glossary#anti-money-laundering-and-countering-the-financing-of-terrorism-aml-cft). Don't share this information with the end user. |
| `600003` | | **PENDING** | Successfully uploaded into the container |
| `600004` | | **CANCELED** | Cancelled by the user |
| `600005` | | **CANCELED** | Cancelled by the operator |
| `600006` | | **CANCELED** | Failed to write the document into the container |
| `600007` | | **CANCELED** | Failed to read the document from the container |
| `600008` | | **REFUSED** | Refused |
| `600009` | | **VALIDATED** | Validated |
| `600010` | | **REFUSED** | Out of scope |
| `600011` | | **REFUSED** | Expired |
| `600012` | | **REFUSED** | Falsified |
| `600013` | | **REFUSED** | Illegible |
| `600014` | | **REFUSED** | Truncated document |
| `600015` | | **REFUSED** | Truncated |
| `600016` | | **REFUSED** | Incoherent |
| `600017` | | **REFUSED** | Other |
## Document object
```json [JSON]
{
"documentId": 0,
"documentTag": "string",
"clientId": 0,
"userId": 0,
"userFirstname": "string", // Deprecated
"userLastname": "string", // Deprecated
"name": "string",
"documentStatus": "string",
"documentTypeId": 0,
"documentType": "sring",
"fileName": "string",
"thumbFileName": "string", // Deprecated
"createdDate": "string",
"modifiedDate": "string",
"codeStatus": "string",
"informationStatus": "string",
"residenceId": 0,
"temporaryUrl": "string", // Deprecated
"temporaryUrlThumb": "string" // Deprecated
}
```
## Endpoints
| Endpoint |[Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/v1/documents`](/api-reference/api-endpoints.html#tag/User%20Documents/createDocuments){target="\_self"} Create a document | `read_write` |
| [`/v1/documents/uploadUrl`](/api-reference/api-endpoints.html#tag/User%20Documents/createDocuments){target="\_self"} Upload a large document | `read_write` |
| [`/v1/documents`](/api-reference/api-endpoints.html#tag/User%20Documents/getDocuments){target="\_self"} Search for documents | `read_only` |
| [`/v1/documents/{documentId}`](/api-reference/api-endpoints.html#tag/User%20Documents/getDocument){target="\_self"} Retrieve a specific document based on its `id` | `read_only` |
| [`/v1/documents/{documentId}`](/api-reference/api-endpoints.html#tag/User%20Documents/putDocument){target="\_self"} Update a document `name` | `read_write` |
| [`/v1/documents/{documentId}`](/api-reference/api-endpoints.html#tag/User%20Documents/deleteDocument){target="\_self"} Delete a document | `read_write` |
| [`/v1/documents/{documentId}/download`](/api-reference/api-endpoints.html#tag/User%20Documents/getDocumentDownloadUrl){target="\_self"} Retrieve a document download URL | `read_only` |
| [`/v1/users/{userId}/Kycreview`](/api-reference/api-endpoints.html#tag/User%20KYC%20Review/putKycreview){target="\_self"} Initiate the user [KYC review](/guide/user-verification/introduction) process | `read_write` |
---
---
url: /guide/users/legal-entity.md
description: >-
Technical guide for creating legal entities via the Treezor API. Also explains
how to check for information veracity and finding the legal representatives.
Includes required parameters, request structure, and response examples.
---
# Legal Entities
A **Legal Entity** is a company, a governmental or non-governmental organization, or an association. It is identified by a legal name, legal register number, etc.
The legal representatives and majority shareholders must have a [parent-children](/guide/users/parent-children) hierarchical relation with the Legal Entity. They are themselves created as [Physical Users](/guide/users/physical).
Once this done, the Legal Entity can be [verified](/guide/user-verification/introduction), which triggers the representatives and shareholders review at the same time.
**Information – Specific case of self-employed persons**
Freelancers and self-employed persons should be created as [Physical Users](/guide/users/physical) with a specific `legalForm`. See [Self-employed Users](./physical#self-employed-users) for more information.
## Creation
### Parameters
Below are the necessary parameters to create Legal Entities.
While some parameters might not be required by the API, they are necessary when it comes to the KYC validation of the user. They should be collected from the creation (or you may have to update the user information later on).
| Attribute | Type | Description |
|--- |--- |--- |
| `userTypeId` | integer | Must be `2` (business), `3` (non-governmental organization), or `4` (governmental organization) for legal entities. |
| `specifiedUSPerson` | integer | Indicates if the user [is a US Person](./tax-residence). |
| `email` | string | The email of the legal entity, which must be [unique and valid](./introduction#using-unique-and-valid-email-addresses) and can't exceed 200 characters. |
| `address{1-3}` (required for KYC) | string | The legal entity's postal address. The max value for each address line is 150 characters. If you're issuing cards, see the [Data Formats](/guide/api-basics/data-format#addresses) article for information on further limitations. |
| `postcode` (required for KYC) | string | The legal entity's address postcode. |
| `city` (required for KYC) | string | The legal entity's address city. |
| `country` (required for KYC) | string | The legal entity's address country (format ISO 3166-1 alpha-2) |
| `phone` (required for KYC) | string | The legal entity's phone number, in international E.164 format. |
| `legalName` (required for KYC) | string | The name of the company. |
| `legalRegistrationNumber` (required for KYC) | string | The registration number of the legal entity (e.g., SIREN/SIRET). |
| `legalForm` (required for KYC) | string | The legal category of the legal entity. See [Legal forms](./introduction#legal-forms-legalform) for more information. |
| `legalTvaNumber` | string | The VAT number of the legal entity. |
| `legalRegistrationDate` (required for KYC) | string | The registration date of the company. Format: YYYY-MM-DD. |
| `legalShareCapital` | integer | The share capital of the legal entity. |
| `legalAnnualTurnOver` (required for KYC) | string | The annual turn over of the legal entity in k€, among the following ranges: `0-39`, `40-99`, `100-249`, `250-999`, `1000-2999`, `3000-9999`, `10000-99999`, and `100000-*` |
| `legalNetIncomeRange` (required for KYC) | string | The net income of the legal entity in k€, among the following ranges: `0-4`, `5-9`, `10-49`, `50-149`, `150-499`, and `500-*`. |
| `legalNumberOfEmployeeRange` (required for KYC) | string | The number of employees of the legal entity among the following ranges: `0`, `1-9`, `10-99`, `100-249`, and `250-*` |
| `legalSectorType` | string | Either `NAF` or `NACE`, qualifies the type of data in the `legalSector` field. |
| `legalSector` (required for KYC) | string | The business sector of the legal entity. Either a 4-digit code if NACE or a 5-digit code followed by an uppercase letter if [NAF](/guide/overview/glossary#nomenclature-activites-francaise-naf), depending on the value of the `legalSectorType`. |
| `distributionCountry` | string | The country in which the end user is using your services. This field is only required when you operate in multiple countries. See [Distribution country](/guide/users/introduction#distribution-country-distributioncountry) for more information. |
**Information – Refer to your KYC Form for declarative data**
Declarative data to submit depends on the type of user, the country you're operating in, the regulations linked to your use case, etc. Treezor Compliance team provides you with your KYC Form listing what needs to be submitted.
### Request example
Endpoint: [`/v1/users`](/api-reference/api-endpoints.html#tag/Users/postUsers){target="\_self"}
Here is an example of `{payload}`:
```json [JSON]
{
"userTypeId": 2,
"specifiedUSPerson": 0,
"email": "contact.company@example.com",
"address1": "56 Bluewoods lane",
"postcode": "75000",
"city": "Paris",
"country": "FR",
"phone": "+33102030405",
"legalName": "Treehouse Company",
"legalRegistrationNumber": "42877171100028",
"legalTvaNumber": "FR27807465059",
"legalRegistrationDate": "2007-10-24",
"legalShareCapital": 4236474,
"legalForm": "5510",
"legalAnnualTurnOver": "100-249",
"legalNetIncomeRange": "50-149",
"legalNumberOfEmployeeRange": "100-249",
"legalSectorType": "NAF",
"legalSector": "1234F",
"entitySanctionsQuestionnaire": 1,
"activityOutsideEu": 1,
"economicSanctions": 0,
"residentCountriesSanctions": 0,
"involvedSanctions": 0
}
```
Returns a User object:
```json [JSON]
{
"users": [
{
"userId": 100138128,
"userTypeId": 2,
"userStatus": "VALIDATED",
"userTag": "",
"parentUserId": 0,
"parentType": "",
"controllingPersonType": 0,
"employeeType": 0,
"specifiedUSPerson": 0,
"title": "",
"firstname": "",
"lastname": "",
"middleNames": "",
"birthday": "0000-00-00",
"email": "contact.company@example.com",
"address1": "56 Bluewoods lane",
"address2": "",
"postcode": "75000",
"city": "Paris",
"state": "",
"country": "FR",
"countryName": "France",
"phone": "+33102030405",
"mobile": "",
"nationality": "",
"nationalityOther": "",
"placeOfBirth": "",
"birthCountry": "",
"occupation": "",
"incomeRange": "",
"legalName": "Treehouse Company",
"legalNameEmbossed": "Treehouse Company",
"legalRegistrationNumber": "42877171100028",
"legalTvaNumber": "FR27807465XX",
"legalRegistrationDate": "2007-10-24",
"legalForm": "5510",
"legalShareCapital": 4236474,
"entityType": null,
"legalSector": "1234F",
"legalAnnualTurnOver": "100-249",
"legalNetIncomeRange": "50-149",
"legalNumberOfEmployeeRange": "100-249",
"effectiveBeneficiary": 0,
"kycLevel": 2,
"kycReview": 0,
"kycReviewComment": "",
"isFreezed": 0,
"isFrozen": null,
"language": "",
"optInMailing": null,
"sepaCreditorIdentifier": "",
"taxNumber": "",
"taxResidence": "",
"position": "",
"personalAssets": "",
"createdDate": "2024-02-15 09:10:05",
"modifiedDate": "0000-00-00 00:00:00",
"walletCount": 0,
"payinCount": 0,
"totalRows": "1",
"activityOutsideEu": 1,
"economicSanctions": 0,
"residentCountriesSanctions": 0,
"involvedSanctions": 0,
"entitySanctionsQuestionnaire": 1,
"address3": null,
"timezone": null,
"occupationType": "",
"isOnStockExchange": 0,
"secondaryAddress1": "",
"secondaryAddress2": "",
"secondaryAddress3": "",
"secondaryPostcode": "",
"secondaryCity": "",
"secondaryState": "",
"secondaryCountry": "",
"clientId": "929252",
"sanctionsQuestionnaireDate": null,
"codeStatus": "110009",
"informationStatus": "",
"legalSectorType": "NAF",
"sourceOfFunds": "",
"occupationCategory": null,
"personalAssetsRange": null,
"monthlyIncomeRange": null,
"birthCityCode": null
}
]
}
```
Endpoint: [`/users`](/api-reference/pci-dss-dev.html#tag/Users/postUsers){target="\_self"}
Here is an example of `{payload}`:
```json [JSON]
{
"userTypeId": 2,
"specifiedUSPerson": 0,
"email": "contact.company@example.com",
"address1": "56 Bluewoods lane",
"postcode": "75000",
"city": "Paris",
"country": "FR",
"phone": "+33102030405",
"legalName": "Treehouse Company",
"legalRegistrationNumber": "42877171100028",
"legalTvaNumber": "FR27807465059",
"legalRegistrationDate": "2007-10-24",
"legalShareCapital": 4236474,
"legalForm": "5510",
"legalAnnualTurnOver": "100-249",
"legalNetIncomeRange": "50-149",
"legalNumberOfEmployeeRange": "100-249",
"legalSectorType": "NAF",
"legalSector": "1234F",
"entitySanctionsQuestionnaire": 1,
"activityOutsideEu": 1,
"economicSanctions": 0,
"residentCountriesSanctions": 0,
"involvedSanctions": 0
}
```
Returns a User object:
```json [JSON]
{
"users": [
{
"userId": 100138128,
"userTypeId": 2,
"userStatus": "VALIDATED",
"userTag": "",
"parentUserId": 0,
"parentType": "",
"controllingPersonType": 0,
"employeeType": 0,
"specifiedUSPerson": 0,
"title": "",
"firstname": "",
"lastname": "",
"middleNames": "",
"birthday": "0000-00-00",
"email": "contact.company@example.com",
"address1": "56 Bluewoods lane",
"address2": "",
"postcode": "75000",
"city": "Paris",
"state": "",
"country": "FR",
"countryName": "France",
"phone": "+33102030405",
"mobile": "",
"nationality": "",
"nationalityOther": "",
"placeOfBirth": "",
"birthCountry": "",
"occupation": "",
"incomeRange": "",
"legalName": "Treehouse Company",
"legalNameEmbossed": "Treehouse Company",
"legalRegistrationNumber": "42877171100028",
"legalTvaNumber": "FR27807465XX",
"legalRegistrationDate": "2007-10-24",
"legalForm": "5510",
"legalShareCapital": 4236474,
"entityType": null,
"legalSector": "1234F",
"legalAnnualTurnOver": "100-249",
"legalNetIncomeRange": "50-149",
"legalNumberOfEmployeeRange": "100-249",
"effectiveBeneficiary": 0,
"kycLevel": 2,
"kycReview": 0,
"kycReviewComment": "",
"isFreezed": 0,
"isFrozen": null,
"language": "",
"optInMailing": null,
"sepaCreditorIdentifier": "",
"taxNumber": "",
"taxResidence": "",
"position": "",
"personalAssets": "",
"createdDate": "2024-02-15 09:10:05",
"modifiedDate": "0000-00-00 00:00:00",
"walletCount": 0,
"payinCount": 0,
"totalRows": "1",
"activityOutsideEu": 1,
"economicSanctions": 0,
"residentCountriesSanctions": 0,
"involvedSanctions": 0,
"entitySanctionsQuestionnaire": 1,
"address3": null,
"timezone": null,
"occupationType": "",
"isOnStockExchange": 0,
"secondaryAddress1": "",
"secondaryAddress2": "",
"secondaryAddress3": "",
"secondaryPostcode": "",
"secondaryCity": "",
"secondaryState": "",
"secondaryCountry": "",
"clientId": "929252",
"sanctionsQuestionnaireDate": null,
"codeStatus": "110009",
"informationStatus": "",
"legalSectorType": "NAF",
"sourceOfFunds": "",
"occupationCategory": null,
"personalAssetsRange": null,
"monthlyIncomeRange": null,
"birthCityCode": null
}
]
}
```
Treezor also sends a [`user.create`](./events#user-create) webhook.
## Checking for veracity
When onboarding a Legal Entity, checking for the veracity of the provided information is key.
Treezor offers a dedicated endpoint to help you in checking these.
### Query parameters
Here are the necessary parameters to pass in the queryString.
| Attribute | Type | Description |
|--- |--- |--- |
| `country` | string | The country of registration of the legal entity. |
| `vatNumber` | string | The VAT number of the legal entity. Required if the `registrationNumber` is left empty. |
| `registrationNumber` | string | The registration number (e.g., SIREN) of the legal entity. Required if the `vatNumber` is left empty. |
### Request examples
Endpoint: [`/v1/businesssearchs`](/api-reference/api-endpoints.html#tag/Businesses/searchBusiness){target="\_self"}
Using the `vatNumber`:
```bash [CURL]
curl -X GET '{baseUrl}/v1/businesssearchs?country={country}&vatNumber={vatNumber}' \
--header 'Authorization: Bearer {accessToken}'
```
Or alternatively, using the `registrationNumber`:
```bash [CURL]
curl -X GET '{baseUrl}/v1/businesssearchs?country={country}®istrationNumber={registrationNumber}' \
--header 'Authorization: Bearer {accessToken}'
```
Returns the Business Search object that contains everything *CreditSafe* knows about this business. You can cross-check these with other reliable source of information (such as [infogreffe.fr](https://www.infogreffe.fr/) or [societe.com](https://www.societe.com/)).
```json [JSON]
{
"businesssearchs": [
{
"legalName": "Treehouse Company",
"phone": "",
"legalTvaNumber": "FR018798XXXXX",
"legalRegistrationNumber": "879804805XXXXX",
"status": "I",
"officeType": "1",
"safeNumber": "FR30XXXXXXX",
"activityType": "6312Z",
"externalId": "FR-X-87980480XXXXXXX",
"address1": "26 Willow Road",
"postcode": "75000",
"city": "PARIS",
"state": "ILE DE FRANCE",
"country": "FR",
"tradename": "Treehouse Company"
}
]
}
```
**Information – This endpoint relies on *CreditSafe***
Despite *CreditSafe*'s best efforts, some information may be inaccurate or up to 72 hours outdated.
## Finding the legal representatives
Treezor offers an endpoint to quickly identify the legal representatives of the Legal Entity.
### Query parameters
Here are the necessary parameters to pass in the queryString.
| Attribute | Type | Description |
|--- |--- |--- |
| `country` | string | The country of registration of the legal entity. |
| `vatNumber` | string | The VAT number of the legal entity. Required if the `registrationNumber` is left empty. |
| `registrationNumber` | string | The registration number (e.g., SIREN) of the legal entity. Required if the `vatNumber` is left empty. |
### Request examples
Endpoint: [`/v1/businessinformations`](/api-reference/api-endpoints.html#tag/Businesses/getBusinessInfo){target="\_self"}
Using the `vatNumber`:
```bash [CURL]
curl -X GET {baseUrl}/v1/businessinformations?country={country}&vatNumber={vatNumber} \
--header 'Authorization: Bearer {accessToken}'
```
Or alternatively, using the `registrationNumber`:
```bash [CURL]
curl -X GET '{baseUrl}/v1/businessinformations?country={country}®istrationNumber={registrationNumber}' \
--header 'Authorization: Bearer {accessToken}'
```
Returns the Business Information object, with the `users` attribute, which contains an array of representatives.
```json [JSON]
{
"businessinformations": [
{
"legalName": "Treehouse Company",
"legalRegistrationNumber": "807465059XXXX",
"legalRegistrationDate": "2014/10/29",
"legalForm": "5710",
"legalShareCapital": "",
"legalSector": "",
"legalAnnualTurnOver": "100-249",
"legalNetIncomeRange": "0-4",
"legalNumberOfEmployeeRange": "100-249",
"phone": "0102030405",
"email": "",
"address1": "33 Rosewood Lane",
"postcode": "75000",
"city": "PARIS",
"state": "Ile-de-France",
"country": "FR",
"status": "A",
"tradename": "Treehouse Company",
"users": [
{
"firstname": "",
"lastname": "",
"fullnames": "M Alex Oak",
"birthday": "1974-12-30T00:00:00Z",
"parentType": "Managing director",
"userTypeId": 2
},
{
"firstname": "",
"lastname": "",
"fullnames": "M Chris Willow",
"birthday": "1982-07-26T00:00:00Z",
"parentType": "President",
"userTypeId": 2
},
// More users can be returned
]
}
]
}
```
**Information – Children relationship for legal representatives**
The legal representatives and majority shareholders must be created as [Physical Users](/guide/users/physical) and [associated](/guide/users/parent-children) to the Legal Entity.
**Information – This endpoint relies on *CreditSafe***
Despite *CreditSafe*'s best efforts, some information may be inaccurate or up to 72 hours outdated.
## Sanctions and embargo
Some legal entities may be obligated to complete a due diligence questionnaire regarding sanctions and embargoes. Treezor provides a series of parameters for your end users to declare this information directly through the API.
The need to answer the questionnaire concerns:
* Legal entities (`userType` set to `2`, `3`, or `4`)
* Self-employed individuals (i.e., individuals with a `legalForm` set to `1000`)
More information is available in the [KYB - Embargo survey](https://treezor.zendesk.com/hc/en-us/articles/18030546139420-KYB-Embargo-survey) article of the Support Center.
### Filling out the questionnaire
To fill out the questionnaire through the API, collect the information while creating a user ([`/v1/users`](/api-reference/api-endpoints.html#tag/Users/postUsers){target="\_self"}) or requesting a user update ([`/v1/users/{userId}`](/api-reference/api-endpoints.html#tag/Users/putUser){target="\_self"}).
Through the collected answers, the User must:
1. Specify for which part of the entity the user answers the questionnaire (`entitySanctionsQuestionnaire`).
2. Indicate whether they have activity outside the European Union (`activityOutsideEu`).
3. If they operate outside the EU, answer the questions regarding economics, resident countries, and involved sanctions.
#### Parameters
Below are the parameters available for the sanctions and embargo questionnaire.
| Attribute | Type | Description |
| --- | --- | --- |
| `entitySanctionsQuestionnaire` | integer | Defines for which part of the entity the user answers the questionnaire (and therefore the scope to which the `activityOutsideEu` field applies): `1` – Only the legal entity`2` – The legal entity and all its subsidiaries held at 100%`3` – The legal entity and all its subsidiaries held at 50% or more`4` – The legal entity and a list of subsidiaries |
| `activityOutsideEu` | integer | Whether the entity and its business units, subsidiaries, and joint ventures have a commercial activity outside the European Union. Can be: `0` – False`1` – True. When set to this value, the next attributes become mandatory. |
| `economicSanctions` | integer | Whether the entity, its subsidiaries, entities, employees, directors, beneficial owners, or joint ventures are subject to Economic Sanctions. Can be: `0` – False`1` – True |
| `residentCountriesSanctions` | integer | Whether the entity, its subsidiaries, or joint ventures, located within or operating from any countries or territories are subject to Comprehensive Sanctions. Can be: `0` – False`1` – True |
| `involvedSanctions` | integer | Whether the entity, its subsidiaries, or joint ventures, are engaged in transactions, investments, business, or other dealings that directly or indirectly involve or benefit: Any countries or territories subject to Comprehensive Sanctions, or Any person or entity which is the target of any Sanctions (“Sanctioned Targets”). Can be: `0` – False`1` – True |
#### Example
Here is an example of a legal entity creation with the questionnaire.
Endpoint: [`/v1/users`](/api-reference/api-endpoints.html#tag/Users/postUsers){target="\_self"}
Here is an example of `{payload}`:
```json [JSON] {22-26}
{
"userTypeId": 2,
"specifiedUSPerson": 0,
"email": "contact.company@example.com",
"address1": "56 Bluewoods lane",
"postcode": "75000",
"city": "Paris",
"country": "FR",
"phone": "+33102030405",
"legalName": "Treehouse Company",
"legalRegistrationNumber": "42877171100028",
"legalTvaNumber": "FR27807465059",
"legalRegistrationDate": "2007-10-24",
"legalShareCapital": 4236474,
"legalNetIncomeRange": "50-149",
"legalNumberOfEmployeeRange": "100-249",
"legalSectorType": "NAF",
"legalForm": "5499",
"legalSector": "2051Z",
"legalAnnualTurnOver": "1000-2999",
"entityType": 4,
"entitySanctionsQuestionnaire": 1,
"activityOutsideEu": 1,
"economicSanctions": 0,
"residentCountriesSanctions": 0,
"involvedSanctions": 0
}
```
Returns a User object:
```json [JSON] {65-69}
{
"users": [
{
"userId": 100138128,
"userTypeId": 2,
"userStatus": "VALIDATED",
"userTag": "",
"parentUserId": 0,
"parentType": "",
"controllingPersonType": 0,
"employeeType": 0,
"specifiedUSPerson": 0,
"title": "",
"firstname": "",
"lastname": "",
"middleNames": "",
"birthday": "0000-00-00",
"email": "contact.company@example.com",
"address1": "56 Bluewoods lane",
"address2": "",
"postcode": "75000",
"city": "Paris",
"state": "",
"country": "FR",
"countryName": "France",
"distributionCountry": null,
"phone": "+33102030405",
"mobile": "",
"nationality": "",
"nationalityOther": "",
"placeOfBirth": "",
"birthCountry": "",
"occupation": "",
"incomeRange": "",
"legalName": "Treehouse Company",
"legalNameEmbossed": "Treehouse Company",
"legalRegistrationNumber": "42877171100028",
"legalTvaNumber": "FR27807465XX",
"legalRegistrationDate": "2007-10-24",
"legalForm": "5499",
"legalShareCapital": 4236474,
"entityType": "4",
"legalSector": "2051Z",
"legalAnnualTurnOver": "1000-2999",
"legalNetIncomeRange": "50-149",
"legalNumberOfEmployeeRange": "100-249",
"effectiveBeneficiary": 0,
"kycLevel": 2,
"kycReview": 0,
"kycReviewComment": "",
"isFreezed": 0,
"isFrozen": null,
"language": "",
"optInMailing": null,
"sepaCreditorIdentifier": "",
"taxNumber": "",
"taxResidence": "",
"position": "",
"personalAssets": "",
"createdDate": "2024-02-15 09:10:05",
"modifiedDate": "0000-00-00 00:00:00",
"walletCount": 0,
"payinCount": 0,
"totalRows": "1",
"activityOutsideEu": 1,
"economicSanctions": 0,
"residentCountriesSanctions": 0,
"involvedSanctions": 0,
"entitySanctionsQuestionnaire": 1,
"address3": null,
"timezone": null,
"occupationType": "",
"isOnStockExchange": 0,
"secondaryAddress1": "",
"secondaryAddress2": "",
"secondaryAddress3": "",
"secondaryPostcode": "",
"secondaryCity": "",
"secondaryState": "",
"secondaryCountry": "",
"clientId": "929252",
"sanctionsQuestionnaireDate": null,
"codeStatus": "110009",
"informationStatus": "",
"legalSectorType": "NAF",
"sourceOfFunds": "",
"occupationCategory": null,
"personalAssetsRange": null,
"monthlyIncomeRange": null,
"birthCityCode": null
}
]
}
```
Endpoint: [`/users`](/api-reference/pci-dss-dev.html#tag/Users/postUsers){target="\_self"}
Here is an example of `{payload}`:
```json [JSON] {22-26}
{
"userTypeId": 2,
"specifiedUSPerson": 0,
"email": "contact.company@example.com",
"address1": "56 Bluewoods lane",
"postcode": "75000",
"city": "Paris",
"country": "FR",
"phone": "+33102030405",
"legalName": "Treehouse Company",
"legalRegistrationNumber": "42877171100028",
"legalTvaNumber": "FR27807465059",
"legalRegistrationDate": "2007-10-24",
"legalShareCapital": 4236474,
"legalNetIncomeRange": "50-149",
"legalNumberOfEmployeeRange": "100-249",
"legalSectorType": "NAF",
"legalForm": "5499",
"legalSector": "2051Z",
"legalAnnualTurnOver": "1000-2999",
"entityType": 4,
"entitySanctionsQuestionnaire": 1,
"activityOutsideEu": 1,
"economicSanctions": 0,
"residentCountriesSanctions": 0,
"involvedSanctions": 0
}
```
Returns a User object:
```json [JSON] {65-69}
{
"users": [
{
"userId": 100138128,
"userTypeId": 2,
"userStatus": "VALIDATED",
"userTag": "",
"parentUserId": 0,
"parentType": "",
"controllingPersonType": 0,
"employeeType": 0,
"specifiedUSPerson": 0,
"title": "",
"firstname": "",
"lastname": "",
"middleNames": "",
"birthday": "0000-00-00",
"email": "contact.company@example.com",
"address1": "56 Bluewoods lane",
"address2": "",
"postcode": "75000",
"city": "Paris",
"state": "",
"country": "FR",
"countryName": "France",
"distributionCountry": null,
"phone": "+33102030405",
"mobile": "",
"nationality": "",
"nationalityOther": "",
"placeOfBirth": "",
"birthCountry": "",
"occupation": "",
"incomeRange": "",
"legalName": "Treehouse Company",
"legalNameEmbossed": "Treehouse Company",
"legalRegistrationNumber": "42877171100028",
"legalTvaNumber": "FR27807465XX",
"legalRegistrationDate": "2007-10-24",
"legalForm": "5499",
"legalShareCapital": 4236474,
"entityType": "4",
"legalSector": "2051Z",
"legalAnnualTurnOver": "1000-2999",
"legalNetIncomeRange": "50-149",
"legalNumberOfEmployeeRange": "100-249",
"effectiveBeneficiary": 0,
"kycLevel": 2,
"kycReview": 0,
"kycReviewComment": "",
"isFreezed": 0,
"isFrozen": null,
"language": "",
"optInMailing": null,
"sepaCreditorIdentifier": "",
"taxNumber": "",
"taxResidence": "",
"position": "",
"personalAssets": "",
"createdDate": "2024-02-15 09:10:05",
"modifiedDate": "0000-00-00 00:00:00",
"walletCount": 0,
"payinCount": 0,
"totalRows": "1",
"activityOutsideEu": 1,
"economicSanctions": 0,
"residentCountriesSanctions": 0,
"involvedSanctions": 0,
"entitySanctionsQuestionnaire": 1,
"address3": null,
"timezone": null,
"occupationType": "",
"isOnStockExchange": 0,
"secondaryAddress1": "",
"secondaryAddress2": "",
"secondaryAddress3": "",
"secondaryPostcode": "",
"secondaryCity": "",
"secondaryState": "",
"secondaryCountry": "",
"clientId": "929252",
"sanctionsQuestionnaireDate": null,
"codeStatus": "110009",
"informationStatus": "",
"legalSectorType": "NAF",
"sourceOfFunds": "",
"occupationCategory": null,
"personalAssetsRange": null,
"monthlyIncomeRange": null,
"birthCityCode": null
}
]
}
```
Treezor also sends a [`user.create`](./events#user-create) webhook.
---
---
url: /guide/transfers/mandates.md
description: >-
Technical guide for creating and managing mandates to emit SEPA Direct Debit
(SDDE). Includes required parameters, request structure, and response
examples.
---
# Mandates
Mandates allow [Legal Entities](/guide/users/legal-entity) to initiate a transfer of funds from somebody else's account, to theirs.
The transfer is made using [SEPA Direct Debit (SDDE)](direct-debit#emitted-direct-debits-sdde) and can be used to receive one-time or recurring payments.
**Information – SEPA Creditor Identifier mandatory in France**
In France, only companies holding a [SEPA creditor identifier (SCI)](/guide/overview/glossary#sepa-creditor-identifier-sci) are allowed to use Mandates and [SDDE](direct-debit#emitted-direct-debits-sdde). A physical person cannot be allowed to actively retrieve funds from somebody else's account.
**Important – Mandates should be kept as proofs in case of litigation**
As litigation rules of the SEPA Network are generally in favor of the debtor, ensure you keep Mandates to be used as proof if the need arises.
## Mandate object
```json [JSON]
{
"mandateId": 0,
"title": "string",
"legalInformations": "string",
"uniqueMandateReference": "string",
"mandateStatus": "PENDING",
"userId": 0,
"debtorName": "string",
"debtorAddress": "string",
"debtorCity": "string",
"debtorZipCode": "string",
"debtorCountry": "string",
"debtorIban": "string",
"debtorBic": "string",
"sequenceType": "string",
"creditorName": "string",
"sepaCreditorIdentifier": "string",
"creditorAddress": "string",
"creditorCity": "string",
"creditorZipCode": "string",
"creditorCountry": "string",
"signatureDate": "string",
"debtorSignatureIp": "string",
"signed": 0,
"debtorIdentificationCode": "string",
"debtorReferencePartyName": "string",
"debtorReferenceIdentificationCode": "string",
"creditorReferencePartyName": "string",
"creditorReferenceIdentificationCode": "string",
"contractIdentificationNumber": "string",
"contractDescription": "string",
"isPaper": true,
"sddType": "core",
"revocationSignatureDate": null,
"createdIP": "string",
"createdDate": "string",
"modifiedDate": "string",
"codeStatus": 0,
"informationStatus": "string",
"userIdUltimateCreditor": 0
}
```
**API – API Reference available**
For a complete list of Mandate attributes, check the [Mandates](/api-reference/api-endpoints.html#tag/Mandates){target="\_self"} section of the API Reference.
## Creation
As of today, Treezor doesn't offer electronic signature services. Therefore, `isPaper` should always be `true` and you should assume the physical mandate signature. **This paper Mandate must include the UMR** (`uniqueMandateReference` attribute of the Mandate object).
### Mandatory parameters
| Attribute | Type | Description |
| --- | --- | --- |
| `sddType` | string | Defines the type of SDD. May be:`core` – To debit individuals (physical persons).`b2b` – To debit legal entities. |
| `sequenceType` | string | Defines whether the debtor will be debited multiple times: `one-off` – For a one-time payment.`recurrent` – For recurring payments. |
| `isPaper` | boolean | Indicates whether the mandate is a paper-based document or electronically signed. **Always set to true**. |
| `userId` | integer | The unique identifier of the [end user](/guide/users/introduction) requesting the SDD. |
| `debtorName` | string | Full name of the debited end user (person or entity). Format: alphanumeric with **at least 3 alphabetic characters**. |
| `debtorAddress` | string | The address of the debited end user. |
| `debtorCity` | string | City in which the debited end user is domiciled. |
| `debtorZipCode` | string | Postcode of the city in which the debited end user is domiciled. |
| `debtorCountry` | string | Country in which the debited end user is domiciled. Format: ISO 3166-1 alpha-2. |
| `debtorIban` | string | [IBAN](/guide/wallets/iban) of the debited end user. |
| `debtorBic` | string | The BIC (or SWIFT) of the debited end user. |
| `signatureDate` | string | Date on which the Mandate has been signed by the end user. Format: YYYY-MM-DD |
**API – API Reference available**
For a complete list of Mandate attributes, check the [Mandates](/api-reference/api-endpoints.html#tag/Mandates){target="\_self"} section of the API Reference.
### Request example
Endpoint: [`/v1/mandates`](/api-reference/api-endpoints.html#tag/Mandates/postMandates){target="\_self"}
```bash [CURL]
curl -X POST '{baseUrl}/v1/mandates' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"sddType": "core",
"isPaper": true,
"userId": 123456,
"debtorName": "Alex Oak",
"debtorAddress": "99 Rosewood lane",
"debtorCity": "Paris",
"debtorZipCode": "75001",
"debtorCountry": "FR",
"debtorIban": "FR763000100794123XXXXXXXXXX",
"debtorBic": "BDFXXXXXXXXX",
"sequenceType": "recurrent",
"signatureDate": "2020-04-01",
"createdIp": "0.0.0.0"
}
```
Returns the Mandate object, with the corresponding `mandateId`.
```json [JSON]
{
"mandates": [
{
"mandateId": 2356,
"title": "M",
"legalInformations": "Treezor",
"uniqueMandateReference": "79069343D1A80C931FABBC5813E3DB",
"mandateStatus": "PENDING",
"userId": 1529390,
"debtorName": "Alex Oak",
"debtorAddress": "99 Rosewood lane",
"debtorCity": "Paris",
"debtorZipCode": "75001",
"debtorCountry": "FR",
"debtorIban": "FR763000100794123XXXXXXXX",
"debtorBic": "BDFXXXXXX",
"sequenceType": "recurrent",
"creditorName": "Treezor",
"sepaCreditorIdentifier": "FR90ZZZ874785",
"creditorAddress": "99 Rosewood lane",
"creditorCity": "Paris",
"creditorZipCode": "75001",
"creditorCountry": "FR",
"signatureDate": "2020-04-01",
"debtorSignatureIp": "",
"signed": 0,
"revocationSignatureDate": null,
"debtorIdentificationCode": "",
"debtorReferencePartyName": "",
"debtorReferenceIdentificationCode": "",
"creditorReferencePartyName": "",
"creditorReferenceIdentificationCode": "",
"contractIdentificationNumber": "",
"contractDescription": "",
"isPaper": true,
"sddType": "core",
"createdIP": "10.xx.x.37",
"createdDate": null,
"modifiedDate": "",
"codeStatus": 220001,
"informationStatus": "Mandat complété",
"userIdUltimateCreditor": 0
}
]
}
```
Treezor assumes you had it signed by the end user as requested, so you can now initiate the corresponding [SEPA Direct Debit](./direct-debit#emitted-direct-debits-sdde)
Treezor also sends a [`mandate.create`](events#mandate-create) webhook.
**Note – Contact Treezor if you encounter a `22026` error**
This error indicates `Unable to create the mandate. User does not have sepa creditor identifier`. Contact your *Treezor Account Manager* to set up an [SCI (SEPA Creditor Identifier)](/guide/overview/glossary#sepa-creditor-identifier-sci) for that User.
## Endpoints
| Endpoint | [Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/v1/mandates`](/api-reference/api-endpoints.html#tag/Mandates/postMandates){target="\_self"} Create a mandate | `read_write` |
| [`/v1/mandates`](/api-reference/api-endpoints.html#tag/Mandates/getMandates){target="\_self"} Search for mandates | `read_only` |
| [`/v1/mandates/{mandateId}`](/api-reference/api-endpoints.html#tag/Mandates/getMandate){target="\_self"} Retrieve a mandate | `read_only` |
| [`/v1/mandates/{mandateId}`](/api-reference/api-endpoints.html#tag/Mandates/deleteMandate){target="\_self"} Revoke a mandate | `read_write` |
---
---
url: /guide/users/physical.md
description: >-
Technical guide for creating physical users, including anonymous and
self-employed users, via the Treezor API. Includes required parameters,
request structure, and response examples.
---
# Physical Users
A **Physical User** is an individual. This kind of end users can also be self-employed professionals, or shareholders and legal representatives of a [Legal Entity](./legal-entity).
Declarative data to collect depends on whether the user is to go through [verification](/guide/user-verification/introduction).
## Creation
### Parameters
Below are the necessary parameters to create Physical Users.
While some parameters might not be required by the API, they are necessary when it comes to the [KYC validation](/guide/user-verification/introduction) of the user. Data should be collected from the creation (or you may have to update the user information later on).
| Attribute | Type | Description |
|--- |--- |--- |
| `userTypeId` | integer | Must be `1` for physical users. |
| `specifiedUSPerson` | integer | Indicates if the user [is a US Person](/guide/users/tax-residence). |
| `email` | string | The email of the user, which must be [unique and valid](./introduction#using-unique-and-valid-email-addresses) and can't exceed 200 characters. |
| `title` (required for KYC) | string | The title of the user. Can be one of the following: `M` – Stands for mister (Mr.)`MME` – Stands for missus (Mrs.)`MLLE` – Stands for miss`MX` – Gender-neutral title |
| `firstname` (required for KYC) | string | The first name of the Physical User. |
| `lastname` (required for KYC) | string | The last name of the Physical User. |
| `birthday` (required for KYC) | string | The birthdate of the Physical User. Format: `YYYY-MM-DD` |
| `placeOfBirth` (required for KYC) | string | The user's place of birth. |
| `birthCountry` (required for KYC) | string | The user's birth country (format ISO 3166-1 alpha-2) |
| `nationality` (required for KYC) | string | The user's nationality (format ISO 3166-1 alpha-2) |
| `mobile` | string | The user's mobile phone number, in international E.164 format. |
| `address{1-3}` (required for KYC) | string | The user's postal address. The max value for each address line is 150 characters. If you're issuing cards, see the [Data Formats](/guide/api-basics/data-format#addresses) article for information on further limitations. |
| `postcode` (required for KYC) | string | The user's address postcode. |
| `city` (required for KYC) | string | The user's address city. |
| `country` (required for KYC) | string | The user's address country (format ISO 3166-1 alpha-2) |
| `phone` (required for KYC) | string | The User phone number in [international E.164 format](https://en.wikipedia.org/wiki/E.164). |
| `occupationType` | string | Deprecated, use `occupationCategory` instead. |
| `occupationCategory` | integer | Type of occupation of the user. Might be required for KYC, please refer to your *KYC Form*. See [occupation category](#occupation-category-occupationcategory) for the list of values. |
| `incomeRange` (required for KYC) | string | Deprecated, use `monthlyIncomeRange` instead. |
| `monthlyIncomeRange` | integer | Net monthly income of the user. Might be required for KYC, please refer to your *KYC Form*. See [monthly income range](#monthly-income-range-monthlyincomerange) for the list of values.|
| `personalAssets` | string | Deprecated, use `personalAssetsRange` instead. |
| `personalAssetsRange` | integer | The personal assets of the user. Might be required for KYC, please refer to your *KYC Form*. See [personal assets range](#personal-assets-range-personalassetsrange) for the list of values. |
| `distributionCountry` | string | The country in which the end user is using your services. This field is only required when you operate in multiple countries. See [Distribution country](/guide/users/introduction#distribution-country-distributioncountry) for more information. |
**Information – Refer to your KYC Form for declarative data**
Declarative data to submit depends on the type of user, the country you're operating in, the regulations linked to your use case, etc. Treezor Compliance team provides you with your KYC Form listing what needs to be submitted.
#### Occupation Category (`occupationCategory`)
Below is the list of values for the occupation category.
| Value | Label |
|:-------:|--------------------------------------------|
| `1` | Pupil, student or apprentice |
| `2` | Beneficiaries of unemployment assistance |
| `3` | Without professional activity |
| `4` | Executive and Intellectual Profession in the private sector |
| `5` | Employee in the private sector |
| `6` | Business owner |
| `7` | Executive and Intellectual Profession in the public sector |
| `8` | Employee and Officer in the public sector |
| `9` | Farmer |
| `10` | Self-employed |
| `11` | Craftsman |
| `12` | Shopkeeper and related professions |
| `13` | Freelance profession |
| `14` | Medical freelance professions (or medical practitioners) |
| `15` | Retired |
#### Personal Assets Range (`personalAssetsRange`)
Below is the list of values for the personal assets range.
| Value | Label |
|:-------:|---------------------------------------|
| `0` | None |
| `1` | 0 to 15 000 Euros |
| `2` | From 15 001 Euros to 50 000 Euros |
| `3` | From 50 001 Euros to 150 000 Euros |
| `4` | From 150 001 Euros to 350 000 Euros |
| `5` | From 350 001 Euros to 750 000 Euros |
| `6` | From 750 001 Euros to 1 500 000 Euros |
| `7` | Greater than 1 500 000 Euros |
#### Monthly Income Range (`monthlyIncomeRange`)
Below is the list of values for the net monthly income range.
| Value | Label |
|:-------:|--------------------------------|
| `1` | 0 - 999 Euros per month |
| `2` | 1000 - 1800 Euros per month |
| `3` | 1801 - 3500 Euros per month |
| `4` | 3501 - 5000 Euros per month |
| `5` | 5001 - 6500 Euros per month |
| `6` | 6501 - 10000 Euros per month |
| `7` | Greater than 10000 Euros per month |
### Request example
Endpoint: [`/v1/users`](/api-reference/api-endpoints.html#tag/Users/postUsers){target="\_self"}
Here is an example of `{payload}`:
```json [JSON]
{
"userTypeId": 1,
"specifiedUSPerson": 0,
"firstname": "Alex",
"lastname": "Oak",
"birthday": "1982-05-31",
"placeOfBirth": "Edgewood",
"birthCountry": "FR",
"nationality": "FR",
"email": "alex.oak@example.com",
"address1": "33 rosewood road",
"postcode": "75017",
"city": "Paris",
"country": "FR",
"phone": "+3311111111"
}
```
Returns a User object, with both its `kycLevel` and `kycReview` initially set to `NONE`. The user now needs to [go through the KYC validation](/guide/user-verification/introduction) process.
```json [JSON] {48,49}
{
"users": [
{
"userId": 8327278,
"userTypeId": 1,
"userStatus": "VALIDATED",
"userTag": "",
"parentUserId": 0,
"parentType": "",
"controllingPersonType": 0,
"employeeType": 0,
"specifiedUSPerson": 0,
"title": "",
"firstname": "Alex",
"lastname": "Oak",
"middleNames": "",
"birthday": "1982-05-31",
"email": "alex.oak@example.com",
"address1": "33 rosewood road",
"address2": "",
"postcode": "75017",
"city": "Paris",
"state": "",
"country": "FR",
"countryName": "France",
"distributionCountry": null,
"phone": "+3311111111",
"mobile": "",
"nationality": "FR",
"nationalityOther": "",
"placeOfBirth": "Paris",
"birthCountry": "FR",
"occupation": "",
"incomeRange": "0-18",
"legalName": "",
"legalNameEmbossed": "",
"legalRegistrationNumber": "",
"legalTvaNumber": "",
"legalRegistrationDate": "0000-00-00",
"legalForm": "",
"legalShareCapital": 0,
"entityType": 0,
"legalSector": "",
"legalAnnualTurnOver": "",
"legalNetIncomeRange": "",
"legalNumberOfEmployeeRange": "",
"effectiveBeneficiary": 0,
"kycLevel": 0,
"kycReview": 0,
"kycReviewComment": "",
"isFreezed": 0,
"isFrozen": null,
"language": "",
"optInMailing": null,
"sepaCreditorIdentifier": "",
"taxNumber": "",
"taxResidence": "",
"position": "",
"personalAssets": "",
"createdDate": "2024-11-13 07:40:10",
"modifiedDate": "0000-00-00 00:00:00",
"walletCount": 0,
"payinCount": 0,
"totalRows": "1",
"activityOutsideEu": 0,
"economicSanctions": 0,
"residentCountriesSanctions": 0,
"involvedSanctions": 0,
"address3": null,
"timezone": null,
"occupationType": "",
"isOnStockExchange": 0,
"secondaryAddress1": "",
"secondaryAddress2": "",
"secondaryAddress3": "",
"secondaryPostcode": "",
"secondaryCity": "",
"secondaryState": "",
"secondaryCountry": "",
"clientId": "929252",
"sanctionsQuestionnaireDate": null,
"codeStatus": "110009",
"informationStatus": "",
"legalSectorType": "",
"sourceOfFunds": "",
"distributionCountry": null,
"entitySanctionsQuestionnaire": 0,
"occupationCategory": 5,
"personalAssetsRange": 2,
"monthlyIncomeRange": 2,
"birthCityCode": null
}
]
}
```
Endpoint: [`/users`](/api-reference/pci-dss-dev.html#tag/Users/postUsers){target="\_self"}
Here is an example of `{payload}`:
```json [JSON]
{
"userTypeId": 1,
"specifiedUSPerson": 0,
"firstname": "Alex",
"lastname": "Oak",
"birthday": "1982-05-31",
"placeOfBirth": "Edgewood",
"birthCountry": "FR",
"nationality": "FR",
"email": "alex.oak@example.com",
"address1": "33 rosewood road",
"postcode": "75017",
"city": "Paris",
"country": "FR",
"phone": "+3311111111"
}
```
Returns a User object, with both its `kycLevel` and `kycReview` initially set to `NONE`. The user now needs to [go through the KYC validation](/guide/user-verification/introduction) process.
```json [JSON] {48,49}
{
"users": [
{
"userId": 8327278,
"userTypeId": 1,
"userStatus": "VALIDATED",
"userTag": "",
"parentUserId": 0,
"parentType": "",
"controllingPersonType": 0,
"employeeType": 0,
"specifiedUSPerson": 0,
"title": "",
"firstname": "Alex",
"lastname": "Oak",
"middleNames": "",
"birthday": "1982-05-31",
"email": "alex.oak@example.com",
"address1": "33 rosewood road",
"address2": "",
"postcode": "75017",
"city": "Paris",
"state": "",
"country": "FR",
"countryName": "France",
"distributionCountry": null,
"phone": "+3311111111",
"mobile": "",
"nationality": "FR",
"nationalityOther": "",
"placeOfBirth": "Paris",
"birthCountry": "FR",
"occupation": "",
"incomeRange": "0-18",
"legalName": "",
"legalNameEmbossed": "",
"legalRegistrationNumber": "",
"legalTvaNumber": "",
"legalRegistrationDate": "0000-00-00",
"legalForm": "",
"legalShareCapital": 0,
"entityType": 0,
"legalSector": "",
"legalAnnualTurnOver": "",
"legalNetIncomeRange": "",
"legalNumberOfEmployeeRange": "",
"effectiveBeneficiary": 0,
"kycLevel": 0,
"kycReview": 0,
"kycReviewComment": "",
"isFreezed": 0,
"isFrozen": null,
"language": "",
"optInMailing": null,
"sepaCreditorIdentifier": "",
"taxNumber": "",
"taxResidence": "",
"position": "",
"personalAssets": "",
"createdDate": "2024-11-13 07:40:10",
"modifiedDate": "0000-00-00 00:00:00",
"walletCount": 0,
"payinCount": 0,
"totalRows": "1",
"activityOutsideEu": 0,
"economicSanctions": 0,
"residentCountriesSanctions": 0,
"involvedSanctions": 0,
"address3": null,
"timezone": null,
"occupationType": "",
"isOnStockExchange": 0,
"secondaryAddress1": "",
"secondaryAddress2": "",
"secondaryAddress3": "",
"secondaryPostcode": "",
"secondaryCity": "",
"secondaryState": "",
"secondaryCountry": "",
"clientId": "929252",
"sanctionsQuestionnaireDate": null,
"codeStatus": "110009",
"informationStatus": "",
"legalSectorType": "",
"sourceOfFunds": "",
"distributionCountry": null,
"entitySanctionsQuestionnaire": 0,
"occupationCategory": 5,
"personalAssetsRange": 2,
"monthlyIncomeRange": 2,
"birthCityCode": null
}
]
}
```
Treezor also sends a [`user.create`](./events#user-create) webhook.
## Anonymous Users
An Anonymous User is a user only represented by its unique email address. No other declarative data is required, nor is the [mandatory KYC validation](/guide/user-verification/introduction).
This specific user is intended for limited use cases such as:
* **Gift cards** which are not associated to a specific user.
* **Bulk card creation**, where the anonymous user is used as a placeholder until the card can be assigned to its owner.
**Information – Anonymous users have limited usage (not KYC-validated)**
* [Payment, withdrawal](/guide/cards/restrictions-limits#payment-withdrawal-limits), and [transfer](/guide/transfers/introduction) limits are highly restricted.
* The transaction can be refused if an address verification (AVS) occurs.
* [3DS verifications](/guide/cards/creation#enrolling-a-card-for-3d-secure) are rejected as no secondary means of validation are available.
### Parameters
| Attribute | Type | Description |
|--- |--- |--- |
| `userTypeId` | integer | Must be `1` for physical users. |
| `specifiedUSPerson` | integer | Indicates if the user [is a US Person](/guide/users/tax-residence). |
| `email` | string | The email of the anonymous user, which must be [unique and valid](./introduction#using-unique-and-valid-email-addresses) and can't exceed 200 characters. |
**Tip – User address must be unique even for bulk card creation**
When generating a batch of [Cards](/guide/cards/introduction) in advance and associating them to Anonymous Users, your can generate random and fictitious email addresses
### Request example
Endpoint: [`/v1/users`](/api-reference/api-endpoints.html#tag/Users/postUsers){target="\_self"}
Here is an example of `{payload}`:
```json [JSON]
{
"userTypeId": 1,
"specifiedUSPerson": 0,
"email": "anonymous@example.com"
}
```
Returns a User object if successful:
```json [JSON]
{
"users": [
{
"userId": "",
"userTypeId": 1,
"userStatus": "",
"specifiedUSPerson": 0,
"email": "anonymous@example.com",
// [...] some attributes are hidden
}
]
}
```
Endpoint: [`/users`](/api-reference/pci-dss-dev.html#tag/Users/postUsers){target="\_self"}
Here is an example of `{payload}`:
```json [JSON]
{
"userTypeId": 1,
"specifiedUSPerson": 0,
"email": "anonymous@example.com"
}
```
Returns a User object if successful:
```json [JSON]
{
"users": [
{
"userId": "",
"userTypeId": 1,
"userStatus": "",
"specifiedUSPerson": 0,
"email": "anonymous@example.com",
// [...] some attributes are hidden
}
]
}
```
Treezor also sends a [`user.create`](./events#user-create) webhook.
## Self-employed Users
Self-employed individuals are a specific case since they work for their own account. That makes them physical users (`userTypeId=1`) with many attributes of a legal entity. Therefore:
* The attributes required for [`/v1/users/{userId}/Kycreview`](/api-reference/api-endpoints.html#tag/User%20KYC%20Review/putKycreview){target="\_self"} cumulates the ones for the [creation of a physical user](#parameters) and [legal entities](/guide/users/legal-entity#parameters).
* Declarative data to submit is specific, you must refer to the KYC Form provided by Treezor.
Here are a few specificities regarding data to provide.
| Attribute | Type | Description |
|--- |--- |--- |
| `userTypeId` | integer | Must be `1` for self-employed users. |
| `email` | string | The email of the user, which must be valid and can't exceed 200 characters. |
| `specifiedUSPerson` | integer | Indicates if the user [is a US Person](/guide/users/tax-residence). |
| `legalForm` | integer | Must be one of the following values depending on the self-employed user `distributionCountry`: `IT` – `10001``DE` – `20001``ES` – `30001``FR` or other if in your KYC Form – `1000` |
| `address{1-3}` (required for KYC) | string | The user's **professional postal address**. See the [Data Formats](/guide/api-basics/data-format#addresses) article for information on limitations. |
| `secondaryAddress{1-3}` (required for KYC) | string | The user's **personal postal address**. See the [Data Formats](/guide/api-basics/data-format#addresses) article for information on limitations. |
| `postcode` (required for KYC) | string | The legal entity's address postcode. |
| `city` (required for KYC) | string | The legal entity's address city. |
| `country` (required for KYC) | string | The legal entity's address country (format ISO 3166-1 alpha-2) |
| `phone` (required for KYC) | string | The legal entity's phone number, in international E.164 format. |
| `legalName` (required for KYC) | string | The name of the company. |
| `legalRegistrationNumber` (required for KYC) | string | The registration number of the legal entity (e.g., SIREN/SIRET). |
| `legalForm` (required for KYC) | string | The legal category of the legal entity. See [Legal forms](./introduction#legal-forms-legalform) for more information. |
| `legalRegistrationDate` (required for KYC) | string | The registration date of the company. Format: YYYY-MM-DD. |
| `legalAnnualTurnOver` (required for KYC) | string | The annual turn over of the legal entity in k€, among the following ranges: `0-39`, `40-99`, `100-249`, `250-999`, `1000-2999`, `3000-9999`, `10000-99999`, and `100000-*` |
| `legalNetIncomeRange` (required for KYC) | string | The net income of the legal entity in k€, among the following ranges: `0-4`, `5-9`, `10-49`, `50-149`, `150-499`, and `500-*`. |
| `legalNumberOfEmployeeRange` (required for KYC) | string | The number of employees of the legal entity among the following ranges: `0`, `1-9`, `10-99`, `100-249`, and `250-*` |
| `legalSectorType` | string | Either `NAF` or `NACE`, qualifies the type of data in the `legalSector` field. |
| `legalSector` (required for KYC) | string | The business sector of the legal entity. Either a 4-digit code if NACE or a 5-digit code followed by an uppercase letter if [NAF](/guide/overview/glossary#nomenclature-activites-francaise-naf), depending on the value of the `legalSectorType`. |
| `distributionCountry` | string | The country in which the end user is using your services. This field is only required when you operate in multiple countries. See [Distribution country](/guide/users/introduction#distribution-country-distributioncountry) for more information. |
In addition, a self-employed user must answer the [Sanctions & Embargo questionnaire](/guide/users/legal-entity#sanctions-and-embargo) and provide their [Tax residence](/guide/users/tax-residence).
## Shareholders and Legal representatives
Among the Physical Users that can be created in Treezor, there is the case of the Shareholders and the Legal Representatives of a company.
These specific physical users, identified with the `parentType` attribute:
* Are attached to the [Legal entity](/guide/users/legal-entity) (the company) with a [parent-children relation](/guide/users/parent-children).
* May require more documents and declarative data to be verified.
---
---
url: /guide/transfers/scheduled-payments.md
description: >-
Technical guide for creating and managing Scheduled Payments (one-time or
recurring) for SEPA Credit Transfers and Wallet-to-Wallet Transfers. Includes
required parameters, request structure, and response examples.
---
# Scheduled Payments
Scheduled Payment orders allow you to plan a payment execution in the future, whether it is a unique operation or recurring ones. Scheduled Payments can be used for both [Payouts (SCTE)](/guide/transfers/credit-transfer#emitted-credit-transfers-scte) and [Wallet-to-Wallet Transfers](/guide/transfers/wallet-to-wallet#wallet-to-wallet-transfers).
The steps are as follows:
1. You create a Scheduled Payment order with the desired settings (type, dates, etc.)
2. The resulting Transfer(s) or Payout(s) occur at the scheduled date(s).
An error in the execution of the payment cancels the occurrence and adds it to the `failedPayment` attribute of the [Scheduled Payment](#scheduled-payment-object) object. In such cases, the end user must complete the payment manually.
**Information – Scheduled Payment is a Beta feature**
Please contact your *Treezor Account Manager* if you're interested in this feature.
## Attributes
Find below the list of attributes for the Scheduled Payment object.
| Attribute | Type | Description |
| --- | --- | --- |
| `id` | string | The unique identifier of the Scheduled Payment (UUIDv4). |
| `status` | string | The status of the Scheduled Payment, which is either `VALIDATED` or `CANCELED`. |
| `scheduledPaymentName` | string | The label describing the goal of the Scheduled Payment. |
| `walletId` | integer | The unique identifier of the Wallet to debit. |
| `beneficiaryType` | string | The type of beneficiary for the operation, which can be: `payout` – The Scheduled Payment targets an external account.`walletTransfer` – The Scheduled Payment targets another Wallet in your Treezor environment. |
| `beneficiary` | integer | The unique identifier of the beneficiary of the Scheduled Payment, which can be either `beneficiaryId` for Payouts or `beneficiaryWalletId` for Wallet-to-Wallet transfers. |
| `amount` | number | The amount of the Scheduled Payment. |
| `type` | string | The type of Scheduled Payment, which can be: `oneshot` – The payment will occur only once.`periodic` – The payment will occur periodically over a defined time frame. |
| `execAt` | string | The date on which the a `oneshot` Scheduled Payment is to be executed. This date must be set at least one day in the future. Format: `YYYY-MM-DD`. |
| `startAt` | string | The date from which a `periodic` Scheduled Payment execution starts. This date must be set at least one day in the future. Format: `YYYY-MM-DD`. |
| `endAt` | string | The date on which a `periodic` Scheduled Payment ends. This date must be set after the `startAt` date. Format: `YYYY-MM-DD`. |
| `creationDate` | string | The date and time at which the Scheduled Payment was created. |
| `period` | string | The frequency at which a `periodic` Scheduled Payment is to occur. Can be: `weekly`, `monthly`, `quarterly`, `bi-annual`, or `annual`. |
| `beneficiaryLabel` | string | The label that will be displayed for the Scheduled Payments, regardless of the type. Max. 140 characters. |
| `currency` | string | The currency of the Scheduled Payments. Can only be `EUR`. |
| `userId` | integer | The unique identifier of the User owning the Wallet to debit. |
| `amr` | array | The type of SCA for per-operation SCA (e.g., `CLOUD_PIN`, `HYBRID_PIN`, `DEVICE_BIOMETRIC`). |
| `failedPayment` | object | Additional information in case of a failed payment (date, error code and error message). |
| `endToEndId` | string | The end-to-end identifier, for Payouts only. Max. 24 characters. Allowed characters: alphanumeric and `/` `-` `?` `:` `(` `)` `.` `,` `+` ` ` (space). Mustn't start nor end with `/`, and mustn't contain `//`. |
### Scheduled Payment object
```json [JSON]
{
"id": "string",
"status": "string",
"scheduledPaymentName": "string",
"walletId": integer,
"beneficiaryType": "string",
"beneficiary": integer,
"amount": number,
"type": "string",
"execAt": "string",
"startAt": "string",
"endAt": "string",
"creationDate": "string",
"period": "string",
"beneficiaryLabel": "string",
"currency": "string",
"userId": integer,
"amr": ["string"],
"failedPayment": [
{
"date": "string",
"errorCode": "string",
"errorMessage": "string"
}
],
"endToEndId": "string"
}
```
## Creating a Scheduled Payment order
The required parameters to create a Scheduled Payment order vary depending on the type:
* [One-time payment](#schedule-a-one-time-payment)
* [Periodic payment](#schedule-a-periodic-payment)
### Schedule a one-time payment
| Attribute | Type | Description |
| --- | --- | --- |
| `scheduledPaymentName` | string | The label describing the goal of the Scheduled Payment. |
| `walletId` | integer | The unique identifier of the Wallet to debit. |
| `beneficiaryType` | string | The type of beneficiary for the operation, which can be: `payout` – The Scheduled Payment targets an external account.`walletTransfer` – The Scheduled Payment targets another Wallet in your Treezor environment. |
| `beneficiary` | integer | The unique identifier of the beneficiary of the Scheduled Payment, which can be either `beneficiaryId` for Payouts or `beneficiaryWalletId` for Wallet-to-Wallet transfers. |
| `amount` | number | The amount of the Scheduled Payment. |
| `type` | string | The type of Scheduled Payment, which can be: `oneshot` – The payment will occur only once.`periodic` – The payment will occur periodically over a defined time frame. |
| `execAt` | string | The date on which the `oneshot` Scheduled Payment is to be executed. This date must be set at least one day in the future. Format: YYYY-MM-DD. |
| `beneficiaryLabel` | string | The label that will be displayed for the Scheduled Payments, regardless of the type. Max. 140 characters. |
| `currency` | string | The currency of the Scheduled Payments. Can only be `EUR`. |
| `endToEndId` | string | The end-to-end identifier, for Payouts only. Max. 24 characters. |
You can use the following request to create your scheduled payment order.
Here is an example of `{payload}`:
```json [JSON]
{
"scheduledPaymentName": "gas",
"walletId": 2695112,
"beneficiaryType": "payout",
"beneficiary": 434403,
"amount": 10,
"type": "oneshot",
"execAt": "2024-02-27",
"beneficiaryLabel": "one-time payment",
"currency": "EUR",
"userId": 100165322,
"endToEndId": "GwZzGqwc"
}
```
Returns the Scheduled Payment object:
```json [JSON]
{
"id": "6492e280-16be-4c15-81c3-13d4c82d111x",
"status": "VALIDATED",
"scheduledPaymentName": "gas",
"walletId": 2695112,
"beneficiaryType": "payout",
"beneficiary": 434403,
"amount": 10,
"type": "oneshot",
"execAt": "2024-02-27",
"startAt": null,
"endAt": null,
"creationDate": "2024-02-26T01:50:08+00:00",
"period": null,
"beneficiaryLabel": "one-time payment",
"currency": "EUR",
"userId": 100165322,
"amr": [
],
"failedPayment": [
],
"endToEndId": "GwZzGqwc"
}
```
### Schedule a periodic payment
| Attribute | Type | Description |
| --- | --- | --- |
| `scheduledPaymentName` | string | The label describing the goal of the Scheduled Payment. |
| `walletId` | integer | The unique identifier of the Wallet to debit. |
| `beneficiaryType` | string | The type of beneficiary for the operation, which can be: `payout` – The Scheduled Payment targets an external account.`walletTransfer` – The Scheduled Payment targets another Wallet in your Treezor environment. |
| `beneficiary` | integer | The unique identifier of the beneficiary of the Scheduled Payment, which can be either `beneficiaryId` for Payouts or `beneficiaryWalletId` for Wallet-to-Wallet transfers. |
| `amount` | number | The amount of the Scheduled Payment. |
| `type` | string | The type of Scheduled Payment, which can be: `oneshot` – The payment will occur only once.`periodic` – The payment will occur periodically over a defined time frame. |
| `startAt` | string | The date from which a `periodic` Scheduled Payment execution starts. This date must be set at least one day in the future. Format: YYYY-MM-DD. |
| `endAt` | string | The date on which a `periodic` Scheduled Payment ends. This date must be set after the `startAt` date. Format: YYYY-MM-DD. |
| `period` | string | The frequency at which a `periodic` Scheduled Payment is to occur. Can be: `weekly`, `monthly`, `quarterly`, `bi-annual`, or `annual`. |
| `beneficiaryLabel` | string | The label that will be displayed for the Scheduled Payments, regardless of the type. Max. 140 characters. |
| `currency` | string | The currency of the Scheduled Payments. Can only be `EUR`. |
| `endToEndId` | string | The end-to-end identifier, for Payouts only. Max. 24 characters. |
You can use the following request to create your scheduled payment order.
Here is an example of `{payload}`:
```json [JSON]
{
"scheduledPaymentName": "gas",
"walletId": 2695112,
"beneficiaryType": "payout",
"beneficiary": 434403,
"amount": 10,
"type": "periodic",
"startAt": "2024-02-27",
"endAt": "2024-12-31",
"period": "weekly",
"beneficiaryLabel": "subscription",
"currency": "EUR",
"endToEndId": "GwZzGqwc"
}
```
Returns the Scheduled Payment object:
```json [JSON]
{
"id": "6492e280-16be-4c15-81c3-13d4c82d111x",
"status": "VALIDATED",
"scheduledPaymentName": "gas",
"walletId": 2695112,
"beneficiaryType": "payout",
"beneficiary": 434403,
"amount": 10,
"type": "periodic",
"execAt": null,
"startAt": "2024-02-27",
"endAt": "2024-12-31",
"creationDate": "2024-02-26T01:50:08+00:00",
"period": "weekly",
"beneficiaryLabel": "subscription",
"currency": "EUR",
"userId": 100165322,
"amr": [
],
"failedPayment": [
],
"endToEndId": "GwZzGqwc"
}
```
## Retrieving the executed payments
To see all the operations linked to a given Scheduled Payment order, you can use the following request (which supports [cursor-based pagination](/guide/api-basics/pagination#cursor-based-pagination)).
```bash [CURL]
curl -X GET '{baseUrl}/core-connect/scheduledPayment/{scheduledPaymentId}/payments' \
--header 'Authorization: Bearer {accessToken}'
```
Returns an array of payment objects, along with a cursor if some payments have already been made against the order.
```json [JSON]
{
"cursor":
{
"current": "string",
"next": "string",
"prev": "string"
},
"payments":
[
{
"date": "2024-02-27 08:15:51",
"amount": "10.00",
"currency": "EUR",
"label": "school fees",
"status": "PENDING",
"paymentId": "184427",
"errorCode": "",
"errorMessage": "",
"endToEndId": "yqCqGiMU-2024-02-27"
}
]
}
```
If no payment have been made against the Scheduled Payment order, an HTTP 204 is returned with an empty list.
## Cancelling a Scheduled Payment
You may want to cancel a Scheduled Payment order, especially in the case of recurring payments with no end dates.
You can use the following request:
```bash [CURL]
curl -X DELETE '{baseUrl}/core-connect/scheduledPayment/{scheduledPaymentId}' \
--header 'Authorization: Bearer {accessToken}'
```
Returns the corresponding Scheduled Payment object with a `status` set to `CANCELED`.
```json [JSON] {3}
{
"id": "6492e280-16be-4c15-81c3-13d4c82d111x",
"status": "CANCELED",
"scheduledPaymentName": "gas",
"walletId": 2695112,
"beneficiaryType": "payout",
"beneficiary": 434403,
"amount": 10,
"type": "oneshot",
"execAt": "2024-02-27",
"startAt": null,
"endAt": null,
"creationDate": "2024-02-26T01:50:08+00:00",
"period": null,
"beneficiaryLabel": "one-time payment",
"currency": "EUR",
"userId": 100165322,
"amr": [
],
"failedPayment": [
],
"endToEndId": "GwZzGqwc"
}
```
## Endpoints
| Endpoint | [Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/core-connect/scheduledPayment`](/api-reference/api-endpoints.html#tag/Scheduled%20Payments/postScheduledPayment){target="\_self"} Create a Scheduled Payment | `read_write` |
| [`/core-connect/scheduledPayment`](/api-reference/api-endpoints.html#tag/Scheduled%20Payments/getScheduledPayment){target="\_self"} Retrieve Scheduled Payments based on the `userId` and/or `walletId` | `read_only` |
| [`/core-connect/scheduledPayment/{scheduledPaymentId}`](/api-reference/api-endpoints.html#tag/Scheduled%20Payments/deleteScheduledPayment){target="\_self"} Cancel a Scheduled Payment order | `read_write` |
| [`/core-connect/scheduledPayment/{scheduledPaymentId}/payments`](/api-reference/api-endpoints.html#tag/Scheduled%20Payments/getScheduledPaymentOperations){target="\_self"} Retrieve the list of executed payments for a given Scheduled Payment order | `read_write` |
---
---
url: /guide/users/tax-residence.md
description: >-
Technical guide for creating and managing user Tax Residence via the Treezor
API. Includes required parameters, request structure, and response examples.
---
# Tax residence
## Introduction
All users (both physical users and legal entities) going through the KYC verification process must declare at least one country of tax residency. This is an obligation enforced by the [CRS](/guide/overview/glossary#common-reporting-standard-crs) and [FATCA](/guide/overview/glossary#foreign-account-tax-compliance-act-fatca).
**Tip – Not requested for Legal representatives**
The legal representative of a legal entity isn’t required to declare a tax residency.
When declaring the tax residence, besides the country, you can also provide:
* The Tax Identification Number (TIN) of the user (optional except for US and Italian taxpayers).
* The waiver exempting Treezor from liability in case of a missing TIN.
**Reading – US taxpayers must declare a US tax residence along with the TIN**
This applies for users whose nationality, birth country, or address is `US`.
Learn more in the [Declare tax residence](https://treezor.zendesk.com/hc/en-us/articles/21466100956444-User-onboarding-3-Declare-tax-residence) article of the Support Center.
## Creation
### Parameters
| Parameters | Type | Description |
|--- |--- |--- |
| `userId` | integer | The unique identifier of the user whose tax residence country is to be declared. |
| `country` | string | The country code for the [country](/guide/api-basics/data-format#countries) of tax residence. Must be `US` if the corresponding user `specificiedUSPerson` attribute is set to `1`. |
| `taxPayerId` | string | The Tax Identification Number (TIN) or Tax Code, which is optional except for US taxpayers or if the Tax Residence `country` is set to `IT`. |
| `liabilityWaiver` | boolean | The waiver exempting Treezor from liability in case of a missing TIN. Must be set to `true` if the `taxPayerId` field is null or empty. |
**API – API Reference available**
For a complete list of Tax Residence attributes, check the [Tax Residences](/api-reference/api-endpoints.html#tag/User%20Tax%20Residences){target="\_self"} section of the API Reference.
### Request
Endpoint: [`/v1/taxResidences`](/api-reference/api-endpoints.html#tag/User%20Tax%20Residences/postTaxresidence){target="\_self"}
```bash [CURL]
curl -X POST '{baseUrl}/v1/taxResidences' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"userId": 100642533,
"country": "FR",
"taxPayerId": "12345",
"liabilityWaiver": false
}
```
Returns the Tax Residence object:
```json [JSON]
{
"taxResidences": [
{
"id": 199519,
"userId": 100642533,
"country": "FR",
"taxPayerId": "12345",
"liabilityWaiver": false,
"createdDate": "2024-07-22 10:38:37",
"lastUpdate": "",
"deletedDate": "",
"isDeleted": false
}
]
}
```
## Retrieval
You may use the dedicated endpoints to search for tax residences.
Here is an example with the [`/v1/taxResidences`](/api-reference/api-endpoints.html#tag/User%20Tax%20Residences/getTaxresidences){target="\_self"} request and the `userId` query parameter to filter the search for a specific user.
```bash [CURL]
curl -X GET '{baseUrl}/v1/taxResidences?userId=100642533' \
--header 'Authorization: Bearer {accessToken}'
```
Returns the list of tax residences filtered for the selected user.
```json [JSON]
{
"taxResidences": [
{
"id": 199519,
"userId": 100642533,
"country": "FR",
"taxPayerId": "12345",
"liabilityWaiver": false,
"createdDate": "2024-07-22 10:38:37",
"lastUpdate": "",
"deletedDate": "",
"isDeleted": false
}
],
"meta": {
"maxPerPage": 10,
"pageNumber": 1,
"totalPages": 1,
"totalResults": 1
}
}
```
## Tax Residence object
```json [JSON]
{
"id": 0,
"userId": 0,
"country": "string",
"taxPayerId": "string",
"liabilityWaiver": true,
"createdDate": "string",
"lastUpdate": "string",
"deletedDate": "string",
"isDeleted": false
}
```
**API – API Reference available**
For a complete list of Tax Residence attributes, check the [Tax Residences](/api-reference/api-endpoints.html#tag/User%20Tax%20Residences){target="\_self"} section of the API Reference.
## Endpoints
| Endpoint |[Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/v1/taxResidences`](/api-reference/api-endpoints.html#tag/User%20Tax%20Residences/postTaxresidence){target="\_self"} Create a Tax Residence | `read_write` |
| [`/v1/taxResidences`](/api-reference/api-endpoints.html#tag/User%20Tax%20Residences/getTaxresidences){target="\_self"} Search for Tax Residences | `read_only` |
| [`/v1/taxResidences/{taxResidenceId}`](/api-reference/api-endpoints.html#tag/User%20Tax%20Residences/getTaxresidence){target="\_self"} Retrieve a Tax Residence based on its `id` | `read_only` |
| [`/v1/taxResidences/{taxResidenceId}`](/api-reference/api-endpoints.html#tag/User%Tax%20Residences/putTaxresidence){target="\_self"} Update a Tax Residence | `read_write` |
| [`/v1/taxResidences/{taxResidenceId}`](/api-reference/api-endpoints.html#tag/User%Tax%20Residences/deleteTaxresidence){target="\_self"} Delete a Tax Residence | `read_write` |
---
---
url: /guide/transfers/wallet-to-wallet.md
description: >-
Technical guide for making peer-to-peer (P2P) fund movements between Treezor
Wallets from the same environment. Includes required parameters, request
structure, and response examples.
---
# Wallet-to-Wallet Transfers
The Transfer object represents a movement of funds from one Treezor Wallet to another, without relying on the [SEPA network](/guide/overview/glossary#sepa-single-euro-payments-aera).
Wallet-to-Wallet Transfer (also referred to as peer-to-peer or P2P) are available 24/7 and can be scheduled (see [Scheduled Payments](/guide/transfers/scheduled-payments)). They send [`transfer.create`](/guide/transfers/events#transfer-create) webhooks and are mapped to `Transfers` objects.
**Prerequisites – Funds can be transferred if:**
* Both [Wallets](/guide/wallets/introduction) are active and belong to the same Treezor environment.
* Both Wallets have the same [BIC](/guide/overview/glossary#bank-identifier-code-bic) (not compatible with [Local IBAN](/guide/wallets/iban)).
* The [Authorized Balance](/guide/wallets/balances) of the debited Wallet is sufficient.
* The amount is within the sender's [KYC](/guide/user-verification/introduction) limits and greater or equal to €0,05.
## Creation
**Information – [SCA](/guide/strong-customer-authentication/introduction) depends on the Wallet owner (`beneficiaryWalletId`)**
* **Per session** – The credited Wallet belongs to the user initiating the transfer.
* **Per operation** – The credited Wallet doesn't belong to the user initiating the transfer.
### Parameters
| Attribute | Type | Description |
|--- | --- | --- |
| `walletId` | integer | The unique identifier of the Wallet to be debited. |
| `beneficiaryWalletId` | integer | The unique identifier of the Wallet to be credited. |
| `amount` | number | The amount of the Transfer. |
| `currency` | string | The currency of the Transfer. Both Wallets must have the same currency. As of today, can only be `EUR`. |
| `transferTypeId` | integer | The type of Transfer, which can be: `1` (**default**) – Wallet-to-Wallet Transfer `3` – Client fees, which allows you to debit fees from end users wallets `4` – Credit note, which allows you handle reimbursement of charges |
| `transferTag` | string | Custom attribute to use as you see fit. Learn more in the [Object tags](/guide/api-basics/objects-tags#objects-tags) article. |
| `label` | string | Custom data. |
**Best practice – Make good use of the `transferTypeId` parameter**
Using the `transferTypeId=3` when billing your customers for your services is strongly recommended. Improper use of `transferTypeId` prevents you from displaying fees on [Account Statements](/guide/wallets/account-documents).
**API – API Reference available**
For a complete list of Transfer attributes, check the [Transfers](/api-reference/api-endpoints.html#tag/Transfers){target="\_self"} section of the API Reference.
### Request example
Endpoint: [`/v1/transfer`](/api-reference/api-endpoints.html#tag/Transfers/postTransfers){target="\_self"}
```bash [CURL]
curl -X POST '{baseUrl}/v1/transfers' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is a `{payload}` example:
```json [JSON]
{
"walletId": {integer},
"beneficiaryWalletId": {integer},
"transferTypeId": 1,
"amount": {amount},
"currency": "EUR"
}
```
Returns the Transfer object if successful:
```json [JSON]
{
"transfers": [
{
"transferId": 4269222,
"transferStatus": "VALIDATED",
"transferTag": "",
"walletId": 1927699,
"walletTypeId": 9,
"beneficiaryWalletId": 2301937,
"beneficiaryWalletTypeId": 9,
"walletEventName": "Account A",
"walletAlias": "account-63346a643a7fa",
"beneficiaryWalletEventName": "Main account",
"beneficiaryWalletAlias": "main-account-64ad18c128f29",
"amount": "101.25",
"currency": "EUR",
"label": "",
"transferTypeId": 1,
"createdDate": "2024-02-07 14:17:51",
"modifiedDate": "2024-02-07 14:17:51",
"totalRows": null,
"foreignId": null,
"partnerFee": null,
"codeStatus": "150005",
"informationStatus": null,
"metadata": null
}
]
}
```
Treezor also sends a [`transfer.create`](/guide/transfers/events#transfer-create) webhooks.
**Note – Treezor sends 1 webhook per transfer-related event**
Treezor **doesn't** send a webhook per Wallet (e.g., one for the debited Wallet and another for the credited Wallet). Only one [`transfer.create`](/guide/transfers/events#transfer-create) and [`transfer.update`](/guide/transfers/events#transfer-update) webhook is sent per transfer-related event.
## Endpoints
| Endpoint |[Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/v1/transfers`](/api-reference/api-endpoints.html#tag/Transfers/getTransfers){target="\_self"} Search Transfers | `read_only` |
| [`/v1/transfer`](/api-reference/api-endpoints.html#tag/Transfers/postTransfers){target="\_self"} Create a Transfers | `read_write` |
| [`/v1/transfers/{transferId}`](/api-reference/api-endpoints.html#tag/Transfers/getTransfer){target="\_self"} Retrieve a Transfer using its `id` | `read_only` |
| [`/v1/transfers/{transferId}`](/api-reference/api-endpoints.html#tag/Transfers/deleteTransfer){target="\_self"} Delete a Transfer using its `id`| `read_write` |
---
---
url: /guide/wallets/creation.md
description: >-
Technical guide for creating payment accounts and electronic money wallets via
the Treezor API. Includes required parameters, request structure, and response
examples.
---
# Creation
Find in this article examples on how to create different types of wallets. Some wallets might require you contact Treezor to create them.
Treezor sends a [`wallet.create`](/guide/wallets/events#wallet-create) webhook regardless the type of Wallet created.
**Prerequisites – Ensure the User is fit to have a Wallet**
Users must have a `VALIDATED` status, and [Legal Entities](/guide/users/legal-entity) must have a legal representative and majority shareholder declared in order to own a Wallet.
## Payment Account Wallet
The Payment Account Wallet has a `walletTypeId` of **`10`**. This type of wallet requires [KYC validation](/guide/user-verification/introduction) of the associated [User](/guide/users/introduction), and can only be created if the Wallet owner has a `VALIDATED` status.
### Mandatory parameters
Below are the necessary parameters to create a Payment Account Wallet.
| Attribute | Type | Description |
|--- |--- |--- |
| `walletTypeId` | integer | `10` for [Payment Account Wallet](introduction#payment-account-wallet-type-10). |
| `userId` | integer | The unique identifier of the User who owns the Wallet. |
| `currency` | string | The currency of the Wallet. Can only be `EUR`. |
| `eventName` | string | The name of the Wallet. |
| `bic` | string | The country in which the wallet is domiciled. The BIC is required depending on your configuration; see [Local IBAN](/guide/wallets/iban#local-iban) |
**API – API Reference available**
For a complete list of Wallet attributes, check the [Wallets](/api-reference/api-endpoints.html#tag/Wallets){target="\_self"} section of the API Reference.
### Request
Endpoint: [`/v1/wallets`](/api-reference/api-endpoints.html#tag/Wallets/postWallets){target="\_self"}
Here is an example of `{payload}`:
```json [JSON]
{
"walletTypeId": 10,
"userId": 123456,
"currency": "EUR",
"eventName": "My Payment Account Wallet"
}
```
Returns a Wallet object, with its `id`. An IBAN (`iban`) and BIC (`bic`) are also automatically assigned and populated. You may [create Virtual IBANs](iban) in a second step.
```json [JSON]
{
"wallets": [
{
"walletId": 2605378,
"walletTypeId": 10,
"walletStatus": "VALIDATED",
"codeStatus": 120005,
"informationStatus": "",
"walletTag": "",
"userId": 100078924,
"userLastname": "Alex",
"userFirstname": "Oak",
"jointUserId": 0,
"tariffId": 396,
"eventName": "Event_test",
"eventAlias": "event-test-65aa83976d9df",
"eventDate": "2024-01-26",
"eventMessage": "",
"eventPayinStartDate": "2024-01-19",
"eventPayinEndDate": "0000-00-00",
"contractSigned": 0,
"bic": "TRZOFR21XXX", // BIC automatically assigned to the Wallet
"iban": "FR761679800001000012345678", // IBAN automatically assigned to the Wallet
"urlImage": "",
"currency": "EUR",
"createdDate": "2024-01-19 15:13:43",
"modifiedDate": "0000-00-00 00:00:00",
"payinCount": 0,
"payoutCount": 0,
"transferCount": 0,
"solde": 0,
"authorizedBalance": 0,
"totalRows": 1,
"country": "FR"
}
]
}
```
Treezor also sends the [`wallet.create`](/guide/wallets/events#wallet-create) webhook.
## Electronic Money Wallet
The Electronic Money Wallet has a `walletTypeId` of **`9`**. While this type of wallet doens't need KYC validation of the associated User, they can only be created if they have a `VALIDATED` status.
### Mandatory parameters
Below are the necessary parameters to create an Electronic Money Wallet.
| Attribute | Type | Description |
|--- |--- |--- |
| `walletTypeId` | integer | `9` for [Electronic Money Wallet](introduction#electronic-money-wallet-type-9). |
| `userId` | integer | The unique identifier of the User who owns the Wallet. |
| `currency` | string | Currency of the Wallet. Can only be `EUR`. |
| `eventName` | string | The Name of the Wallet. |
| `bic` | string | The country in which the wallet is domiciled. The BIC is required depending on your configuration; see [Local IBAN](/guide/wallets/iban#local-iban) |
**API – API Reference available**
For a complete list of Wallet attributes, check the [Wallets](/api-reference/api-endpoints.html#tag/Wallets){target="\_self"} section of the API Reference.
### Request
Endpoint: [`/v1/wallets`](/api-reference/api-endpoints.html#tag/Wallets/postWallets){target="\_self"}
Here is an example of `{payload}`:
```json [JSON]
{
"walletTypeId": 9,
"userId": 123456,
"currency": "EUR",
"eventName": "My Electronic Money Wallet"
}
```
Returns a Wallet object with its `id`. An IBAN (`iban`) and BIC (`bic`) are also automatically assigned and populated. You may [create Virtual IBANs](iban) in a second step.
```json [JSON]
{
"wallets": [
{
"walletId": 2605123,
"walletTypeId": 0,
"walletStatus": "VALIDATED",
"codeStatus": 120005,
"informationStatus": "",
"walletTag": "",
"userId": 100078924,
"userLastname": "Alex",
"userFirstname": "Oak",
"jointUserId": 0,
"tariffId": 396,
"eventName": "Event_test",
"eventAlias": "event-test-65aa83976d9df",
"eventDate": "2024-01-26",
"eventMessage": "",
"eventPayinStartDate": "2024-01-19",
"eventPayinEndDate": "0000-00-00",
"contractSigned": 0,
"bic": "TRZOFR21XXX", // BIC automatically assigned to the Wallet
"iban": "FR761679800001000012345678", // IBAN automatically assigned to the Wallet
"urlImage": "",
"currency": "EUR",
"createdDate": "2024-01-19 15:13:43",
"modifiedDate": "0000-00-00 00:00:00",
"payinCount": 0,
"payoutCount": 0,
"transferCount": 0,
"solde": 0,
"authorizedBalance": 0,
"totalRows": 1,
"country": "FR"
}
]
}
```
Treezor also sends the [`wallet.create`](/guide/wallets/events#wallet-create) webhook.
---
---
url: /guide/use-cases/prerequisites/creating-your-company.md
description: >-
Create and verify your company as a legal entity using the Treezor Dashboard
application. This implementation guide takes you through the steps without
need of any technical knowledge. This introduction includes the functional
architecture of your company and keywords you need to know to get started.
---
# Creating your company
Before starting with any of the use cases, you first need to verify your company, which means going through the KYC/KYB process for your company’s legal representative and shareholders, as well as your company as a legal entity.
We propose two guides to help you through the onboarding of your company:
**Important – Rely on the KYC Form shared with you by Treezor**
All the requirements for declarative data and supporting documents are available in your KYC form.
## Functional architecture
Your company is a legal entity, to which are attached (with a children-parent relationship) its shareholders (UBOs) and its legal representative.
Use cases also rely on a Master Wallet, which is directly attached to your legal entity, and through which all the funds will be transiting.
## Keywords
Find below a few terms specific to the guides.
If you have any doubts, you may find more definitions in the [Glossary](/guide/overview/glossary).
### Know Your Business (KYB)
KYB stands for Know Your Business and, in this guide, covers the verification process of:
* Your company (as a legal entity)
* Its legal representative
* Its shareholders
User (legal entities and individuals) verification is a legal and mandatory process. All banking institutions are subject to these rules, as part of the AML/CFT. Without being verified, your company won’t be allowed to use the funds stored in its wallet.
This process is very similar to the KYC (Know Your Customer) process through which your end users may have to go. You will find the term KYC in the guide, especially when referring to the Dashboard screens for instance.
*Treezor Compliance* creates a KYC Form which is specific for your company. You must abide by the documents and declarative data to be provided for your company to be verified.
### Shareholders
As part of the KYB process, you must declare and verify any shareholder who owns 25% or more of your company (directly or via a holding company). These majority shareholders are usually defined as ultimate beneficial owners (UBO) or beneficial owners.
For convenience purposes, this guide will use the term **shareholder**.
### Legal representative
The legal representative is the person legally appointed to represent your company.
They are the signatory for all company operational activities, and they must ensure the good operation and standing of the company.
### Master Wallet
The [Master Wallet](/guide/wallets/introduction##master-wallet-type-15) refers to the single wallet attached to a company through which all the funds transit.
You may also find the French term *Titres Spéciaux de Paiements*.
## Get to know your Dashboard
The no-code guide relies on Treezor's Dashboard, a user interface allowing you to interact with the Treezor API without relying on developer tools.
### Log into your Dashboard
Treezor provided you with the URL to log into your Dashboard. For your Sandbox, the URL is built as follows:
* `https://dashboard-{yourCompanyName}.sandbox.treezor.co`
Upon entering this URL, you'll be redirected to the sign-in page, which is different depending on whether you've opted for [standard login with 2FA](/guide/dashboard/introduction#standard-login-with-2fa) or [Company SSO login](/guide/dashboard/introduction#company-sso-login).
Below is an example of Treezor's default login page.
### Discover the Dashboard interface
Before you start, let’s take a quick guided tour of the key components of the Dashboard interface.
**Note – Your Dashboard is customizable**
The views may differ from the screenshots displayed depending on:
* Where you’re at in your integration process, if you’re customizing the design
* The [User Role](/guide/dashboard/dashboard-users#dashboard-user-roles) of the logged-in user, if you’re not using all of Treezor's features
* Your localization and language selection
| # | Section | Description |
| :---: | --- | --- |
| | Navigation menu | Located on the left-hand side, this foldable menu allows you to navigate to the different views:*Dashboard* views, which focus on the features.*Configuration* views, which are about setting up your Dashboard. |
| | Main toolbar | In the upper part of each view, the Main toolbar contains the search field, the list of favorites, the language selection, and the account drop-down, for you to log out or access your *Account* page. |
| | Main view | Main content, which depends on the selected view. By default, the *Users* view is displayed. |
| | Environment | In the bottom left corner, you’ll find information about your environment and the version of the Dashboard. |
### Accessing your users
You may access your user information by:
* Taking advantage of the main [*Search field*](#search-field).
* Navigating the [*Users*](#users-view) view.
Upon selecting a user, the corresponding details will be displayed in the *User details* view.
#### Search field
The Dashboard main toolbar provides a search field, whose searchable attribute becomes dynamically available depending on what you enter.
Here are the attributes for you to search users:
* **User ID** – The `userId` automatically generated by Treezor when creating a user.
* **User Tag** – The [`userTag`](/guide/api-basics/objects-tags), a field you can populate to suit your needs.
* **Email** – The `email` provided during the user creation.
* **Name** – Takes into account the `firstName`, `lastName`, `legalName`, and `email` provided during the user creation.
After validating your search for a given user attribute, the [*Users*](#users-view) view is displayed, filtered on the corresponding User for you to select.
#### Users view
The *Users* view lists all your users with their key information. Clicking on arrow icon for a user switches the view to the corresponding profile in the *User details* view.
## Select the Business User creation path
The Dashboard offers tailored user creation paths for you to do all the steps to create your company in one go. Your company is a legal entity, a user that is referred to as a Business User in the Dashboard.
→ Access the *Create User* view by clicking on the "Create User" button in the upper-right corner of the *Users view*.
→ Select the "Business User" creation path and click on the "Continue" button to start creating your company.
## Fill the main information of your company
You can now provide the declarative data of your company, as requested by the KYC Form shared with you by Treezor.
If your company is listed in Credit Safe, entering the legal registration number will allow you to automatically prefill information.
→ Enter your company registration number or SIREN.
After a short loading time, the following may occur:
→ Click on the "Prefill data" button.
→ Thoroughly check and edit the prefilled information if need be.
→ Click on the "Select the company" button.
→ In the *Select the company* popup, select the correct company from the list. If not available, you may cancel and enter data manually.
→ Click on the "Enter Data Manually" button to display the fields for you to fill in.
Legal sector information differs depending on the Legal Sector Type:
* **Legal Sector Type** – Will define which data you will have to enter in the Legal Sector field (either NACE, or NAF)
* **Legal Sector** – Either a 4-digit code (NACE) or a 4-digit code followed by an uppercase character (NAF).
Once all the mandatory information is entered, you may click on the "Next" button to proceed to the next step.
## Add verification details and documents
The verification details step focuses on the declarative data necessary for the KYC Review of your compnay.
→ Fill the information as requested by the KYC Form shared with you by Treezor.
→ Upload all the necessary documents for the legal entity as well, still abiding by the KYC Form shared with you by Treezor.
**Tip – You can upload the documents later**
You may upload documents after the creation process is done. Ensure however that all documents for all users (legal entity and company members) are provided before requesting the KYC Review.
Once all the mandatory information is entered, you may click on the "Next" button to proceed to the next step.
## Add the company members
Now, you can directly declare the legal representatives and shareholders of your company.
### Add the legal representatives
The legal representative is the person legally appointed to represent your company.
As such, you need to create a child user of your company in order to declare this legal representative.
→ Click on the "Add Members" button.
→ Provide the name and unique email of the legal representative in the displayed fields.
→ Select the "Legal representative" role.
→ Navigate the *User information*, *Birth and Nationality*, *Situation and tax residence*, and *Documents* tabs to fill in all the required information regarding your legal representative.
### Add the shareholders
You must declare any shareholder who owns 25% or more of your company (directly or via a holding company).
→ Scroll up to click on the "Add Members" button located in the upper right corner of the view.
Upon doing so, a new section is displayed at the bottom for you to fill with the shareholder information.
→ Provide the name and unique email of the Shareholder in the displayed fields.
→ Select the "Shareholder" role and add the ownership percentage.
→ Navigate the *User information*, *Birth and Nationality*, *Situation and tax residence*, and *Documents* tabs to fill in all the required information regarding your shareholder.
Repeat the operation for as many shareholders as you need to declare.
Once all the company members are declared, click on the "Next" button located at the bottom of the view.
## Confirm the creation
The *Summary* view displays all the information entered for your company (legal entity) and the company members. Review the information before confirming the creation.
A success message is displayed, and you’re redirected to the *User details* view, with your company selected.
## Review the KYC Documents
**Tip – Make sure all the necessary documents are uploaded**
If you didn't upload the documents during the user creation steps, you can go to the *User details* view, *KYB* tab to [upload more documents](/guide/dashboard/kyc#uploading-kyc-documents).
To make sure you’re about to submit the relevant documents to Treezor, a validation step is required.
For each one of your users' documents (company, legal representative, and shareholders):
→ In the *User details* view, *KYC* (or *KYB*) tab, *Documents* section, click on the ellipsis button and select the “Review document” command for each document whose [status](/guide/dashboard/kyc#document-statuses) is “Pending (you)”.
→ In the prompted *Review Document* popup, review the uploaded document on the left section of the popup.
→ If the document is accurate, selected the "Reviewed" option of the *Status* and enter a comment.
→ Click on the “Submit” button to complete the validation.
As a result, the document status becomes "Reviewed".
→ Repeat this process for as many documents and users as you need for the KYB process of your legal entity.
Once all the documents are validated, the status changed for "Reviewed, to submit".
## Submit your company's KYB to Treezor
Once you have uploaded and validated all the required documents for your company, legal representative and shareholders, you can send this information to Treezor for review.
To do so:
→ In the *User details* view, make sure the currently selected user is your company’s legal entity.
→ In the *KYC* tab, click on the “Submit KYC to Treezor” button in the upper right corner of the view.
You don’t need to repeat this operation for the legal representative and the shareholders, it has automatically been done by Treezor.
→ In Sandbox, contact your *Implementation Manager* to validate your KYB in order to continue testing your implementation.
**Information – In Production, verification is done by Treezor Compliance team**
Verification usually takes about 24h, but may take up to 48h or more (working days only).
## Create your Master Wallet
Your Master Wallet is a wallet of type 15, but only Treezor can create them. You need to create a dummy wallet and then contact your *Implementation Manager* to turn it into a Master Wallet. To do so:
→ In the *User details* view, select your legal entity user and click on the *Wallets* tab.
→ Click on the “Add Wallet” available in the upper right corner.
→ In the prompted *Create Wallet* popup, enter the following information:
* **Wallet name** – Name of the wallet
* **Wallet type** – The Wallet Type 15 is not available by default. You can select any wallet you want and request for an update afterwards.
→ Click on the "Create wallet" button to confirm the creation.
→ Contact your *Implementation Manager* and provide them with the Wallet ID to change your wallet type to 15.
## Abide by additional vigilance measures
Your KYC Form provided by Treezor may indicate that you need to make a credit transfer to complete your company validation process.
This is usually covered in the use cases by the initial transfer made to your Master Wallet.
You can’t make this transfer through the Dashboard. In Sandbox, you will need to go through this step with an API Transfer emulation if you wish to test card transactions.
## Check your company’s status
Once Treezor has validated your company, the *Global KYC Status* section will indicate a “Validated” status.
The Master Wallet can only be used once the company is validated.
---
---
url: /guide/strong-customer-authentication/cross-device.md
description: >-
Technical guide for implementing strong customer authentication for web
applications, by delegating the generation of SCA proofs to another enrolled
device. Includes required parameters, request structure, and response
examples.
---
# Cross-Device SCA
## When to use cross-device SCA
If you expose a web application that uses the Treezor API in any way, it must also enforce SCA. This means having at least one enrolled device capable of generating SCA proofs.
Without an SCA proof, Users can connect to your back end but can't make any request to the Treezor API. Your web application would then be limited to non-Treezor features.
You can however delegate the generation of SCA proofs to another device that has been previously enrolled, therefore allowing for full-featured web application experience from any device.
In a nutshell, when logging in from a computer using a non-enrolled web browser, the User either:
* Logs only into your back end and cannot make any request to the Treezor API, or
* Approves the login attempt from an enrolled device, using the methods described in this article.
Treezor offers 2 solutions to delegate SCA proofs to an enrolled device.
| Solution | Description |
| --- | --- |
| [**Web Native**](introduction#web-native) | This method uses exclusively **web-based** technologies provided by Treezor. |
| [**Mobile SDK**](sdk) | This method consists in running your **mobile application**, but is only relevant if you provide both a mobile and a web application. |
### Process
Cross-Device SCA implies the following steps.
| | Step | Device |
| :---: | --- | --- |
| | **[Queuing new SCA proof requests from the non-enrolled device](#create-the-operation-on-the-web-browser)** `/core-connect/sca/scaOperations` | |
| | **Retrieving the queued SCA proof request on an enrolled device** `/core-connect/sca/scaOperations` | |
| | **[Generating SCA proof on the enrolled device](#sca-signature-on-enrolled-device)**| |
| | **Updating the queue with the signed SCA proof** `/core-connect/sca/scaOperations/{id}` | |
| | **Retrieving the signed proof from the queue on the non-enrolled device** `/core-connect/sca/scaOperations/{id}` | |
| | **[Sending the SCA proofed query to Treezor from the non-enrolled device](#final-submission-on-the-web-browser)** | |
Find below the code for the exhaustive diagram for you to view in [Mermaid](https://mermaid.live/edit).
```
sequenceDiagram
autonumber
actor endUser as End user
participant notenr as Not-enrolled device
participant enr as Enrolled device
participant agent as Your back end
participant trz as Treezor
endUser->>notenr: Try to make a sensitive operation or a login
notenr->>agent: Queue new SCA proof requests (POST /core-connect/sca/scaOperations)
agent->>trz: POST /core-connect/sca/scaOperations with end user JWT
trz->>trz: Store operation request
trz->>agent: Return SCA Operation ID
agent->>notenr: Return SCA Operation ID
par Pulling on non-enrolled device
loop Every X seconds
notenr-->agent: Pull the SCA Operation status (GET /core-connect/sca/scaOperations/{operationId})
agent-->trz: GET /core-connect/sca/scaOperations/{operationId} with end user JWT
end
and End user validates operation on enrolled device
alt Send a notification to end user enrolled device (if it's mobile device)
agent->>enr: Send push notification
end
endUser->>enr: Log in (with SCA)
enr->>agent: Send credentials
agent->>agent: Validate credentials
agent->>trz: Get end user JWT (delegated_end_user grant type)
endUser->>enr: List SCA Operation PENDING
enr->>agent: Request SCA Operation PENDING (GET /core-connect/sca/scaOperations)
agent->>trz: Request SCA Operation PENDING (GET /core-connect/sca/scaOperations) with end user JWT
trz->>agent: Response
agent->>enr: Response
endUser-->enr: Trigger SCA to validate operation
alt User refuse operation
endUser-->enr: Refuse operation
enr-->agent: PUT /core-connect/sca/scaOperations/{operationId}
agent->>trz: PUT /core-connect/sca/scaOperations/{operationId} with end user JWT
notenr-->endUser: Display message "Your operation was refused"
end
enr-->agent: Send SCA Proof
agent-->trz: PUT /core-connect/sca/scaOperations/{operationId} with SCA proof and end user JWT
notenr-->endUser: Display message "Operation validated"
end
notenr->>agent: Call the requested endpoint like POST /beneficiaries
agent->>trz: Call the requested endpoint like POST /beneficiaries with the SCA proof generated on enrolled device
```
## Prerequisites
Treezor exposes a set of endpoints to queue and update operations mandating an SCA signature.
On your back end, you should proxy the following endpoints:
| Endpoint | Description |
| --- | --- |
| `/core-connect/sca/scaOperations/` | Queue an operation that requires SCA signature |
| `/core-connect/sca/scaOperations/` | Retrieve a list of all operations pending SCA signature |
| `/core-connect/sca/scaOperations/{scaOperationRequestId}` | Retrieve a specific operating pending SCA signature |
| `/core-connect/sca/scaOperations/{scaOperationRequestId}` | Update a pending operation with the appropriate signature (SCA proof) |
## Create the operation on the web browser
The end user submits an operation on your web app using a form (e.g., creating a [Beneficiary](/guide/transfers/beneficiaries)) which you save to the queue as it cannot be sent to Treezor without an SCA proof.
### Attributes
| Attribute | Type | Description|
| --- | --- | --- |
| `dataToSign` | string | The expected [data to be signed](securing-endpoints) for the desired endpoint and action. |
| `actionName` | string | Must be one of the allowed actions. We recommend you concatenate the HTTP verb and the route name (e.g., `postPayouts`). |
| `actionDescription` | string | Describes the action to help the User understand what they are validating. |
| `userId` | string | The User `id` that must sign the operation. If your `{accessToken}` was obtained with `grant_type` = `delegated_end_user`, this value must be equal to the User `id` available in the JWT. |
**Tip – `iat` attribute always available in `dataToSign`**
While the `iat` (current timestamp in milliseconds) is only necessary for [Web Native](introduction#web-native) signing, Treezor provides it regardless of the Treezor SCA proofing options ([SDK](sdk), [SDK Abstraction](sdk-abstraction), [Web Native](introduction#web-native)).
This way, you don't have to alter the `dataToSign` depending on the signing solution which isn't known at the time of operation queuing.
### Examples
Below is an example to request an SCA proof of a [per-operation](securing-endpoints#individual-actions) action (the creation of a Beneficiary).
```bash [CURL]
curl -X POST '{baseUrl}/core-connect/sca/scaOperations' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"dataToSign": {
"iat": {currentTimestampInMillisecond},
"url": "{baseURL}/v1/beneficiaries?accessTag=12345",
"body":{
"userId": "12345",
"name": "Alex Oak",
"address": "15 Magnolia road",
"iban": "FR113000300030592123456789",
"bic": "SOGEFRPPXXX",
"usableForSct": true
}
},
"actionName": "postBeneficiaries",
"actionDescription": "Creates a beneficiary",
"userId": "{userId}",
}
```
Below is an example to obtain an SCA proof that can be used authenticate the User with a `grant_type` set to [`delegated_end_user`](/guide/strong-customer-authentication/introduction#authentication), allowing for [per-session operations](securing-endpoints#per-session).
```bash [CURL]
curl -X POST '{baseUrl}/core-connect/sca/scaOperations' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"dataToSign": {
"iat": {currentTimestampInMillisecond},
},
"actionName": "getWallets",
"actionDescription": "Retrieve the user's wallets",
"userId": "",
}
```
Returns an object containing the UUIDv4 (`scaOperationRequestId`) of the operation, allowing you to [check on its evolution](#checking-for-signature) later on.
```json [JSON]
{
"scaOperationRequestId": ""
}
```
This pending operation is made available via the `/core-connect/sca/scaOperations/{scaOperationRequestId}?userId={userId}` endpoint.
## Checking for signature
The browser should display a message indicating to the end user that they must check their enrolled device for pending operations.
In the meantime the browser must continuously check if a signature has been provided yet.
To do so, check the `status` attribute of the scaOperation by either:
* Querying your `/core-connect/sca/scaOperations/{scaOperationRequestId}` endpoint at fixed intervals (e.g., every 5 seconds), or
* Using [HTTP long-polling](https://www.rfc-editor.org/rfc/rfc6202) to be updated as soon as the operation gets signed.
The `status` is initially valued to `PENDING` and can change to `REFUSED` or `VALIDATED` upon User confirmation on the enrolled device.
### Example
```bash [CURL]
curl -X GET '{baseUrl}/core-connect/sca/scaOperations/{scaOperationRequestId}' \
--header 'Authorization: Bearer {accessToken}'
```
Returns the following.
```json [JSON]
{
"scaOperationRequestId": "",
"dataToSign": "{}",
"actionName": "postBeneficiaries",
"actionDescription": "Creates a beneficiary",
"createdAt": "{date time with timezone, RFC 3339}",
"status": "PENDING|REFUSED|VALIDATED",
"validatedAt": "{date time with timezone, RFC 3339}"|null,
"refusedAt": "{date time with timezone, RFC 3339}"|null,
"scaProof": ""
}
```
## Push to the enrolled device
If you have implemented push notifications with your Mobile or Web App, you should push a notification to the device asking it to check for pending SCA operations.
## SCA Signature on enrolled device
Your Mobile or Web App has retrieved the operations (`/core-connect/sca/scaOperations`) either:
* By automatically following the push notification or
* By the action of the end user who opened the App and clicked on your *Pending operations* button.
From the enrolled device, and with a JWT obtained with a `grant_type` = `delegated_end_user`
```bash [CURL]
curl -X GET '{baseUrl}/core-connect/sca/scaOperations' \
--header 'Authorization: Bearer {accessToken}'
```
**Tip – You may also:**
* Filter SCA operations by appending `?status=PENDING` to the URL.
* Retrieve only the specific SCA operation using `{baseUrl}/core-connect/sca/scaOperations/{scaOperationRequestId}`.
Returns the list of SCA Operations.
```json [JSON]
[
{
"id": "",
"dataToSign": "{}",
"actionName": "",
"actionDescription": "",
"userId": "12345",
"createdDate": "{date time with timezone, RFC 3339}",
"status": "PENDING|REFUSED|VALIDATED",
"validatedAt": "{date time with timezone, RFC 3339}"|null,
"refusedAt": "{date time with timezone, RFC 3339}"|null,
"scaProof": "",
}
]
```
You can now display the details of the pending operation to your end user so that can make sure that they validate or refuse the correct operation.
If the end user decides to approve the operation, you:
* Use the [SDK](sdk), [SDK wrapper](sdk-abstraction) or [Web Native](introduction#web-native) option to sign the operation.
* Update the operation (`/core-connect/sca/scaOperations/{scaOperationRequestId}`) with the SCA proof `scaProof` generated on the enrolled device.
```bash [CURL] {5,6}
curl -X PUT '{baseUrl}/core-connect/sca/scaOperations/{scaOperationRequestId}' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{
"status": "REFUSED|VALIDATED",
"scaProof": "" # the scaProof is only mandatory if status=VALIDATED
}'
```
**Security – Grant Type**
This endpoint is only accessible using a JWT obtained with `grant_type` = `delegated_end_user`
## Final submission on the web browser
Using periodic requests to `/core-connect/sca/scaOperations/{scaOperationRequestId}?userId={userId}` or using HTTP long-polling, the web browser is informed that the previously created operation is now signed.
```json{7,8,10} [JSON]
{
"scaOperationRequestId": "",
"dataToSign": "{}",
"actionName": "postBeneficiaries",
"actionDescription": "Creates a beneficiary",
"createdAt": "{date time with timezone, RFC 3339}",
"status": "VALIDATED",
"validatedAt": "{date time with timezone, RFC 3339}",
"refusedAt": null,
"scaProof": "ZHVtbXlwYXNzY29kZQ==.ZHVtbXl3ZWJhdXRobg==",
}
```
The browser can now [submit the operation to Treezor](/guide/strong-customer-authentication/introduction), along with the SCA proof.
The request therefore has exactly the same structure as if it was sent from the enrolled device itself.
---
---
url: /guide/dashboard/dashboard-users.md
description: >-
Provide access to the Dashboard to your teams. Fine-tune your operational
efficiency by assigning dedicated roles, which grant permissions for specific
views and actions.
---
# Dashboard Users
Dashboard Users are the users that can access your Dashboard for administration and support purposes.
You can manage them in the *Dashboard Users* view available from the main navigation, *Administration* section.
## Create a Dashboard User
If you have an Administrator or a Manager Role, you can create new Dashboard Users by clicking on the “Create Dashboard User” button available in the upper right corner.
In the prompted *Create Dashboard user* dialog box, fill in the following fields:
* Username (or email), which must be unique
* Role (as described in the table below)
* Password, following the indicated rules
* SAML Key (when using your own SSO solution, to link automatically a Dashboard User to a Dashboard OAuth2 client)
## Dashboard User Roles
Dashboard Users can have different Roles, granting different [Scopes](/guide/api-basics/authentication).
| Role | Ab. | Description |
|--- | --- | --- |
| Read-only | RO | Restricted role with first-level viewing rights. |
| Basic editor | BE | Restricted role for first-level edition rights. |
| User management | UM | For operators to edit information and create users. |
| User & beneficiary management | BM | For operators to create beneficiaries and manage users. |
| Transfer management only | TM | For operators to create transfers only. |
| All rights editor | AR | For operators with advanced editing rights. |
| Manager | M | Dashboard managers, with exhaustive rights and Dashboard User management rights. |
| Administrator | A | Administrators with all the rights including configuration and bulk card creation. |
**Note – Administrator Role specificities**
Only Administrators can create, edit and delete other Administrators. Also, only Administrators can grant the Administrator Role.
### Accessible views per role
| Dashboard views | RO | BE | UM | BM | TM | AR | M | A |
|--- |:---: |:---: |:---: |:---: |:---: | :---: | :---: | :---: |
| Users | | | | | | | | |
| User details | | | | | | | | |
| Create User | | | | | | | | |
| Cards | | | | | | | | |
| Wallets | | | | | | | | |
| Beneficiaries | | | | | | | | |
| All Card Transactions | | | | | | | | |
| Bulk Cards | | | | | | | | |
| Administration views | RO | BE | UM | BM | TM | AR | M | A |
|--- |:---: |:---: |:---: |:---: |:---: | :---: | :---: | :---: |
| Dashboard Users | | | | | | | | |
| Predef Restriction Groups | | | | | | | | |
| Templating management | | | | | | | | |
| Webhooks | | | | | | | | |
### Possible actions per user role
| Action | RO | BE | UM | BM | TM | AR | M | A |
|--- |:---: |:---: |:---: |:---: |:---: | :---: | :---: | :---: |
| Edit User main information | | | | | | | | |
| Delete User | | | | | | | | |
| Secure SCA on this device | | | | | | | | |
| Unlock SCA on this device | | | | | | | | |
| Reset PIN on the device | | | | | | | | |
| Delete SCA on this device | | | | | | | | |
| Action | RO | BE | UM | BM | TM | AR | M | A |
|--- |:---: |:---: |:---: |:---: |:---: | :---: | :---: | :---: |
| Edit User information | | | | | | | | |
| Add KYC document | | | | | | | | |
| Submit KYC to Treezor | | | | | | | | |
| Review document | | | | | | | | |
| Delete document | | | | | | | | |
| View processed KYC documents | | | | | | | | |
| Download processed KYC documents | | | | | | | | |
| Action | RO | BE | UM | BM | TM | AR | M | A |
|--- |:---: |:---: |:---: |:---: |:---: | :---: | :---: | :---: |
| Add Child User | | | | | | | | |
| Action | RO | BE | UM | BM | TM | AR | M | A |
|--- |:---: |:---: |:---: |:---: |:---: | :---: | :---: | :---: |
| Add Wallet | | | | | | | | |
| Make a Payout | | | | | | | | |
| Create Wallet to Wallet Transfer | | | | | | | | |
| Download Operations | | | | | | | | |
| View Wallet Details | | | | | | | | |
| Generate PDF Documents | | | | | | | | |
| Edit Wallet | | | | | | | | |
| Deactivate Wallet | | | | | | | | |
| Action | RO | BE | UM | BM | TM | AR | M | A |
|--- |:---: |:---: |:---: |:---: |:---: | :---: | :---: | :---: |
| Create card | | | | | | | | |
| Activate card | | | | | | | | |
| Block card | | | | | | | | |
| Update card settings | | | | | | | | |
| Action | RO | BE | UM | BM | TM | AR | M | A |
|--- |:---: |:---: |:---: |:---: |:---: | :---: | :---: | :---: |
| Create Beneficiary | | | | | | | | |
| Edit Beneficiary | | | | | | | | |
**Tip – It is possible to create or customize a Dashboard User Role**
This excludes Manager & Administrator roles and requires specific configuration from Treezor. Contact your *Treezor Account Manager* to learn more.
## Manage a Dashboard User
### Commands
Below are the commands available to manage Dashboard Users.
| | Action | Description |
| :---: | --- | --- |
| | **Suspend** | Suspend access for a Dashboard User. You can click on the "Manage suspended users" button located above the Dashboard Users list to access suspended users and either restore their access or remove them permanently. |
| | **Unblock** | Unblock a blocked Dashboard User. This action is only available for Dashboard Users who failed to log in 3 times in a row. |
| | **More** | Provides access to the following commands: **"Change password"** - Opens the *Change password* popup.**"Reset 2FA"** - The corresponding user will have to set up their [2FA](./introduction#standard-login-with-2fa) the next time they logged in.**"Remove"** - Removes access to the Dashboard User. This action is irreversible. |
| | **Details** | Opens the side panel for you see the detailed information of the Dashboard User and manage them. |
### Access renewal
Dashboard User accesses are to be renewed every 3, 6, or 12 months depending on the duration configured with your *Treezor Implementation Manager*.
In the *Dashboard Users* view, *Status* column, you can see for each user whether they are "Active", "Expiring soon", or "Expired". Clicking on the "info" icon displays the necessary command to renew the user's access to the Dashboard when needed.
**Security – Activate renewable access for all users**
Some users might still have permanent access after the delivery of this feature; they are indicated by a red "Active" status.
## Audit trail
From the *Dashboard Users* view, as a Manager or Admin, you can access the *Audit Trail* view by clicking on the ellipsis button located in the upper right corner of the view.
The view lists all the actions made by your team members, allowing you to trace back any creation, modification, or deletion.
---
---
url: /guide/api-basics/data-format.md
description: >-
Learn about the supported data structures for API requests and responses.
Covers JSON conventions, data type mapping, and best practices for accurate
API interaction.
---
# Data Format
The Treezor API follows the standards below regarding the formats of data it returns and accepts. Exceptions are detailed in the documentation when relevant.
## Amounts
Amounts are expected as `number` with two decimals. They do not include the currency name.
### Example
* `180.99` for an amount of **180,99**
* `1285.00` for an amount of **1285**
## Currencies
Currencies follow the **ISO 4217** standard, a 3-character code. While this code is usually in the 3-letter capitalized format, you may encounter the numerical version on some endpoints (e.g., `EUR` or `978` for **Euro**).
## Countries
Countries follow the **ISO 3166-1 alpha-2** standard, a 2 capitalized letter code (e.g., `FR` for France).
* `FR` for **France**
* `DE` for **Germany**
* `CH` for **Switzerland**
## Dates
Most dates follow the **[RFC3339](https://tools.ietf.org/html/rfc3339)** standard.
They are provided and expected to be in Paris time, which is:
* `UTC+2` Central European **DST (Daylight Saving Time)**
* `UTC+1` Central European Time **otherwise**.
Some exceptions such as the card transaction `authorizationIssuerTime` can apply a different timezone (Europe/London in this example). When in doubt, please refer to the [API Reference](/api-reference/api-endpoints).
### Examples
```php [PHP]
date('Y-m-d\TH:i:sP');
// 2020-08-25T07:06:13+02:00
```
```console
2020-08-25T07:06:13-07:00
```
You can [read about UTC here](https://en.wikipedia.org/wiki/Coordinated_Universal_Time) and [check UTC time zones by country there](https://en.wikipedia.org/wiki/List_of_time_zones_by_country).
## Phones
Phone numbers are expected with the country code prefix (e.g., `+33`), without leading zero.
* The French number `06 05 04 03 02` is expected as `+33605040302`
* The German number `013 456 7899` is expected as `+491234567899`
## Files
Files (such as [documents](/guide/user-verification/documents) and [templates](/guide/api-basics/templates)) are expected to be in [`base64` encoded format](https://en.wikipedia.org/wiki/Base64) in a JSON object attribute.
They are also returned as base64.
### Example
```php [PHP]
// composer require php-curl-class/php-curl-class
$request = new Curl\Curl;
$request->setHeader('Authorization', 'Bearer '); // Don't forget to replace with your token
$request->setHeader('Content-Type', 'application/json');
$request->post(
'https://.sandbox.treezor.co/v1/documents/', [
// [...] this example doesn't show all the mandatory parameters
'userId' =>'',
'documentTypeId' =>'',
'name' =>'19-Extrait-Kbis.pdf',
'fileContentBase64' =>base64_encode(
file_get_contents(
'/home/johnsmith/Downloads/19-Extrait-Kbis.pdf'
)
)
]
);
```
```bash [CURL]
# encode the file into base64
base64 /home/johnsmith/Downloads/19-Extrait-Kbis.pdf > /home/johnsmith/Downloads/19-Extrait-Kbis.base64
# show the content of the encoded file
cat /home/johnsmith/Downloads/19-Extrait-Kbis.base64 # ZHVtbXkg[...]dGVzdAo=
# post the encoded file
curl -X POST '{baseUrl}/v1/documents' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{
"userId": "{userId}",
"documentTypeId": "{documentTypeId}",
"name": "19-Extrait KBis.pdf",
"fileContentBase64": "ZHVtbXkg[...]dGVzdAo="
}'
# [...]
# This example doesn't show all the mandatory parameters
```
## IDs
* **Numerical identifiers** such as [`userId`](/guide/users/introduction) should be provided as `integer`.
* **Textual identifiers** such as [`client_id`](/guide/api-basics/authentication#credentials) should be provided as `string`.
**Ids are progressively migrated to [UUIDv4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_\(random\)).**
You should anticipate this API-wide migration by typing all IDs as 36-character **strings** in your databases.
### Numerical example
```json [JSON]
{
"userId": 18742 // No quotes (legacy ID)
}
```
### Textual example
```json [JSON]
{
"client_id": "" // with quotes
}
```
### UUIDv4 example
```json [JSON]
{
"webhook_id": "45a10236-4e55-41b5-8cbd-00acea4cb553"
}
```
## Texts, metas, tags
Strings are expected in Unicode (UTF-8).
## Addresses
Address lines (`address{1-3}` attributes) for User addresses allow for 150 characters, but you may limit them to 56 characters following the [AFNOR XP Z 10-011](https://fr.wikipedia.org/wiki/Restructuration,_normalisation_et_validation_postale) standard of May 1997.
If you're issuing [Cards](/guide/cards/introduction), the Card object applies further restrictions and we recommend even shorter strings due to mail carrier limitations. Below the maximum number of characters per field.
| Field | User object | Card object | Mail carrier recommendation |
| --- | ---: | ---: | ---: |
| `address1` | 150 | 50 | ~38 |
| `address2` | 150 | 50 | ~38 |
| `address3` | 150 | 35 | 35 |
More rules and character restrictions are available in the [Users](/api-reference/api-endpoints.html#tag/Users){target="\_self"} section of the API Reference.
**Important – Mail carrier limitations**
The table above provides an estimate for mail carrier's maximum number of printed characters; those limitations may change depending on the font for example.
---
---
url: /guide/api-basics/using-treezor-as-oauth-identity-provider.md
description: >-
Leverage Treezor as your OAuth Identity Provider for delegated authentication.
This guide details the process of authenticating end users, covering the OAuth
2.0 flow, JWT exchange and validation, and extracting user identity for your
application.
---
# Delegated Authentication
Treezor allows you to use its [OAuth](https://oauth.net/) industry standard authentication mechanism to **authenticate your customers through your application**.
Delegating the authentication to Treezor allows you to focus on your business while having the peace of mind provided by an expertly set up authentication mechanism.
Using Treezor as an Identity Provider means that:
* You don't need to handle passwords yourself (nor password retrievals/resets)
* You don't need to maintain a database of User credentials
* You don't need to keep up with hashing and salting best practices
* You only keep an association between the `userId` provided by Treezor authentication mechanism and the User's information in your own databases
**Prerequisites – To use delegated authentication, you need**
* **To onboard end users with [Connect](/guide/overview/getting-started#treezor-api)** – Creates their credentials in Treezor Identity Provider.
* **A post-authentication URL to be declared to [Connect](/guide/overview/getting-started#treezor-api)** – Where users are redirected after authenticating with Treezor.
* **A private/public key pair to be generated by Treezor** – The public key will be provided to you, allowing you to [assert the Tokens authenticity](#asserting-the-jwt-s-legitimacy).
## Flow
```mermaid
sequenceDiagram
autonumber
participant user as User
participant app as Regular Web App
participant auth as Auth0 Tenant
participant api as Your API
user->>app: Click to login
app->>auth: Authorization Code Request to /authorize
auth->>user: Redirect login/authorize prompt
user->>auth: Authenticate and Consent
auth->>app: Authorization Code
app->>auth: Authorization Code + Client ID + Client Secret to /oauth/token
auth->>auth: Validate Authorization Code + Client ID + Client Secret
auth->>app: ID Token and Access Token
app->>api: Request user data with Access Token
api->>app: Response
```
## Logging-in
When a User accesses your application and doesn't have a JWT, you redirect them to a [customizable login page](#templating-the-login-page) hosted by Treezor.
The User enters their credentials and submits the login form.
If the authentication is successful, the user is redirected to a previously [configured URL](#defining-the-redirection-url) of your application with a `code` query parameter appended by Treezor.
In and of itself, the `code` doesn't allow you to authenticate the User. You will have to exchange this single-use `code` for a [JWT](/guide/overview/glossary#json-web-token-jwt) using the following request.
```bash [CURL]
curl -X POST '{baseUrl}/oauth/token' \
--form 'grant_type="authorization_code"' \ # mandatory
--form 'code="{yourTemporaryCode}"' \ # mandatory
--form 'client_id="{yourClientId}"' \ # mandatory
# --form 'scope=""' # optional, if you want a specific scope
```
Returns an object containing the User's [JWT](/guide/overview/glossary#json-web-token-jwt).
```json [JSON]
{
"token_type": "Bearer",
"expires_in": 3600,
"access_token": "{theUsersAccessToken}",
"refresh_token": "{theTokenAllowingForJwtRefresh}"
}
```
The User can now add this `access_token` in the `Authentication` header of all requests made to your application so that you can [authenticate](#authenticating) them.
## Authenticating
To authenticate an end user, you must:
* [Ensure that their JWT is legitimate](#asserting-the-jwt-s-legitimacy)
* [Extract their identity from the JWT](#extracting-the-user-s-identity)
### Asserting the JWT legitimacy
**Security – Ensure your application validates the JWT legitimacy**
You must implement and test this step with great care. If your application were to accidentally accept invalid tokens would leave it open to anyone.
To check that the token is legitimate, you will use:
* The User's JWT Token,
* The `RSASSA_PKCS1_V1_5_SHA_256` algorithm,
* Your Connect public key.
The User's JWT is composed of three sections each encoded in base64 and separated by dots.
* The **second** section is the token payload
* The **last** section is the token signature
Consider the following JWT, as provided by your User in the `Authentication` header.
```json [JSON]
eyJ0eXAiOiJKV1QiLCJhbGciOiJSU0FTU0FfUEtDUzFfVjFfNV9TSEFfMjU2In0.eyJpc3MiOiJ0cmVlem9yX2Nvbm5lY3QiLCJpYXQiOjE2MzM1MTMyMjEsImV4cCI6MTYzMzUxNjgyMSwic3ViIjoiNzkwMzdlNmUtYzFlMS00MmYyLWJlOWEtZTI0OWM3NjdjNDc2Iiwic2NvcGUiOlsiYWRtaW4iLCJrZXlzIiwibGVnYWwiLCJyZWFkX29ubHkiLCJyZWFkX3dyaXRlIiwicmVhZF9hbGwiXSwidXNlcklkIjpudWxsLCJjYXJkcyI6W10sIndhbGxldHMiOltdLCJjaGlsZHJlbiI6W10sInVzZXJUeXBlIjoiYXBwbGljYXRpb24iLCJjbGllbnRJZCI6IjkyOTI1MiJ9.cPWi6RY1n0tPIJ1jG8600wZQvMUU1eIZPq1uzIju7OI8SnJ77FBmj25q8w0JcUwGIZf0GDKI51tovi0aqFNZsVrsP1V8o3b_5eJiEA2LtUVimAyWWtheMEa1J5Seqh3_rH5BO0xos2fRXM6CyFK1xDwc5EJeD0Pko5Yq3ls4-bcJt3yYBPH3JkaaADt2ettYATnpv9KnBeTPU7INDwNd2d6orVdc0yUgx9dmO9-NPbYBQuNsPTDOV8nnCWu6P0RAqUdjDZKbrr71Vj61ULur5yIr0oHLYg--80p6mgrMMAbPHQTKHO-wrcA94NvTCQ_5STXxUVfxh34xbOotdmeUeQ
```
You encrypt the payload using the `RSASSA_PKCS1_V1_5_SHA_256` algorithm and Connect public key.
```bash [CURL]
# an example will soon be provided
aws kms sign \
--key-id '{connectPublicKey}' \
--signing-algorithm RSASSA_PKCS1_V1_5_SHA_256 \
--message '{payload}'
```
You then compare the newly generated signature with the JWT signature.
* **If they match**: you can proceed to the next step.
* **If they do not match**:
* Deny any access to your application,
* Consider the event as a potential attack and take appropriate measures.
### Extracting the User's identity
As you now can trust the token payload, simply use a base64 decoding function on the token second section (payload).
```bash [CURL]
base64 -d "eyJpc3MiOiJ0cmVlem9yX2Nvbm5lY3QiLCJpYXQiOjE2MzM1MTMyMjEsImV4cCI6MTYzMzUxNjgyMSwic3ViIjoiNzkwMzdlNmUtYzFlMS00MmYyLWJlOWEtZTI0OWM3NjdjNDc2Iiwic2NvcGUiOlsiYWRtaW4iLCJrZXlzIiwibGVnYWwiLCJyZWFkX29ubHkiLCJyZWFkX3dyaXRlIiwicmVhZF9hbGwiXSwidXNlcklkIjpudWxsLCJjYXJkcyI6W10sIndhbGxldHMiOltdLCJjaGlsZHJlbiI6W10sInVzZXJUeXBlIjoiYXBwbGljYXRpb24iLCJjbGllbnRJZCI6IjkyOTI1MiJ9"
```
Returns the decoded payload.
```json [JSON]
{
"iss": "treezor_connect",
"iat": 1624439479,
"exp": 1624443079,
"sub": "79037e6e-c1e1-42f2-be9a-e249c767c476", // here is the trzConnectUserId
"scope": [
"keys",
"legal",
"read_only",
"read_write"
],
"userId": {userId}, // here is the userId
"clientId": {yourClientId},
"cards": [],
"wallets": [],
"children": [],
"userType": "user"
}
```
Note that two distinct IDs are contained in this object:
* `userId` used across the Treezor API to identify the User (to use to match Connect Users with your locally stored Users).
* `sub` (`trzConnectUserId`) used initially during the Connect Onboarding, and when changing password.
It is very important to store the `userId` as a string since `userId` will be migrated to UUID in the future.
Now you could for example retrieve your locally stored User using the following pseudocode:
```java [Javascript]
try {
// assert that the JWT signature is valid
// and retrieve trzConnectUserId from the JWT payload
connectUserId = JWT
.assertSignatureIntegrity()
.decodePayload()
.getConnectUserId()
}
catch(Exception authenticationError) {
// The JWT has an invalid signature, forbid access and terminate
App.die(authenticationError.toString(), 403)
}
// retrieve the locally stored User from your database
customer = Customers.getByConnectUserId(connectUserId)
// perform any action necessary : display wallets balances, recent operations, etc.
wallets = customer.getWallets()
```
**Reading – Learn more about OAuth**
You may find [OAuth website](https://oauth.net/) helpful in implementing Treezor's OAuth Identity Provider.
---
---
url: /content-updates/_components/dec0425.md
description: 'The main updates published on the Treezor documentation on December 4, 2025.'
---
**Payouts – Simulation** The new endpoint to simulate the approval or refusal of multiple standard emitted SEPA Credit Transfers (SCTE) is now available in the documentation.
**Links**: [Emulation](/guide/transfers/faking-operations.html#update-scte-payouts-in-bulk) article | [`/simulation/payouts/bulk`](/api-reference/api-endpoints.html#tag/Payouts/putSimuScteBulk){target="\_self"} endpoint
**Cards – Customization** Unsupported extensions for `logoId` & `logoBackId` were displayed in the dedicated article. This issue has been fixed.
**Links**: [Customization](/guide/cards/creation#customization) article
**Transfers – SEPA Credit Transfers** For SCT, the list of codes has been updated with the codes that can be returned depending on the network.
**Links**: [SCT Inst reason codes](/guide/transfers/error-codes.html#sct-inst-reason-codes) article
**Users – Tax Residence** Added the error returned when the User status doesn't allow for the update of the tax residence.
**Links**: [Errors](/guide/users/error-codes) article
**Users – Self-employed users KYC** Added the exact list of parameters required for KYC in the specific case of self-employed users.
**Links**: [Self-employed users](/guide/users/physical##self-employed-users) article
---
---
url: /content-updates/_components/dec1125.md
description: 'The main updates published on the Treezor documentation on December 11, 2025.'
---
**Cards – Delivery Address** The fields related to the card delivery address (`deliveryTitle`, `deliveryLastName`, `deliveryAddress1`, etc.) are now fully documented in all the responses.
**Links**: [Cards](/api-reference/api-endpoints.html#tag/Cards){target="\_self"} endpoints
**Cards – Renewal** Added new optional fields to the renewal details request body.
**Links**: [`/v1/cards/{cardId}/renewalDetails`](/api-reference/api-endpoints.html#tag/Cards/updateRenewalDetails){target="\_self"} endpoint
**Cards – Batch Delivery** Added precision to the timeline for creating cards that are to be sent in the same batch.
**Links**: [Card creation, Batch Delivery](/guide/cards/creation#batch-delivery-batchdeliveryid) article
**Users – LegalForms** Added new items to the list of values for Italian and German users.
**Links**: [Legal Forms](/guide/users/introduction#legal-forms-legalform) article | [2025 Product updates #12](https://treezor.zendesk.com/hc/en-us/articles/23657196117276-13-11-2025-PROD-Product-Updates-12#h_01KC8WJJVYA6V8DBM24RXC5ZRY)
---
---
url: /content-updates/_components/dec1825.md
description: 'The main updates published on the Treezor documentation on December 18, 2025.'
---
**Cards – Digitized Cards** The scopes for the digitized cards endpoints were missing. This issue has been fixed.
**Links**: [X-Pay](/guide/cards/x-pay-google-apple) article | [Digitized Cards](/api-reference/api-endpoints.html#tag/Digitized%20Cards){target="\_self"} endpoints
**Beneficiary – Verification of Payee (VoP)** Added prerequisites to VoP emulation.
**Links**: [Emulation, Beneficiary Validation](/guide/transfers/faking-operations#beneficiary-validation-result) article
---
---
url: /content-updates/_components/feb0526.md
description: 'The main updates published on the Treezor documentation on February 5, 2026.'
---
**SCA – PCI DSS endpoints data to sign** Added the PCI DSS endpoints to the list of endpoints requiring SCA, as well as the `cardId` as data to sign.
**Links**: [Securing endpoints](/guide/strong-customer-authentication/securing-endpoints) article
**Payouts – Mass Payouts** The `massPayoutTag` parameter wasn't indicated as required. This issue has been fixed.
**Links**: [Mass Payouts](/guide/strong-customer-authentication/user-enrollment#web-native-enrollment) article | [`/v1/massPayouts`](/api-reference/api-endpoints.html#tag/Payouts/postMassPayout){target="\_self"} endpoint
---
---
url: /content-updates/_components/feb1226.md
description: 'The main updates published on the Treezor documentation on February 12, 2026.'
---
**Verification of Payee – Mandatory messages** Added the mandatory message to display when the verification service is unavailable.
**Links**: [Verification of Payee](/guide/transfers/beneficiaries#validation-result-result) article
**Payouts – Idempotency** Added specific maximum character limit for SCTE `accessTag`.
**Links**: [Emitted SEPA Credit Transfers](/guide/transfers/credit-transfer#parameters) article | [`/v1/payouts`](/api-reference/api-endpoints.html#tag/Payouts/postPayout){target="\_self"} endpoint
**Cards – Multi-Criteria Dynamic Card** Added an example for single-use card.
**Links**: [MDC Help Center](https://treezor.zendesk.com/hc/en-us/articles/13231619074844-Multi-Criteria-Dynamic-Card-MDC) article
**Dashboard – Audit trail** Added information regarding how to access the new *Audit Trail* view for Admins and Managers.
**Links**: [Dashboard users](/guide/dashboard/dashboard-users) article
---
---
url: /content-updates/_components/jan0826.md
description: 'The main updates published on the Treezor documentation on January 8, 2026.'
---
**Wallet documents – Confirmation letter** Added this new type of document and related endpoints in the documentation.
**Links**: [Account documents](/guide/wallets/account-documents) article | [Account Documents](/api-reference/api-endpoints.html#tag/Account%20Documents){target="\_self"} endpoints | [Dashboard Wallets](/guide/dashboard/wallets#wallet-commands) article | [Dashboard Q4 evolutions](https://treezor.zendesk.com/hc/en-us/articles/25023247516956-15-01-2026-DASHBOARD-Your-Dashboard-evolutions-Q4-2025#h_01KFN4X22G8CXVD7XZG2H74Q31)
**SCA – WebAuthn** Added the `userVerification` option for Web Native enrollment.
**Links**: [Web Native enrollment](/guide/strong-customer-authentication/user-enrollment#web-native-enrollment) article
**Dashboard – Cards view** Updated all card-related articles due to recent redesign.
**Links**: [Dashboard Q4 evolutions](https://treezor.zendesk.com/hc/en-us/articles/25023247516956-15-01-2026-DASHBOARD-Your-Dashboard-evolutions-Q4-2025#h_01KFN4X22G8CXVD7XZG2H74Q31)
---
---
url: /content-updates/_components/jan1526.md
description: 'The main updates published on the Treezor documentation on January 15, 2026.'
---
**Cards – New transaction simulation** Added the new card transaction simulation endpoints to the documentation.
**Links**: [Emulation](/guide/cards/faking-operations) article | [Card Transactions](/api-reference/api-endpoints.html#tag/Card%20Transactions){target="\_self"} endpoints | [Dashboard Wallets](/guide/dashboard/wallets#wallet-commands) article | [2026 Product updates #1](https://treezor.zendesk.com/hc/en-us/articles/25024318670492-21-01-2026-PROD-Product-updates-2026-1#h_01KFN6SA3WSJKVYQH5A5E6VPAP)
**Users – Status simulation** Updated the new methods to simulate the user status and verification statuses in Sandbox.
**Links**: [Emulation (Users)](/guide/users/faking-operations) article | [Emulation (User Verification)](/guide/users/faking-operations) article | [2026 Product updates #1](https://treezor.zendesk.com/hc/en-us/articles/25024318670492-21-01-2026-PROD-Product-updates-2026-1#h_01KFN6V6S0Z3NSAA6E8W5R8T9T)
---
---
url: /content-updates/_components/jan2226.md
description: 'The main updates published on the Treezor documentation on January 22, 2026.'
---
**Cards – Multi-Criteria Dynamic Card (MDC)** Added the new `merchant_data_pos_terminal_id` fact to the list. The corresponding `posTerminalId` was added to the Card Transaction simulation in the API Reference as well.
**Links**: [MDC Help Center](https://treezor.zendesk.com/hc/en-us/articles/13231619074844-Multi-Criteria-Dynamic-Card-MDC) article | [`/simulation/cardtransaction/authorization`](/api-reference/api-endpoints.html#tag/Card%20Transactions/simuTransacAuthorization){target="\_self"} endpoint
**User verification – Verification solutions** Added the 90-day link expiry delay of the QES and Video Conference solutions.
**Links**: [Qualified eSignature (QES)](/guide/user-verification/qes) & [Video conference](/guide/user-verification/videoconf) articles | [Verification Solutions](/api-reference/api-endpoints.html#tag/Verification%20Solutions%20\(KYC\)){target="\_self"} endpoints
---
---
url: /content-updates/_components/jan2926.md
description: 'The main updates published on the Treezor documentation on January 29, 2026.'
---
**Dashboard – Card Security** Updated the card 3DS enrollment sections to fit the new experience.
**Links**: [Cards, Enroll Card for 3DS](/guide/dashboard/cards#enroll-card-for-3ds) article | [Gift Cards](/guide/use-cases/gift-cards/nocode-guide#enroll-3ds) no-code use case
**Payouts – Standard Emitted SEPA Credit Transfer** Updated the list of parameters to put forward the `label` and `endToEndId` attributes.
**Links**: [Emitted Credit Transfers (SCTE)](/guide/transfers/credit-transfer#emitted-credit-transfers-scte) article
---
---
url: /content-updates/_components/mar0526.md
description: 'The main updates published on the Treezor documentation on March 05, 2026.'
---
**Wallets – Events** Added more context regarding wallet events, including where to find the attribute descriptions and which endpoint triggers an event.
**Links**: [Wallet events](/guide/wallets/events) article
**Payouts – Payout refunds** Added for which reason codes a payout refund can be requested.
**Links**: [Refunding an SDDR](/guide/transfers/direct-debit#refunding-an-sddr) article | [Refunding an SDDR](/guide/transfers/sepa-recalls#emitting-sct-recalls) article
**SCA – SCA Wallets** Some endpoints displayed the wrong scope. This issue has been fixed.
**Links**: [SCA Wallets life cycle](/guide/strong-customer-authentication/sca-wallet-lifecycle) article | [SCA Wallets](/api-reference/api-endpoints.html#tag/SCA){target="\_self"} endpoints
**Webhooks – Race conditions** Moved the "race conditions" article to the introduction to optimize the information structure and navigation.
**Links**: [Webhooks introduction](/guide/webhooks/introduction#race-conditions) article
---
---
url: /content-updates/_components/feb2626.md
description: 'The main updates published on the Treezor documentation on February 26, 2026.'
---
**Checks – Cancellation** Added a dedicated section to clarify check cashing cancellation.
**Links**: [Check cashing](/guide/cheques/cashing#cancellation) article
**Documentation – New content updates page** Added dedicated page to highlight major documentation changes.
**Links**: [Content updates](/content-updates/content-updates) page
**Wallets – Balance** Optimized content by removing glossary item and improving the Balances article.
**Links**: [Balances](/guide/wallets/balances) article
---
---
url: /guide/strong-customer-authentication/enrolled-devices.md
description: >-
Technical guide to retrieve the SCA Wallets created from the Mobile SDK or the
Web Native solution via the Treezor API. Includes required parameters, request
structure, and response examples.
---
# Enrolled devices
The [SCA Wallet](introduction#sca-wallet-object) objects returned may be valued differently depending on whether they've been created through the [Mobile SDK](sdk) or Web Native solution. You can define which by having a look at the `settingsProfile` value.
```json [JSON] {9}
{
"id": "b72c48e91af6543db755cf24gf2d31e1",
"status": "CREATED",
"subStatus": "CREATED_READY",
"passcodeStatus": "NOT_SET",
"locked": false,
"lockReasons": [],
"lockMessage": null,
"settingsProfile": "default",
"mobileWallet": {
"appBuildNumber": null,
"sdkVersion": null,
"os": null,
"osVersion": null,
"brand": null,
"productModel": null,
"deviceId": null,
"deviceIdType": null,
"productFingerprint": null,
"secretFingerprint": null,
"root": null,
"pushMessagingId": null,
"pushMessagingProvider": null,
"mobileUpdateDate": null,
"lastEligibilityCheck": null,
"nfc": null,
"emulator": false,
"appleTeamId": null
},
"activationCode": null,
"creationDate": "2024-12-24T09:40:00+01:00",
"deletionDate": null,
"activationCodeExpiryDate": "2024-12-24T10:00:00+01:00",
"authenticationMethods": [
{
"type": "DEVICE_BIOMETRIC",
"usages": [
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": {
"validityDuration": 60
}
},
{
"type": "NONE",
"usages": [
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": []
},
{
"type": "HYBRID_PIN",
"usages": [
"WALLET_MANAGEMENT",
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": {
"maxAttempts": 3,
"validityDuration": 60
}
}
],
"invalidActivationAttempts": null,
"userId": "1234567",
"scaWalletTag": null,
"clientId": "0998765",
"activationDate": null,
"lockDate":null,
"unlockDate":null,
"resetPinDate":null
}
```
```json [JSON] {9}
{
"id": "a[...]]9kjw_k",
"status": "ACTIVE",
"subStatus": null, // Always null
"passcodeStatus": null, // "SET" if user has a defined passcode (same passcode for all webauthn wallets)
"locked": false, // false by default
"lockReasons": [], // empty array by default, see list of values
"lockMessage": null, // null or string
"settingsProfile": "webauthn", // "webauthn" (Web Native) or "default" (Mobile SDK)
"mobileWallet": null, // Always null for webauthn
"activationCode": null, // Always null for webauthn
"creationDate": "2024-12-24T09:57:01+00:00",
"deletionDate": null,
"activationCodeExpiryDate": null, // Always null for webauthn
"authenticationMethods": [ // array of objects, PublicKeyCredentialInterface is a webauthn-only parameter
{
"userHandle": "dXNlcjEyM0BleGFtcGxlLmNvbQ==", // base64 encoded id of the user you've given during credentials.create for webauthn.
"publicKeyCredentialId": "x9yT3mR-1KG-BNSpGMXbgP_WzxY1ywk6wujUkJHzQoL", // Unique identifier of the webauthn public key
"transports": [
"internal"
],
"aaguid": "bcde1234-56ef-78ab-90cd-123456789012",
"backupStatus": false,
"uvInitialized": true,
"credentialPublicKey": "pQECAyYgASFYIFXcd7YDfxFsfyPEp187k0WVZ5lEE_GHW2ub-fpHuPxSIlggQXMDVfyhBXl1T3LwzohgKJmC_oS4p_EVNeLzRycWz5x",
"attestationType": "self",
"trustPath": {
"type": "Webauthn\\TrustPath\\EmptyTrustPath"
},
"backupEligible": false,
"counter": 0,
"type": "public-key"
}
],
"invalidActivationAttempts": null, // Always null for webauthn
"userId": "100218468", // The user id for the webauthn scaWallet
"scaWalletTag": "",
"clientId": "http://example", // URL on which the webauthn public key can be used
"activationDate": "2024-12-24T09:57:01+00:00", // Identical to creationDate
"lockDate":null,
"unlockDate":null,
"resetPinDate":null
}
```
## Retrieve an SCA Wallet
To retrieve a specific SCA Wallet you can use the following request.
```bash [CURL]
curl -X GET '{baseUrl}/core-connect/sca/scawallets/{scaWalletId}' \
--header 'Authorization: Bearer {accessToken}'
```
Answers with a `200` HTTP Status Code and returns the SCA Wallets object.
```json [JSON]
{
"id": "b72c48e91af6543db755cf24gf2d31e1",
"status": "CREATED",
"subStatus": "CREATED_READY",
"passcodeStatus": "NOT_SET",
"locked": false,
"lockReasons": [],
"lockMessage": null,
"settingsProfile": "default",
"mobileWallet": {
"appBuildNumber": null,
"sdkVersion": null,
"os": null,
"osVersion": null,
"brand": null,
"productModel": null,
"deviceId": null,
"deviceIdType": null,
"productFingerprint": null,
"secretFingerprint": null,
"root": null,
"pushMessagingId": null,
"pushMessagingProvider": null,
"mobileUpdateDate": null,
"lastEligibilityCheck": null,
"nfc": null,
"emulator": false,
"appleTeamId": null
},
"activationCode": null,
"creationDate": "2024-12-24T09:40:00+01:00",
"deletionDate": null,
"activationCodeExpiryDate": "2024-12-24T10:00:00+01:00",
"authenticationMethods": [
{
"type": "DEVICE_BIOMETRIC",
"usages": [
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": {
"validityDuration": 60
}
},
{
"type": "NONE",
"usages": [
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": []
},
{
"type": "HYBRID_PIN",
"usages": [
"WALLET_MANAGEMENT",
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": {
"maxAttempts": 3,
"validityDuration": 60
}
}
],
"invalidActivationAttempts": null,
"userId": "1234567",
"scaWalletTag": null,
"clientId": "0998765",
"activationDate": null,
"lockDate":null,
"unlockDate":null,
"resetPinDate":null
}
```
## List SCA Wallets for a User
You may also retrieve all SCA Wallets belonging to a User using the following request.
```bash [CURL]
curl -X GET '{baseUrl}/core-connect/sca/scawallets?userId={userId}' \
--header 'Authorization: Bearer {accessToken}'
```
Answers with a `200` HTTP Status Code and returns the list of SCA Wallet objects.
```json [JSON]
{
"scawallets": [
{
"id": "b72c48e91af6543db755cf24gf2d31e1",
"status": "CREATED",
"subStatus": "CREATED_READY",
"passcodeStatus": "NOT_SET",
"locked": false,
"lockReasons": [],
"lockMessage": null,
"settingsProfile": "default",
"mobileWallet": {
"appBuildNumber": null,
"sdkVersion": null,
"os": null,
"osVersion": null,
"brand": null,
"productModel": null,
"deviceId": null,
"deviceIdType": null,
"productFingerprint": null,
"secretFingerprint": null,
"root": null,
"pushMessagingId": null,
"pushMessagingProvider": null,
"mobileUpdateDate": null,
"lastEligibilityCheck": null,
"nfc": null,
"emulator": false,
"appleTeamId": null
},
"activationCode": null,
"creationDate": "2024-12-24T09:40:00+01:00",
"deletionDate": null,
"activationCodeExpiryDate": "2024-12-24T10:00:00+01:00",
"authenticationMethods": [
{
"type": "DEVICE_BIOMETRIC",
"usages": [
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": {
"validityDuration": 60
}
},
{
"type": "NONE",
"usages": [
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": []
},
{
"type": "HYBRID_PIN",
"usages": [
"WALLET_MANAGEMENT",
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": {
"maxAttempts": 3,
"validityDuration": 60
}
}
],
"invalidActivationAttempts": null,
"userId": "1234567",
"scaWalletTag": null,
"clientId": "0998765",
"activationDate": null,
"lockDate":null,
"unlockDate":null,
"resetPinDate":null
},
{
"id": "a[...]]9kjw_k",
"status": "ACTIVE",
"subStatus": null,
"passcodeStatus": null,
"locked": false,
"lockReasons": [],
"lockMessage": null,
"settingsProfile": "webauthn",
"mobileWallet": null,
"activationCode": null,
"creationDate": "2024-12-24T09:57:01+00:00",
"deletionDate": null,
"activationCodeExpiryDate": null,
"authenticationMethods": [
{
"userHandle": "dXNlcjEyM0BleGFtcGxlLmNvbQ==",
"publicKeyCredentialId": "x9yT3mR-1KG-BNSpGMXbgP_WzxY1ywk6wujUkJHzQoL",
"transports": [
"internal"
],
"aaguid": "bcde1234-56ef-78ab-90cd-123456789012",
"backupStatus": false,
"uvInitialized": true,
"credentialPublicKey": "pQECAyYgASFYIFXcd7YDfxFsfyPEp187k0WVZ5lEE_GHW2ub-fpHuPxSIlggQXMDVfyhBXl1T3LwzohgKJmC_oS4p_EVNeLzRycWz5x",
"attestationType": "self",
"trustPath": {
"type": "Webauthn\\TrustPath\\EmptyTrustPath"
},
"backupEligible": false,
"counter": 0,
"type": "public-key"
}
],
"invalidActivationAttempts": null,
"userId": "100218468",
"scaWalletTag": "",
"clientId": "http://example",
"activationDate": "2024-12-24T09:57:01+00:00",
"lockDate":null,
"unlockDate":null,
"resetPinDate":null
}
],
"cursor": {
"prev": "356a192b7913b04c54574d18c28d46e6395428ab",
"current": "da4b9237bacccdf19c0760cab7aec4a8359010b0",
"next": "da4b9237bacccdf19c0760cab7aec4a8359010b0"
}
}
```
---
---
url: /guide/strong-customer-authentication/user-enrollment.md
description: >-
Technical guide for creating SCA Wallets to enroll users. The SCA Wallet is a
secure enclave stored on a device, containing the private key necessary for
Strong Customer Authentication.
---
# Enrolling Users
Enrolling users consists in creating [SCA Wallets](introduction#sca-wallet-object) for them. An SCA Wallet is the secure enclave locally present on a device. This digital safe contains a private key necessary for Strong Customer Authentication.
Below the enrollment steps and device limits per solution:
| Device | Enrollment steps | Limits |
| --- | --- | --- |
| **Mobile** | 1 – Creation of the SCA Wallet on the user's device2 – Provisioning of the SCA Wallet with the `activationCode`3 – Definition of PIN code or biometry by the user to finalize device enrollment |1 active SCA Wallet per device |
| **Web** | 1 – Generation of the passkeys on the user's device2 – Passcode creation and encryption on the user's device3 – Forwarding of the public key and encrypted passcode to Treezor to finalize the device enrollment | 5 active SCA Wallets per device |
If these limits are exceeded, an HTTP error is returned.
## Mobile enrollment
This section describes the main steps involved in mobile enrollment, regardless of the mobile solution you chose. You can learn more in the [Mobile SDK](sdk) and [Mobile Abstraction Layer](sdk-abstraction) articles.
With mobile solutions, only one active SCA Wallet can be created per device. You can take advantage of the [Swap](#swap-sca-wallets) feature to create a new wallet on an existing device without needing to delete the old one.
### New User enrollment
When using the [SDK](sdk), an SCA Wallet can be automatically created when creating a new User. In such cases, the following occurs:
* A key pair is generated for this SCA Wallet.
* The SCA Wallet is associated to the new User.
* Treezor sends you a [`sca.wallet.create`](events#sca-wallet-create) webhook notifying you of the SCA Wallet creation.
By default, there is a limit of 1 active SCA Wallet per device when using the mobile solution. If this limit is exceeded, an HTTP error is returned.
### Existing User enrollment
You may need to create an SCA Wallet for an existing user, when migrating to SCA services for instance. To manually create an SCA Wallet when choosing a mobile solution, you can use the following request.
#### Parameters
Below are the parameters to create an SCA Wallet manually.
| Attribute | Type | Description |
| --- | --- | --- |
| `userId` | string | The unique identifier of the user the SCA Wallet is to be attached to. |
| `scaWalletTag` | string | Custom value for the SCA Wallet. Can be used to name the device for which the new SCA Wallet is created. Max length: 256 characters. |
| `authMethod` | array | The chosen methods for the 2-factor authentication. Can be the following strings: `ID`, `OTP EMAIL`, `OTP SMS`, `OTHER` |
#### Request example
Here is an example of `{payload}`:
```json [JSON]
{
"userId": "123456",
"scaWalletTag": "Iphone 13 mini", // Can be the device name (the SCA Wallet is created for)
"authMethod": ["ID", "OTP SMS"] // Optional
}
```
Answers with a `200` HTTP Status Code and the following response.
```json [JSON]
{
"id": "3532d3d44dd999e8957e07cc7e860b2a",
"status": "CREATED",
"subStatus": "CREATED_READY",
"passcodeStatus": "NOT_SET",
"locked": false,
"lockReasons": [],
"lockMessage": null,
"settingsProfile": "default",
"activationCode": "**********************",
"creationDate": "2023-07-12T17:15:25+02:00",
"deletionDate": null,
"activationCodeExpiryDate": "2023-07-12T17:35:25+02:00",
"authenticationMethods": [
{
"type": "DEVICE_BIOMETRIC",
"usages": [
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": {
"validityDuration": 60
}
},
{
"type": "HYBRID_PIN",
"usages": [
"WALLET_MANAGEMENT",
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": {
"maxAttempts": 3,
"validityDuration": 60
}
},
{
"type": "NONE",
"usages": [
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": []
},
{
"type": "CLOUD_PIN",
"usages": [
"WALLET_MANAGEMENT",
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": {
"maxAttempts": 3,
"validityDuration": 60
}
}
],
"invalidActivationAttempts": null,
"userId": "3400118",
"scaWalletTag": "Iphone 13 mini",
"clientId": "0998765"
}
```
Note that the `activationCode` attribute is only populated in the response, it cannot be retrieved later.
Treezor also sends you a [`sca.wallet.create`](events#sca-wallet-create) webhook which contains the `activationCode` to use before the `activationCodeExpiryDate` to [provision the SCA Wallet](#provision-the-sca-wallet).
### Provision the SCA Wallet
You must provision the SCA Wallet when using the SDK on the end user's device before the `activationCodeExpiryDate` using either:
* The `connect(activationCode)` method from the [abstraction layer](sdk-abstraction)
* The `WalletProvisioning#launch(activationCode)` [SDK method](sdk)
The `activationCode` is provided in the [`sca.wallet.create`](events#sca-wallet-create) webhook (or in the response when created manually). You may push silently the code to the end user's device to enable a seamless provisioning.
Once a given SCA Wallet has been provisioned into one app installation, it cannot be provisioned anymore and the `activationCode` is consumed.
**Note – SCA Wallets must be provisioned before the expiration date**
The `activationCodeExpiryDate` is available in the [`sca.wallet.create`](events#sca-wallet-create) webhook. If the provisioning fails due to an expired `activationCode`, you must [delete the SCA Wallet](#deletion) and create a new one.
### Set PIN or Biometry
The user is prompted to authenticate differently depending on the method:
* **Pin** – Using a 6 to 8 digits PIN code.
* **Biometric** – Using the local biometric authentication system of the device.
* **None** – No input required, the operation is transparent.
You may use indistinctly **Pin** or **Biometric**, depending on the capabilities of the device.
Regardless of the method, basic checks are carried out to ensure the mobile device is legitimate and has not been altered or cloned.
### Swap SCA Wallets
Treezor offers a way for end users to enroll a new device for SCA while automatically deleting the previously enrolled device. It makes for a smoother experience than deleting the SCA Wallet first then creating a new one.
Swapping devices is a sensitive action, so users must be strongly authenticated before proceeding. How it is done depends on whether the user owns the previous device.
| Owns previous device | Swapping scenario | Grant type |
| :---: | --- | --- |
| | The user swaps with the SCA Proof from the previous device. | `delegated_end_user` |
| | You secure the swap with 2-factor authentication (e.g., OTP, ID check). | `client_credentials` |
When swapping devices:
1. The previous [SCA Wallet](introduction#sca-wallet-object) is deleted (i.e., status set to `DELETED`).
2. The new [SCA Wallet](introduction#sca-wallet-object) is created, and is activated and/or usable on the new device.
3. Treezor sends the relevant [webhooks](events) for deletion, creation, and swap.
#### Parameters
Below the key parameters for the swap endpoint. The necessary parameters may differ depending on the use case.
| Attribute | Type | Description |
| --- | --- | --- |
| `removeScaWalletId` | string | The unique identifier of the SCA Wallet that is to be deleted. |
| `swapReason` | string | The reason for swapping SCA Wallet. Can be: `LOST`, `STOLEN`, or `OTHER`. |
| `authMethod` | array | The chosen methods for the 2-factor authentication. **Required if** no `sca` is provided. Must be two of the following (strings): `OTP SMS`, `OTP EMAIL`, `ID`, `OTHER`. |
| `sca` | string | The valid proof that authenticated the swap. **Required if** no `authMethod` is provided. |
| `scaWalletTag` | string | Custom value for the SCA Wallet. Can be used to name the device for which the new SCA Wallet is created. Max length: 256 characters. |
#### Swap with SCA proof
In this case, the user still owns the previous device and can provide an SCA proof with it. This method is end user-oriented, and therefore requires a `delegated_end_user` grant type.
```bash [CURL]
curl -X POST '{baseUrl}/core-connect/sca/scawallets/swap' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}` (with SCA proof):
```json [JSON]
{
"removeScaWalletId": "5710a5536cf04712b922f04exx9da5e2",
"swapReason": "OTHER",
"sca": "{scaProof}",
"scaWalletTag": "Pixel 6"
}
```
Returns the newly created SCA Wallet object when successful.
```json [JSON]
{
"id": "992596bacded4c2fba18c716929df58e",
"status": "CREATED",
"subStatus": "CREATED_READY",
"passcodeStatus": "NOT_SET",
"locked": false,
"lockReasons": [],
"lockMessage": null,
"settingsProfile": "default",
"mobileWallet": null,
"activationCode": "0xb95404c543d5549a2eb04b4b94e2e110",
"creationDate": "2025-03-20T09:21:18+01:00",
"deletionDate": null,
"activationCodeExpiryDate": "2025-03-20T09:41:18+01:00",
"authenticationMethods": [
{
"type": "DEVICE_BIOMETRIC",
"usages": [
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": {
"validityDuration": 60
}
},
{
"type": "NONE",
"usages": [
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": []
},
{
"type": "HYBRID_PIN",
"usages": [
"WALLET_MANAGEMENT",
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": {
"maxAttempts": 3,
"validityDuration": 60
}
}
],
"invalidActivationAttempts": null,
"userId": "101706958",
"scaWalletTag": "Pixel 6",
"clientId": "12345",
"activationDate": null,
"lockDate": null,
"unlockDate": null,
"resetPinDate": null
}
```
Treezor also sends a [`sca.wallet.swap`](events#sca-wallet-swa) webhook, with the `activationCode`. You must [provision](#provision-the-sca-wallet) before its `activationCodeExpiryDate`.
#### Swap with 2-factor authentication
This method is not for your end users, but for your back end to swap wallets. Therefore, it requires a `client_credentials` grant type.
```bash [CURL]
curl -X POST '{baseUrl}/core-connect/sca/scawallets/swap' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}` (without SCA proof):
```json [JSON]
{
"swapReason": "LOST",
"removeScaWalletId": "5710a5536cf04712b922f04exx9da5e2",
"authMethod": ["OTP SMS", "ID"],
"scaWalletTag": "iPhone 13"
}
```
Returns the SCA Wallet object when successful.
```json [JSON]
{
"id": "498e5cd161214a128ccc65b376113b94",
"status": "CREATED",
"subStatus": "CREATED_READY",
"passcodeStatus": "NOT_SET",
"locked": false,
"lockReasons": [],
"lockMessage": null,
"settingsProfile": "default",
"mobileWallet": null,
"activationCode": "0x9cd852b8cdcaa5c63e21797b6b5976c9",
"creationDate": "2025-03-19T09:15:24+01:00",
"deletionDate": null,
"activationCodeExpiryDate": "2025-03-19T09:35:24+01:00",
"authenticationMethods": [
{
"type": "DEVICE_BIOMETRIC",
"usages": [
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": {
"validityDuration": 60
}
},
{
"type": "NONE",
"usages": [
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": []
},
{
"type": "HYBRID_PIN",
"usages": [
"WALLET_MANAGEMENT",
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": {
"maxAttempts": 3,
"validityDuration": 60
}
}
],
"invalidActivationAttempts": null,
"userId": "101699619",
"scaWalletTag": "Pixel-5",
"clientId": "12345",
"activationDate": null,
"lockDate": null,
"unlockDate": null,
"resetPinDate": null
}
```
Treezor also sends a [`sca.wallet.swap`](events#sca-wallet-swa) webhook, with the `activationCode`. You must [provision](#provision-the-sca-wallet) before its `activationCodeExpiryDate`.
## Web Native enrollment
This section describes the main steps involved in enrolling users with the [Web Native](introduction#web-native) solution.
By default, there is a limit of 5 active SCA Wallets per device when using the Web Native solution. If this limit is exceeded, an HTTP error is returned. Please note you have to [delete an SCA Wallet](sca-wallet-lifecycle#deletion) to enroll a new additional device.
### User authentication methods
WebAuthn supports two distinct modes for authenticating users. You must define the specific mode during the credential registration process by setting the `userVerification` parameter to the appropriate value.
#### 1. With User Verification (Recommended)
In this mode, the authenticator (e.g., the mobile phone or laptop) verifies the identity of the end user directly using local security features, such as biometrics (FaceID, TouchID) or a device PIN.
* **Passcode:** **Optional**. Since the device has already authenticated the user, an additional passcode is not strictly necessary.
* **Benefit:** Offers a seamless user experience with fewer steps.
#### 2. Without User Verification (Legacy)
In this mode, the authenticator only verifies that the end user is in possession of the registered device. It does not verify *who* is holding the device.
* **Passcode:** **Required**. Because the device does not validate the specific user, a passcode is mandatory to guarantee the user's identity.
* **Benefit:** Primarily used for backward compatibility with older devices or security keys that do not support user verification.
### New User enrollment
The device enrollment process pairs the User with their WebAuthn secured passkeys (and passcode if applicable). This must happen when first creating the User in the Treezor API as the User can't use the Treezor API without an enrolled device.
The following steps are required:
1. Generation of the passkeys using WebAuthn on the User's device
2. Creation of a passcode (min. length: 6 characters) and its encryption on the User's device. **Only required when there is no [user verification](#user-authentication-methods)**
3. Forwarding of the public key (and encrypted passcode if applicable) to Treezor to finalize the device enrollment
The following snippet triggers the passkeys creation process using Web Authentication API on the User's device.
```js [JavaScript]
const publicKeyCredentialCreationOptions = {
// Mandatory, must be set to "device-enrollment"
challenge: convertToArrayBuffer('device-enrollment'),
user: {
// Mandatory, the User's login (this name will be displayed on WebAuthn key selection screen during the authentication process)
name: 'foobar',
// Optional, the User's full name (Firstname LASTNAME)
displayName: '',
// Mandatory, a random ID for each User's device, this is never displayed to the user and doesn't need to be stored anywhere
id: convertToArrayBuffer(randomId),
},
pubKeyCredParams: [{ alg: -7, type: "public-key" }], // Mandatory, as specified
authenticatorSelection: {
// Optional, can be set to "platform", "cross-platform" or omited to allow all authenticators types
authenticatorAttachment: '',
userVerification: 'required' // Passcode isn't required in that case, other case are 'preferred' or 'discouraged' with required passcode
},
// Mandatory, timeout to complete the enrollment in milliseconds. We recommend keeping a fairly high value, as user might be unfamiliar with the process it could take them some time
600000,
// Mandatory, this value must be set to "direct"
"direct",
{
name: "Your website name",
// FQDN, Must be the same at the current domain where your trigger WebAuthn
id: 'www.example.com',
},
};
// trigger Web Authn to register the current device
const credential = await navigator.credentials.create({
publicKey: publicKeyCredentialCreationOptions,
});
const response = credential.response;
const rawId = arrayBufferToBase64Url(credential.rawId).toString();
const clientDataJSON = arrayBufferToBase64Url(
credential.response.clientDataJSON
).toString();
const attestationObject = arrayBufferToBase64Url(
(credential.response).attestationObject
).toString();
// this base 64 encoded string will be required at a later stage
let encodedResponse = btoa(
JSON.stringify({
response: {
attestationObject,
clientDataJSON,
transports: ["string"] // ajout de cette propriété
},
id: credential.id,
rawId,
type: "public-key",
authenticatorAttachment:"platform" // platform or cross-platform
})
);
// helper function
function convertToArrayBuffer(input) {
return Uint8Array.from(input, (c) => c.charCodeAt(0));
}
// helper function
function arrayBufferToBase64Url(arrayBuffer) {
const bytes = new Uint8Array(arrayBuffer);
let str = "";
for (const charCode of bytes) {
str += String.fromCharCode(charCode);
}
const base64String = btoa(str);
return base64String.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
}
```
**Note – Platform vs. Roaming authenticator (`authenticatorAttachment`)**
* **Platform** – Attached with client device-specific transport (`platform` attachment). Usually not removable from the client device.
* **Roaming** – Attached with cross-platform transports (`cross-platform` attachment). Removable and can “roam” between client devices.
If the keys are created successfully, you can now ask the User to define a passcode (minimum length 6 characters) and [encrypt it](#passcode-encryption).
```js [JavaScript]
const encryptedPassCode = encryptPasscode(passCode)
// see Passcode encryption section below for how to encrypt the passcode
```
At this point, you may use the User creation request ([`/v1/users`](/api-reference/api-endpoints.html#tag/Users/postUsers){target="\_self"}) with:
* A `legal` [scope](/guide/api-basics/authentication.html#available-scopes),
* The `passcode` and `webauthn` attributes to the usual payload.
Here is an example of `{payload}`:
```json [with userVerification] {7}
{
"userTypeId": 1,
"specifiedUSPerson": 0,
"firstname": "Alex",
"lastname": "Oak",
// [...] other User attributes hidden for brevity
"webauthn": "eyJyZXNwbrRG[...]9CejhlWWNxem9mUSIsInR5cGUiOiJwdWJsaWMta2V5In0="
}
```
```json [With passcode] {7,8}
{
"userTypeId": 1,
"specifiedUSPerson": 0,
"firstname": "Alex",
"lastname": "Oak",
// [...] other User attributes hidden for brevity
"passcode": "2kdqUTkb3MF[...]My+VIBZB6Xm/tECw+RE9L02/K3x97cvwFXKDTIEZzzwAv1OYbS0w==",
"webauthn": "eyJyZXNwbrRG[...]9CejhlWWNxem9mUSIsInR5cGUiOiJwdWJsaWMta2V5In0="
}
```
In this case, no webhook is sent upon creating the SCA Wallet.
### Existing User enrollment
You may need to create an SCA Wallet for an existing user, either for migrating purposes or for additional devices.
By default, 5 devices may be enrolled with Web Native. If you've reached the limit, you first need to [delete an SCA Wallet](sca-wallet-lifecycle#deletion) to enroll a new additional device.
When a new device must be enrolled for an existing User, two options are available to you:
* [Using an already enrolled device](#using-an-already-enrolled-device) to ensure that the request is legitimate
* [Validating the User's identity using questions](#using-questions) that only they can answer (i.e., birthdate, email OTP, etc.)
Both methods aim at ensuring that the User is who they claim to be before allowing the new device to be enrolled and generate SCA signatures.
#### Parameters
Below are the parameters to create an SCA Wallet manually.
| Attribute | Type | Description |
| --- | --- | --- |
| `userId` | string | The unique identifier of the user the SCA Wallet is to be attached to. |
| `scaWalletTag` | string | Custom value for the SCA Wallet. Can be used to name the device for which the new SCA Wallet is created. Max length: 256 characters. |
| `authMethod` | array | The chosen method for the 2-factor authentication when signing the operation with the [Web Native](introduction#web-native) solution. Must be two of the following (strings): `OTP SMS`, `OTP EMAIL`, `ID`, `OTHER`. |
| `sca` | string | For the [Web Native](introduction#web-native) solution, when creating the SCA Wallet as an end user (required if no `authMethod` is provided). |
| `webauthn` | string | For the [Web Native](introduction#web-native) solution. The `PublicKeyCredential` after the WebAuthn Register, encoded in base64. |
| `passcode` | string | Required if the `webauthn` field is provided **without `userVerification`** and if there is no existing passcode for the user yet. Must be base64-encoded and encrypted. Initial passcode must at least 6 characters. |
#### Using an already enrolled device
If the User already has a device enrolled and accessible, you may use the [cross-device method](cross-device), requesting that the User approves the new device from their already enrolled device.
The passkeys generation process should be carried out on the non-enrolled device (without carrying out last User creation step).
Once the `encodedResponse` from the non-enrolled device available, you can finalize the new device enrollment using the following request.
Here is an example of `{payload}`.
```json [JSON]
{
"userId": "{userId}",
"webauthn": "{encryptedPublicKey}",
"sca": "{scaProofObtainedAtThePreviousStep}"
}
```
#### Using questions
This method can typically be used when the User:
* Has lost or cannot access their already enrolled device
* Was created in the Treezor API before the enforcement of SCA regulations
**Security – Verify the User's identity**
In this situation, you are sole responsible for verifying the User's identity.
In addition to authenticating the User using your usual authentication mechanism, you should ensure the User is able to provide personal information. Use as much relevant information as necessary, such as:
* Their birthdate, current password, email address, mobile phone number
* A one-time-password that you sent to their email address
* A one-time-password that you sent to their mobile phone
If enough conditions are met, you may contact Treezor endpoint and enroll the new device with the following request.
Treezor expects the following `{payload}`:
```json [With userVerification]
{
"userId": "",
"authMethod": ["OTP SMS", "OTP EMAIL", "ID", "OTHER"], // List methods used to ensure the user's identity
"webauthn": "{newDevicePublicKeyWithUserVerification}"
}
```
```json [With passcode]
{
"userId": "",
"authMethod": ["OTP SMS", "OTP EMAIL", "ID", "OTHER"], // List methods used to ensure the user's identity
"passcode": "{theUsersCurrentPasscodeInEncryptedForm}",
"webauthn": "{newDevicesPublicKey}"
}
```
Answers with a `200` HTTP Status Code and the following response.
```json [JSON]
{
"id": "3532d3d44dd999e8957e07cc7e860b2a",
"status": "CREATED",
"subStatus": "CREATED_READY",
"passcodeStatus": "NOT_SET",
"locked": false,
"lockReasons": [],
"lockMessage": null,
"settingsProfile": "default",
"mobileWallet": null,
"activationCode": "**********************",
"creationDate": "2023-07-12T17:15:25+02:00",
"activationDate": null,
"lockDate": null,
"unlockDate": null,
"resetPinDate": null,
"deletionDate": null,
"activationCodeExpiryDate": "2023-07-12T17:35:25+02:00",
"authenticationMethods": [
{
"userHandle": "dGVzdEB3ZWJhdXRobg",
"publicKeyCredentialId": "-7TzaTMjA3dk-1fLf3fEch_Rwqp3hxB0-yaxQXoqEeo",
"aaguid": "adce0002-35bc-c60a-648b-0b25f1f05503",
"uvInitialized": true,
"attestationType": "self",
"backupEligible": false,
"counter": 0,
"otherUI": null,
"type": "public-key",
"transports": [],
"backupStatus": false,
"credentialPublicKey": "pQECAyYgA[...]qWcprI5yqvTz5P7-frvEHIzI", // Truncated for readability
"trustPath": {
"type": "Webauthn\\TrustPath\\EmptyTrustPath"
}
}
],
"invalidActivationAttempts": null,
"userId": "3400118",
"scaWalletTag": "Iphone 12 mini",
"clientId": "0998765"
}
```
In this case, no webhook is sent upon creating the SCA Wallet.
### Passcode encryption
Anytime Treezor requires the User's passcode to be provided, you must use Treezor public key to encrypt the passcode.
**Security – Passcode privacy**
The User's passcode must only be known to the User. It must never be stored on your infrastructure in any form.
The following code snippet includes all the necessary code for client-side encryption of the passcode.
```js [JavaScript]
(async () => {
const str2ab = (str) => {
const buf = new ArrayBuffer(str.length);
const bufView = new Uint8Array(buf);
for (let i = 0, strLen = str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
const pemEncodedKey = `-----BEGIN PUBLIC KEY-----
-----END PUBLIC KEY-----`;
const importRsaKey = async (pem) => {
// fetch the part of the PEM string between header and footer
const pemHeader = "-----BEGIN PUBLIC KEY-----";
const pemFooter = "-----END PUBLIC KEY-----";
const pemContents = pem.substring(
pemHeader.length,
pem.length - pemFooter.length - 1,
);
// base64 decode the string to get the binary data
const binaryDerString = window.atob(pemContents);
// convert from a binary string to an ArrayBuffer
const binaryDer = str2ab(binaryDerString);
return await window.crypto.subtle.importKey(
"spki",
binaryDer,
{
name: "RSA-OAEP",
hash: "SHA-256",
},
true,
["encrypt"],
);
}
let key = await importRsaKey(pemEncodedKey)
const encryptMessage = async (publicKey) => {
let message = 'nicolas'
let enc = new TextEncoder();
let encoded = enc.encode(message)
return window.crypto.subtle.encrypt(
{
name: "RSA-OAEP",
},
publicKey,
encoded,
);
}
let result = await encryptMessage(key)
_arrayBufferToBase64 = ( buffer ) => {
var binary = '';
var bytes = new Uint8Array( buffer );
var len = bytes.byteLength;
for (var i = 0; i < len; i++) {
binary += String.fromCharCode( bytes[ i ] );
}
return window.btoa( binary );
}
let enc = new TextDecoder();
// enc.encode(enc.decode(result))
console.log(_arrayBufferToBase64(result))
})()
```
---
---
url: /guide/api-basics/environments.md
description: >-
Understand Treezor API environments. This guide details the Sandbox and
Production environments, including their base URLs and how to configure your
setup for development and testing.
---
# Environments
To help you integrate the Treezor Connect API with your project, Treezor provides two distinct environments.
Each environment offers its own set of:
* **API URLs** (different URLs must be used to access different environments)
* **Webhooks URLs** (different webhook URLs must be used to receive events from different environments)
* [**Credentials**](/guide/api-basics/authentication#credentials) (different credentials must be used to access different environments)
* **Dataset** (data is sealed and doesn't leak from one environment to another)
* **Features** (features available in one environment may not be present in the other)
* [**Dashboards**](/guide/dashboard/introduction)
**Best practice – Choose your environment wisely**
Each environment has a specific use case, you should use the environment best suited for the current stage of your development.
## Sandbox
This environment receives stable releases and **has features identical to the `production` environment**.
It provides a safe place to test (with no consequences in the real world), develop and run functional tests with your CI tools before going to production:
* **Use case**: Day-to-day software development.
* **URL scheme**: `https://.sandbox.treezor.co`.
* **Placeholder**: The environment is indicated with the `{baseUrl}` variable in code examples.
Please note that performance is **slower** than in [Production](#production) due to the cold-start effect of low traffic on Serverless architectures. If this presents a critical issue, please get in touch with your *Treezor Implementation Manager* to set up automatic warm-ups.
**Alert – Some features and their webhooks are not available in Sandbox**
* [SEPA transfers](/guide/transfers/introduction) can only be **emulated** (no real funds movements).
* [Card payments](/guide/cards/introduction) can only be **emulated**.
* [Card digitization](/guide/cards/introduction) not available with Apple Pay.
[Webhooks](/guide/webhooks/introduction) that cannot be sent in Sandbox are available through the documentation, giving you a reference of what to expect in [Production](#production).
## Production
**This environment is connected to the real world.** It's the environment your users experience and interact with, and on which you must comply with banking services regulations.
* **Use case**: Production exclusively. **Do NOT use it for your CI or other testing processes.**
* **URL scheme**: `https://.api.treezor.co`
**Security – Keep your credentials safe**
Don't share your credentials with anyone, especially for your Production environment.
---
---
url: /guide/wallets/account-documents.md
description: >-
Generate official bank account documents for a given Wallet in PDF or JSON
format, such as account details, account statements, and certificates
(closure, domiciliation, and balance).
---
# Account documents
Account documents are official records that can be generated with Treezor for your Wallets.
Treezor offers the flexibility to retrieve these documents either as ready-to-use PDFs (generated using configurable templates) or as raw JSON data, giving you full control over the document's final presentation and integration into your services.
## Available account documents
### Account details
Account Details corresponds to the bank details of the Wallet, with all the relevant information such as the IBAN and the owner's identity. This is known as *RIB* in French.
### Account statements
Account Statements synthesize all operations affecting the [Balance](/guide/wallets/balances) of a [Wallet](/guide/wallets/introduction) for a given month. It also provides the Balance at the start and end of that month, the sum of debits, and the sum of credits.
**Feature activation – Accounts Statements are disabled by default**
You can request access to this feature by contacting Treezor. Please keep in mind this service only applies starting February, 2022.
#### Account statement legal obligations
Banks are legally obligated to provide Accounts Statements for a duration of 5 years, although the requirements differ depending on the nature of the end user.
Account statements must provide the following mandatory information about the **account holder** and the **mediator**: name, legal status, address, capital, VAT no., and Company Registration no. (RCS).
Please note that in the context of parent-children relations, [Parent Users](/guide/users/parent-children) can access Accounts Statement of their [Children Users](/guide/users/parent-children).
**Reading – Your legal obligations explained**
Learn more about the requirements regarding [statement of account and statement of fees](https://treezor.zendesk.com/hc/en-us/articles/360019159279-Statement-of-account-and-statement-of-fees).
### Account certificates
For reporting or declarative purposes, your Wallets or the ones of your end users might require some official documents.
The Treezor API now natively provides 4 documents for financial auditors and tax services:
| Certificate | Description |
| --- | --- |
| **Balance certificate** | Attestation proving the current balance on your account. |
| **Closure certificate** | Attestation proving the account was closed. |
| **Confirmation letter** | Attestation containing all balances at the end of the fiscal year (*"Lettre de circularisation"* in French). |
| **Domiciliation certificate** | Attestation proving the account registered address. |
## Retrieve raw JSON data
The process for generating a document from raw data is as follows:
1. Retrieve the required data using the dedicated endpoint.
2. Optionally decrypt the data (for statements, if encrypted).
3. Generate the document in your preferred format using the collected data.
**Note – when the [Encryption](https://treezor.zendesk.com/hc/en-us/articles/12862766194844-Encryption) feature is active for Statements**
* The operation `name` field returns an empty string.
* Encrypted fields are returned among the header parameters with the following structure: `operations.metadata.`.
### Query parameters
| Attribute | Type | Description |
| --- | --- | --- |
| `walletId` | string | The unique identifier of the Wallet. |
| `month` | integer | **Statements only**. The month of the statement (2 digits leading with `0`) |
| `year` | integer | **Statements only**. The year of the statement (4 digits, e.g., `2025`) |
**Caution – You can generate statements from Feb, 2022 only**
Treezor can't generate statements before the service was made available. Therefore, the earliest statement you can generate is for 02/2022.
### Request examples
```bash [Account details]
curl -X GET '{baseUrl}/core-connect/account-details/{walletId}/raw' \
--header 'Authorization: Bearer {accessToken}'
```
```bash [Statement]
curl -X GET '{baseUrl}/core-connect/statements/{walletId}/raw?month={month}&year={year}' \
--header 'Authorization: Bearer {accessToken}'
```
```bash [Balance cert.]
curl -X GET '{baseUrl}/core-connect/certificates/walletBalance/{walletId}/raw' \
--header 'Authorization: Bearer {accessToken}'
```
```bash [Closure cert.]
curl -X GET '{baseUrl}/core-connect/certificates/walletClosure/{walletId}/raw' \
--header 'Authorization: Bearer {accessToken}'
```
```bash [Domiciliation cert.]
curl -X GET '{baseUrl}/core-connect/certificates/walletDomiciliation/{walletId}/raw' \
--header 'Authorization: Bearer {accessToken}'
```
```bash [Confirmation letter]
curl -X GET '{baseUrl}/core-connect/certificates/confirmationLetter/{walletId}/raw?date=2026-01-01' \
--header 'Authorization: Bearer {accessToken}'
```
Returns the JSON version of the document.
```json [Account details]
{
"bic": "TRZOFR21XXX",
"iban": "FR7616798000010000XXXXXXXXX",
"title": "",
"firstname": "Alex",
"lastname": "Willow",
"postcode": "75000",
"city": "Paris",
"address1": "15 Hazel road",
"address2": "",
"countryName": "Allemagne",
"treezorAddress": {
"name": "Treezor SAS",
"address1": "33, av de Wagram",
"address2": null,
"postcode": "75017",
"city": "Paris"
}
}
```
```json [Statement]
{
"firstBalance": {
"amount": "50.10",
"date": "2025-02-01"
},
"lastBalance": {
"amount": "-322.25",
"date": "2025-02-28"
},
"operations": [
{
"date": "2025-02-08",
"type": "Prlv SEPA",
"name": "Hertha Abbott Ipsa quod dolores modi quia et. RUM: 864a91c7-e7f7-3a3f-a688-2a6271bdd9af",
"direction": "DEBIT",
"amount": "56.90",
"walletBalance": "1100.90",
"metadata": {
"payoutId": "649715658",
"payoutTag": "Eos voluptatum impedit quasi rem adipisci.",
"label": "Ipsa quod dolores modi quia et.",
"beneficiaryId": "1181276320",
"beneficiaryName": "Hertha Abbott",
"endToEndId": null,
"reasonCode": null,
"reasonDescription": null,
"uniqueMandateReference": "864a91c7-e7f7-3a3f-a688-2a6271bdd9af"
}
},
{
"date": "2025-02-10",
"type": "Vir SEPA",
"name": "Miss Katherine Swift ",
"direction": "DEBIT",
"amount": "15.11",
"walletBalance": "1085.79",
"metadata": {
"payoutId": "331556016",
"payoutTag": "Facere nihil odit error et.",
"label": "",
"beneficiaryId": "415584822",
"beneficiaryName": "Miss Katherine Swift",
"endToEndId": null,
"reasonCode": null,
"reasonDescription": null,
"uniqueMandateReference": ""
}
},
{
"date": "2025-02-21",
"type": "Carte",
"name": "Austyn Nolan (EUR 36.91) Card ****9835",
"direction": "DEBIT",
"amount": "36.91",
"walletBalance": "1048.88",
"metadata": {
"maskedPan": "****9835",
"merchantName": "Austyn Nolan",
"localAmount": {
"amount": 3691,
"currency": "978"
},
"paymentId": "1173130796"
}
},
],
"totalDebit": 586.83,
"totalCredit": 214.48,
"user": {
"title": "",
"firstname": "",
"lastname": "",
"address1": "99 rue de test",
"address2": "",
"address3": null,
"postcode": "75001",
"city": "Paris",
"country": "FR",
"userTypeId": 2,
"state": "",
"legalName": "Compagnie",
"legalRegistrationNumber": "42877171100028"
},
"wallet": {
"iban": "FR7616798000010002753144040",
"bic": "TRZOFR21XXX",
"eventName": "Name of the Wallet",
"walletTag": ""
},
"totalAmountFees": 0,
"totalAmountCreditNote": 0
}
```
```json [Balance cert.]
{
"user": {
"userTypeId": 1,
"title": "MX",
"firstname": "Alex",
"lastname": "Oak",
"birthday": "1989-09-03",
"placeOfBirth": "Paris",
"birthCountry": "France",
"legalName": "Tree Company",
"legalRegistrationNumber": "34567",
"legalRegistrationDate": "2021-09-23"
},
"wallet": {
"walletStatus": "VALIDATED",
"bic": "TRZOFR21XXX",
"iban": "FR7616798000010000101039007",
"createdDate": "2021-09-23 16:33:50"
},
"balance": {
"currentBalance": 638.98,
"calculationDate": "2021-09-23 16:33:50"
},
"certificateDate": "2025-06-02T13:07:58+00:00"
}
```
```json [Closure cert.]
{
"user": {
"userTypeId": 1,
"title": "MX",
"firstname": "Alex",
"lastname": "Oak",
"birthday": "1989-09-03",
"placeOfBirth": "Paris",
"birthCountry": "France",
"legalName": "Tree Company",
"legalRegistrationNumber": "34567",
"legalRegistrationDate": "2021-09-23"
},
"wallet": {
"walletStatus": "CANCELED",
"bic": "TRZOFR21XXX",
"iban": "FR7630006000011234567890189",
"modifiedDate": "2025-09-23 15:31:53"
},
"modifiedDate": "2025-09-23T15:31:53.777Z",
"certificateDate": "2025-06-02T13:07:58+00:00"
}
```
```json [Domiciliation cert.]
{
"user": {
"userTypeId": 1,
"title": "MX",
"firstname": "Alex",
"lastname": "Oak",
"birthday": "1989-09-03",
"placeOfBirth": "Paris",
"birthCountry": "France",
"legalName": "Tree Company",
"legalRegistrationNumber": "34567",
"legalRegistrationDate": "2021-09-23"
},
"wallet": {
"walletStatus": "VALIDATED",
"bic": "TRZOFR21XXX",
"iban": "FR7616798000010000101039007",
"createdDate": "2021-09-23 16:33:50"
},
"certificateDate": "2025-06-02T13:07:58+00:00"
}
```
```json [Confirmation letter]
{
"legalEntity": {
"userId": "102859440",
"userTypeId": 2,
"legalName": "TREE CIE",
"legalRegistrationNumber": "79801583000010",
"legalRegistrationDate": "2013-10-21"
},
"usersLR": [
{
"userId": "102859442",
"userTypeId": "1",
"userStatus": "VALIDATED",
"title": "M",
"firstname": "Alex",
"lastname": "Oak",
"birthday": "1988-01-12",
"email": "user@example.com",
"address1": "11 rue d'Athènes",
"address2": "",
"postcode": "75009",
"city": "Paris",
"country": "FR",
"phone": "+33731309131",
"nationality": "FR",
"placeOfBirth": "Le Blanc-Mesnil",
"birthCountry": "FR",
"effectiveBeneficiary": "33.33"
}
],
"wallet": {
"walletId": "28915577",
"walletTypeId": 10,
"walletStatus": "VALIDATED",
"walletTag": "",
"userId": "103808447",
"userLastname": "",
"userFirstname": "",
"eventName": "Name of the Wallet",
"bic": "TRZOFR21XXX",
"iban": "FRxx xxxxx xxxxx xxx91557705 xx",
"currency": "EUR",
"country": "FR"
},
"balance": {
"balance": 0,
"calculationDate": "2025-10-11T00:00:00+00:00"
},
"certificateDate": "2025-12-02T09:30:23+00:00"
}
```
## Retrieve PDFs
**Note – [Customizable](#customize-pdfs-with-templates) PDFs available in multiple languages**
The PDF Template can support French, German, Italian, and Spanish. The applied language depends on the associated user's [Distribution Country](/guide/users/introduction#distribution-country-distributioncountry). If the `distributionCountry` field is not specified, the configuration default applies.
### Query parameters
| Attribute | Type | Description |
| --- | --- | --- |
| `walletId` | string | The unique identifier of the Wallet. |
| `month` | integer | **Statements only**. The month of the statement (2 digits leading with `0`) |
| `year` | integer | **Statements only**. The year of the statement (4 digits, e.g., `2025`) |
**Caution – You can generate statements from Feb, 2022 only**
Treezor can't generate statements before the service was made available. Therefore, the earliest statement you can generate is for 02/2022.
### Request example
```bash [Account details]
curl -X GET '{baseUrl}/core-connect/account-details/{walletId}/computed' \
--header 'Authorization: Bearer {accessToken}'
```
```bash [Statement]
curl -X GET '{baseUrl}/core-connect/statements/{walletId}/computed?year={year}&month={month}' \
--header 'Authorization: Bearer {accessToken}'
```
```bash [Balance cert.]
curl -X GET '{baseUrl}/core-connect/certificates/walletBalance/{walletId}/computed' \
--header 'Authorization: Bearer {accessToken}'
```
```bash [Closure cert.]
curl -X GET '{baseUrl}/core-connect/certificates/walletClosure/{walletId}/computed' \
--header 'Authorization: Bearer {accessToken}'
```
```bash [Domiciliation cert.]
curl -X GET '{baseUrl}/core-connect/certificates/walletDomiciliation/{walletId}/computed' \
--header 'Authorization: Bearer {accessToken}'
```
```bash [Confirmation letter]
curl -X GET '{baseUrl}/core-connect/certificates/confirmationLetter/{walletId}/computed?date=2026-01-01' \
--header 'Authorization: Bearer {accessToken}'
```
Returns an object containing a URL to download the PDF.
```json [JSON]
{
"link": "https://xxx.s3.eu-west-3.amazonaws.com/tmp/xxx.pdf",
"expireIn": 300
}
```
The PDF must be **downloaded within 5 minutes**, after which it expires.
## Customize PDFs with Templates
### Produce the template
The templating engine that should be used for the template is [Twig with some limitations](/guide/api-basics/templates).
Providing a new template will not affect previously generated documents.
```html [HTML – Account statement example]
Statement
RELEVE D'OPERATIONS
Compte - en euros
{% if user.userTypeId and user.legalName and user.legalRegistrationNumber and user.userTypeId !=
1 %}
Votre nouveau solde au {{ lastBalance.date|date("d/m/Y") }}
{{ lastBalance.amount }} €
Total des frais de gestion sur la période : {{ totalAmountFees }} €
Total des remboursements des frais de gestion sur la période : {{ totalAmountCreditNote }} €
```
You can check the list of [available variables for account statements](#variables-for-account-statements).
**Notes for statements**
* The `operation.type` variable is always provided in French.
* The `totalAmountFees` must be present
* The `totalAmountCreditNote` is optional
### Upload the template
Use the following request to upload your [base-64 encoded template](/guide/api-basics/data-format#files).
```bash [CURL]
curl -X PUT '{baseUrl}/customization/templates/{templateName}/template' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{
"template": "{base64encodedTemplate}"
}'
```
Returns a `201`HTTP Status Code, without any content.
If something goes wrong, you can also get an [error](/guide/api-basics/templates#errors).
You may also customize the template using the [Dashboard](/guide/dashboard/introduction).
### Test the template
You can easily test your document templates by generating the PDFs, except for the statements, which requires you to simulate operations.
Endpoint: [`/simulation/operations`](/api-reference/api-endpoints.html#tag/Operations/simulateOperations){target="\_self"}
Here is a `{payload}` example:
```json [JSON]
{
"walletId": "{walletId}",
"date": "2023-10",
"operations": {
"payin": 5,
"payinrefund": 2,
"payout": 6,
"payoutrefund": 1,
"transfer": 3,
"cardtransaction": 7,
"transferfees":2,
"transfercreditnote":1
}
}
```
Returns a `201` HTTP Status Code.
You can then follow with a [normal request of Account Statement](#request-an-account-statement) to download it.
**Tips**
* Use the same value for `payin` and `payinrefund` to include payin refunds in your test.
* Use a fairly high `payin` value, as types (cheque, sctr) are generated randomly.
* An Account Statement generated for a given month can't be overridden nor regenerated.
### Variables for account statements
Below is a list of available variables for Account Statement templates.
| Variable | Related to | Additional information (if any) |
| --- | --- | --- |
| `wallet.iban` | [Wallet](/guide/wallets/introduction) | |
| `wallet.bic` | [Wallet](/guide/wallets/introduction) | |
| `wallet.eventName` | [Wallet](/guide/wallets/introduction) | |
| `wallet.walletTag` | [Wallet](/guide/wallets/introduction) | |
| `user.title` | [User](/guide/users/introduction) | |
| `user.firstname` | [User](/guide/users/introduction) | |
| `user.lastname` | [User](/guide/users/introduction) | |
| `user.address1` | [User](/guide/users/introduction) | |
| `user.address2` | [User](/guide/users/introduction) | |
| `user.address3` | [User](/guide/users/introduction) | |
| `user.postcode` | [User](/guide/users/introduction) | |
| `user.city` | [User](/guide/users/introduction) | |
| `user.country` | [User](/guide/users/introduction) | |
| `operations[*].date` | | |
| `operations[*].type` | | Always provided in French, but can be [customized](#customize-pdfs-with-templates). |
| `operations[*].name` | | |
| `operations[*].direction` | | |
| `operations[*].amount` | | |
| `operations[*].walletBalance` | | Running balance for each operation. |
| `firstBalance.currency` | [Balances](/guide/wallets/balances) | |
| `firstBalance.date` | [Balances](/guide/wallets/balances) | The date of the first Balance of the month. |
| `firstBalance.amount` | [Balances](/guide/wallets/balances) | The amount of the first Balance of the month. |
| `lastBalance.currency` | [Balances](/guide/wallets/balances) | |
| `lastBalance.date` | [Balances](/guide/wallets/balances) | The date of the last Balance of the month. |
| `lastBalance.amount` | [Balances](/guide/wallets/balances) | The amount of the last Balance of the month. |
| `totalDebit` | [Balances](/guide/wallets/balances) | The cumulated amount of debit Operations. |
| `totalCredit` | [Balances](/guide/wallets/balances) | The cumulated amount of credit Operations. |
| `totalOperation` | Totals | The sum of all Operations |
| `totalAmountFees` | Totals | The sum of [Transfers of type **Fees**](/guide/transfers/wallet-to-wallet#types-transfertypeid) |
| `totalAmountCreditNote` | Totals | The sum of [Transfers of type **Credit note**](/guide/transfers/wallet-to-wallet#types-transfertypeid) |
## Endpoints
| Endpoint |[Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/core‑connect/account‑details/{walletId}/computed`](/api-reference/api-endpoints.html#tag/Account%20Documents/getComputedWalletAccountDetail){target="\_self"} Request a PDF account details for a given Wallet | `read_only` |
| [`/core‑connect/account‑details/{walletId}/raw`](/api-reference/api-endpoints.html#tag/Account%20Documents/getRawWalletAccountDetail){target="\_self"} Retrieve a JSON account details for a given Wallet | `read_only` |
| [`/core-connect/statements/{walletId}/computed`](/api-reference/api-endpoints.html#tag/Account%20Documents/getPdfAccountStatement){target="\_self"} Request a PDF statement for a given Wallet | `read_only` |
| [`/core-connect/statements/{walletId}/raw`](/api-reference/api-endpoints.html#tag/Account%20Documents/getRawStatement){target="\_self"} Retrieve statement information for a given Wallet | `read_only` |
| [`/core-connect/certificates/walletBalance/{walletId}/computed`](/api-reference/api-endpoints.html#tag/Account%20Documents/getWalletBalanceComputed){target="\_self"} Request a PDF Balance Certificate for a given Wallet | `read_write` |
| [`/core-connect/certificates/walletBalance/{walletId}/raw`](/api-reference/api-endpoints.html#tag/Account%20Documents/getWalletBalanceRaw){target="\_self"} Request a JSON Balance Certificate for a given Wallet | `read_write` |
| [`/core-connect/certificates/walletClosure/{walletId}/computed`](/api-reference/api-endpoints.html#tag/Account%20Documents/getWalletClosureComputed){target="\_self"} Request a PDF Closure Certificate for a given Wallet | `read_write` |
| [`/core-connect/certificates/walletClosure/{walletId}/raw`](/api-reference/api-endpoints.html#tag/Account%20Documents/getWalletClosureRaw){target="\_self"} Request a JSON Closure Certificate for a given Wallet | `read_write` |
| [`/core-connect/certificates/walletDomiciliation/{walletId}/computed`](/api-reference/api-endpoints.html#tag/Account%20Documents/getWalletDomiciliationComputed){target="\_self"} Request a PDF Domiciliation Certificate for a given Wallet | `read_write` |
| [`/core-connect/certificates/walletDomiciliation/{walletId}/raw`](/api-reference/api-endpoints.html#tag/Account%20Documents/getPdfAccountStatement){target="\_self"} Request a JSON Domiciliation Certificate for a given Wallet | `read_write` |
---
---
url: /guide/overview/getting-started.md
description: >-
Welcome to Treezor Documentation, which provides the tools and knowledge for
you to implement Treezor's solutions. Find out more about Treezor, the payment
flows and services, as well as your documentation journey before diving into
the API.
---
# Getting started with Treezor
Treezor documentation aims to provide all the tools and knowledge you need to implement Treezor’s solutions.
## What is Treezor?
Treezor is a Banking-as-a-Service solution provider.
It relies on a REST API to offer embedded finance services, allowing you to accelerate your banking projects while remaining compliant and secure in a highly regulated banking sector.
### Treezor services
Once you’re all set up, you’ll be able to consume the API to create and verify users, and benefit from the following banking services.
| | Service | Description |
| - |--- |--- |
| | **Payment accounts** | Rely on Treezor [Wallets](/guide/wallets/introduction) to create accounts adapted to your needs. Included features: [Virtual IBAN](/guide/wallets/iban#virtual-iban)[Local IBAN](/guide/wallets/iban#local-iban)[Account Statements](/guide/wallets/account-documents) |
| | **Card issuing** | Design and print physical and virtual Cards. Included features: [Rules engine](/guide/cards/transactions-rules-engine)[X-Pay](/guide/cards/x-pay-google-apple) |
| | **Transfers** | Move funds in and out of your [Wallets](/guide/wallets/introduction) using international networks. Included features: [SEPA Credit Transfers](/guide/transfers/credit-transfer)[SEPA Inst. Payments](/guide/transfers/credit-transfer-inst)[SEPA Direct Debit](/guide/transfers/direct-debit)[International Transfers](/guide/transfers/international)[Wallet-to-Wallet](/guide/transfers/wallet-to-wallet#wallet-to-wallet-transfers) |
| | **Card acquiring** | Credit [Wallets](/guide/wallets/introduction) using cards as a means of payment. |
| | **Check cashing** | Credit Wallets using [Checks](/guide/cheques/introduction). |
### Treezor flows
The use of Treezor services and features can be illustrated with the following money flows:
## Your documentation journey
Some prerequisites are necessary before you can fully take advantage of Treezor Documentation. If it’s not the case yet, contact [Treezor commercial team](https://www.treezor.com/contact-us/contact-sales/) to get started on your project with us!
Once you’ve got your [Sandbox environment and credentials](#environments-and-credentials), and your onboarding is moving along with Treezor teams, you can start testing your implementation.
While it may vary depending on your project, you usually go through the following steps before exploring our banking services:
* [Authentication](/guide/api-basics/authentication)
* [Webhook subscription](/guide/webhooks/introduction)
* [User creation](/guide/users/introduction) and [verification (KYC)](/guide/user-verification/introduction)
* [Wallet creation](/guide/wallets/introduction)
**Caution – Regulatory and compliance steps are required**
Banking is a highly regulated environment. Treezor will guide you through the steps you must complete for your project to remain compliant.
### LLM-optimized documentation
The Treezor documentation provides the necessary plain text content for easy ingestion by **large language models (LLMs)** such as ChatGPT, Gemini, or Claude.
* **[llm.txt](/llms.txt)** – Structure of the documentation, summarizing all sections.
* **[llm-full.txt](/llms-full.txt)** – Unordered compilation of the whole documentation into one file.
* **Copy as Markdown** – Button available on each page for you to copy the content in Markdown.
* **Download as Markdown** – Button available on each page for you to download the .md file.
These allow you to leverage LLMs for tasks like generating code examples, writing integration scripts, or asking questions about the API without needing to navigate the full site.
While the [API Reference](/api-reference/api-endpoints) can't be included in the documentation compilation, you can download the openAPI file to facilitate your integration.
## Treezor API
As a REST API, Treezor accepts and returns JSON payloads, along with the associated `application/json` content type header. You can read more in the [Data formats](/guide/api-basics/data-format) article.
**Information – Documentation focuses on the most recent version**
You may find mentions to Treezor BaaS (legacy) and Treezor Connect (new services). Please bear in mind that the documentation focuses on the latest behavior of the Treezor Connect API.
### Security
Every call to the API must use HTTP**S** and requires the presence of a [JSON Web Token](/guide/api-basics/authentication) in the `Authorization` header. To obtain this token, you need [to authenticate](/guide/api-basics/authentication) against our OAuth 2.0 provider or with an alternative provider.
Treezor also relies on:
* The [mutual TLS](/guide/api-basics/mutual-tls) protocol for the latest services such as [PCI DSS](/guide/cards/pci-dss).
* The optional [encryption](https://treezor.zendesk.com/hc/en-us/articles/12862766194844-Encryption) layer for sensitive data.
### Environments and credentials
Two environments are available: `sandbox` and `production`. Each has sealed data, distinct credentials, features, and URLs.
You can read more details in the summaries below, or go to the dedicated [Environments](/guide/api-basics/environments) article.
#### Sandbox
Upon subscription and to discover the API, your *Treezor Implementation Manager* will send you your [**`sandbox`**](/guide/api-basics/environments#sandbox) credentials. If you have received them and are in the development phase of your project, [here is a guide to make your first requests](/guide/overview/tinker).
#### Production
Once you reach the *alpha production* stage of your development, you will need [**`production`**](/guide/api-basics/environments#production) credentials.
As these credentials are very sensitive information, Treezor will provide them in an encrypted format using the Pretty Good Privacy (PGP) encryption program.
**Reading – Implementation path**
You can read about the different stages of implementation in the [Validating your implementation](https://treezor.zendesk.com/hc/en-us/sections/360002673359-Your-Implementation-Path) articles of the Support Center.
## Getting help
**Information – Treezor API Status available at all times**
A real-time status of the Treezor API services is available at [treezor.statuspage.io](https://treezor.statuspage.io/).
Answers to your questions may be available in the following articles:
* [HTTP Status Codes](/guide/api-basics/response-codes) returned by the API
* Card transactions [Status](/guide/cards/transactions#statuses-paymentstatus), [Authorization Notes](/guide/cards/authorization-notes), [Codes](/guide/cards/authorization-notes#authorization-response-codes), and [Life cycle](/guide/cards/transactions-lifecycle)
* KYC [Status, Levels, and life cycle](/guide/user-verification/introduction)
* SEPA [Codes](/guide/transfers/error-codes)
* Checks [Codes](/guide/cheques/introduction#codes-codestatus), [Errors](/guide/cheques/introduction#api-errors), and [Life cycle](/guide/cheques/cashing#life-cycle)
### Contacting Treezor Support
When [opening a ticket](https://treezor.zendesk.com/hc/en-us/articles/4403978479634-How-to-create-a-Zendesk-ticket), make sure to provide:
* **The request** – The API request made (URI, HTTP verb, and payload).
* **The response** – The response returned by the API (HTTP Status Code and payload).
* **The expected behavior** – The description of what should have occurred.
* **The actual behavior** – The description of what actually occurred.
* **The date and time** – The approximate date and time at which the request was sent (for us to check the logs).
The [more detailed](https://stackoverflow.com/help/how-to-ask) your message is, the better and quicker Treezor can assist!
**Security – Never share your credentials with Treezor**
You must redact the token or credentials when sharing an issue. If somebody asks for your credentials, report them immediately by [opening a ticket](https://treezor.zendesk.com/hc/en-us/articles/4403978479634-How-to-create-a-Zendesk-ticket).
---
---
url: /guide/use-cases/gift-cards/api-guide.md
description: >-
Issue and manage Gift Cards programmatically via the Treezor API. This API
implementation guide takes you step-by-step through creating users, issuing
cards, setting restrictions, activating, and handling card lifecycle with
detailed API calls and examples.
---
# Gift cards: API guide
The API guide will take you through the following steps to successfully create users and gift cards:
1. [Create a physical user](#create-a-physical-user) – Define your users with the required information.
2. [Create a card](#create-a-card) – Create cards for your users, with their limits and restriction groups.
3. [Activate the card](#activate-a-card) – Activate the card for the user to be able use it.
4. [Manage cards](#manage-cards) – Update your card information as needed.
5. [Handle the end of life cycle](#handle-the-end-of-the-gift-card-life-cycle) – Make sure your destroy the card and delete the user once the funds are used.
## Create a physical user
Physical users are your end users, that is to say, individuals who will use the gift cards. They are identified with the `userTypeId` value `1`.
You must create users with the declarative data Treezor Compliance indicated in your KYC Form. In this use case, it corresponds to the following parameters.
| Attribute | Type | Description |
|--- |--- |--- |
| `firstname` | string | The end user's first name. |
| `lastname` | string | The end user's last name. In Sandbox, you might need to simulate the `VALIDATED` status with the dedicated suffix. |
| `birthday` | string | The end user's birthdate. Format: `YYYY-MM-DD` |
| `placeOfBirth` | string | The end user's place of birth. |
| `birthCountry` | string | The end user's birth country (format: ISO 3166-1 alpha-2) |
| `nationality` | string | The end user's nationality (format: ISO 3166-1 alpha-2) |
| `specifiedUSPerson` | integer | Needs to be set to `1` if the user is a citizen or a resident of the United States. In such cases a US tax residence (`taxResidence`) must be declared as well. |
| `email` | string | The end user's email, which must be valid and can't exceed 200 characters. |
| `mobile` | string | The end user's mobile phone number, in international E.164 format. |
| `address{1-3}` | string | The end user's postal address. The max value for each address line is 56 characters, although due to mail carrier limitations, only the first 36 are printed on envelopes used to deliver Cards. |
| `postcode` | string | The end user's address postcode. |
| `city` | string | The end user's address city. |
| `country` | string | The end user's address country (format ISO 3166-1 alpha-2) |
**Information – Declarative data to submit depends on the use case**
In our use case, users are not KYC-validated, so only the fields indicated in the KYC Form provided by Treezor are to be filled in.
You need to use the following request:
Here is a `{payload}` example:
```json [JSON]
{
"userTypeId": 1,
"specifiedUSPerson": 0,
"title": "MX",
"firstname": "Alex",
"lastname": "Oak.userStatusValidated", // Suffix to emulate VALIDATED status
"birthday": "1982-05-31",
"placeOfBirth": "Edgewood",
"birthCountry": "FR",
"nationality": "FR",
"email": "alex.oak@example.com",
"address1": "33 rosewood road",
"postcode": "75017",
"city": "Paris",
"country": "FR",
"phone": "+3311111111",
}
```
It returns a User object if successful:
```json{4} [JSON]
{
"users": [
{
"userId": 8327278,
"userTypeId": 1,
"userStatus": "VALIDATED",
"userTag": "",
"parentUserId": 0,
"parentType": "",
"controllingPersonType": 0,
"employeeType": 0,
"specifiedUSPerson": 0,
"title": "",
"firstname": "Alex",
"lastname": "Oak",
"middleNames": "",
"birthday": "1982-05-31",
"email": "alex.oak@example.com",
"address1": "33 rosewood road",
"address2": "",
"postcode": "75017",
"city": "Paris",
"state": "",
"country": "FR",
"countryName": "France",
"distributionCountry": null,
"phone": "+3311111111",
"mobile": "",
"nationality": "FR",
"nationalityOther": "",
"placeOfBirth": "Edgewood",
"birthCountry": "FR",
"occupation": "",
"incomeRange": "",
"legalName": "",
"legalNameEmbossed": "",
"legalRegistrationNumber": "",
"legalTvaNumber": "",
"legalRegistrationDate": "0000-00-00",
"legalForm": "",
"legalShareCapital": 0,
"entityType": null,
"legalSector": "",
"legalAnnualTurnOver": "",
"legalNetIncomeRange": "",
"legalNumberOfEmployeeRange": "",
"effectiveBeneficiary": 0,
"kycLevel": 1,
"kycReview": 0,
"kycReviewComment": "",
"isFreezed": 0,
"isFrozen": null,
"language": "",
"optInMailing": null,
"sepaCreditorIdentifier": "",
"taxNumber": "",
"taxResidence": "",
"position": "",
"personalAssets": "",
"createdDate": "2023-10-23 12:28:00",
"modifiedDate": "0000-00-00 00:00:00",
"walletCount": 0,
"payinCount": 0,
"totalRows": "1",
"activityOutsideEu": null,
"economicSanctions": null,
"residentCountriesSanctions": null,
"involvedSanctions": null,
"entitySanctionsQuestionnaire": null,
"address3": null,
"timezone": null,
"occupationType": "",
"isOnStockExchange": 0,
"secondaryAddress1": "",
"secondaryAddress2": "",
"secondaryAddress3": "",
"secondaryPostcode": "",
"secondaryCity": "",
"secondaryState": "",
"secondaryCountry": "",
"clientId": "945198",
"sanctionsQuestionnaireDate": null,
"codeStatus": "110009",
"informationStatus": "",
"legalSectorType": "",
"sourceOfFunds": "",
"occupationCategory": null,
"personalAssetsRange": null,
"monthlyIncomeRange": null,
"birthCityCode": null
}
]
}
```
You’ll need the `userId` parameter value for the next step.
## Create a card
The card is connected to both your company Master Wallet and the user it’s going to be allocated to. You need the corresponding `userId` and `walletId` in the next steps.
Creating a card in this use case is divided into the following steps:
1. **[Create the card restriction groups](#create-your-restriction-groups)**
2. **[Create a virtual card](#create-a-virtual-card)**
3. **[Convert a virtual card into a physicial one](#convert-a-virtual-card-into-a-physical-one)**
### Create your restriction groups
To select the relevant options for the cards that you’ll be creating in the next step, you may create the restriction groups that apply to your use case.
**Information – Restrictions are not testable in Sandbox**
When emulating card transactions to test your integration, restrictions won’t apply.
#### Merchant Id restrictions
Defining the Merchant ID (MID) restrictions allows you to easily define if the card should be usable in some specific shops.
Here are the attributes you need to create a MID restriction group.
| Attribute | Type | Description |
|--- |--- |--- |
| `name` | string | The name of the restriction group |
| `isWhitelist` | boolean | Indicates the kind of restriction: `true` (default) – Allows only a specified list of merchants (whitelist)`false` – Allows all merchants except the specified list (blacklist) |
| `merchants` | array of strings | The list of MIDs (each MID is a string). |
| `status` | string | One of the following values:`VALIDATED` – The restriction is active.`PENDING` (default) – The restriction is created but not yet active.`CANCELED` – The restriction has been deactivated (this is irreversible). |
| `startDate` | string | The date and time at which the restriction starts. Defaults to the date and time of creation. |
To create MID restrictions, use the following request:
```bash [CURL]
curl -X POST '{baseUrl}/v1/merchantIdRestrictionGroups' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}` to create a single-merchant whitelist restriction:
```json [JSON]
{
"name": "Single-merchant example",
"merchants": [
"128787"
],
"status": "VALIDATED"
}
```
It returns a Merchant ID Restriction Group object if successful:
```json [JSON] {4}
{
"merchantIdRestrictionGroups": [
{
"id": 95447,
"name": "Single-merchant example",
"isWhitelist": true,
"merchants": [
"128787"
],
"status": "VALIDATED",
"startDate": "2023-10-23 12:19:49",
"createdDate": "2023-10-23 12:19:49",
"modifiedDate": ""
}
]
}
```
Later on, you'll need the `id` to take into account the restriction during the card creation.
#### Merchant category restrictions
Defining specific merchant category codes (MCC) restrictions allows you to easily define if the card should be used in only certain categories of merchants (or, to blacklist some categories of merchants).
Here are the attributes you need to create a MCC restriction group.
| Attribute | Type | Description |
|--- |--- |--- |
| `name` | string | The name of the restriction group. |
| `isWhitelist` | boolean | Indicates the kind of restriction: `true` (default) – Allows only a specified list of merchant categories (whitelist)`false` – Allows all merchant categories except the specified list (blacklist) |
| `mcc` | array | The list of MCCs (each MCC is an integer). |
| `status` | string | One of the following values:`VALIDATED` – The restriction is active.`PENDING` (default) – The restriction is created but not yet active.`CANCELED` – The restriction has been deactivated (this is irreversible). |
| `startDate` | string | The date and time at which the restriction starts. Defaults to the date and time of creation. |
To create MCC restrictions, use the following request:
```bash [CURL]
curl -X POST '{baseUrl}/v1/mccRestrictionGroups' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}` to blacklist specific merchant categories:
```json [JSON]
{
"name": "MCC blacklist",
"mcc": [
5813,
5993
],
"status": "VALIDATED",
"isWhitelist": false
}
```
It returns the MCC Restriction Group object if successful:
```json [JSON] {4}
{
"mccRestrictionGroups": [
{
"id": 45599,
"name": "MCC blacklist",
"isWhitelist": false,
"mcc": [
5813,
5993
],
"status": "VALIDATED",
"startDate": "2023-10-31 08:58:50",
"createdDate": "2023-10-31 08:58:50",
"modifiedDate": ""
}
]
}
```
Later on, you'll need the `id` to take into account the restriction during the card creation.
#### Country restrictions
Defining specific countries allows you to easily define if the card should be used in certain countries only (or, to blacklist some countries).
Here are the attributes you need to create a Country restriction group.
| Attribute | Type | Description |
|--- |--- |--- |
| `name` | string | The name of the restriction group |
| `isWhitelist` | boolean | Indicates the kind of restriction: `true` (default) – Allows only a specified list of countries (whitelist)`false` – Allows all countries except the specified list (blacklist) |
| `countries` | array of strings | The list of countries (each country is a string featuring a Country Code in the [ISO 3166-1 numeric format 3-digit code](https://en.wikipedia.org/wiki/ISO_3166-1_numeric)). |
| `status` | string | One of the following values:`VALIDATED` – The restriction is active.`PENDING` (default) – The restriction is created but not yet active.`CANCELED` – The restriction has been deactivated (this is irreversible). |
| `startDate` | string | The date and time at which the restriction starts. Defaults to the date and time of creation. |
To create country restrictions, use the following request:
```bash [CURL]
curl -X POST '{baseUrl}/v1/countryRestrictionGroups' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}
```
Here is an example of `{payload}` to create a single-country whitelist restriction:
```json [JSON]
{
"name": "Spanish only cards",
"countries": [
"724"
],
"status": "VALIDATED"
}
```
It returns the following Country Restriction Group object if successful:
```json [JSON] {4}
{
"countryRestrictionGroups": [
{
"id": 165327,
"name": "Spanish only cards",
"isWhitelist": true,
"countries": [
"724"
],
"status": "VALIDATED",
"startDate": "2022-02-18 14:58:54",
"createdDate": "2023-10-23 12:17:26",
"modifiedDate": ""
}
]
}
```
Later on, you'll need the `id` to take into account the restriction during the card creation.
### Create a virtual card
To create a virtual card and attach to your user, you’ll need:
* The `walletId` of the Master Wallet
* The `userId` of the end user who will use the card
* The Id of the restriction groups you want to apply to your card
#### Main attributes
Here are the attributes you need to create a virtual card:
| Attribute | Type | Description |
| --- | --- | --- |
| `userId` | integer | The unique identifier of the cardholder. |
| `walletId` | integer | The unique identifier of your company Master Wallet. |
| `permsGroup` | string | A code indicating whether the card main options (contactless, online payments, withdrawals, and international payments) are activated or not. In this use case, it may be one of the following values: `TRZ-CU-011` (contactless and online payments, recommended)`TRZ-CU-003` (online payments)`TRZ-CU-009` (contactless payments)`TRZ-CU-001` (no option activated)|
| `cardPrint` | string | It corresponds to your Card Program and the options provided with them. This information is shared with you by Treezor. |
| `merchantRestrictionGroupId` | integer | The unique identifier of your MID restriction group if you’ve created one in the [previous step](#merchant-id-restrictions). |
| `mccRestrictionGroupId` | integer | The unique identifier of your MCC restriction group if you’ve created one in the [previous step](#merchant-category-restrictions). |
| `countryRestrictionGroupId` | integer | The unique identifier of your Country restriction group if you’ve created one in the [previous step](#country-restrictions). |
#### Payment and ATM limits parameters
In addition, you need to define limits in order to credit the amount you want on the card.
Ensure you fill in all the limits below by setting:
* All values you don't need to `0` to deactivate them
* At least one ATM daily, weekly, or monthly limit to another value than `0`
* At least one Payment daily, weekly, or monthly limit to another value than `0`
**Information – Limits can't be expressed in cents**
Limits only accept integer values, which means you can't have limits with decimals (except for `paymentDailyLimit`).
| Attribute | Type | Description |
| --- | --- | --- |
| `limitPaymentAll` | integer | Lifetime payment limit |
| `limitPaymentYear` | integer | Yearly payment limit |
| `limitPaymentMonth` | integer | Monthly payment limit |
| `limitPaymentWeek` | integer | Weekly payment limit |
| `limitPaymentDay` | integer | Daily payment limit |
| `paymentDailyLimit` | number | Daily payment limit (for food vouchers use cases) |
| `limitAtmAll` | integer | Lifetime withdrawal limit |
| `limitAtmYear` | integer | Yearly withdrawal limit |
| `limitAtmMonth` | integer | Monthly withdrawal limit |
| `limitAtmWeek` | integer | Weekly withdrawal limit |
| `limitAtmDay` | integer | Daily withdrawal limit |
**Best practice – ATM limit must be defined**
Even if the ATM option has been deactivated for your cards, ATM limits must be defined for the card creation to be successful.
#### Request & Response example
To create a virtual card, use the following request:
Here is an example of `{payload}` to create a virtual gift card of €25 using the previously created restriction groups:
```json [JSON]
{
"cardPrint": "{cardPrint}",
"userId": 8290083,
"walletId": 2464676,
"permsGroup": "TRZ-CU-011",
"mccRestrictionGroupId": 95447,
"merchantRestrictionGroupId": 45599,
"countryRestrictionGroupId": 165327,
"limitAtmYear": 0,
"limitAtmMonth": 0,
"limitAtmWeek": 0,
"limitAtmDay": 1,
"limitAtmAll": 1,
"limitPaymentYear": 0,
"limitPaymentMonth": 0,
"limitPaymentWeek": 0,
"limitPaymentDay": 25,
"limitPaymentAll": 25
}
```
It returns the Card object if successful:
```json [JSON]
{
"cards": [
{
"cardId": 241709,
"userId": 8290083,
"walletId": 2464676,
"walletCardtransactionId": 2473310,
"mccRestrictionGroupId": 95447,
"merchantRestrictionGroupId": 45599,
"countryRestrictionGroupId": 165327,
"publicToken": "107277882",
"cardTag": "",
"statusCode": "UNLOCK",
"isLive": 0,
"pinTryExceeds": 0,
"maskedPan": "519872******4839",
"embossedName": "ALEX OAK",
"expiryDate": "2026-10-31",
"CVV": "260",
"startDate": "2023-10-23",
"endDate": "0000-00-00",
"countryCode": "FR",
"currencyCode": "EUR",
"lang": null,
"deliveryTitle": "M",
"deliveryLastname": "OAK",
"deliveryFirstname": "ALEX",
"deliveryAddress1": "15 EDGEWOOD ROAD",
"deliveryAddress2": "",
"deliveryAddress3": "",
"deliveryCity": "ROSEWOOD",
"deliveryPostcode": "12365",
"deliveryCountry": "FR",
"mobileSent": "+33633333333",
"limitsGroup": "TRZ-VL-001",
"permsGroup": "TRZ-CU-011",
"cardDesign": "13664",
"virtualConverted": 0,
"physical": 0,
"optionAtm": 0,
"optionForeign": 0,
"optionOnline": 1,
"optionNfc": 1,
"limitAtmYear": 0,
"limitAtmMonth": 0,
"limitAtmWeek": 0,
"limitAtmDay": 1,
"limitAtmAll": 1,
"limitPaymentYear": 0,
"limitPaymentMonth": 0,
"limitPaymentWeek": 0,
"limitPaymentDay": 25,
"limitPaymentAll": 25,
"paymentDailyLimit": 0.0,
"totalAtmYear": null,
"totalAtmMonth": null,
"totalAtmWeek": null,
"totalAtmDay": null,
"totalAtmAll": null,
"totalPaymentYear": null,
"totalPaymentMonth": null,
"totalPaymentWeek": null,
"totalPaymentDay": null,
"totalPaymentAll": null,
"createdBy": 945198,
"createdDate": "2023-10-31 10:37:04",
"modifiedBy": 0,
"modifiedDate": "0000-00-00 00:00:00",
"renewalType": "A",
"renewalDate": null,
"originalCardId": null,
"totalRows": null,
"designCode": null,
"cardLanguages": "",
"eventName": "Master Wallet",
"eventAlias": "master-wallet-6537b83040735",
"restrictionGroupLimits": null,
"cancellationNumber": "",
"metadata": null,
"renewalDate": null,
"renewalType": null,
"originalCardId": null,
"logoId": "",
"logoBackId": "",
"packageId": "",
"customizeInfo": "",
"letterCustomizedInfo": "",
"freeCustomizedInfo": "",
"deliveryMethod": null,
"pinMailer": null,
"batchDeliveryId": null,
"sendToParent": 0,
"isTemporary": true
}
]
}
```
### Convert a virtual card into a physical one
You can convert a virtual card into a physical one (the card will become "virtual converted", which means it will exist in both forms). When doing so, a physical card is created and delivered to the end user’s address.
**Tip – The ability to create physical cards directly depends on the Card Program**
The default Card Program supports both virtual and physical cards. As a result, the endpoint to create directly a physical card is not available. You must create a virtual card to convert, even if you don't plan on exposing it to your end users.
To convert a card, use the following request, with the `id` of the card to convert as a path parameter:
```bash [CURL]
curl -X PUT '{baseUrl}/v1/cards/{cardId}/ConvertVirtual' \
--header 'Authorization: Bearer {accessToken}'
```
It returns the Card object if successful, with the `virtualConverted` attribute set to `1`.
```json [JSON] {38}
{
"cards": [
{
"cardId": 239391,
"userId": 8322635,
"walletId": 2462231,
"walletCardtransactionId": 2462233,
"mccRestrictionGroupId": 0,
"merchantRestrictionGroupId": 0,
"countryRestrictionGroupId": 0,
"publicToken": "107199750",
"cardTag": "Event-test-card",
"statusCode": "UNLOCK",
"isLive": 0,
"pinTryExceeds": 0,
"maskedPan": "519872******5608",
"embossedName": "JOHN SMITH",
"expiryDate": "2026-10-31",
"CVV": "901",
"startDate": "2023-10-23",
"endDate": "0000-00-00",
"countryCode": "FR",
"currencyCode": "EUR",
"lang": null,
"deliveryTitle": "M",
"deliveryLastname": "SMITH",
"deliveryFirstname": "JOHN",
"deliveryAddress1": "33 AVENUE DE WAGRAM",
"deliveryAddress2": "",
"deliveryAddress3": "",
"deliveryCity": "PARIS",
"deliveryPostcode": "75017",
"deliveryCountry": "FR",
"mobileSent": "+33141358530",
"limitsGroup": "TRZ-VL-001",
"permsGroup": "TRZ-CU-016",
"cardDesign": "13664",
"virtualConverted": 1,
"physical": 0,
"optionAtm": 1,
"optionForeign": 1,
"optionOnline": 1,
"optionNfc": 1,
"limitAtmYear": 0,
"limitAtmMonth": 0,
"limitAtmWeek": 2000,
"limitAtmDay": 1000,
"limitAtmAll": 0,
"limitPaymentYear": 0,
"limitPaymentMonth": 0,
"limitPaymentWeek": 3000,
"limitPaymentDay": 2000,
"limitPaymentAll": 0,
"paymentDailyLimit": 0.0,
"totalAtmYear": null,
"totalAtmMonth": null,
"totalAtmWeek": null,
"totalAtmDay": null,
"totalAtmAll": null,
"totalPaymentYear": null,
"totalPaymentMonth": null,
"totalPaymentWeek": null,
"totalPaymentDay": null,
"totalPaymentAll": null,
"createdBy": 945198,
"createdDate": "2023-10-23 13:55:34",
"modifiedBy": 945198,
"modifiedDate": "2023-10-23 14:09:18",
"renewalType": "A",
"renewalDate": null,
"originalCardId": null,
"totalRows": null,
"designCode": null,
"cardLanguages": "",
"eventName": "Event_test",
"eventAlias": "event-test-65365bb9d864b",
"restrictionGroupLimits": null,
"cancellationNumber": "",
"metadata": null,
"renewalDate": null,
"renewalType": null,
"originalCardId": null,
"logoId": "",
"logoBackId": "",
"packageId": "",
"customizeInfo": "",
"letterCustomizedInfo": "",
"freeCustomizedInfo": "",
"deliveryMethod": null,
"pinMailer": null,
"batchDeliveryId": null,
"sendToParent": 0,
"isTemporary": true
}
]
}
```
### Retrieve a virtual card
The created virtual cards are available as an image (base64 encoded format). You can retrieve a card and expose it to your users.
To retrieve a virtual card, use the following request with the `cardId` as a query parameter.
```bash [CURL]
curl -X POST '{baseUrl}/v1/cardimages?cardId={cardId}' \
--header 'Authorization: Bearer {accessToken}' \
```
It returns the Card Image object if successful:
```json [JSON]
{
"cardimages": [
{
"id": "155341",
"cardId": "239391",
"file": "/xj/base64encodedfile"
}
]
}
```
**Security – Sensitive data storage is forbidden**
You are forbidden from storing card images on your servers (except if you are PCI/DSS-certified).
## Activate a card
As a security measure, all Cards are issued in an `inactive` state to ensure that a Card is not usable before the cardholder receives it. Inactive cards can’t be used to make any type of payment or withdrawal.
There are two possible ways to activate a card:
* **[Machine-to-machine](#machine-to-machine-activation)** – To automate the activation without any action from your end users (e.g., they directly receive the virtual card through your app).
* **[User-oriented](#user-oriented-activation)** – To process an end user action (when you provide in your app a way for your end users to activate the card).
In addition, you have to [Enroll the card for 3DS](#enroll-the-card-for-3d-secure).
### Machine-to-machine activation
To activate a card, use the following request, with the `id` of the card to activate as a path parameter:
```bash [CURL]
curl -X PUT '{baseUrl}/v1/cards/{id}/Activate' \
--header 'Authorization: Bearer {accessToken}'
```
It returns the Card object if successful, with the `isLive` attribute set to `1`.
```json [JSON] {14}
{
"cards": [
{
"cardId": 244989,
"userId": 8290083,
"walletId": 2464676,
"walletCardtransactionId": 2487810,
"mccRestrictionGroupId": 0,
"merchantRestrictionGroupId": 0,
"countryRestrictionGroupId": 0,
"publicToken": "107290575",
"cardTag": "",
"statusCode": "UNLOCK",
"isLive": 1,
"pinTryExceeds": 0,
"maskedPan": "519872******8922",
"embossedName": "ALEX OAK",
"expiryDate": "2026-11-30",
"CVV": "843",
"startDate": "2023-11-23",
"endDate": "0000-00-00",
"countryCode": "FR",
"currencyCode": "EUR",
"lang": null,
"deliveryTitle": "M",
"deliveryLastname": "OAK",
"deliveryFirstname": "ALEX",
"deliveryAddress1": "15 EDGEWOOD ROAD",
"deliveryAddress2": "",
"deliveryAddress3": "",
"deliveryCity": "ROSEWOOD",
"deliveryPostcode": "12365",
"deliveryCountry": "FR",
"mobileSent": "+33633333333",
"limitsGroup": "TRZ-VL-001",
"permsGroup": "TRZ-CU-011",
"cardDesign": "13664",
"virtualConverted": 0,
"physical": 0,
"optionAtm": 0,
"optionForeign": 0,
"optionOnline": 1,
"optionNfc": 1,
"limitAtmYear": 0,
"limitAtmMonth": 0,
"limitAtmWeek": 0,
"limitAtmDay": 1,
"limitAtmAll": 1,
"limitPaymentYear": 0,
"limitPaymentMonth": 0,
"limitPaymentWeek": 0,
"limitPaymentDay": 25,
"limitPaymentAll": 25,
"paymentDailyLimit": 0.0,
"totalAtmYear": null,
"totalAtmMonth": null,
"totalAtmWeek": null,
"totalAtmDay": null,
"totalAtmAll": null,
"totalPaymentYear": null,
"totalPaymentMonth": null,
"totalPaymentWeek": null,
"totalPaymentDay": null,
"totalPaymentAll": null,
"createdBy": 945198,
"createdDate": "2023-11-13 12:40:35",
"modifiedBy": 945198,
"modifiedDate": "2023-11-13 13:41:27",
"renewalType": "A",
"renewalDate": null,
"originalCardId": null,
"totalRows": null,
"designCode": null,
"cardLanguages": "",
"eventName": "Master Wallet",
"eventAlias": "master-wallet-6537b83040735",
"restrictionGroupLimits": null,
"cancellationNumber": "",
"metadata": null,
"renewalDate": null,
"renewalType": null,
"originalCardId": null,
"logoId": "",
"logoBackId": "",
"packageId": "",
"customizeInfo": "",
"letterCustomizedInfo": "",
"freeCustomizedInfo": "",
"deliveryMethod": null,
"pinMailer": null,
"batchDeliveryId": null,
"sendToParent": 0,
"isTemporary": true
}
]
}
```
### User-oriented activation
To activate a card, use the following request, with the `publicToken` of the card to activate as a path parameter:
```bash [CURL]
curl -X PUT '{baseUrl}/v1/cards/{cardToken}/public-token-activation' \
--header 'Authorization: Bearer {accessToken}'
```
It returns the Card object if successful, with the `isLive` attribute set to `1`.
```json [JSON] {14}
{
"cards": [
{
"cardId": 244989,
"userId": 8290083,
"walletId": 2464676,
"walletCardtransactionId": 2487810,
"mccRestrictionGroupId": 0,
"merchantRestrictionGroupId": 0,
"countryRestrictionGroupId": 0,
"publicToken": "107290575",
"cardTag": "",
"statusCode": "UNLOCK",
"isLive": 1,
"pinTryExceeds": 0,
"maskedPan": "519872******8922",
"embossedName": "ALEX OAK",
"expiryDate": "2026-11-30",
"CVV": "843",
"startDate": "2023-11-23",
"endDate": "0000-00-00",
"countryCode": "FR",
"currencyCode": "EUR",
"lang": null,
"deliveryTitle": "M",
"deliveryLastname": "OAK",
"deliveryFirstname": "ALEX",
"deliveryAddress1": "15 EDGEWOOD ROAD",
"deliveryAddress2": "",
"deliveryAddress3": "",
"deliveryCity": "ROSEWOOD",
"deliveryPostcode": "12365",
"deliveryCountry": "FR",
"mobileSent": "+33633333333",
"limitsGroup": "TRZ-VL-001",
"permsGroup": "TRZ-CU-011",
"cardDesign": "13664",
"virtualConverted": 0,
"physical": 0,
"optionAtm": 0,
"optionForeign": 0,
"optionOnline": 1,
"optionNfc": 1,
"limitAtmYear": 0,
"limitAtmMonth": 0,
"limitAtmWeek": 0,
"limitAtmDay": 1,
"limitAtmAll": 1,
"limitPaymentYear": 0,
"limitPaymentMonth": 0,
"limitPaymentWeek": 0,
"limitPaymentDay": 25,
"limitPaymentAll": 25,
"paymentDailyLimit": 0.0,
"totalAtmYear": null,
"totalAtmMonth": null,
"totalAtmWeek": null,
"totalAtmDay": null,
"totalAtmAll": null,
"totalPaymentYear": null,
"totalPaymentMonth": null,
"totalPaymentWeek": null,
"totalPaymentDay": null,
"totalPaymentAll": null,
"createdBy": 945198,
"createdDate": "2023-11-13 12:40:35",
"modifiedBy": 945198,
"modifiedDate": "2023-11-13 13:41:27",
"renewalType": "A",
"renewalDate": null,
"originalCardId": null,
"totalRows": null,
"designCode": null,
"cardLanguages": "",
"eventName": "Master Wallet",
"eventAlias": "master-wallet-6537b83040735",
"restrictionGroupLimits": null,
"cancellationNumber": "",
"metadata": null,
"renewalDate": null,
"renewalType": null,
"originalCardId": null,
"logoId": "",
"logoBackId": "",
"packageId": "",
"customizeInfo": "",
"letterCustomizedInfo": "",
"freeCustomizedInfo": "",
"deliveryMethod": null,
"pinMailer": null,
"batchDeliveryId": null,
"sendToParent": 0,
"isTemporary": true
}
]
}
```
## Enroll the card for 3D Secure
Enrolling the card with the 3DS protocol will ensure the payment isn't declined if strong customer authentication is triggered during an online payment.
To enroll a card for 3DS, use the following request:
```bash [CURL]
curl -X POST '{baseUrl}/v1/cards/Register3DS' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}
```
With the `{payload}` containing the `cardId`:
```json [JSON]
{
"cardId": 241709
}
```
An HTTP 200 response confirms the operation.
## Manage cards
You can manage and update the cards after their creation. Here are a few actions that may prove useful to your use case:
* [Update card options](#update-card-options)
* [Update card limits](#update-card-limits)
* [Update card restrictions](#update-card-restrictions)
* [Block a card](#block-a-card)
### Update card options
To update the card options, use the following request with the `id` of the card to update as a path parameter:
```bash [CURL]
curl -X PUT '{baseUrl}/v1/cards/{id}/Options' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}`
```
Here is an example of `{payload}`:
```json [JSON]
{
"atm":1,
"online":1,
"nfc":1,
"foreign":0
}
```
It returns the Card object if successful:
```json [JSON] {36,40-43}
{
"cards": [
{
"cardId": 241709,
"userId": 8290083,
"walletId": 2464676,
"walletCardtransactionId": 2473310,
"mccRestrictionGroupId": 0,
"merchantRestrictionGroupId": 0,
"countryRestrictionGroupId": 0,
"publicToken": "107277882",
"cardTag": "",
"statusCode": "UNLOCK",
"isLive": 1,
"pinTryExceeds": 0,
"maskedPan": "519872******4839",
"embossedName": "ALEX OAK",
"expiryDate": "2026-10-31",
"CVV": "260",
"startDate": "2023-10-23",
"endDate": "0000-00-00",
"countryCode": "FR",
"currencyCode": "EUR",
"lang": null,
"deliveryTitle": "M",
"deliveryLastname": "OAK",
"deliveryFirstname": "ALEX",
"deliveryAddress1": "15 EDGEWOOD ROAD",
"deliveryAddress2": "",
"deliveryAddress3": "",
"deliveryCity": "ROSEWOOD",
"deliveryPostcode": "12365",
"deliveryCountry": "FR",
"mobileSent": "+33633333333",
"limitsGroup": "TRZ-VL-001",
"permsGroup": "TRZ-CU-016",
"cardDesign": "13664",
"virtualConverted": 0,
"physical": 0,
"optionAtm": 1,
"optionForeign": 1,
"optionOnline": 1,
"optionNfc": 1,
"limitAtmYear": 0,
"limitAtmMonth": 0,
"limitAtmWeek": 2000,
"limitAtmDay": 1000,
"limitAtmAll": 0,
"limitPaymentYear": 0,
"limitPaymentMonth": 0,
"limitPaymentWeek": 3000,
"limitPaymentDay": 2000,
"limitPaymentAll": 2500,
"paymentDailyLimit": 0.0,
"totalAtmYear": null,
"totalAtmMonth": null,
"totalAtmWeek": null,
"totalAtmDay": null,
"totalAtmAll": null,
"totalPaymentYear": null,
"totalPaymentMonth": null,
"totalPaymentWeek": null,
"totalPaymentDay": null,
"totalPaymentAll": null,
"createdBy": 945198,
"createdDate": "2023-10-31 10:37:04",
"modifiedBy": 945198,
"modifiedDate": "2023-11-07 15:34:33",
"renewalType": "A",
"renewalDate": null,
"originalCardId": null,
"totalRows": null,
"designCode": null,
"cardLanguages": "",
"eventName": "Master Wallet",
"eventAlias": "master-wallet-6537b83040735",
"restrictionGroupLimits": null,
"cancellationNumber": "",
"metadata": null,
"renewalDate": null,
"renewalType": null,
"originalCardId": null,
"logoId": "",
"logoBackId": "",
"packageId": "",
"customizeInfo": "",
"letterCustomizedInfo": "",
"freeCustomizedInfo": "",
"deliveryMethod": null,
"pinMailer": null,
"batchDeliveryId": null,
"sendToParent": 0,
"isTemporary": true
}
]
}
```
**Information – Options are correlated with the `permsGroup` parameter**
When updating your card options, the Card [Permission Group](/guide/cards/restrictions-limits#options-permission-groups) is automatically updated as well.
### Update card limits
To update the card limits, use the following request with the `id` of the card to update as a path parameter:
```bash [CURL]
curl -X PUT '{baseUrl}/v1/cards/{id}/Limits' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"limitPaymentAll":25,
"limitPaymentYear":0,
"limitPaymentMonth":0,
"limitPaymentWeek":10,
"limitPaymentDay":0,
"limitAtmAll":0,
"limitAtmYear":0,
"limitAtmMonth":0,
"limitAtmWeek":1,
"limitAtmDay":0
}
```
It returns the Card object if successful:
```json [JSON] {44-53}
{
"cards": [
{
"cardId": 241709,
"userId": 8290083,
"walletId": 2464676,
"walletCardtransactionId": 2473310,
"mccRestrictionGroupId": 0,
"merchantRestrictionGroupId": 0,
"countryRestrictionGroupId": 0,
"publicToken": "107277882",
"cardTag": "",
"statusCode": "UNLOCK",
"isLive": 1,
"pinTryExceeds": 0,
"maskedPan": "519872******4839",
"embossedName": "ALEX OAK",
"expiryDate": "2026-10-31",
"CVV": "260",
"startDate": "2023-10-23",
"endDate": "0000-00-00",
"countryCode": "FR",
"currencyCode": "EUR",
"lang": null,
"deliveryTitle": "M",
"deliveryLastname": "OAK",
"deliveryFirstname": "ALEX",
"deliveryAddress1": "15 EDGEWOOD ROAD",
"deliveryAddress2": "",
"deliveryAddress3": "",
"deliveryCity": "ROSEWOOD",
"deliveryPostcode": "12365",
"deliveryCountry": "FR",
"mobileSent": "+33633333333",
"limitsGroup": "TRZ-VL-001",
"permsGroup": "TRZ-CU-016",
"cardDesign": "13664",
"virtualConverted": 0,
"physical": 0,
"optionAtm": 1,
"optionForeign": 1,
"optionOnline": 1,
"optionNfc": 1,
"limitAtmYear": 2000,
"limitAtmMonth": 2000,
"limitAtmWeek": 2000,
"limitAtmDay": 1000,
"limitAtmAll": 0,
"limitPaymentYear": 5000,
"limitPaymentMonth": 0,
"limitPaymentWeek": 3000,
"limitPaymentDay": 2000,
"limitPaymentAll": 2500,
"paymentDailyLimit": 0.0,
"totalAtmYear": null,
"totalAtmMonth": null,
"totalAtmWeek": null,
"totalAtmDay": null,
"totalAtmAll": null,
"totalPaymentYear": null,
"totalPaymentMonth": null,
"totalPaymentWeek": null,
"totalPaymentDay": null,
"totalPaymentAll": null,
"createdBy": 945198,
"createdDate": "2023-10-31 10:37:04",
"modifiedBy": 945198,
"modifiedDate": "2023-11-07 15:34:33",
"renewalType": "A",
"renewalDate": null,
"originalCardId": null,
"totalRows": null,
"designCode": null,
"cardLanguages": "",
"eventName": "Master Wallet",
"eventAlias": "master-wallet-6537b83040735",
"restrictionGroupLimits": null,
"cancellationNumber": "",
"metadata": null,
"renewalDate": null,
"renewalType": null,
"originalCardId": null,
"logoId": "",
"logoBackId": "",
"packageId": "",
"customizeInfo": "",
"letterCustomizedInfo": "",
"freeCustomizedInfo": "",
"deliveryMethod": null,
"pinMailer": null,
"batchDeliveryId": null,
"sendToParent": 0,
"isTemporary": true
}
]
}
```
### Update card restrictions
To update the card restrictions, use the following request with the `id` of the card to update as a path parameter:
```bash [CURL]
curl -X PUT '{baseUrl}/v1/cards/{id}' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`, which contains each of the possible restriction groups:
```json [JSON]
{
"mccRestrictionGroupId": 95447,
"merchantRestrictionGroupId": 45599,
"countryRestrictionGroupId": 165327
}
```
It returns the Card object if successful:
```json [JSON] {8-10}
{
"cards": [
{
"cardId": 241709,
"userId": 8290083,
"walletId": 2464676,
"walletCardtransactionId": 2473310,
"mccRestrictionGroupId": 45633,
"merchantRestrictionGroupId": 95988,
"countryRestrictionGroupId": 165327,
"publicToken": "107277882",
"cardTag": "",
"statusCode": "UNLOCK",
"isLive": 1,
"pinTryExceeds": 0,
"maskedPan": "519872******4839",
"embossedName": "ALEX OAK",
"expiryDate": "2026-10-31",
"CVV": "260",
"startDate": "2023-10-23",
"endDate": "0000-00-00",
"countryCode": "FR",
"currencyCode": "EUR",
"lang": null,
"deliveryTitle": "M",
"deliveryLastname": "OAK",
"deliveryFirstname": "ALEX",
"deliveryAddress1": "15 EDGEWOOD ROAD",
"deliveryAddress2": "",
"deliveryAddress3": "",
"deliveryCity": "ROSEWOOD",
"deliveryPostcode": "12365",
"deliveryCountry": "FR",
"mobileSent": "+33633333333",
"limitsGroup": "TRZ-VL-001",
"permsGroup": "TRZ-CU-016",
"cardDesign": "13664",
"virtualConverted": 0,
"physical": 0,
"optionAtm": 1,
"optionForeign": 1,
"optionOnline": 1,
"optionNfc": 1,
"limitAtmYear": 2000,
"limitAtmMonth": 2000,
"limitAtmWeek": 2000,
"limitAtmDay": 1000,
"limitAtmAll": 0,
"limitPaymentYear": 5000,
"limitPaymentMonth": 0,
"limitPaymentWeek": 3000,
"limitPaymentDay": 2000,
"limitPaymentAll": 2500,
"paymentDailyLimit": 0.0,
"totalAtmYear": null,
"totalAtmMonth": null,
"totalAtmWeek": null,
"totalAtmDay": null,
"totalAtmAll": null,
"totalPaymentYear": null,
"totalPaymentMonth": null,
"totalPaymentWeek": null,
"totalPaymentDay": null,
"totalPaymentAll": null,
"createdBy": 945198,
"createdDate": "2023-10-31 10:37:04",
"modifiedBy": 945198,
"modifiedDate": "2023-11-07 16:29:52",
"renewalType": "A",
"renewalDate": null,
"originalCardId": null,
"totalRows": null,
"designCode": null,
"cardLanguages": "",
"eventName": "Master Wallet",
"eventAlias": "master-wallet-6537b83040735",
"restrictionGroupLimits": null,
"cancellationNumber": "",
"metadata": null,
"renewalDate": null,
"renewalType": null,
"originalCardId": null,
"logoId": "",
"logoBackId": "",
"packageId": "",
"customizeInfo": "",
"letterCustomizedInfo": "",
"freeCustomizedInfo": "",
"deliveryMethod": null,
"pinMailer": null,
"batchDeliveryId": null,
"sendToParent": 0
}
]
}
```
### Block a card
If you suspect fraud or misuse, the API allows you to temporarily or permanently block a card, effective immediately.
The `lockStatus` attribute allows you to set the desired `statusCode` for the card, hence choosing to block it in a way that is relevant to the encountered situation.
| Code | Plaintext value | Description | Lock type |
| :---: | --- | --- | --- |
| `0` | `UNLOCK` | The card is unlocked and can be used (if no other options or limits prevent it). | N/A |
| `1` | `LOCK` | The card is locked and cannot be used. | Reversible |
| `2` | `LOST` | The card is lost and cannot be used. | Permanent |
| `3` | `STOLEN` | The card is stolen and cannot be used. | Permanent |
| `4` | `DESTROYED` | The card is terminated and cannot be used. | Permanent |
| `5` | `LOCK_INTERNAL` | The card is locked by Treezor and cannot be used, only Treezor is able to unlock it. | Reversible |
| `6` | `EXPIRED` | Automatically set value indicating the card has expired. The card was either renewed or the expiry date passed. Treezor sends the following webhooks: [`card.expiryAlert`](/guide/cards/events#card-expiryalert) – The card expires at the end of the next month; you can anticipate [Renewal](/guide/cards/renewal). [`card.update`](/guide/cards/events#card-update) – The card expired. | Permanent |
| `7` | `CUSTOM_LOCK` | Secondary lock; the card is locked and cannot be used. This is the same mechanism as `LOCK`, providing you more flexibility to manage cards (e.g., reporting reasons, preventing cardholders to unlock the card themselves). | Reversible |
To block a card, use the following request with the `id` of the card to block as a path parameter:
```bash [CURL]
curl -X PUT '{baseUrl}/v1/cards/{id}/LockUnlock' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}` setting the `lockStatus` to locked (temporarily):
```json [JSON]
{
"lockStatus":1
}
```
It returns the Card object if successful, with the updated `statusCode` (displayed a plaintext value):
```json [JSON] {13}
{
"cards": [
{
"cardId": 241709,
"userId": 8290083,
"walletId": 2464676,
"walletCardtransactionId": 2473310,
"mccRestrictionGroupId": 45633,
"merchantRestrictionGroupId": 95988,
"countryRestrictionGroupId": 165327,
"publicToken": "107277882",
"cardTag": "",
"statusCode": "LOCK",
"isLive": 1,
"pinTryExceeds": 0,
"maskedPan": "519872******4839",
"embossedName": "ALEX OAK",
"expiryDate": "2026-10-31",
"CVV": "260",
"startDate": "2023-10-23",
"endDate": "0000-00-00",
"countryCode": "FR",
"currencyCode": "EUR",
"lang": null,
"deliveryTitle": "M",
"deliveryLastname": "OAK",
"deliveryFirstname": "ALEX",
"deliveryAddress1": "15 EDGEWOOD ROAD",
"deliveryAddress2": "",
"deliveryAddress3": "",
"deliveryCity": "ROSEWOOD",
"deliveryPostcode": "12365",
"deliveryCountry": "FR",
"mobileSent": "+33633333333",
"limitsGroup": "TRZ-VL-001",
"permsGroup": "TRZ-CU-016",
"cardDesign": "13664",
"virtualConverted": 0,
"physical": 0,
"optionAtm": 1,
"optionForeign": 1,
"optionOnline": 1,
"optionNfc": 1,
"limitAtmYear": 2000,
"limitAtmMonth": 2000,
"limitAtmWeek": 2000,
"limitAtmDay": 1000,
"limitAtmAll": 0,
"limitPaymentYear": 5000,
"limitPaymentMonth": 0,
"limitPaymentWeek": 3000,
"limitPaymentDay": 2000,
"limitPaymentAll": 2500,
"paymentDailyLimit": 0.0,
"totalAtmYear": null,
"totalAtmMonth": null,
"totalAtmWeek": null,
"totalAtmDay": null,
"totalAtmAll": null,
"totalPaymentYear": null,
"totalPaymentMonth": null,
"totalPaymentWeek": null,
"totalPaymentDay": null,
"totalPaymentAll": null,
"createdBy": 945198,
"createdDate": "2023-10-31 10:37:04",
"modifiedBy": 945198,
"modifiedDate": "2023-11-07 17:01:40",
"renewalType": "A",
"renewalDate": null,
"originalCardId": null,
"totalRows": null,
"designCode": null,
"cardLanguages": "",
"eventName": "Master Wallet",
"eventAlias": "master-wallet-6537b83040735",
"restrictionGroupLimits": null,
"cancellationNumber": "",
"metadata": null,
"renewalDate": null,
"renewalType": null,
"originalCardId": null,
"logoId": "",
"logoBackId": "",
"packageId": "",
"customizeInfo": "",
"letterCustomizedInfo": "",
"freeCustomizedInfo": "",
"deliveryMethod": null,
"pinMailer": null,
"batchDeliveryId": null,
"sendToParent": 0,
"isTemporary": true
}
]
}
```
## Handle the end of the gift card life cycle
Once the gift card is used by the end user (`totalPaymentAll` is reached), and if this was a one-time use card, you need to perform the following actions:
1. [Destroy the card](#destroy-the-card)
2. [Deactivate the user](#deactivate-the-user)
### Check the card has been used
Because you’ve defined the card amount using the `limitPaymentAll` parameter, you can use the `cardtransaction.create` webhook to be notified once the card has been used.
In such cases, the `totalPaymentAll` value equals the `limitPaymentAll`.
Here is an example of `cardtransaction.create` webhook using fully the gift card available amount:
```json [JSON] {10,11}
{
"webhook": "cardtransaction.create",
"webhook_id": "42xxxxxx7",
"object": "cardtransaction",
"object_id": "8xxxxxx5",
"object_payload": {
"cardtransactions": [
{
// [...] some attributes are hidden
"limitPaymentAll": "25.00",
"totalPaymentAll": "25.00",
"paymentAmount": "25.00",
"paymentStatus": "A",
"authorizationNote": "",
"authorizationResponseCode": "0",
// [...] some attributes are hidden
}
]
},
"object_payload_signature": "2rshbUX7b2xtxPOYKgHKvvDx9MA/19Aep07yzSpDm5U="
}
```
### Destroy the card
Once the card has been used, you must destroy it by updating its status accordingly (see [Block a card](#block-a-card) section for more information on card statuses).
To destroy a card, use the following request with the `id` of the card to destroy as a path parameter:
```bash [CURL]
curl -X PUT '{baseUrl}/v1/cards/{cardId}/LockUnlock' |
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
And in the `{payload}`, set the `lockStatus` to `4` for `DESTROYED`:
```json [JSON]
{
"lockStatus":4
}
```
It returns the Card object if successful, with the updated `statusCode` (displayed a plaintext value):
```json [JSON] {13}
{
"cards": [
{
"cardId": 241709,
"userId": 8290083,
"walletId": 2464676,
"walletCardtransactionId": 2473310,
"mccRestrictionGroupId": 45633,
"merchantRestrictionGroupId": 95988,
"countryRestrictionGroupId": 165327,
"publicToken": "107277882",
"cardTag": "",
"statusCode": "DESTROYED",
"isLive": 1,
"pinTryExceeds": 0,
"maskedPan": "519872******4839",
"embossedName": "ALEX OAK",
"expiryDate": "2026-10-31",
"CVV": "260",
"startDate": "2023-10-23",
"endDate": "0000-00-00",
"countryCode": "FR",
"currencyCode": "EUR",
"lang": null,
"deliveryTitle": "M",
"deliveryLastname": "OAK",
"deliveryFirstname": "ALEX",
"deliveryAddress1": "15 EDGEWOOD ROAD",
"deliveryAddress2": "",
"deliveryAddress3": "",
"deliveryCity": "ROSEWOOD",
"deliveryPostcode": "12365",
"deliveryCountry": "FR",
"mobileSent": "+33633333333",
"limitsGroup": "TRZ-VL-001",
"permsGroup": "TRZ-CU-016",
"cardDesign": "13664",
"virtualConverted": 0,
"physical": 0,
"optionAtm": 1,
"optionForeign": 1,
"optionOnline": 1,
"optionNfc": 1,
"limitAtmYear": 2000,
"limitAtmMonth": 2000,
"limitAtmWeek": 2000,
"limitAtmDay": 1000,
"limitAtmAll": 0,
"limitPaymentYear": 5000,
"limitPaymentMonth": 0,
"limitPaymentWeek": 3000,
"limitPaymentDay": 2000,
"limitPaymentAll": 2500,
"paymentDailyLimit": 0.0,
"totalAtmYear": null,
"totalAtmMonth": null,
"totalAtmWeek": null,
"totalAtmDay": null,
"totalAtmAll": null,
"totalPaymentYear": null,
"totalPaymentMonth": null,
"totalPaymentWeek": null,
"totalPaymentDay": null,
"totalPaymentAll": 2500,
"createdBy": 945198,
"createdDate": "2023-10-31 10:37:04",
"modifiedBy": 945198,
"modifiedDate": "2023-11-07 17:01:40",
"renewalType": "A",
"renewalDate": null,
"originalCardId": null,
"totalRows": null,
"designCode": null,
"cardLanguages": "",
"eventName": "Master Wallet",
"eventAlias": "master-wallet-6537b83040735",
"restrictionGroupLimits": null,
"cancellationNumber": "",
"metadata": null,
"renewalDate": null,
"renewalType": null,
"originalCardId": null,
"logoId": "",
"logoBackId": "",
"packageId": "",
"customizeInfo": "",
"letterCustomizedInfo": "",
"freeCustomizedInfo": "",
"deliveryMethod": null,
"pinMailer": null,
"batchDeliveryId": null,
"sendToParent": 0,
"isTemporary": true
}
]
}
```
### Deactivate the user
For legal reasons, Users cannot be deleted. They are permanently “Canceled” instead.
To cancel a user, use the following request with the `id` of the user to cancel as a path parameter:
In the `{payload}`, specify the mandatory `origin` parameter to `OPERATOR`, indicating you’re at the origin of the cancellation.
It returns a User object if successful, with the `userStatus` set to `CANCELED`:
**Tip – Recreate a user with the same email**
The unique email rule only applies to active users. In other words, once the user canceled, you can create them again using the same email.
---
---
url: /guide/use-cases/gift-cards/nocode-guide.md
description: >-
Issue and manage Gift Cards using the Treezor Dashboard application. This
no-code implementation guide takes you step-by-step through creating cards,
managing users, applying restrictions, and handling card lifecycle without
needing technical knowledge.
---
# Gift cards: No-code guide
The no-code guide will take you through the following steps to successfully create users and gift cards:
1. [Get to know your Dashboard](#get-to-know-your-dashboard) – Learn how to log into the Dashboard and discover the interface.
2. [Create card restriction groups](#create-card-restriction-groups) – Predefine your restriction groups to save time during the card creation process.
3. [Create physical cards in bulk](#create-physical-cards-in-bulk) – Create several cards at once while automatically generating users.
4. [Update the user declarative data](#update-the-user-declarative-data) – Define your users with the required information.
5. [Activate and manage cards](#activate-cards) – Make the final changes to the card for the end user to use.
6. [Handle the end of life cycle](#handle-the-end-of-the-gift-card-life-cycle) – Make sure your destroy the card and delete the user once the funds are used.
**Information – Some features are unavailable**
The no-code guide may propose fewer options as some features are not available in the Dashboard. Workarounds are available in the API guide (coming soon).
## Get to know your Dashboard
The no-code guide relies on Treezor's Dashboard, a user interface allowing you to interact with the Treezor API without relying on developer tools.
### Log into your Dashboard
Treezor provided you with the URL to log into your Dashboard. For your Sandbox, the URL is built as follows:
* `https://dashboard-{yourCompanyName}.sandbox.treezor.co`
Upon entering this URL, you'll be redirected to the sign-in page, which is different depending on whether you've opted for [standard login with 2FA](/guide/dashboard/introduction#standard-login-with-2fa) or [Company SSO login](/guide/dashboard/introduction#company-sso-login).
Below is an example of Treezor's default login page.
### Discover the Dashboard interface
Before you start, let’s take a quick guided tour of the key components of the Dashboard interface.
**Note – Your Dashboard is customizable**
The views may differ from the screenshots displayed depending on:
* Where you’re at in your integration process, if you’re customizing the design
* The [User Role](/guide/dashboard/dashboard-users#dashboard-user-roles) of the logged-in user, if you’re not using all of Treezor's features
* Your localization and language selection
| # | Section | Description |
| :---: | --- | --- |
| | Navigation menu | Located on the left-hand side, this foldable menu allows you to navigate to the different views:*Dashboard* views, which focus on the features.*Configuration* views, which are about setting up your Dashboard. |
| | Main toolbar | In the upper part of each view, the Main toolbar contains the search field, the list of favorites, the language selection, and the account drop-down, for you to log out or access your *Account* page. |
| | Main view | Main content, which depends on the selected view. By default, the *Users* view is displayed. |
| | Environment | In the bottom left corner, you’ll find information about your environment and the version of the Dashboard. |
## Predefine card restriction groups
To select the relevant options for the cards that you’ll be creating in the next step, you may create the restriction groups that apply to your use case. This step requires the Administrator user role.
**Information – Restrictions are not testable in Sandbox**
When emulating card transactions to test your integration, restrictions won’t apply.
In the *Administration* section of the navigation menu, select the [*Predefined Restriction Groups*](/guide/dashboard/card-restrictions) view to start creating restrictions.
### Merchant ID restrictions
Defining the [Merchant ID (MID)](/guide/overview/glossary#mid-merchant-identifier) restrictions allows you to define if the card should be usable in some specific merchants.
→ In the *Merchant Id Groups* tab, click on the “Add a new restriction” button to start creating your Merchant Id restriction group.
→ In the displayed popup:
* Define a name and a start date for your restriction group
* Select whether you want to blacklist or whitelist a group of Merchant Ids
* Enter the codes manually or upload a CSV file (the list of values in a single column)
* Click on the “Save” button to validate your creation
### MCC restrictions
Defining the [merchant category codes (MCC)](/guide/overview/glossary#mcc-merchant-category-code) restrictions allows you to define if the card should be used in only certain categories of merchants (or, to blacklist some categories of merchants).
→ In the *MCC Groups* tab, click on the “Add a new restriction” button to start creating your MCC restriction group.
→ In the displayed popup:
* Define a name and a start date for your restriction group
* Select whether you want to blacklist or whitelist a group of MCC codes
* Enter the codes manually or upload a CSV file (the list of values in a single column)
* Click on the “Save” button to validate your creation
### Country restrictions
Defining specific country restrictions allows you to define if the card should be used in certain countries only (or, to blacklist some countries).
→ In the *Country Restrictions* tab, click on the “Add a new restriction” button to start creating your Country restriction group.
→ In the displayed popup:
* Define a name and a start date for your restriction group
* Select whether you want to blacklist or whitelist a group of countries
* Enter the codes manually or upload a CSV file (the list of values in a single column)
* Click on the “Save” button to validate your creation
Once all your desired restriction groups have been created, you can move on to the next step.
## Create physical cards in bulk
In the Dashboard, you can create several cards at once while automatically generating users that you can edit afterward.
Before you start, ensure that you already have:
* A Card Print reference (as indicated in the [prerequisites](overview#introduction-prerequisites))
* The Id of your Master Wallet (i.e., the Wallet attached to your company user).
→ Select the *Bulk Cards* view in the menu, and click on the “Create bulk cards” button to start your bulk card creation.
### Step 1 – Define the number of cards
Be mindful of the number of cards you enter. Any ordered card will be charged to you. You must create at least 2 cards for the creation to be successful.
If you’ve subscribed to a specific offer with a preset Sandbox and set of cards, you are limited to 15 cards.
→ Enter the number of cards to create and click “next”.
### Step 2 – Select your card type
Let's make sure you have both virtual and physical cards. Cards will be displayed as virtual cards converted into physical ones in your user profile.
→ Select the Virtual card program in the pick-list and the “Virtual converted to physical” before going to the next step.
### Step 3 – Select your permission groups
Usually, only “NFC” and “online” toggles should be activated for this use case.
→ Switch on the relevant toggle buttons and click “next”.
### Step 4 – Select the wallet and users for the cards to create
For cards to be created, you need both a wallet and users to link them to.
→ In this case, you need to:
* Select the “An existing wallet” option and enter the Id of your company Wallet (i.e., Master Wallet)
* Select the “Several User Ids” option (new users will be automatically generated)
* Ensure your company address is properly defined for the physical cards to be delivered.
You may need to select a [distribution country](/guide/users/introduction#distribution-country-distributioncountry) as well.
### Step 5 – Define the name to be displayed on the cards
In this specific case, the cards will have no names displayed on them as the users, as generic users, are automatically created (you will be able to edit user information only after the card creation).
→ Click “next” to continue.
### Step 6 – Define your card options
#### Enter more card design information (optional)
In the top of this page, additional card design fields are available. If provided at the same time as your credentials, you may enter the “Logo Id reference”, the "Batch delivery Id reference" (if you have subscribed to the option), and the “Package Id reference” for your cards.
→ Enter your references in the dedicated fields.
#### Select restrictions
If you’ve created card restriction groups, you can define what restrictions apply to your set of cards.
→ Click on the arrow icon available next to the “Attach restriction groups” label.
→ In the *Select restrictions* popup, use the drop-down to select the desired predefined restriction groups and click “confirm”.
#### Define the limits
The card limits will define the available amount on the gift card. You must set one by default, but you can update this information later.
→ Click on the arrow icon available next to the “Define limits” label.
The prompted popup already displays limits which are the default limits of your card program.
→ In the prompted popup:
* Define a random limit for ATMs (at least one must be entered for the creation to be successful). This will not be taken into account since you deactivated the “Withdrawal” default permission group in Step 3.
* Define a “Global Payment limit” of the desired default amount for your gift cards.
→ Save your changes before going to the next step.
### Step 7 – Finalize your card creation
Because you're ordering cards in bulk and you're going to be charged for these cards, you need to make sure everything is as expected.
→ Review the details of the cards to be created before validating your order.
The bulk creation may take a few minutes. You can check the progression in the *Bulk Cards* view.
Once the order Status is “Complete,” you can go to the next step.
## Update the user declarative data
The bulk card creation process created as many users as cards. As a result, you have to edit each one of these users with the necessary declarative data as indicated by *Treezor Compliance*.
**Information – Declarative data to submit depends on the use case**
In our use case, users are not KYC-validated, so only the fields indicated in the KYC Form provided by Treezor are to be filled in.
→ In the *Users* view, the automatically generated users are identifiable as "Anonymous users", with their random email address and the absence of name.
→ Click on an automatically generated user to open the corresponding profile in the *User details* view.
→ In the *Overview* tab, *Main information* section, click on the "Edit" button (pen icon) to access the *Edit user* popup.
→ In the *Edit user* popup, enter the required declarative data:
* *Main Information* section: Email, Last Name, First Name
* *Address* section
* *Birth and Nationality* section: Birthday, Birth country, Place of birth, Nationality
* *Contact* section: Phone number
→ Repeat the operation for as many users as you’ve created.
Once all your users are correctly defined, you can proceed to activate and manage their individual cards.
## Activate cards
As a security measure, all Cards are issued in an inactive state to ensure that a Physical Card is not usable before the cardholder receives it. Inactive cards can’t be used to make any type of payment or withdrawal.
→ In the *User details* view, select the *Cards* tab for your user to display the inactive card. Click on the “Activate” button below the card preview.
→ In the prompted confirmation popup, click on the “Activate card” button.
Now that the card is activated, payments can be made, and you can update the card settings as you see fit.
## Enroll 3DS
Enrolling the card with the [3DS protocol](/guide/overview/glossary#_3d-secure-3ds) will ensure the payment isn't declined if strong customer authentication is triggered during an online payment.
→ In the *Manage card* popup, *Security* tab, click on the “Add OOB” available in the 3D Secure section to activate **[Out of Band](/guide/strong-customer-authentication/securing-endpoints#enrolling-to-out-of-band-authentication)**. This is the primary strong customer authentication of the cardholder through their payment application.
→ Then, activate the **[OTP SMS](/guide/cards/creation#enrolling-a-card-for-3d-secure)** option. This is the fallback method, which sends a one-time password (OTP) by SMS.
## Manage cards
### Update card settings
→ In the *Cards* tab of the *User details* view, select the “More” button (vertical ellipsis) for the card whose settings are to be updated, and select the “Card settings” option.
The *Manage card* popup displayed allows you to manage all the card options, including enrolling the card with the [3DS protocol](#enroll-3ds) and updating limits and restrictions.
#### Update card limits
You may want to update the card limits to define the amount available for the gift card.
→ In the *Manage card* popup, *Settings* tab, *Limits* section, set the *Global Payment limit* with the desired amount.
→ Save your changes to apply the new limit.
#### Update card restrictions
You may update or set MID, MCC, or Country restrictions directly in the *Manage card* popup.
→ To do so, in the *Manage card* popup, *Restrictions* tab, select the restrictions group to set on the right-hand side on the view.
→ Select a restriction list in the picklist. Restriction lists are defined by your Administrator.
→ Once the restriction selected, click "Save" to validate your choice.
## Handle the end of the gift card life cycle
Once the gift card is used by the end user (Global Payment limit is reached), and if this was a one-time use card, you need to perform the following actions:
1. [Destroy the card](#destroy-the-card)
2. [Deactivate the user](#deactivate-the-user)
### Destroy the card
Once the card has been used, you must destroy it. To do so:
→ In the *Cards* tab, click on the "Other statuses" button and select the "Destroy card" option.
→ Select "Destroy card" in the prompted confirmation popup.
As a result, the card status is changed to destroyed, and is displayed in the card preview.
### Deactivate the user
For legal reasons, Users information can't be removed from your Dashboard. They have a permanent "Deleted" status instead.
→ In the *User details* view, once the user selected, click on the “Delete User” button.
→ In the prompted confirmation popup, click “Yes, delete this user” to continue.
As a result, the user is now “Deleted”.
**Tip – Recreate a user with the same email**
The unique email rule only applies to active users. In other words, once the user canceled, you can create them again using the same email.
---
---
url: /guide/use-cases/gift-cards/overview.md
description: >-
Get some preliminary context regarding the Gift Cards use case before choosing
to follow the API or No-Code guide. Includes functional architecture,
financial flows, and keywords to fully understand the Gift Cards model.
---
# Gift cards: Overview
## Introduction & Prerequisites
The Gift Cards use case is meant for companies who wish to distribute gift cards to their customers or employees.
In this specific case, the cardholders are not KYC-validated. It may be applied to:
* **Single-merchant gift cards** – Cards that may only be used in one merchant’s point of sale.
* **Special events gift cards** – Usually specific to your country's legislation, these are cards allocated by a company on special occasions such as marriages and children’s births.
We propose two guides to help you through the Gift Cards use case: No-code or API.
### No-code guide
Recommended for people who wish to get started with no development effort.
Once you’ve gone through the prerequisites listed below and have access to your Dashboard, you’re good to go!
[Start your no-code implementation →](./nocode-guide)
### API guide
Recommended for people with experience working with APIs.
Once you’ve completed the prerequisites and got your credentials, you’re good to set up your favorite development and testing tools (e.g., set up our Postman Collection).
[Start integrating Treezor API →](./api-guide)
**Prerequisites – Before starting this use case, make sure that you’ve:**
* Created your company, its legal representatives, shareholders and its Master Wallet (see [Creating your company](../prerequisites/creating-your-company) guides)
* Gone through the KYC validation process for your legal entity
* Set up a Card Program with Treezor (it may be a default one provided with your Sandbox)
## Functional architecture
The use case relies on the following actors and objects:
* **Your company** – The legal entity (corporate user, legal representatives and ultimate beneficial owners).
* **End users** – Physical persons (not KYC-validated) who will use the gift cards.
* **Master Wallet** – The wallet attached to the legal entity (your company), and through which all the funds are going to transit.
* **Cards** – The final gift cards, which may be physical or virtual. They are attached to both your Master Wallet and the end users they are allocated to.
## Financial flows
The following money flows will occur in this use case:
1. **SEPA Credit Transfers** – Your company wires the necessary amount into its Master Wallet. (Usually to cover about 3 to 4 days of expenses, hence avoiding being short on funds).
2. **Card transactions** – Your end users pay in the approved merchants' point of sale (POS) with the cards (attached to the company’s Master Wallet).
**Best practice – Develop alerting for your Master Wallet**
To ensure your transactions never fail due to insufficient funds, we recommend you develop an alerting system to be notified when your Master Wallet is low on funds.
## Keywords
Find below a few terms specific to the use case.
If you have any doubts, you may find more definitions in the [Glossary](/guide/overview/glossary).
### Master Wallet
The [Master Wallet](/guide/wallets/introduction##master-wallet-type-15) refers to the single wallet attached to a company through which all the funds transit.
You may also find the French term *Titres Spéciaux de Paiements*.
### Card Program
The Card Program covers everything regarding the final issued card, from its design and packaging to the features the card provides (i.e., limits, restrictions, etc.).
When creating your cards, you'll need the Id of your Card Program which has been communicated to you by Treezor. This Id is usually referred to as the `cardPrintId`, card print reference or GPS Id.
---
---
url: /guide/overview/glossary.md
description: >-
Find out about Treezor and Banking as a Service (BaaS) terms, concepts, and
definitions. Don't let acronyms get the best of you!
---
# Glossary
Treezor documentation’s glossary lists all the terms and acronyms you need to fully grasp the concepts of our embedded finance services.
**Tip — Not finding what you're looking for?**
This may be because you’re looking for business-oriented content. Don’t hesitate to have a look at the [Support Center](https://treezor.zendesk.com/hc/en-us) articles!
## 3D Secure (3DS)
A protocol designed to add security layer to online card payments.
When the 3D Secure protocol is triggered, the cardholder is required to perform a validation step (such as entering a code received by SMS or validating the operation on an already enrolled device) to authenticate.
The second version (3DS2) facilitates [strong customer authentication (SCA)](#strong-customer-authentication-sca) to meet the regulatory technical standards of the EU Revised Payments Services Directive (PSD2).
***
## Anti-Money Laundering and Countering the Financing of Terrorism (AML/CFT)
Regulations applying to entities of the financial sector to prevent the illicit use of the money transacting through their system.
AML/CFT regulations focus notably on:
* **Money laundering** (concealing the source of money acquired illegally to reinvest in legal activities).
* **Terrorism financing** (e.g., providing funds with the intent of using them in an act of terrorism).
AML/CFT also applies to entities of the non-financial sector (both public and private). It isn’t restricted to the use of licit or illicit funds, but any act participating in terrorism (e.g., lending a car).
The equivalent in French is LCB/FT (“lutte contre le blanchiment des capitaux et le financement du terrorisme”).
***
## Account Status Inquiry (ASI)
Authorization request from the card token provider to ensure the card exists.
Before tokenizing the card, the token provider sends an ASI to Treezor. The ASI is an authorization request of a `0` amount. The proper processing of the authorization confirms the existence of the card.
See the [X-Pay](/guide/cards/x-pay-google-apple) article for more information.
***
## Activation Complete Notification (ACN)
Authentication message sent to the cardholder with their activation code to tokenize their card.
This message triggered directly from the [wallet provider](#wallet-provider) application. When receiving it, Treezor sends the code to the cardholder by email or SMS according their preference.
See the [X-Pay](/guide/cards/x-pay-google-apple) article for more information.
***
## ARA
Processing message from the banking system, acknowledging the reception of the transaction.
The banking system uses this functional Payment Status Report (PSR) to notify Treezor that it received the transaction. Once acknowledged, the banking system is in charge of routing the transaction to the designated entity.
ARA stands for *“Accusé de réception applicatif”* in French. It translates into “application acknowledgment of receipt”.
***
## Authorization
Step of the card transaction during which:
* The merchant requests the issuer’s approval for the initiated transaction.
* The issuer approves or rejects the payment based on the card status, spending limits, and restrictions to be enforced.
See the [Transactions life cycle](/guide/cards/transactions-lifecycle#authorization) article for more information.
***
## Automated Teller Machine (ATM)
A computerized device that allows the cardholder to perform banking operations such cash withdrawals, balance inquiries, deposits, fund transfers, PIN updates and mini statements.
Available banking operations depend on what is supported by the card issuer.
***
## Bank Identifier Code (BIC)
The unique international identifier of the bank.
This code can be 8 or 11 alphanumeric characters, which concatenates the following information:
* **Bank code** or **institution code** (first 4 characters)
* **Country code** (next 2 characters), indicating the country the bank is located in
* **Location** (next 2 characters), indicating the location of the bank
* **Branch code** or another additional identifier (last 3 characters)
Let's consider the following BIC: "AAAABBCCXXX"
In which:
* AAAA is the bank code
* BB is the country code
* CC is the location code
* XXX is the branch code (or any other optional identifier)
***
## Card Verification Code (CVC)
The 3-digit code usually printed on the back of a physical card.
The CVC aims to enhance security when the card is not physically present (e.g., online payments).
Many acronyms are used to refer to this code, including CVV, CVC2, CSC, CVD, CVN, and SPC.
***
## Chargeback
The cancellation of a financial transaction which occurs when the customer contacts their issuer to dispute a charge made to their account and request a refund.
The chargeback process is designed to:
* Protect consumers from fraudulent or unauthorized transactions.
* Address issues such as non-delivery of goods or services, defective products, or billing errors.
When a user initiates a chargeback, the funds from the disputed transaction are temporarily withdrawn from the merchant’s account. The issuer investigates the claim and determines whether the chargeback is valid. If deemed legitimate, the customer account is credited, and the merchant may incur additional fees or penalties.
***
## Chip
The embedded microchip of the card.
This chip is an integrated circuit that contains encrypted details about the card and securely transmits payment data to the terminal or the ATM during the transaction.
***
## Common Reporting Standard (CRS)
Standard developed by the OECD in 2014 for the automatic exchange of information between partner countries to fight tax evasion. It applies to each country that has committed to the CRS and transposed it into its law.
***
## Contactless
See [Near field communication (NFC)](#near-field-communication-nfc).
***
## Device Primary Account Number (DPAN)
The [tokenized](/guide/cards/x-pay-google-apple) version of the [Primary Account Number (PAN)](#pan-primary-account-number) dedicated to a device such as a smartphone. It aims to securely identify a Card. It cannot be used to pay on its own.
The DPAN has to be detokenized by the Card network (e.g., Mastercard) during the payment.
***
## Effective Date
The date on which funds are effectively credited or debited. You may also find the term settlement date or collection date.
This date differs from the date the transaction is requested in the case of a [SEPA Credit Transfer (SCT)](/guide/transfers/credit-transfer) or a [SEPA Direct Debit (SDD)](/guide/transfers/direct-debit) for example.
Consider an SCT requested on February 3rd, but which is set to be credited on February 7th. February 7th is the effective date of the transaction.
***
## Electronic money (e-money)
Monetary value stored electronically and issued upon receiving funds. It is a digital equivalent of cash.
E-money is stored on an electronic device (or remotely on a server) and can be used to pay for goods and services. Specific regulations (e.g., [EU’s E-Money Directive](https://eur-lex.europa.eu/legal-content/en/TXT/?uri=CELEX%3A32009L0110)) enforce restrictions and limits to e-money usage. E-money also requires an [EM approval](https://treezor.zendesk.com/hc/en-us/articles/360014672580-Note-EM-5th-Directive) of your project. See [Electronic Money Wallets](/guide/wallets/introduction#electronic-money-wallet-type-9) for more information.
***
## Foreign Account Tax Compliance Act (FATCA)
US extraterritorial regulation (in force since July 1st, 2014) that aims to identify and report US taxpayers to the US tax authorities.
***
## French Cybersecurity Agency (ANSSI)
The French national security cybersecurity agency (*Agence nationale de la sécurité des systèmes d'information*), in charge of granting the [PVID](#remote-identity-verification-providers-pvid) certification.
Learn more on the [ANSSI official website](https://cyber.gouv.fr/en/about-french-cybersecurity-agency-anssi).
***
## JSON Web Token (JWT)
Authentication token which also contains information about the User (e.g., `id`) and their [Scopes](/guide/api-basics/authentication#available-scopes). The token claimed information can be verified using a signature mechanism.
You need to provide this Token for any request made to the Treezor API.
Read more about the JWT in the [Authentication](/guide/api-basics/authentication#obtaining-an-access-token-jwt) article.
***
## Mag Stripe
The magnetic stripe found on the back of a card. It is encoded with data, hence providing similar information as the card’s Chip.
***
## Merchant
A business accepting electronic payment transactions.
Merchants are therefore equipped to accept and process card payments. This term applies to both in-person and online transactions.
***
## Merchant Category Code (MCC)
The code categorizing the merchant’s commercial activity (e.g., clothing retailers, restaurants, etc.).
This code is included in any card transaction (withdrawals or payments) and allows you to restrict payments based on the merchant’s activity.
Find the list of MCC in the [MasterCard's Quick Reference Booklet](https://www.mastercard.us/content/dam/public/mastercardcom/na/global-site/documents/quick-reference-booklet-merchant.pdf).
***
## Merchant Identification Number (MID)
The unique identifier assigned to a [merchant](/guide/overview/glossary#merchant) by their bank.
This 15-digit identifier is usually included in the card transaction, which:
* Helps identify a merchant.
* Allows you to [restrict payments based on the MID](/guide/cards/restrictions-limits#mid-restrictions).
You may also find the terms Merchant Identifier or Merchant ID to refer to this number.
***
## Near Field Communication (NFC)
Technology that powers contactless payments with credit cards or smartphones for instance.
***
## Nomenclature Activités Française (NAF)
The French coding system categorizing business and [merchant](/guide/overview/glossary#merchant) activities.
**Reading – Additional documentation in French**
* [CITI-NACE-NAF correspondence table](https://www.insee.fr/fr/statistiques/fichier/2408180/CITI_NACE_NAFrev1_2003.pdf)
* Full list of NAF codes on [insee.fr](https://www.insee.fr/fr/statistiques/fichier/2120875/Nomenclatures_NAF_et_CPF_Reedition_2020.pdf)
***
## Payment Card Industry Data Security Standards (PCI DSS)
Payment industry security standards to secure the sensitive data of payment cards.
It sets the technical and operational requirements to create a secure environment for sensitive card data, such as the PAN, CVV, and PIN.
PCI DSS was created by the [Payment Card Industry Security Standards Council (PCI SSC)](https://www.pcisecuritystandards.org/standards/pci-dss/) and is a contractual obligation adopted by major card schemes (Visa, Mastercard, etc.). It applies to all card payment process actors, including issuers and service providers.
**Reading – PCI DSS integration**
Find out more in the dedicated [PCI DSS integration](/guide/cards/pci-dss) article.
***
## Personal Identification Number (PIN)
The 4-digit code of the card, entered by the cardholder during a “card present” payment.
***
## Primary Account Number (PAN)
The main card number, made up of 16 to 19 digits displayed on the card.
The first 6 to 8 numbers correspond to the IIN (Issuer Identification Number) or BIN (Bank Identification Number), hence identifying the entity that emitted the card.
**Tip – The IIN first number identifies the network**
Card schemes are easily identified with the IIN. For instance, 4 stands for Visa, and 5 for Mastercard.
***
## Qualified Electronic Signature (QES)
Electronic signature with the highest level of security.
These electronic signatures are “qualified” because the user’s identity is verified through a selfie at the same time as they electronically sign the document.
QES is therefore [eIDAS-compliant](https://digital-strategy.ec.europa.eu/en/policies/eidas-regulation) and:
* Ensures the signer identification
* Protects the signature against forgery and tampering
* Provides a certificate for electronic signature issued by a certified provider
***
## Regulated institution
[Legal Entity](/guide/users/legal-entity) that has gone through a thorough administrative process with the regulators (*ACPR* in France) to be allowed to provide payment services to customers.
Regulated Institutions encompass a wide group of institutions such as Payment Institutions, Microfinance institutions, Financial holding companies, etc.
They benefit from additional features in return for added legal and administrative responsibilities.
**Tip – Dedicated Regulated Institutions badge in the documentation**
Features that are available only to Regulated Institutions are tagged with the badge across the documentation.
* Dedicated IT infrastructure at Treezor
* [Custom IBAN/BIC](/guide/wallets/iban#create-a-virtual-iban)
* [Users Freezing](/guide/users/introduction#freezing)
* Choosing whether to use Treezor's technical features or build alternatives yourself (e.g., KYC)
* You are responsible for your customers' [KYC](/guide/user-verification/introduction)
* You must enforce anti-fraud and anti-laundering systems
* You must report to the regulators
* You are responsible for monitoring [outgoing funds](/guide/transfers/introduction#types-of-transfers) (although this can be delegated to Treezor TMS (Transaction Monitoring System))
**Reading – Learn more about Payment Institutions**
You can read more about Payment Institutions (a type of Regulated Institution) on the [European Payment Institutions Federation's website](https://paymentinstitutions.eu/the-payment-institutions-sector/about/).
***
## Remote Identity Verification Providers (PVID)
Standard for robust and reliable remote identity verification processes to minimize fraud risks. Becoming a PVID (*Prestataires de vérification d’identité à distance* in French) requires passing a certification with the [French Cybersecurity Agency (ANSSI)](#french-cybersecurity-agency-anssi).
***
## SEPA Creditor Identifier (SCI)
The unique and mandatory reference for [SEPA Direct Debit mandates](/guide/transfers/direct-debit#emitted-direct-debits-sdde).
It must appear in any direct debit application. Its main purpose is to allow each creditor, who may be located in any SEPA country, and their bank to know the precise identity of the issuer of the direct debit. This facilitates claims for reimbursement or action in the event of a complaint.
The SCI length varies from country to country, but never exceeds 35 characters. Its structure is AABBCCCX, in which:
* AA – ISO country code (e.g., FR for France)
* BB – 2 control numbers
* CCC – Activity code that can be freely used by the creditor
* X – National identifier, which is up to 28 figures. This is the NNE (National Issuer Number), 13 characters long in France, formerly used for national debits.
***
## SEPA Credit Transfer (SCT)
[SEPA](/guide/overview/glossary#single-euro-payments-area-sepa) transfers initiated by the sender; the debtor *credits* another account.
This feature allows the sender to make Euro-denominated payments to SEPA countries accounts. Learn more from the European Payments Council [SEPA Credit Transfers](https://www.europeanpaymentscouncil.eu/what-we-do/sepa-credit-transfer) article.
***
## SEPA Direct Debit (SDD)
[SEPA](/guide/overview/glossary#single-euro-payments-area-sepa) transfers initiated by the receiver; the receiver *debits* another account, allowed doing so by a [*Mandate*](/guide/transfers/mandates).
This feature allows the recipient to collect Euro-denominated payments from SEPA countries accounts. Learn more from the European Payments Council [SEPA Direct Debit](https://www.europeanpaymentscouncil.eu/what-we-do/sepa-direct-debit) article.
***
## SEPA Instant Payments
Real-time electronic payment method allowing for rapid and secure fund transfers between bank accounts within the [SEPA](/guide/overview/glossary#single-euro-payments-area-sepa) region. The rapid processing offers a settlement within a matter of seconds, providing users with immediate access to transferred funds.
Learn more about [SEPA Instant Credit Transfers](https://www.europeanpaymentscouncil.eu/what-we-do/sepa-instant-credit-transfer) from the European Payments Council article.
***
## SEPA Open Banking Days
Days on which operations using the SEPA network are processed.
Operations on the SEPA Network are indeed subject to handling delays and time frames. Operations aren't processed on **closed days**, which are the weekends (Saturdays & Sundays) and the following [TARGET2](https://www.ecb.europa.eu/paym/target/target2/html/index.en.html) closed days:
* January, 1st (New Year's Day)
* Good Friday (*Vendredi saint*)
* Easter day (Monday)
* May, 1st (Labor Day)
* December, 25th (Christmas)
* December, 26th
When a delay or time frame is indicated as *Open Banking Days*, these closed days must be excluded.
The list of closed days for the current year is available on the [European Central Bank website](https://www.ecb.europa.eu/paym/target/target2/html/index.en.html).
***
## Settlement
Step of the card transaction during which the funds are debited from the cardholder's account and credited to the merchant's account.
See the [Transactions life cycle](/guide/cards/transactions-lifecycle#settlement) article for more information.
***
## Single Euro Payments Area (SEPA)
Payment integration initiative of the European Union which simplified euro bank transfers (credit transfers and direct debits).
Learn more from the [European Central Bank website](https://www.ecb.europa.eu/paym/integration/retail/sepa/html/index.en.html).
***
## Strong Customer Authentication (SCA)
A regulatory requirement aiming at reducing fraud and making payments more secure.
It enforces two-factor authentication for cardholders to validate online transactions. The factors must be two of the following elements:
* **Knowledge** – Something only the user knows (e.g., password)
* **Possession** – Something only the user has (e.g., phone)
* **Inherence** – Something only the user is (e.g., fingerprint)
Strong Customer Authentication (SCA) was introduced by the EU Revised Directive on Payment Services (PSD2) in 2015.
Learn more about SCA in the [dedicated section of the documentation](/guide/strong-customer-authentication/introduction).
***
## Terminal
Electronic device usually found in physical points of sale, allowing merchants to process card transactions.
You may also find the term point of sale (POS); it refers to a more global definition of terminals (including cash registers, for instance).
***
## Token provider
Actor who tokenizes the PAN to allow its storage as a DPAN by the Wallet provider. The token provider also detokenizes the DPAN during payments.
In the context of Treezor card digitization services, the token providers are the schemes through their corresponding services:
* Mastercard Digitalization Enablement Service (MDES)
* Visa Tokenization System (VTS)
See the [X-Pay](/guide/cards/x-pay-google-apple) article for more information.
***
## Tokenization Authentication Value (TAV)
Encrypted card data which allows the token provider to identify the card and allows to start the digitization process. At Treezor, the TAV is often referred to as the “cryptogram”.
See the [X-Pay](/guide/cards/x-pay-google-apple) article for more information.
***
## Tokenization Authorization Request (TAR)
Message sent to Treezor’s card processor to verify the card configuration.
The wallet provider requests the tokenization authorization verification to the card processor which confirms to Treezor that the tokenization services are available.
During this step, Treezor may refuse the digitization of the card for various reasons, such as the lack of compliance with anti-fraud requirements.
Treezor sends you the `cardDigitalization.request` webhook, in which the `tokenizationDecision` field indicates whether the request is ACCEPTED or DECLINED.
See the [X-Pay](/guide/cards/x-pay-google-apple) article for more information.
***
## Tokenization Complete Notification (TCN)
Notification from the token provider that the card was digitized and added to the wallet provider application.
Treezor forwards this information to you with the `cardDigitalization.complete` webhook, and also sends a one-time password (OTP) to the cardholder by SMS or email.
See the [X-Pay](/guide/cards/x-pay-google-apple) article for more information.
***
## Top-up
The act of crediting (or recharging) an account. At Treezor, [Wallets](/guide/wallets/introduction) can be credited with [card payments](/guide/acquiring/introduction) and [check cashing](/guide/cheques/cashing) for instance.
***
## Unique Mandate Reference (UMR)
The mandatory reference provided by the owner of an account, allowing the account to be debited by [SEPA Direct Debit](#sepa-direct-debit-sdd).
At Treezor, the UMR is:
* **Obtained by creating a Mandate** – For [SDDE](/guide/transfers/direct-debit#emitted-direct-debits-sdde).
* **Provided by the Beneficiary** – For [SDDR](/guide/transfers/direct-debit#received-direct-debits-sddr). This value is available in the `mandate_id` attribute of the [`sepa.sddr_reception`](/guide/transfers/events#sepa-sddr-reception) webhook.
The UMR is a sequence of characters that ensures the mandate traceability. UMR coupled with SCI allows to uniquely identify a creditor and a contract for any mandate.
***
## Verification of Payee (VoP)
Regulatory obligation allowing the initiator of a SEPA transfer to verify that the beneficiary’s name and IBAN match the information registered at their bank.
This service aims to prevent fraud and misdirected payments, and applies when emitting:
* SEPA Credit Transfers (SCT)
* SEPA Instant Credit Transfers (SCT Inst)
At Treezor, verification of the beneficiary is a prerequisite before initiating the payout request, and end users initiate the payout once the results of the VoP are returned to them.
The Verification of Payee (VoP) obligation is mandated by the [European Payments Council (EPC)](https://www.europeanpaymentscouncil.eu/) and takes effect on October 5, 2025.
See the [Beneficiary validation](/guide/transfers/beneficiaries#beneficiary-validation-vop) article for more information.
***
## Wallet provider
Actor who stores the DPAN of a card for the cardholder to use their devices as a payment method (e.g., Apple, Google).
See the [X-Pay](/guide/cards/x-pay-google-apple) article for more information.
---
---
url: /guide/api-basics/response-codes.md
description: >-
Understand HTTP Status Codes in the Treezor API. This guide explains common
2xx, 4xx, and 5xx response codes, detailing their meaning and the JSON error
structure for effective API response processing.
---
# HTTP Status codes
The Treezor API returns an *HTTP Status Code* that indicates how your request went. It points you in the general direction of the issue (if any).
The table below details the meaning of each *HTTP Status Code* and possible solutions.
| HTTP Code | Status name | Meaning | Solution |
|:-: |- |- |- |
| `200` | OK | The most common code, **everything is fine**. | None needed |
| `201` | Created | **The resource has been created by the API**. | None needed |
| `204` | No content | **The server handled the request successfully but did not produce a response**. | This can be a normal behavior with `POST` requests |
| `303` | See other | **The response to the request can be found using the GET method**. | This occurs when you attempt to create a duplicate document for instance. |
| `400` | Bad request | **Something is wrong with your request itself**. | Your parameters or payload might be erroneous, check the [API Reference](/api-reference/api-endpoints) for the endpoint |
| `401` | Authentication problem | **The provided JWT is not valid**. | Check if the JWT is properly set in the `Authorization` header and make sure that it hasn't expired |
| `403` | Authorization problem | **You do not have access to this endpoint**. | Check your JWT scopes and [API Reference](/api-reference/api-endpoints) for that endpoint to check what scope is required |
| `404` | Not found | **The endpoint was not found or the resource was not found**. | Make sure the object's ID you are requesting is valid and exists |
| `413` | Content Too Large | **The file size exceeds the limit**. | Make sure the documents to upload comply with the limits |
| `500` | Treezor Connect server error | **Our servers failed while handling your request**. | Try again and/or look at the response's payload, it can provide more information regarding the cause |
| `501` | Not implemented | **The endpoint called is not implemented** or not implemented with your *Treezor Connect* configuration. | Make sure the endpoint is correct, or contact your *Treezor Account Manager* to enable the feature |
| `502` `504` `522` | Bad gateway | **Our servers didn't respond in a timely manner**. | Try again or [contact the Treezor Support team](/guide/overview/getting-started#getting-help) if the error persists |
**Important – If you're not receiving any response, check that**
* You are using HTTPS. Treezor doesn't automatically upgrade HTTP to HTTP**S**.
* Your IP was declared to Treezor (when using the [Production environment](/guide/api-basics/environments#production)).
**Alongside the HTTP Status code, the API will generally return one or more Errors objects in a JSON array.**
These objects contain detailed information to help you understand and debug the situation. They are always provided in English.
**Security – Don't display any part of these errors to your end user**
This could leak sensitive information. You should create your own generic error messages.
## Error attributes
Errors have the following attributes:
| Field | Type | Description | Nullable |
|---|----|----|----|
| `type` | `string` | Machine-readable type (authentication, request format…) | No |
| `code` | `string` | Machine-readable code (expired JWT, missing parameter…) | No |
| `message` | `string` | Human-readable explanation | No |
| `docUrl` | `string` | URL of the relevant documentation page | No |
| `requestId` | `string` | Unique identifier of the error, to help Treezor trace back the error | No |
Example of a response containing a single error.
```json [JSON]
{
"errors": [
{
"type": "invalid_request",
"code": "authorization_error",
"message": "You cannot read operations for this wallet.",
"docUrl": "https://developers.treezor.co",
"requestId": "fa433c8c-1232-4c14-9f9e-95eddad19764"
}
]
}
```
## Error types
The `type` attribute may take the following values.
| Type | Description |
|:---|:----|
| `invalid_client` | Client is not valid |
| `invalid_grant` | Issue with the user credentials or permissions |
| `invalid_request` | Request is malformed: Invalid Option, Input validation not passed |
| `unexpected_internal_server_error` | Something unexpected happened |
| `unsupported_grant_type` | Issue with the grant\_type which may not be recognized or supported by the server |
## Error codes
The `code` attribute may take the following values.
| Code | Description | Solution |
|- |- |- |
| `authentication_error` | An authentication error occurred | Check that your [JWT](/guide/api-basics/authentication) is valid and hasn't expired |
| `authorization_error` | Core Banking returned an `unauthorized` error | |
| `functional_error` | A Core Banking functional error occurred | Make sure that all the functional requirements for the action are met |
| `input_validation_error` | Input validation failed | Double-check the provided [parameters format](/guide/api-basics/data-format) and content |
| `invalid_parameter_in_request` | An unexpected request parameter was found | Check that you don't have non-allowed parameters in your request |
| `invalid_user_id` | The provided User ID is invalid. | Check that the [User ID](/guide/users/introduction) is correct (either uuid `trzconnectUser` or int Treezor `userId`) |
| `resource_not_found_error` | The resource was not found | Make sure the object or endpoint you are trying to access actually exists |
| `undefined_cursor_error` | Undefined cursor | Check the [pagination](/guide/api-basics/pagination) or cursor documentation |
| `unexpected_error` | An unexpected error occurred | Try again or [contact Treezor](/guide/overview/getting-started#getting-help) if the error persists |
| `0` | The requested URL is malformed | Make sure no trailing `/` exists when they shouldn't (or the opposite) |
---
---
url: /guide/api-basics/idempotency.md
description: >-
Understand idempotency in the Treezor API. This guide explains how to prevent
duplicate operations and ensure data consistency by implementing idempotency
keys in your requests.
---
# Idempotency
Accidentally sending a request twice can cause duplicates and errors. To avoid such situations, Treezor recommends adding a unique identifier to your `POST` and `PUT` requests using the `accessTag` attribute.
The `accessTag` parameter is a string with a maximum length of 250 characters for you to use in accordance with the best practices to generate unique identifiers in your development environment. Here are tips for [Java](https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html), [npm](https://www.npmjs.com/package/uniqid), and [PHP](https://stackoverflow.com/questions/4070110/how-unique-is-uniqid), for instance.
**Information – The `accessTag` values are only kept for 24 hours**
Therefore, it is not a permanent solution to reconcile Treezor objects to your local database objects. To reconcile objects, use the persistent [object tags](/guide/api-basics/objects-tags).
## Examples with idempotency
### User creation
Let's take an example in which you send a User creation request with an `accessTag`. The following occurs:
* Treezor receives the request and creates the user.
* You do not receive an answer from Treezor, or the request times out on your side.
* You reasonably send the User creation request again.
* Treezor receives the new request, **identifies it as a duplicate (same `accessTag`)**, and **returns the previously created User** object.
### Money transfer
Let's take an example in which you send a Transfer request from a Wallet to another Wallet with an `accessTag`. The following occurs:
* Treezor receives the Transfer request and transfers funds to the destination Wallet.
* You do not receive an answer from Treezor, or the request times out on your side.
* You reasonably send the Transfer request again.
* Treezor receives the new request, **identifies it as a duplicate (same `accessTag`)**, and **returns the previously created Transfer** object.
## Examples without idempotency
### User creation
Let's take an example in which you send a User creation request without any idempotency `accessTag`. The following occurs:
* Treezor receives the request and creates a user.
* You do not get an answer from Treezor, or the request times out on your side.
* You reasonably send the User creation request again.
* Treezor receives the new request, treats it as a different request and **attempts to create the same user a second time**.
**Alert – This situation returns an error**
Duplicate users are not allowed, using an `accessTag` would have prevented this situation.
### Money transfer
Let's take an example in which you send a Transfer request from a Wallet to another Wallet without any idempotency `accessTag`. The following occurs:
* Treezor receives the Transfer request and moves funds to the other Wallet.
* You do not receive an answer from Treezor, or the request times out on your side.
* You reasonably send the Transfer request again.
* Treezor receives the request, handles it as a different request and **transfers the same amount a second time**.
**Alert – Twice the expected amount is moved**
Because the transfer occurs twice, you will then need to refund the duplicate transfer in order to solve the issue. Using an `accessTag` would have prevented this situation.
---
---
url: /guide/transfers/international.md
description: >-
Technical guide for emitting and receiving International Transfers. Includes
required parameters, request structure, and response examples.
---
# International Transfers
International transfers allow you to receive and send funds internationally (outside the SEPA network), and thus in different currencies.
**Configuration – International Transfers are not enabled by default**
Please contact Treezor if you're interested in this feature.
## Introduction
The International Transfer feature allows you to send and receive funds globally, in the supported countries and currencies.
An international transfer usually takes 1 to 6 business days to reach the beneficiary’s account. This delay varies depending on the opening schedules and international wire cut-off times of the bank you deal with. Treezor relies on a third-party and the SWIFT Network to process international transfers.
### Supported currencies
Treezor currently supports the following currencies for international transfers. Please note this list may change over time.
| Code | Country | Name | Reception | Emission |
|:---------------:|--------------------|---------------------------|:---------:|:---------:|
| AED | United Arab Emirates | United Arab Emirates Dirham | | |
| ARS | Argentina | Argentine Peso | | |
| AUD | Australia | Australian Dollar | | |
| BGN | Bulgaria | Bulgarian Lev | | |
| BHD | Bahrain | Bahraini Dinar | | |
| BRL | Brazil | Brazilian Real | | |
| CAD | Canada | Canadian Dollar | | |
| CHF | Switzerland | Swiss Franc | | |
| CLP | Chile | Chilean Peso | | |
| CNY | China | Chinese Yuan | | |
| CZK | Czech Republic | Czech Koruna | | |
| DKK | Denmark | Danish Krone | | |
| GBP | United Kingdom | Pound Sterling | | |
| HKD | Hong Kong | Hong Kong Dollar | | |
| HUF | Hungary | Hungarian Forint | | |
| IDR | Indonesia | Indonesian Rupiah | | |
| ILS | Israel | Israeli Shekel | | |
| INR | India | Indian Rupee | | |
| JPY | Japan | Japanese Yen | | |
| KRW | South Korea | South Korean Won | | |
| KWD | Kuwait | Kuwaiti Dinar | | |
| MAD | Morocco | Moroccan Dirham | | |
| MXN | Mexico | Mexican Peso | | |
| MYR | Malaysia | Malaysian Ringgit | | |
| NOK | Norway | Norwegian Krone | | |
| NZD | New Zealand | New Zealand Dollar | | |
| OMR | Oman | Omani Rial | | |
| PLN | Poland | Polish Zloty | | |
| QAR | Qatar | Qatari Riyal | | |
| RON | Romania | Romanian Leu | | |
| RSD | Serbia | Serbian Dinar | | |
| SAR | Saudi Arabia | Saudi Riyal | | |
| SEK | Sweden | Swedish Krona | | |
| SGD | Singapore | Singapore Dollar | | |
| THB | Thailand | Thai Baht | | |
| TND | Tunisia | Tunisian Dinar | | |
| TRY | Turkey | Turkish Lira | | |
| USD | United States | US Dollar | | |
| UYU | Uruguay | Uruguayan Peso | | |
| ZAR | South Africa | South African Rand | | |
| EUR | Europe (SEPA) | Euro | | |
### Fees management
International transfers come with fees from all the actors:
* **Included in each transfer** – Issuance fees, correspondent fees, and exchange fees.
* **Charged by Treezor** – Each month, as agreed upon in your contract with Treezor.
To mitigate your costs, you can collect fees from your end users regarding International Transfers by using [Wallet-to-Wallet (P2P) Transfers](./wallet-to-wallet) with the dedicated `transferType` value (`3`).
## Received International Transfers
### Exchange rates
Treezor Wallets are euro-denominated; therefore, the wallet is always credited in euros when receiving an international transfer.
Exchange rates are handled as follows:
* If the originating bank sends a euro-denominated operation to Treezor, then the originating bank has already applied its exchange rate.
* If the originating bank sends a non-euro-denominated operation to Treezor, Treezor’s exchange rate applies.
Detailed information regarding the exchange rate and applied fees is available in the [`additionalData`](#additional-data-additionaldata) object of the Payin.
### Processing flow
When receiving an International Transfer, Treezor operates controls on the transfer before accepting it.
```mermaid
sequenceDiagram
autonumber
participant bank as Originating bank
participant trz as Treezor
participant app as Your app
bank->>trz: Initiates an International Transfer
trz->>app: Sends payin.create webhook
trz->>trz: Operates controls
alt Success
trz->>app: Sends payin.update webhook (payinStatus: VALIDATED)
trz->>app: Sends transaction.create webhook
trz->>app: Sends balance.update webhook
else Failure
trz->>app: Sends payin.cancel webhook (payinStatus: CANCELED)
end
```
You can receive the following webhooks for an international transfer.
| Event | | Status | Description |
| --- | :---: | --- | --- |
| [`payin.create`](./events#payin-create-3) | | `PENDING` | Treezor receives an International Transfer. |
| [`payin.update`](./events#payin-update-2) | | `VALIDATED` | Treezor accepts the International Transfer. |
| [`payin.cancel`](./events#payin-cancel-2) | | `CANCELED` | Treezor rejects the International Transfer.|
```mermaid
flowchart TD
A("Treezor receives an International Transfer")
B("Sends a payin.create webhook payinStatus: PENDING")
C("Sends a payin.update webhook payinStatus: VALIDATED")
D("Sends a payin.cancel webhook payinStatus: CANCELED")
E("Sends a transaction.create webhook")
F("Sends a balance.update webhook")
A --> B -- Accepted --> C
B -- Rejected --> D
C --> E --> F
class A MermaidNeutral;
class B neutral;
class C neutral;
class D neutral;
class E neutral;
class F neutral;
```
### The Received International Transfer Payin object
```json [JSON] {17}
{
"payins": [
{
"payinId": "0049e4d5-7510-4765-974e-66fba1233a06",
"payinTag": "",
"payinStatus": "VALIDATED",
"codeStatus": "",
"informationStatus": "",
"walletId": "12345678",
"userId": "12345678",
"cartId": null,
"walletEventName": "main account",
"walletAlias": "main-account-123",
"userFirstname": "Alex",
"userLastname": "Oak",
"messageToUser": "messageTesting",
"paymentMethodId": "28",
"subtotalItems": "",
"subtotalServices": "",
"subtotalTax": "",
"amount": "1.23",
"currency": "EUR",
"distributorFee": null,
"createdDate": "2025-09-20 21:07:21",
"createdIp": null,
"paymentHtml": null,
"paymentLanguage": null,
"paymentPostUrl": null,
"paymentPostDataUrl": null,
"paymentAcceptedUrl": null,
"paymentWaitingUrl": null,
"paymentRefusedUrl": null,
"paymentCanceledUrl": null,
"paymentExceptionUrl": null,
"ibanFullname": "ALEX OAK",
"ibanId": null,
"ibanBic": "BIC-REVOFRP2XXX",
"ibanTxEndToEndId": "aa002083-1705-46cd-98cf-04a5bb467afc",
"ibanTxId": null,
"refundAmount": "",
"forwardUrl": "",
"payinDate": "2025-09-19",
"mandateId": 0,
"creditorName": "CHRIS WILLOW",
"creditorAddressLine": "165 Pine street, PARIS 75007",
"creditorCountry": "FR",
"creditorIban": "FR7616798000010001661493000",
"creditorBIC": "1",
"virtualIbanId": 0,
"virtualIbanReference": "",
"totalRows": null,
"DbtrIBAN": "FR4912739000506642887939D34",
"additionalData": [
"{\"fees\":[{\"currency\":\"CAD\",\"type\":\"conversion\",\"value\":0.01},{\"currency\":\"CAD\"},{\"currency\":\"CAD\"}],\"exchange\":{\"instructed_currency\":\"CAD\",\"exchange_rate\":0.615915,\"instructed_value\":2}}"
]
}
]
}
```
#### Key attributes
Below are some of the few Payin attributes specificities for received international transfers.
| Attribute | Type | Description |
| --- | --- | --- |
| `paymentMethodId` | string | The type of payin. The value is `28` for international transfers |
| `DbtrIBAN` | string | The account number of the transfer issuer. In the international system, this number may refer to an IBAN, BBAN, etc. |
| `additionalData` | array | Contains all the information regarding the fees, currency, and exchange rate of the international transfer. See the [Additional data](#additional-data-additionaldata) section below for more information. |
| `ibanBic` | string | The concatenation of the type of bank code and its value. Example: BIC-CMCIFRPAXXX |
| `ibanTxEndToEndId` | string | The unique End-to-End Transaction Reference (UETR). This is a reference shared by all parties involved in the payment chain. It allows the transaction to be identified throughout the network. |
| `payinDate` | string | The date on which Treezor received the international transfer. Format: `YYYY-MM-DD` |
| `createdDate` | string | The date on which the transfer was carried out. Format: `YYYY-MM-DD HH:mm:ss` |
**API – API Reference available**
For a complete list of Payin attributes, check the [Payins](/api-reference/api-endpoints.html#tag/Payins){target="\_self"} section of the API Reference.
#### Additional data (`additionalData`)
Information regarding fees, currency, and exchange rate are contained in the `additionalData`.
| Attribute | Type | Description |
| --- | --- | --- |
| `fees.currency` | string | The currency in which the fees were charged. |
| `fees.type` | string | The type of fees. When using the Treezor International Transfer feature, the type is always valued to `conversion`. |
| `fees.value` | number | The amount of the fees, expressed in the `fees.currency`. |
| `exchange.exchange_rate` | number | The exchange rate applied. |
| `exchange.instructed_currency` | string | The currency in which the transfer was initially processed. |
| `exchange.instructed_value` | number | The amount of the transfer expressed in its initial currency (`exchange.instructed_currency`). This value doesn't take into account fees the emitting bank applies. |
### Return of a received International Transfer
When receiving an International Transfer, Treezor might not be able to credit the wallet.
It can occur when, for instance:
* The beneficiary wallet is closed;
* The beneficiary wallet is incorrect;
* The International Transfer was made in an unsupported currency.
In such cases, Treezor sends you a [`payin.cancel`](./events#payin-cancel-2) webhook, with [the reason](/guide/transfers/error-codes#transfer-reason-codes) specified in the `informationStatus`.
---
---
url: /guide/acquiring/events.md
description: >-
Reference a comprehensive list of card acquiring events for Treezor API
webhooks, detailing each event's structure and payload for integration.
---
# Events
This article lists the [webhooks](/guide/webhooks/introduction) you may receive when using the Acquiring feature.
For the [legacy flow](./legacy-v1), the reception of any `payin` webhook meant that a payment had been accepted. This is **no longer the case** in the newest version. Please refer to the `payinStatus` attribute of the `payin`. The payment is accepted when valued to `VALIDATED`.
```mermaid
flowchart TD
id1[Payment creation] --> id2("authorization.create authorizationStatus:PENDING") --> id3("authorization.update authorizationStatus:PENDING") ----> id5("payin.create payinStatus:PENDING") --> id6("payin.update payinStatus:VALIDATED");
id3 --> id4("authorization.cancel authorizationStatus:CANCELED") ;
id1 --> id4;
id5 --> id8("payin.cancel payinStatus:CANCELED");
class id1 neutral;
```
## TopupCard events
### `topupCard.validate`
```json [JSON]
{
"webhook": "topupCard.validate",
"webhook_created_at": 16867326126402,
"object_id": "61e46d74-54db-4170-968f-28c307ba255c",
"object": "topupCard",
"object_payload": {
"topupCards": [
{
"topupCardId": "61e46d74-54db-4170-968f-28c307ba255c",
"userId": "1656177",
"profile": "00001340585",
"token": "4d2e3ce0aa972bb3726fa609b648535c803d725dccf3d8cbe738762f84281d3e",
"brand": "MASTERCARD",
"maskedPan": "545454xxxxxx5454",
"cardHolder": "Tom Pes",
"cardExpiryMonth": "12",
"cardExpiryYear": "2025",
"issuer": "CENTRAL TRUST BANK, THE",
"country": "US",
"domesticNetwork": null,
"cardType": "CREDIT",
"status": "VALIDATED",
"createdDate": "2023-06-14 10:50:08",
"updatedDate": "2023-06-14 10:50:08"
}
]
},
"webhook_id": "185cf5c2-766d-4168-8848-6bd754083ef4",
"object_payload_signature": "CktrgqtW2rknbedybQ3VIDTxygjZRE3zrY6dR\/g3YpE=",
"auth_key": "true"
}
```
### `topupCard.cancel`
```json [JSON]
{
"webhook": "topupCard.cancel",
"webhook_created_at": 16867326507819,
"object_id": "61e46d74-54db-4170-968f-28c307ba255c",
"object": "topupCard",
"object_payload": {
"topupCards": [
{
"topupCardId": "61e46d74-54db-4170-968f-28c307ba255c",
"userId": "1656177",
"profile": "00001340585",
"token": "4d2e3ce0aa972bb3726fa609b648535c803d725dccf3d8cbe738762f84281d3e",
"brand": "MASTERCARD",
"maskedPan": "545454xxxxxx5454",
"cardHolder": "Tom Pes",
"cardExpiryMonth": "12",
"cardExpiryYear": "2025",
"issuer": "CENTRAL TRUST BANK, THE",
"country": "US",
"domesticNetwork": null,
"cardType": "CREDIT",
"status": "CANCELED",
"createdDate": "2023-06-14 10:50:08",
"updatedDate": "2023-06-14 10:50:50"
}
]
},
"webhook_id": "c69a1148-ea41-479c-a33d-af0df5e95f72",
"object_payload_signature": "fn\/rOnp3\/YWJFodXHIRUzMmKmT82ohYIqapwcRG5VvI=",
"auth_key": "true"
}
```
## Authorization events
### `authorization.create`
```json [JSON]
{
"webhook": "authorization.create",
"webhook_created_at": 16867327260694,
"object_id": "7ec56e11-02fe-5f53-a7e9-d8403e95bbe5",
"object": "authorization",
"object_payload": {
"authorizations": [
{
"authorizationId": "7ec56e11-02fe-5f53-a7e9-d8403e95bbe5",
"walletId": "878744",
"userId": "1656177",
"authorizationStatus": "PENDING",
"messageToUser": "The financial institution has approved the payment.",
"amount": "100.00",
"currency": "EUR",
"createdDate": "2023-06-14 10:51:56",
"walletEventName": "Hondwallet",
"walletAlias": "Hondwallet-620e13cb0760f",
"userFirstname": "John",
"userLastname": "Doe",
"codeStatus": "150116",
"informationStatus": "Authorized",
"payinDate": "0000-00-00 00:00:00",
"additionalData": "{\"card\":{\"externalProvider\":{\"transactionReference\":\"800240081686\"}}}"
}
]
},
"webhook_id": "65ad7aad-2c72-4abd-920d-e73107afcf78",
"object_payload_signature": "d6u1VgSn+hWZHpb4Z2nfbwm3\/RtyAVdsyS3CTD0+Qc8=",
"auth_key": "true"
}
```
### `authorization.update`
```json [JSON]
{
"webhook": "authorization.update",
"webhook_created_at": 16867328446792,
"object_id": "7ec56e11-02fe-5f53-a7e9-d8403e95bbe5",
"object": "authorization",
"object_payload": {
"authorizations": [
{
"authorizationId": "7ec56e11-02fe-5f53-a7e9-d8403e95bbe5",
"walletId": "878744",
"userId": "1656177",
"authorizationStatus": "PENDING",
"messageToUser": "Authorization cancellation requested.",
"amount": "100.00",
"currency": "EUR",
"createdDate": "2023-06-14 10:51:56",
"walletEventName": "Hondwallet",
"walletAlias": "Hondwallet-620e13cb0760f",
"userFirstname": "John",
"userLastname": "Doe",
"codeStatus": "150175",
"informationStatus": "Authorization Cancellation Requested",
"payinDate": "0000-00-00 00:00:00",
"additionalData": "{\"card\":{\"externalProvider\":{\"transactionReference\":\"800240081686\"}}}"
}
]
},
"webhook_id": "c9e92612-6780-4fb0-871e-137158a870a3",
"object_payload_signature": "wa9DCqC1wj0XKBmexQSmwlu1lZbi8Vvl+t277sxDTGs=",
"auth_key": "true"
}
```
### `authorization.cancel`
```json [JSON]
{
"webhook": "authorization.cancel",
"webhook_created_at": 16867328881913,
"object_id": "7ec56e11-02fe-5f53-a7e9-d8403e95bbe5",
"object": "authorization",
"object_payload": {
"authorizations": [
{
"authorizationId": "7ec56e11-02fe-5f53-a7e9-d8403e95bbe5",
"walletId": "878744",
"userId": "1656177",
"authorizationStatus": "CANCELED",
"messageToUser": "Merchant cancelled the payment attempt.",
"amount": "100.00",
"currency": "EUR",
"createdDate": "2023-06-14 10:51:56",
"walletEventName": "Hondwallet",
"walletAlias": "Hondwallet-620e13cb0760f",
"userFirstname": "John",
"userLastname": "Doe",
"codeStatus": "150115",
"informationStatus": "Canceled",
"payinDate": "0000-00-00 00:00:00",
"additionalData": "{\"card\":{\"externalProvider\":{\"transactionReference\":\"800240081686\"}}}"
}
]
},
"webhook_id": "40ca0506-00c8-469f-b5c1-d0016bcc277f",
"object_payload_signature": "\/h8+\/ekdSsDHYSsmyJaQmP75XJT8Il7wOJ5PutVqmeY=",
"auth_key": "true"
}
```
## Payin events
### `payin.create`
```json [JSON]
{
"webhook": "payin.create",
"webhook_created_at": 17232080879509,
"object_id": "ddd4a268-ac2a-5359-afa1-2c1c92ed83c5",
"object": "payin",
"object_payload": {
"payins": [
{
"payinId": "ddd4a268-ac2a-5359-afa1-2c1cxxed83c5",
"payinTag": "",
"walletId": "878744",
"userId": "1656177",
"payinStatus": "PENDING",
"paymentMethodId": "25",
"messageToUser": "A capture request has been sent to the financial institution.",
"subtotalItems": "0.00",
"subtotalServices": "0.00",
"subtotalTax": "0.00",
"amount": "12.48",
"currency": "EUR",
"createdDate": "2024-08-09 14:54:38",
"walletEventName": "reset",
"walletAlias": "alias878744",
"userFirstname": "Alex",
"userLastname": "Oak",
"codeStatus": "150117",
"informationStatus": "Capture Requested",
"refundAmount": null,
"ibanId": null,
"ibanFullname": null,
"DbtrIBAN": null,
"ibanBic": null,
"ibanTxEndToEndId": null,
"ibanTxId": null,
"forwardUrl": null,
"paymentAcceptedUrl": null,
"paymentRefusedUrl": null,
"paymentWaitingUrl": null,
"paymentExceptionUrl" null,
"payinDate": "0000-00-00 00:00:00",
"mandateId": "0",
"creditorName": null,
"creditorAddressLine": null,
"creditorCountry": null,
"creditorIban": null,
"creditorBIC": null,
"virtualIbanId": null,
"virtualIbanReference": null,
"additionalData": "{\"card\":{\"externalProvider\":{\"state\":\"completed\",\"mid\":\"00001340255\",\"authorizationCode\":\"no_code\",\"transactionReference\":\"800315441134\",\"dateCreated\":\"2024-08-09T14:54:38+0200\",\"dateUpdated\":\"2024-08-09T14:54:43+0200\",\"status\":117,\"message\":\"Capture Requested\",\"authorizedAmount\":12.48,\"capturedAmount\":12.48,\"refundedAmount\":0,\"currency\":\"EUR\",\"ipAddress\":\"0.0.0.0\",\"ipCountry\":\"\",\"cdata1\":\"212707\",\"cdata2\":\"878744\",\"cdata3\":\"1656177\",\"cdata4\":\"\",\"cdata5\":\"\",\"cdata6\":\"\",\"cdata7\":\"\",\"cdata8\":\"\",\"cdata9\":\"\",\"cdata10\":\"\",\"eci\":\"9\",\"paymentProduct\":\"mastercard\",\"paymentMethod\":{\"pan\":\"545454******5454\",\"cardHolder\":\"ALEX OAK\",\"token\":\"5d******63\",\"issuer\":\"TREE BANK, THE\",\"brand\":\"MASTERCARD\",\"country\":\"US\",\"cardExpiryMonth\":\"12\",\"cardExpiryYear\":\"2025\"},\"fraudScreening\":{\"scoring\":\"0\",\"result\":\"not_launched\",\"review\":\"\"}}}}"
}
]
},
"webhook_id": "a58d8791-2e74-4b04-8351-6b421931f80e",
"object_payload_signature": "SItdZHqCRm64kHVlcNsf/7Txxvuj6/tC274xFq4p6BU="
}
```
### `payin.update`
```json [JSON]
{
"webhook": "payin.update",
"webhook_created_at": 17232080901832,
"object_id": "ddd4a268-ac2a-5359-afa1-2c1c92ed83c5",
"object": "payin",
"object_payload": {
"payins": [
{
"payinId": "ddd4a268-ac2a-5359-afa1-2c1c92ed83c5",
"payinTag": "",
"walletId": "878744",
"userId": "1656177",
"payinStatus": "VALIDATED",
"paymentMethodId": "25",
"messageToUser": "The financial institution has processed the payment.",
"subtotalItems": "0.00",
"subtotalServices": "0.00",
"subtotalTax": "0.00",
"amount": "12.48",
"currency": "EUR",
"createdDate": "2024-08-09 14:54:38",
"walletEventName": "reset",
"walletAlias": "alias878744",
"userFirstname": "Alex",
"userLastname": "Oak",
"codeStatus": "150118",
"informationStatus": "Captured",
"refundAmount": null,
"ibanId": null,
"ibanFullname": null,
"DbtrIBAN": null,
"ibanBic": null,
"ibanTxEndToEndId": null,
"ibanTxId": null,
"forwardUrl": null,
"paymentAcceptedUrl": null,
"paymentRefusedUrl": null,
"paymentWaitingUrl": null,
"paymentExceptionUrl": null,
"paymentCanceledUrl": null,
"payinDate": "0000-00-00 00:00:00",
"mandateId": "0",
"creditorName": null,
"creditorAddressLine": null,
"creditorCountry": null,
"creditorIban": null,
"creditorBIC": null,
"virtualIbanId": null,
"virtualIbanReference": null,
"additionalData": "{\"card\":{\"externalProvider\":{\"state\":\"completed\",\"mid\":\"00001340255\",\"authorizationCode\":\"no_code\",\"transactionReference\":\"800315441134\",\"dateCreated\":\"2024-08-09T14:54:38+0200\",\"dateUpdated\":\"2024-08-09T14:54:43+0200\",\"status\":118,\"message\":\"Captured\",\"authorizedAmount\":12.48,\"capturedAmount\":12.48,\"refundedAmount\":0,\"currency\":\"EUR\",\"ipAddress\":\"0.0.0.0\",\"ipCountry\":\"\",\"cdata1\":\"212707\",\"cdata2\":\"878744\",\"cdata3\":\"1656177\",\"cdata4\":\"\",\"cdata5\":\"\",\"cdata6\":\"\",\"cdata7\":\"\",\"cdata8\":\"\",\"cdata9\":\"\",\"cdata10\":\"\",\"eci\":\"9\",\"paymentProduct\":\"mastercard\",\"paymentMethod\":{\"pan\":\"545454******5454\",\"cardHolder\":\"ALEX OAK\",\"token\":\"5d******63\",\"issuer\":\"TREE BANK, THE\",\"brand\":\"MASTERCARD\",\"country\":\"US\",\"cardExpiryMonth\":\"12\",\"cardExpiryYear\":\"2025\"},\"fraudScreening\":{\"scoring\":\"0\",\"result\":\"not_launched\",\"review\":\"\"}}}}"
}
]
},
"webhook_id": "e45a778a-12b5-49fd-8646-28d127ba68f8",
"object_payload_signature": "KuAWRSGPPEIwLmMuowh5cxxEucsyAri3zIH4ZxwsDTM="
}
```
### `payin.cancel`
```json [JSON]
{
"webhook": "payin.cancel",
"object_id": "248c79b7-fc5e-5c32-96b3-c434fd0d2639",
"object": "payin",
"object_payload": {
"payins": [
{
"payinId": "248c79b7-fc5e-5c32-96b3-c434fd0d2639",
"payinTag": "",
"walletId": "878744",
"userId": "1656177",
"payinStatus": "CANCELED",
"paymentMethodId": 25,
"messageToUser": "",
"subtotalItems": "0.00",
"subtotalServices": "0.00",
"subtotalTax": "0.00",
"amount": "20",
"currency": "EUR",
"createdDate": "2021-09-17T09:32:49+00:00",
"walletEventName": "Wallet",
"walletAlias": "alias",
"userFirstname": "Louis",
"userLastname": "Pinsard",
"codeStatus": "150113",
"informationStatus": "The financial institution refused to authorize the payment.",
"refundAmount": null,
"ibanId": null,
"ibanFullname": null,
"DbtrIBAN": null,
"ibanBic": null,
"ibanTxEndToEndId": null,
"ibanTxId": null,
"forwardUrl": null,
"paymentAcceptedUrl": null,
"paymentRefusedUrl": null,
"paymentWaitingUrl": null,
"paymentExceptionUrl": null,
"paymentCanceledUrl": null,
"payinDate": "2021-09-17T11:32:49+02:00",
"mandateId": "0",
"creditorName": null,
"creditorAddressLine": null,
"creditorCountry": null,
"creditorIban": null,
"creditorBIC": null,
"virtualIbanId": null,
"virtualIbanReference": null,
"additionalData": {
"card": {
"externalProvider": {
"transaction_reference": "mock_385371f00f004d42"
}
}
}
}
]
},
"webhook_id": "d6d58cd7-46d6-4159-bab6-48cae27a1a6a",
"object_payload_signature": "Ze1KRBH5EzV+56h9LCq048ECU3WiXiIPxrFJDgPBWA0=",
"auth_key": "true"
}
```
## PayinRefund events
### `payinrefund.create`
```json [JSON]
{
"webhook": "payinrefund.create",
"webhook_created_at": 16426047629673,
"object_id": "b457966e-6cf9-5d1d-8483-45425cfc8101",
"object": "payinrefund",
"object_payload": {
"payinrefunds": [
{
"payinrefundId": "b457966e-6cf9-5d1d-8483-45425cfc8101",
"payinrefundTag": null,
"payinrefundStatus": "PENDING",
"payinrefundDate": "2022-01-19 16:06:01",
"walletId": "971021",
"payinId": "29b4e8a8-0abc-5a24-8405-808c5eb34835",
"amount": "5",
"currency": "EUR",
"createdDate": "2022-01-19 16:04:11",
"modifiedDate": "2022-01-19 16:06:00",
"userId": "1778843",
"codeStatus": "150124",
"informationStatus": "A refund request has been sent to the financial institution.",
"reasonTms": null
}
]
},
"webhook_id": "935260ff-dd91-466c-9148-f27364db0857",
"object_payload_signature": "oFj6BWt8N4dSU7j6lamfBJoxqS0l1AczQzbRvyBwTY4=",
"auth_key": "true"
}
```
### `payinrefund.update`
```json [JSON]
{
"webhook": "payinrefund.update",
"webhook_created_at": 16426049523256,
"object_id": "b457966e-6cf9-5d1d-8483-45425cfc8101",
"object": "payinrefund",
"object_payload": {
"payinrefunds": [
{
"payinrefundId": "b457966e-6cf9-5d1d-8483-45425cfc8101",
"payinrefundTag": null,
"payinrefundStatus": "VALIDATED",
"payinrefundDate": "2022-01-19 16:09:09",
"walletId": "971021",
"payinId": "29b4e8a8-0abc-5a24-8405-808c5eb34835",
"amount": "5",
"currency": "EUR",
"createdDate": "2022-01-19 16:04:11",
"modifiedDate": "2022-01-19 16:09:07",
"userId": "1778843",
"codeStatus": "150126",
"informationStatus": "The payment was partially refunded.",
"reasonTms": null
}
]
},
"webhook_id": "e81865f8-4258-488c-b960-28035fa5c665",
"object_payload_signature": "76H1+eZsgCU\/2VrhUOES0CgFQARZPRCXX6b\/NCv2sAg=",
"auth_key": "true"
}
```
### `payinrefund.cancel`
```json [JSON]
{
"webhook": "payinrefund.cancel",
"webhook_id": "701629730",
"object": "payinrefund",
"object_id": "7dd5d61b-22db-404f-9899-d473109a6aad",
"object_payload": {
"payinrefunds": [
{
"payinrefundId": "7dd5d61b-22db-404f-9899-d473109a6aad",
"payinrefundTag": null,
"payinrefundStatus": "CANCELED",
"walletId": "366026",
"payinId": "6455658",
"payinrefundDate": "0000-00-00",
"amount": "921.00",
"currency": "EUR",
"createdDate": "2021-05-10 09:20:07",
"modifiedDate": "2021-06-01 11:30:11",
"codeStatus": "170003",
"informationStatus": "",
"reasonTms": null
}
]
},
"object_payload_signature": "pdbm9lmV2Q5ggl4EAugoT4\/HWGScmS6umv251CsBn0A="
}
```
## Chargeback events
### `card.acquiring.chargeback.create`
```json [JSON]
{
"webhook": "card.acquiring.chargeback.create",
"object_id": "0b1787dc-02f6-5c6f-a559-cb033d6890a0",
"object": "card.acquiring",
"object_payload": {
"chargebacks": [
{
"userId": "1656177",
"walletId": "878744",
"payinId": "be17c043-9287-50b2-8fb2-188546dfc72a",
"transactionReference": "10",
"payinrefundId": "0b1787dc-02f6-5c6f-a559-cb033d6890a0",
"payinMethodId": 25,
"paymentBrand": "mastercard",
"currency": "EUR",
"amount": "20",
"country": "CA",
"isRefunded": false,
"chargebackReason": "",
"payinCreatedDate": "2021-08-10 15:33:50",
"chargebackCreatedDate": "2021-08-16 11:38:45",
"payinRefundCreatedDate": null
}
]
},
"webhook_id": "48902d9b-bb04-4698-ae26-46ba6fb6233c",
"object_payload_signature": "HDkynjtisOCPOcHeD8t7Kz6Le+UBBEvjmrBJTBGPESU=",
"auth_key": "true"
}
```
---
---
url: /guide/acquiring/introduction.md
description: >-
Understand Treezor card acquiring; how to process third-party card payments to
credit a Wallet and explore common topup use cases.
---
# Introduction
Card Acquiring involves capturing funds from a third-party card to credit a Treezor [Wallet](/guide/wallets/introduction).
Treezor relies on HiPay as a payment service provider (PSP) for card acquiring. It is compatible with various [payment products](#payment-products-specificities) such as CB, Visa, and Mastercard.
**Feature activation – Acquiring is not enabled by default**
Please contact Treezor to obtain your [HiPay credentials](#hipay-environments-credentials) and to activate your [payment products](#payment-products-specificities).
Treezor supports 2 versions of Acquiring. While this documentation mainly focuses on the newest version, you may find information specific to the in the corresponding [Legacy flow](./legacy-v1) article.
## Use cases
The Card Acquiring feature can be used in the following use cases.
| Use case | Description |
| --- | --- |
| **Top-up** | The end user credits their Treezor Wallet by using their external account payment card. In such cases, the end user can credit their wallet either: Occasionally – Single payment made to credit the Treezor Wallet.Periodically – Recurring payments to credit the Wallet at regular intervals. |
| **Complement** | When the end user doesn't have enough funds on their Treezor Wallet to make the payment, they may complement the payment with funds captured on their external account payment card. This use case requires the "recurring" mode. |
## HiPay environments & credentials
HiPay provides 2 environments: *Staging* (sandbox) and *Production*.
Each environment has its own set of credentials (public and private) that Treezor provides to you. Your public credentials are to be base64-encoded before being used in the Authorization header of your requests (basic access authentication).
You may replace the values in the code snippets of this documentation as follows:
| Value | URLs |
| --- | --- |
| `{hiPayBaseUrl}` | Staging: `https://stage-secure-gateway.hipay-tpp.com/`Production: `https://secure-gateway.hipay-tpp.com/` |
| `{hiPayTokenizationFormBaseUrl}` | Staging: `https://stage-api.hipay.com/` Production: `https://api.hipay.com/` |
| `{hiPayTokenizationBaseUrl}` | Staging: `https://stage-secure2-vault.hipay-tpp.com/`Production: `https://secure2-vault.hipay-tpp.com/` |
HiPay also provides 2 dashboards:
* Staging:
* Production:
**Tip – Test cards available**
Because HiPay's staging environment and Treezor's sandbox are linked, you can use [HiPay's test cards](https://support.hipay.com/hc/en-us/articles/213882649-How-can-I-test-payment-methods) in Sandbox.
## Payment products specificities
Below are the specific details for each payment product.
| `paymentProduct` | Mandatory attributes | End user forwarding | Advanced capture | Refunds |
|--- |:---: |:---: |:---: |:---: |
| `mastercard` | `topupCardId` | | | |
| `visa` | `topupCardId` | | | |
| `cb` | `topupCardId` | | | |
| `maestro` | `topupCardId` | | | |
| `bcmc` | `topupCardId` | | | |
| `sofort-uberweisung` | ∅ | To `forwardUrl` | | |
| `ideal` | `issuerBankId` | To `forwardUrl` | | |
## Apple Pay payments compatibility
You can capture funds from a card digitized on an Apple Pay wallet. Doing so doesn't fundamentally change your acquiring flow; this is an authentication step that occurs before the [tokenization](./card-tokenization).
To set up card acquiring via Apple Pay, you must follow HiPay's documentation and send your certificate to your *Treezor Implementation Manager* to configure your environment. Please note that Treezor only supports integration with your [own certificate](https://developer.hipay.com/online-payments/payment-means/apple-pay-web#apple-pay-certificates).
**Reading – Integration guide**
See HiPay's [Apple Pay web integration guide](https://developer.hipay.com/online-payments/payment-means/apple-pay-web) for more information.
Once the authentication step is done, you can use the Apple Pay token instead of the card detailed information when [tokenizing the card](./card-tokenization).
## Endpoints
| Endpoint | [Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/v1/topups/cards/users/{userId}/topupCards`](/api-reference/api-endpoints.html#tag/Acquiring%20\(Card%20Topups\)/postTopupCard){target="\_self"} Associate a tokenized topup card to a user | `read_write` |
| [`/v1/topups/cards/users/{userId}/topupCards`](/api-reference/api-endpoints.html#tag/Acquiring%20\(Card%20Topups\)/getTopupCards){target="\_self"} Search topup cards for a given user | `read_only` |
| [`/v1/topups/cards/users/{userId}/topupCards/{topupCardId}`](/api-reference/api-endpoints.html#tag/Acquiring%20\(Card%20Topups\)/getTopupCard){target="\_self"} Retrieve information about a topup card | `read_only` |
| [`/v1/topups/cards/users/{userId}/topupCards/{topupCardId}`](/api-reference/api-endpoints.html#tag/Acquiring%20\(Card%20Topups\)/deleteTopupCard){target="\_self"} Cancel a topup card | `read_write` |
| [`/v1/topups/cards/authorizations`](/api-reference/api-endpoints.html#tag/Acquiring%20\(Card%20Topups\)/postAcqAuth){target="\_self"} Create a card topup authorization | `read_write`|
| [`/v1/topups/cards/authorizations/{authorizationId}`](/api-reference/api-endpoints.html#tag/Acquiring%20\(Card%20Topups\)/getAcqAuth){target="\_self"} Retrieve a card topup authorization | `read_only` |
| [`/v1/topups/cards/authorizations/{authorizationId}`](/api-reference/api-endpoints.html#tag/Acquiring%20\(Card%20Topups\)/deleteAcqAuth){target="\_self"} Delete a card topup authorization | `read_write` |
| [`/v1/topups/cards/authorizations/{authorizationId}/payins`](/api-reference/api-endpoints.html#tag/Acquiring%20\(Card%20Topups\)/postAcqAuthPayin){target="\_self"} Create payin from an authorization | `read_write` |
| [`/v1/topups/cards/authorizations/{authorizationId}/payins`](/api-reference/api-endpoints.html#tag/Acquiring%20\(Card%20Topups\)/getAcqAuthPayins){target="\_self"} List all payins from an authorization | `read_only` |
| [`/v1/topups/cards/refunds/{refundId}`](/api-reference/api-endpoints.html#tag/Acquiring%20\(Card%20Topups\)/acquiringv2-topup-cards-refunds-get){target="\_self"} Retrieve a card topup payin refund | `read_only` |
| [`/v1/topups/cards/refunds`](/api-reference/api-endpoints.html#tag/Acquiring%20\(Card%20Topups\)/acquiringv2-topup-cards-refunds-post){target="\_self"} Create a card topup payin refund | `read_write` |
| [`/v1/topups/cards/chargebacks/{chargebackId}`](/api-reference/api-endpoints.html#tag/Acquiring%20\(Card%20Topups\)/acquiringv2-topup-cards-chargebacks-get){target="\_self"} Retrieve a card topup payin chargeback | `read_only` |
**Reading – Learn more about Acquiring**
* [HiPay official API](https://developer.hipay.com/online-payments/overview)
* [HiPay best practices](https://treezor.zendesk.com/hc/en-us/articles/360015946959-HiPay-Best-practices)
* [Recurring Payins](https://treezor.zendesk.com/hc/en-us/articles/360017100639-HiPay-PayIn)
* [Sentinel profile](https://treezor.zendesk.com/hc/en-us/articles/360017474380-What-is-Sentinel-Hipay)
* [3DS Strong authentication](https://treezor.zendesk.com/hc/en-us/articles/360017648859-DSP2-Strong-customer-authentication-and-3DSv2)
---
---
url: /guide/cards/introduction.md
description: >-
Get a foundational understanding of the Treezor API card issuing, your card
program and customization. Includes the card object key attributes, JSON
structure, and related endpoints list.
---
# Introduction
Treezor allows you to issue both Physical and Virtual Cards. This section focuses on Card creation and management.
Before starting to issue Cards, you must have a [Card Program](#card-program) set up with Treezor.
**Information – Card Top-up feature also available**
If you're looking to receive card payments to credit a Wallet, see the [Card Acquiring](/guide/acquiring/introduction) section of the documentation.
## Card Program
Your Card Program defines the design and configuration of the issued Cards. Your *Welcome Pack* provided by Treezor contains all the forms to fill in.
Card Programs require assistance from Treezor teams. Contact your Treezor:
* **Account Manager** to [define the design your cards](#card-design).
* **Implementation Manager** to [define configuration and customization options](#card-product-customization-options).
Once your Card Program is set up, Treezor will give you your `cardPrint`. This value is the unique identifier of you Card Program and is required to [create Cards](creation).
### Card Design
You can design both your cards and their shipping packaging.
Your *Welcome Pack* contains forms and templates for [Physical Cards](creation#physical-card-creation) and [Virtual Cards](creation#virtual-card-creation) design, along with resources to design your cards while abiding by:
* The guidelines provided by the schemes (e.g., Mastercard, Visa, etc.).
* The predefined formats from the card printing third-party.
### Card Product & Customization options
Your Card Product defines options such as [Permissions Group](/guide/cards/restrictions-limits#permission-groups-permsgroup) and default limits for the Cards you issue.
You can also add logos, customized text, and specify packaging and card design on a per-Card basis. See the [Customization](/guide/cards/creation#customization) article for more information.
## Key attributes
Below are some of the most important Card attributes.
| Attribute | Type | Description |
|--- |--- |--- |
| `isLive` | integer | The activation status of the Card. Cards are issued as inactive and are activated using the [dedicated request](./creation#activation). `0` – Not activated yet`1` – Activated |
| `statusCode` | integer | The [current Card status](#card-status-statuscode) such as active, stolen, temporarily or permanently blocked. |
| `pinTryExceeds` | integer | Indicates if the PIN try limit has been exceeded (when set to `1`, the PIN is blocked). |
| `cardDesign` | string | The Card Print Id, the design that is/will be printed on the Card. |
| `optionAtm` | integer | The ability to make [withdrawals at ATM](/guide/cards/restrictions-limits#payment-withdrawal-limits). |
| `optionForeign` | integer | The ability to use the Card [outside the user's country](/guide/cards/restrictions-limits#options-permission-groups). |
| `optionOnline` | integer | The ability to use the Card for [online Payments](/guide/cards/restrictions-limits#options-permission-groups). |
| `optionNfc` | integer | The ability to use the Card for [contactless payment](/guide/cards/restrictions-limits#options-permission-groups). |
| `embossedName` | string | The cardholder's name, as embossed or etched on the Card. |
| `maskedPan`| string | The [PAN](/guide/overview/glossary#primary-account-number-pan) with the middle numbers redacted for safety. |
| `publicToken` | string | 9-character long string printed on the Card. It can be used to [activate a card](./creation#activation). |
**API – API Reference available**
For a complete list of Card attributes, check the [Cards](/api-reference/api-endpoints.html#tag/Cards){target="\_self"} section of the API Reference.
### Card Status (`statusCode`)
Statuses are defined in the `statusCode` attribute of a Card.
| Code | Plaintext value | Description | Lock type |
| :---: | --- | --- | --- |
| `0` | `UNLOCK` | The card is unlocked and can be used (if no other options or limits prevent it). | N/A |
| `1` | `LOCK` | The card is locked and cannot be used. | Reversible |
| `2` | `LOST` | The card is lost and cannot be used. | Permanent |
| `3` | `STOLEN` | The card is stolen and cannot be used. | Permanent |
| `4` | `DESTROYED` | The card is terminated and cannot be used. | Permanent |
| `5` | `LOCK_INTERNAL` | The card is locked by Treezor and cannot be used, only Treezor is able to unlock it. | Reversible |
| `6` | `EXPIRED` | Automatically set value indicating the card has expired. The card was either renewed or the expiry date passed. Treezor sends the following webhooks: [`card.expiryAlert`](/guide/cards/events#card-expiryalert) – The card expires at the end of the next month; you can anticipate [Renewal](/guide/cards/renewal). [`card.update`](/guide/cards/events#card-update) – The card expired. | Permanent |
| `7` | `CUSTOM_LOCK` | Secondary lock; the card is locked and cannot be used. This is the same mechanism as `LOCK`, providing you more flexibility to manage cards (e.g., reporting reasons, preventing cardholders to unlock the card themselves). | Reversible |
## Card object
```json [JSON]
{
"cardId": 0,
"userId": 0,
"walletId": 0,
"walletCardtransactionId": 0,
"mccRestrictionGroupId": 0,
"merchantRestrictionGroupId": 0,
"countryRestrictionGroupId": 0,
"publicToken": "string",
"cardTag": "string",
"statusCode": "UNLOCK",
"isLive": 0,
"pinTryExceeds": 0,
"maskedPan": "string",
"embossedName": "string",
"expiryDate": "string",
"CVV": "string",
"startDate": "string",
"endDate": "string",
"countryCode": "string", // Inherited from the User's country
"currencyCode": "string", // Always EUR
"lang": "string", // Inherited from the User's language
"deliveryTitle": "string",
"deliveryLastname": "string",
"deliveryFirstname": "string",
"deliveryAddress1": "string",
"deliveryAddress2": "string",
"deliveryAddress3": "string",
"deliveryCity": "string",
"deliveryPostcode": "string",
"deliveryCountry": "string",
"mobileSent": "string", // Inherited from the User's phone
"limitsGroup": "string",
"permsGroup": "string",
"cardDesign": "string",
"virtualConverted": 0,
"optionAtm": 0,
"optionForeign": 0,
"optionOnline": 0,
"optionNfc": 0,
"limitAtmYear": 0,
"limitAtmMonth": 0,
"limitAtmWeek": 0,
"limitAtmDay": 0,
"limitAtmAll": 0,
"limitPaymentYear": 0,
"limitPaymentMonth": 0,
"limitPaymentWeek": 0,
"limitPaymentDay": 0,
"limitPaymentAll": 0,
"paymentDailyLimit": 0,
"totalAtmYear": 0,
"totalAtmMonth": 0,
"totalAtmWeek": 0,
"totalAtmDay": 0,
"totalAtmAll": 0,
"totalPaymentYear": 0,
"totalPaymentMonth": 0,
"totalPaymentWeek": 0,
"totalPaymentDay": 0,
"totalPaymentAll": 0,
"createdBy": 0,
"createdDate": "string",
"modifiedBy": 0,
"modifiedDate": "string",
"renewalType": "string",
"renewalDate": "string",
"originalCardId": 0,
"totalRows": 0,
"designCode": "string",
"cardLanguages": "string",
"eventName": "string", // Inherited from the Wallet the card is attached to
"eventAlias": "string", // Inherited from the Wallet the card is attached to
"restrictionGroupLimits": [
{
"paymentDailyLimit": 0,
"mccRestrictionGroups": 0,
"countryRestrictionGroups": 0,
"merchantIdRestrictionGroups": 0
}
],
"cancellationNumber": "string",
"metadata": "string",
"renewalDate": "string",
"renewalType": "string",
"originalCardId": 0,
"logoId": "string",
"logoBackId": "string",
"packageId": "string",
"customizeInfo": "string",
"letterCustomizedInfo": "string",
"freeCustomizedInfo": "string",
"deliveryMethod": 0,
"pinMailer": 0,
"batchDeliveryId": 0,
"sendToParent": 0
}
```
## Endpoints
| Endpoint |[Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/v1/cards/CreateVirtual`](/api-reference/api-endpoints.html#tag/Cards/postCardVirtual){target="\_self"} Create a new Virtual Card | `read_write` |
| [`/v1/cards/RequestPhysical`](/api-reference/api-endpoints.html#tag/Cards/postCardPhysical){target="\_self"} Request a new Physical Card | `read_write` |
| [`/v1/cards/Register3DS`](/api-reference/api-endpoints.html#tag/Cards/post3ds){target="\_self"} Register a Card for 3D Secure | `read_write` |
| [`/v1/cardimages`](/api-reference/api-endpoints.html#tag/Cards/getCardImage){target="\_self"} Retrieve a Virtual (or Virtual converted) Card image | `read_write` |
| [`/v1/cards`](/api-reference/api-endpoints.html#tag/Cards/getCards){target="\_self"} Search Cards | `read_only` |
| [`/v1/cards/{cardId}`](/api-reference/api-endpoints.html#tag/Cards/getCard){target="\_self"} Retrieve a Card using its `id` | `read_only` |
| [`/v1/cards/{cardId}`](/api-reference/api-endpoints.html#tag/Cards/putCard){target="\_self"} Update a Card information | `read_write` |
| [`/v1/cards/{cardId}/Activate`](/api-reference/api-endpoints.html#tag/Cards/activateCard){target="\_self"} Activate a Card initially | `read_write` |
| [`/v1/cards/{cardId}/Assign`](/api-reference/api-endpoints.html#tag/Cards/reassignCard){target="\_self"} Assign or Reassign a Card to a User | `read_write` |
| [`/v1/cards/{cardId}/ChangePIN`](/api-reference/api-endpoints.html#tag/Cards/changePin){target="\_self"} Change a PIN (requires to know the previous one) | `read_write` |
| [`/v1/cards/{cardId}/setPIN`](/api-reference/api-endpoints.html#tag/Cards/setPin){target="\_self"} Define a PIN code | `read_write` |
| [`/v1/cards/{cardId}/UnblockPIN`](/api-reference/api-endpoints.html#tag/Cards/unblockPin){target="\_self"} Unblock a PIN code | `read_write` |
| [`/v1/cards/{cardId}/ConvertVirtual`](/api-reference/api-endpoints.html#tag/Cards/convertVirtual){target="\_self"} Convert a Virtual Card to a Physical one | `read_write` |
| [`/v1/cards/{cardId}/Limits`](/api-reference/api-endpoints.html#tag/Cards/putLimits){target="\_self"} Change a Card limits | `read_write` |
| [`/v1/cards/{cardId}/Options`](/api-reference/api-endpoints.html#tag/Cards/cardOptions){target="\_self"} Change a Card options | `read_write` |
| [`/v1/cards/{cardId}/LockUnlock`](/api-reference/api-endpoints.html#tag/Cards/updateBlockStatus){target="\_self"} Toggle the locking status of a Card | `read_write` |
| [`/v1/cards/{cardId}/Regenerate`](/api-reference/api-endpoints.html#tag/Cards/regenerateCard){target="\_self"} Regenerate a Virtual Card image | `read_write` |
If you have migrated to the [PCI DSS services](./pci-dss), please note some endpoints have been replaced. See the list of [PCI DSS-specific endpoints](./pci-dss#pci-dss-endpoints) for more information.
## Object relations diagram
---
---
url: /guide/cheques/introduction.md
description: >-
Get a foundational understanding of Treezor check cash-in feature. Includes
key attributes, JSON structure, and related endpoints list.
---
# Introduction
Treezor allows your end users to [cash checks](cashing).
Checks are a traditional means of physical payment, mapped to `Payin` objects, with a `paymentMethodId` attribute set to `26`.
**Configuration – Checks are not enabled by default**
You can request access to this feature by contacting your *Treezor Account Manager*.
**Important – Limitations**
* Recipient name on the check must match the Wallet owner name.
* Maximum amount set by Treezor. Contact your *Treezor Account Manager* to define your limit.
## Process
Check cashing into a Wallet implies the creation of the relevant object in Treezor API and the physical handling of checks so that they can be processed.
```mermaid
sequenceDiagram
autonumber
participant app as You
participant trz as Treezor
app->>trz: Create a Payin for the check
trz->>app: Sends a payin.create webhook (status 160001) While waiting for aknowledgement
trz->>app: Sends a payin.create webhook (status 160003) Once the check can be mailed
app->>trz: Send the physical check within 14 days
trz->>trz: Check processing
trz->>app: Sends a payin.update webhook (status 140005 for VALIDATED)
```
The steps are the following:
1. You create a Payin (`paymentMethodId` `26`)
2. Treezor sends a [`payin.create`](/guide/cheques/events) webhook (status `160001`) confirming the creation
3. Treezor sends a [`payin.create`](/guide/cheques/events) webhook (status `160003`) allowing you to mail the check in
4. You mail in the physical check to the indicated postal address
5. The check is processed by Treezor's partner and is either:
* **Accepted** – The [`payinStatus`](/guide/cheques/introduction#status-payinstatus) is set to `VALIDATED`
* **Refused** – The [`payinStatus`](/guide/cheques/introduction#status-payinstatus) is set to `CANCELED` and the check is mailed back to you.
The processing of a check follows strict delays:
* Delay between the check Payin creation and physical check reception can't exceed **14 days**
* Delay between the physical check reception and the validation can't be lower than **11 days**
**Tip – Check life cycles examples are available**
Refer to the [Life cycle](./cashing#life-cycle) section for more information.
## Anatomy of a check
The physical check contains information that you have to include in the corresponding Payin object.
| Section | Description |
| --- | --- |
| **CMC7 line** | The unique identifier of the physical check printed in magnetic ink at the bottom of the check. Made up of: **CMC7A** – The first part of the CMC7 line**CMC7B** – The second part of the CMC7 line**CMC7C** – The third part of the CMC7 line |
| **RLMC key** | The 2-character key, enclosed by `<>` or `()` used to check the integrity of the CMC7 line (%97.) |
| **Drawer** | Information about the user who emitted the check. |
| **Beneficiary** | The user who receives the check and cashes it. |
## Key attributes
Checks rely on the Payin object. Below are some of the relevant Payin attributes when it comes to cashing checks.
| Attribute | Type | Description |
|--- |--- |--- |
| `paymentMethodId` | integer | The payment method. For checks, this value is always `26`. |
| `payinStatus` | string | The status of the check cashing process. May be one of the following: `PENDING` – Waiting for payment`VALIDATED` – Payment is validated`CANCELED` – Payment is canceled |
| `amount` | number | The [amount](/guide/api-basics/data-format#amounts) of the check. |
| `currency` | string | The [currency](/guide/api-basics/data-format#currencies) of the check. |
| `additionalData` | object | Contains the cmc7 line, the drawer data and the RLMC key of the check. |
**API – API Reference available**
Refer to the [Payins](/api-reference/api-endpoints.html#tag/payins){target="\_self"} section in the API Reference for a complete list of Checks attributes.
### Additional Data (`additionalData`)
The `additionalData` object allows you to provide information that is available on the physical check.
```json [JSON]
"additionalData":
{
"cheque": {
"cmc7": {
"a": "000036", // required, 1st section of CMC7 line
"b": "0230021566985", // required, 2nd section of CMC7 line
"c": "00700065456" // required, 3rd section of CMC7 line
},
"RLMCKey": "22", // required, RMLC key
"drawerData": { // required object
"isNaturalPerson": true, // required, boolean, true: physical / false: legal entity
"email": "aoak@example.com", // drawer's email
"firstName": "Alex", // drawer's firstname
"lastName": "Oak", // drawer's lastname
"address": "22 Rosewood Lane", // drawer's address
"address2": "App. 12", // drawer's address continued
"zipCode": "75001", // drawer's postcode
"city": "Paris" // drawer's city
}
}
}
```
### Status Codes (`codeStatus`)
| Code | Description |
|- |- |
| 140004 | The cheque Payin has been cancelled before the reception at the treatment center. |
| 140005 | Funds received by Treezor. Payin is validated and funds are usable on the wallet. |
| 160001 | Waiting for treatement center aknowledgement |
| 160002 | The treatement center aknowledgement failed|
| 160003 | The cheque can now be sent to the treatement center |
| 151125 | The controls of the cheque have failed. |
| 151129 | Cheque has been successfully treated. Waiting for bank settlement |
| 151130 | Payment is in the 11 working days delay period, to prevent bounced cheques. |
| 151132 | The check has been received by the treatment center of our partner. |
| 151134 | The check has not been received by the treatement center in the allowed delay of 14 calendar days |
| 151136 | Check rejected |
| 170001 | Refund request |
| 170005 | Refund validated |
## Check payin object
```json [JSON]
{
"payinId": "2xxxxx1",
"payinTag": "",
"walletId": "3xxxx4",
"userId": "1xxxx2",
"payinStatus": "CANCELED",
"paymentMethodId": "26",
"messageToUser": "",
"subtotalItems": "0.00",
"subtotalServices": "0.00",
"subtotalTax": "0.00",
"amount": "195.00",
"currency": "EUR",
"createdDate": "2020-09-22 12:43:14",
"walletEventName": "Name Test",
"walletAlias": "Alias Test",
"userFirstname": "TEST Chèque",
"userLastname": "",
"codeStatus": "151128",
"informationStatus": "Cheque cannot be treated amount is too low comparing to original demand",
"refundAmount": null,
"DbtrIBAN": null,
"forwardUrl": null,
"paymentAcceptedUrl": null,
"paymentRefusedUrl": null,
"paymentWaitingUrl": null,
"paymentExceptionUrl": null,
"paymentCanceledUrl": null,
"payinDate": "0000-00-00",
"mandateId": "0",
"creditorName": null,
"creditorAddressLine": null,
"creditorCountry": null,
"creditorIban": null,
"creditorBIC": null,
"virtualIbanId": null,
"virtualIbanReference": null,
"additionalData": {
"cheque": {
"cmc7": {
"a": "5xxxxx1",
"b": "0xxxxxxxxxx8",
"c": "1xxxxxxxxxx4"
},
"RLMCKey": "xx",
"drawerData": {"isNaturalPerson":false}
}
}
}
```
## Endpoints
| Endpoint | [Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/v1/payins`](/api-reference/api-endpoints.html#tag/Payins/postPayin){target="\_self"} Create a check payin | `read_write` |
| [`/v1/payins`](/api-reference/api-endpoints.html#tag/Payins/getPayins){target="\_self"} Search for check payins | `read_only` |
| [`/v1/payins/{payinId}`](/api-reference/api-endpoints.html#tag/Payins/getPayin){target="\_self"} Retrieve a check payin using its `id` | `read_only` |
| [`/v1/payins/{payinId}`](/api-reference/api-endpoints.html#tag/Payins/deletePayin){target="\_self"} Delete a check payin | `read_write` |
---
---
url: /guide/strong-customer-authentication/introduction.md
description: >-
Learn about Strong Customer Authentication (SCA), a European regulatory
requirement, and its implementation with Treezor services for secure payments.
---
# Introduction
[Strong Customer Authentication (SCA)](https://en.wikipedia.org/wiki/Multi-factor_authentication) is a European regulatory requirement aiming at reducing fraud and making payments more secure.
Because you're using Treezor ACPR agreement, you must implement SCA into your user flow by declaring SCA either:
* [With Treezor services](/guide/strong-customer-authentication/securing-endpoints#applying-sca-with-treezor-services) for Treezor endpoints falling into SCA functional context and/or
* [Outside Treezor services](/guide/strong-customer-authentication/securing-endpoints#declaring-sca-external-operations) for any sensitive operation made from your back end.
## Key concepts
A defined set of user actions requires Strong Customer Authentication, either by session or by operation.
| Context | Description |
|---|---|
| [**Per session**](#per-session-authentication-main-steps) | When logging-in, the User is required to authenticate with SCA. This allows for some follow-up actions without an additional SCA. |
| [**Per operation**](#per-operation-authentication-main-steps) | When doing a sensitive operation, the User is required to use SCA to confirm it, even if they already went through strong authentication when logging-in. |
To ensure a Strong Customer Authentication, we use at least 2 of the following 3 elements:
* Something the User **has** (smartphone, hardware token)
* Something the User **is** (fingerprint, facial identification)
* Something the User **knows** (password, PIN)
In a nutshell, SCA aims to prove that the operation effectively originates from the User by:
1. **Generating a cryptographic signature** known as SCA Proof (JWS) of the requested operation on the User's device.
2. **Sending this SCA proof** to the Treezor API along with the usual operation request (e.g., creating a Beneficiary).
3. **Checking the received SCA proof** by the Treezor API and only allowing operation if legitimate.
Treezor relies on a digital safe containing a private key necessary for Strong Customer Authentication: the [SCA Wallet object](#sca-wallet-object).
### SCA authentication flow
The following diagram illustrates what is required of your app and back end to enforce Strong Customer Authentication.
**Information – The diagram is not exhaustive, it doesn't cover:**
* The notion of [session expiration](#sessions)
* The necessity of a [strong authentication every 180 days](#per-session)
```mermaid
sequenceDiagram
participant app as Your app
participant agent as Your back end
participant trz as Treezor
Note over app: Generate an SCA Proof (JWS) using the SDK (either of type None, Biometry or Passcode) or using WebAuthn
app->>agent: End User logs in to your API
Note over app, agent: Forward the SCA proof (JWS)
agent->>trz: Authentication using delegated_end_user
Note over agent, trz: Forward the SCA proof (JWS)
trz->>agent: Returns a JWT
Note over agent: Store this JWT and associate it to the User as it can only be used on behalf of this User
loop For each call to Per-Session endpoints
app->>agent: End User wants to do some Per-Session requests
Note over agent: Retrieve the User's JWT from your database Do not request a new JWT from Treezor if yours hasn't expired
agent->>trz: Call the relevant endpoint
Note over agent, trz: Place the JWT in the "Authorization:" header
trz->>agent: Response
agent->>app: Response
end
loop For each call to Per-Operation endpoints
app->>agent: End User wants to do some Per-Operation requests
Note over app: Generate an SCA Proof (JWS) using the SDK or using WebAuthn The proof must sign the relevant parameters (payload) of the request
Note over app, agent: Forward the SCA proof (JWS)
Note over agent: Retrieve the User's JWT from your database Do not request a new JWT from Treezor if yours hasn't expired
agent->>trz: Call the relevant endpoint
Note over agent, trz: Place the JWT in the "Authorization:" header
%Note over agent, trz: Place the JWS in the "X-SCA-Authorization:" header
Note over agent, trz: Forward the SCA proof (JWS)
trz->>agent: Response
agent->>app: Response
end
```
#### Per Session authentication main steps
For other requests to the Treezor API.
This can be done using the [SDK](sdk) or [Web Native](#web-native) solution.
The SCA proof is passed as a header parameter of your authentication request.
| Signature | SCA type | Treezor returns |
| --- | --- | --- |
| **Valid** | Other than `None` | Treezor returns a JWT (`trz:sca` valued to `true`) |
| **Valid** | `None` | Treezor returns a JWT (`trz:sca` valued to `false`). |
| **Invalid** | N/A | N/A, no JWT is delivered |
* [Per Session requests](/guide/strong-customer-authentication/securing-endpoints#active-session-actions) will be accepted if the JWT:
* Contains `trz:sca` = `true` and
* Has been obtained less than 5 minutes ago
* Has been used to make any type of valid request
* [Per Session requests **with 180 days exemption**](/guide/strong-customer-authentication/securing-endpoints#passive-session-actions) regardless of the `trz:sca` value and inactivity (as long as the JWT itself hasn't expired).
#### Per Operation authentication main steps
When a request to the Treezor API [mandates a per-operation SCA](/guide/strong-customer-authentication/securing-endpoints#individual-actions):
This step is the same as for any endpoint.
This produces a unique signature (using [the SDK](sdk#mobile-sdk) or [Web Native](#web-native)).
* For requests using `GET`, `DELETE` you add the signature as a `sca` query parameter
* For requests using `PUT`, `POST` you add the signature as a `sca` body parameter
* If the signature is **valid**, the request is handled by Treezor
* If the signature is **invalid or missing**, the request is rejected by Treezor with a `400` Status Code
## SCA solutions
Treezor offers mobile and web native solutions for you to produce the cryptographic signatures necessary for Strong Customer Authentication:
| Solution | Description |
| --- | --- |
| **[Mobile Abstraction Layer](sdk-abstraction)** | React abstraction layer wrapping the Mobile SDK. |
| **[Mobile Flutter Bridge](#mobile-flutter-bridge)** | Bridge exposing the same methods and interfaces as the Mobile SDK, in Flutter. |
| **[Mobile SDK](sdk)** | SDK providing SCA wallet functionality, device eligibility checks, and cryptographic signature generation for strong authentication. |
| **[Web Native](#web-native)** | Solution to generate SCA proofs within a web browser for use cases without a mobile app. |
### Mobile Abstraction Layer
Treezor provides a React abstraction layer that lives above the [Mobile SDK](sdk). This wrapper allows you to implement SCA features more easily than via the SDK directly.
**Prerequisites:**
* Import `react-native-treezor-sca` using credentials provided by Treezor.
* Import `bridge-reactNative-{version}` provided to you encrypted using GPG.
* Using `npm install -S {package}` or `yarn add {package}`.
Learn more in the dedicated [Mobile Abstraction Layer](sdk-abstraction) article.
### Mobile Flutter Bridge
Treezor provides a Flutter bridge which exposes the same methods and interfaces as the [Mobile SDK](sdk), in Flutter.
To use it you have to specify the following dependency in your `pubspec.yaml`.
```yaml[YAML]
dependencies:
endtrust_bridge_flutter:
path: path_to_the_bridge_folder
```
The bridge will be provided to you as a ZIP archive.
#### Android Bridge Configuration
Add the following to `android/app/build.gradle`
```json [JSON]
android {
[...]
defaultConfig {
[...]
minSdkVersion 21
}
packagingOptions {
jniLibs {
keepDebugSymbols += "*/*/libscm.so"
useLegacyPackaging = true
}
}
}
```
##### Metadata
Add the following metadata to `android/app/src/main/AndroidManifest.xml`
```xml [XML]
```
##### Permissions
Add the following permissions to `android/app/src/main/AndroidManifest.xml`
```xml [XML]
```
### Mobile SDK
All the SDK features are provided through an SCA Wallet object implemented in the SDK itself. It can be seen as a base layer, gathering configuration and security settings on which Strong Customer Authentication relies.
SCA Wallets are synchronized between the mobile device and Treezor back end.
The main property of the SCA wallet is its state, evolving from actions triggered on the back end or on hosting app side, and defining how an SCA Wallet is accessible to the hosting app.
**Android**
* Minimum supported version – Android 5.0 Lollipop (API level 21)
* Target version – Tested with Android versions until Android 13 (API level 33)
**iOS**
* Minimum supported version – iOS 11
* Minimum supported version for pushing a Card to Apple Pay – iOS 13.4
* Swift 5
Learn more in the dedicated [Mobile SDK](sdk) article.
#### Sandbox
#### Production
### Web Native
Web-only banking scenarios can't rely on mobile app SDK for cryptography and signing. Instead, you can use the web native solution to generate SCA proofs within a web browser. It leverages public key cryptography for user authentication, achieving a security level comparable to native apps.
Please note that in the case of Web Native, all passive session actions require [per-session SCA](./securing-endpoints#per-session) instead.
Treezor technology is built relying on [WebAuthn](https://webauthn.io/). This solution and related documentation includes materials copied or derived from the [W3C Web Authentication recommendation](https://www.w3.org/TR/webauthn/).
This work is distributed under the [W3C® Software and Document License](https://www.w3.org/copyright/software-license-2023/) in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#### Web Native & SCA Elements
WebAuthn addresses the [SCA elements](/guide/strong-customer-authentication/introduction#key-concepts) as follows.
| Element | Description |
| --- | --- |
| **Passkey** | Represents “something the user **has**”. |
| **Passcode** | Represents “something the user **knows**”. The passcode is unique by user for all their devices, and is [encrypted](#passcode-encryption) on the user's device before transmission to Treezor. |
You might wonder why Treezor requires the passcode, when a smartphone might already mandate biometry to unlock the passkeys, satisfying both “something the user **has**” and “something the user **is**”.
Although the conditions *may* be satisfied in this very situation, due to the multiplicity of authenticators supported by WebAuthn the passkeys may be accessed with or without biometry.
**Therefore, to be SCA-compliant with every WebAuthn authenticator, Treezor requires the [encrypted passcode](/guide/strong-customer-authentication/user-enrollment#passcode-encryption) in addition to the WebAuthn generated signature**.
**Note – Authentication type `= None` only applies to the [SDK](sdk).**
When using Web Native, the authentication is always stronger than `None` as we use “something the user **has**” (trusted browser/device) and require “something the user **knows**” (passcode).
#### Requirements
Web Authentication API usage requires hardware capabilities to handle cryptographic operations and keys. Unauthorized access protection can be ensured using either:
* A [Trusted Execution Environment (TEE)](https://en.wikipedia.org/wiki/Trusted_execution_environment) or
* A [Trusted Platform Module (TPM)](https://en.wikipedia.org/wiki/Trusted_Platform_Module)
TEEs and TPMs are available on modern computers and smartphones. They can also be found in dedicated roaming hardware authenticators.
When first generating their passkey, the browser prompts the User to select a storage location. The passkey storage location depends on the device capabilities and how the WebAuthn API is called. They can be one of the following:
Requires the device to possess necessary cryptographic capabilities (TEE, TPM, or other hardware-based security features).
Such as YubiKey, SoloKey, or Google Titan for instance.
Utilizing a QR code displayed during the Web Native enrollment process, a smartphone can scan the code to assist in the key pair generation and storage process.
This last method leverages the smartphone security features to extend Web Native reach beyond the first two options. The smartphone can either store the key pair or assist in the authentication process by verifying the user's identity before the key pair is generated, stored, or accessed securely. Both the computer and the smartphone must have Bluetooth enabled and be connected to the internet (although they do not necessarily need to be on the same network).
**Reading – Matrix of device support**
A comprehensive matrix detailing device support and key pair synchronization features is available at , offering developers insight into the wide array of compatible devices and their specific capabilities.
## SCA Wallet object
An SCA Wallet is the secure enclave locally present on a device. Please note that this is an example of SCA Wallet object, and that some attributes such as the `activationCode` are only valorized when relevant.
```json [JSON]
{
"id": "1a73b1eca9a64cf19a448b61dd494d15",
"status": "CREATED",
"subStatus": "CREATED_READY",
"passcodeStatus": "NOT_SET",
"locked": false,
"lockReasons": [],
"lockMessage": null,
"settingsProfile": "default",
"mobileWallet": {
"pushMessagingId": "c9wB0BakTaakW9vwtDIyl_:APA91bH-0-ArJEbYdV9s8m-6332wXfvO1DLYeoZzkkqasU3s-1893KdLarFdM7dJBHsb22H4lOFI4Xr_PzE9bFS2w",
"productModel": "SM-A415F",
"os": "ANDROID",
"deviceIdType": "ANDROID_ID",
"secretFingerprint": "0x83ec6a38e8cd9f12bc1ed89e771ca402048959e738943dAAAAAAAA",
"lastEligibilityCheck": "2023-11-15T10:04:50Z",
"nfc": true,
"deviceId": "c2032a73ac90de11",
"appBuildNumber": "v04-04-06-06-02-02",
"productFingerprint": "samsung/a41eea/a41:12/SP1A.210812.016/A415FXX123456:user/release-keys",
"mobileUpdateDate": "2023-11-15T10:04:50Z",
"appleTeamId": null,
"emulator": false,
"pushMessagingProvider": "FIREBASE",
"osVersion": "12",
"root": "0",
"sdkVersion": "2.4.11",
"brand": "samsung"
},
"activationCode": null,
"creationDate": "2023-07-13T15:29:05+02:00",
"deletionDate": null,
"activationCodeExpiryDate": "2023-07-13T15:49:05+02:00",
"authenticationMethods": [
{
"type": "DEVICE_BIOMETRIC",
"usages": [
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": {
"validityDuration": 60
}
},
{
"type": "HYBRID_PIN",
"usages": [
"WALLET_MANAGEMENT",
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": {
"maxAttempts": 3,
"validityDuration": 60
}
},
{
"type": "NONE",
"usages": [
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": []
},
{
"type": "CLOUD_PIN",
"usages": [
"WALLET_MANAGEMENT",
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": {
"maxAttempts": 3,
"validityDuration": 60
}
}
],
"invalidActivationAttempts": null,
"userId": "3400118",
"scaWalletTag": "Iphone 13 mini",
"clientId": "string",
"activationDate": "2023-07-15T15:29:05+02:00",
"lockDate":null,
"unlockDate":null,
"resetPinDate":null
}
```
### Key attributes
#### Status (`status`)
| Status | Description |
| --- | --- |
| `CREATING` | SCA Wallet is being created |
| `CREATED` | SCA Wallet has been created, but has not yet been initialized |
| `INITIALIZING` | SCA Wallet is being initialized |
| `ACTIVE` | SCA Wallet has been initialized and is not locked or deleted |
| `DELETED` | SCA Wallet has been deleted by issuer |
#### Sub Status (`subStatus`)
| Sub Status | Description |
| --- | --- |
| `CREATING_IN_PROGRESS` | SCA Wallet is being created |
| `CREATED_BLOCKED` | SCA Wallet created but may not be used yet |
| `CREATED_READY` | SCA Wallet created that can be used |
| `INITIALIZING_MOBILE` | SCA Wallet is being initializing by the mobile |
| `ACTIVATED_LOGGED_IN` | User is logged in |
| `ACTIVATED_LOGGED_OUT` | User is logged out |
| `DELETED_BY_ISSUER` | SCA Wallet has been deleted by the issuer |
| `DELETED_UNINSTALLED` | SCA Wallet has been deleted because the SCA wallet has been uninstalled |
#### Passcode Status (`passcodeStatus`)
| Passcode Status | Description |
| --- | --- |
| `SET` | Passcode was set by the customer |
| `NOT_SET` | Passcode was not set by the customer |
| `TO_BE_CHANGED` | Passcode has to be changed |
| `NONE` | None |
#### Locking Reasons (`lockReason`)
| Lock Reason | Description |
| --- | --- |
| `ISSUER` | You locked the SCA Wallet (generic lock reason) |
| `LOST_DEVICE` | End user declared a lost device |
| `STOLEN_DEVICE` | End user declared a stolen device |
| `FRAUDULENT_USE_SUSPECTED_BY_ISSUER` | You suspected a fraudulent use of the SCA Wallet |
| `FRAUDULENT_USE_SUSPECTED_BY_CLIENT` | End user suspected a fraudulent use of the SCA Wallet |
| `TERMINATE_SERVICE` | Your business relation with the end user was terminated |
**Note – You may encounter locking reasons that can't be set manually**
* `DELETED` – The SCA Wallet [was deleted](sca-wallet-lifecycle#deletion)
* `PASSCODE` – The end user entered too many wrong PIN codes
* `PAYMENT` – The end user entered too many wrong PIN codes during a payment SCA
## Endpoints
| Endpoint | [Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/core-connect/sca/scawallets`](/api-reference/api-endpoints.html#tag/SCA/postScaWallet){target="\_self"} | `legal`, `read_write` |
| [`/core-connect/sca/scawallets/swap`](/api-reference/api-endpoints.html#tag/SCA/swapSCAWallets){target="\_self"} | `read_write` |
| [`/core-connect/sca/scawallets?userId={userId}`](/api-reference/api-endpoints.html#tag/SCA/getSCAWallets){target="\_self"} | `read_only` |
| [`/core-connect/sca/scawallets/{scaWalletId}`](/api-reference/api-endpoints.html#tag/SCA/getScaWallet){target="\_self"} | `read_only` |
| [`/core-connect/sca/scawallets/{scaWalletId}/lock`](/api-reference/api-endpoints.html#tag/SCA/putScaWallet){target="\_self"} | `read_only` |
| [`/core-connect/sca/scawallets/{scaWalletId}/resetPin`](/api-reference/api-endpoints.html#tag/SCA/resetScaWalletPin){target="\_self"} | `legal` |
| [`/core-connect/sca/scawallets/{scaWalletId}/unlock`](/api-reference/api-endpoints.html#tag/SCA/unlockScaWallet){target="\_self"} | `read_only` |
| [`/core-connect/sca/setPasscode`](/api-reference/api-endpoints.html#tag/SCA/setPasscode){target="\_self"} | `read_write` |
| [`/core-connect/sca/scawallets/{scaWalletId}`](/api-reference/api-endpoints.html#tag/SCA/deleteScaWallet){target="\_self"} | `read_only` |
---
---
url: /guide/dashboard/introduction.md
description: >-
Configure your Treezor experience and let your team of operators provide
support to your end users through the ready-to-use Treezor Dashboard web
application.
---
# Introduction
The Dashboard is a ready-to-use web application for your teams to use as a back office.
From there, your Dashboard Users can manage your end users, hence providing support without having to develop an application or going through complex, technical-driven processes.
Here is what the Dashboard can do for you:
* **End users support** – Manage users, wallets, cards, and operations from the interface.
* **Technical configuration** – Makes subscribing to webhooks or configuring templates easier.
* **Testing** – Control the results of your integration directly from your Sandbox Dashboard.
* **Company account management** – Manage your own accounts in the Treezor ecosystem (keep track of operations, initiate transfers to your bank accounts, etc.).
The complete list of actions you can do from the Dashboard is available in the [Dashboard User Roles](./dashboard-users#dashboard-user-roles) article.
## Accessing your Dashboard
If you’ve opted for this option when starting to work with Treezor services, you have a Dashboard for each of your [environments](/guide/api-basics/environments) shared with you by your *Treezor Implementation Manager*:
* **Sandbox** – `https://dashboard-{yourCompanyName}.sandbox.treezor.co`
* **Production** – `https://dashboard.{yourCompanyName}.api.treezor.co`
There are two ways to log in to the Dashboard for you and your teams:
| Method | Description |
|---|---|
| [**Standard with 2FA**](#standard-login-with-2fa) | You and your team log in with a username and password. Once this done, the user also goes through 2-factor authentication (2FA). |
| [**SSO Identity Provider**](#company-sso-login) | If your company has a single authentication solution for multiple applications, you can configure your Dashboard to authenticate your users with it. |
**Best practice – Always use your individual account**
Treezor has provided you with a technical account in the early steps of your journey. This account is to be used as a backup account only.
### Standard login with 2FA
When logging in with Treezor, 2-Factor Authentication (2FA) is mandatory for security reasons.
With 2FA, Dashboard Users enter:
* Their username and password
* A second authentication factor (biometric or PIN/password).
This technology relies on a pair of cryptographic keys: a private key stored on a trusted device and a public key registered on our servers.
It makes sharing accounts impossible, and only one device for a given account can hold the passkey for the second factor.
#### Configuring Dashboard 2FA
Available options for 2FA depend on the configuration, device, and browser, and can be:
* Internal device (the one the Dashboard User uses to access the Dashboard)
* External device (phone, tablet, security key)
* All types of devices
If needed, your *Treezor Implementation Manager* will help you configure the authentication to fit your work environment.
#### Logging in with 2FA
When prompted, Dashboard Users set up and provide a second authentication factor, which can be biometric (fingerprint, facial recognition) or a personal PIN/password.
After entering their username and password for the first time, they must click on “Enable 2-Factor Authentication” to set up their passkey.
From there, they follow the browser prompts to select their authenticator of choice based on your Dashboard configuration.
Once the relevant option is selected, they can name their passkey for convenience purposes, and get back to log in.
After this initial setup, the passkey is required every time the user logs in (or if the session exceeds 12 hours).
**Tip – Managing 2FA accesses**
* Dashboard Users can edit their password by accessing the [Account page](#get-to-know-the-dashboard-interface).
* [Managers](./dashboard-users#dashboard-user-roles) can reset the users 2FA in the [Dashboard Users view](./dashboard-users).
### Company SSO login
You can also use your company Single Sign-On (SSO) solution to log in to the Dashboard seamlessly.
#### Configuring your SSO
You need to contact Treezor to configure your SSO. Your *Treezor Implementation Manager* will ask for your SAML app configuration file (see [Google documentation](https://support.google.com/a/answer/6087519?hl=en) for example).
Then, you can define a SAML key when creating your [Dashboard Users](/guide/dashboard/dashboard-users#dashboard-users). The SAML key links automatically a Dashboard User to a Dashboard OAuth2 client.
#### Logging in with SSO
Once the setup done, this is a straightforward experience for your Dashboard Users.
## Get to know the Dashboard Interface
Let’s take a quick guided tour of the key components of the Dashboard interface.
| # | Section | Description |
| :---: | --- | --- |
| | Navigation menu | Located on the left-hand side, this foldable menu allows you to navigate to the different views:*Dashboard* views, which focus on the features.*Configuration* views, which are about setting up your Dashboard. |
| | Main toolbar | In the upper part of each view, the Main toolbar contains the search field, the list of favorites, the language selection, and the account drop-down, for you to log out or access your *Account* page. |
| | Main view | Main content, which depends on the selected view. By default, the *Users* view is displayed. |
| | Environment | In the bottom left corner, you’ll find information about your environment and the version of the Dashboard. |
**Note – Your Dashboard is customizable**
The views may differ from the screenshots displayed depending on:
* Where you’re at in your integration process, if you’re customizing the design
* The User Role of the logged-in user, if you’re not using all of Treezor features
* Your localization and language selection
---
---
url: /guide/transfers/introduction.md
description: >-
Get a foundational understanding of Treezor payins and payouts, whether they
are wallet transfers, SEPA Direct Debits, SEPA Credit Transfers, or
International Transfers.
---
# Introduction
A bank transfer is the movement of funds from one account to another.
Therefore, for a given Treezor environment, any funds movement listed below is considered a transfer:
| From | To | Object |
| --- | --- | --- |
| Wallet | External account | Payout |
| External account | Wallet | Payin |
| Wallet | Wallet (same environment) | Transfer |
## Type of transfers
Treezor provides a variety of transfer options to meet different needs:
* [SEPA Credit Transfers](/guide/transfers/credit-transfer)
* [SEPA Instant Payments](/guide/transfers/credit-transfer-inst)
* [SEPA Direct Debit](/guide/transfers/direct-debit)
* [International Transfers](./international)
* [Wallet-to-Wallet](/guide/transfers/wallet-to-wallet)
The prerequisites and processing differ for each type of transfer depending on the direction of the funds, the service used, and the initiator.
Contact Treezor to learn which types of transfers best fit your needs among the following:
| Transfer | Type | Initiator | Coverage |
|------------------------------|--------|----------------------------|-----------------------|
| [Emitted SEPA Direct Debit](/guide/transfers/direct-debit#emitted-direct-debits-sdde) | Payin | Treezor User (recipient) | SEPA |
| [Received SEPA Direct Debit](/guide/transfers/direct-debit#received-direct-debits-sddr) | Payout | External account owner | SEPA |
| [Emitted SEPA Credit Transfer](/guide/transfers/credit-transfer#emitted-credit-transfers-scte) | Payout | Treezor User (sender) | SEPA |
| [Received SEPA Credit Transfer](/guide/transfers/credit-transfer#received-credit-transfers-sctr) | Payin | External account owner | SEPA |
| [Emitted Instant Credit Transfers](/guide/transfers/credit-transfer-inst#emitted-instant-credit-transfers-scte-inst) | Payout | Treezor User (sender) | SEPA |
| [Received Instant Credit Transfers](/guide/transfers/credit-transfer-inst#received-instant-credit-transfers-sctr-inst) | Payin | External account owner | SEPA |
Additional services such as [Scheduled payments](scheduled-payments) may be of interest as well.
## Statuses
### Payin statuses (`codeStatus`)
| `codeStatus` | | `payinStatus` | Description |
|:---: | :---: | --- |--- |
| `140001` | | `PENDING` | Pending payment (during SDDE/SCTR payin creation) |
| `140004` | | `CANCELED` | For SDDE, this status indicates either that the [ARA](/guide/overview/glossary#ara) is rejected or that you have canceled the payin. For SCTR, this status indicates the payin cannot be validated. |
| `140005` | | `VALIDATED` | For SDDE, this status indicates the [ARA](/guide/overview/glossary#ara) is accepted. For SCTR, indicates the transaction is processed. |
| `140006` | | `PENDING` | Pending non-repudiation |
| `140007` | | `PENDING` | Fraud suspicion (AML/CFT). Don't communicate this information with your end users. |
| `140010` | | `CANCELED` | SEPA Transfer refused |
### Payout statuses (`codeStatus`)
| `codeStatus` | | `payoutStatus` | Description |
|:---: |:---: | --- |--- |
| `160001` | | `PENDING` | Refund request populated |
| `160002` | | `PENDING` | Refund request received by mail |
| `160003` | | `VALIDATED` | Internaly validated |
| `160004` | | `VALIDATED` | Transfer request sent to bank |
| `160005` | | `VALIDATED` | Refund transfer validated |
| `160006` | | `CANCELED` | Canceled by the User |
| `160007` | | `PENDING` | Bank account in error during the first transfert or debit |
| `160008` | | `PENDING` | Fraud suspicion or AML/CFT |
| `160009` | | `CANCELED` | Canceled by operator |
| `160010` | | `CANCELED` | Insufficient Authorized Balance when the operation was presented |
| `160011` | | `PENDING` | Outgoing funds pending validation due to Beneficiary being in a non-[FATF](https://www.fatf-gafi.org) country |
| `160012` | | `PENDING` | Outgoing funds pending validation due to amount exceeding €10,000 |
| `160013` | | `PENDING` | Outgoing funds pending validation due poor scoring of the operation |
| `160014` | | `PENDING` | Outgoing funds sent to recipient's institution, pending acknowledgment |
| `160015` | | `PENDING` | Outgoing funds suspended by operator |
### Payout Refund statuses (`codeStatus`)
| `codeStatus` | | `payoutStatus` | Description |
|:---: |:---: | --- |--- |
| `790001` | | `PENDING` | Message of refund has been sent to Scheme. Wait for confirmation. |
| `790002` | | `CANCELED` | Canceled by the Scheme (Treezor received a negative answer) |
| `790003` | | `VALIDATED` | Validated |
| `790004` | | `PENDING_NO_RESPONSE` | No response received in legal delay |
### Transfer statuses (`codeStatus`)
| `codeStatus` | | `transferStatus` | Description |
|:---: |:---: | --- |--- |
| `150001` | | `PENDING` | Transfer has been initiated. |
| `150002` | | `PENDING` | Fraud suspicion, you can't expose this information to your end users. |
| `150003` | | `CANCELED` | Canceled by the end user. |
| `150004` | | `CANCELED` | Canceled by the operator. |
| `150005` | | `VALIDATED` | Validated |
| `150006` | | `CANCELED` | Transfer canceled due to lack of funds from the debited Wallet Authorized Balance. |
## Endpoints
### Payins
| Endpoint |[Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/v1/payins`](/api-reference/api-endpoints.html#tag/Payins/postPayin){target="\_self"} Create a Payin | `read_write` |
| [`/v1/payins`](/api-reference/api-endpoints.html#tag/Payins/getPayins){target="\_self"} Search Payins | `read_only` |
| [`/v1/payins/{payinId}`](/api-reference/api-endpoints.html#tag/Payins/getPayin){target="\_self"} Retrieve a Payin using its `id` | `read_only` |
| [`/v1/payinrefunds`](/api-reference/api-endpoints.html#tag/Payin%20Refunds/getPayinrefunds){target="\_self"} Search Payin Refunds | `read_only` |
| [`/v1/payinrefunds/{id}`](/api-reference/api-endpoints.html#tag/Payin%20Refunds/getPayinrefund){target="\_self"} Retrieve a Payin Refund using its `id` | `read_only` |
### Payouts
| Endpoint |[Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/v1/payouts`](/api-reference/api-endpoints.html#tag/Payouts/postPayout){target="\_self"} Create a Payout | `read_write` |
| [`/v1/payouts`](/api-reference/api-endpoints.html#tag/Payouts/getPayouts){target="\_self"} Search Payouts | `read_only` |
| [`/v1/payouts/{payoutId}`](/api-reference/api-endpoints.html#tag/Payouts/getPayout){target="\_self"} Retrieve a Payout using its `id` | `read_only` |
| [`/v1/payouts/{payoutId}`](/api-reference/api-endpoints.html#tag/Payouts/deletePayout){target="\_self"} Cancel a Payout| `read_write` |
| [`/core-connect/payouts/{payoutId}/proof`](/api-reference/api-endpoints.html#tag/Payouts/getProofPayout){target="\_self"} Create a Payout Proof| `read_only` |
| [`/v1/payoutRefunds`](/api-reference/api-endpoints.html#tag/Payout%20Refunds/postPayoutRefund){target="\_self"} Create a Payout Refund | `read_write` |
| [`/v1/payoutRefunds/{payoutRefundId}`](/api-reference/api-endpoints.html#tag/Payout%20Refunds/getPayoutRefund){target="\_self"} Retrieve a Payout Refund based on its `id` | `read_only` |
### Recalls & RROs
| Endpoint |[Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/v1/recallRs`](/api-reference/api-endpoints.html#tag/Recalls/getRecalls){target="\_self"} Search for SCT Recalls | `read_only` |
| [`/v1/recallRs/{recallRId}`](/api-reference/api-endpoints.html#tag/Recalls/getRecallR){target="\_self"} Retrieve an SCT Recall or RRO by its `id` | `read_only` |
| [`/v1/recallRs/{recallRId}/response/`](/api-reference/api-endpoints.html#tag/Recalls/putRecallR){target="\_self"} Provide your decision following an SCT Recall request | `read_write` |
| [`/v1/recall-sct-inst/{sctInstId}/{recallId}`](/api-reference/api-endpoints.html#tag/Recalls/getRecallSctInst){target="\_self"} Retrieve an SCT Inst Recall | |
| [`/v1/recall-sct-inst/{sctinstId}/{recallId}/response`](/api-reference/api-endpoints.html#tag/Recalls/putRecallSctInst){target="\_self"} Provide your decision following an SCT Inst Recall | |
| [`/v1/payinrefunds/{recallId}`](/api-reference/api-endpoints.html#/) Retrieve a payinrefund following a Recall | |
| [`/v1/payoutRefunds`](/api-reference/api-endpoints.html#tag/Payout%20Refunds/postPayoutRefund){target="\_self"} Create a Recall (SCTE Inst only) | `read_write` |
| [`/v1/payoutRefunds/{payoutRefundId}`](/api-reference/api-endpoints.html#tag/Payout%20Refunds/getPayoutRefund){target="\_self"} Create a Recall (SCTE Inst only) | `read_only` |
| [`/simulation/sct-inst/payin`](/api-reference/api-endpoints.html#tag/Simulation/simulateSctInstReception){target="\_self"} Emulate an SCTR, to test the procedure | |
| [`/simulation/sct-inst/recall`](/api-reference/api-endpoints.html#tag/Simulation/simulateSctInstRecall){target="\_self"} Emulate a reception of a SCTR inst recall, to test the procedure | |
| [`/simulation/recall-r`](/api-reference/api-endpoints.html#/) Emulate a Recallr, to test the procedure | |
### Transfers
| Endpoint |[Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/v1/transfer`](/api-reference/api-endpoints.html#tag/Transfers/postTransfers){target="\_self"} Create a Transfers | `read_write` |
| [`/v1/transfers`](/api-reference/api-endpoints.html#tag/Transfers/getTransfers){target="\_self"} Search Transfers | `read_only` |
| [`/v1/transfers/{transferId}`](/api-reference/api-endpoints.html#tag/Transfers/getTransfer){target="\_self"} Retrieve a Transfer using its `id` | `read_only` |
| [`/v1/transfers/{transferId}`](/api-reference/api-endpoints.html#tag/Transfers/deleteTransfer){target="\_self"} Delete a Transfer using its `id`| `read_write` |
### Beneficiaries
| Endpoint | [Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/v1/beneficiaries`](/api-reference/api-endpoints.html#tag/Beneficiaries/postBeneficiary){target="\_self"} Create a Beneficiary | `read_write` |
| [`/v1/beneficiaries`](/api-reference/api-endpoints.html#tag/Beneficiaries/getBeneficiaries){target="\_self"} Search for Beneficiaries | `read_only` |
| [`/v1/beneficiaries/{beneficiaryId}`](/api-reference/api-endpoints.html#tag/Beneficiaries/getBeneficiary){target="\_self"} Retrieve a Beneficiary | `read_only` |
| [`/v1/beneficiaries/{beneficiaryId}`](/api-reference/api-endpoints.html#tag/Beneficiaries/putBeneficiary){target="\_self"} Update a Beneficiary | `read_write` |
### Mandates
| Endpoint | [Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/v1/mandates`](/api-reference/api-endpoints.html#tag/Mandates/postMandates){target="\_self"} Create a mandate | `read_write` |
| [`/v1/mandates`](/api-reference/api-endpoints.html#tag/Mandates/getMandates){target="\_self"} Search for mandates | `read_only` |
| [`/v1/mandates/{mandateId}`](/api-reference/api-endpoints.html#tag/Mandates/getMandate){target="\_self"} Retrieve a mandate | `read_only` |
| [`/v1/mandates/{mandateId}`](/api-reference/api-endpoints.html#tag/Mandates/deleteMandate){target="\_self"} Revoke a mandate | `read_write` |
---
---
url: /guide/use-cases/prerequisites/introduction.md
description: >-
Explore Treezor's Use Cases section. This introduction sets the context for
integrating common business models via step by step (API and no-code) guides,
outlining key requirements such as KYC and Strong Customer Authentication
(SCA).
---
# Introduction
The Use Cases section of the documentation provides implementation step-by-step guides (either no-code or API) to help users through the integration of common use cases without in-depth support from you *Treezor Implementation Manager*.
Nevertheless, you are still required to abide by the following:
* **KYC Form** – Treezor provided you a KYC Form listing the documents and declarative data you must provide for each type of user.
* **Implementation best practices** – Treezor will validate your implementation to make sure you abide by regulations and requirements.
You should only go through those guides if you've been oriented to them by Treezor.
## About Strong Customer Authentication
Usually, Treezor won't request you implement strong customer authentication for use cases. However, your local regulator (e.g., la Banque de France for French companies) may require you declare sensitive end users' actions.
In the use case articles, actions to declare are flagged with the badges. You may use either Treezor SCA endpoints or your own solution to implement SCA.
Learn more in the [Strong Customer Authentication (SCA)](/guide/strong-customer-authentication/introduction) documentation.
---
---
url: /guide/user-verification/introduction.md
description: >-
Get a foundational understanding of your legal obligation to verify your end
users identity to present the misuse of the financial system for illegitimate
purposes. Includes an overview of the KYC / KYB process and life cycle.
---
# Introduction
Treezor is legally obligated to verify the identity of the users using its services, whether it's you as a company or your end users.
The obligations placed on banking services providers aim to prevent the misuse of the financial system for illegitimate purposes, as stated by the [anti-money laundering and countering the financing of terrorism (AML/CFT)](/guide/overview/glossary#anti-money-laundering-and-countering-the-financing-of-terrorism-aml-cft) rules.
In this context, Treezor collaborates closely with regulating institutions through reporting and monitoring, and any other measure that aims to provide a compliant and secure banking ecosystem.
Once your project is approved and you start using your `Production` environment, you must abide by the same rules and regulations.
## KYC / KYB
The terms Know Your Customer (KYC) and Know Your Business (KYB) refer to the verification of a user, whether they are a legal entity or an individual.
For Treezor to make sure users are who they say they are, you need to provide:
* **Declarative data** – Regarding the user, such as their name, address, etc.
* **Documents** – Proving the user or entity identity (IDs, company registration, proof of address, etc.)
The KYC / KYB of a user is not a one-time check. In addition to the initial check done during the end user onboarding, multiple reviews are made along the user life cycle.
The requirements to verify a user identity vary depending on factors such as:
* The type of services you provide
* The country you’re operating in
* The type of users to be verified
Some additional vigilance measures are required, such as a SEPA Transfer to a Wallet from the user to be verified or a certified video process.
Treezor provides you with a *KYC Form* upon starting your project. It indicates everything you need to provide for user verification.
## Process
Below is a high-level example of the KYC process for end user onboarding:
The key steps are the following:
1. You collect the necessary data based on your *KYC Form* (declarative data, [documents](./documents), [tax residence](/guide/users/tax-residence)).
2. You pre-review the documents to ensure proper quality before [requesting a KYC review](./kyc-request).
3. Treezor [manually verifies the user's identity](https://treezor.zendesk.com/hc/en-us/articles/360010167539-KYC) and decides whether they are eligible to use Treezor services.
**Best practice – Make sure you provide data of quality**
Bad data quality may result in unnecessary back-and-forth with Treezor. The more accurate and vigilant you are when providing the necessary data when requesting a KYC / KYB review, the smoother the end user experience.
### Provide user declarative data
User key information to provide (based on your KYC Form) is to be populated through the following objects:
* [Users](/guide/users/introduction) – Create or update your user with the relevant attributes
* [Tax Residence](/guide/users/tax-residence) – Declare the country of tax residency with a specific object (and add it to the corresponding User object)
### Provide documents
Treezor offers 2 ways for end users to upload documents:
* [To the Treezor API (with pre-review)](./documents-prereview)
* [From your application to the Treezor API](./documents)
The processes differ depending on the option you implement. Only once all the documents are properly updated can the KYC review by Treezor be requested. Learn more in the [Documents](./documents) section.
### Verification solutions
Treezor relies on several verification solutions to ease the physical user verification process. The solutions available to you depend on the type of user and the [distribution country](/guide/users/introduction#distribution-country-distributioncountry).
| Verification solution | Description |
| --- | --- |
| [Liveness](/guide/user-verification/live-verification) | Live verification which requires a video of the end user, their identity proof, and a SEPA transfer into their Treezor Wallet as an extra validation step. |
| [Certified video (PVID)](/guide/user-verification/live-verification) | Live verification which requires a video of the end user and their identity proof, with challenges for the user to complete. PVID is ANSSI-certified. |
| [Qualified eSignature (QES)](/guide/user-verification/qes) | Electronic signature verified with a selfie. It ensures the signer identification, protects the signature, and provides a certificate from a certified provider. |
| [Video conference](/guide/user-verification/videoconf) | Feature that verifies the user through an online video call with an expert who reviews the ID and asks questions to ensure the user is who they claim to be. |
Using a verification solution may still require you to collect documents and implement additional vigilance measures. Make sure you rely on the information provided by Treezor Compliance.
#### Solution availability by `distributionCountry`
| | End user | Children (-18) | Legal Rep. | Shareholder |
| --- | :---: | :---: | :---: | :---: |
| **Liveness** [+ SEPA Transfer](#additional-vigilance-measures) | | | | |
| **PVID** | | | | |
| **QES** | | | | |
| **Video conf.** | | | | |
| **Documents** | | | | |
| | End user | Children (-18) | Legal Rep. | Shareholder |
| --- | :---: | :---: | :---: | :---: |
| **Liveness** | | | | |
| **PVID** | | | | |
| **QES** [+ SEPA Transfer](#additional-vigilance-measures) | | | | |
| **Video conf.** | | | | |
| **Documents** | | | | |
| | End user | Children (-18) | Legal Rep. | Shareholder |
| --- | :---: | :---: | :---: | :---: |
| **Liveness** [+ SEPA Transfer](#additional-vigilance-measures) | | | | |
| **PVID** | | | | |
| **QES** | | | | |
| **Video conf.** | | | | |
| **Documents** | | | | |
### Additional vigilance measures
Your *KYC Form* may indicate a [SEPA Transfer](/guide/transfers/introduction#key-words) as an additional vigilance measure, allowing Treezor to know that the User has already passed a verification process with a credit institution located in the European Economic Area (EEA).
This step consists of Users wiring money from their existing bank account to their new Treezor Wallet, and takes place between the upload of all the Documents and the request for a KYC review.
The User can wire money to their [Wallet](/guide/wallets/introduction) via its [IBAN](/guide/wallets/iban) using one of the following methods:
* [SCTR](/guide/transfers/credit-transfer#received-credit-transfers-sctr)
* [SCTR Inst](/guide/transfers/credit-transfer-inst#received-instant-credit-transfers-sctr-inst)
**Prerequisites – In order to make the initial transfer, the User must be created and**
* Must have [Wallet](/guide/wallets/introduction)
* Must have uploaded all their [Documents](/guide/user-verification/documents)
This money wiring will send you a [`payin.create`](/guide/transfers/events#payin-create) webhook.
You must then wait for this Payin status (`payinStatus`) to be `VALIDATED` before [requesting a KYC review](/guide/user-verification/kyc-request).
**The validation of the Payin confirms that this measure was passed.**
Depending on the type of transfer, the validation of the Payin may be provided immediately upon creation of the Payin, or via the [`payin.update`](/guide/transfers/events#payin-update) webhook within a few days.
**Information – Transfer must be refunded if the User is not KYC-validated**
You will need to get in touch with your *Treezor Account Manager* before being able to send a [payinrefund](/guide/transfers/events#payinrefund-create).
## User KYC Levels (`kycLevel`)
The `kycLevel` represents our confidence in the assigned KYC Review status.
| Value | Plaintext | Description |
| :---: | --- | --- |
| `0` | `NONE` | **No review** occurred yet for this User. |
| `1` | `LIGHT` | User has been accepted or refused for light reasons (invalidating this status is possible with new documents). |
| `2` | `REGULAR` | The User is KYC-validated. |
| `3` | `STRONG` | The User is KYC-validated. |
| `4` | `REFUSED` | **Permanent refusal**, further reviews will be denied. |
Services availability for the User differ depending on their KYC Level.
| Service | `NONE` | `LIGHT` | `REGULAR` | `REFUSED` |
| --- | :---: | :---: | :---: | :---: |
| [Create Cards](/guide/cards/creation) | | | | |
| [Pay by Card](/guide/cards/transactions) | | | | |
| [Send funds](/guide/transfers/introduction) | | | | |
| [Receive funds](/guide/wallets/introduction#how-to-credit-wallets-top-up) | | | | |
| [Request another KYC review](/guide/user-verification/kyc-request) | | | | |
Services may also be unavailable due to Wallet specificities (i.e., [Electronic Money Limits](/guide/wallets/introduction#electronic-money-limits)).
**Caution – When the User KYC level is `LIGHT`:**
* It is your responsibility to [lock the User's Cards](/guide/cards/modification#block-a-card)
* Payouts are enabled only to allow the User to retrieve their funds before definitely closing their Wallet.
## User KYC Review status (`kycReview`)
The `kycReview` represent the current status of the user review by Treezor. It's for information purposes only, this value doesn't impact the services available to the User.
| Value | Plaintext | Additional information|
| :---: | --- | --- |
| `0` | `NONE` | No review yet. |
| `1` | `PENDING` | Review in progress. |
| `2` | `VALIDATED` | Review is done and the user is KYC-validated. |
| `3` | `REFUSED` | Review is done and the user is refused. |
| `4` | `INVESTIGATING` | |
| `5` | `CLOSED` | |
| `6` | `REVIEW_OPEN` | |
| `7` | `REVIEW_PENDING` | |
**Note – [Each document receives its own review status](/guide/user-verification/documents#status-documentstatus)**
The User's review status is automatically deduced from all the documents individual review status.
## KYC Life cycle
All Users start their KYC journey with [kycLevel](#user-s-kyc-levels-kyclevel) `0` (`NONE`) and [kycReview](#user-s-kyc-review-status-kycreview) `0` (`NONE`).
The most common scenario and life cycles are described below.
### Straightforward validation
In this ideal process, the user produces decent quality and valid documents right away and doesn't exhibit counter indications to having a wallet.
| # | Description | `user.kycLevel` | `user.kycReview` |
|- |- |- |- |
| 0 | Initial state | `0` None | `0` None |
| 1 | User uploads all documents | `0` None | `0` None |
| 2 | You request a KYC Review | `0` None | `1` **Pending** |
| 3 | Treezor approves all documents | `2` **Regular** | `2` **Validated** |
**Note – A validated Document cannot be replaced**
If the user wishes to replace it, a new [Document](documents) object has to be created, and a new [KYC Review request](./kyc-request) has to be sent.
### Non-compliant documents
The user uploads all documents (1) but one is expired or non-acceptable (3). The user loops back to the upload step (4) and provides an acceptable document that is validated by Treezor (5).
| # | Description | `user.kycLevel` | `user.kycReview` |
|- |- |- |- |
| 0 | Initial state | `0` None | `0` None |
| 1 | User uploads all documents | `0` None | `0` None |
| 2 | You request a KYC Review | `0` None | `1` **Pending** |
| 3 | Treezor rejects at least one document | `1`, `2` or `3` **Light**, **Regular** or **Strong** | `3` **Refused** |
| 4 | User uploads new documents | `1`, `2` or `3` Light, Regular or Strong | `3` Refused |
| 5 | You request a KYC Review | `0` **None** | `1` **Pending** |
| 6 | Treezor approves all documents | `2` **Regular** | `2` **Validated** |
**Note – A refused Document cannot be replaced**
If the user wishes to replace it, a new [Document](documents) object has to be created, and a new [KYC Review request](./kyc-request) has to be sent.
### Permanent refusal
The user uploads all documents (1), but analysis of the provided documents concluded that this user is not permitted to use Treezor's services (3).
This is a **definitive refusal**, all subsequent document uploads will be refused.
| # | Description | `user.kycLevel` | `user.kycReview` |
|- |- |- |- |
| 0 | Initial state | `0` None | `0` None |
| 1 | User uploads all documents | `0` None | `0` None |
| 2 | You request a KYC Review | `0` None | `1` **Pending** |
| 3 | Treezor refuses the User | `4` **Refused** | `3` **Refused** |
### Modifying a non-validated user
The user has uploaded documents but is not yet validated.
| # | Description | `user.kycLevel` | `user.kycReview` |
|- |- |- |- |
| 0 | Initial state | `0` None | `0` None |
| 1 | User uploads all documents | `0` None | `0` None |
| 2 | User cancels a document | `0` None | `0` None |
| 3 | User uploads a new document | `0` None | `0` None |
| 4 | You request a KYC Review | `0` None | `1` **Pending** |
| 5 | Treezor approves all documents | `2` **Regular** | `2` **Validated** |
### Modifying an already validated user
The user has been validated previously, and decides to upload new documents.
During the upload of new documents, the user can still access his/her account.
| # | Description | `user.kycLevel` | `user.kycReview` |
|- |- |- |- |
| 0 | Already validated user | `2` **Regular** | `2` **Validated** |
| 1 | User uploads new documents | `2` Regular | `2` Validated |
| 2 | You request a KYC Review | `2` Regular | `1` **Pending** |
| 3 | Treezor approves the new documents | `2` Regular | `2` **Validated** |
### Straightforward (live verification)
In this ideal process, the user goes into Live verification, and produces acceptable documents right away.
| # | Description | `user.kycLevel` | `user.kycReview` | `kycliveness.kyc-status` |
|- |- |- |- |- |
| 0 | Initial state | `0` None | `0` None | |
| 1 | You request a live verification | `0` None | `0` None | **`initiated`** |
| 2 | Treezor provides the verification URL | `0` None | `0` None | `initiated` |
| 3 | You redirect the end user to the verification URL | `0` None | `0` None | `initiated` |
| 4 | The end user is guided into uploading the documents | `0` None | `0` None | `initiated` |
| 5 | Treezor sends a `kycliveness.create` webhook | `0` None | `0` None | **`processing`** |
| 6 | Treezor sends a `kycliveness.update` webhook | `0` None | `0` None | **`processed`** |
| 7 | You request a KYC Review | `0` None | `1` **Pending** | `processed` |
| 8 | Treezor sends `document.create` webhooks | `0` None | `1` Pending | `processed` |
| 9 | Treezor approves the documents | `2` **Regular** | `2` **Validated** | `processed` |
### Non-compliant documents (live verification)
The user completes the Live verification process, but some documents are non-compliant. The user is refused by Treezor live verification provider.
| # | Description | `user.kycLevel` | `user.kycReview` | `kycliveness.kyc-status` |
|- |- |- |- |- |
| 0 | Initial state | `0` None | `0` None | |
| 1 | You request a live verification | `0` None | `0` None | **`initiated`** |
| 2 | Treezor provides the verification URL | `0` None | `0` None | `initiated` |
| 3 | You redirect the end user to the verification URL | `0` None | `0` None | `initiated` |
| 4 | The end user is guided into uploading the documents | `0` None | `0` None | `initiated` |
| 5 | Treezor sends a `kycliveness.create` webhook | `0` None | `0` None | **`processing`** |
| 6 | Treezor sends a `kycliveness.update` webhook | `0` None | `0` None | **`processed`** |
### Compliant documents but refused User (live verification)
The user completes the Live verification process and provides compliant documents. Nonetheless, Treezor refuses the User.
| # | Description | `user.kycLevel` | `user.kycReview` | `kycliveness.kyc-status` |
|- |- |- |- |- |
| 0 | Initial state | `0` None | `0` None | |
| 1 | You request a live verification | `0` None | `0` None | **`initiated`** |
| 2 | Treezor provides the verification URL | `0` None | `0` None | `initiated` |
| 3 | You redirect the end user to the verification URL | `0` None | `0` None | `initiated` |
| 4 | The end user is guided into uploading the documents | `0` None | `0` None | `initiated` |
| 5 | Treezor sends a `kycliveness.create` webhook | `0` None | `0` None | **`processing`** |
| 6 | Treezor sends a `kycliveness.update` webhook | `0` None | `0` None | **`processed`** |
| 7 | You request a KYC Review | `0` None | `1` **Pending** | `processed` |
| 8 | Treezor sends `document.create` webhooks | `0` None | `1` **Pending** | `processed` |
| 9 | Treezor refuses the documents | `1` **Light** | `3` **Refused** | `processed` |
## Endpoints
| Endpoint | [Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/v1/documents`](/api-reference/api-endpoints.html#tag/User%20Documents/createDocuments){target="\_self"} Create a document | `read_write` |
| [`/v1/users/{userId}/kycliveness`](/api-reference/api-endpoints.html#tag/User%20Live%20Verification/postKycliveness){target="\_self"} Initiate the user [Live verification](/guide/user-verification/introduction) process | `read_write` |
| [`/v1/documents`](/api-reference/api-endpoints.html#tag/User%20Documents/getDocuments){target="\_self"} Search for documents | `read_only` |
| [`/v1/documents/{documentId}`](/api-reference/api-endpoints.html#tag/User%20Documents/getDocument){target="\_self"} Retrieve a specific document based on its `id` | `read_only` |
| [`/v1/documents/{documentId}/download`](/api-reference/api-endpoints.html#tag/User%20Documents/getDocumentDownloadUrl){target="\_self"} Retrieve a document download URL | `read_only` |
| [`/v1/users/{userId}/Kycreview`](/api-reference/api-endpoints.html#tag/User%20KYC%20Review/putKycreview){target="\_self"} Initiate the user [KYC review](/guide/user-verification/introduction) process | `read_write` |
| [`/v1/documents/{documentId}`](/api-reference/api-endpoints.html#tag/User%20Documents/putDocument){target="\_self"} Update a document `name` | `read_write` |
| [`/v1/users/{userId}/kycliveness`](/api-reference/api-endpoints.html#tag/User%20Live%20Verification/put-kyc-liveness){target="\_self"} Upload the documents once the Live verification is completed. | `read_write` |
| [`/v1/documents/{documentId}`](/api-reference/api-endpoints.html#tag/User%20Documents/deleteDocument){target="\_self"} Delete a document | `read_write` |
---
---
url: /guide/users/introduction.md
description: >-
Get a foundational understanding of Treezor physical users and legal entities,
and their compatible functionalities. Includes key attributes, JSON structure,
and related endpoints list.
---
# Introduction
Users typically refer to your customers, also known as end users. They can be:
* [Physical Users](/guide/users/physical), representing an actual human being.
* [Legal Entities](/guide/users/legal-entity), representing a company, association, etc.
* [Anonymous](/guide/users/physical#anonymous-users), which are users with close to no declarative data, intended for specific and limited use cases.
Users can also have hierarchical [parent-children relations](/guide/users/parent-children) between them.
## Key attributes
Below are some of the most important User attributes.
| Attribute | Type | Description |
|--- |--- |--- |
| `email` | string | The [unique and valid email address](#using-unique-and-valid-email-addresses) of the user. |
| `specifiedUSPerson` | integer | Indicates if the user is a [US Person](/guide/users/tax-residence). |
| `userTypeId` | integer | The type of user. See the [list of user types](#types-usertypeid). |
| `kycLevel` | integer | The current level of KYC validation. See the [verification](/guide/user-verification/introduction#user-kyc-levels-kyclevel) section for more information. |
| `kycReview` | integer | The current status of the KYC validation. See [list of statuses](/guide/user-verification/introduction#user-kyc-review-status-kycreview) in the verification section. |
| `kycComment` | string | The comment set by Treezor upon [KYC review](/guide/user-verification/introduction). It concatenates information for each KYC Review update, with the date, the `kycReview` and `kycLevel` values, and the comment from Treezor. |
| `userStatus` | string | The user status. Can be one of the following values:`PENDING` – User is being created.`VALIDATED` – User is active.`CANCELED` – User is [deleted](/guide/users/modifications#deletion). |
| `employeeType` | integer | The kind of employment relation between the user and the company in the context of [parent-children relations](./parent-children). |
| `controllingPersonType` | integer | The type of relation between the user and the legal entity in the context of [parent-children relations](./parent-children). |
| `parentType` | string | The kind of relationship in the context of [parent-children relations](./parent-children). |
| `parentUserId` | integer | The parent user to which the current user is linked, in the context of [parent-children relations](./parent-children). |
| `title` | string | The title of the user (also [used when sending physical cards](/guide/cards/creation#physical-card-creation)). Can be one of the following: `M` – Stands for mister (Mr.)`MME` – Stands for missus (Mrs.)`MLLE` – Stands for miss`MX` – Gender-neutral title |
| `firstname` | string | The first name of the Physical User (also [used when sending physical cards](/guide/cards/creation#physical-card-creation)). |
| `lastname` | string | The last name of the Physical User (also [used when sending physical cards](/guide/cards/creation#physical-card-creation)). |
| `middleNames` | string | The middle names of the Physical User, if any. |
| `address{1-3}` | string | Postal address of the user (also [used when sending physical cards](/guide/cards/creation#physical-card-creation); see [limitations regarding address fields length](/guide/api-basics/data-format#addresses)). |\
| `postcode` | string | Postcode of the user (also [used when sending physical cards](/guide/cards/creation#physical-card-creation)). |
| `city` | string | The user's address city (also [used when sending physical cards](/guide/cards/creation#physical-card-creation)). |
| `state` | string | The user's address state, if any (may also be [used when sending physical cards](/guide/cards/creation#physical-card-creation)). |
| `country` | string | The residence country of the user in the ISO 3166-1 alpha-2 format (also [used when sending physical cards](/guide/cards/creation#physical-card-creation)). |
| `position` | string | Only for NGOs, indicating their geographic activity coverage. |
| `legal{Name/Form/...}` | string | Used to describe [Legal Entities](/guide/users/legal-entity). |
| `birthday` | string | The date of birth of the Physical User in the `YYYY-MM-DD` format. |\
| `occupationCategory` | string | Type of occupation of the physical user. See [occupation category](./physical#occupation-category-occupationcategory) for the list of values. |
| `timezone` | string | The local timezone of the user [in tz database format `Area/Location`](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) (e.g., `America/New_York`, `Europe/Paris`). |
| `language` | string | The preferred language of the user (ISO 639-1). Conditions the language of the SMS sent for the [X-Pay](/guide/cards/x-pay-google-apple) feature. |
| `distributionCountry` | string | The country in which the end user is using your services. This field is only required when you operate in multiple countries. Otherwise, it either defaults to your country or is set to `null`. Please contact Treezor to configure this feature. Format: ISO 3166-1 alpha-2 format. |
**API – API Reference available**
For a complete list of User attributes, **including rules and character restrictions**, check the [Users](/api-reference/api-endpoints.html#tag/Users){target="\_self"} section of the API Reference.
### Types (`userTypeId`)
| `userTypeId` | User types |
| :---: | --- |
| `1` | [Physical User](/guide/users/physical) and [Anonymous User](/guide/users/physical#anonymous-users) |
| `2` | [Business User](/guide/users/legal-entity) |
| `3` | [Non-governmental organization](/guide/users/legal-entity) |
| `4` | [Governmental organization](/guide/users/legal-entity) |
**Reading – Special case of charity, clubs, and syndicates**
More information is available on Treezor Support Center regarding [charity, clubs, and syndicates](https://treezor.zendesk.com/hc/en-us/articles/360018874259-KYB-Associations).
### User Status (`codeStatus`)
Most user `codeStatus` values are deprecated, here are the ones you might encounter.
| | `codeStatus` | `userStatus` | Description |
| :---: | :---: | --- | --- |
| | `110012` | PENDING | Internal checks in progress. |
| | `110005` | CANCELED | User canceled by the end user. |
| | `110006` | CANCELED | User canceled by an operator. |
| | `110009` | VALIDATED | User is validated. |
### Using unique and valid email addresses
Email addresses must be unique, except for `CANCELED` users, which are not taken into account for email address checks.
During your [Sandbox](/guide/api-basics/environments) development phase, however, if you don't cancel users, we recommend that stakeholders (e.g., developers, QA testers) use their own email address with a random `+tag` suffixed to it.
For example, if your email address is `firstname.lastname@example.com`, you can use:
* `firstname.lastname+test1@example.com`
* `firstname.lastname+test2@example.com`
* `firstname.lastname+testn@example.com`
All of which are unique and valid addresses that automatically redirect emails to `firstname.lastname@example.com`.
Please note that the use of disposable email addresses or services is strongly discouraged and can be rejected by the Treezor API.
**Note – 50-character limit for X-Pay provisioning OTP method**
If you're using the [X-Pay](/guide/cards/x-pay-google-apple) feature, consider enforcing a < 50-character limit on user's email. Only emails complying with this limit are used for the X-Pay provisioning OTP method.
### Legal Forms (`legalForm`)
The `legalForm` indicates the legal category of the User.
It is required for the [KYC Review](/guide/user-verification/introduction) of any user with a professional activity:
* `userTypeId` of `2`, `3`, or `4`
* `userTypeId` of `1` with a `legalForm` set to `1000`, `10001`, `20001`, or `30001` (self-employed physical users)
You can use the [`/v1/businessinformations`](/api-reference/api-endpoints.html#tag/Businesses/getBusinessInfo){target="\_self"} request if you have any doubt regarding the `legalForm` of your User. An example is available in the [Finding the legal representatives](./legal-entity#finding-the-legal-representatives) section.
**Reading – The list of French Legal Forms available on the Insee website**
For the most up-to-date list, you can check out the [Insee website](https://www.insee.fr/fr/information/2028129).
Below is the list of `legalForm` values for users with a `distributionCountry` set to `IT`. These apply to users with a `userTypeId` of `2` except for the first one which is for [self-employed users](./physical#self-employed-users).
| Value | Description |
| :---: | --- |
| `10001` | Ditta individuale |
| `10002` | **S.S.** – Società semplice |
| `10003` | **S.N.C.** – Società in nome collettivo |
| `10004` | **S.A.S.** – Società in accomandita semplice |
| `10005` | **S.P.A.** – Società per azioni |
| `10006` | **S.A.P.A.** – Società in accomandita per azioni |
| `10007` | **S.R.L.** – Società a responsabilità limitata |
| `10008` | **S.R.L.S.** – Società a responsabilità limitata semplificata |
| `10009` | **COOP.** – Società cooperativa |
| `10010` | **E.P.E.** – Ente Pubblico Economico |
| `10011` | Associazione |
Below is the list of `legalForm` values for users with a `distributionCountry` set to `DE`. These apply to users with a `userTypeId` of `2` except for the first one which is for [self-employed users](./physical#self-employed-users).
| Value | Description |
| :---: | --- |
| `20001` | **Freiberufler** – Selbstständiger |
| `20002` | **GmbH** – Gesellschaft mit beschränkter Haftung |
| `20003` | **AG** – Aktiengesellschaft Kapitalgesellschaft |
| `20004` | **UG** – Unternehmergesellschaft (haftungsbeschränkt) |
| `20005` | **OHG** – Offene Handelsgesellschaft Personengesellschaft |
| `20006` | **KG** – Kommanditgesellschaft Personengesellschaft |
| `20007` | **GmbH & Co. KG** – GmbH & Co. Kommanditgesellschaft Mischform |
| `20008` | **e.K.** – Eingetragener Kaufmann Einzelunternehmen |
| `20009` | **eG** – Eingetragene Genossenschaft Zusammenschluss |
| `20010` | **PartG** – Partnerschaftsgesellschaft Personengesellschaft |
| `20011` | **KGaA** – Kommanditgesellschaft auf Aktien Mischform |
| `20012` | **Stiftung** – Stiftung Vermögensgebundene Organisation |
| `20013` | **e.V.** – Eingetragener Verein Nichtwirtschaftlicher |
| `20014` | **SCE** – Europäische Genossenschaft Genossenschaft |
| `20015` | **PartG mbB.** – Partnergesellschaft mit beschränkter Berufshaftung |
| `20016` | **jur. Person des öR** – juristische Personen des öffentlichen Rechts |
| `20017` | **WEG** – Wohnungseigentümergesellschaft |
| `20018` | **EU** – Einzelunternehmer (Gewerbetreibender) |
| `20019` | **GbR** – Gesellschaft bürgerlichen Rechts |
| `20020` | **SE** – Europäische Aktiengesellschaft (Societas Euro.) |
| `20021` | **GmbH u. Co. OHG** – Gesellschaft mit beschränkter Haftung Kapitalgesellschaft mit beschränkter Haftung der Gesellschafter und Offene Handelsgesellschaft Personengesellschaft (beschränkte Haftung auf GmbH) |
| `20022` | **gGmbH** – Gemeinnützige Gesellschaft mit beschränkter Haftung |
| `20023` | **AG u. Co. KG** – Aktiengesellschaft (AG) Kommanditgesellschaft = AG übernimmt die Rolle des Komplementärs (persönlich haftend) |
| `20024` | **AG u. Co. OHG** – Personenhandelsgesellschaft mit einer AG als Komplementärin |
| `20025` | **AöR** – Anstalt des öffentlichen Rechts |
Below is the list of `legalForm` values for users with a `distributionCountry` set to `ES`. These apply to users with a `userTypeId` of `2` except for the first one which is for [self-employed users](./physical#self-employed-users).
| Value | Description |
| :---: | --- |
| `30001` | **Autónomo** – Empresario Individual |
| `30002` | **SC** – Sociedad civil |
| `30003` | **S.C.** – Sociedad colectiva |
| `30004` | **S.Com.** – Sociedad Comanditaria Simple |
| `30005` | **S.Com.P.A.** – Sociedad Comanditaria por acciones |
| `30006` | **S.L.** – Sociedad de responsabilidad limitada |
| `30007` | **S.L.U.** – Sociedad de responsabilidad limitada unipersonal |
| `30008` | **S.A.** – Sociedad Anónima |
| `30009` | **S.A.U.** – Sociedad Anónima Unipersonal |
| `30010` | **S.L.N.E** – Sociedad Limitada Nueva Empresa |
| `30011` | **S.L.L.** – Sociedad Limitada Laboral |
| `30012` | **S.COOP.** – Sociedad Cooperativa |
| `30013` | **AIE** – Agrupación de Interés económique |
| `30014` | **SGR** – Sociedad de garantía recíproca |
| `30015` | **SAT** – Sociedad agraria de transformación |
| `30016` | **CB** – Comunidad de Bienes |
| `30017` | Fundación |
| `30018` | Asociaciones y otras instituciones sin fines de lucro a servicio de los hogares |
| `30019` | Entidad de derecho público |
| `30020` | Patrimonio de inversión sin personalidad jurídica |
### Distribution country (`distributionCountry`)
The [KYC](/guide/user-verification/introduction) requirements and regulations may depend on the country your end user is located. Therefore, if you operate in multiple countries, your Treezor configuration includes the list of countries in which you operate.
You must then associate the countries available in your configuration to your Users with the `distributionCountry` parameter. Doing so helps you tailor the onboarding process of your users, requesting the relevant declarative data and going through the appropriate [verification solution](/guide/user-verification/introduction#verification-solutions).
Treezor currently supports the following distribution countries.
| Country | `distributionCountry` value |
| --- | --- |
| Belgium | `BE` |
| France | `FR` |
| Germany | `DE` |
| Italy | `IT` |
| Luxembourg | `LU` |
| Spain | `ES` |
| The Netherlands | `NL` |
## User object
```json [JSON]
{
"userId": 0,
"userStatus": "PENDING",
"userTag": "string",
"parentUserId": 0,
"parentType": "shareholder",
"controllingPersonType": 0,
"employeeType": 0,
"specifiedUSPerson": 0,
"title": "M",
"firstname": "string",
"lastname": "string",
"middleNames": "string",
"birthday": "string",
"email": "string",
"address1": "string",
"address2": "string",
"address3": "string",
"postcode": "string",
"city": "string",
"state": "string",
"country": "string",
"countryName": "string",
"distributionCountry": "FR",
"secondaryAddress1": "string",
"secondaryAddress2": "string",
"secondaryAddress3": "string",
"secondaryPostcode": "string",
"secondaryCity": "string",
"secondaryState": "string",
"secondaryCountry": "string",
"phone": "string",
"mobile": "string",
"nationality": "string",
"nationalityOther": "string",
"placeOfBirth": "string",
"birthCountry": "string",
"legalName": "string",
"legalNameEmbossed": "string",
"legalRegistrationNumber": "string",
"legalTvaNumber": "string",
"legalRegistrationDate": "string",
"legalForm": "string",
"legalShareCapital": 0,
"legalSector": "string",
"legalAnnualTurnOver": "string",
"legalNetIncomeRange": "string",
"legalNumberOfEmployeeRange": "string",
"effectiveBeneficiary": 0,
"kycLevel": 0,
"kycReview": 0,
"kycReviewComment": "string",
"isFrozen": 0,
"language": "string",
"optInMailing": 0,
"sepaCreditorIdentifier": "string",
"position": "string",
"activityOutsideEu": 0,
"economicSanctions": 0,
"residentCountriesSanctions": 0,
"involvedSanctions": 0,
"entitySanctionsQuestionnaire": 0,
"sanctionsQuestionnaireDate": "string",
"timezone": "string",
"sourceOfFunds": "donation",
"legalSectorType": "NAF",
"isOnStockExchange": 0,
"codeStatus": "string",
"informationStatus": "string",
"createdDate": "string",
"modifiedDate": "string",
"walletCount": 0,
"payinCount": 0,
"totalRows": 0,
"occupationCategory": 1,
"personalAssetsRange": 0,
"monthlyIncomeRange": 1,
"birthCityCode": null
}
```
## Endpoints
| Endpoint | [Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/v1/users`](/api-reference/api-endpoints.html#tag/Users/postUsers){target="\_self"} Create a User | `legal`, `admin` |
| [`/v1/users`](/api-reference/api-endpoints.html#tag/Users/getUsers){target="\_self"} Search for Users | `read_only` |
| [`/v1/users/{userId}`](/api-reference/api-endpoints.html#tag/Users/getUser){target="\_self"} Retrieve a User based on its `id` | `read_only` |
| [`/v1/users/{userId}`](/api-reference/api-endpoints.html#tag/Users/putUser){target="\_self"} Update a User | `read_write` |
| [`/v1/users/{userId}/FreezeAssets`](/guide/users/restricted-users#freeze) Freeze/Unfreeze a User | `admin` |
| [`/v1/users/{userId}`](/api-reference/api-endpoints.html#tag/user/deleteUser){target="\_self"} Delete a User | `read_write`, `admin` |
| [`/v1/taxResidences`](/api-reference/api-endpoints.html#tag/User%20Tax%20Residences/postTaxresidence){target="\_self"} Create a Tax Residence | `read_write` |
| [`/v1/taxResidences`](/api-reference/api-endpoints.html#tag/User%20Tax%20Residences/getTaxresidences){target="\_self"} Search for Tax Residences | `read_only` |
| [`/v1/taxResidences/{taxResidenceId}`](/api-reference/api-endpoints.html#tag/User%20Tax%20Residences/getTaxresidence){target="\_self"} Retrieve a Tax Residence based on its `id` | `read_only` |
| [`/v1/taxResidences/{taxResidenceId}`](/api-reference/api-endpoints.html#tag/User%Tax%20Residences/putTaxresidence){target="\_self"} Update a Tax Residence | `read_write` |
| [`/v1/taxResidences/{taxResidenceId}`](/api-reference/api-endpoints.html#tag/User%Tax%20Residences/deleteTaxresidence){target="\_self"} Delete a Tax Residence | `read_write` |
## Diagram
```mermaid
flowchart LR
User(User)
AnonymousUser(Anonymous)
PhysicalUser(Physical)
BusinessUser(Business)
NGOUser(Non-Governmental Organization)
GovernmentalUser(Governmental Organization)
Documents(Documents)
KYCValidation("KYC Validation by Treezor")
User -- userTypeId=1,2 --> AnonymousUser
User -- userTypeId=1 --> PhysicalUser
User -- userTypeId=2 --> BusinessUser
User -- userTypeId=3 --> NGOUser
User -- userTypeId=4 --> GovernmentalUser
AnonymousUser -. optional .- Documents
PhysicalUser --- Documents
BusinessUser --- Documents
NGOUser --- Documents
GovernmentalUser --- Documents
Documents -- Submission to Treezor --> KYCValidation
class User MermaidUser
class AnonymousUser MermaidNeutral
class PhysicalUser MermaidNeutral
class BusinessUser MermaidNeutral
class NGOUser MermaidNeutral
class GovernmentalUser MermaidNeutral
class Documents MermaidNeutralAlternate
class KYCValidation MermaidCard
click AnonymousUser "/guide/users/physical.html#anonymous-users"
click PhysicalUser "/guide/users/physical.html"
click BusinessUser "/guide/users/legal-entity.html"
click NGOUser "/guide/users/legal-entity.html"
click GovernmentalUser "/guide/users/legal-entity.html"
click Documents "/guide/user-verification/documents.html"
click KYCValidation "/guide/user-verification/introduction.html"
```
---
---
url: /guide/wallets/introduction.md
description: >-
Get a foundational understanding of Treezor wallet and account types, and
their compatible functionalities. Includes key attributes, JSON structure, and
related endpoints list.
---
# Introduction
Wallets are accounts used to store funds. They are necessary for any type of transaction in the Treezor environment.
In most cases, Wallets are attached to your end users (Wallets (n) → User (1)), allowing for the setup of their means of payment (cards, transfers, etc.). You can check their [Balance](balances), and they come with a dedicated [IBAN](iban).
Treezor offers various types of wallets to adapt to multiple use cases and technical architectures while remaining compliant in a highly regulated context.
Here are the wallet types you might encounter:
* [Electronic Money Wallet](#electronic-money-wallet-type-9)
* [Payment Account Wallet](#payment-account-wallet-type-10)
* [Master Wallet](#master-wallet-type-15)
* [Card Transaction Wallet](#card-transaction-wallet-type-14-18)
## Electronic Money Wallet (type `9`)
Electronic Money Wallets are accounts specifically designed to hold funds in the form of [e-money](/guide/overview/glossary#electronic-money-e-money) and are compatible with a specific set of features.
They are mostly used for prepaid services and online transactions, as the account balance represents prepaid monetary value.
Such accounts are governed by the E-money regulation (EU’s E-Money Directive), so you require an [**EM approval**](https://treezor.zendesk.com/hc/en-us/articles/360014672580-Note-EM-5th-Directive) of your project to create this type of Wallets.
Electronic wallets can store either:
* **Nominative e-money** – The owner is KYC-validated.
* **Anonymous e-money** – The owner is not KYC-validated.
Depending on the type of [e-money](/guide/overview/glossary#electronic-money-e-money), different limits and restrictions may apply.
### Electronic Money Limits
[E-money](/guide/overview/glossary#electronic-money-e-money) is governed by national and international rules that Electronic Money institutions must comply with.
Following these rules, Treezor applies different types of restrictions and limits for anonymous and nominative e-money.
The limits and restrictions are currently enforced in Belgium, France, Germany, and Spain. In addition, anonymous electronic money isn't allowed in Italy.
#### Features
Below the compatibility of Electronic Wallets with Treezor features.
| Feature | Anonymous | Nominative |
|-------------------|:----------------------------:|:----------------------:|
| Check cashing (payin) | | |
| Emitted SEPA Credit Transfer (payout) | | |
| Received SEPA Direct Debit (payout) | | |
| Received SEPA Credit Transfer (payin) | | |
| Instantaneous Received SEPA Credit Transfer (payin) | | |
| Emitted SEPA Direct Debit (payin) | | |
| Card Acquiring (payin) | | |
| Card payment | | |
| Wallet-to-Wallet transfers with `type=10` | | |
| Wallet-to-Wallet transfers with `type=9` (Anonymous) | | |
| Wallet-to-Wallet transfers with `type=9` (Nominative) | | |
| Wallet-to-Wallet transfers with `type=9` with parent-children relationship between users | | |
| Wallet-to-Wallet transfers with `type=9` of the same user | | |
#### Limits & restrictions
Below are the e-money limits and restrictions. Limits are calculated on a rolling 30-day period per user (regardless of the number of `type=9` wallets they own).
| Feature | Anonymous | Nominative |
|------------------------------------------------|------------------------------------------------------------|------------------------------------------------|
| Balance | Max. €150/user | Max. €10.000/user (with physical card) |
| Crediting Wallets | Max. €150/user | Max. €10.000/user (with physical card) |
| Debiting Wallets | Max. €150/user | Max. €10.000/user (with physical card) |
| Cash withdrawals | | Max. €1.000/user |
| Cash top-ups | | Max. €1.000/user |
| Card top-ups | Max. €150/user | Max. €1.000/user |
| Cash refunds | | Max. €1.000/user |
| Card Transaction MCC | Prohibited MCCs: 4829, 6050, 6051, 6536, 6537, 6538, 6540, 7800, 7801, 7995, 9406 | No restriction |
| Card transactions | Max. €50/transaction (online) Max. €150/transaction ([POS](/guide/overview/glossary#terminal)) | Max. €3.000/transaction |
| Receiving funds from an anonymous e-money account | | Max. €1.000/user |
| Country | Anonymous e-money cannot be used outside of the country where the e-money was issued. | No restriction |
**Information – The €150 limit does not apply when the wallet is:**
* Used for special payment vouchers (i.e., restricted to certain categories of goods or services) **and**
* [Associated](/guide/users/parent-children) to a parent [Legal entity](/guide/users/legal-entity) that is KYC validated.
## Payment Account Wallet (type `10`)
Payment Account Wallets are accounts that facilitate payment transactions. They support a wider range of operations, including check cashing, emitted SEPA Credit Transfers, and received SEPA Direct Debit.
Payment accounts are governed by payment services regulations, such as the EU's Payment Services Directive 2 (PSD2). Therefore, you require the [**ACPR approval**](https://acpr.banque-france.fr/) of your project to create this type of Wallets.
Only [KYC-validated](/guide/user-verification/introduction) users can use Payment Account Wallets.
## Master Wallet (type `15`)
Master Wallets are only created by Treezor, mostly to process payment titles with specific and regulated usage (e.g., employee benefits, lunch vouchers). This is what is called in French *“Titres Spéciaux de Paiement (TSPs)“*.
They are only available to certain projects, as per agreement with Treezor.
## Card Transaction Wallet (type `14` & `18`)
Treezor automatically creates additional Wallets to process card transactions properly. They can be of type:
* `14` for the Mastercard scheme
* `18` for the Visa scheme
These wallets are exclusively for Treezor’s internal usage, and you shouldn't have to interact with them at any point. You may however encounter such Wallets in the `walletCardtransactionId` attribute in the Card object.
## How To Credit Wallets (Top-up)
To credit a Wallet, multiple options are available to you.
| Feature | Description |
| --- | --- |
| **Card Top-up** | [Card Topups](/guide/acquiring/introduction) allow you to display a Card acquisition form in your application, in a similar way to a payment form on a web shop. The user can use their existing Card to credit the wallet instantly. |
| **SEPA Credit Transfer** | [SEPA Credit Transfers (SCTR)](/guide/transfers/credit-transfer#received-credit-transfers-sctr) are a type of inter-bank transfers, initiated by the debtor who needs to know the IBAN of the Wallet to credit. It usually takes a few days to appear on the Wallet. [Instantaneous SEPA Credit Transfers (SCTR Inst)](/guide/transfers/credit-transfer-inst#received-instant-credit-transfers-sctr-inst) are a quicker variant of the aforementioned SCTR. It usually takes a few seconds to appear on the Wallet. |
| **SEPA Direct Debit** | [SEPA Direct Debit (SDDE)](/guide/transfers/direct-debit#emitted-direct-debits-sdde) are a type of inter-bank debit, initiated by the creditor who needs to know the IBAN of the account to debit and have a [Mandate](/guide/transfers/mandates) signed by the debtor. |
| **Checks cashing** | Traditional check cashing remains a reliable way of receiving money on a Wallet. Treezor offers the ability to first register a check via the API, then mail in that check for cashing on a Wallet. See the [Checks](/guide/cheques/introduction) section of the documentation for more information. |
| **Wallet-to-Wallet transfers** | Within Treezor, you can use inter-wallet [Transfers](/guide/transfers/wallet-to-wallet) that take effect immediately. |
## Key attributes
Below are some of the most important Wallet attributes.
| Attribute | Type | Description |
|--- |--- |--- |
| `walletTypeId` | integer | The type of wallet. The Wallet type is editable up to the first operation. Once the first transaction occurred, the `walletTypeId` can no longer be updated |
| `eventName` | string | The name of the Wallet. |
| `solde` | number | The current [**Balance**](/guide/wallets/balances) of the Wallet. Prefer the [Balance endpoints](/guide/wallets/balances) for more accurate values. |
| `authorizedBalance` | number | The balance of the Wallet, [including **currently pending operations**](/guide/wallets/balances). Prefer the [Balance endpoints](/guide/wallets/balances) for more accurate values. |
| `userId` | integer | The unique identifier of the [User](/guide/users/introduction) owning the Wallet. |
| `walletTag` | string | Custom attribute that you can use as you see fit. Learn more in the [Object tags](/guide/api-basics/objects-tags) article. |
| `tariffId` | integer | The fees applied to the Wallet, as defined by your contract with Treezor. |
| `walletStatus` | string | The [status of the Wallet](#wallet-status), which can be one of the following: `PENDING`, `VALIDATED`, or `CANCELED`. |
| `bic` | string | The [Bank Unique Identifier](/guide/overview/glossary#bank-identifier-code-bic) of the bank hosting the Wallet. All Wallets at Treezor have the same BIC unless you are a Payment Institution or more broadly a [Regulated Institution](/guide/overview/glossary#regulated-institution). |
| `iban` | string | The automatically assigned [IBAN](./iban) of the Wallet. |
| `currency`| string | The currency of the Wallet, in the [ISO 4217 3-letter code](/guide/api-basics/data-format#currencies) format. As of today, Treezor only supports `EUR`. |
**API – API Reference available**
For a complete list of Wallet attributes, check the [Wallets](/api-reference/api-endpoints.html#tag/Wallets){target="\_self"} section of the API Reference.
### Wallet Status
| | `codeStatus` | `walletStatus` | Description |
| :---: | :---: | --- | --- |
| | `120001` | PENDING | Some checks are in progress. |
| | `120002` | PENDING | KYC process in progress. |
| | `120003` | CANCELED | Wallet closed by an operator. |
| | `120004` | CANCELED | Wallet closed by the end user. |
| | `120005` | VALIDATED | Wallet is ready for use. |
## Wallet object
```json [JSON]
{
"walletId": 0,
"walletTypeId": 0,
"walletStatus": "PENDING",
"codeStatus": 0,
"informationStatus": "string",
"walletTag": "string",
"userId": 0,
"userLastname": "string",
"userFirstname": "string",
"jointUserId": 0, // Legacy attribute, do not use
"tariffId": 0,
"eventName": "string",
"eventAlias": "string", // Legacy attribute, do not use
"eventDate": "string", // Legacy attribute, do not use
"eventMessage": "string",
"eventPayinStartDate": "string",// Legacy attribute, do not use
"eventPayinEndDate": "string", // Legacy attribute, do not use
"contractSigned": 0,
"bic": "string",
"iban": "string",
"urlImage": "string",
"currency": "string",
"createdDate": "string",
"modifiedDate": "string",
"payinCount": 0,
"payoutCount": 0,
"transferCount": 0,
"solde": 0, // currentBalance
"authorizedBalance": 0,
"totalRows": 0
}
```
**Best practice – Use the endpoints dedicated to Balances**
You may experience some latency with the Wallet `solde` and `authorizedBalance` fields. Use the [`/v1/balances/{walletId}`](/api-reference/api-endpoints.html#tag/Balances/getBalances){target="\_self"} endpoint for a more performant usage. See the [Balances](/guide/wallets/balances) article.
## Endpoints
| Endpoint |[Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/v1/wallets`](/api-reference/api-endpoints.html#tag/Wallets/postWallets){target="\_self"} Create a Wallet | `read_write` |
| [`/v1/wallets`](/api-reference/api-endpoints.html#tag/Wallets/getWallets){target="\_self"} Search for Wallets | `read_only` |
| [`/v1/wallets/{walletId}`](/api-reference/api-endpoints.html#tag/Wallets/getWallet){target="\_self"} Retrieve a Wallet based on its `id` | `read_only` |
| [`/v1/wallets/{walletId}`](/api-reference/api-endpoints.html#tag/Wallets/putWallet){target="\_self"} Update a Wallet | `read_write` |
| [`/v1/wallets/{walletId}`](/api-reference/api-endpoints.html#tag/Wallets/deleteWallet){target="\_self"} Set the Wallet status to `CANCELED` | `read_write` |
| [`/v1/balances/{walletId}`](/api-reference/api-endpoints.html#tag/Balances/getBalances){target="\_self"} Retrieve the Balance of Wallets based on the `walletId` or `userId` | `read_only` |
| [`/core-connect/balance/{walletId}/balance`](/api-reference/api-endpoints.html#tag/Balances/getWalletBalanceHistory){target="\_self"} Retrieve the Balance History of a Wallet | `read_only` |
---
---
url: /guide/webhooks/introduction.md
description: >-
Get started with Treezor API webhooks. Learn what webhooks are, their core
structure (payload, signature), and why to use them for real-time event
notifications and handling unpredictable banking events.
---
# Introduction
When a specific event occurs, an HTTP request is sent from our infrastructure to a URL of your choice and provides you with relevant information regarding that event.
A webhook is characterized by:
* The unique identifier of the webhook
* The callback URL – The URL receiving the event notification
* The [event](/guide/webhooks/events-descriptions) – The event triggering a webhook request
* The payload – The data passed along with the event
* The signature – A means of [checking authenticity](/guide/webhooks/integrity-checks)
## Why use Webhooks?
Although optional, using webhooks is strongly recommended. They provide much quicker event notifications (no need to periodically check the API for changes).
As a result, webhooks allow you to better handle:
* The intrinsic unpredictability of some banking events such as:
* Receiving a [card payment](/guide/acquiring/introduction) or [money transfer](/guide/transfers/introduction),
* Blocked transfers due to [AML/CFT suspicion](/guide/overview/glossary#aml-cft-anti-money-laundering-combating-the-financing-of-terrorism)
* [Check cashing](/guide/cheques/cashing)
* [Card](/guide/cards/introduction) activation by a [User](/guide/users/introduction)
* The inherent delay of some actions such as requesting a [KYC](/guide/user-verification/introduction) or [Document](/guide/user-verification/documents) review.
**Information – Not all Webhooks are available in Sandbox**
[Read more about those limitations](/guide/api-basics/environments#sandbox)
## What does a Webhook look like?
It looks like a standard HTTP POST request.
Details regarding the event are embedded as a JSON array (`object_payload`). A hash (`object_payload_signature`) of the body allows you to [assert the authenticity](/guide/webhooks/integrity-checks) of the received information.
**Information – Webhooks may not be received in chronological order**
While Treezor sends webhooks chronologically, there is [no guarantee your servers receives them in the same order](./race-conditions). Compare the `webhook_created_at` values against your locally stored values to know which is most recent.
## Structure of a webhook
| Attribute | Description |
|--- |--- |
| `webhook` | Name of the webhook |
| `webhook_id` | Unique identifier of the webhook (UUID v4, 36-character long string). Please note duplicates can be sent, in which case they have the same `webhook_id`. |
| `webhook_created_at` | Date and time at which the webhook was created, as [Unix epoch (timestamp)](https://en.wikipedia.org/wiki/Unix_time) in the form `10^-4` seconds |
| `object` | Name of the Treezor object |
| `object_id` | ID of the Treezor object |
| `object_payload` | **Standard Treezor objects** (Payin, Payout, CardTransaction, User, Wallet, etc.), generally in an array |
| `object_payload_signature` | Hash of \[payload + `webhook_secret`]. This field allows you to [ensure the payload originates from Treezor](/guide/webhooks/integrity-checks) and has not been tempered with. |
**Tip – Webhooks content matches the API's**
Objects contained in the payload are identical to any other object retrieved from *Treezor Connect* API. They are simply embedded in an event object.
## Example
Below is an example of a webhook request.
It was triggered by the creation of a transaction ([`transaction.create`](/guide/cards/events-tx#cardtransaction-create) event).
```json [JSON]
{
"webhook": "transaction.create",
"webhook_id": "54350b79-9250-4e4e-bc0e-c2c01f6c43c6",
"object": "transaction",
"object_id": "16700",
"object_payload": {
"transactions": [
{
"transactionId": "16700",
[...] // some attributes are hidden for clarity
}
]
},
"object_payload_signature": "XWvC\/4wAhkqIOgHAccHTkZQ73zp7QMBZC5APTU5oZww="
}
```
While webhooks return JSON, **they are provided with the `text/plain` mime type** .
## Race conditions
Treezor sends webhooks chronologically, but cannot guarantee that your servers will receive them in the same order.
In some situations, you could receive a [`payin.update`](/guide/transfers/events#payin-update) before the associated [`payin.create`](/guide/transfers/events#payin-create) for instance.
**Therefore, your code must not rely on the order in which webhooks are received**.
### Identifying the latest webhook
To identify which of two or more webhooks were sent last, you must compare their `webhook_created_at` attribute with your locally stored values.
Most webhook-contained objects also have a `createdDate` and `modifiedDate` attribute. You may also use these when they exist.
This is of critical importance for [CardTransactions](/guide/cards/transactions-lifecycle) as they go through many steps and only the latest is authoritative. Failure to do so implies displaying outdated and erroneous information to the user.
---
---
url: /guide/user-verification/faking-operations.md
description: >-
Learn how to update the user KYC status within the Sandbox environment for
development and API integration testing.
---
# Emulation
Emulation features are only available in `Sandbox` [environment](/guide/api-basics/environments).
**Tip – You can also rely on webhooks**
For operations that cannot be emulated in the Sandbox, [webhook examples](events) are provided.
## KYC validation
Emulate the KYC validation of a single user by adding a suffix to the User's `lastname` (or `legalName` for legal entities) using the following requests:
* [`/v1/users`](/api-reference/api-endpoints.html#tag/Users/postUser){target="\_self"}
* [`/v1/users/{userId}`](/api-reference/api-endpoints.html#tag/Users/putUser){target="\_self"}
| Suffix | `kycLevel` | `kycReview` | Description |
| --- | :---: | :---: | --- |
| `.validated` | `2` | `2` | The User is `REGULAR` / `VALIDATED` |
| `.refused` | `4` | `3` | The User is `REFUSED` / `REFUSED` |
**Tip – Compatible with User status emulation**
You can cumulate the suffixes to achieve both KYC and [status emulation](/guide/users/faking-operations) at once. For instance: `lastname.refused.userStatusValidated`.
Wait a few minutes and make a [`/v1/users/{userId}`](/api-reference/api-endpoints.html#tag/Users/getUser){target="\_self"} request for the User you've just updated.
The API returns the User with the emulated `kycLevel` and `kycReview`.
**Information – Incompatibility with Parent-Children hierarchical relations**
As opposed to the API behavior when requesting a KYC Review, emulating the validation of a parent user won't have any consequence on its children.
### Example
Let's take an example in which we'd like to simulate a KYC refusal of a User.
```bash [CURL]
curl -X PUT '{baseUrl}/v1/users' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
With a `{payload}` containing the suffixed `lastname`:
```json [JSON]
{
"lastname": "Oak.refused"
}
```
You need to retrieve the User a few moments after the update with the following request:
```bash [CURL]
curl -X GET '{baseUrl}/v1/users/{userId}' \
--header 'Authorization: Bearer {accessToken}'
```
The User object returned with the updated `kycLevel` and `kycReview`.
```json [JSON] {47-49}
{
"users": [
{
"userId": 100135695,
"userTypeId": 1,
"userStatus": "VALIDATED",
"userTag": "emulationTestr36748",
"parentUserId": 0,
"parentType": "",
"controllingPersonType": 0,
"employeeType": 0,
"specifiedUSPerson": 0,
"title": "",
"firstname": "Alex",
"lastname": "Oak.refused",
"middleNames": "",
"birthday": "1982-05-31",
"email": "aOak533@example.com",
"address1": "12 rosewood lane",
"address2": "",
"postcode": "75000",
"city": "Paris",
"state": "",
"country": "FR",
"countryName": "France",
"phone": "+33121212121",
"mobile": "",
"nationality": "FR",
"nationalityOther": "",
"placeOfBirth": "Montreuil",
"birthCountry": "FR",
"occupation": "",
"incomeRange": "0-18",
"legalName": "",
"legalNameEmbossed": "",
"legalRegistrationNumber": "",
"legalTvaNumber": "",
"legalRegistrationDate": "0000-00-00",
"legalForm": "",
"legalShareCapital": 0,
"entityType": null,
"legalSector": "",
"legalAnnualTurnOver": "",
"legalNetIncomeRange": "",
"legalNumberOfEmployeeRange": "",
"effectiveBeneficiary": 0,
"kycLevel": 4,
"kycReview": 3,
"kycReviewComment": "Refused automatic simulation",
"isFreezed": 0,
"isFrozen": null,
"language": "",
"optInMailing": null,
"sepaCreditorIdentifier": "",
"taxNumber": "",
"taxResidence": "",
"position": "",
"personalAssets": "465-",
"createdDate": "2024-02-14 07:24:21",
"modifiedDate": "2024-02-14 08:25:12",
"walletCount": 0,
"payinCount": 0,
"totalRows": "1",
"activityOutsideEu": 0,
"economicSanctions": 0,
"residentCountriesSanctions": 0,
"involvedSanctions": 0,
"entitySanctionsQuestionnaire": 0,
"address3": null,
"timezone": null,
"occupationType": "",
"isOnStockExchange": 0,
"secondaryAddress1": "",
"secondaryAddress2": "",
"secondaryAddress3": "",
"secondaryPostcode": "",
"secondaryCity": "",
"secondaryState": "",
"secondaryCountry": "",
"clientId": "929252",
"sanctionsQuestionnaireDate": null,
"codeStatus": "110009",
"informationStatus": "",
"legalSectorType": "",
"sourceOfFunds": ""
}
]
}
```
## KYC Liveness
### Refused Liveness
To emulate a refused Liveness process, create a User under one name and provide documents (ID Card, driving license, etc.) under a different name during the Liveness.
### Accepted Liveness
To emulate an accepted Liveness process, create a User under one name and provide documents (ID Card, driving license, etc.) in the same name during the liveness.
---
---
url: /guide/dashboard/kyc.md
description: >-
Let your team provide support regarding your end users onboarding using the
Treezor Dashboard. Includes the upload of documents and pre-review.
---
# KYC / KYB
Know Your Customer (KYC) or Know Your Business (KYB) refers to the verification of your users' identity. Part of this process consists in submitting documents to Treezor for validation, which can be done from the Dashboard.
**Reading – Know Your Customer**
Learn more about the user verification process with the dedicated [KYC](/guide/user-verification/introduction) section.
## Accessing user KYC/KYB information
You may access KYC information for a specific user in the *User details* view, *KYC* tab once a user is selected (learn more about [accessing user information](/guide/dashboard/users#accessing-your-users)). The tab appears only for users who can go through verification.
**Information – The tab changes depending on the type of user**
The name of the tab and the details depend on the user type. For the sake of convenience, this article uses mostly the term KYC rather than KYB.
The *KYC* / *KYB* tab is made up of the following sections:
* [**Global KYC Status**](#global-kyc-status) – Information about the KYC Status of the selected user, including [additional vigilance measures](#additional-vigilance-measure).
* **User information** – Main declarative data about the user.
* **Verification details** – Declarative data necessary for user verification, such as nationality, situation, or tax residence for instance.
* [**Documents section**](#documents-section) – List of documents uploaded for the user, for you to review.
In the upper right corner, the "Submit KYC to Treezor" button allows you to [request a KYC review by Treezor](#request-a-kyc-review-by-treezor). This button is only enabled once the required data is provided.
## Global KYC Status
The *Global KYC Status* section provides information about the KYC Status of the selected user.
### KYC Status
On the left-hand side, the KYC Status indicates the overall status of the user verification.
The status can be one of the following values:
| Status | Description |
| --- | --- |
| **Not required** | The user is not subject to verification. |
| **Optional** | The user doesn't need to go through verification unless they reach [Electronic Money Limits](/guide/wallets/introduction#electronic-money-limits). |
| **To submit to Treezor** | The necessary declarative data is filled in; you can now request verification from Treezor. Ensure all documents have been uploaded and pre-reviewed before submitting. |
| **Pending Treezor** | Treezor Compliance team is reviewing the user. |
| **To review** | Treezor rejected the user (e.g., missing data). Complete user data and documents before resubmitting. |
| **To check** | Treezor triggered a periodical or exceptional review. Update user data and documents before requesting a new review. |
| **Validated** | Treezor has verified the user and deemed them fit to use the financial services. |
| **Refused** | Treezor has verified the user and deemed them unfit to use the financial services. This status is definitive. |
Clicking on the "See details" button opens the *KYC History* popup which contains:
* Date and time at which Treezor Compliance team reviewed the user
* Comments and note from Treezor compliance team
* [KYC Level](/guide/user-verification/introduction#user-kyc-levels-kyclevel) set during the verification.
* [KYC Review status](/guide/user-verification/introduction#user-kyc-review-status-kycreview) set during the verification.
#### KYC life cycle
### Additional vigilance measure
Additional vigilance measures might be necessary to complete the user verification process.
It consists of a received SEPA Credit Transfer to the user wallet. Status can be:
* **None** – No SCTR has been initiated yet.
* **Pending** – An SCTR has been initiated, but not validated yet.
* **Settled** – The SCTR is validated, completing the additional vigilance measure.
Once the transfer "Settled", the vigilance measure is complete and the user will be able to use Treezor financial services when verified.
When clicking on the "See details" button, the *Additional vigilance measure* popup is displayed, providing the list of SCT payins made with the following key attributes: Operation date, status, amount, emitter, IBAN, and BIC.
## User information sections
You can view user main information which are necessary for the KYC/KYB review in the *User information* and *Verification details* sections.
If you have the relevant rights, you can update existing user data.
Make sure the provided data is in accordance with the Compliance rules in terms of KYC.
### Manage user tax residence
When declaring the tax residence, you need to provide the country and Tax Identification Number (TIN) of the user (optional for all the countries except for [US and Italian taxpayers](/guide/users/tax-residence)).
It is possible to add or edit the user Tax Residence in the *Verification details* section, by clicking on the dedicated "Edit" button.
Click on the "Add Tax Residence" button to declare a new tax residence.
Fill in the displayed fields with the relevant country and Tax Identification Number.
"Save Changes" to complete your new declaration.
## Documents section
Documents are evidence required by Treezor to ensure Users are who they claim to be.
During the KYC/B review, Treezor compares documents to the user’s declarative data. The user is verified if the documents are in order (as well as any other verification requirement).
This section lists documents uploaded for the KYC Review. You must pre-review the documents before requesting the KYC review from Treezor.
### Documents list
Documents are displayed if:
* The end user uploaded documents from your application
* Your Dashboard Users uploaded a document for your end users
Each document has a menu icon that provides access to the following commands (depending on the status of the document):
| Action | Description |
| --- | --- |
| **Review document** | Opens the [*Review document*](#review-document-popup) popup, allowing you to validate or refuse the document. |
| **See document details** | Opens the read-only version of the [*Review document*](#review-document-popup) popup, allowing you to validate or refuse the document. |
| **Delete document** | Deletes the document. |
Also, clicking on the arrow displays the document in a new browser tab or downloads it (depending on the format).
### Document statuses
Documents can have one of the following statuses. Please note every time "you" is indicated, the name of your company will be displayed instead.
| Status | Description |
| --- | --- |
| **To review (you)** | Waiting for pre-review from your teams. |
| **Reviewed (you)** | The document has been pre-reviewed (validated) by your teams, but at least another document from this use is still to be pre-reviewed. |
| **Reviewed, to submit** | All the documents have been pre-reviewed by your teams. They will be sent to Treezor for validation when requesting the KYC review. |
| **Pending validation** | The documents are waiting for Treezor team's validation. |
| **Validated (Treezor)** | The document has been validated by Treezor as part of the KYC/KYB review process. |
| **Refused (you)** | Your team refused the document during the pre-review process. |
| **Refused (Treezor)** | The document was rejected by Treezor as part of the KYC/KYB review process. |
| **Canceled** | The document was deleted by the end user or your teams, or was subject to a technical issue. |
#### Document life cycle
### Review document popup
The *Review document* popup displays a preview of the uploaded document on the left-hand side, and details of the document on the right.
In order to review a document:
1. Select the relevant status in the picklist.
2. Add a comment explaining your choice.
3. Click on the enabled "Submit" button.
### Uploading KYC Documents
Usually, end users are the ones uploading their KYC documents through your application. In some cases, however, your [Dashboard Users](/guide/dashboard/dashboard-users) might upload documents for the end users.
They can do so by clicking on the "Add KYC Document" button to open the *Upload KYC document* popup.
From there, you can select a document type, then upload the file while abiding by the requested format and weight.
If the upload is successful, the document appears in the *Documents* section.
## Requesting a KYC review by Treezor
When all the necessary documents have been uploaded and properly pre-reviewed, you can request a review from Treezor.
To do so, click on the "Submit KYC to Treezor" button located in the upper right corner of the *User details* view, *KYC tab*.
**Information – In Production, verification is done by Treezor Compliance team**
Verification usually takes about 24h, but may take up to 48h or more (working days only).
---
---
url: /guide/api-basics/mutual-tls.md
description: >-
Understand Mutual TLS (mTLS) for the Treezor API. This guide explains two-way
authentication, how to implement client certificates, and enhance API security
for robust and trusted connections.
---
# Mutual Transport Layer Security (mTLS)
The Mutual Transport Layer Security (mTLS) protocol ensures mutual authentication and encrypted communication, preventing interception and identity theft between systems.
**Configuration – Mutual Transport Layer Security (mTLS) availability**
If you've been working with Treezor prior to the mTLS authentication availability, you will have to migrate to the new services.
## Introduction
Mutual TLS ensures that both parties at each end of the network connection are who they claim to be by verifying that each has the correct private key.
This protocol relies on the exchange of Transport Layer Security (TLS) certificates. TLS certificates contain the necessary information for verifying the server's or device's identity, such as the public key, a statement of who issued the certificate, and the expiration date.
## Setting up your certificates
To use mTLS, you need to send 2 Certificate Signing Requests (CSRs) to Treezor. This will allow you to set up the TLS negotiation with your private key.
In return, Treezor provides the signed certificates for you to configure your client and authenticate your requests.
You need to provide a different set of certificates for each of your Treezor environments (Sandbox and Production). If you're using PCI DSS services, you'll need an additional set of CSR files (see [PCI DSS integration](/guide/cards/pci-dss)).
### 1. Create your RSA keys
You need a private key to create your Certificate Signing Request (CSR). This key must have the following attributes:
* **Type**: RSA
* **Format**: PKCS1
* **Size**: 2048
**Configuration – Use a different RSA key for each CSR**
Your mTLS certificate and your signature certificate for [signing PCI DSS requests](/guide/cards/pci-dss#sign-your-requests) must have different private keys.
Here is the command to run for your Sandbox environment. Keep in mind you'll need to repeat this process for your Production environment.
```[Linux / macOS]
openssl genrsa -out _privatekey_mtls.pem 2048
```
**Security – Protect your private key**
Don’t share your private key with anyone and make sure they are securely stored (e.g., secure vault, key management system).
### 2. Create your CSR files
The Certificate Signing Request (CSR) is a request you send to a Certificate Authority (or CA, in this case, Treezor) to apply for a digital identity certificate. The CSR includes the public key and additional information such as the common name (CN) of the entity requesting the certificate.
Here is the command to run:
```[Linux / macOS]
openssl req -new -key _privatekey_mtls.pem -out _csr_mtls.pem
```
Then use the information in the table below to complete the CSR information.
| Information | Description |
|---------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Country | The two-letter country code representing the country where the organization is located. |
| State / Province | The state or province where the organization is located (e.g., Brittany, IdF). |
| Locality | The locality or city where the organization is located. |
| Organization Name | The legal name of the organization to which the entity belongs. This could be the company, department, or other organizational unit. |
| Organizational Unit | (optional) The specific unit within the organization. For example, “IT Department” or “Marketing”. |
| Common Name | Usually, the fully qualified domain name (FQDN) for which the certificate is being requested. For example, if the certificate is for a website, the CN might be the domain name (e.g., https://yourcompany.com). |
| Email | The email address of the organization. |
### 3. Ask Treezor to generate your certificates
CSR files and certificates are not considered sensitive data. This is why you can exchange them by email.
1. Send your CSR files to your *Treezor Technical Account Manager*.
2. Treezor will send you back the signed certificates.
**Security – Don't send your private keys, only the CSR files**
If you were to send us your private key, you would have to generate new ones and start the process from scratch.
## Renewing your certificates
Your certificates have a specific validity period. You need to contact Treezor about a month before their expiration date to set up new ones.
Here is the command to run to check the start and end dates of a certificate:
```[Linux / macOS]
openssl x509 -startdate -enddate -noout -in _csr_.pem
```
Outputs the following:
```[Linux / macOS]
notBefore=Jan 22 12:25:04 2024 GMT
notAfter=Jan 22 13:25:04 2025 GMT
```
## Revoking your certificates
If you suspect your private key has been compromised, you must contact Treezor immediately to revoke your certificate. You can then go through the process described in this article to set up new certificates.
---
---
url: /guide/api-basics/objects-tags.md
description: >-
Understand Object Tags in the Treezor API. This guide explains how to use
custom tags to categorize and manage your API objects for enhanced
organization and filtering of your data.
---
# Object tags
Tag attributes allow you to match Treezor objects with objects stored in your databases. These attributes have the following characteristics:
* Strings (max 250 characters)
* Always in the API's responses
* Named as a concatenation of the object's class and the word "Tag" (camelCase)
Here are a few examples of tag attributes: `userTag`, `cardTag`, `payinTag`, `walletTag`.
**Best practice – Tags must:**
* **Be unique**. Tagging convention must avoid tag collisions.
* **Use alphanumeric characters** plus `/` `!` `-` `_` `.` `*` `'` `(` `)`. Using other characters can have unexpected consequences.
## Tag examples
### User Tag
When creating a User object, the associated tag is the `userTag`. Consider the following request to create a user:
```bash [CURL]
curl -X POST '{baseUrl}/users' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
You can include the corresponding `userTag` in the `{payload}`:
```json [JSON] {3}
{
"userTypeId": 1,
"userTag": "6050c342b8e240.82964",
"specifiedUSPerson": 0,
"firstname": "Alex",
"lastname": "Oak",
"birthday": "1982-05-31",
"placeOfBirth": "Edgewood",
"birthCountry": "FR",
"nationality": "FR",
"email": "alex.oak@example.com"
}
```
The `userTag` is then included in the returned User object.
### Wallet Tag
When creating a Wallet object, the associated tag is the `walletTag`. Consider the following request to create a wallet:
```bash [CURL]
curl -X POST '{baseUrl}/wallets' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
You can include the corresponding `walletTag` in the `{payload}`:
```json [JSON] {3}
{
"walletTypeId": 10,
"walletTag": "6050c342b8e240.82964",
"userId": 123456,
"currency": "EUR",
"eventName": "My Wallet Name"
}
```
The `walletTag` is then included in the returned Wallet object.
---
---
url: /guide/api-basics/pagination.md
description: >-
Master API pagination in the Treezor API. This guide explains how to retrieve
large datasets, detailing both offset-based and cursor-based pagination types
for efficient data handling.
---
# Pagination
Pagination involves breaking down the list of returned objects into subsets that you can then navigate.
Treezor offers 2 methods to paginate API responses, depending on the endpoints.
| Method | Description |
| --- | --- |
| **[Offset-based](#offset-based-pagination)** | Divides the results into pages by indicating the number of items per page. |
| **[Cursor-based](#cursor-based-pagination)** | Uses a cursor to mark the last item in each page. |
## Offset-based pagination
### Parameters
[Endpoints that support offset pagination](#supported-endpoints) rely on the following query parameters.
| Attribute | Description |
| --- | --- |
| `pageNumber` | The number of the page to retrieve. |
| `pageCount` | The number of objects per page. |
| `sortBy` | The object attribute to sort the list with (e.g., `creationDate`, `modifiedDate`, etc.). Differs for each endpoint. |
| `sortOrder` | The order you want to sort the list. Either: `DESC` (default) for a descending order`ASC` for an ascending order |
### Examples
Let's retrieve the list of transfers for a specific wallet with the following pagination parameters:
* **1st page** (`pageNumber=1`)
* **30 objects** (`pageCount=30`)
* **Sorted by creation date** (`sortBy=creationDate`)
* **In chronological order**, so that the most recently created is displayed last (`sortOrder=ASC`)
You need to make the following request:
```bash [CURL]
curl -X GET '{baseUrl}/v1/transfers?pageNumber=1&pageCount=30&sortBy=creationDate&sortOrder=ASC&walletId={walletId}' \
--header 'Authorization: Bearer {accessToken}'
```
Returns an array of `30` objects (or less, in the last page).
```json [JSON]
[
{
"walletId": 28749,
"createdDate": "2019-03-10T08:05:10-00:00",
[...]
},
{
"walletId": 92758,
"createdDate": "2020-08-25T07:08:20-00:00",
[...]
},
{
"walletId": 57820,
"createdDate": "2021-02-03T07:09:33-00:00",
[...]
},
[...] // 27 more objects hidden
]
```
Now, let's retrieve the same list of transfers for the wallet, but with different pagination parameters:
* **5th page** (`pageNumber=5`)
* **50 objects** (`pageCount=50`)
* **Sorted by amount** (`sortBy=amount`)
* **In descending order**, so that the highest amount is displayed first (`sortOrder=DESC`)
You need to make the following request:
```bash [CURL]
curl -X GET '{baseUrl}/v1/transfers?pageNumber=5&pageCount=50&sortBy=amount&sortOrder=DESC&walletId={walletId}' \
--header 'Authorization: Bearer {accessToken}'
```
Returns an array of `50` objects (or less, in the last page).
```json [JSON]
[
{
"walletId": 82749,
"amount": 4298,
[...]
},
{
"walletId": 10855,
"amount": 2310,
[...]
},
{
"walletId": 42187,
"amount": 150,
[...]
},
[...] // 47 more objects hidden
]
```
### Supported endpoints
Usually, endpoints with a `v1` prefix in their path and used to retrieve a list of objects support offset pagination.
* [`/v1/beneficiaries`](/api-reference/api-endpoints.html#tag/Beneficiaries/getBeneficiaries){target="\_self"}
* [`/v1/cards`](/api-reference/api-endpoints.html#tag/Cards/getCards){target="\_self"}
* [`/v1/cardtransactions`](/api-reference/api-endpoints.html#tag/Card%20Transactions/readCardTransaction){target="\_self"}
* [`/v1/countryRestrictionGroups`](/api-reference/api-endpoints.html#tag/Country%20Restriction%20Groups/getCountryRestrictionGroups){target="\_self"}
* [`/v1/documents`](/api-reference/api-endpoints.html#tag/User%20Documents/getDocuments){target="\_self"}
* [`/issuerInitiatedDigitizationDatas`](/api-reference/api-endpoints.html#tag/issuerInitiatedDigitizationData/tavrequestget){target="\_self"}
* [`/v1/mccRestrictionGroups`](/api-reference/api-endpoints.html#tag/MCC%20Restriction%20Groups/getMccRestrictionGroups){target="\_self"}
* [`/v1/merchantIdRestrictionGroups`](/api-reference/api-endpoints.html#tag/Merchant%20ID%20Restriction%20Groups/getMerchantIdRestrictionGroup){target="\_self"}
* [`/v1/recallRs`](/api-reference/api-endpoints.html#tag/Recalls/getRecallRs){target="\_self"}
* [`/v1/taxResidences`](/api-reference/api-endpoints.html#tag/User%20Tax%20Residences){target="\_self"}
* [`/v1/transactions`](/api-reference/api-endpoints.html#tag/Transactions/getTransactions){target="\_self"}
* [`/v1/transfers`](/api-reference/api-endpoints.html#tag/Transfers/getTransfers){target="\_self"}
* [`/v1/users`](/api-reference/api-endpoints.html#tag/Users/getUsers){target="\_self"}
* [`/v1/virtualIbans`](/api-reference/api-endpoints.html#tag/Virtual%20IBANs/getvirtualibans){target="\_self"}
* [`/v1/wallets`](/api-reference/api-endpoints.html#tag/Wallets/getWallets){target="\_self"}
## Cursor-based pagination
Cursor-based pagination works by returning a pointer to a specific item in the dataset. Then, you specify one of the returned cursors in your next request to navigate the datasets.
Unlike offset pagination, cursor-based pagination is not optional. As soon as you make your request to retrieve your list of objects, the results will be paginated and the first page will be displayed by default.
The number of objects returned varies depending on each endpoint. Most endpoints return `50` objects.
### Cursor object
API Responses for endpoints that support cursors include the `cursor` object.
```json [JSON]
"cursor": {
"prev": null,
"current": "356a192b7913b04c54574d18c28d46e6395428ab",
"next": "da4b9237bacccdf19c0760cab7aec4a8359010b0"
}
```
| Attribute | Type | Description |
| --- | --- | --- |
| `prev` | string | Pointer for the previous page. `null` if on the first page. |
| `current` | string | Pointer for the current page. |
| `next` | string | Pointer for the next page. `null` if on the last page. |
If there is no adjacent operation, the `next` attribute will be set to `null`. The `current` attribute can be cached and used later to only retrieve new operations.
### Parameters
[Endpoints supporting cursor-based pagination](#supported-endpoints-1) rely on the `cursor` query parameter for pagination. The size of the subset (number of objects returned) varies depending on each endpoint. Most endpoints return `50` objects.
| Attribute | Description |
| --- | --- |
| `cursor` | The desired starting position for your next subset of objects. |
### Example
When initially using [`{baseUrl}/core-connect/operations`](/api-reference/api-endpoints.html#tag/Operations/getOperations){target="\_self"}, the response returns 50 operations and includes the `cursor` object.
```json [JSON]
"cursor": {
"prev": null,
"current": "356a192b7913b04c54574d18c28d46e6395428ab",
"next": "da4b9237bacccdf19c0760cab7aec4a8359010b0"
}
```
Since there is no `prev` value, we know we are on the first subset of responses. To navigate to the next subset, the `next` value must be used for the `cursor` query parameter, as in the following request:
```bash [CURL]
curl -X GET '{baseUrl}/core-connect/operations?walletId={walletId}&dateFrom={dateFrom}&dateTo={dateTo}&cursor=da4b9237bacccdf19c0760cab7aec4a8359010b0' \
--header 'Authorization: Bearer {accessToken}'
```
This returns the next subset of Operations objects, which will include the `cursor` object again:
```json [JSON]
"cursor": {
"prev": "e99a18c428cb38d5f260853678922e03abd83395",
"current": "da4b9237bacccdf19c0760cab7aec4a8359010b0",
"next": null
}
```
In this example, the `next` value is `null`, indicating that we are on the last subset.
### Supported endpoints
Usually, endpoints with a `core-connect` prefix in their path and used to retrieve a list of objects support cursor-based pagination. Some `v1` endpoints have been migrated to this pagination system too.
* [`/core-connect/cardtransactions`](/api-reference/api-endpoints.html#tag/Card%20Transactions/getCoCardTransactions){target="\_self"}
* [`/core-connect/cardtransactions/{cardId}`](/api-reference/api-endpoints.html#tag/Card%20Transactions/getCoCardTransaction){target="\_self"}
* [`/core-connect/merchantIdRestrictionGroups/{groupId}/mid/metadata`](/api-reference/api-endpoints.html#tag/Merchant%20ID%20Metadata/getAllMidMetadata){target="\_self"}
* [`/core-connect/operations`](/api-reference/api-endpoints.html#tag/Operations/getOperations){target="\_self"}
* [`/v1/payins`](/api-reference/api-endpoints.html#tag/Payins/getPayins){target="\_self"}
* [`/v1/payinrefunds`](/api-reference/api-endpoints.html#tag/Payin%20Refunds/getPayinrefunds){target="\_self"}
* [`/v1/payouts`](/api-reference/api-endpoints.html#tag/Payouts){target="\_self"}
* [`/core-connect/scheduledPayment`](/api-reference/api-endpoints.html#tag/Scheduled%20Payments/getScheduledPayment){target="\_self"}
* [`/core-connect/sca/scawallets`](/api-reference/api-endpoints.html#tag/SCA/getSCAWallets){target="\_self"}
---
---
url: /guide/user-verification/documents-prereview.md
description: >-
Technical guide for pre-reviewing KYC documents via the Treezor API. Includes
required parameters, request structure, and response examples.
---
# Document pre-review
The Documents pre-review process offers another way to upload documents to Treezor. It includes a built-in pre-validation process.
Users upload files through pre-signed forms. These files are stored on dedicated servers while your teams review them. The actual Document objects are created in the Treezor API once the files are validated.
This is the same method as the one used by the [Dashboard](/guide/dashboard/introduction).
**Caution – The Document object is created after pre-validation**
While their structure is similar, [objects](#structure) created during the pre-review process aren't [Document](./documents) object.
## Process
1. The end user requests the necessary form to upload the document with the dedicated request: [`/core-connect/users/{userId}/kyc/document`](/api-reference/api-endpoints.html#tag/User%20Document%20Pre-review/getPreSignedKycForm){target="\_self"}
2. The Treezor API answers with the pre-signed form dedicated endpoint.
3. The end user uploads the document using the pre-signed form.
4. You request the download URL of the uploaded document with the dedicated request:[`/core-connect/kyc/documents/{documentId}/preview`](/api-reference/api-endpoints.html#tag/User%20Document%20Pre-review/getPresignedUrlDocument){target="\_self"}
5. The Treezor API answers with the download URL to use in the allocated time frame.
6. You download the document and expose it to your teams for pre-review.
7. Your team members update the document with the dedicated request:[`/core-connect/kyc/documents/{documentId}/status`](/api-reference/api-endpoints.html#tag/User%20Document%20Pre-review/updateDocument){target="\_self"}When doing so, the corresponding [Document](./documents) object is created in the Treezor API.
8. Once all the documents for a given user are uploaded and pre-validated, you request a review process using the [`/v1/users/{userId}/Kycreview`](/api-reference/api-endpoints.html#tag/User%20KYC%20Review/putKycreview){target="\_self"} endpoint.
**Tip – You can use pre-signed forms without pre-review**
To do so, automate the `PUT /core-connect/kyc/documents/{documentId}/status` request to set the pre-review status to `VALIDATED` and hence creating the Document object in the Treezor API.
## Request the upload form
Make the following request to generate the pre-signed form to upload the document.
```bash [CURL]
curl -X POST '{baseUrl}/core-connect/users/{userId}/kyc/document' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is `{payload}` example for an ID card (`documentTypeId=9`).
```json [JSON]
{
"documentType":9,
"metadata":[]
}
```
Returns the necessary information to upload the document to through the form.
```json [JSON]
{
"documentId": "900f0614-78ff-49e6-90ec-adaa53de7f43",
"form": {
"action": "https:\/\/connect-kyc-files.s3.eu-west-3.amazonaws.com",
"method": "POST",
"enctype": "multipart\/form-data"
},
"formFields": {
"acl": "private",
"key": "1625063017_1370854_9_900f0614-78ff-49e6-90ec-adaa53de7f43_0",
"Content-Type": "",
"X-Amz-Security-Token": "IQo...7x4j", // Truncated for clarity
"X-Amz-Credential": "ASI...est", // Truncated for clarity
"X-Amz-Algorithm": "AWS4-HMAC-SHA256",
"X-Amz-Date": "20210630T142337Z",
"Policy": "eyJ...V19", // Truncated for clarity
"X-Amz-Signature": "5ae...4f7" // Truncated for clarity
},
"expireIn": 300
}
```
**Information – The newly exposed endpoint expires after 300 seconds.**
The file must therefore be uploaded within 5 minutes of this request.
## Upload documents to the form
All the values returned in the previous response are to be used for your request to upload the document:
* The `form` object contains your URL (`action`), `method` and `enctype` for your request.
* The `formFields` object contains the form inputs.
You must provide the document in the `file` input.
**Configuration – Documents must:**
* Abide by size restrictions (file < 4.5Mo)
* Be in mime type: `application/pdf`, `image/jpg`, `image/png`, `image/tiff`, or `image/svg+xml`
```bash [CURL]
curl -X POST 'https://connect-kyc-files.s3.eu-west-3.amazonaws.com/' \
-H 'Content-Type: multipart/form-data' \
--form 'acl="{useValueProvidedInThePreviousResponse}"' \
--form 'key="{useValueProvidedInThePreviousResponse}"' \
--form 'Content-Type="{useValueProvidedInThePreviousResponse}"' \
--form 'X-Amz-Security-Token="{useValueProvidedInThePreviousResponse}"' \
--form 'X-Amz-Credential="{useValueProvidedInThePreviousResponse}"' \
--form 'X-Amz-Algorithm="{useValueProvidedInThePreviousResponse}"' \
--form 'X-Amz-Date="{useValueProvidedInThePreviousResponse}"' \
--form 'Policy="{useValueProvidedInThePreviousResponse}"' \
--form 'X-Amz-Signature="{useValueProvidedInThePreviousResponse}"' \
file=@{theDocumentsPath}
```
Answers with a `204 No Content` [HTTP Status Code](/guide/api-basics/response-codes), signaling that the file was succesfully uploaded.
You may use the [`/core-connect/users/{userId}/kyc/document`](/api-reference/api-endpoints.html#tag/User%20Document%20Pre-review/getKYCDocuments){target="\_self"} request to retrieve the `documentId` necessary for the next step.
## View the document
You must download the file to expose it to your teams for validation. Documents can only be downloaded with the following method during the **pre-review** phase.
**Tip – Files are automatically deleted**
Validated documents are deleted once the user is validated (i.e., you've received a [`user.kycreview`](/guide/user-verification/events#user-kycreview) webhook with the `kycReview` set to `2`).
Use the following request to obtain the URL to view the document.
```bash [CURL]
curl -X GET '{baseUrl}/core-connect/kyc/documents/{documentId}/preview' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json'
```
Returns the following object containing a `url`.
```json [JSON]
{
"url": "https:\/\/dev-connect-kyc-files.s3.eu-west-3.amazonaws.com\/161...4_2?X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Security-Token=IQo...Nce&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ASI...est&X-Amz-Date=20210708T092227Z&X-Amz-SignedHeaders=host&X-Amz-Expires=300&X-Amz-Signature=33b...400",
"contentType": "image\/jpeg",
"duration": 300
}
```
You can now download the file using the `url`.
**Information – The preview URL expires after 300 seconds.**
The file can be viewed for 5 minutes after this request.
## Pre-validate documents
Your teams may either validate of refuse a document by updating its pre-review `status`.
| Value | Status | Description |
| :---: | --- | --- |
| `0` | PENDING | The document hasn't been pre-reviewed yet. |
| `1` | REFUSED | The document was refused during the pre-review. |
| `2` | VALIDATED | The document was validated during the pre-review. As a result, a Document object is created in the Treezor API. |
In addition, the `comment` mandatory attribute allows you to specify why the document is accepted or refused.
### Validation of the document
Here is an example of request to pre-validate the document.
```bash [CURL]
curl -X PUT '{baseUrl}/core-connect/kyc/documents/{documentId}/status' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{
"status": 2,
"comment": "This document is fine" #Avoid special characters
}'
```
Returns the updated object.
```json [JSON]
{
"documentId": "1ca27e96-0cf1-45ba-82ea-404f850c2264",
"documentType": 9,
"status": 2,
"userId": 1370854,
"createdAt": "2021-03-08T14:13:00+00:00",
"metadata": {
"creationdate": "2021-03-08T14:13:00.438Z",
"treezor_document_id": "383597" // Created Document object id
},
"comment": "This document is fine",
"updatedAt": "2021-05-14T11:19:46+00:00"
}
```
Once validated, the corresponding Document object is created in the Treezor API and Treezor sends the corresponding [`document.create`](/guide/user-verification/events#document-create) webhook.
Since the `metadata` may take a few seconds to be populated, you might not receive it with the API response right away. However, the webhook for document creation contains all the information you need.
```json [JSON]
{
"webhook": "document.create",
"object_payload": {
"documents": [
{
"documentId": "383597", // treezor_document_id
"documentTag": "",
"clientId": "929252",
"userId": "1370854",
"userFirstname": "Alex",
"userLastname": "Oak",
"name": "1ca27e96-0cf1-45ba-82ea-404f850c2264", // pre-review document uuid
"documentStatus": "PENDING",
"documentTypeId": "9",
"documentType": "ID",
"fileName": "1012512.png",
"thumbFileName": "",
"createdDate": "2024-07-17 14:34:47",
"modifiedDate": "0000-00-00 00:00:00",
"codeStatus": "600003",
"informationStatus": "",
"residenceId": "0",
"totalRows": 1
}
]
},
"object_id": "1012512",
"object": "document",
"webhook_created_at": 17212196888641,
"webhook_id": "ca1a6f2f-7d2f-46b8-a1dc-b76e5e656ee6",
"object_payload_signature": "IuXf8vyqvswwPKwadf/Encpwe/RiW8ixxxxlLLLM3QY="
}
```
### Refusal of the document
Here is an example of request to refuse the document.
```bash [CURL]
curl -X PUT {baseUrl}/core-connect/kyc/documents/{documentId}/status \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{
"status": 1,
"comment": "This document is not suitable" #Avoid special characters
}'
```
Returns the updated object.
```json [JSON]
{
"documentId": "1ca27e96-0cf1-45ba-82ea-404f850c2264",
"documentType": 9,
"status": 1,
"userId": 1370854,
"createdAt": "2021-03-08T14:13:00+00:00",
"metadata": {
"creationdate": "2021-03-08T14:13:00.438Z"
},
"comment": "This document is not suitable",
"updatedAt": "2021-07-08T09:31:03+00:00"
}
```
## Structure
The file for pre-review is slightly different from the actual [Document object](./documents), starting with the fact that the `documentId` is an UUID and the `status` indicates the pre-validation status.
```json [JSON]
[
{
"documentId": "bb18a003-050c-4acb-b33e-e44f26534b87",
"documentType": 9,
"status": 0,
"userId": 100554428,
"createdAt": "2024-07-15T13:45:48+00:00",
"metadata": [],
"comment": "",
"updatedAt": "2024-07-15T15:48:23+02:00"
}
]
```
## Endpoints
| Endpoint |[Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/core-connect/users/{userId}/kyc/document`](/api-reference/api-endpoints.html#tag/User%20Document%20Pre-review/getPreSignedKycForm){target="\_self"} Create a pre-signed form to upload document | `read_write` |
| [`/core-connect/users/{userId}/kyc/document`](/api-reference/api-endpoints.html#tag/User%20Document%20Pre-review/getKYCDocuments){target="\_self"} Retrieve the pre-review documents for a user | `legal` |
| [`/core-connect/kyc/documents/{documentId}/preview`](/api-reference/api-endpoints.html#tag/User%20Document%20Pre-review/getPresignedUrlDocument){target="\_self"} Retrieve a pre-signed URL to download the document | `legal` |
| [`/core-connect/kyc/documents/{documentId}/status`](/api-reference/api-endpoints.html#tag/User%20Document%20Pre-review/updateDocument){target="\_self"} Update the pre-review document status | `legal` |
| [`/v1/users/{userId}/Kycreview`](/api-reference/api-endpoints.html#tag/User%20KYC%20Review/putKycreview){target="\_self"} Initiate the user [KYC review](/guide/user-verification/introduction) process | `read_write` |
| [`/core-connect/kyc/documents/{documentId}`](/api-reference/api-endpoints.html#tag/User%20Document%20Pre-review/deleteKYCDocumentcument){target="\_self"} Delete a pre-review document | `legal` |
---
---
url: /guide/transfers/proof-of-payout.md
description: >-
Technical guide for generating proof of payout documents via the Treezor API.
Includes required parameters, request structure, and response examples.
---
# Proof of Payout
Proof of Payout are PDF documents that can be generated to prove the creation of a Payout.
## Templates
Proof of Payouts can be templated using Treezor [template feature](/guide/api-basics/templates).
## Retrieval
To retrieve a proof of payout, use the following request.
```bash [CURL]
curl -X GET '{baseUrl}/core-connect/payouts/{payoutId}/proof' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
```
Returns an object containing a download URL (`link`) which **expires after 5 minutes**:
```json [JSON]
{
"link": "https://xxxxxx.s3.eu-west-3.amazonaws.com/tmp/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx.pdf",
"expireIn": 300
}
```
---
---
url: /guide/overview/tinker.md
description: >-
Get a first taste of the Treezor API by following these simple testing steps.
Explore various functionnalities with request and examples, from
authentication to the first payment.
---
# Quickstart
Not sure where to start? Find below the testing steps for you to start exploring the Treezor API capabilities in Sandbox.
**Tip – Rely on Treezor [Webhooks](/guide/webhooks/introduction) and [Dashboard](/guide/dashboard/introduction)**
These tools will allow you to better visualize the results of your testing.
## Authenticate to your Sandbox
**Reading – Related documentation in API Basics**
[Environments](/guide/api-basics/environments) | [Credentials](/guide/api-basics/authentication#credentials) | [Authentication](/guide/api-basics/authentication) | [Scope & Permissions](/guide/api-basics/authentication)
Once you have your `client_id` and `client_secret` for your Sandbox environment, you can generate your JSON Web Token (JWT) that you will use to authenticate your API requests.
```bash [CURL]
curl -X POST '{baseUrl}/oauth/token' \
--form 'grant_type="client_credentials"' \ # required
--form 'client_id=""' \ # required
--form 'client_secret=""' \ # required
# --form 'scope=""' # optional
```
Returns the `access_token` for you to use in the `Authorization` header of all your subsequent requests.
```json [JSON]
{
"token_type": "Bearer",
"expires_in": 3600,
"access_token": "eyJ0eX[...]PcOIkQ"
}
```
**Note – The access token expires after 1 hour**
Read how to extend its lifetime in the [Authentication](/guide/api-basics/authentication) article.
## Create a User
**Reading – Related documentation**
[Users](/guide/users/introduction) | [Physical Users](/guide/users/physical)
In this example, your end user is a physical person to whom you will offer banking services thanks to Treezor.
You can use the following request to create a [physical user](/guide/users/physical).
Endpoint: [`/v1/users`](/api-reference/api-endpoints.html#tag/Users/postUsers){target="\_self"}
Here is a `{payload}` example:
```json [JSON]
{
"userTypeId": 1, // required, 1 is for Physical User
"specifiedUSPerson": 0, // required
"title": "MX",
"firstname": "Alex",
"lastname": "Oak.userStatusValidated", // Suffix to emulate VALIDATED status
"email": "aoak@example.com", // required, must be unique
"address1": "101 Willow lane", // required to create a Card later on
"phone": "+33102030405" // required to create a Card later on
}
```
Returns the new [User](/guide/users/introduction) with its `id` (1545392) that you will use for the next steps.
```json [JSON] {4}
{
"users": [
{
"userId": 8327278,
"userTypeId": 1,
"userStatus": "VALIDATED",
"userTag": "",
"parentUserId": 0,
"parentType": "",
"controllingPersonType": 0,
"employeeType": 0,
"specifiedUSPerson": 0,
"title": "MX",
"firstname": "Alex",
"lastname": "Oak",
"middleNames": "",
"birthday": "",
"email": "alex.oak@example.com",
"address1": "101 Willow lane",
"address2": "",
"postcode": "",
"city": "",
"state": "",
"country": "",
"countryName": "",
"distributionCountry": null,
"phone": "+33102030405",
"mobile": "",
"nationality": "",
"nationalityOther": "",
"placeOfBirth": "",
"birthCountry": "",
"occupation": "",
"incomeRange": "",
"legalName": "",
"legalNameEmbossed": "",
"legalRegistrationNumber": "",
"legalTvaNumber": "",
"legalRegistrationDate": "0000-00-00",
"legalForm": "",
"legalShareCapital": 0,
"entityType": 0,
"legalSector": "",
"legalAnnualTurnOver": "",
"legalNetIncomeRange": "",
"legalNumberOfEmployeeRange": "",
"effectiveBeneficiary": 0,
"kycLevel": 0,
"kycReview": 0,
"kycReviewComment": "",
"isFreezed": 0,
"isFrozen": null,
"language": "",
"optInMailing": null,
"sepaCreditorIdentifier": "",
"taxNumber": "",
"taxResidence": "",
"position": "",
"personalAssets": "",
"personalAssetsRange": 2,
"createdDate": "2024-11-13 07:40:10",
"modifiedDate": "0000-00-00 00:00:00",
"walletCount": 0,
"payinCount": 0,
"totalRows": "1",
"activityOutsideEu": 0,
"economicSanctions": 0,
"residentCountriesSanctions": 0,
"involvedSanctions": 0,
"address3": null,
"timezone": null,
"occupationType": "",
"isOnStockExchange": 0,
"secondaryAddress1": "",
"secondaryAddress2": "",
"secondaryAddress3": "",
"secondaryPostcode": "",
"secondaryCity": "",
"secondaryState": "",
"secondaryCountry": "",
"clientId": "929252",
"sanctionsQuestionnaireDate": null,
"codeStatus": "110009",
"informationStatus": "",
"legalSectorType": "",
"sourceOfFunds": "",
"distributionCountry": null,
"entitySanctionsQuestionnaire": 0,
"occupationCategory": 5,
"monthlyIncomeRange": 2,
"personalAssetsRange": null,
"occupationCategory": null,
"birthCityCode": null
}
]
}
```
**Note – Treezor API offers a variety of Users to fit your use cases**
You could also create other types of users, such as [Legal Entities](/guide/users/legal-entity) and [Anonymous Users](/guide/users/physical#anonymous-users). Users can also be linked by hierarchical relations referred to as [parent-children relations](/guide/users/parent-children).
## Simulate User KYC validation
**Reading – Related documentation**
[User verification (KYC)](/guide/user-verification/introduction) | [KYC Simulation](/guide/user-verification/faking-operations)
In real life, Users must be verified to use Treezor services. This process includes sending documents and declarative data for Treezor to manually approve the User.
In Sandbox, you can use the following request to [force the KYC validation](/guide/user-verification/faking-operations), allowing you to proceed with the next steps.
Endpoint: [`/v1/users/{userId}`](/api-reference/api-endpoints.html#tag/Users/putUser){target="\_self"}
Here is a `{payload}` example with the `.validated` suffix to approve the KYC in Sandbox:
```json [JSON]
{
"lastname": "Oak.validated"
}
```
Returns the new [User](/guide/users/introduction), but you might not see they are verified right away.
You need to make a [`/v1/users/{userId}`](/api-reference/api-endpoints.html#tag/Users/getUser){target="\_self"} call to see the User object with the updated [`kycLevel` and `kycReview`](/guide/user-verification/introduction#user-kyc-levels-kyclevel).
```json [JSON] {3,4}
{
"userId": 1545392,
"kycLevel": "2",
"kycReview": "2"
// [...] some attributes are hidden
}
```
## Create a Wallet
**Reading – Related documentation**
[Wallets](/guide/wallets/introduction) | [Wallet Creation](/guide/wallets/creation)
Let's create a payment account, which is represented by the [Wallet](/guide/wallets/introduction) object in the API. We will define the previously created [User](/guide/users/introduction) as its owner.
Endpoint : [`/v1/wallets`](/api-reference/api-endpoints.html#tag/Wallets/postWallets){target="\_self"}
Here is a `{payload}` example:
```json [JSON]
{
"walletTypeId": 10, // required, 10 = Payment Account Wallet
"userId": 1545392, // required, attach this wallet to the previously created user
"currency": "EUR", // required
"eventName": "AO's Account" // required, name the wallet
}
```
Returns a [Wallet](/guide/wallets/introduction) object, with its `id` (826210) and its ready-to-use [IBAN](/guide/wallets/iban):
```json [JSON] {4,23}
{
"wallets": [
{
"walletId": 2702198,
"walletTypeId": 10,
"walletStatus": "VALIDATED",
"codeStatus": 120005,
"informationStatus": "",
"walletTag": "",
"userId": 1545392,
"userLastname": "Oak.validated",
"userFirstname": "Alex",
"jointUserId": 0,
"tariffId": 136,
"eventName": "AO's Account",
"eventAlias": "ao-s-account-65df2ab48f029",
"eventDate": "2024-03-06",
"eventMessage": "",
"eventPayinStartDate": "2024-02-28",
"eventPayinEndDate": "0000-00-00",
"contractSigned": 0,
"bic": "TRZOFR21XXX",
"iban": "FR7616798000010000270219811",
"urlImage": "",
"currency": "EUR",
"createdDate": "2024-02-28 13:44:36",
"modifiedDate": "0000-00-00 00:00:00",
"payinCount": 0,
"payoutCount": 0,
"transferCount": 0,
"solde": 0,
"authorizedBalance": 0,
"totalRows": 1,
"country": "FR"
}
]
}
```
**Note – Treezor API offers a variety of Wallets to fit your use cases**
There are [different types of wallets](/guide/wallets/introduction), some requiring [KYC validation](/guide/user-verification/introduction), some that don't.
## Credit the Wallet
**Reading – Related documentation**
[Wallets](/guide/wallets/introduction) | [SEPA Transfers](/guide/transfers/introduction) | [SCTR Simulation](/guide/transfers/faking-operations#sctr)
Let's simulate a payin into a [Wallet](/guide/wallets/introduction) by emulating an [incoming SEPA Transfer](/guide/transfers/credit-transfer#received-credit-transfers-sctrs). These fictitious funds will then be useful to further test Treezor abilities, such as payouts to external accounts, or Wallet-to-Wallet transfers.
Here is the simulation request, in which you must pass the IBAN of the wallet to credit and the amount (integer) to credit.
```bash [CURL]
curl -X POST '{baseUrl}/simulation/payin-sct' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`
```json [JSON]
{
"iban": "FR7616798000010001726649397",
"amount": 20
}
```
Returns the `id` of the SCTR, its `txId` (transaction `Id`) and its `payinId`.
```json [JSON]
{
"sctrs": [
{
"id": 10116,
"txId": "1zS0fKXhAuzDnNBL",
"payinId": 1287763,
"returnReasonCode": null
}
]
}
```
**Note – Discover all the ways to credit a Wallet**
Treezor offers a large range of payins for you to credit wallets. Learn more in the [How to credit wallets](/guide/wallets/introduction#how-to-credit-wallets-top-up) article.
## Check the Wallet Balance
**Reading – Related documentation**
[Wallets](/guide/wallets/introduction) | [Balances](/guide/wallets/balances)
Let's make sure the Wallet was properly credited by checking its [Balance](/guide/wallets/balances).
Use the following request to retrieve a given Wallet Balance, with the corresponding `walletId` expected as a query parameter.
Endpoint: [`/v1/balances/{walletId}`](/api-reference/api-endpoints.html#tag/Balances/getBalances){target="\_self"}
```bash [CURL]
curl -X GET '{baseUrl}/v1/balances?walletId=826210' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
```
Returns the Balance object, with both the [Authorized Balance](/guide/wallets/balances) (`authorizedBalance`) and [Balance](/guide/wallets/balances) (`currentBalance`).
```json [JSON]
{
"balances": [
{
"walletId": 826210,
"currentBalance": 50, // Actual Balance, as credited in the previous step
"authorizations": 0, // Currently pending authorizations
"authorizedBalance": 50, // Balance, minus pending authorizations
"currency": "EUR", // Currency of the balance
"calculationDate": "2024-02-01 15:52:40" // When the Balance was last actualized
}
]
}
```
**Tip – Balance History is available**
The dedicated [Balance History endpoint](/guide/wallets/balances#check-the-balance-history) gives the Balance evolution over time.
## Create a Beneficiary
**Reading – Related documentation**
[Beneficiaries](/guide/transfers/beneficiaries) | [SEPA Transfers](/guide/transfers/introduction)
To send money to bank accounts outside your Treezor environment, you must create a [Beneficiary](/guide/transfers/beneficiaries) beforehand.
Endpoint: [`/v1/beneficiaries`](/api-reference/api-endpoints.html#tag/Beneficiaries/postBeneficiary){target="\_self"}
```bash [CURL]
curl -X POST '{baseUrl}/v1/beneficiaries' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"userId": 123456, // required, user ID allowed to use the beneficiary
"name": "Chris Oak", // Name of the Beneficiary
"tag": "oak-1982", // Custom field you're free to populate
"nickName": "C. Oak checking", // Alias of the Beneficiary
"address": "Woods Bank",
"iban": "FR7616798000010000012345678", // required, IBAN of the Beneficiary
"bic": "TRZOFR21XXX", // required, BIC of the Beneficiary
"usableForSct": true // required, if the Beneficiary can be used for SCT
}
```
Returns the [Beneficiary](/guide/transfers/beneficiaries) object, with its `id` allowing you to send funds to it using a Payout.
```json [JSON]
{
"id": 11XXXX8,
"tag": "oak-1982",
"userId": 22XXXX6,
"nickName": "C. Oak checking",
"name": "Chris Oak",
"address": "Woods Bank",
"iban": "2XXXXXXXX X X 7XXXXXXXXX5 X X 75XXXXXXXX6 X X 1XXXXX4",
"bic": "BNPAFRPP",
"sepaCreditorIdentifier": "",
"sddB2bWhitelist": [],
"sddCoreBlacklist": [],
"usableForSct": true,
"sddCoreKnownUniqueMandateReference": [],
"isActive": true
}
```
## Request the Beneficiary validation
**Reading – Related documentation**
[Beneficiaries](/guide/transfers/beneficiaries) | [Beneficiary validation (VoP)](/guide/transfers/beneficiaries#beneficiary-validation-vop)
The [Verification of Payee (VoP)](/guide/overview/glossary#verification-of-payee-vop) is a legal obligation for the initiator of a SEPA transfer to verify that the beneficiary’s name and IBAN match the information registered at their bank.
Endpoint: [`/v1/beneficiaries/validation`](/api-reference/api-endpoints.html#tag/Beneficiaries/postBeneficiaryVerification){target="\_self"}
```bash [CURL]
curl -X POST '{baseUrl}/v1/beneficiaries/validation' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is a `{payload}` example:
```json [JSON]
{
"beneficiaryName": "{Full name; identical to Beneficiary object}",
"beneficiaryIBAN": "{IBAN; identical to Benefiacry object}"
}
```
Returns the following beneficiary validation object if successful.
```json [JSON]
{
"beneficiaryValidationId": "f8e4a7b2-c1d3-4e5a-8b0f-9c2d1e0a3b5c",
"createdDate": "2025-08-29T16:52:27.379Z",
"vop": {
"result": "CMTC",
"matchedName": "Chris Oak",
"reasonCode": "",
"recurrenceType": "default"
}
}
```
The `beneficiaryValidationId` is to be included in the next step.
See [Beneficiary validation emulation](/guide/transfers/faking-operations.html#beneficiary-validation-result) for VoP mock values to test the different results.
## Send funds to an external account
**Reading – Related documentation**
[Wallets](/guide/wallets/introduction) | [SEPA Transfers](/guide/transfers/introduction)
This sends funds from the created [Wallet](/guide/wallets/introduction), to the created [Beneficiary](/guide/transfers/beneficiaries) using a [SEPA transfer](/guide/transfers/introduction).
Endpoint: [`/v1/payouts`](/api-reference/api-endpoints.html#tag/Payouts/postPayout){target="\_self"}
```json [JSON]
{
"walletId": 826210, // required, the wallet to debit
"beneficiaryId": {beneficiaryId}, // required, id of the beneficiary created in the previous step
"beneficiaryValidationId": "{beneficiaryValidationId}", // required, id of the beneficiary validation created in the previous step
"amount": 11.56, // required
"currency": "EUR" // required
}
```
Returns a Payout object with its `id`.
```json [JSON]
{
"payoutId": "",
"payoutTag": "",
"payoutStatus": "PENDING",
"payoutTypeId": ,
"payoutType": "",
"walletId": ,
"payoutDate": "",
"walletEventName": "",
"userId": ,
"beneficiaryId": ,
"amount": "",
"currency": ""
// [...] some attributes are hidden
}
```
**Tip – SEPA Direct Debit also available**
You could also use [Direct Debit](/guide/transfers/direct-debit#received-direct-debits-sddr) to debit funds from the Wallet to an external account.
## Simulate the Payout validation
In Sandbox, the SCTE payout stays in the `PENDING` status unless you make the following API call.
Endpoint: [`/simulation/payouts/{payoutId}`](/api-reference/api-endpoints.html#tag/Payouts/putSimuScte){target="\_self"}
```bash [CURL]
curl -X PUT '{baseUrl}/simulation/payouts/{payoutId}' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is a `{payload}` example.
```json [JSON]
{
"payoutStatus": "VALIDATED" // or CANCELED
}
```
Returns the following information if successful.
```json [JSON]
{
"payoutId": "12345",
"payoutStatus": "VALIDATED",
"payoutTypeId": 1,
"payoutTag": "string"
}
```
## Send funds to another Wallet
**Reading – Related documentation**
[Wallets](/guide/wallets/introduction) | [Wallet-to-Wallet Transfers](/guide/transfers/wallet-to-wallet)
You can also transfer funds from one [Wallet](/guide/wallets/introduction) to another in your Treezor environment.
Endpoint: [`/v1/transfer`](/api-reference/api-endpoints.html#tag/Transfers/postTransfers){target="\_self"}
```bash [CURL]
curl -X POST '{baseUrl}/v1/transfers' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is a `{payload}` example:
```json [JSON]
{
"walletId": 826210, // required, source wallet for the transfer
"beneficiaryWalletId": 123456, // required, destination wallet for the transfer
"amount": 21.25, // required
"currency": "EUR" // required
}
```
Returns a Transfer object.
```json [JSON]
{
"transfers": [
{
"transferId": 4269222,
"transferStatus": "VALIDATED",
"transferTag": "",
"walletId": 826210,
"walletTypeId": 10,
"beneficiaryWalletId": 2301937,
"beneficiaryWalletTypeId": 10,
"walletEventName": "Account A",
"walletAlias": "account-63346a643a7fa",
"beneficiaryWalletEventName": "Main account",
"beneficiaryWalletAlias": "main-account-64ad18c128f29",
"amount": "21.25",
"currency": "EUR",
"label": "",
"transferTypeId": 1,
"createdDate": "2024-02-07 14:17:51",
"modifiedDate": "2024-02-07 14:17:51",
"totalRows": null,
"foreignId": null,
"partnerFee": null,
"codeStatus": "150005",
"informationStatus": null,
"metadata": null
}
]
}
```
You can now [recheck the balance](#check-the-balance-of-the-wallet) of the Wallet.
## Create a Card to make payments
**Reading – Related documentation**
[Cards](/guide/cards/introduction) | [Card Program](/guide/cards/introduction#card-program) | [Card Creation](/guide/cards/creation)
If you already have a `cardPrint` provided once your [Card Program](/guide/cards/introduction#card-program) is set up, you can test the creation of [Virtual Card](/guide/cards/introduction) and/or [Physical Cards](/guide/cards/introduction).
Let's take the example of the [Virtual Card](/guide/cards/introduction) creation.
Endpoint: [`/v1/cards/CreateVirtual`](/api-reference/api-endpoints.html#tag/Cards/postCardVirtual){target="\_self"}
Here is an example of `{payload}`:
```json [JSON]
{
"userId": 1545392, // required, card owner
"walletId": 826210, // required, wallet to which the card will be associated
"permsGroup": "TRZ-CU-016", // required, defines a set of permissions for the card
"cardPrint": "{cardPrint}" // required, as a string, defines your card program and card design
}
```
Returns a Card object with its `id`, expiration date, [CVV](/guide/overview/glossary#card-verification-number-cvc), etc.
```json [JSON]
{
"cardId": "10xxxx4",
"userId": "22xxxx7",
"walletId": "2xxxxx1",
"walletCardtransactionId": "2xxxxx1",
"expiryDate": "2023-06-30",
"CVV": "757",
"physical": "0"
// [...] some attributes are hidden
}
```
**Note – A lot of options come with your Card Product**
You can set [withdrawals and payments limits](/guide/cards/restrictions-limits#payment-withdrawal-limits), [options for payments](/guide/cards/restrictions-limits#options-permission-groups), restrictions based on [countries](/guide/cards/restrictions-limits#country-restrictions), [business categories](/guide/cards/restrictions-limits#mcc-restrictions), and [merchants](/guide/cards/restrictions-limits#mid-restrictions). You can also [digitize cards](/guide/cards/x-pay-google-apple) with Apple Pay, Google Pay and Samsung Pay.
## Simulate a Card Transaction
**Reading – Related documentation**
[Cards](/guide/cards/introduction) | [Card Transactions](/guide/cards/transactions#card-program) | [Card Transaction simulation](/guide/cards/faking-operations)
Now that you've created a Virtual Card, you may simulate a Card Transaction.
```bash [CURL]
curl -X POST '{baseUrl}/simulation/cardtransactions' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
--data-raw '{payload}'
```
Here is a `{payload}` example:
```json [JSON]
{
"publicToken": "103020378",
"date": "2022-02-12 13:00:00",
"amount": 15.90,
"mcc": "8574",
"merchantId": "3256",
"merchantName": "Merchant Name",
"paymentStatus": "A",
"paymentCode": "100000000000004"
}
```
The request returns a `201` HTTP Status Code without any content.
**Note – Disclaimers about simulating card transactions**
* No Wallet balance update: sends a [`balance.update`](/guide/wallets/events#balance-update) webhook with `0` values.
* No refunds and negative amount settlements support yet.
---
---
url: /guide/user-verification/kyc-request.md
description: >-
Technical guide for making a KYC request via the Treezor API. Includes
required parameters, request structure, and response examples.
---
# KYC Request
Prior to requesting a KYC Review for a user, make sure that:
* All the necessary declarative data has been provided in the [User](/guide/users/introduction) object
* All the necessary [Documents](/guide/user-verification/documents) have been uploaded and checked
* The country of [tax residency](/guide/users/tax-residence) has been properly declared
**Best practice – Submitting a KYB must be done for all users at once**
The legal entity, its legal representative and shareholders are reviewed as a whole. You can submit the legal entity KYB request only once you have provided all the required documents for all the corresponding users.
The more you abide by the rules of verification, the more efficient Treezor teams will be in verifying your users, allowing for a much smoother experience.
## Request a review of the user
Endpoint: [`/v1/users/{userId}/Kycreview`](/api-reference/api-endpoints.html#tag/User%20KYC%20Review/putKycreview){target="\_self"}
```bash [CURL]
curl -X PUT '{baseUrl}/v1/users/{userId}/Kycreview' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json'
```
It returns the User object, with its `kycLevel` set to `0` **(NONE)** and `kycReview` set to `1` **(PENDING)**.
```json [JSON]
{
"users": [
{
"userId": "1611975",
"userTypeId": "1",
"kycLevel": "0", // <--- 0 means NONE
"kycReview": "1", // <--- 1 means PENDING
"kycReviewComment": "", // <--- No comment has been set by Treezor yet
[...] // some attributes are hidden
}
]
}
```
Treezor also sends a [`user.kycrequest`](./events#user-kycrequest) webhook. Once the user refused or validated, you receive a [`user.kycreview`](./events#user-kycreview) webhook.
**Information – Treezor's Compliance team verifies your company in Production**
Verification usually takes about 24h, but may take up to 48h or more (working days only).
---
---
url: /guide/users/restricted-users.md
description: >-
Understand the restrictions that may be placed upon end users as part of your
obligations to prevent the misuse of the financial system for illegitimate
purposes. Includes required parameters, request structure, and response
examples.
---
# Restricted Users
## Introduction
The obligations placed on banking services providers aim to prevent the misuse of the financial system for illegitimate purposes, as stated by the [anti-money laundering and countering the financing of terrorism (AML/CFT)](/guide/overview/glossary#anti-money-laundering-and-countering-the-financing-of-terrorism-aml-cft) rules.
In this context, Treezor may restrict the usage of the API to some Users to provide a compliant and secure banking ecosystem.
### Types of User restrictions
There are 2 ways a user may be under restrictions:
| Restriction type | Field | Usage |
| ---- | --- | --- |
| [Freeze](#freeze) | `isFrozen` | Allows operational teams to block the user’s assets, preventing most payout operations from their wallets. This feature may be open for as an operational tool. |
| [Legal Freeze](#legal-freeze) | Not exposed | Freezes the user’s assets, preventing funds from being debited from their Wallets. Treezor freezes assets when the user is deemed unfit to use banking services based on AML/CFT regulations. This feature is only open to Treezor. |
**Important – Don’t share their blocked status with end users**
Due to legal implications, you mustn’t let your users know if their assets are frozen.
### Blocked operations
When a User is blocked, some operations on their Wallets are no longer possible while others are still permitted.
Below is the list of available operations by user restriction status.
| Operation | Type | `isFrozen` | `IsLegalFrozen` |
| --- | --- | :---: | :---: |
| Card transactions | Payout | | |
| Emitted wallet-to-wallet transfers | Payout | | |
| Received wallet-to-wallet transfers | Payin | | |
| Emitted SEPA Credit Transfers (including SCTE Inst) | Payout | | |
| Received SEPA Credit Transfers (including SCTR Inst) | Payin | | |
| Emitted SEPA Direct Debit | Payin | | |
| Received SEPA Direct Debit | Payout | | |
| Card acquiring | Payin | | |
| Check cashing | Payin | | |
Operations such as SEPA Recalls & RROs, as well as Refunds may be enabled or not depending on the situation, and may be manually checked by Treezor teams prior to blocking.
## Freeze
When a User is blocked with the `isFrozen` status, all payout operations **except** SDDR are forbidden while it’s still possible to credit their Wallet with payins.
Also, Treezor notifies you through a `user.update` webhook with the `isFreezed` field valued to `1` when a user is blocked.
### Block a User
This endpoint is only available if you’re a [Regulated Institution](/guide/overview/glossary#regulated-institution). If you’re not, you may contact Treezor for any action relative to blocking/unblocking users.
#### Parameters
| Attribute | Type | Description |
| --- | --- | --- |
| `isFrozen` | integer | Indicates whether to freeze or unfreeze the user. `0` – The User isn’t frozen `1` – The User is frozen|
| `comment` | string | Explanation for the blocked status of the user. You can’t retrieve this value afterward. |
#### Request
You can use the following request with the `admin` scope to freeze/unfreeze a user.
```bash [CURL]
curl -X PUT '{baseUrl}/v1/users/{userId}/FreezeAssets' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"isFrozen": 1,
"comment": "Mandatory comment explaining the reason for freezing"
}
```
Returns the User object, with the corresponding `isFrozen` attribute updated accordingly.
## Legal Freeze
This endpoint is only available if you’re a [Regulated Institution](/guide/overview/glossary#regulated-institution). If you’re not, you may contact Treezor for any action relative freeze and unfreeze a user's assets.
When a User has the `IsLegalFrozen` status, all payout operations **including** SDDR are forbidden while it’s still possible to credit their Wallet with payins.
Treezor notifies you through a `user.update` webhook with the `IsLegalFrozen` field valued to `1`.
---
---
url: /guide/strong-customer-authentication/authenticating.md
description: >-
Technical guide for authenticating in the name of your end user for SCA. Learn
how to obtain your SCA proof (JWS) and use it to request a JWT to
authenticate. Includes required parameters, request structure, and response
examples.
---
# SCA Authentication
## Key principles
Before the SCA mechanism, all your requests to the Treezor API were made using the same [authentication token](/guide/api-basics/authentication).
To leverage the SCA mechanism, your requests to the Treezor API will have to be made ***in the name of*** each end user, using a distinct authentication token.
```mermaid
flowchart LR
A("End User A")
B("End User B")
C("End User C")
D("Your back end")
F("Treezor API")
A --> D
B --> D
C --> D
D -- User A's JWT --> F
D -- User B's JWT --> F
D -- User C's JWT --> F
class D dark;
class F neutral;
```
To make requests in the name of the end user, you:
1. [Obtain an SCA Proof](#obtain-an-sca-proof) in the form of a JSON Web Signature (JWS) using the [Mobile SDK](sdk) or [Web Native](introduction#web-native) on the end user's device.
2. Provide this SCA Proof and a different [grant type](#parameters) when [requesting a JWT](#request-the-end-user-s-jwt).
3. Use this JWT to authenticate all future requests to the Treezor API made in the name of that end user.
Depending on the type of SCA Proof provided, the JWT will contain a `trz:sca` attribute valued to:
* `false` if the provided SCA was of type `None`.
* `true` if any stronger type of authentication was used (Biometry, Passcode, etc.).
**Information – SCA type other than `None` required every 180 days**
The end user is required to authenticate using a stronger SCA type (Biometry, Passcode, etc.) if no authentication using an SCA type other than `None` occurred in the last 180 days.
## Obtain an SCA Proof
**Prerequisites – Users must be enrolled first**
For both the mobile and web native solutions, the user must have an active SCA Wallet. See [Enrolling users](user-enrollment) for more information.
### Mobile signature
SCA proof capabilities are provided by the SDK via `CustomerAuthenticatedSignature`, it produces a signature once the user has performed the required authentication. This signature is generated locally within Entrust SDK and is returned to the hosting app.
`CustomerAuthenticatedSignature` must first be instantiated with the following parameters.
| Parameter | Description |
| --- | --- |
| `patternName` | The name of the authentication pattern to use for this authentication. Can be:`patterns.NONE.name` for none authentication`patterns.PIN.name` for PIN authentication`patterns.BIOMETRY.name` for Biometric authentication |
| `message` | The message to display to the customer. Must be set if the SDK is used to display the UI. In any case, this information is part of the signed data. |
| `signatureType` | Type of signature result to generate. You must use the `CustomerAuthenticatedSignatureType.LocalJws` option. |
| `signatureInputData` | Custom, context-related information that is part of [the signed data](sdk#payload). |
Once instantiated, you must call `CustomerAuthenticatedSignature#sign()` to start the signature process.
When the `CustomerAuthenticatedSignature` is successfully completed, you're notified by the `CustomCustomerAuthenticatedProcessCallback#onProcessSuccess()` callback. The generated signature result can be fetched by calling `CustomerAuthenticatedSignature#getResult()`.
See the SDK [Signature](/guide/strong-customer-authentication/sdk#signature) article for more information.
After [connecting to an SCA Wallet](sdk-abstraction#connect-to-an-sca-wallet), you can generate an SCA proof with or without user action.
```js [JavaScript - Without user action]
// Generate a JWS to make session calls
const signature = await sign();
const decoded = jwtDecode(signature);
console.info(decoded);
```
```js [JavaScript – With user action]
// Generate a JWS to make session calls
const signature = await sign({ type: 'authenticate' });
const decoded = jwtDecode(signature);
console.info(decoded);
```
### Web Native signature
Once the browser has undergone the [enrollment](user-enrollment#web-native-enrollment), it is able to produce SCA signatures.
SCA enforcement requires that all request to the Treezor API be made [in the name of the User](#key-principles). Therefore, when obtaining a JWT, you must now provide an SCA proof.
The following code snippet shows how to generate an SCA proof that can then be used to obtain a JWT.
```js [JavaScript]
const publicKeyCredentialRequestOptions = {
challenge: convertToArrayBuffer(JSON.stringify({ iat: Date.now() })),
// for the login step, you must strictly provide the challenge above
allowCredentials: [
{
id: base64URLStringToBuffer(publicKeyCredentialId), // publicKeyCredentialId from "authenticationMethods" on the scawallets of the user
type: type, // type from "authenticationMethods" on the scawallets of the user
transports: transports // transports [] from "authenticationMethods" on the scawallets of the user
}
],
// the list of active scawallets of the user with "settingsProfile": "webauthn"
timeout: 60000,
// time in milliseconds for the end user to complete the WebAuthn flow
rpId: 'www.example.com',
// the current FQDN, must be the same used during enrollment flow
userVerification: 'required' // Passcode isn't required in that case, other case are 'preferred' or 'discouraged' with required passcode
};
const assertion = await navigator.credentials.get({
publicKey: publicKeyCredentialRequestOptions
});
const response = assertion.response;
const rawId = arrayBufferToBase64Url(assertion.rawId).toString();
const clientDataJSON = arrayBufferToBase64Url(
assertion.response.clientDataJSON
).toString();
const authenticatorData = arrayBufferToBase64Url(
response.authenticatorData
).toString();
const signature = arrayBufferToBase64Url(response.signature).toString();
const userHandle = arrayBufferToBase64Url(response.userHandle).toString();
let encodedResponse = btoa(
JSON.stringify({
response: {
authenticatorData,
clientDataJSON,
signature,
userHandle,
},
id: assertion.id,
rawId,
type: "public-key",
})
);
```
Details of `base64URLStringToBuffer` method.
```js [JavaScript]
export function base64URLStringToBuffer(base64URLString: string): ArrayBuffer {
// Convert from Base64URL to Base64
const base64 = base64URLString.replace(/-/g, "+").replace(/_/g, "/");
/**
* Pad with '=' until it's a multiple of four
* (4 - (85 % 4 = 1) = 3) % 4 = 3 padding
* (4 - (86 % 4 = 2) = 2) % 4 = 2 padding
* (4 - (87 % 4 = 3) = 1) % 4 = 1 padding
* (4 - (88 % 4 = 0) = 4) % 4 = 0 padding
*/
const padLength = (4 - (base64.length % 4)) % 4;
const padded = base64.padEnd(base64.length + padLength, "=");
// Convert to a binary string
const binary = atob(padded);
// Convert binary string to buffer
const buffer = new ArrayBuffer(binary.length);
const bytes = new Uint8Array(buffer);
for (let i = 0; i < binary.length; i++) {
bytes[i] = binary.charCodeAt(i);
}
return buffer;
}
```
Request the User to enter their passcode and encrypt it (only required if user verification was not performed during authentication).
```js [JavaScript]
const encryptedPassCode = encryptPasscode(passCode)
// see Passcode encryption section below regarding how to encrypt the passcode
```
Then, depending on whether you're using a passcode:
```js [With userVerfication (JavaScript)]
const sca = `${encodedResponse}`
```
```js [With passcode (JavaScript)]
const sca = `${encryptedPassCode}.${encodedResponse}` // concatenate these values with a dot
```
## Request the end user's JWT
### Parameters
| Parameter | Description |
| --- | --- |
| `client_id` | The `client_id` as per your [usual authentication flow](/guide/api-basics/authentication). |
| `client_secret` | The `client_secret` as per your [usual authentication flow](/guide/api-basics/authentication). |
| `username` | The `userId` or the end user's email, as used in [User](/guide/users/introduction) objects |
| `password` | A hash to be generated by concatenating `userId` with `client_secret` and hashing the string using `sha256` i.e., `sha256(userIdclient_secret)`. |
| `grant_type` | Must be set to `delegated_end_user`. |
| `sca` | The SCA proof (which can be generated using a type [`None`](sdk#methods) if a stronger type was used in the last 180 days). |
In return, Treezor provides you with a JWT for all subsequent requests to the Treezor API made in the name of that User. It must be placed in the `Authorization: Bearer` header as described in the [Authentication](/guide/api-basics/authentication#using-the-token) article.
### Request example
```bash [With userVerification (CURL)]
curl -X POST '{baseUrl}/oauth/token' \
--form 'grant_type="delegated_end_user"' \
--form 'client_id="{clientId}"' \
--form 'client_secret="{clientSecret}"' \
--form 'scope="read_write"' \
--form 'username="101109094"' \
--form 'password="bc6ead2bbcd9cc409ba53d9cfbf145a667647414eae496xxxx75636b15384a8"' \
--form 'sca="WQBp_Xg7w"'
```
```bash [With passcode (CURL)]
curl -X POST '{baseUrl}/oauth/token' \
--form 'grant_type="delegated_end_user"' \
--form 'client_id="{clientId}"' \
--form 'client_secret="{clientSecret}"' \
--form 'scope="read_write"' \
--form 'username="101109094"' \
--form 'password="bc6ead2bbcd9cc409ba53d9cfbf145a667647414eae496xxxx75636b15384a8"' \
--form 'sca="eyJh_NDN9.WQBp_Xg7w"'
```
Returns the Bearer token:
```json [JSON]
{
"token_type": "Bearer",
"expires_in": 3600,
"access_token": "eyJ0_XXX_q44Q"
}
```
## Make requests in the name of the end user
Here is an example for creating a Beneficiary (per-operation SCA, so you need another SCA proof prior to this action).
```bash [CURL]
curl -X POST '{baseUrl}/v1/beneficiaries' \
--header 'Authorization: Bearer eyJ0_XXX_q44Q' \
--header 'Content-Type: application/json'\
--data '{payload}'
```
With the following `{payload}`:
```json [JSON]
{
"userId": "101109094",
"name": "Alex Oak",
"adress": "33 av de Wagram Paris",
"iban": "FR1130003000305928344XXXXX",
"bic": "SOGEFRPPXXX",
"usableForSct": true,
"sca": "eyJh_UxfQ.nNIH_n9kA" // SCA proof that you need as a prerequisite (example with passcode)
// Alernatively userVerification: "sca":"nNIH_n9kA"
}
```
Returns the Beneficiary object:
```json [JSON]
{
"beneficiaries": [
{
"id": 527977,
"tag": "",
"userId": 101109094,
"nickName": "",
"name": "Alex Oak",
"address": "",
"iban": "3537524356444355504255444055564B574C405157455041XXXX",
"bic": "SOGEFRPPXXX",
"sepaCreditorIdentifier": "",
"sddB2bWhitelist": [],
"sddCoreBlacklist": [],
"usableForSct": true,
"sddCoreKnownUniqueMandateReference": [],
"isActive": true,
"createdDate": "2024-11-21 08:05:56",
"modifiedDate": "2024-11-21 08:05:56",
"metadata": {
"iban": "FR1130003000305928344XXXXX"
}
}
]
}
```
---
---
url: /guide/strong-customer-authentication/errors.md
description: >-
Troubleshoot and handle strong customer authentication-related issues using
the Treezor API's complete list of error messages and codes, and their
corresponding meanings.
---
# Errors
Find below the codes and messages for SCA-related errors.
## Authentication errors
| HTTP | `code` | `message`| Description |
| :---: | --- | --- | --- |
| 400 | `authentication_error` | The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed. | The SCA proof is missing |
| 403 | `sca_forbidden` | The authentication requires a valid ScaProof. | The SCA proof is older than 180 days. |
| 400 | `authentication_error` | The user credentials were incorrect. | No SCA proof recorded during the last 180 days. |
## SCA Proof errors
| HTTP | `code` | `message`| Description |
| :---: | --- | --- | --- |
| 500 | `sca_error` | The SCA wallet does not belong to the user. | |
| 403 | `sca_forbidden` | Delay between SCA proof and JWT creation is over. | SCA proof has expired. |
| 400 | `sca_bad_request` | The sca proof is already used. | SCA proofs must be unique. |
| 401 | `sca_unauthorized` | The SCA proof must come from the same ScaWallet used to generate your JWT. | Mismatch between the SCA wallet and the SCA proof. |
| 403 | `sca_forbidden` | The ScaWallet must be active and not locked. | |
| 500 | `sca_error` | The ScaProof is invalid. | Mobile SDK only. The SCA proof is either not properly formatted or not readable. |
| 500 | `sca_error` | The certificate from sca proof cannot be parsed. | Mobile SDK only. |
| 500 | `sca_error` | The certificate of the ScaProof is expired. | Mobile SDK only. |
| 500 | `sca_error` | The identifier of the ScaProof is invalid.| Mobile SDK only. |
| 500 | `sca_error` | The amr of the ScaProof is invalid. | Mobile SDK only. |
| 500 | `sca_error` | The sub value of the ScaProof is invalid | Mobile SDK only. |
| 500 | `sca_error` | The ScaProof signature is invalid | Mobile SDK only. |
| 500 | `sca_error` | The ScaProof is expired or iat is in the future | Mobile SDK only. |
| 500 | `sca_error` | No Entrust public keys were retrieved. | Mobile SDK only. |
| 500 | `sca_error` | The ScaProof certificate cannot be verified. | Mobile SDK only. |
| 500 | `sca_error` | The ScaProof is invalid. | Web Native only. |
| 500 | `sca_error` | An error occurred while decrypting the passcode. | Web Native only. |
| 500 | `sca_error` | The user has no passcode registered. | Web Native only. |
| 500 | `sca_error` | The passcode is not valid. | Web Native only. |
| 500 | `sca_error` | The data are not valid. | Web Native only. |
| 500 | `sca_error` | Unable to load the data | Web Native only. |
| 500 | `sca_error` | The SCA Wallet is not found | Web Native only. |
| 500 | `sca_error` | The SCA wallet has no authenticator to validate the SCA proof. | Web Native only. |
| 500 | `sca_error` | The SCA proof is invalid. | Web Native only. |
## Per-operation SCA errors
| HTTP | `code` | `message`| Description |
| :---: | --- | --- | --- |
| 400 | `sca_bad_request` | The sca field is required. | |
| 401 | `sca_unauthorized` | The sca proof is invalid. | |
| 400 | `sca_bad_request` | The sca proof amr is invalid. | |
| 400 | `sca_bad_request` | The sca proof is invalid. | The SCA proof message URL is missing. |
| 400 | `sca_bad_request` | The message in the sca proof is invalid. | The SCA proof message body is missing or not readable. |
| 400 | `sca_bad_request` | The message in the sca proof is invalid. | The SCA proof message is not valid. |
## Per-session SCA errors
| HTTP | `code` | `message` |
| :---: | --- | --- |
| 403 | `sca_forbidden` | The ScaWallet must be active and not locked. |
| 401 | `sca_session_expired` | Your session has expired. |
## SCA Wallet errors
| HTTP | `code` | `message` | Description |
| :---: | --- | --- | --- |
| 400 | `input_validation_error` | webauthn is invalid. | Web Native only. |
| 400 | `input_validation_error` | passcode is invalid. | Web Native only. |
| 400 | `input_validation_error` | The password must be at least 6 characters | Web Native only. |
| 400 | `functional_error` | The maximum number of scaWallets is reached | |
| 400 | `input_validation_error` | The passcode is already defined. | Web Native only. |
| 400 | `input_validation_error` | The maximum number of scaWallets is reached for userId `{userId}`. | |
| 400 | `functional_error` | The sca field is required. | |
| 400 | `functional_error` | The ScaWallet is deleted. | When attempting to lock the SCA Wallet. |
| 400 | `input_validation_error` | The ScaWallet is already locked. | |
| 403 | `functional_error` | The user `{userId}` is not authorized. | |
| 403 | `authorization_error` | Forbidden access for the current scope | |
| 404 | `resource_not_found_error` | The resource was not found | The SCA Wallet not found |
| 400 | `input_validation_error` | The ScaWallet is already unlocked. | |
| 400 | `input_validation_error` | The ScaWallet is deleted. | When attempting to unlock or delete the SCA Wallet. |
| 400 | `unexpected_error` | The wallet with identifier `{walletId}` is not active. | |
| 400 | `input_validation_error` | The new passcode and confirm passcode do not match. | |
| 400 | `input_validation_error` | The user has no passcode defined. | |
| 400 | `input_validation_error` | The ScaWallet is already deleted. | When attempting to swap SCA Wallets. |
| 400 | `input_validation_error` | The passcode field is required when WebAuth process did not perform User Verification. |
## External Operation errors
| HTTP | `code` | `message` |
| :---: | --- | --- |
| 400 | `functional_error` | ResourceIds is required |
| 400 | `input_validation_error` | The resource ids field is required when action name is externalGetStatement. |
| 400 | `functional_error` | Update of `{actionName}` is not allowed |
| 400 | `input_validation_error` | The following resource are already saved : `{resource_id}` |
---
---
url: /guide/strong-customer-authentication/sdk-abstraction.md
description: >-
Technical guide for configuration and usage of React abstraction layer of the
Mobile SDK. Includes JavaScript code examples.
---
# Mobile Abstraction Layer
Treezor provides a React abstraction layer that lives above the [Mobile SDK](sdk).
This wrapper allows you to implement SCA features more easily than via the SDK directly.
**Alert – The abstraction layer is provided “as is”**
Contrary to the [SDK](sdk), this abstraction layer is provided “as is” without any warranty.
To use it, you have to:
* Import `react-native-treezor-sca` using credentials provided by Treezor.
* Import `bridge-reactNative-{version}` provided to you encrypted using GPG.
Using `npm install -S {package}` or `yarn add {package}`.
## iOS SDK Configuration
**Reading – iOS SDK configuration guide is available**
This section is to be read along with the iOS SDK full documentation. Contact Treezor if you don't have access to the partner's integration guides yet.
**Prerequisites – Requires Apple Developer Account**
You need a valid Apple Developer Account to achieve a valid configuration, as well as an up-to-date membership in Apple Developer Program (see [Apple Membership](https://developer.apple.com/support/compare-memberships/)).
You need the following Apple Capabilities to work with the SDK:
* **Push Notifications** – Required for SCA Wallet activation (silent push) and for authentication request (classic push)
* **App Groups** – Required to decrypt an authentication request and present decrypted content to iOS Push System.
If you're unfamiliar with how to configure these capabilities, you can either refer to the 2.3 section of the SDK documentation or go through the configuration steps listed below.
In your Apple [Developer Portal](https://developer.apple.com/account/resources/profiles/list), you'll need to:
1. Create your identifier (if it's not already the case)
2. Configure App Groups
3. Configure Apple Push Notifications
**To create your identifier**, go to *Identifiers* and select or create your application identifier (for a creation, check your identifier has an "Explicit" Bundle ID).
**To configure App Groups**:
* Select *Identifiers* in the left menu of the Developer, then select *App Groups* from the upper right dropdown
* Click on the "+" button and follow the instructions from the creation assistant
* Open your Application Identifier and click "Configure" from the "App Groups" feature. Then, select your previously created App Groups Identifier.
**To Configure Push Notifications**:
* Select *Keys* in the left menu of the Developer Portal.
* Click on the "+" button and:
* Provide a "Key name"
* Check "Apple Push Notifications service (APNs)"
* Click on "Continue", then "Register"
* Click on the "Download" button to retrieve the generated key and the "APNS Key ID" value. Also keep the "Team ID" value.
* Open your Application Identifier and click "Configure" from the "Push Notification" feature.
You can also:
* Follow the [Apple's documentation](https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/establishing_a_certificate-based_connection_to_apns) to add an Apple Push Notification Production SSL certificate.
* Send Push information to the SDK
### AntelopRelease.plist
Using XCode, create `AntelopRelease.plist` file in iOS → AppName → `AntelopRelease.plist` and add it to your TargetAppName.
Your file should look like this:
```xml [XML]
fr.antelop.alertLoggingEnabledThe Antelop SDK is logging.fr.antelop.applicationGroupIdentifiergroup.com.treezor.scaintegrationfr.antelop.initialConnectionTimeout60fr.antelop.application_id{yourApplicationId}fr.antelop.issuer_id{yourIssuerId}fr.antelop.teamIdentifier{yourTeamIdentifier}
```
### Configure XCode
If you are using the last architecture of React Native which uses Obj-c++, you will need to add the following flag: Target → BuildSettings → Other C++ flags: `-fmodules` and `-fcxx-modules`
If you get the "C++ modules are disabled" error, please set the following settings to true. Target → BuildSettings → Enable Modules(C and Objective-C)
### Configure AppDelegate
In `AppDelegate.mm`, add `@import react_native_antelop;` at the top of the document.
```c
@import react_native_antelop;
```
Override the [AppDelegate.didFinishLaunchingWithOptions](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1622921-application) and use this code.
```c
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// [...] Your application code
// Add these lines at end of the method
[AntelopBridgeAppDelegate.shared didFinishLaunchingWithOptionsWithApplication:application launchOptions:launchOptions];
return YES;
}
```
**Note – Do not replace your complete `didFinishLaunchingWithOptions` method**
Just add the provided code at the end of the method.
Override the [AppDelegate.applicationDidBecomeActive](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1622956-applicationdidbecomeactive) and use this code :
```c
- (void)applicationDidBecomeActive:(UIApplication *)application {
[AntelopBridgeAppDelegate.shared applicationDidBecomeActiveWithApplication:application];
}
```
Override the [AppDelegate.didRegisterForRemoteNotificationsWithDeviceToken](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1622958-application) and use this code:
```c
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
// You can retreive the deviceToken for you own Server side push
// Link to Antelop Bridge
[AntelopBridgeAppDelegate.shared didRegisterForRemoteNotificationsWithDeviceTokenWithApplication:application data:deviceToken];
}
```
Override the [AppDelegate.didReceiveRemoteNotification](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623013-application) and use this code:
```c
-(void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void
(^)(UIBackgroundFetchResult))completionHandler
{
typedef void (^FetchCompletionHandler)(UIBackgroundFetchResult);
typedef void (^ClientNotificationHandler)(NSDictionary * _Nonnull, FetchCompletionHandler);
ClientNotificationHandler clientNotificationHandler = ^void(NSDictionary * _Nonnull userInfo, FetchCompletionHandler handler) {
// To be implemented if the default behaviour is not desired
};
[AntelopBridgeAppDelegate.shared didReceiveRemoteNotificationWithUserInfo:userInfo completionHandler:completionHandler clientNotificationHandler:clientNotificationHandler];
}
```
Override the [AppDelegate.performFetchWithCompletionHandler](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623125-application) and use this code:
```c
-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
[AntelopBridgeAppDelegate.shared performFetchWithCompletionHandlerWithApplication:application completion:completionHandler];
}
```
### Push notifications
Adding the Notification Service is required to decrypt the encrypted content of the Push Notifications.
To add the necessary files for iOS, run the command `yarn installNotificationIOS`
**Note – `installNotificationIOS` script depends on `npm xcode` package**
Therefore, you should make sure that your `package.json` specifies this package (`yarn add xcode` or `npm i xcode`).
This will add a new target "PushExtension" to your project. Verify the settings below for the newly added target:
* In XCode navigate to section "General"
* Verify your Bundle identifier, Version and Build
* Navigate to section "Signing & Capabilities"
* Add "App Groups" by clicking "+ Capability" and check the group identifier embed in your provisioning profile
* Verify your Bundle identifier
* Navigate to section "Build Settings":
* Search for "SWIFT\_VERSION" in the filter and ensure that it is valued to "SWIFT 5"
In order to share data with the main app, the Extension must have access to the [App Group](https://developer.apple.com/documentation/xcode/configuring-app-groups) declared in the `AntelopRelease.plist` at `fr.antelop.applicationGroupIdentifier`.
In your Podfile, add these lines to the target of your application:
```c
pod 'react-native-antelop', :path => '../node_modules/react-native-antelop'
pod 'AntelopSDK', :path => '../node_modules/react-native-antelop/ios/Frameworks/'
pod 'SecureCModule', :path => '../node_modules/react-native-antelop/ios/Frameworks/'
```
In your Podfile, add these lines at the end of the file:
```c
target 'PushExtension' do
config = use_native_modules!
use_react_native!(:path => config["reactNativePath"])
inherit! :search_paths
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['APPLICATION_EXTENSION_API_ONLY'] = 'NO'
end
end
flipper_post_install(installer)
end
end
```
Make sure to add the `AntelopRelease.plist` to the Extension Target: File Inspector → Target Membership, check the box for the Extension Target if necessary.
## Android SDK Configuration
**Reading – Android SDK configuration guide is available**
This section is to be read along with the Android SDK full documentation. Contact Treezor if you don't have access to the partner's integration guides yet.
### Metadata
Add the following metadata to `android/app/src/main/AndroidManifest.xml`
```xml [XML]
```
### Permissions
Add the following permissions to `android/app/src/main/AndroidManifest.xml`
```xml [XML]
```
### Libraries
Add the following libraries to `android/build.gradle`
```json [JSON]
allprojects {
// ...
repositories {
// ...
flatDir {
dirs project(':react-native-antelop').file('libs')
dirs project(':react-native-antelop').file('google-libs')
}
}
// ...
}
```
Add the following to `android/app/build.gradle` (if not already present)
```json [JSON]
dependencies {
// ...
implementation 'androidx.work:work-runtime-ktx:2.7.0'
}
```
## Usage
Declare a custom prompt `YourCustomPrompt.tsx` using:
```js [JavaScript]
import {
StrongCustomerAuthenticationProvider,
CustomPromptProps,
CustomPromptAction,
CustomPromptError,
} from 'react-native-treezor-sca';
const YourCustomPrompt = ({
onPasscodeEntered,
onClose,
action,
error,
}: CustomPromptProps) => {
const title: Record = {
auth: 'Enter your passcode',
check: 'Enter your current passcode',
setup: isConfirmation ? 'Repeat your passcode' : 'Set your passcode',
update: isConfirmation
? 'Repeat your new passcode'
: 'Enter your new passcode',
unlock: 'Enter your passcode to unlock your account',
activateBiometric: 'Enter your passcode to activate biometric',
deactivateBiometric: 'Enter your passcode to deactivate biometric',
};
const scaErrors: Record = {
wrongPasscode: remainingPasscodeAttempts
? `Invalid passcode.\n You have ${remainingPasscodeAttempts} attempt(s) left`
: 'Invalid passcode.\n Please try again ',
wrongBiometrics:
"Many incorrect attempts to verify biometrics; use passcode until it's reactivated again",
};
return (
{title[action]}
{error && {errors[error]}}
{/* Rest of your prompt design & logic */}
);
};
```
When a passcode error in the prompt occurs, the set `remainingPasscodeAttempts` value depends on the context.
| Passcode error context | Value | Description |
| --- | --- | --- |
| **SCA** | numerical | The number of remaining attempts before the authentication passcode is blocked. Applies to both per-session and per-operation SCA. |
| **SCA Wallet action** | `undefined` | Specifically for biometry activation/deactivation or unlocking of the SCA Wallet. If there are too many erroneous attempts, the SCA Wallet will be blocked. |
Wrap your application in `App.tsx` using the following.
```js [JavaScript]
import { StrongCustomerAuthenticationProvider } from 'react-native-treezor-sca';
return (
{/* Your application */}
);
```
Then initialize the abstraction layer using:
```js [JavaScript]
import { useStrongCustomerAuthentication } from 'react-native-treezor-sca';
const {
isConnected,
biometricStatus,
destroy,
connect,
disconnect,
provision,
sign,
changePasscode,
activateBiometric,
deactivateBiometric,
} = useStrongCustomerAuthentication({
rootedDeviceForbidden: false,
onError: (code, details) => console.error(code, details),
onProvisioningRequired: async () => {
const scaWallet = await MyApiService.createScaWallet({ userId });
provision(scaWallet.activationCode);
},
onChangeCredentialsSuccess: () => console.info('Passcode has been updated'),
onCheckCredentialsSuccess: () => console.info('Passcode has been checked'),
onActivateBiometricSuccess: () =>
console.info('Biometric Authentication has been activated'),
onDeactivateBiometricSuccess: () =>
console.info('Biometric Authentication has been deactivated'),
});
```
### Connect to an SCA Wallet
```js [JavaScript]
// by calling the connect() method :
// if no wallet exists, onProvisioningRequired() will be called
// if a wallet is already provisionned, a simple connexion to it is established
connect();
```
You should only connect to an SCA Wallet once the end user has authenticated on your app.
### Generate an SCA Proof (without user action)
```js [JavaScript]
// Generate a JWS to make session calls
const signature = await sign();
const decoded = jwtDecode(signature);
console.info(decoded);
```
### Generate an SCA Proof (with user action)
Generate an SCA proof with a user passcode or user biometrics request.
```js [JavaScript]
// Generate a JWS to make session calls
const signature = await sign({ type: 'authenticate' });
const decoded = jwtDecode(signature);
console.info(decoded);
```
### Customize prompt biometric
```js [JavaScript]
// Customizing biometric prompt with android title, android subtitle or ios subtitle
const signature = await sign({
type: 'authenticate',
biometryMessage: {
androidTitle: 'Android title to custom',
androidSubTitle: 'Android subtitle to custom',
iosSubTitle: "iOS subtitle to custom
},
});
```
### Sign parameters interface
```js [JavaScript (v2.6.6 & higher)]
// Sign params interface
type ISignMethod = 'passcode' | 'biometric';
export interface ISignOptions {
type: ISignType;
data?: unknown;
signMethod?: ISignMethod;
biometryMessage?: IBiometryMessage;
passcodeFallback?: boolean; // If true, if biometry cancelation, the passcode prompt will be displayed. If false or undefined the biometry cancelation will close the biometry prompt
}
```
```js [JavaScript (up to v2.6.5.1)]
// Sign params interface
const sign = async (options: ISignOptions = { type: 'none' })
interface ISignOptions {
type: ISignType;
data?: unknown;
biometryMessage?: IBiometryMessage;
}
interface IBiometryMessage {
title?: string;
subTitle?: string;
}
```
Find below the details for `isSignOptions`:
| Property | Type | Description |
|-----------------|------------------|--------|
| type | ISignType | The authentication type, either `none` or `authenticate`. |
| data | unknown | Data to be displayed as part of the authentication or null. |
| signMethod | ISignMethod | The user specified sign method, either `biometry` or `passcode`. If no value is specified, the current signMethod is used. |
| biometryMessage | IBiometryMessage | Custom biometric prompt message. |
| passcodeFallback | boolean | Whether to fall back to passcode authentication when canceling biometry authentication. If false or undefined, canceling the biometry closes the biometry prompt. |
### Sign act parameters interface
```js [JavaScript (v2.6.6 & higher)]
// Sign act params interface
type OperationSignature = {
url: string;
body: unknown;
};
type TSignActOptions = {
signMethod?: ISignMethod;
biometryMessage?: IBiometryMessage;
passcodeFallback?: boolean;
}
const signAct = (
operation: OperationSignature,
options?: TSignActOptions
)
```
```js [JavaScript (up to v2.6.5.1)]
// Sign act params interface
const signAct = (
operation: OperationSignature,
biometryMessage?: IBiometryMessage // you can also customize biometric prompt message for signAct
)
export type OperationSignature = {
url: string;
body: unknown;
};
```
Find below the details for `signAct`:
| Property | Type | Description |
|----------|----------------------|------------------------------------------------------------------------------------------------|
| operation | OperationSignature | The url and body of the sign act. |
| options | TSignActOptions | Options included the sign method, custom prompt message, and fallback to passcode in case of biometry cancellation. |
Find below the details for `TSignActOptions`:
| Property | Type | Description |
|------------------|------------------|------------------------------------------------------------------------------------------------|
| signMethod | ISignMethod | The user specified sign method, either `biometry` or `passcode`. If no value is specified, the current signMethod is used. |
| biometryMessage | IBiometryMessage | Custom biometric prompt message. |
| passcodeFallback | boolean | Whether to fall back to passcode authentication when canceling biometry authentication. If false or undefined, canceling the biometry closes the biometry prompt. |
### Activate biometric
```js [JavaScript]
// Activate biometric
activateBiometric();
```
### Deactivate biometric
```js [JavaScript]
// Deactivate biometric
deactivateBiometric();
```
### Generate a per-operation SCA Proof
```js [JavaScript]
// Generate a JWS to update a Card's limits, with a user passcode request
const signature = await signAct({
url: '{baseUrl}/v1/cards/{cardId}/Limits',
body: {
limitAtmMonth: 1000,
limitPaymentMonth: 800,
},
});
const decoded = jwtDecode(signature);
console.info(decoded);
```
You can check out [the format of the payload](./sdk#payload) to sign.
### Change the passcode
```js [JavaScript]
// change passcode requested by end user
changePasscode();
```
### Disconnect from an SCA Wallet
```js [JavaScript]
// disconnect from an SCA Wallet
disconnect();
```
A disconnect should occur when your app is put to the background, or when the end user disconnects from your app.
### Delete an SCA Wallet
```js [JavaScript]
// irreversibly destroy the SCA Wallet from mobile device
destroy();
```
## Listeners
Subscribing for "WalletEventListener" and "PushAuthenticationRequestListener" enables the application to capture events from remote notifications, thereby ensuring correct wallet and authentication statuses. For subscription, a set of callback functions for each event have to be provided.
Find below two examples of listening to notifications, with display or actions triggered afterwards.
### Example 1 – Listen and display log or toaster outside the application
```js [JavaScript]
import {AppRegistry} from 'react-native';
import {Toast} from 'react-native-toast-message/lib/src/Toast';
import {
WalletEventListener,
PushAuthenticationRequestListener,
} from 'react-native-antelop';
import {name as appName} from './app.json';
import App from './src/App';
const walletEventListenerProtocole = {
onWalletLoaded: () => {
Toast.show({
type: 'info',
text1: 'Wallet has been loaded',
});
console.log('Event', '@WalletEventListener/onWalletLoaded');
},
onWalletLocked: reason => {
Toast.show({
type: 'info',
text1: 'Wallet has been locked',
});
console.log('Event', '@WalletEventListener/onWalletLocked', reason);
},
onWalletUnlocked: () => {
Toast.show({
type: 'info',
text1: 'Wallet has been unlocked',
});
console.log('Event', '@WalletEventListener/onWalletUnlocked');
},
onWalletDeleted: () => {
Toast.show({
type: 'info',
text1: 'Wallet has been deleted',
});
console.log('Event', '@WalletEventListener/onWalletDeleted');
},
onLogout: () => {
console.log('Event', '@WalletEventListener/onLogout');
},
onSettingsUpdated: () => {
console.log('Event', '@WalletEventListener/onSettingsUpdated');
},
onCountersUpdated: () => {
console.log('Event', '@WalletEventListener/onCountersUpdated');
},
onCustomerCredentialsReset: () => {
console.log('Event', '@WalletEventListener/onCustomerCredentialsReset');
},
onLostEligibility: () => {
console.log('Event', '@WalletEventListener/onLostEligibility');
},
onCardsUpdated: () => {
console.log('Event', '@WalletEventListener/onCardsUpdated');
},
};
const pushAuthProtocole = {
onRequestReceived(pushAuthenticationRequestId) {
console.log(
'PushAuthenticationRequestFetcher',
'onRequestReceived',
pushAuthenticationRequestId,
);
},
onRequestCancelled(requestId, reason) {
console.log(
'PushAuthenticationRequestFetcher',
'onRequestCancelled',
requestId,
reason,
);
},
};
PushAuthenticationRequestListener().setBackgroundListener(pushAuthProtocole);
PushAuthenticationRequestListener().setForegroundListener(pushAuthProtocole);
WalletEventListener().setBackgroundListener(walletEventListenerProtocole);
WalletEventListener().setForegroundListener(walletEventListenerProtocole);
AppRegistry.registerComponent(appName, () => App);
```
### Example 2 – Listen and trigger appropriate actions inside the application
In this example, we listen for notification events relating to the SCA Wallet status (e.g., `onWalletLocked`, `onCredentialsReset`, and `onWalletDelete`) to dispatch an event from the `index.js` (other notifications are handled as the same way as the first example).
Inside the application logic (`MobileActions.tsx`), on capturing the event, we display a modal with explanation and a CTA button to disconnect the SCA Wallet.
#### index.js
```js [JavaScript]
import {AppRegistry, NativeEventEmitter, NativeModules} from 'react-native';
import {Toast} from 'react-native-toast-message/lib/src/Toast';
import {
WalletEventListener,
PushAuthenticationRequestListener,
} from 'react-native-antelop';
import {name as appName} from './app.json';
import App from './src/App';
// For ios, the EmitterModule must be declared beforehand as describled in: https://reactnative.dev/docs/native-modules-ios
// As example, Add RCTEmitterModule.h and RCTEmitterModule.m inside the ios folder to to register the emitter module
const {EmitterModule} = NativeModules;
const eventEmitter = new NativeEventEmitter(EmitterModule);
const walletEventListenerProtocole = {
onWalletLoaded: () => {
Toast.show({
type: 'info',
text1: 'Wallet has been loaded',
});
console.log('Event', '@WalletEventListener/onWalletLoaded');
},
onWalletLocked: reason => {
console.log('Event', '@WalletEventListener/onWalletLocked', reason);
// dispatch an event in case of WalletLocked
eventEmitter.emit('onWalletUpdated', {type: 'Wallet locked', reason});
},
onWalletUnlocked: () => {
Toast.show({
type: 'info',
text1: 'Wallet has been unlocked',
});
console.log('Event', '@WalletEventListener/onWalletUnlocked');
},
onWalletDeleted: () => {
console.log('Event', '@WalletEventListener/onWalletDeleted');
// dispatch an event in case of WalletDeleted
eventEmitter.emit('onWalletUpdated', {type: 'Wallet deleted'});
},
onLogout: () => {
console.log('Event', '@WalletEventListener/onLogout');
},
onSettingsUpdated: () => {
console.log('Event', '@WalletEventListener/onSettingsUpdated');
},
onCountersUpdated: () => {
console.log('Event', '@WalletEventListener/onCountersUpdated');
},
onCustomerCredentialsReset: () => {
console.log('Event', '@WalletEventListener/onCustomerCredentialsReset');
// dispatch an event in case of CustomerCredentialsReset
eventEmitter.emit('onWalletUpdated', {type: 'Credentials reset'});
},
onLostEligibility: () => {
console.log('Event', '@WalletEventListener/onLostEligibility');
},
onCardsUpdated: () => {
console.log('Event', '@WalletEventListener/onCardsUpdated');
},
};
const pushAuthProtocole = {
onRequestReceived(pushAuthenticationRequestId) {
console.log(
'PushAuthenticationRequestFetcher',
'onRequestReceived',
pushAuthenticationRequestId,
);
},
onRequestCancelled(requestId, reason) {
console.log(
'PushAuthenticationRequestFetcher',
'onRequestCancelled',
requestId,
reason,
);
},
};
PushAuthenticationRequestListener().setBackgroundListener(pushAuthProtocole);
PushAuthenticationRequestListener().setForegroundListener(pushAuthProtocole);
WalletEventListener().setBackgroundListener(walletEventListenerProtocole);
WalletEventListener().setForegroundListener(walletEventListenerProtocole);
AppRegistry.registerComponent(appName, () => App);
```
#### MobileActions.tsx
```js [JavaScript]
...
const [walletStatus, setWalletStatus] = useState();
...
// Listening to onWalletUpdated to display the modal on received
// Remove listener on unmount
useEffect(() => {
eventEmitter.addListener('onWalletUpdated', data => {
console.log(data);
isConnected && setWalletStatus(data?.type);
});
return () => {
eventEmitter.removeAllListeners('onWalletUpdated');
};
}, [isConnected]);
...
// Display the modal with explanation and CTA button to disconnect the sca wallet
<>
{!!walletStatus && (
setWalletStatus(undefined)}
onSubmit={() => {
setWalletStatus(undefined);
disconnect();
}}
/>
)}
>
```
## Errors
Treezor abstraction layer returns error objects in the following format:
```json [JSON]
{
"code": 449,
"error": "Canceled"
}
```
Here is the list of errors you may encounter:
| HTTP Status code | SDK error | Description |
| --- | --- | --- |
| 401 | Invalid Credentials | Occurs when the passcode of the end user are invalid or provided in an invalid format. |
| 404 | Wallet Not Found | Occurs when the SCA Wallet doesn't exist (deleted, wrong Id). |
| 405 | Passcode Authentication Impossible | Occurs when the number of authentication attempts with a passcode is reached. To unblock this situation, you may activate the biometry or reset the passcode (via the app, dashboard, or your own back office with a PIN reset). |
| 406 | Device Not Eligible | Occurs when the device is not supported (due to the OS version for instance). |
| 407 | Authentication Error | Occurs when there is an issue with the strong customer authentication (timeout, duplicate, etc.). |
| 416 | Wallet Not Activated | Occurs when the SCA Wallet is not active. |
| 423 | Wallet Locked | Occurs when the SCA Wallet is locked. You may unlock the SCA Wallet per your end user's request in the Dashboard or in your own back office. |
| 428 | Activation Required | Occurs when the end user is active on their device and an action is made from the back office or Dashboard (unlock or reset PIN). The end user must log out and log back in order to reactivate their account or reinitialize their passwords. |
| 451 | Other Error | Contact Treezor for more information. |
| 498 | Invalid Activation Code | Occurs when the activation code is invalid, already used, expired or locked during the SCA Wallet initialization or provisioning. |
| 499 | Canceled | Occurs when the end user cancels the SCA. |
| 500 | Internal Error | Occurs in case of an unexpected server error. Contact Treezor if the error persists. |
| 511 | Network Not Available | Occurs when there is a network issue. |
---
---
url: /guide/strong-customer-authentication/sdk.md
description: >-
Technical guide for using the Mobile SDK for Strong Customer Authentication
(SCA). Includes the links to download the SDK in multiple languages, for both
sandbox and production.
---
# Mobile SDK
**Information – SDK *Wallet* or *SCA Wallet* do not refer to Treezor Wallets**
The SDK uses the terms *Wallet* or *SCA Wallet* to describe a secure enclave present locally on a mobile device where the private key is stored. Not to be mixed up with [Treezor Wallets](/guide/wallets/introduction) feature.
All the SDK features are provided through an SCA wallet object implemented in the SDK itself. It can be seen as a base layer, gathering configuration and security settings on which Strong Customer Authentication relies.
SCA Wallets are synchronized between the mobile device and Treezor back end.
The main property of the SCA Wallet is its state, evolving from actions triggered on the back end or on hosting app side, and defining how an SCA wallet is accessible to the hosting app.
**Android**
* Minimum supported version – Android 5.0 Lollipop (API level 21)
* Target version – Tested with Android versions until Android 13 (API level 33)
**iOS**
* Minimum supported version – iOS 11
* Minimum supported version for pushing a Card to Apple Pay – iOS 13.4
* Swift 5
## Access
To request SCA proofs, the hosting app must first build a `WalletManager` object with a custom implementation of `WalletManagerCallback`. The callback functions will be called by the SDK upon the completion of asynchronous actions requested on the `WalletManager` instance.
Once a `WalletManager` object is built, SCA Wallet access is requested by calling the `WalletManager#connect()` method.
`connect()` calls are asynchronous and trigger one of the following method of the `WalletManager` upon completion.
| Callback | Description |
| --- | --- |
| `WalletManagerCallback#onConnectionSuccess()` | The **wallet is ready** and any of its services can be used. |
| `WalletManagerCallback#onProvisioningRequired()` | The **wallet access is refused because there is no initialized wallet** in the app. The hosting app [must first initialize a wallet](#provisionning) and then attempt to access it again. |
| `WalletManagerCallback#onCredentialsRequired()` | The **wallet access is refused because credentials must be provided**. It can be either: New credentials to define when the wallet is accessed for the first time after provisioning.Current credentials when the wallet is accessed after log out. The hosting App must request and acquire credentials from the customer, then forward them to the SDK as method arguments through a new call to `WalletManager#connect(currentCredentials,newCredentials)`. If the Wallet is configured to not enforce access protection, this callback is never called. |
| `WalletManagerCallback#onConnectionError()` | The **wallet access cannot be established**, for a specific reason provided as method argument. |
Calls to the `connect()` method happen mostly locally, but can require online connectivity in some specific cases (for example when credentials are provided or when critical security checks must be carried out).
**Best practice – Ensure the SCA Wallet handled by the app is up-to-date**
Don't handle the SCA Wallet instance returned by the SDK statically or in a singleton on the hosting app side. Each time a new context on the App needs to interact with an SCA Wallet, it must connect to a `WalletManager` and wait for `onConnectionSuccess` callback function.
## Device Eligibility
SCA features can be forbidden if the device is rooted or if the device model is explicitly blacklisted. Checking device eligibility is done by calling the `WalletProvisioning#checkEligibility()` method.
This starts a light operation and executes the following callbacks.
| Callback | Description |
| --- | --- |
| `WalletProvisioningCallback#onDeviceEligible()` | If the **device is considered eligible** for SCA services. Features available on the SCA wallet are provided as method argument. After this callback, the hosting app can proceed with wallet provisioning. |
| `WalletProvisioningCallback#onDeviceNotEligible()` | If the **device is considered not eligible** for SCA services (wallet provisioning isn't possible). The eligibility denial reason is provided as method argument with the eligibility denial reference (i.e., the identifier used to record this specific eligibility denial on the back end). |
| `WalletProvisioningCallback#onCheckEligibilityError()` | If the **eligibility check has failed** for a specific reason provided as method argument. |
### Provisioning flow
The following diagram illustrates the provisioning procedure. This applies to **one** User and **one** mobile device.
```mermaid
sequenceDiagram
participant sdk as Mobile SDK
participant app as Mobile App
participant agent as Agent back end
participant trz as Treezor
% participant entrust as Entrust
app->>sdk: Attempt to connect to the SCA Wallet using WalletManager.connect()
Note over app: Wait for onProvisioningRequired async event
% alt onProvisioningRequired
% sdk-->>app: WalletManagerCallback.onProvisioningRequired()
% else onCredentialsRequired
% sdk-->>app: WalletManagerCallback.onCredentialsRequired()
% else onConnectionError
% sdk-->>app: WalletManagerCallback.onConnectionError()
% end
sdk-->>app: WalletManagerCallback.onProvisioningRequired()
app->>agent: Request creation of SCA Wallet
agent->>trz: Create an SCA Wallet
trz->>agent: Response (with activationCode)
%Note over trz,agent: Containing the SCA Wallet activationCode
trz-->>agent: Send an SCA.wallet.create webhook
Note over trz,agent: Containing the SCA Wallet activationCode
agent->>app: Response (with activationCode)
%% agent-->>app: Send a push notification
%% Note over agent,app: Containing the SCA Wallet activation code
app->>sdk: Intialize the provisionning instance using WalletProvisioning.initialize()
Note over app: Wait for onInitializationSuccess async event
% alt onInitializationSuccess
sdk-->>app: WalletProvisioningCallback.onInitializationSuccess()
% else onInitializationError
% sdk-->>app: WalletProvisioningCallback.onInitializationError()
% else onPermissionNotGranted
% sdk-->>app: WalletProvisioningCallback.onPermissionNotGranted()
% end
app->>sdk: Check device elligibility using WalletProvisioning.checkEligibility()
Note over app: Wait for onDeviceEligible async event
% alt onDeviceEligible
sdk-->>app: WalletProvisioningCallback.onDeviceEligible()
% else onDeviceNotEligible
% sdk-->>app: WalletProvisioningCallback.onDeviceNotEligible()
% else onCheckEligibilityError
% sdk-->>app: WalletProvisioningCallback.onCheckEligibilityError()
% end
app->>sdk: Provision the SCA Wallet using WalletProvisioning.launch(activationCode)
Note over app: Wait for onProvisioningSuccess async event
% alt onProvisioningSuccess
sdk-->>app: WalletProvisioningCallback.onProvisioningSuccess()
% else onProvisioningError
% sdk-->>app: WalletProvisioningCallback.onProvisioningError()
% end
app->>sdk: Attempt to connect to the SCA Wallet using WalletManager.connect()
Note over app: Wait for onCredentialsRequired async event
sdk-->>app: WalletManagerCallback.onCredentialsRequired()
Note over app: Prompt the user to define a PIN Code (4 to 8 digits)
app->>sdk: Attempt to connect to the SCA Wallet using WalletManager.connect(null,pinCode)
Note over app,sdk: This defines the pinCode of the SCA Wallet
Note over app: Wait for onConnectionSuccess async event
% alt onConnectionSuccess
sdk-->>app: WalletManagerCallback.onConnectionSuccess()
% else onCredentialsRequired
% sdk-->>app: WalletManagerCallback.onCredentialsRequired()
% else onConnectionError
% sdk-->>app: WalletManagerCallback.onConnectionError()
% end
Note over app: The SCA Wallet is ready
% provisionner
% creer credentials
```
**Best practice – Your code must be event-based**
Although this diagram is fairly procedural for clarity, your code must be event-based to handle all possibilities.
## Signature
SCA proof capabilities are provided by the SDK via `CustomerAuthenticatedSignature`, it produces a signature once the user has performed the required authentication. This signature is generated locally within Entrust SDK and is returned to the hosting app.
`CustomerAuthenticatedSignature` must first be instantiated with the following parameters.
| Parameter | Description |
| --- | --- |
| `patternName` | The name of the authentication pattern to use for this authentication. Can be:`patterns.NONE.name` for none authentication`patterns.PIN.name` for PIN authentication`patterns.BIOMETRY.name` for Biometric authentication |
| `message` | The message to display to the customer. Must be set if the SDK is used to display the UI. In any case, this information is part of the signed data. |
| `signatureType` | Type of signature result to generate. You must use the `CustomerAuthenticatedSignatureType.LocalJws` option. |
| `signatureInputData` | Custom, context-related information that is part of [the signed data](#payload). |
Once instantiated, you must call `CustomerAuthenticatedSignature#sign()` to start the signature process.
When the `CustomerAuthenticatedSignature` is successfully completed, you're notified by the `CustomCustomerAuthenticatedProcessCallback#onProcessSuccess()` callback. The generated signature result can be fetched by calling `CustomerAuthenticatedSignature#getResult()`.
### SCA Proof flow
The following diagram illustrates the generation of SCA Proofs using type PIN. It assumes the [provisioning is completed](#provisioning-flow).
```mermaid
sequenceDiagram
participant sdk as Mobile SDK
participant app as Mobile App
participant agent as Agent API
participant trz as Treezor
% participant entrust as Entrust
app->>sdk: Attempt to connect to the SCA Wallet using WalletManager.connect()
Note over app: Wait for onConnectionSuccess async event
sdk-->>app: WalletManagerCallback.onConnectionSuccess()
Note over app: Prepare the payload that needs to be signed
app->>sdk: Instanciate the CustomerAuthenticatedSignature(pattern, message, type, input)
Note over app,sdk: The following parameters are expected : pattern: patterns.PIN.name message: "A description of the signature action" type: CustomerAuthenticatedSignatureType.LocalJws input: Buffer.from(JSON.stringify(payload), 'utf8')
app->>sdk: Call the sign(callback, callback, ...) method on the CustomerAuthenticatedSignature instance
Note over app,sdk: The following callbacks are expected : onCustomerCredentialsRequired() onCustomerCredentialsInvalid() onAuthenticatedDeclined() onError() onProcessStart() onProcessSuccess()
Note over app: Wait for onCustomerCredentialsRequired async event
sdk-->>app: CustomCustomerAuthenticatedProcessCallback.onCustomerCredentialsRequired()
Note over app: Prompt the user for their PIN Code
%app->>sdk: Set their PIN Code using CustomerAuthenticatedProcess.setCustomerCredentials( new CustomerAuthenticationPasscode(pinCode) )
app->>sdk: Set their PIN Code using CustomerAuthenticatedProcess.setCustomerCredentials(pinCode)
Note over app: Wait for onProcessSuccess async event
app->>sdk: Retrieve the SCA Proof using CustomerAuthenticatedSignature.getResult()
Note over sdk,app: This is the SCA Proof JWS
app->>agent: Send the Per-Operation request
Note over app, agent: Forward the SCA proof (JWS)
Note over agent: Retrieve the User's JWT from your database Do not request a new JWT from Treezor if yours hasn't expired
agent->>trz: Call the relevant endpoint
Note over agent, trz: Place the JWT in the "Authorization:" header
%Note over agent, trz: Place the JWS in the "X-SCA-Authorization:" header
Note over agent, trz: Forward the SCA proof (JWS)
trz->>agent: Response
agent->>app: Response
```
**Best practice – Your code must be event-based**
Although this diagram is fairly procedural for clarity, your code must be event-based to handle all possibilities.
#### SCA Wallet states
SCA Wallets may have the following states.
| State | Description |
| --- | --- |
| **Not provisioned** | The app has not initialized the SDK yet, so no SCA wallet exists on it. |
| **Ready** | The SDK was initialized by the app, an SCA wallet was provisioned into it, and its properties and features can be accessed by the app (after [establishing a connection](#access) to the SCA wallet). |
| **Locked** | The SCA wallet provisioned into the app is locked. Its properties and features aren't accessible to the app until the SCA wallet is unlocked from the back end. |
| **Logout** | Access to properties and features of the SCA wallet provisioned into the app requires first a customer authentication. |
## Authentication
### Methods
The user is prompted to authenticate differently depending on the method:
* **Pin** – Using a 6 to 8 digits PIN code.
* **Biometric** – Using the local biometric authentication system of the device.
* **None** – No input required, the operation is transparent.
You may use indistinctly **Pin** or **Biometric**, depending on the capabilities of the device.
Regardless of the method, basic checks are carried out to ensure the mobile device is legitimate and has not been altered or cloned.
## Events
The following functions can be called by the SDK upon SCA Wallet updates.
| Event | Description |
| --- | --- |
| `WalletEventListener#onWalletSettingUpdated()` | The SCA wallet settings are updated. |
| `WalletEventListener#onWalletProductsUpdated()` | The SCA wallet products are updated. |
| `WalletEventListener#onWalletCountersUpdated()` | The SCA wallet passcode (PIN Code) attempt counter is updated. |
| `WalletEventListener#onCustomerCredentialsReset()` | The SCA wallet passcode (PIN Code) has been reset. |
| `WalletEventListener#onWalletLocked()` | The SCA wallet has been locked. |
| `WalletEventListener#onWalletUnlocked()` | The SCA wallet has been unlocked. |
| `WalletEventListener#onDeviceEligibilityLost()` | The current device is no longer eligible to SCA service. |
| `WalletEventListener#onWalletDeleted()` | The SCA wallet has been deleted. |
| `WalletEventListener#onWalletLoaded()` | The SCA wallet has completed its initialization. |
| `WalletEventListener#onAppSunsetScheduled()` | The current version of the mobile application has been deprecated. |
## Payload
When providing a payload to the SDK for signature, it should be in the following format, with:
* The `url` (string) – Always populated with the endpoint that requires the SCA.
* The `body` (object) – Populated with parameters to sign, and left as an empty array when [no parameters have to be signed](securing-endpoints#per-session).
### No parameters to be signed
```json [JSON]
{
"url": "string",
"body": {}
}
```
### With parameters to be signed
```json [JSON]
{
"url": "string",
"body": {
"foo0": "bar0",
"foo1": "bar1"
}
}
```
### Payload examples
Find below a series of examples that illustrate different payloads.
#### GET /v1/cardimages
Request example:
```bash [CURL]
GET {baseURL}/v1/cardimages?cardId=123456&encryptionMethod=2
```
Signed data:
```json [JSON]
{
"url": "{baseURL}/v1/cardimages",
"body": {
"cardId": "123456"
}
}
```
#### PUT /v1/cards/{id}/Activate
Request example:
```bash [CURL]
PUT {baseURL}/v1/cards/{id}/Activate?accessTag=12345
```
Signed data:
```json [JSON]
{
"url": "{baseURL}/v1/cards/{id}/Activate",
"body": {}
}
```
#### POST /v1/beneficiaries
Request example:
```bash [CURL]
POST {baseURL}/v1/beneficiaries?accessTag=12345
{
"userId": "12345",
"name": "Alex Oak"
"address": "15 Magnolia road",
"iban": "FR113000300030592123456789",
"bic": "SOGEFRPPXXX",
"usableForSct": true
}
```
Signed data:
```json [JSON]
{
"url": "{baseURL}/v1/beneficiaries",
"body": {
"userId": "12345",
"name": "Alex Oak",
"address": "15 Magnolia road",
"iban": "FR113000300030592123456789",
"bic": "SOGEFRPPXXX",
"usableForSct": true
}
}
```
#### PUT /v1/users/{userId}
Request example:
```bash [CURL]
PUT {baseURL}/v1/users/{userId}?accessTag=12345
{
"phone": “0702030405”,
"middleNames": "Chris"
}
```
Signed data:
```json [JSON]
{
"url": "{baseURL}/v1/users/{userId}",
"body": {
"phone": “0765432190”
}
}
```
#### PUT /v1/cards/{cardId}/Limits
Request example:
```bash [CURL]
PUT {baseURL}/v1/cards/{cardId}/Limits
{
"limitPaymentDay":25,
"limitAtmDay":100
}
```
Signed data:
```json [JSON]
{
"url": "{baseURL}/v1/cards/{cardId}/Limits",
"body": {
"limitPaymentDay":25,
"limitAtmDay": 100
}
}
```
## PIN Change
To change the PIN of an SCA Wallet, you have to follow these steps.
### Check the current PIN
Call the `WalletManager#checkCredentials(currentCredentials)` method. As the operation is async:
* Subscribe to the `WalletManager#onAsyncRequestSuccess` callback for the **success** response
* Subscribe to the `WalletManager#onAsyncRequestError` callback for the **error** response
### Change the PIN
Use the `WalletManager#changeCredentials(currentCredentials,newCredentials)` method. As the operation is async:
* Subscribe to the `WalletManager#onAsyncRequestSuccess` callback for the **success** response
* Subscribe to the `WalletManager#onAsyncRequestError` callback for the **error** response
## Disconnection
When disconnecting from an SCA Wallet, you have to follow these steps:
```c
WalletManager#disconnect()
WalletManager#clean()
```
## Compatibility chart
| Language | SDK Availability | iOS | Android |
|--- |:---: |:---: |:---: |
| [React Native](https://doc.antelop-solutions.com/latest/common/sdk-reactdoc/index.html) | | | |
| [Java](https://doc.antelop-solutions.com/latest/common/sdk-javadoc/index.html) | | | |
| [Swift](https://doc.antelop-solutions.com/latest/common/sdk-swiftdoc/index.html) | | | |
| Cordova | | | |
| Flutter | | | |
| Dart | | | |
| Kotlin | | | |
| Objective C | | | |
| Web | | N/A | N/A |
**Information – The SDK is not compatible with pure Web applications**
If your mobile stack is not available yet, get in touch with your *Implementation Manager*.
***
**Reading – Full SDK Documentation available**
Contact Treezor to request access to the SDK full documentation.
## Download SDK
### Sandbox
### Production
---
---
url: /guide/strong-customer-authentication/events.md
description: >-
Reference a comprehensive list of SCA wallets events for Treezor API webhooks,
detailing each event's structure and payload for integration.
---
# Events
## SCA Wallet events
**Caution – The SDK uses the term *Wallet* differently from Treezor**
In the [SDK](/guide/strong-customer-authentication/sdk), the term *Wallet* or *SCA Wallet* describes the secure enclave on a mobile device, not [Treezor Wallets](/guide/wallets/introduction).
### `sca.wallet.create`
```json [JSON]
{
"webhook": "sca.wallet.create",
"object": "scaWallet",
"object_id": "aef88f9c07b54056a5db807c4c3131b5",
"object_payload": {
"scaWallets": [
{
"id": "aef88f9c07b54056a5db807c4c3131b5",
"status": "CREATED",
"subStatus": "CREATED_READY",
"passcodeStatus": "NOT_SET",
"locked": false,
"lockReasons": [],
"lockMessage": null,
"settingsProfile": "default",
"mobileWallet": null,
"activationCode": "0x8a6074281ac911e04623cb2ba915bea6",
"creationDate": "2025-06-26T16:29:36+02:00",
"deletionDate": null,
"activationCodeExpiryDate": "2025-06-26T16:49:36+02:00",
"authenticationMethods": [
{
"type": "DEVICE_BIOMETRIC",
"usages": [
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": {
"validityDuration": 60
}
},
{
"type": "NONE",
"usages": [
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": []
},
{
"type": "HYBRID_PIN",
"usages": [
"WALLET_MANAGEMENT",
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": {
"maxAttempts": 3,
"validityDuration": 60
}
}
],
"invalidActivationAttempts": null,
"userId": "102267425",
"scaWalletTag": null,
"clientId": "12345",
"activationDate": null,
"lockDate": null,
"unlockDate": null,
"resetPinDate": null
}
]
},
"webhook_created_at": 17509481770133,
"webhook_id": "7e2c1954-5149-45f8-9fc9-b5e01beafb5a",
"object_payload_signature": "gzeErSE8a8A7taIImbTXRY5pFdpSrxxffx4Y246Onic="
}
```
### `sca.wallet.update`
Treezor sends this webhook when the SCA Wallet is activated (Mobile SDK). At this step, the `activationDate` and `status` are updated.
```json [JSON] {9,73}
{
"webhook": "sca.wallet.update",
"object": "scaWallet",
"object_id": "ed4e1329628443bf84113a9231ed34cb",
"object_payload": {
"scaWallets": [
{
"id": "ed4e1329628443bf84083a9231ed34cb",
"status": "ACTIVE",
"subStatus": "ACTIVATED_LOGGED_IN",
"passcodeStatus": "SET",
"locked": false,
"lockReasons": null,
"lockMessage": null,
"settingsProfile": "default",
"mobileWallet": {
"appBuildNumber": "v04-04-06-06-02-02",
"sdkVersion": "2.4.11",
"os": "ANDROID",
"osVersion": "14",
"brand": "Google",
"productModel": "sdk_gphone64_arm64",
"deviceId": "749676e2ci91c8fd",
"deviceIdType": "ANDROID_ID",
"productFingerprint": "google/sdk_gphone64_arm64/emu64a:14/[...]",
"secretFingerprint": "0xbc311dfcef97f93fe3611722d[...]",
"root": "0",
"pushMessagingId": "feT82iyLTFqZi6SXG3l8Qd:APA91bHIhquMcd359oKGbdFKX5jTuTYpfw1XU9n1ohAglN8dLpVLMrI-[...]",
"pushMessagingProvider": "FIREBASE",
"mobileUpdateDate": "2025-04-22T12:22:31Z",
"lastEligibilityCheck": "2025-04-22T12:22:31Z",
"nfc": false,
"emulator": true,
"appleTeamId": null
},
"activationCode": null,
"creationDate": "2025-04-22T14:17:31+02:00",
"deletionDate": null,
"activationCodeExpiryDate": "2025-04-22T14:37:32+02:00",
"authenticationMethods": [
{
"type": "DEVICE_BIOMETRIC",
"usages": [
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": {
"validityDuration": 60
}
},
{
"type": "NONE",
"usages": [
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": []
},
{
"type": "HYBRID_PIN",
"usages": [
"WALLET_MANAGEMENT",
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": {
"maxAttempts": 3,
"validityDuration": 60
}
}
],
"invalidActivationAttempts": null,
"userId": "101887833",
"scaWalletTag": "test",
"clientId": "12345",
"activationDate": "2025-04-22T14:22:31+02:00",
"lockDate": null,
"unlockDate": null,
"resetPinDate": null
}
]
},
"webhook_created_at": 17453245629317,
"webhook_id": "41338a50-daec-4191-a531-e7b02dcc50d3",
"object_payload_signature": "rKilCnGC0EngkPF+7McW02L/NevQlk3kY3sHc6M7OJg="
}
```
### `sca.wallet.delete`
```json [JSON]
{
"webhook": "sca.wallet.delete",
"object": "sca.wallet",
"object_id": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
"object_payload": {
"scaWallets": [
{
"id": 1234567890123456789,
"issuerWalletId": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
"issuerClientId": "123456",
"preparationType": "default",
"msisdn": null,
"status": "DELETED",
"subStatus": "DELETED_BY_ISSUER",
"passcodeStatus": "NOT_SET",
"eligibleProducts": [
],
"locked": true,
"lockReasons": [
"ISSUER"
],
"lockMessage": "USER_REQUEST",
"incidentCounter": 0,
"settingsProfile": "default",
"settings": null,
"userSettings": null,
"applicableSettings": {
"limits": {
"maxTransactionAmount": 100000000,
"mobileConnectionTimeout": 60,
"activationCodeLifetime": 1200,
"checkTransactionOutcomeTimeout": 4000,
"checkTransactionOutcomePolling": 2000,
"pingAckDelay": 500,
"pingPeriod": 604799,
"checkEligibilityPeriod": 30
},
"security": {
"rootAllowed": true,
"geolocateMessages": false,
"userGeolocatePayments": false,
"settingsProtection": true,
"accelerometerProtection": false,
"paymentCondition": "NO",
"scaOfflineAuthenticationReuseDuration": 0
},
"credentials": {
"sessionLifetime": 10
}
},
"issuerData": null,
"mobileWallet": {
"appBuildNumber": null,
"sdkVersion": null,
"os": null,
"osVersion":null,
"brand": null,
"productModel": null,
"deviceId": null,
"deviceIdType": null,
"productFingerprint": null,
"secretFingerprint": null,
"root": null,
"pushMessagingId": null,
"pushMessagingProvider": null,
"mobileUpdateDate": null,
"lastEligibilityCheck": null,
"nfc": null,
"emulator": false,
"appleTeamId": null
},
"activationCode": null,
"activationCodeB32": null,
"creationDate": "2025-03-24T10:34:41+01:00",
"deletionDate": "2025-03-24T11:06:22+01:00",
"activationCodeExpiryDate": "2025-03-24T10:54:41+01:00",
"cards": [
],
"currencyCode": "EUR",
"authenticationMethods": [
{
"type": "DEVICE_BIOMETRIC",
"usages": [
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": {
"validityDuration": 60
}
},
{
"type": "NONE",
"usages": [
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": [
]
},
{
"type": "HYBRID_PIN",
"usages": [
"WALLET_MANAGEMENT",
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": {
"maxAttempts": 3,
"validityDuration": 60
}
}
],
"lastPasscodeSyncDate": null,
"issuerActivationId": null,
"invalidActivationAttempts": null,
"userId": "100000001",
"scaWalletTag": "test",
"activationDate": null,
"lockDate": null,
"unlockDate": null,
"resetPinDate": null
}
]
},
"webhook_created_at": 17428108419449,
"webhook_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"object_payload_signature": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX="
}
```
### `sca.wallet.lock`
```json [JSON]
{
"webhook": "sca.wallet.lock",
"object": "sca.wallet",
"object_id": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
"object_payload": {
"scaWallets": [
{
"id": 1234567890123456789,
"issuerWalletId": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
"issuerClientId": "123456",
"preparationType": "default",
"msisdn": null,
"status": "CREATED",
"subStatus": "CREATED_READY",
"passcodeStatus": "NOT_SET",
"eligibleProducts": [
],
"locked": true,
"lockReasons": [
"ISSUER"
],
"lockMessage": "USER_REQUEST",
"incidentCounter": 0,
"settingsProfile": "default",
"settings": null,
"userSettings": null,
"applicableSettings": {
"limits": {
"maxTransactionAmount": 100000000,
"mobileConnectionTimeout": 60,
"activationCodeLifetime": 1200,
"checkTransactionOutcomeTimeout": 4000,
"checkTransactionOutcomePolling": 2000,
"pingAckDelay": 500,
"pingPeriod": 604799,
"checkEligibilityPeriod": 30
},
"security": {
"rootAllowed": true,
"geolocateMessages": false,
"userGeolocatePayments": false,
"settingsProtection": true,
"accelerometerProtection": false,
"paymentCondition": "NO",
"scaOfflineAuthenticationReuseDuration": 0
},
"credentials": {
"sessionLifetime": 10
}
},
"issuerData": null,
"mobileWallet": {
"appBuildNumber": null,
"sdkVersion": null,
"os": null,
"osVersion": null,
"brand": null,
"productModel": null,
"deviceId": null,
"deviceIdType": null,
"productFingerprint": null,
"secretFingerprint": null,
"root": null,
"pushMessagingId": null,
"pushMessagingProvider": null,
"mobileUpdateDate": null,
"lastEligibilityCheck": null,
"nfc": null,
"emulator": false,
"appleTeamId": null
},
"activationCode": null,
"activationCodeB32": null,
"creationDate": "2025-03-24T10:34:41+01:00",
"deletionDate": null,
"activationCodeExpiryDate": "2025-03-24T10:54:41+01:00",
"cards": [
],
"currencyCode": "EUR",
"authenticationMethods": [
{
"type": "DEVICE_BIOMETRIC",
"usages": [
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": {
"validityDuration": 60
}
},
{
"type": "NONE",
"usages": [
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": [
]
},
{
"type": "HYBRID_PIN",
"usages": [
"WALLET_MANAGEMENT",
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": {
"maxAttempts": 3,
"validityDuration": 60
}
}
],
"lastPasscodeSyncDate": null,
"issuerActivationId": null,
"invalidActivationAttempts": null,
"userId": "100000001",
"scaWalletTag": "test",
"activationDate": null,
"lockDate": "2025-03-24T09:34:41+00:00",
"unlockDate": null,
"resetPinDate": null
}
]
},
"webhook_created_at": 17428089074303,
"webhook_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"object_payload_signature": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX="
}
```
### `sca.wallet.unlock`
```json [JSON]
{
"webhook": "sca.wallet.unlock",
"object": "sca.wallet",
"object_id": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
"object_payload": {
"scaWallets": [
{
"id": 1234567890123456789,
"issuerWalletId": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
"issuerClientId": "123456",
"preparationType": "default",
"msisdn": null,
"status": "CREATED",
"subStatus": "CREATED_READY",
"passcodeStatus": "NOT_SET",
"eligibleProducts": [
],
"locked": false,
"lockReasons": [
],
"lockMessage": null,
"incidentCounter": 0,
"settingsProfile": "default",
"settings": null,
"userSettings": null,
"applicableSettings": {
"limits": {
"maxTransactionAmount": 100000000,
"mobileConnectionTimeout": 60,
"activationCodeLifetime": 1200,
"checkTransactionOutcomeTimeout": 4000,
"checkTransactionOutcomePolling": 2000,
"pingAckDelay": 500,
"pingPeriod": 604799,
"checkEligibilityPeriod": 30
},
"security": {
"rootAllowed": true,
"geolocateMessages": false,
"userGeolocatePayments": false,
"settingsProtection": true,
"accelerometerProtection": false,
"paymentCondition": "NO",
"scaOfflineAuthenticationReuseDuration": 0
},
"credentials": {
"sessionLifetime": 10
}
},
"issuerData": null,
"mobileWallet": {
"appBuildNumber": null,
"sdkVersion": null,
"os": null,
"osVersion": null,
"brand": null,
"productModel": null,
"deviceId": null,
"deviceIdType": null,
"productFingerprint": null,
"secretFingerprint": null,
"root": null,
"pushMessagingId": null,
"pushMessagingProvider": null,
"mobileUpdateDate": null,
"lastEligibilityCheck": null,
"nfc": null,
"emulator": false,
"appleTeamId": null
},
"activationCode": null,
"activationCodeB32": null,
"creationDate": "2025-03-24T10:35:09+01:00",
"deletionDate": null,
"activationCodeExpiryDate": "2025-03-24T10:55:09+01:00",
"cards": [
],
"currencyCode": "EUR",
"authenticationMethods": [
{
"type": "DEVICE_BIOMETRIC",
"usages": [
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": {
"validityDuration": 60
}
},
{
"type": "NONE",
"usages": [
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": [
]
},
{
"type": "HYBRID_PIN",
"usages": [
"WALLET_MANAGEMENT",
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": {
"maxAttempts": 3,
"validityDuration": 60
}
}
],
"lastPasscodeSyncDate": null,
"issuerActivationId": null,
"invalidActivationAttempts": null,
"userId": "100000001",
"scaWalletTag": "test",
"activationDate": null,
"lockDate": "2025-03-24T10:35:10+01:00",
"unlockDate": "2025-03-24T09:35:10+00:00",
"resetPinDate": null
}
]
},
"webhook_created_at": 17428089747334,
"webhook_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"object_payload_signature": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX="
}
```
### `sca.wallet.resetPin`
```json [JSON]
{
"webhook": "sca.wallet.resetPin",
"object": "sca.wallet",
"object_id": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
"object_payload": {
"scaWallets": [
{
"id": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
"status": "ACTIVE",
"subStatus": "ACTIVATED_LOGGED_OUT",
"passcodeStatus": "NOT_SET",
"locked": false,
"lockReasons": [
],
"lockMessage": null,
"settingsProfile": "default",
"mobileWallet": {
"appBuildNumber": "v04-04-06-06-02-02",
"sdkVersion": "2.4.11",
"os": "ANDROID",
"osVersion": "14",
"brand": "Google",
"productModel": "sdk_gphone64_arm64",
"deviceId": "abcdef1234567890",
"deviceIdType": "ANDROID_ID",
"productFingerprint": "google/sdk_gphone64_arm64/emu64a:14/UE1A.230829.036.A1/11228894:user/release-keys",
"secretFingerprint": "0xbc311dfcef97f93fe3611722d81cd4061ee3711ea9148d7ee0ef88fe97f4fddb",
"secretFingerprint": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
"pushMessagingId": "abcdefghijklmnopqrstuvwx:APA91bABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890",
"pushMessagingProvider": "FIREBASE",
"pushMessagingId": "abcdefghijklmnopqrstuvwx:APA91bABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890",
"lastEligibilityCheck": "2025-03-21T09:09:21Z",
"nfc": false,
"emulator": true,
"appleTeamId": null
},
"activationCode": null,
"creationDate": "2025-03-21T10:07:29+01:00",
"deletionDate": null,
"activationCodeExpiryDate": "2025-03-21T10:27:29+01:00",
"authenticationMethods": [
{
"type": "DEVICE_BIOMETRIC",
"usages": [
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": {
"validityDuration": 60
}
},
{
"type": "NONE",
"usages": [
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": [
]
},
{
"type": "HYBRID_PIN",
"usages": [
"WALLET_MANAGEMENT",
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": {
"maxAttempts": 3,
"validityDuration": 60
}
}
],
"invalidActivationAttempts": null,
"userId": "100000001",
"scaWalletTag": "test",
"clientId": "123456",
"activationDate": "2025-03-21T10:09:21+01:00",
"lockDate": "2025-03-21T11:46:00+01:00",
"unlockDate": null,
"resetPinDate": "2025-03-24T10:35:05+01:00"
}
]
},
"webhook_created_at": 17428089054820,
"webhook_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"object_payload_signature": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX="
}
```
### `sca.wallet.swap`
```json [JSON]
{
"webhook": "sca.wallet.swap",
"object": "scaWallet",
"object_id": "23cbf5648a234c4fb4624036f988b0d1",
"object_payload": {
"scaWallets": [
{
"id": "23cbf5648a234c4fb4624036f988b0d1",
"status": "CREATED",
"subStatus": "CREATED_READY",
"passcodeStatus": "NOT_SET",
"locked": false,
"lockReasons": [],
"lockMessage": null,
"settingsProfile": "default",
"mobileWallet": null,
"activationCode": "0x9a63a75dfc9f78dbef298ea0635b8d21",
"creationDate": "2025-06-26T15:22:45+02:00",
"deletionDate": null,
"activationCodeExpiryDate": "2025-06-26T15:42:45+02:00",
"authenticationMethods": [
{
"type": "DEVICE_BIOMETRIC",
"usages": [
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": {
"validityDuration": 60
}
},
{
"type": "NONE",
"usages": [
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": []
},
{
"type": "HYBRID_PIN",
"usages": [
"WALLET_MANAGEMENT",
"STRONG_CUSTOMER_AUTHENTICATION"
],
"parameters": {
"maxAttempts": 3,
"validityDuration": 60
}
}
],
"invalidActivationAttempts": null,
"userId": "102267265",
"scaWalletTag": "",
"clientId": "92912345252",
"activationDate": null,
"lockDate": null,
"unlockDate": null,
"resetPinDate": null
}
]
},
"webhook_created_at": 17509441656229,
"webhook_id": "f6d4bf56-0e0f-4136-b210-e5ba5c8d3b36",
"object_payload_signature": "8sCloQ+CVXvLk1EJu8/mHTmxxxffrUKAeJLJHd4sKqWo="
}
```
---
---
url: /guide/strong-customer-authentication/sca-wallet-lifecycle.md
description: >-
Technical guide for managing the SCA Wallets life cycle, such as locking,
unlocking, and changing passcodes or PINs. Includes required parameters,
request structure, and response examples.
---
# SCA Wallet life cycle
## Locking
When you suspect that an SCA Wallet or device may have been compromised, you should lock the SCA Wallet and provide a [reason](/guide/strong-customer-authentication/introduction#locking-reasons-lockreason) for doing so.
Locking is a sensitive action, so users must be strongly authenticated before proceeding.
```bash [CURL]
curl -X PUT '{baseUrl}/core-connect/sca/scawallets/{scaWalletId}/lock' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"lockReason": "LOST_DEVICE", // see list below
"lockMessage": "string" // optional, max 256 characters
}
```
Returns a `200` HTTP Status Code and the updated SCA Wallet object.
Treezor also sends the [`sca.wallet.lock`](/guide/strong-customer-authentication/events#sca-wallet-lock) webhook.
On the SDK, this triggers the [`WalletEventListener#onWalletLocked()`](sdk#events) event.
## Unlocking
If an SCA Wallet has been [locked](#locking) by one of your [Dashboard Users](/guide/dashboard/dashboard-users) **and after the legitimacy of the device has been reestablished**, you may unlock it using the following request.
This is a sensitive action that can be done by:
* **Your Dashboard Users**, with two-factor authentication, or
* **The end user**, if they provide a per-operation SCA proof.
```bash [CURL]
curl -X PUT '{baseUrl}/core-connect/sca/scawallets/{scaWalletId}/unlock' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json'
```
Answers with a `200` HTTP Status Code and the updated SCA Wallet object.
Treezor also sends the [`sca.wallet.unlock`](/guide/strong-customer-authentication/events#sca-wallet-unlock) webhook.
Unlocking the SCA Wallet also triggers the [`WalletEventListener#onWalletUnlocked()`](sdk#events) event on the SDK.
## Deletion
A user using a single device should have a single SCA Wallet. The SCA Wallets of your users should be monitored as to avoid multiple or inactive SCA Wallets for a unique end user.
SCA Wallets should be deleted when:
* They haven't been used in a long time and probably can't be trusted anymore,
* The user declared their device stolen/lost,
* The user gets a new device that replaces the old one,
* Your commercial relationship with the user ends.
**Alert – Automatic deletion**
Treezor automatically deletes SCA Wallets that have been inactive for 6 months. An SCA Wallet is considered inactive if the last SCA Proof is older than 6 months.
The following request can be used to delete an SCA Wallet, including by the end user if they provide a per-operation SCA proof.
```bash [CURL]
curl -X DELETE '{baseUrl}/core-connect/sca/scawallets/{scaWalletId}' \
--header 'Authorization: Bearer {accessToken}'
```
Answers with a `200` HTTP Status Code and the updated SCA Wallet object.
Treezor also sends the [`sca.wallet.delete`](/guide/strong-customer-authentication/events#sca-wallet-delete) webhook.
Deleting an SCA Wallet triggers the [`WalletEventListener#onWalletDeleted()`](sdk#events) event on the SDK.
## Reset PIN (Mobile)
SCA Wallets are protected by PIN codes on end user devices. Resetting PIN codes is only available to you and your team, this is not an action that can be exposed to your end users.
This only applies to mobile SCA Wallets (i.e., SCA Wallets whose `settingsProfile` attribute is `default`).
To reset a PIN code, you can use the following request.
```bash [CURL]
curl -X PUT '{baseUrl}/core-connect/sca/scawallets/{scaWalletId}/resetPin' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json'
```
Returns a `200` HTTP Status Code and the updated SCA Wallet object.
Treezor also sends the [`sca.wallet.resetPin`](/guide/strong-customer-authentication/events#sca-wallet-resetpin) webhook.
On the SDK, this triggers the [`WalletEventListener#onCustomerCredentialsReset()`](sdk#events) event.
The end user is now able to define a new PIN from their device.
## Passcode change (Web Native)
This is considered a sensitive action, so users must be strongly authenticated before setting a new passcode (at least 6 characters). There are two use cases depending on whether the user knows their current passcode:
* **[With SCA proof](#with-sca-proof)** – If the user knows their current passcode.
* **[With 2-factor authentication](#with-2-factor-authentication)** – If the user doesn't know their current passcode.
This only applies to mobile SCA Wallets (i.e., SCA Wallets whose `settingsProfile` attribute is `webauthn`).
**Tip – Passcode is shared between devices**
Contrary to device-specific [SDK passcodes](/guide/strong-customer-authentication/sdk#pin-change), the passcode used with Web Native is not tied to the device passkeys and technically not used to access the passkeys. Therefore, the passcode is not device-specific; if a User has multiple Web Native devices enrolled, a single and unique passcode is used for all of them.
### With SCA proof
If your user already knows their passcodes, use the following request with a `delegated_end_user` JWT.
```bash [CURL]
curl -X PUT '{baseUrl}/core-connect/sca/setPasscode' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"userId": "123456",
"newPasscode": "",
"confirmPasscode": "",
"sca": "{scaProof}"
}
```
Answers with `204 Accepted` HTTP status code.
### With 2-factor authentication
If your user don't know their passcodes, use the following request with a `client_credentials` JWT while ensuring the user is who they claim to be with relevant information as necessary, such as:
* Their birthdate, email address, mobile phone number
* A one-time-password that you sent to their email address
* A one-time-password that you sent to their mobile phone
If enough conditions are met, you may contact Treezor endpoint for the user to set their new passcode with the following request.
```bash [CURL]
curl -X PUT '{baseUrl}/core-connect/sca/setPasscode' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"userId": "123456",
"newPasscode": "",
"confirmPasscode": "",
"authMethod":["OTP SMS", "OTP EMAIL", "ID", "OTHER"], // List methods used to ensure the user's identity
}
```
Answers with `204 Accepted` HTTP status code.
## Endpoints
| Endpoint | [Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/core-connect/sca/scawallets/swap`](/api-reference/api-endpoints.html#tag/SCA/swapSCAWallets){target="\_self"} | `read_write` |
| [`/core-connect/sca/scawallets/{scaWalletId}/lock`](/api-reference/api-endpoints.html#tag/SCA/putScaWallet){target="\_self"} | `read_write` |
| [`/core-connect/sca/scawallets/{scaWalletId}/resetPin`](/api-reference/api-endpoints.html#tag/SCA/resetScaWalletPin){target="\_self"} | `legal` |
| [`/core-connect/sca/scawallets/{scaWalletId}/unlock`](/api-reference/api-endpoints.html#tag/SCA/unlockScaWallet){target="\_self"} | `read_write` |
| [`/core-connect/sca/setPasscode`](/api-reference/api-endpoints.html#tag/SCA/setPasscode){target="\_self"} | `read_write` |
| [`/core-connect/sca/scawallets/{scaWalletId}`](/api-reference/api-endpoints.html#tag/SCA/deleteScaWallet){target="\_self"} | `read_write` |
---
---
url: /guide/strong-customer-authentication/securing-endpoints.md
description: >-
Guide for declaring your end users actions (passive session, active session,
or invididual), whether they are made with Treezor endpoints or not. Includes
request and examples for the external operation declaration.
---
# Securing endpoints
## Functional context
If you're eligible to SCA, you're legally required to declare the end users actions, regardless of whether they are done with [Treezor endpoints](#applying-sca-with-treezor-services) or with [your own back end](#declaring-sca-external-operations).
The actions requiring SCA can be broken down into 3 categories:
* [Passive session actions](#passive-session-actions)
* [Active session actions](#active-session-actions)
* [Individual actions](#individual-actions)
A session means that the requests of the end user to the Treezor API are [authenticated](authenticating) using a [JWT](/guide/overview/glossary#json-web-token-jwt) which:
* Was obtained with an SCA of type != [`None`](sdk#methods) (JWT with a `trz:sca` valued to `true`).
* Is not expired (i.e., obtained in the last 60 minutes as JWT have a 60-minute lifetime)
* Was used in the last 5 minutes to make any valid call to the Treezor API.
**Note – Session expiration after 5 minutes**
Even if the JWT itself hasn't expired yet, if it has not been used in the last 5 minutes to call Treezor API **the SCA session is considered expired**.
If the session has expired, the following error will be returned by the API with a `401` HTTP Status Code.
```json [JSON]
{
"errors": [
{
"type": "invalid_request",
"code": "sca_session_expired",
"message": "Your session has expired.",
"docUrl": "string"
}
]
}
```
### Passive session actions
Per-session operations with 180 days exemption.
The following actions can be done if a [session](introduction#session) with an SCA (`!= None`) was used in the last 180 days:
* Logging into the customer space
* Checking the Balance of Wallets
* Checking the Operations history of the last 90 days
**Information – Web Native only allows for active session SCA**
For [Web Native](./introduction#web-native) integrations, all the passive session actions require [per-session SCA](#per-session) when using Treezor services.
### Active session actions
Per-session operations
The following actions can be done if this very session was opened using an SCA (`!= None`), and if the session is still active.
* Ordering a [new Card](/guide/cards/creation)
* [Transferring funds](/guide/transfers/wallet-to-wallet) between Wallets belonging to the same User
* Searching for [operations](/guide/wallets/operations)
* Checking or downloading [Account Statements](/guide/wallets/account-documents) or [certificates](/guide/wallets/account-documents)
* Displaying bank account details
* Self-certifications (such as defining a tax residence, etc.)
If the session is no longer active or if this is the first time the user is authenticating, then a new session must be open with an SCA (`!= None`).
### Individual actions
For all the following operations, a per-operation SCA is required (regardless of the use of an SCA during initial authentication and session opening).
* [Activating a Card](/guide/cards/creation#activation)
* [Approving an online payment](/guide/cards/transactions-authentication) with a Card (e-commerce)
* Displaying a Card information (PAN, CVV, etc.)
* Enrolling a Card into [X-Pay](/guide/cards/x-pay-google-apple)
* Changing a [Card payment or withdrawal limits](/guide/cards/restrictions-limits#payment-withdrawal-limits)
* Changing a [Card restrictions or options](/guide/cards/restrictions-limits#options-permission-groups)
* [Modifying, displaying, and unlocking a PIN](/guide/cards/modification#change-pin)
* [Unlocking the CVV](/guide/cards/modification#unlock-cvv)
* [Updating personal information](/guide/users/introduction) (mobile phone, email, address)
* [Transferring funds between Wallets](/guide/transfers/wallet-to-wallet) belonging to distinct Users
* Adding or changing a [Beneficiary](/guide/transfers/beneficiaries)
* Creating a [SEPA transfer](/guide/transfers/credit-transfer#emitted-credit-transfers-scte)
* Initiating recurring payments or mass payment
## Applying SCA with Treezor services
You must provide an SCA proof anytime you use a Treezor API request that falls into the functional context of Strong Customer Authentication. This proof of SCA is to be presented in a specific way (i.e., data to sign in the path and [payload](/guide/strong-customer-authentication/sdk#payload)), as listed in the endpoints requiring SCA in the table below.
You may also:
* Find badges across the documentation, indicating the need for an SCA.
* Check out the [Regulatory Technical Standards](https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=CELEX:32018R0389\&from=EN) for an exhaustive and authoritative list of operations requiring SCA.
### Per Session
| Endpoint | Note |
|--- |--- |
| [`/v1/cards/CreateVirtual`](/api-reference/api-endpoints.html#tag/Cards/postCardVirtual){target="\_self"} | |
| [`/v1/cards/RequestPhysical`](/api-reference/api-endpoints.html#tag/Cards/postCardPhysical){target="\_self"} | |
| [`/cards`](/api-reference/pci-dss-dev.html#tag/Cards/createCard){target="\_self"} | |
| [`/core-connect/card/bulk`](/api-reference/api-endpoints.html#tag/Cards%20Bulk%20Creation/postBulkCard){target="\_self"} | |
| [`/v1/taxResidences`](/api-reference/api-endpoints.html#tag/User%20Tax%20Residences/postTaxresidence){target="\_self"} | |
| [`/v1/taxResidences/{taxResidenceId}`](/api-reference/api-endpoints.html#tag/User%20Tax%20Residences/putTaxresidence){target="\_self"} | |
| [`/v1/transfers`](/api-reference/api-endpoints.html#tag/Transfers/postTransfers){target="\_self"} | Only if `beneficiaryWalletId` belongs to the current User |
| [`/v1/virtualibans`](/api-reference/api-endpoints.html#tag/Virtual%20IBANs/postVirtualIban){target="\_self"} | |
| [`/v1/virtualibans`](/api-reference/api-endpoints.html#tag/Virtual%20IBANs/getvirtualibans){target="\_self"} | |
| [`/v1/virtualibans/{virtualIbanId}`](/api-reference/api-endpoints.html#tag/Virtual%20IBANs/getvirtualiban){target="\_self"} | |
| [`/v1/virtualibans/{virtualIbanId}`](/api-reference/api-endpoints.html#tag/Virtual%20IBANs/putVirtualIban){target="\_self"} | |
| [`/v1/wallets`](/api-reference/api-endpoints.html#tag/Wallets/postWallets){target="\_self"} | |
| [`/v1/wallets`](/api-reference/api-endpoints.html#tag/Wallets/getWallets){target="\_self"}| |
| [`/v1/wallets/{walletId}`](/api-reference/api-endpoints.html#tag/Wallets/getWallet){target="\_self"} | |
| [`/v1/wallets/{walletId}`](/api-reference/api-endpoints.html#tag/Wallets/putWallet){target="\_self"} | |
| [`/core-connect/account-details/{walletId}/raw`](/api-reference/api-endpoints.html#tag/Account%20Documents/getRawWalletAccountDetail){target="\_self"} | |
| [`/core-connect/account-details/{walletId}/computed`](/api-reference/api-endpoints.html#tag/Account%20Documents/getComputedWalletAccountDetail){target="\_self"} | |
| [`/core-connect/statements/{walletId}/raw`](/api-reference/api-endpoints.html#tag/Account%20Statements/getRawStatement){target="\_self"} | |
| [`/core-connect/statements/{walletId}/computed`](/api-reference/api-endpoints.html#tag/Account%20Statements/getPdfAccountStatement){target="\_self"} | |
| [`/core-connect/operations`](/api-reference/api-endpoints.html#tag/Operations/getOperations){target="\_self"} | Only for operations that are more than 90 days old |
| [`/core-connect/certificates/walletBalance/{walletId}/computed`](/api-reference/api-endpoints.html#tag/Account%20Documents/getWalletBalanceComputed){target="\_self"} | |
| [`/core-connect/certificates/walletBalance/{walletId}/raw`](/api-reference/api-endpoints.html#tag/Account%20Documents/getWalletBalanceRaw){target="\_self"} | |
| [`/core-connect/certificates/walletClosure/{walletId}/computed`](/api-reference/api-endpoints.html#tag/Account%20Documents/getWalletClosureComputed){target="\_self"} | |
| [`/core-connect/certificates/walletClosure/{walletId}/raw`](/api-reference/api-endpoints.html#tag/Account%20Documents/getWalletClosureRaw){target="\_self"} | |
| [`/core-connect/certificates/walletDomiciliation/{walletId}/computed`](/api-reference/api-endpoints.html#tag/Account%20Documents/getWalletDomiciliationComputed){target="\_self"} | |
| [`/core-connect/certificates/walletDomiciliation/{walletId}/raw`](/api-reference/api-endpoints.html#tag/Account%20Documents/getPdfAccountStatement){target="\_self"} | |
### Per Operation
| Endpoint | Data to sign in the SCA proof `body`(only if present in the [payload](/guide/strong-customer-authentication/sdk#payload)) | Note |
|--- |--- |--- |
| `/v1/auth-requests/{authRequestId}/result` | | |
| `/v1/bankaccounts` | `userId`, `bankaccountOwnerName`, `bankaccountOwnerAddress`, `bankaccountIBAN`, `bankaccountBIC`, `bankaccountType` | |
| [`/v1/beneficiaries`](/api-reference/api-endpoints.html#tag/Beneficiaries/postBeneficiary){target="\_self"} | `userId`, `name`, `nickname`, `iban`, `bic`, `usableForSct` | [*Payload example*](/guide/strong-customer-authentication/sdk#post-v1-beneficiaries) |
| [`/v1/beneficiaries/{beneficiaryId}`](/api-reference/api-endpoints.html#tag/Beneficiaries/putBeneficiary){target="\_self"} | `nickName`, `name`, `iban`, `bic`, `usableForSct`, `isActive` | |
| [`/v1/cardimages`](/api-reference/api-endpoints.html#tag/Cards/getCardImage){target="\_self"} | `cardId` | [*Payload example*](/guide/strong-customer-authentication/sdk#get-v1-cardimages) |
| [`/v1/cards/{cardId}/Activate`](/api-reference/api-endpoints.html#tag/Cards/activateCard){target="\_self"} | | [*Payload example*](/guide/strong-customer-authentication/sdk#put-v1-cards%E2%80%8B-id-%E2%80%8B-activate) |
| [`/v1/cards/{publicToken}/public-token-activation`](/api-reference/api-endpoints.html#tag/Cards/activateCardToken){target="\_self"} | | |
| [`/v1/cards/{cardId}/ChangePIN`](/api-reference/api-endpoints.html#tag/Cards/changePin){target="\_self"} | | |
| [`/v1/cards/{cardId}/setPIN`](/api-reference/api-endpoints.html#tag/Cards/setPin){target="\_self"} | | |
| [`/v1/cards/{cardId}/UnblockPIN`](/api-reference/api-endpoints.html#tag/Cards/unblockPin){target="\_self"} | | |
| [`/v1/cards/{cardId}/LockUnlock`](/api-reference/api-endpoints.html#tag/Cards/updateBlockStatus){target="\_self"} | `lockStatus` | Only when unlocking (`lockStatus` is `0`) |
| [`/v1/cards/{cardId}/Limits`](/api-reference/api-endpoints.html#tag/Cards/putLimits){target="\_self"} | `limitAtmYear`, `limitAtmMonth`, `limitAtmWeek`, `limitAtmDay`, `limitAtmAll`, `limitPaymentYear`, `limitPaymentMonth`, `limitPaymentWeek`, `limitPaymentDay`, `limitPaymentAll`, `paymentDailyLimit`, `restrictionGroupLimits` | [*Payload example*](/guide/strong-customer-authentication/sdk#put-v1-cards-cardid-limits) |
| [`/v1/cards/{cardId}/Options`](/api-reference/api-endpoints.html#tag/Cards/cardOptions){target="\_self"} | `foreign`, `online`, `atm`, `nfc` | |
| [`/v1/cards/{cardId}/unblockcvc2`](/api-reference/api-endpoints.html#tag/Cards/unblockCvcs){target="\_self"} | | |
| [`/v1/issuerInitiatedDigitizationDatas`](/api-reference/api-endpoints.html#tag/Issuer%20Initiated%20Digitization%20Data/tavRequestPOST){target="\_self"} | `cardId`, `tokenRequestor`, `additionnalData` | |
| [`/v1/cardDigitalizations/{cardDigitalizationId}`](/api-reference/api-endpoints.html#tag/Cards%20Digitalization/putcardDigitalizationsId){target="\_self"} | `status`, `reasonCode` | Only if the `status` is `unsuspend` |
| [`/v1/payouts`](/api-reference/api-endpoints.html#tag/Payouts/postPayout){target="\_self"} | `walletId`, `amount`, `currency`, `beneficiaryId` | |
| [`/core-connect/sca/scawallets/{scaWalletId}/setPasscode`](/api-reference/api-endpoints.html#tag/SCA/setPasscode){target="\_self"} | | For web native wallets only, when using a `delegated_end_user` JWT. |
| [`/core-connect/sca/scawallets/{scaWalletId}/resetPin`](/api-reference/api-endpoints.html#tag/SCA/resetScaWalletPin){target="\_self"} | | For mobile wallets only. |
| [`/core-connect/sca/scawallets/{scaWalletId}/unlock`](/api-reference/api-endpoints.html#tag/SCA/unlockScaWallet){target="\_self"} | | |
| [`/core-connect/scheduledPayment`](/api-reference/api-endpoints.html#tag/Scheduled%20Payments/postScheduledPayment){target="\_self"} | `walletId`, `beneficiaryType`, `beneficiary`, `beneficiaryLabel`, `amount`, `type`, `execAt`, `startAt`, `endAt`, `period`, `currency`, `scheduledPaymentName`, `endToEndId` | |
| [`/v1/transfers`](/api-reference/api-endpoints.html#tag/Transfers/postTransfers){target="\_self"} | `walletId`, `beneficiaryWalletId`, `amount`, `currency`, `transferTypeId` | Only if `beneficiaryWalletId` doesn't belong to the current User |
| [`/v1/users/{userId}`](/api-reference/api-endpoints.html#tag/Users/putUser){target="\_self"} | `phone`, `mobile`, `email`, `address1`, `address2`, `address3`, `postcode`, `city`, `state`, `country`, `countryName` | Only if `phone`, `mobile`, `email`, or any of the `address` attributes are modified. [*Payload example*](/guide/strong-customer-authentication/sdk#put-v1-users-userid) |
| [`/cards/{cardId}/pan`](/api-reference/pci-dss-dev.html#tag/Cards/getPAN){target="\_self"} | `cardId` | |
| [`/cards/{cardId}/pin`](/api-reference/pci-dss-dev.html#tag/Cards/getPIN){target="\_self"} | `cardId` | |
| [`/cards/{cardId}/changePIN`](/api-reference/pci-dss-dev.html#tag/Cards/putChangePin){target="\_self"} | `cardId` | |
| [`/cards/{cardId}/setPIN`](/api-reference/pci-dss-dev.html#tag/Cards/putSetPin){target="\_self"} | `cardId` | |
| [`/cards/{cardId}/cardImage`](/api-reference/pci-dss-dev.html#tag/Cards/getCardImage){target="\_self"} | `cardId` | |
| [`/cards/{cardId}/inappcryptogram/mastercard/apple-pay`](/api-reference/pci-dss-dev.html#tag/Cards/postInappApple){target="\_self"} | `cardId` | |
| [`/cards/{cardId}/inappcryptogram/mastercard/google-pay`](/api-reference/pci-dss-dev.html#tag/Cards/postInappGpay){target="\_self"} | `cardId` | |
| [`/cards/{cardId}/inappcryptogram/visa/apple-pay`](/api-reference/pci-dss-dev.html#tag/Cards/postVisaInappApple){target="\_self"} | `cardId` | |
| [`/cards/{cardId}/inappcryptogram/visa/google-pay`](/api-reference/pci-dss-dev.html#tag/Cards/postVisaInappGpay){target="\_self"} | `cardId` | |
**Best practice – Optimize user experience by avoiding subsequent calls on per-operation SCA endpoints**
When an action on your application requires several calls to per-operation SCA endpoints, the user goes through multiple SCA in a row. Split your sensitive actions on your mobile app for a better experience.
In your application, changing both the Card limits (`PUT /v1/cards/{cardId}/Limits`) and options (`PUT /v1/cards/{cardId}/Options`) at the same time and on the same screen requires 2 sequential SCA operations. This means your end user has to go through SCA twice.
To avoid this, you could offer to change Options and Limits on different screens of your application.
## SCA for Card Transactions
When eligible to SCA, most card transactions must be authenticated. Therefore, the steps of a card transaction are the following:
1. **Authentication** – Ensuring the legitimate cardholder is initiating the transaction.
2. **Authorization** – Checking the balance, limits, restrictions, etc. to accept the transaction.
3. **Transaction** – Moving the funds from the cardholders' account.
For the authentication step to be properly SCA-compliant, you must:
* [Enroll the user card for OOB authentication & SMS OTP](#card-authentication-methods-enrollment)
* [Ensure your handle card transaction authentication properly](#card-transactions-authentication)
Please note that the [3D Secure (3DS)](/guide/overview/glossary#_3d-secure-3ds) protocol on its own is not SCA-compliant. It is used as a fallback option only.
### Card authentication methods enrollment
Cards **must be registered with the 2 following methods** to accept secure online payments:
| Method | Endpoint |
| --- | --- |
| **[Out of Band (OOB)](#enrolling-to-out-of-band-authentication)** | [`/v1/cards/{cardId}/authentication-methods`](/api-reference/api-endpoints.html#tag/Card%203DSecure%20Enrollment%20\(SCA\)/postAuthMethods){target="\_self"} **Primary and mandatory** strong customer authentication of the cardholder through their payment application. |
| **[SMS method](#enrolling-to-fallback-sms-authentication)** | [`/v1/cards/Register3DS`](/api-reference/api-endpoints.html#tag/Cards/post3ds){target="\_self"} **Mandatory fallback** with a one-time password (OTP) sent by SMS. |
Cards are enrolled with both methods at the same time to allow you to request a FALLBACK to the SMS method if the Out of Band authentication is not possible during a card transaction.
#### Enrolling to Out of Band Authentication
When a User has an active (provisioned) SCA Wallet, you must enable the SCA for a Card using the following request.
```bash [CURL]
curl -X POST '{baseURL}/v1/cards/{cardId}/authentication-methods' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{
"method": "OOB"
}'
```
Returns an HTTP 201 response.
```json [JSON]
{
"publicToken": "103685666",
"id": "b7478da6-4165-4c8c-xxx0-8e9200f5162a",
"method": "OOB",
"system": "GPS"
}
```
#### Retrieving a Card authentication methods
```bash [CURL]
curl -X GET '{baseURL}/v1/cards/{cardId}/authentication-methods' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
```
Returns the Card enrollments list.
```json [JSON]
[
{
"publicToken": "103685965",
"id": "2739879",
"method": "OTPSMS",
"system": "GPS"
},
{
"publicToken": "103685965",
"id": "b7478da6-4165-4c8c-aaa0-8e9200f5162a",
"method": "OOB",
"system": "GPS"
}
]
```
#### Enrolling to fallback SMS Authentication
3D Secure provides an enhanced level of security for online (e-commerce) [payments](/guide/cards/transactions-lifecycle) by adding the possibility to authenticate the cardholder. This a **mandatory fallback** with a one-time password (OTP) sent by SMS; the card must be enrolled for [Out of Band (OOB) authentication](/guide/strong-customer-authentication/securing-endpoints#enrolling-to-out-of-band-authentication) first.
**Registering the card for 3D Secure requires a mobile phone number**. The cardholder then receives a secure code on their mobile phone when an authentication is required for an online payment. This code is unique for each payment and needs to be entered on the merchant's website or mobile application when prompted.
**Prior to this step, your must ensure the User was created with a [mobile phone number](/guide/api-basics/data-format#phones)**. Otherwise, the [User](/guide/users/introduction) must be updated with a mobile phone number.
Endpoint: [`/v1/cards/Register3DS`](/api-reference/api-endpoints.html#tag/Cards/post3ds){target="\_self"}
```bash [CURL]
curl -X POST '{baseUrl}/v1/cards/Register3DS' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{
"cardId": 123456
}'
```
This returns a Card object, but doesn't specify the 3D Secure enrolling status. Treezor also sends a [`card.register3DS`](/guide/cards/events#cardregister3ds) webhook.
**Configuration – By default, 3DS SMS are sent under the name "Secure3DS"**
You can contact Treezor and provide a new sender name that:
* Contains only alphanumeric characters (no spaces)
* Starts with a letter
* Is less than 12-character long
#### 3DSecure enrollment endpoints
Find below the list of 3DSecure endpoints (SCA Mode).
| Endpoint | Description |
| --- | --- |
| [`/v1/cards/{cardId}/authentication-methods`](/api-reference/api-endpoints.html#tag/Card%203DSecure%20Enrollment%20\(SCA\)/postAuthMethods){target="\_self"} | Define the authentication methods of a Card |
| [`/v1/cards/{cardId}/authentication-methods`](/api-reference/api-endpoints.html#tag/Card%203DSecure%20Enrollment%20\(SCA\)/getAuthMethods){target="\_self"} | Retrieve the authentication methods of a Card |
| [`/v1/cards/{cardId}/authentication-methods/{authMethodId}`](/api-reference/api-endpoints.html#tag/Card%203DSecure%20Enrollment%20\(SCA\)/getAuthMethodsDetails){target="\_self"} | Retrieve details regarding the authentication method of a Card |
| [`/v1/cards/{cardId}/authentication-methods/{authMethodId}`](/api-reference/api-endpoints.html#tag/Card%203DSecure%20Enrollment%20\(SCA\)/deleteAuthMethods){target="\_self"} | Delete the authentication method of a Card. Only available for OOB method. |
### Card transactions authentication
When a [Card Transaction](/guide/cards/transactions) goes through SCA, the following occurs:
1. **Treezor notifies you** by sending a [`card3DSv2Authentication.create`](/guide/cards/events-tx#card3DSv2authentication-create) webhook.
2. **You authenticate your end user** using [the SDK](/guide/strong-customer-authentication/sdk) and an SCA method.
3. **You inform Treezor** of the authentication result using [the dedicated endpoint](/guide/cards/transactions-authentication#notification-of-authentication-result).
4. **Treezor notifies you** of the final transaction status by sending a [`card3DSv2Authentication.update`](/guide/cards/events-tx#card3DSv2authentication-update) webhook.
**Reading – Article dedicated to Card transaction SCA**
Learn more in the [Transactions authentication (SCA)](/guide/cards/transactions-authentication) article.
## Declaring SCA External Operations
When applying SCA outside of Treezor services, you are legally required to declare the [listed end user actions](#functional-context) to Treezor. Treezor uses these declarations for reporting to the regulator.
The External Operations endpoint allows you to declare any sensitive action that:
* Required a Strong Customer Authentication (SCA) and,
* Was made from your back end (rather than Treezor's)
### Key attributes
Below are the most important External Operation attributes:
| Attribute | Type | Description |
| --- | --- | --- |
| `externalOperationId` | string | 32-character long identifier of the External Operation the database (UUIDv4). |
| `actionName` | string | The end user action that was secured by an SCA. See [list of actions](#action-names-actionname). |
| `scaProof` | string | The valid proof that authenticated the end user's action. |
| `actionDate` | string | The date on which the declared action took place. |
| `resourceIds` | array | The list of unique identifiers (strings) of the objects, conditioned by the type of action: **walletId** for `externalGetStatement`, `externalGetBalance`, `externalOperationView`, `externalOperationView90Days`, and `externalDisplayAccountDetails`**payoutId** for **transferId** in case of a payout or transfer**cardId** for `externalUpdateLimitsCard`|
| `createdAt` | string | The date and time at which the External Operation was created. |
| `scaDate` | string | The `iat` timestamp of the `scaProof` for per-operation SCA. |
| `amr` | string | The type of SCA for per-operation SCA (e.g., `CLOUD_PIN`, `HYBRID_PIN`, `DEVICE_BIOMETRIC`) |
| `externalOperationNote` | string | Comment left by Treezor after scoring, indicating a potential issue. See [List of notes](#notes-externaloperationnote). |
#### Action names (`actionName`)
The `actionName` parameter is required to declare an SCA External Operation. It can be one of the following:
| `actionName` | Description | Session |
| --- | --- | --- |
| `externalGetBalance` | Retrieve the wallet balance | [Per-session (180 days exempt.)](#passive-session-actions) |
| `externalOperationView90Days` | Retrieve the operations history for the last 90 days | [Per-session (180 days exempt.)](#passive-session-actions) | |
| `externalOperationView` | Retrieve the operations history for operations older than 90 days | [Per-session](#active-session-actions) |
| `externalDisplayAccountDetails` | Retrieve information about the Wallet (i.e., account details) | [Per-session](#active-session-actions) |
| `externalGetStatement` | Retrieve the Account Statement (i.e., operations for a given month) | [Per-session](#active-session-actions) |
| `externalMassPayoutOrderCreation` | Creation of a transfer order for a mass payout | [Per-operation](#individual-actions) |
| `externalMassTransferOrderCreation` | Creation of a transfer order for a mass transfer | [Per-operation](#individual-actions) |
| `externalScheduledPayoutOrder` | Creation of a transfer order for a scheduled or recurring payout | [Per-operation](#individual-actions) |
| `externalScheduledTransferOrder` | Creation of a transfer order for a scheduled or recurring transfer | [Per-operation](#individual-actions) |
| `externalUpdateLimitsCard` | Update of the card limits externally. | [Per-operation](#individual-actions) |
| `internalCheck` | Declare a sensitive action that is not part of Treezor's Regulatory Technical Standard but that you want to secure with strong authentication. | [Per-operation](#individual-actions) |
### Notes (`externalOperationNote`)
The `externalOperationNote` parameter displays information when there is an issue with your External Operation Declaration.
| `externalOperationNote` | Description |
| --- | --- |
| `Wrong sca value` | The JWT `trz:sca` is not to `true` |
| `Wrong JWT. Grant type must be delegated end user` | The JWT `userType` is not `user` |
| `Parse error` | The SCA proof is not readable |
| `Wrong certificate` | The SCA proof certificate is not valid |
| `Signature error` | The SCA proof is not signed |
| `AMR not allowed` | The SCA proof `amr` is not allowed |
| `Declaration delay is too long` | The time elapsed between SCA proof and the `actionDate` is over 300 seconds |
### Declare an External Operation
In order to declare an SCA External Operation, you must use a JWT `accessToken` with a `delegated_end_user` grant type and the `read_write` scope. See the [SCA Authentication](authenticating) article for more information.
You can then use the following request to declare an external operation.
```bash [CURL]
curl -X POST '{baseUrl}/core-connect/sca/externalOperations' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is a `{payload}` example:
```json [JSON]
{
"actionName": "string", // Required
"scaProof": "string", // Conditional
"actionDate": "date", // Required - RFC 3339
"resourceIds":[""] // Conditional depending on the actionName
}
```
Returns the External Operation object if successful.
```json [JSON]
{
"externalOperationId": "7a5740ed-b1ae-4afd-940b-1193275728ab",
"actionName": "externalScheduledTransferOrder",
"scaProof": "[...]MJsrki4orRnqQ",
"actionDate": "2024-02-16T14:37:04+01:00",
"resourceIds": [
"12345",
"67890"
],
"createdAt": "2024-02-16T14:37:05+01:00",
"scaDate": "2024-02-16T14:37:04+01:00",
"amr": "HYBRID_PIN",
"externalOperationNote": "",
"externalOperationResponseCode": 0 // For Treezor purposes only
}
```
### Update an External Operation
You must update per-operation payment external operations in order to link all subsequent payments to the initial declaration.
For instance, for recurring or mass payments, the steps are the following:
1. Declare your External Operation with [`/core-connect/sca/externalOperations`](/api-reference/api-endpoints.html#tag/SCA%20External%20Operations/postExtOperation){target="\_self"}
2. When the corresponding payments are created, update your external Operation by adding the `id` with [`/core-connect/sca/externalOperations/{externalOperationId}`](/api-reference/api-endpoints.html#tag/SCA%20External%20Operations/putExtOperation){target="\_self"}
Each recurring payment must be declared and linked to the original External Operation declaration. In the case of mass payments, all the payment ids must be declared when updating the External Operation.
Use the following request to update an External Operation declaration.
```bash [CURL]
curl -X PUT '{baseUrl}/core-connect/sca/externalOperations/{externalOperationId}' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is a `{payload}` example:
```json [JSON]
{
"resourcesIds":["54321", "12345"] // Required
}
```
Returns the External Operation object if successful, with the updated list of `resourceIds`.
```json [JSON]
{
"externalOperationId": "7a5740ed-b1ae-4afd-940b-1193275728ab",
"actionName": "externalScheduledPayoutOrder",
"scaProof": "[...]MJsrki4orRnqQ",
"actionDate": "2024-02-16T14:37:04+01:00",
"resourceIds": [
"54321",
"12345"
],
"createdAt": "2024-02-16T14:37:05+01:00",
"scaDate": "2024-02-16T14:37:04+01:00",
"amr": "HYBRID_PIN",
"externalOperationNote": "",
"externalOperationResponseCode": 0 // For Treezor purposes only
}
```
### External Operation object
```json [JSON]
{
"externalOperationId": "7a5740ed-b1ae-4afd-940b-1193275728ab",
"actionName": "externalScheduledPayoutOrder",
"scaProof": "[...]MJsrki4orRnqQ",
"actionDate": "2024-02-16T14:37:04+01:00",
"resourceIds": [
"12345",
"67890"
],
"createdAt": "2024-02-16T14:37:05+01:00",
"scaDate": "2024-02-16T14:37:04+01:00",
"amr": "HYBRID_PIN",
"externalOperationNote": "",
"externalOperationResponseCode": 0 // For Treezor purposes only
}
```
### External Operation endpoints
| Endpoint | [Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/core-connect/sca/externalOperations`](/api-reference/api-endpoints.html#tag/SCA%20External%20Operations/postExtOperation){target="\_self"} Create an SCA External Operation Declaration | `read_write` |
| [`/core-connect/sca/externalOperation/{externalOperationId}`](/api-reference/api-endpoints.html#tag/SCA%20External%20Operations/putExtOperation){target="\_self"} Update an SCA External Operation Declaration | `read_write` |
---
---
url: /guide/transfers/credit-transfer.md
description: >-
Technical guide for emitting and receiving SEPA Credit Transfers (SCT).
Includes required parameters, request structure, and response examples.
---
# SEPA Credit Transfers (SCT)
[SEPA Credit Transfers (SCT)](/guide/overview/glossary#sepa-credit-transfer-sct) allow the initiator of the transfer (sender) to make Euro-denominated payments to [SEPA](/guide/overview/glossary#single-euro-payments-aera-sepa) countries accounts.
At Treezor, SCT can be used in two directions:
* [`SCTR`](#received-credit-transfers-sctr) are Received into a Wallet and mapped to **Payin** objects
* [`SCTE`](#emitted-credit-transfers-scte) are Emitted from a Wallet and mapped to **Payout** objects
## Received Credit Transfers (SCTR)
When an SCTR is received, a Payin object is created, along with a [`payin.create`](/guide/transfers/events#payin-create-1) webhook.
Treezor receives batches of SCTR from other banks every worked day between 6:30 and 19:00 Paris local time. They are handled and Wallets are credited as they are received.
**Tip – You can also provide [Virtual IBANs](/guide/wallets/iban) to receive SCTR**
Virtual IBANs have many benefits over your main IBAN (restriction in the direction they can be used, restriction in validity period, easier funds movements categorization, etc.).
### The SCTR Payin object
```json [JSON]
{
"payins": [
{
"payinId": "12345",
"payinTag": null,
"walletId": "34567",
"userId": "852741", // Valued to 3 initially in Production. DO NOT USE.
"payinStatus": "VALIDATED", // Funds are available to the Wallet owner
"paymentMethodId": "20",
"messageToUser": "Transfer to my Wallet",
"subtotalItems": "100.00",
"subtotalServices": "0.00",
"subtotalTax": "0.00",
"amount": "100.00",
"currency": "EUR",
"createdDate": "2018-01-01 17:00:00",
"walletEventName": "Wallet Test",
"walletAlias": "test-wallet-abcd",
"userFirstname": "CMA",
"userLastname": "",
"codeStatus": "140005",
"informationStatus": "",
"refundAmount": null,
"ibanFullname": "ALEX OAK",
"DbtrIBAN": "FR763000401544999999999123",
"ibanBic": "BNPAFRPP",
"ibanTxEndToEndId": "XXXXXXXXX",
"ibanTxId": "180799999990123",
"forwardUrl": null,
"paymentAcceptedUrl": null,
"paymentRefusedUrl": null,
"paymentWaitingUrl": null,
"paymentExceptionUrl": null,
"paymentCanceledUrl": null,
"payinDate": null,
"mandateId": null,
"creditorName": "WILL OAK",
"creditorAddressLine": null,
"creditorCountry": null,
"creditorIban": "FR761679999999999999011456",
"creditorBIC": "TRZOFR21XXX",
"virtualIbanId": null,
"virtualIbanReference": null,
"ibanId": "995d69d1839999999999a6935979ea8110d3"
}
]
}
```
**Caution – `UserId` initial value in Production**
In [Production environment](/guide/api-basics/environments), all SCTR are initially received with `userId` attribute valued to `3`. **It is strictly forbidden to use this value, this is a technical user for Treezor use only**.
### Rejection of an SCTR
#### Immediate rejection
An SCTR can be immediately rejected for [multiple reasons](error-codes#sctr-errors).
In this case, a [`sepa.return_sctr`](/guide/transfers/events#sepa-return-sctr) webhook is sent with the [reason code](error-codes#sct-errors) provided in the [`return_reason_code`](events#sepa-return-sctr) attribute.
#### Delayed rejection
Treezor enforces [AML/CFT](/guide/overview/glossary#anti-money-laundering-and-countering-the-financing-of-terrorism-aml-cft) checks before validating an SCTR.
When a suspicious SCTR is encountered, the SCTR funds are frozen and Treezor sends you:
* A [`payinrefund.create`](events#payinrefund-create-1) webhook with `reasonTms` attribute set to `null` and `payinrefundStatus` attribute set to `PENDING` (which freezes the funds).
* A [`payinrefund.update`](events#payinrefund-update-1) webhook with `reasonTms` attribute populated by an explanation.
Upon further inspection by Treezor, the following occurs depending on whether the anomaly is confirmed:
* **No anomaly** – A [`payinrefund.cancel`](events#payinrefund-cancel) webhook is sent (the wallet can be credited by the SCTR).
* **Anomaly confirmed** – A [`payinrefund.update`](events#payinrefund-update-1) webhook is sent, with a `VALIDATED` `payinrefundStatus` (which refunds the SCTR).
**Information – [AML/CFT](/guide/overview/glossary#anti-money-laundering-and-countering-the-financing-of-terrorism-aml-cft) inspection by Treezor can last up to 48h**
Therefore, an SCTR can be delayed by up to 48 hours.
## Emitted Credit Transfers (SCTE)
Treezor allows you to send funds from wallets to external accounts using SCTE.
### Requirements
* The sender's Wallet must be valid and not [frozen](/guide/users/introduction#freezing)
* The sender's User must be valid
* You have the IBAN of the recipient
* You have created an active [Beneficiary](beneficiaries) using this IBAN
* You have requested a [Beneficiary Validation](./beneficiaries#beneficiary-validation-vop)
Although SCTE can be created an any time, they will only take place on a [SEPA Open Banking Day](/guide/overview/glossary#sepa-open-banking-days).
### Parameters
| Attribute | Type | Description |
| --- | --- | --- |
| `walletId` | integer | The unique identifier of the debited Wallet. |
| `beneficiaryId` | integer | The unique identifier of the Beneficiary of the Transfer. You must have created the [Beneficiary](./beneficiaries#sepa-beneficiaries) object beforehand. |
| `beneficiaryValidationId` | string | The unique identifier of the [Beneficiary Validation](./beneficiaries#beneficiary-validation-vop). |
| `amount` | string | The amount of the credit transfer. |
| `currency` | string | The currency of the credit transfer. Must be `EUR`. |
| `supportingFileLink` | string | The HTTPS link to the supporting documents file, which is mandatory if the payout exceeds €10,000 (B2C) or €50,000 (B2B). The protocol must be secure (HTTPS). See [processing](#processing) for more information. |
| `label` | string | The payout label that will be displayed on the receiver's bank account. |
| `endToEndId` | string | Unique identification assigned by the final client to unambiguously identify the transaction. |
| `accessTag` | string | A unique identifier used to enforce [Idempotency](/guide/api-basics/idempotency). In this specific case, the value can't exceed 245 characters. |
**API – API Reference available**
For more details regarding the Payout attributes, check the [Payouts](/api-reference/api-endpoints.html#tag/Cards){target="\_self"} section of the API Reference.
**Best practice – Enforce [Idempotency](/guide/api-basics/idempotency) to avoid duplicates**
This allows you to avoid the costs of handling duplicated requests.
### Request
Endpoint: [`/v1/payouts`](/api-reference/api-endpoints.html#tag/Payouts/postPayout){target="\_self"}
Here is an example of `{payload}`:
```json [JSON]
{
"walletId": {walletId},
"beneficiaryId": {beneficiaryId},
"beneficiaryValidationId": "{beneficiaryValidationId}",
"amount": "1000.43",
"currency": "EUR"
}
```
Returns the Payout object, with its `payoutStatus` set to `PENDING` at first. You will then receive sequentially the following webhooks.
| Webhook | When | Specific attributes |
| --- | --- | --- |
| [`payout.create`](/guide/transfers/events#payout-create-1) | The SCTE is created. | `PENDING` status and `160001` codeStatus|
| [`payout.update`](/guide/transfers/events#pending) | The SCTE is sent to the SEPA network. | `PENDING` status and `160014` codeStatus |
| [`payout.update`](/guide/transfers/events#validated) | The SCTE sender's wallet is debited. | `VALIDATED` status |
```json [JSON]
{
"payouts":[
{
"payoutId": "2XX40",
"payoutTag": "25XXXXXXXXXXXXXXXX86f5cb",
"payoutStatus": "VALIDATED",
"payoutTypeId": 1,
"payoutType": "Credit Transfer",
"walletId": "85090",
"label": "Remboursement",
"payoutDate": "2017-10-04",
"amount": "1000.43",
"currency": "EUR",
"partnerFee": "0",
"createdDate": "2017-10-04 09:37:34",
"modifiedDate": "2017-10-04 09:55:57",
"walletEventName": "XXXXXXXAB",
"walletAlias": "XXXXXXXXXX",
"userLastname": "",
"userFirstname": "",
"userId": "636338",
"bankaccountIBAN": "XXXXXXXXXXXXXXXXXXXXXXXX",
"codeStatus": "160004",
"informationStatus": "",
"supportingFileLink": "",
"endToEndId": "2dbb81b26db94db3b530988b4189aad7",
"reasonCode": null,
"reasonDescription": null,
"internationalBeneficiaryId": null,
"quotationId": null,
"metadata": null,
"totalRows": null,
"beneficiaryValidationId": "f8e4a7b2-c1d3-4e5a-8b0f-9c2d1e0a3b5c"
}
]
}
```
Please note that to retrieve the beneficiary IBAN, you can fetch the Beneficiary object using the `beneficiaryId`.
### Processing
Emitted SEPA Credit Transfers (SCTE) are **executed the next working day** when requested after the cut-off time (10:30 AM).
When the SCTE exceeds €10,000 (B2C) or €50,000 (B2B), you must provide support documents in the `supportingFileLink` parameter:
* An invoice, bill, contract, or similar document.
* A RIB of the creditor, edited by the creditor's bank.
Support documents may be required for additional controls if Treezor deems the transaction of interest.
Treezor is entitled to refuse an SCTE when the aforementioned requirements are not met, or upon suspicion of fraudulent activity.
### Rejection of an SCTE
A beneficiary's bank can reject an SCTE for [multiple reasons](error-codes#sctr-errors).
In this situation a [`payoutrefund.create`](/guide/transfers/events#payoutrefund-create-1) webhook is sent, with the [`reasonCode`](error-codes#sct-errors) for the rejection provided.
### Recalling an SCTE
To recall an SCTE, please [check out the dedicated article](sepa-recalls#scte-recalls).
## Mass Payouts
The Mass Payout feature allows you to request up to 1,000 SEPA Credit Transfer emissions at once from a single wallet.
Because of the [Verification of Payee (VoP)](/guide/overview/glossary#verification-of-payee-vop) obligation, the Mass Payouts only apply for non-consumers end users who have explicitly opted out of the VoP service.
### Mass Payout initiation
Mass Payout is only available for the following Users:
* Legal entities (`userTypeId` other than `1`), and
* [Self-employed individuals](/guide/users/physical#self-employed-users)
You must ensure you collect their approval for opting out of VoP.
#### Parameters
| Attribute | Type | Description |
|--- |--- |--- |
| `vopOptOut` | boolean | Upon setting this value to `true`, you declare that you have collected the end users' consent to opt out of the VoP service. |
| `massPayoutTag` | string | Custom field which **value must be unique**, as Treezor uses this field to verify the uniqueness of the request. |
| `payouts` | array of objects | The list of payouts to include in the batch, with the following mandatory parameters: `payoutTag`, `walletId` (the same wallet for all the payouts of the batch), `beneficiaryId`, `amount`, and `currency`. Max. 1,000 items. |
**API – API Reference available**
For a complete list of Mass Payout attributes, check the [Payouts](/api-reference/api-endpoints.html#tag/Payouts){target="\_self"} section of the API Reference.
#### Request example
Endpoint: [`/v1/massPayouts`](/api-reference/api-endpoints.html#tag/Payouts/postMassPayout){target="\_self"}
```bash [CURL]
curl -X POST '{baseUrl}/v1/massPayouts' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"massPayoutTag": "ref-pay-nov-2024",
"vopOptOut": true,
"payouts": [
{
"payoutTag": "aaa",
"accessTag": "aaa",
"walletId": 1,
"payoutTypeId": 1,
"beneficiaryId": 1,
"label": "aaa",
"endToEndId": "123",
"amount": "100.28",
"currency": "EUR",
"supportingFileLink": ""
},
{
"payoutTag": "bbb",
"accessTag": "bbb",
"walletId": 1,
"payoutTypeId": 1,
"beneficiaryId": 1,
"label": "bbb",
"endToEndId": "456",
"amount": "101.29",
"currency": "EUR",
"supportingFileLink": ""
}
]
}
```
Returns the following information about the Mass Payout if successful:
```json [JSON]
{
"massPayoutId": "8b9dacf4-6acf-407b-953c-fcbb21355c1c",
"massPayoutTag": "ref-pay-nov-2024",
"vopOptOut": true,
"createdDate": "2024-04-24 08:55:26"
}
```
Treezor also sends a [`payout.create`](/guide/transfers/events#payout-create-1) webhook for each successfully created payout in the batch.
### Retrieve Mass Payout
You can retrieve a Mass Payout object to get information regarding the batch, including successful and failed payout creations.
#### Request example
Endpoint: [`/v1/massPayouts/{massPayoutId}`](/api-reference/api-endpoints.html#tag/Payouts/getMassPayoutStatus){target="\_self"}
```bash [CURL]
curl -X GET '{baseUrl}/v1/massPayouts/{massPayoutId}' \
--header 'Authorization: Bearer {accessToken}'
```
Returns the following Mass Payout:
```json [JSON]
{
"massPayoutId": "8b9dacf4-6acf-407b-953c-fcbb21355c1c",
"massPayoutTag": "ref-pay-nov-2024",
"vopOptOut": true,
"createdDate": "2024-04-24 08:55:26",
"processedDate": "2024-04-24 09:55:26",
"createdPayouts": {
"count": 20,
"payoutIds": [
"12345"
]
},
"failedPayoutCreations": {
"count": 5,
"payouts": [
{
"tag": "string",
"reason": "AUTHENTICATION_ERROR"
}
]
}
}
```
---
---
url: /guide/transfers/direct-debit.md
description: >-
Technical guide for emitting and receiving SEPA Direct Debits (SDD). Includes
required parameters, request structure, and response examples.
---
# SEPA Direct Debits (SDD)
[SEPA Direct Debit (SDD)](/guide/overview/glossary#sepa-direct-debit-sdd) allows the recipient of the transfer to collect Euro-denominated payments from [SEPA](/guide/overview/glossary#single-euro-payments-aera-sepa) countries accounts. This type of transfer is initiated by the creditor, hence requiring an IBAN and a debtor-approved [Mandate](/guide/transfers/mandates).
At Treezor, SDD can be used in two directions:
* [`SDDR`](#received-direct-debits-sddr) are Received into a Wallet and mapped to **Payout** objects
* [`SDDE`](#emitted-direct-debits-sdde) are Emitted from a Wallet and mapped to **Payin** objects
## Received Direct Debits (SDDR)
Treezor allows for the Wallets to be debited using SEPA Direct Debit (SDDR).
They can be received by Treezor between 24h and 14 days before the desired SDD [effective date](/guide/overview/glossary#effective-date).
While the creditor of the SDDR is always a business, there are 2 types of SDDR depending on the nature of the debtor:
| Type | Debtor | Specific policies |
| --- | --- | --- |
| **SDDR Core** | Business or private individual | Refund is possible Accepted by default, can be blocked by blacklisting [UMRs](/guide/overview/glossary#unique-mandate-reference-umr) on the [Beneficiary](/guide/transfers/beneficiaries) |
| **SDDR B2B** | Legal entity or individual acting for professional purposes | Refund is not possible Denied by default, can be authorized by whitelisting [UMRs](/guide/overview/glossary#unique-mandate-reference-umr) on the [Beneficiary](/guide/transfers/beneficiaries) |
**Tip – [Virtual IBAN](/guide/wallets/iban) SDD reception is also supported**
You may provide a Virtual IBAN to receive a SEPA Direct Debit into a Wallet. Virtual IBANs have many benefits over your main IBAN (direction and validity period restrictions, easier funds movements categorization, etc.).
### Receiving an SDDR
When an SDD is received, Treezor sends a [`sepa_sddr.reception`](events#sepa-sddr-reception) webhook, so you can inform the end user about the Direct Debit and its amount.
Treezor also controls the validity of the operation (e.g., the wallet is active, the Beneficiary not blacklisted, etc.). If the controls:
* **Succeed**: The [Balance](/guide/wallets/balances) and [Authorized Balance](/guide/wallets/balances) of the Wallet remain unaffected until the SDD [effective date](/guide/overview/glossary#effective-date).
* **Fail**: Treezor sends a [`sepa.reject_sddr_core`](events#sepa-reject-sddr-core) or a [`sepa.reject_sddr_b2b`](events#sepa-reject-sddr-b2b) webhook.
**Best practice – Inform your end users of the SDD reception**
They need to provision their Wallet to cover the corresponding amount.
On the [effective date](/guide/overview/glossary#effective-date) of the SDD, Treezor:
* Re-runs the controls made when the SDD was initially received.
* Checks if the Wallet is sufficiently provisioned.
* Checks if the [Beneficiary](/guide/transfers/beneficiaries) was created (SDDR B2B) or automatically creates the [Beneficiary](/guide/transfers/beneficiaries) (SDDR Core), which sends a [`beneficiary.create`](events#beneficiary-create) webhook.
Then, if the controls:
* **Succeed**: Treezor creates the Payout and sends a [`payout.create`](events#payout-create) webhook (`VALIDATED` status).
* **Fail**: Treezor sends a [`sepa.return_sddr`](events#sepa-return-sddr) or a [`sepa.refund_sddr`](/guide/transfers/events#sepa-refund-sddr) webhook (no payout is created).
**Reading – SDDR Rejection**
Learn more about received SEPA Direct Debit rejection in the [SDDR Rejection](#rejection-of-an-sddr) section.
### The SDDR Payout object
The SDDR takes the form of a payout object, structured and valued as follows.
Please note that to retrieve the beneficiary IBAN, you can fetch the Beneficiary object using the `beneficiaryId`.
```json [JSON]
{
"payouts": [
{
"payoutId": "12345",
"payoutTag": "some-tag",
"payoutStatus": "PENDING",
"payoutTypeId": 2,
"payoutType": "Direct Debit",
"walletId": "258024",
"beneficiaryId": "33587",
"uniqueMandateReference": null,
"label": "Direct Debit SEAP ALEX OAK",
"payoutDate": "2018-01-10",
"amount": "100.00",
"currency": "EUR",
"partnerFee": "0",
"createdDate": "2018-01-01 11:00:00",
"modifiedDate": "0000-00-00 00:00:00",
"walletEventName": "Wallet-Client",
"walletAlias": "test-wallet",
"userLastname": "",
"userFirstname": "",
"userId": "98765",
"bankaccountIBAN": "ENCRYPTED IBAN",
"codeStatus": "160001",
"informationStatus": "",
"supportingFileLink": "",
"endToEndId": "2dbb81b26db94db3b530988b4189aad7",
"reasonCode": null,
"reasonDescription": null,
"internationalBeneficiaryId": null,
"quotationId": null,
"metadata": null,
"totalRows": null,
"beneficiaryValidationId": null
}
]
}
```
You can check the [list of SDDR Errors Codes](error-codes#sddr-errors).
### Rejection of an SDDR
#### Rejection upon reception by Treezor
If the SDD is not valid, you receive a [`sepa.reject_sddr_core`](/guide/transfers/events#sepa-reject-sddr-core) or a [`sepa.reject_sddr_b2b`](/guide/transfers/events#sepa-reject-sddr-b2b) webhook. The [Wallet](/guide/wallets/introduction) [Balance](/guide/wallets/balances) is not affected.
#### Rejection on the effective date
If the SDD operation can't take place on (or after) the effective date, Treezor sends you:
* A [`sepa.return_sddr`](/guide/transfers/events#sepa-return-sddr) webhook (e.g., insufficient funds) **or**
* A [`sepa.refund_sddr`](/guide/transfers/events#sepa-refund_sddr) webhook (unexpected delays in the controls or transmission of the SDD).
### Refunding an SDDR
You can create a refund for an SDDR (Core only), depending on the `reasonCode`.
| `reasonCode` | SDDR Core Refund |
| --- | --- |
| `MD01` | |
| `MD06` | |
[Regulated Institution](/guide/overview/glossary#regulated-institution) can emit SDDR Core Refunds regardless of the reason code.
#### Parameters
Below some key attributes for the payout refund.
| Attribute | Type | Description |
| --- | --- | --- |
| `payoutId` | string | The unique identifier of the payout (SCTE Inst) for which the recall is to be made. |
| `reasonCode` | string | Must be one of the following: `MD01` (No Mandate) – Up to 13 months after the collection date, as the operation in unauthorized.`MD06` (Refund Request By End Customer) – Up to 8 weeks after the collection date. |
| `requestAmount` | number | The amount of the refund request. Defaults to the initial payout amount. |
| `requestCurrency` | number | The currency of the refund request. Defaults to the initial payout currency. |
#### Request example
Endpoint: [`/v1/payoutRefunds`](/api-reference/api-endpoints.html#tag/Payout%20Refunds/postPayoutRefund){target="\_self"}
```bash [CURL]
curl -X POST '{baseUrl}/v1/payoutRefunds' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"payoutId": "bf9367cb-22be-4a86-ad68-8f30fxxxx15",
"accessTag": "test-{timestamp}", // max. 250 characters
"payoutRefundTag": "test", // max. 250 characters
"requestAmount": 1000.10,
"requestCurrency": "EUR",
"reasonCode": "MD06"
}
```
Returns a payoutRefund object.
```json [JSON]
{
"payoutRefunds": [
{
"id": "f0eb0186-1592-4fb8-84a1-a65db6901234",
"payoutRefundTag": "test",
"codeStatus": "790001",
"informationStatus": "PENDING",
"payoutId": "bf9367cb-22be-4a86-ad68-8f30fxxxx15",
"requestAmount": 1000.1,
"requestCurrency": "EUR",
"requestComment": "",
"reasonCode": "MDO6",
"refundAmount": 1000.1,
"refundCurrency": "EUR",
"refundDate": "",
"refundComment": "",
"negativeResponseReasonCode": "",
"createdDate": "2024-03-14 17:09:19",
"modifiedDate": ""
}
]
}
```
Treezor sends you a [`payoutrefund.create`](/guide/transfers/events#payoutrefund-create) webhook with its status set to `PENDING`. Then, the refund can be either accepted or declined by the debiting bank:
* **Accepted** – You receive a [`payoutrefund.update`](/guide/transfers/events#payoutrefund-update) webhook (`VALIDATED` status) which concludes the refund.
* **Declined** – You receive a [`payoutrefund.update`](/guide/transfers/events#payoutrefund-update) webhook (`CANCELED` status) and the refund doesn't take place.
Declines may occur if the SDDR is more than 8-week old or if the refund reason was improperly set, for instance.
You can retrieve an SDDR Core Refund by using the [`/v1/payoutRefunds/{payoutRefundId}`](/api-reference/api-endpoints.html#tag/Payout%20Refunds/getPayoutRefund){target="\_self"} endpoint.
Here is a diagram for an SDDR Core Refund processing.
```mermaid
flowchart TD
A("You create an SDDR Refund")
B("The corresponding bank receives the request")
C("Treezor receives the response")
D("Treezor sends a `payoutrefund.update` webhook with `informationStatus=VALIDATED`")
E("Treezor sends a `transaction.create` webhook")
F("Treezor sends a `balance.update` webhook")
G("Treezor sends a `payoutrefund.cancel` webhook")
H("Treezor sends a `payoutrefund.create` webhook")
A --> B
D --> E --> F
B --> H --> C
C -- Rejected --> G
C -- Accepted --> D
class A dark;
class B neutral;
class C neutral;
```
## Emitted Direct Debits (SDDE)
Treezor allows [Users](/guide/users/introduction) to debit funds from somebody else's account using SEPA Direct Debit (SDDE).
### Creating an SDDE
**Prerequisites – Prior to making an SDDE, you must have a:**
* **SEPA Creditor Identifier (SCI)** – Contact Treezor to obtain one.
* **[Mandate](/guide/transfers/mandates) signed by the debtor** – With the correct [`sddType`](mandates#mandatory-parameters), explicitly allowing you to initiate a transfer, and that you must store as proof in case of litigation.
Also, the debit date (`payinDate`) must be on a [SEPA Open Banking Day](/guide/overview/glossary#sepa-open-banking-days).
#### Parameters
Below are the main parameters of a SEPA Direct Debit Payin.
| Attribute | Type | Description |
| --- | --- | --- |
| `paymentMethodId` | integer | Must be `21` for SDDE Core, or `22` for SDDE B2B. |
| `walletId` | integer | The unique identifier of the credited Wallet. |
| `mandateId` | integer | The unique identifier of the associated [Mandate](/guide/transfers/mandates) |
| `amount` | number | The amount of the Payin. |
| `currency` | string | The currency of the Payin. Must be `EUR`. |
| `payinDate` | string | The [desired date](/guide/overview/glossary#effective-date) of the Payin, which must be a [SEPA Open Banking Day](/guide/overview/glossary#sepa-open-banking-days). Format: YYYY-MM-DD The earliest date you can define depends on when the payin is made compared to cut-off time (7:55PM UTC+1): **Before** – On the next SEPA Open Banking Day**After** – On the second next SEPA Open Banking DayDefaults to the third SEPA Open Banking Day following the payin creation if left empty. |
| `messageToUser` | string | Message to send to Wallet of the user. For SEPA Direct Debit Core payment method, this parameter reconciles information transmitted to the Debtor (i.e., Invoice number). In this case, it can't exceed 140 characters. |
#### Request
Here is an example of `{payload}`:
```json [JSON]
{
"walletId": {walletId},
"paymentMethodId": 21, // Or 22 for SDDE B2B
"messageToUser": "Invoice number 089063",
"mandateId": {mandateId},
"amount": 1.25,
"currency": "EUR"
}
```
Returns the Payin object, with its status set to `PENDING`. You will receive the corresponding [webhook](/guide/transfers/events) on the [desired Payin date](/guide/overview/glossary#effective-date) (`payinDate`).
```json [JSON]
{
"payins": [
{
"payinId": "",
"payinTag": "",
"payinStatus": "", // is set to PENDING until the payinDate
"codeStatus": ,
"informationStatus": "",
"walletId": , // the wallet to credit
"userId": "", // valued to 3 initially in Production. DO NOT USE.
"cartId": ,
"walletEventName": "",
"walletAlias": "",
"userFirstname": "",
"userLastname": "",
"messageToUser": "", // commentary
"paymentMethodId": ,
"amount": "",
"currency": "",
"distributorFee": "",
"createdDate": "",
"createdIp": "",
"ibanFullname": "",
"ibanId": "",
"ibanBic": "",
"ibanTxEndToEndId": "",
"ibanTxId": "",
"refundAmount": "",
"totalRows": "",
"forwardUrl": "",
"payinDate": "", // desired date of effect, or "effective date"
"mandateId": "", // is ID of the associated Mandate
"creditorName": "",
"creditorAddressLine": "",
"creditorCountry": "",
"creditorIban": "",
"creditorBIC": "",
"virtualIbanId": ,
"virtualIbanReference": ""
[...] // some attributes are hidden
}
]
}
```
**Caution – `userId` value in Production initially set to `3`.**
It is strictly forbidden to use this value, this is a technical user for Treezor use only.
#### Processing flow
Depending on the evolution of the emitted SEPA Direct Debit, you might receive the following webhooks for the payin.
| Event | | Status | Description |
| --- | :---: | --- | --- |
| `payin.create` | | `PENDING` | Treezor issues an SDDE Payin. |
| `payin.update` | | `VALIDATED` | The SDDE is accepted. |
| `payin.cancel` | | `CANCELED` | The SDDE is rejected **before the effective date**. |
Here is the diagram for an SDDE processing.
```mermaid
flowchart TD
A("Treezor issues an SDDE")
B("Sends a payin.create webhook payinStatus: PENDING")
C("Sends a payin.update webhook payinStatus: VALIDATED")
D("Sends a payin.cancel webhook payinStatus: CANCELED")
E("Sends a transaction.create webhook")
F("Sends a balance.update webhook")
A --> B -- Accepted --> C
B -- Rejected --> D
C --> E --> F
class A MermaidNeutral;
class B neutral;
class C neutral;
class D neutral;
class E neutral;
class F neutral;
```
**Information – Funds usability delays**
Depending on your configuration and contract, usability delays can occur after settlement date. Please contact Treezor for more information.
### Cancelling an SDDE
You can cancel an SDDE before Treezor processes it. SDDE processing at Treezor occurs daily at 8AM UTC+1.
| Payin creation time | Deletable until |
| --- | --- |
| 2PM UTC+1 | 8:OO AM UTC+1 on the next day. |
| 7AM UTC+1 | 8:OO AM UTC+1 on the same day. |
#### Request
```bash [CURL]
curl -X DELETE '{baseUrl}/v1/payins/{payinId}' \
--header 'Authorization: Bearer {accessToken}'
```
Returns the Payin object, with its status set to `CANCELED`. Treezor also sends a `payin.cancel` webhook.
```json [JSON]
{
"payins": [
{
"payinId": "",
"payinTag": "",
"payinStatus": "CANCELED", // is set to CANCELED
"codeStatus": 140004,
"informationStatus": "",
"walletId": ,
"userId": "",
"cartId": ,
"walletEventName": "",
"walletAlias": "",
"userFirstname": "",
"userLastname": "",
"messageToUser": "",
"paymentMethodId": ,
"amount": "",
"currency": "",
"distributorFee": "",
"createdDate": "",
"createdIp": "",
"ibanFullname": "",
"ibanId": "",
"ibanBic": "",
"ibanTxEndToEndId": "",
"ibanTxId": "",
"refundAmount": "",
"totalRows": "",
"forwardUrl": "",
"payinDate": "",
"mandateId": "",
"creditorName": "",
"creditorAddressLine": "",
"creditorCountry": "",
"creditorIban": "",
"creditorBIC": "",
"virtualIbanId": ,
"virtualIbanReference": ""
[...] // some attributes are hidden
}
]
}
```
If it is too late for you to cancel the SDDE, you receive the following HTTP 400 error:
```json [JSON]
{
"errors": [
{
"type": "invalid_request",
"code": "input_validation_error",
"message": "The payin has already been sent to the scheme",
"docUrl": "https://docs.treezor.com/guide/api-basics/response-codes.html"
}
]
}
```
### Rejection of an SDDE
SDDE can be rejected either before or after the [effective date](/guide/overview/glossary#effective-date).
* **Reject** – Refusal of the direct debit by the debited PSP before the effective date.
* **Return** – Refusal of the direct debit by the debited PSP up to 5 (core) or 3 (B2B) days banking days after the effective date.
* **Refund** (Core only) – Request of reimbursement from the debtor and initiated by their PSP after the effective date. This refund can be sent up to 13 months after the settlement date in case of a claim for unauthorized operation.
#### Rejection before effective date
If the debtor bank rejects the SDDE, Treezor sends you a [`payin.cancel`](/guide/transfers/events#payin-cancel) webhook with:
* The status set to `CANCELED`
* The [reason code](/guide/transfers/error-codes#sdd-reason-codes) for rejection (e.g., closed account) in the `informationStatus` field.
#### Rejection after effective date
Although SDDE Returns and Refunds are 2 distinct R-transactions, Treezor handles them the same way.
When receiving a return/refund for an SDDE, Treezor will try to refund the transaction and sends the corresponding webhooks. Those webhooks contain the reason for the return/refund in the `informationStatus` field.
| Event | | Status | Description |
| --- | :---: | --- | --- |
| `payinrefund.create` | | `PENDING` | Treezor received an SDDE refund or return request. |
| `payinrefund.update` | | `VALIDATED` | The SDDE refund or return is accepted. |
| `payinrefund.cancel` | | `CANCELED` | The SDDE refund or return is refused. |
If the refund is validated, then Treezor also sends a `transaction.create` webhook with a `transactionType` valued to "Payin Refund".
#### Processing flow
Here is the processing flow of a refund or return of an SDDE.
```mermaid
flowchart TD
A("Treezor receives an SDDE return or refund request")
B("Sends a payinrefund.create webhook payinrenfundStatus: PENDING")
C("Sends a payinrefund.update webhook payinrenfundStatus: VALIDATED")
D("Sends a payinrefund.cancel webhook payinrenfundStatus: CANCELED")
E("Sends a transaction.create webhook transactionType: Payin Refund")
F("Sends a balance.update webhook")
A --> B -- Accepted --> C
B -- Rejected --> D
C --> E --> F
class A MermaidNeutral;
class B neutral;
class C neutral;
class D neutral;
class E neutral;
class F neutral;
```
---
---
url: /guide/transfers/credit-transfer-inst.md
description: >-
Technical guide for emitting and receiving SEPA Instant Credit Transfers (SCT
Inst). Includes required parameters, request structure, and response examples.
---
# SEPA Instant Payments
The [SEPA Instant Credit Transfer](/guide/overview/glossary#sepa-instant-payments) is a real-time electronic payment method allowing for rapid and secure fund transfers between bank accounts within the SEPA region. The rapid processing offers a settlement within a matter of seconds, providing users with immediate access to transferred funds.
Key benefits:
* **Real-time transfers** – Allows for almost instant availability of funds to the recipient.
* **SEPA region coverage** – Operates within the [SEPA](/guide/overview/glossary#single-euro-payments-aera-sepa), ensuring cross-border transfers in multiple European countries.
* **24/7 availability** – Processes transfers 7 days a week, including weekends and holidays.
* **Secure and efficient** – Enforces security measures to safeguard transfers while keeping an efficient process.
**Configuration – SCT Inst are not enabled by default**
You can request access to the SCT Inst feature by contacting Treezor.
At Treezor, instant payments can be used in two directions:
* [`SCTR Inst`](#received-instant-credit-transfers-sctr-inst) are Received into a Wallet and mapped to [**Payin**](#key-payin-attributes) objects
* [`SCTE Inst`](#emitted-instant-credit-transfers-scte-inst) are Emitted from a Wallet, mapped to [**Payout**](#key-payout-attributes) objects
## Received Instant Credit Transfers (SCTR Inst)
An SCTR Inst is a variant of an SCTR, that is received and makes funds available within 10 seconds of its emission. Therefore, an SCTR Inst can be received any day, any time.
When receiving an SCTR Inst, Treezor might either [accept](#accepting-an-sctr-inst) or [refuse](#rejecting-an-sctr-inst) the transaction.
You may also receive Recalls for SCTR Inst. See the [Emitting SCTR Inst Recalls](/guide/transfers/sepa-recalls#receiving-sctr-inst-recalls) article for details and how to answer.
**Information – SCTR Inst amount is limited to:**
* €10,000 in B2C context
* €50,000 in B2B context
Upon mutual agreement with Treezor, these limits may be lowered.
### Accepting an SCTR Inst
When successfully receiving an SCTR Inst, Treezor:
* Sends a [`payin.create`](events#payin-create-2) webhook (with a `paymentMethodId` valued to `27` and a `VALIDATED` status).
* Creates a [Transaction](/guide/wallets/transactions) ([`transactionType`](/guide/wallets/transactions#transaction-types-transactiontype) valued to `Payin`).
You can retrieve an SCTR Inst using the [`/v1/payins/{payinId}`](/api-reference/api-endpoints.html#tag/Payins/getPayin){target="\_self"} request.
### Rejecting an SCTR Inst
Treezor may reject an SCTR Inst, if the [Wallet is closed](/guide/wallets/modification#delete) or if the amount exceeds the limits for instance.
In such cases, Treezor sends a [`sepaSctrInst.reject_sctr_inst`](events#sepasctrinst-reject-sctr-inst) webhook. It contains a [`return_reason_code`](error-codes#sct-inst-errors) indicating the reason for the rejection.
### Processing flow
Here is a diagram for an SCTR Inst processing.
```mermaid
flowchart TD
A("Originator PSP")
B("Treezor")
C("Sends a payin.create webhook (VALIDATED)")
D("Sends a sepaSctrInst.reject_sctr_inst webhook")
E("Sends a transaction.create webhook")
F("Sends a balance.update webhook")
A -- Sends SCTR Inst. --> B -- Accepted --> C
B -- Refused --> D
C --> E --> F
class A MermaidNeutral;
class C neutral;
class D neutral;
class E neutral;
class F neutral;
```
### The SCTR Inst Payin object
```json [JSON] {9}
{
"payins": [
{
"payinId": "xxxxxx-xxxx-5xxx-9xxx-xxxxxxxxxxxx", // uuid for SCTR Inst
"payinTag": null,
"walletId": "34567",
"userId": "852741", // Valued to 3 initially in Production. DO NOT USE.
"payinStatus": "VALIDATED", // Means that the funds are available to the Wallet owner
"paymentMethodId": "27",
"messageToUser": "Transfer to my Wallet",
"subtotalItems": "100.00",
"subtotalServices": "0.00",
"subtotalTax": "0.00",
"amount": "100.00",
"currency": "EUR",
"createdDate": "2018-01-01 17:00:00",
"walletEventName": "Wallet Test",
"walletAlias": "test-wallet-abcd",
"userFirstname": "CMA",
"userLastname": "",
"codeStatus": "140005",
"informationStatus": "",
"refundAmount": null,
"ibanFullname": "ALEX OAK",
"DbtrIBAN": "FR763000401544999999999173",
"ibanBic": "BNPAFRPP",
"ibanTxEndToEndId": "XXXXXXXXX",
"ibanTxId": "180799999990292",
"forwardUrl": null,
"paymentAcceptedUrl": null,
"paymentRefusedUrl": null,
"paymentWaitingUrl": null,
"paymentExceptionUrl": null,
"paymentCanceledUrl": null,
"payinDate": null,
"mandateId": null,
"creditorName": "WILL OAK",
"creditorAddressLine": null,
"creditorCountry": null,
"creditorIban": "FR761679999999999999011987",
"creditorBIC": "TRZOFR21XXX",
"virtualIbanId": null,
"virtualIbanReference": null,
"ibanId": "995d69d1839999999999a6935979ea8220d8"
}
]
}
```
**Caution – `UserId` initial value in Production**
In [Production environment](/guide/api-basics/environments), all SCTR Inst are initially received with `userId` attribute valued to `3`. **It is strictly forbidden to use this value, this is a technical user for Treezor use only**.
## Emitted Instant Credit Transfers (SCTE Inst)
An SCTE Inst is a variant of an SCTE, that makes funds available for the beneficiary within about 10 seconds of its emission. Therefore, contrary to the classic SCTE, an SCTE Inst can be sent any day, any time.
When an SCTE Inst is emitted, Treezor updates the [Balance authorizations](/guide/wallets/balances) accordingly (`balance.update` webhook) while making a series of checks to determine if the beneficiary account is eligible to instant payout. Then:
* The payout is created ([`payout.create`](events#payout-create-2)) with a temporary `PENDING` status.
* Once the payout confirmed, Treezor sends a series of webhooks ([`payout.update`](events#payout-update-1), `balance.update`, [`transaction.create`](events#transaction-create-3)) while the account is debited.
```mermaid
sequenceDiagram
autonumber
participant app as You
participant trz as Treezor
app->>trz: Create an instant payout
trz->>app: balance.update webhook (blocks)
trz->>app: payout.create webhook (PENDING)
trz->>app: payout.update webhook (VALIDATED)
trz->>app: balance.update webhook (unblocks the funds)
trz->>app: transaction.create webhook
trz->>app: balance.updated webhook (debited funds)
```
Please bear in mind that Treezor cannot guarantee you will receive the webhooks in the relevant order. See the [Race conditions](/guide/webhooks/race-conditions) article for more information.
You may request a Recall for the SCTE Inst. For more information, please refer to the [Emitting SCTE Inst Recalls](/guide/transfers/sepa-recalls#emitting-scte-inst-recalls) article.
**Information – SCTE Inst can't be canceled**
The [`/v1/payouts/{payoutId}`](/api-reference/api-endpoints.html#tag/Payouts/deletePayout){target="\_self"} endpoint is not available for SCTE Inst.
### The SCTE Inst Payout object
```json [JSON]
{
"payouts":[
{
"payoutId": "2dbb81b2-6db9-4db3-b530-988b4189xxx7",
"payoutTag": "",
"payoutStatus": "VALIDATED",
"payoutTypeId": 3,
"payoutType": "Instant Credit Transfer",
"walletId": 1902786,
"payoutDate": "2024-03-05 17:01:43",
"walletEventName": "Main Account",
"walletAlias": "mainaccount-65e741xxx62e6",
"userFirstname": "Alex",
"userLastname": "Oak",
"userId": 100026123,
"beneficiaryId": 321123,
"uniqueMandateReference": "",
"bankaccountIBAN": "FR76174180000100001234567",
"label": "",
"amount": "10.00",
"currency": "EUR",
"partnerFee": "0",
"createdDate": "2024-03-05 17:01:43",
"modifiedDate": "",
"virtualIbanId": null,
"virtualIbanReference": null,
"codeStatus": "160001",
"informationStatus": "VALIDATED",
"supportingFileLink": "",
"endToEndId": "2dbb81b26db94db3b530988b418xxxd7",
"reasonCode": null,
"reasonDescription": null,
"internationalBeneficiaryId": null,
"quotationId": null,
"metadata": null,
"totalRows": null,
"beneficiaryValidationId": "f8e4a7b2-c1d3-4e5a-8b0f-9c2d1e0a3b5c"
}
]
}
```
Please note the payout object doesn't contain the beneficiary IBAN, you need to fetch the Beneficiary object using the `beneficiaryId` instead.
### Parameters
Below are the main attributes to create a SEPA Credit Transfer Payout.
| Attribute | Type | Description |
| --- | --- | --- |
| `payoutTypeId` | integer | Value must be `3` for Instant Payment. |
| `walletId` | integer | The unique identifier of the debited Wallet. |
| `beneficiaryId` | integer | The unique identifier of the Beneficiary of the Transfer. You must have created the [Beneficiary](./beneficiaries#sepa-beneficiaries) object beforehand. |
| `beneficiaryValidationId` | string | The unique identifier of the [Beneficiary Validation](./beneficiaries#beneficiary-validation-vop). |
| `amount` | number | The amount of the credit transfer. |
| `currency` | string | The currency of the credit transfer. Must be `EUR`. |
| `accessTag` | string | A unique identifier used to enforce [Idempotency](/guide/api-basics/idempotency). |
For the transfer to be successful, make sure the information of the User associated to the Beneficiary is accurate:
* The name must be at least 2-character long (`firstname` + `lastname` or `legalName`).
* The address must be at least 4-character long (`addressLine{1|2|3}` + `postcode` + `city`)
**Best practice – Enforce [Idempotency](/guide/api-basics/idempotency) to avoid duplicates**
The instantaneous nature of these transfers and the fact that they can't be canceled enhances the costs of duplicated requests.
### Request
Use the following request:
Here is an example of `{payload}`:
```json [JSON] {4}
{
"accessTag": "{guid}", // max. 250 characters
"payoutTag": "", // max. 250 characters
"payoutTypeId": 3,
"walletId": {walletId},
"beneficiaryId": {beneficiaryId},
"beneficiaryValidationId": "{beneficiaryValidationId}",
"label": "", // max. 140 characters
"amount": 10.00, // max. amount depends on your implementation and contract
"currency": "EUR",
"supportingFileLink": "",
"endToEndId": "testdu15fevrier12h15" // max. 35 characters
}
```
Returns a `VALIDATED` Payout object with the `payoutTypeId` value to `3`.
```json [JSON] {6,7}
{
"payouts":[
{
"payoutId": "2dbb81b2-6db9-4db3-b530-988b4189aad7",
"payoutTag": "",
"payoutStatus": "VALIDATED",
"payoutTypeId": 3,
"payoutType": "Instant Credit Transfer",
"walletId": 1902786,
"payoutDate": "2024-03-05 17:01:43",
"walletEventName": "Main Account",
"walletAlias": "mainaccount-65e741b1a62e6",
"userFirstname": "Alex",
"userLastname": "Oak",
"userId": 100026123,
"beneficiaryId": 321123,
"uniqueMandateReference": "",
"bankaccountIBAN": "FR76174180000100001234567",
"label": "",
"amount": "10.00",
"currency": "EUR",
"partnerFee": "0",
"createdDate": "2024-03-05 17:01:43",
"modifiedDate": "",
"virtualIbanId": null,
"virtualIbanReference": null,
"codeStatus": "160001",
"informationStatus": "VALIDATED",
"supportingFileLink": "",
"endToEndId": "2dbb81b26db94db3b530988b4189aad7",
"reasonCode": null,
"reasonDescription": null,
"internationalBeneficiaryId": null,
"quotationId": null,
"metadata": null,
"totalRows": null,
"beneficiaryValidationId": "f8e4a7b2-c1d3-4e5a-8b0f-9c2d1e0a3b5c"
}
]
}
```
Treezor also sends a [`payout.create`](events##payout-create-2) webhook.
You can retrieve an SCTE Inst using the [`/v1/payouts/{payoutId}`](/api-reference/api-endpoints.html#tag/Payouts/getPayout){target="\_self"} request.
**Tip – See `reasonCode` and `reasonDescription` for rejection information**
You can refer to the list of reason codes in the [corresponding section](/guide/transfers/error-codes#transfer-reason-codes). As opposed to regular SCT, the SCTE Inst can't have R-trans of type "Return".
---
---
url: /guide/transfers/sepa-recalls.md
description: >-
Technical guide for requesting and handling SEPA R Transactions (recalls and
RROs). Includes required parameters, request structure, and response examples.
---
# SEPA Recalls & RROs
In some situations (technical errors, fraud, human errors, etc.) the originator of a [SEPA Credit Transfer (SCT)](/guide/overview/glossary#sepa-credit-transfer-sct) can ask to reverse the transfer.
Requests have different names depending on the requesting entity:
* **RROs** (initiated by the end user) – Must be requested [**within 13 months**](/guide/overview/glossary#sepa-open-banking-days) after the [SCT](/guide/transfers/credit-transfer).
* **Recalls** (initiated by the banking institution) – Must be requested [**within 10 open banking days**](/guide/overview/glossary#sepa-open-banking-days) after the [SCT](/guide/transfers/credit-transfer) (or 13 months in case of [`FRAD`](#types-of-recalls-reasoncode)).
Treezor allows you to:
* **Receive** recalls when you unduly received funds.
* **Emit** recalls when you unduly sent funds.
### Types of Recalls (`reasonCode`)
When receiving or emitting a Recall, it can be any of the following types.
| `reasonCode` | For | Description | Reception delay |
| :---: | --- | --- | --- |
| `DUPL` | Recalls | Duplicate payment | 10 days |
| `TECH` | Recalls | Technical problem | 10 days |
| `FRAD` | Recalls | Fraudulent origin (these don't send webhooks, only Treezor analyzes them) | 13 months |
| `CUST` | RROs | Customer's reason | 13 months |
| `AM09` | RROs | Wrong amount | 13 months |
| `AC03` | RROs | Invalid creditor account number | 13 months |
Once the delay for reception passed, recalls and RROs are automatically rejected.
### Types of Recall Rejection (`negativeResponseReasonCode`)
When rejecting a Recall, the reason may be any of the following.
| `negativeResponseReasonCode` | Description |
| :---: | --- |
| `NOOR` | The associated transaction (SCTR/SCTR Inst) was **not received** |
| `ARDT` | The associated transaction has **already been returned** |
| `AC04` | The associated **account is closed** |
| `NOAS` | The beneficiary **didn't answer** (neither accepted nor declined) |
| `CUST` | The beneficiary **rejected the recall** |
| `AM04` | The beneficiary has **insufficient funds** |
| `LEGL` | Legal decision (regulatory rules) |
**Information – Beneficiary obligation to return the funds**
Article 1376 of the French Civil Code states that in case of an error, the beneficiary is obligated to return the funds (i.e., [accept the recall request](#accept-a-recall)). If the beneficiary [rejects the Recall](#reject-a-recall), they engage their own legal responsibility.
## Receiving SCTR Recalls
SCTR Recalls are first analyzed by Treezor upon reception, to decide whether it is legitimate or not. Treezor may:
* Reject the recall directly (e.g., the account is closed).
* Handle the decision-making process for recalls of type `FRAD`, `TECH`, and `DUPL`.
* Pass on the decision-making to you for recalls of type `CUST`, `AM09`, and `AC03`.
If an SCTR recall is passed on to you, then the following occurs:
1. **Treezor informs you** of the Recall request sending a [`recallR.need_response`](events#recallr-need-response) webhook.
2. **Treezor blocks immediately** the funds on the involved Wallet and sends a [`payinrefund.create`](events#payinrefund-create-1) webhook.
3. **You decide** if you want to accept or reject the recall (within 15 working days). To do so, use the [dedicated request](#responding-to-an-sctr-recall) after receiving the [`recallR.need_response`](events#recallr-need-response) webhook.
**Tip – A `statusId` of `1` or `3` indicates that you haven't responded**
The [`statusId`](#status-statusid) is available in the [`recallR.need_response`](events#recallr-need-response) webhook or in the SCTR Recall object.
**Information – Treezor rejects duplicates**
Since it is impossible to make several recall requests for the same SCT, duplicates are rejected with the `ARDT` reason code.
### Status (`statusId`)
| | `statusId` | Status | Notes |
| :---: | :---: | --- | --- |
| | `1` | `PENDING` | Pending analysis by you (or by Treezor for recalls of type `FRAD`, `TECH`, and `DUPL`) |
| | `2` | `PENDING_PAYIN_REFUND_CREATED` | For simulation purposes. |
| | `3` | `PENDING_ANSWER_REQUESTED` | Treezor is awaiting an answer. |
| | `7` | `IN_ERROR` | |
| | `6` | `CANCELED` | |
| | `5` | `REJECTED` | |
| | `4` | `ACCEPTED` | |
**Caution – When receiving `FRAD`, `TECH`, and `DUPL` recalls**
* You **can't respond** to these recalls. Only Treezor is accountable (unless for ).
* You **must not** inform the end users of the reception of `FRAD` recalls.
### The SCTR Recall object
The structure of an SCTR Recall is as follows. While the `recallR.need_response` webhooks only contain a subset of the following attributes, you may retrieve the Recall object by using the [`/recallRs/{recallId}`](/api-reference/api-endpoints.html#tag/Recalls/getRecallR){target="\_self"} endpoint.
```json [JSON]
{
"id": 10,
"recallRSepaMessageId": 351170,
"cxlId": "401",
"txId": "401", // transaction id of the initial SCT.
"statusId": 3,
"statusLabel": "PENDING ANSWER REQUESTED",
"reasonCode": "TECH", // see available reasons list above
"additionalInformation": "",
"clientId": 878950,
"clientName": "trois_soc",
"userId": 1321404,
"userTypeId": 1,
"userName": "Alex Oak",
"userStatusId": 9,
"walletId": 714744, // related wallet id
"walletStatusId": 5,
"walletActivationDate": "2020-10-30 00:00:00",
"walletDesactivationDate": null,
"sctrId": 401, // related SCTR id
"sctrTxId": 0,
"sctrAmount": "1451.00", // related SCTR amount
"sctrSettlementDate": "2020-12-30 00:00:00",
"sctrDbtrIBAN": "FR7612548029981234567123456",
"sctrDbtrBIC": "AXABFRPP",
"sctrDbtrName": "Test name debitor",
"responseSepaMessageId": 0,
"receivedDate": null,
"payinId": 0,
"payinRefundId": 3566, // related Payin created to block the Authorized Balance
"responseType": false,
"negativeResponseReasonCode": "",
"negativeResponseAdditionalInformation": "",
"responseComment": "",
"boResponse": false,
"frozenWalletFollowingRecallR": false,
"automaticResponse": "",
"comment": "",
"fraudConfirmed": false, // is set to true if Treezor confirms a case of fraud
"partialRefund": false, // is set to true if the refunds was done outside of the Recall protocol
"inError": false,
"createdDate": "2020-12-30 15:01:12",
"updatedDate": "2020-12-30 15:01:12"
}
```
### Responding to an SCTR Recall
Your response must be sent to the dedicated [`/v1/recallRs/{recallId}/response`](/api-reference/api-endpoints.html#tag/Recalls/putRecallSctInst){target="\_self"} endpoint.
### Accept a Recall
Here is a payload example to accept a recall.
```json [JSON]
{
"responseType": 1, // mandatory, 1 for accepted
"negativeResponseAdditionalInformation": "",// must be kept empty
"negativeResponseReasonCode": "", // must be kept empty
"responseComment": "" // optional
}
```
Treezor sends a [`payinrefund.update`](events#payinrefund-update-1) with a `VALIDATED` status after receiving your acceptance of the SCTR Recall. This webhook indicates that the blocked funds will be debited.
### Reject a Recall
Here is a payload example to reject a recall.
```json [JSON]
{
"responseType": 0, // mandatory, 0 for declined
"negativeResponseAdditionalInformation": "",// optional
"negativeResponseReasonCode": "", // mandatory, see "Types of Recall Rejection (negativeResponseReasonCode)" at the top of this page
"responseComment": "" // optional
}
```
Treezor sends a [`payinrefund.update`](events#payinrefund-update-1) with a status `CANCELED` and the [Authorized Balance](/guide/wallets/balances) is freed up.
You may encounter the following errors while answering to a Recall:
* `115000` – This recall request does not exist
* `115001` – Unable to answer because status is not `PENDING` nor `ANSWER REQUESTED`
* `74001` – Input validation failed. The Recall does not belong to you
### Processing flow
Here is a diagram for an SCTR Recall processing.
```mermaid
flowchart TD
A("Reception of an SCTR Recall")
B("Treezor assesses the Recall")
C("Treezor sends a `recallr.need_response` webhook")
D("Treezor sends a `payinrefund.create` webhook")
F("You assess the Recall")
I("You PUT your refusal decision using `responseType=0`")
J("You PUT your approval decision using `responseType=1`")
K("Treezor sends a `payinrefund.update` webhook with `payinStatus=VALIDATED`")
L("Treezor sends you a `payinrefund.cancel` webhook with `payinStatus=CANCELED`")
G("Recall rejected by Treezor")
A --> B -- Accepted --> C --> D --> F
B -- Rejected --> G
F -- Rejected --> I
F -- Accepted --> J
J --> K
I --> L
class A dark;
class B neutral;
class F neutral;
```
## Receiving SCTR Inst Recalls
When a Recall regarding an [SCTR Inst](/guide/transfers/credit-transfer-inst) is received, Treezor sends:
* A [`separecallsctrinst.reception`](events#separecallsctrinst-reception) webhook.
* A [`payinrefund.create`](events#payinrefund-create-2) webhook with a `PENDING` status, hence blocking the funds on the involved Wallet.
If the recall reason allows you to answer, you have 15 working days to accept or reject the recall. If you don't answer within 15 days, Treezor sends a negative answer on your behalf, and you receive a [`payinrefund.cancel`](events#payinefund-cancel) webhook with a `REJECTED` status.
**Information – Treezor rejects duplicates**
Since it is impossible to make several recall requests for the same SCT Inst, duplicates are rejected with the `ARDT` reason code.
### Status (`statusLabel`)
| | `statusLabel` | Description |
| :---: | --- | --- |
| | `PENDING` | **Received** recall, it is being analyzed by you (or by Treezor for recalls of type `FRAD`, `TECH`, and `DUPL`) |
| | `PENDING_REJECTED_WAITING_ACK` | **Rejected** recall, waiting for interbanking system confirmation |
| | `PENDING_ACCEPTED_WAITING_ACK` | **Accepted** recall, waiting for interbanking system confirmation |
| | `REJECTED` | **Rejected** recall (final state) |
| | `ACCEPTED` | **Accepted** recall (final state) |
**Caution – When receiving `FRAD`, `TECH`, and `DUPL` recalls, you:**
* **Can't respond**, only Treezor is accountable, except for .
* **Must not** inform the end users of the reception of `FRAD` recalls.
### The SCTR Inst Recall object
The structure of an SCTR Recall is as follows. You may retrieve the Recall object by using the [`/v1/recall-sct-inst/{sctInstId}/{recallId}`](/api-reference/api-endpoints.html#tag/Recalls/getRecallR){target="\_self"} endpoint.
```json [JSON]
{
"recallId": "string", // uuid
"creationDateTime": "string",
"statusLabel": "PENDING",
"cxlId": "string",
"reasonCode": "CUST",
"additionalInformation": "",
"sctrDbtrIBAN": "string",
"sctrDbtrBIC": "string",
"sctrDbtrName": "string",
"sctrDbtrAddress": "string",
"sctrDbtrCountry": "string",
"sctrCdtrIBAN": "string",
"sctrCdtrBIC": "srting",
"sctrCdtrName": "string",
"sctrCdtrAddress": "string",
"sctrCdtrCountry": "FR",
"sctrMsgId": "string",
"sctrInstrId": "string",
"sctrTxId": "string",
"sctrE2EID": "string",
"sctrAmount": "string",
"sctrSettlementDate": "string",
"sctrRemittanceInformation": "string",
"sctrTrzId": "string",
"sctrExternalId": "string",
"clientId": 0,
"userId": 0,
"walletId": 0,
"receivedDate": "string",
"payinRefundId": 0,
"payinRefundUid": "string",
"responseType": -1,
"negativeResponseReasonCode": "string",
"negativeResponseAdditionalInformation": "string",
"responseComment": "string",
"automaticResponse": "string",
"createdDate": "string",
"updatedDate": "string"
}
```
### Responding to an SCTR Inst Recall
Your response must be sent to the dedicated [`/v1/recall-sct-inst/{sctinstId}/{recallId}/response`](/api-reference/api-endpoints.html#tag/Recalls/putRecallSctInst){target="\_self"} endpoint within 15 working days, to which Treezor answers with an HTTP Status Code `201`.
### Accept a Recall
Here is an example of payload to accept a recall.
```json [JSON]
{
"responseType": 1, // mandatory, 1 for accepted
"negativeResponseAdditionalInformation": "",// must be kept empty
"negativeResponseReasonCode": "", // must be kept empty
}
```
Treezor sends a [`payinrefund.update`](events#payinrefund-update-2) webhook with an `ACCEPTED` status and the Wallet is debited a few seconds later.
### Reject a Recall
Here is an example of payload to reject a recall.
```json [JSON]
{
"responseType": 0, // mandatory, 0 for declined
"negativeResponseAdditionalInformation": "",// mandatory, optional or not expected depending on the situation, see details below
"negativeResponseReasonCode": "", // mandatory, see "Types of Recall Rejection (negativeResponseReasonCode)" at the top of this page
}
```
The `negativeResponseAdditionalInformation` attribute is limited to 202 alphanumeric characters and is:
* **Mandatory** when the recall `reasonCode` was `FRAD` or `DUPL` or `TECH` and `negativeResponseReasonCode` is `LEGL`
* **Optional** when
* The recall `reasonCode` was `FRAD` and `negativeResponseReasonCode` is **not** `LEGL` or
* The recall `reasonCode` was `AC03`
* **Not expected** (must be left empty) in any other situations.
Treezor sends a [`payinrefund.cancel`](events#payinefund-cancel-1) with a status `REJECTED` and the [Authorized Balance](/guide/wallets/balances) is freed up.
### Processing flow
Here is a diagram for an SCTR Inst Recall processing.
```mermaid
flowchart TD
A("Reception of an SCTR Inst Recall")
B("Treezor assesses the Recall")
C("Treezor sends a `separecallsctrinst.reception` webhook with a `statusLabel=PENDING`")
D("Treezor sends a `payinrefund.create` webhook")
E("Treezor sends a `separecallsctrinst.reception` webhook with a `statusLabel=REJECTED`")
F("You assess the Recall")
G("You PUT your refusal decision using `responseType=0`")
H("You PUT your approval decision using `responseType=1`")
I("Treezor sends a `payinrefund.cancel` webhook with a `payinStatus=REJECTED`")
J("Treezor sends a `payinrefund.update` webhook with a `payinStatus=ACCEPTED`")
class A dark;
class B neutral;
class F neutral;
A --> B -- Accepted --> C --> D --> F
B -- Rejected --> E
F -- Rejected --> G
F -- Accepted --> H
G --> I
H --> J
```
## Emitting SCT Recalls
When requesting a recall, you are not guaranteed to receive the funds back. The decision regarding the recall request is up to the beneficiary bank and depends on various factors, including funds availability and compliance with delays.
You can emit recalls for both SCTE and SCTE Inst payouts using the [`/v1/payoutRefunds`](/api-reference/api-endpoints.html#tag/Payout%20Refunds/postPayoutRefund){target="\_self"} endpoint for the following reason codes.
| `reasonCode` | SCT Recall | Delay to emit |
| --- | --- | --- |
| `FRAD` | | 13 months |
| `TECH` | | [10 open banking days](/guide/overview/glossary#sepa-open-banking-days) |
| `DUPL` | | 13 months |
| `CUST` | | [10 open banking days](/guide/overview/glossary#sepa-open-banking-days) |
| `AM09` | | [10 open banking days](/guide/overview/glossary#sepa-open-banking-days) |
| `AC03` | | [10 open banking days](/guide/overview/glossary#sepa-open-banking-days) |
[Regulated Institution](/guide/overview/glossary#regulated-institution) can emit SCT Recalls regardless of the reason code.
The beneficiary bank has up to [15 open banking days](/guide/overview/glossary#sepa-open-banking-days) from the reception of your recall request to respond.
### Create a Recall
Recalls for SCTE and SCTE Inst payouts are created with the payoutRefunds request.
Please note that, for a given payout, only one recall can be requested, regardless of the result of the first request.
#### Parameters
Below some key attributes for the payout refund.
| Attribute | Type | Description |
| --- | --- | --- |
| `payoutId` | string | The unique identifier of the payout (SCTE Inst) for which the recall is to be made. |
| `reasonCode` | string | The [reasons](/guide/transfers/sepa-recalls#types-of-recalls-reasoncode) of the Recall. |
| `requestAmount` | number | The amount of the recall request. Defaults to the initial payout amount. |
| `requestCurrency` | number | The currency of the recall request. Defaults to the initial payout currency. |
#### Request example
Endpoint: [`/v1/payoutRefunds`](/api-reference/api-endpoints.html#tag/Payout%20Refunds/postPayoutRefund){target="\_self"}
```bash [CURL]
curl -X POST '{baseUrl}/v1/payoutRefunds' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"payoutId": "bf9367cb-22be-4a86-ad68-8f30fxxxx15",
"accessTag": "test-{timestamp}", // max. 250 characters
"payoutRefundTag": "test", // max. 250 characters
"requestAmount": 1000.10,
"requestCurrency": "EUR",
"reasonCode": "DUPL"
}
```
Returns a payoutRefund object.
```json [JSON]
{
"payoutRefunds": [
{
"id": "f0eb0186-1592-4fb8-84a1-a65db6901234",
"payoutRefundTag": "test",
"codeStatus": "790001",
"informationStatus": "PENDING",
"payoutId": "bf9367cb-22be-4a86-ad68-8f30fxxxx15",
"requestAmount": 1000.1,
"requestCurrency": "EUR",
"requestComment": "",
"reasonCode": "DUPL",
"refundAmount": 1000.1,
"refundCurrency": "EUR",
"refundDate": "",
"refundComment": "",
"negativeResponseReasonCode": "",
"createdDate": "2024-03-14 17:09:19",
"modifiedDate": ""
}
]
}
```
Treezor also sends a [`payoutRefund.create`](events#payoutrefund-create-2) webhook with a `payoutStatus` attribute set to `PENDING`.
You can retrieve a SCTE Recall by using the [`/v1/payoutRefunds/{payoutRefundId}`](/api-reference/api-endpoints.html#tag/Payout%20Refunds/getPayoutRefund){target="\_self"} endpoint.
### Processing flow
Here is a diagram for an SCT Recall processing.
```mermaid
flowchart TD
A("You create an SCT Recall")
B("The beneficiary bank receives the request")
C("Treezor receives the response")
D("Treezor sends a `payoutrefund.update` webhook with `informationStatus=VALIDATED`")
E("Treezor sends a `transaction.create` webhook")
F("Treezor sends a `balance.update` webhook")
G("Treezor sends a `payoutrefund.cancel` webhook")
H("Treezor sends a `payoutrefund.create` webhook")
A --> B
D --> E --> F
B --> H
H --> C
C -- Rejected --> G
C -- Accepted --> D
class A dark;
class B neutral;
class C neutral;
```
## Endpoints
| Endpoint |[Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/v1/recallRs`](/api-reference/api-endpoints.html#tag/Recalls/getRecalls){target="\_self"} Search for SCT Recalls | `read_only` |
| [`/v1/recallRs/{recallRId}`](/api-reference/api-endpoints.html#tag/Recalls/getRecallR){target="\_self"} Retrieve an SCT Recall or RRO by its `id` | `read_only` |
| [`/v1/recallRs/{recallRId}/response/`](/api-reference/api-endpoints.html#tag/Recalls/putRecallR){target="\_self"} Provide your decision following an SCT Recall request | `read_write` |
| [`/v1/recall-sct-inst/{sctInstId}/{recallId}`](/api-reference/api-endpoints.html#tag/Recalls/getRecallSctInst){target="\_self"} Retrieve an SCT Inst Recall | |
| [`/v1/recall-sct-inst/{sctinstId}/{recallId}/response`](/api-reference/api-endpoints.html#tag/Recalls/putRecallSctInst){target="\_self"} Provide your decision following an SCT Inst Recall | |
| [`/v1/payinrefunds/{recallId}`](/api-reference/api-endpoints.html#/) Retrieve a payinrefund following a Recall | |
| [`/v1/payoutRefunds`](/api-reference/api-endpoints.html#tag/Payout%20Refunds/postPayoutRefund){target="\_self"} Create a Recall (SCTE Inst only) | `read_write` |
| [`/v1/payoutRefund/{payoutRefundId}`](/api-reference/api-endpoints.html#tag/Payout%20Refunds/getPayoutRefund){target="\_self"} Create a Recall (SCTE Inst only) | `read_only` |
| [`/simulation/sct-inst/payin`](/api-reference/api-endpoints.html#tag/Simulation/simulateSctInstReception){target="\_self"} Emulate an SCTR, to test the procedure | |
| [`/simulation/sct-inst/recall`](/api-reference/api-endpoints.html#tag/Simulation/simulateSctInstRecall){target="\_self"} Emulate a reception of a SCTR inst recall, to test the procedure | |
| [`/simulation/recall-r`](/api-reference/api-endpoints.html#tag/Recalls/simulateSctInstRecall){target="\_self"} Emulate a Recallr, to test the procedure | |
---
---
url: /guide/strong-customer-authentication/faking-operations.md
description: Technical guide for generating an SCA Proof to test the SCA flow in Sandbox.
---
# Emulation
Emulation features are only available in `Sandbox` [environment](/guide/api-basics/environments).
## Simulate SCA Proof
The [`/simulation/scaProof`](/api-reference/api-endpoints.html#tag/SCA%20Proof%20Simulation/postScaProof){target="\_self"} endpoint allows you to simulate an SCA proof.
### Parameters
| Attribute | Type | Description |
| --- | --- | --- |
| `scaWalletId` | string | The unique identifier of the SCA Wallet from which the `scaProof` is to be created. |
| `url` | string | The URL of the endpoint for which the sensitive action is to be secured with strong customer authentication. |
| `body` | string | Data to sign in the SCA proof body. See the [Per Operation](securing-endpoints#per-operation) table to know which data to sign for each endpoint. |
### Request
In order to generate an SCA Proof in Sandbox, you must use a JWT `accessToken` with a `client_credentials` grant type and the `admin` scope. See the [SCA Authentication](authenticating) article for more information.
```bash [CURL]
curl -X POST '{baseUrl}/simulation/scaProof' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json'
```
Here is a `{payload}` example:
```json [JSON]
{
"scaWalletId": "string", // required
"url": "string", // optional
"body": {"string"} // optional
}
```
Returns the SCA proof.
```json [JSON]
{
"scaProof": "string"
}
```
### Worked example
Let's take an example where you want to test in Sandbox the creation of a new Beneficiary, an action which requires strong customer authentication.
The steps are the following:
1. [Use the simulator as the App](#_1-use-the-simulator-as-the-app)
2. [Simulate an SCA proof as the App](#_2-simulate-an-sca-proof-as-the-app)
3. [Authenticate as end user](#_3-authenticate-as-end-user)
4. [Simulate SCA Proof as App](#_4-simulate-sca-proof-as-app)
5. [Create the beneficiary as end user](#_5-create-the-beneficiary-as-end-user)
**Prerequisites**
A User must be already created, with an active [SCA Wallet](introduction#sca-wallet-object).
#### 1. Use the simulator as the App
Authenticate as the application to use the simulator. Here is the authentication request:
```bash [CURL]
curl -X POST '{baseUrl}/oauth/token' \
--form 'grant_type="client_credentials"' \
--form 'client_id="{clientId}"' \
--form 'client_secret="{clientSecret}"' \
--form 'scope="admin"'
```
Returns the Bearer token:
```json [JSON]
{
"token_type": "Bearer",
"expires_in": 3600,
"access_token": "eyJ0_XXX_DSnw"
}
```
#### 2. Simulate an SCA proof as the App
Use the simulator to create an SCA proof that you'll be able to use to authenticate as the end user in the next step.
```bash [CURL]
curl -X POST '{baseUrl}/simulation/scaProof' \
--header 'Authorization: Bearer eyJ0_XXX_DSnw' \
--header 'Content-Type: application/json' \
--data '{payload}'
```
With the user's `scaWalletId` in the `{payload}`:
```json [JSON]
{
"scaWalletId": "e59b5fadd69f4d2693a60492b0334464"
}
```
Returns the SCA Proof:
```json [JSON]
{
"scaProof": "eyJh_NDN9.WQBp_Xg7w"
}
```
#### 3. Authenticate as end user
Authenticate as the end user to create the beneficiary. Here is the authentication request:
```bash [CURL]
curl -X POST '{baseUrl}/oauth/token' \
--form 'grant_type="delegated_end_user"' \
--form 'client_id="{clientId}"' \
--form 'client_secret="{clientSecret}"' \
--form 'scope="read_write"' \
--form 'username="101109094"' \
--form 'password="bc6ead2bbcd9cc409ba53d9cfbf145a667647414eae496xxxx75636b15384a8"' \
--form 'sca="eyJh_NDN9.WQBp_Xg7w"'
```
Returns the Bearer token:
```json [JSON]
{
"token_type": "Bearer",
"expires_in": 3600,
"access_token": "eyJ0_XXX_q44Q"
}
```
#### 4. Simulate SCA Proof as App
```bash [CURL]
curl -X POST '{baseUrl}/simulation/scaProof' \
--header 'Authorization: Bearer eyJ0_XXX_DSnw' \
--header 'Content-Type: application/json' \
--data '{payload}'
```
With the following `{payload}` which contains the data to sign:
```json [JSON]
{
"scaWalletId": "e59b5fadd69f4d2693a60492b0334464",
"url": "https://yourcompanyname.sandbox.treezor.co/v1/beneficiaries",
"body": {
"userId": "101109094",
"name": "Alex Oak",
"adress": "33 av de Wagram Paris",
"iban": "FR1130003000305928344XXXXX",
"bic": "SOGEFRPPXXX",
"usableForSct": true
}
}
```
Returns the SCA Proof:
```json [JSON]
{
"scaProof": "eyJh_UxfQ.nNIH_n9kA"
}
```
#### 5. Create the beneficiary as end user
```bash [CURL]
curl -X POST '{baseUrl}/v1/beneficiaries' \
--header 'Authorization: Bearer eyJ0_XXX_q44Q' \
--header 'Content-Type: application/json'\
--data '{payload}'
```
With the following `{payload}`:
```json [JSON]
{
"userId": "101109094",
"name": "Alex Oak",
"adress": "33 av de Wagram Paris",
"iban": "FR1130003000305928344XXXXX",
"bic": "SOGEFRPPXXX",
"usableForSct": true,
"sca": "eyJh_UxfQ.nNIH_n9kA"
}
```
Returns the Beneficiary object:
```json [JSON]
{
"beneficiaries": [
{
"id": 527977,
"tag": "",
"userId": 101109094,
"nickName": "",
"name": "Alex Oak",
"address": "",
"iban": "3537524356444355504255444055564B574C405157455041XXXX",
"bic": "SOGEFRPPXXX",
"sepaCreditorIdentifier": "",
"sddB2bWhitelist": [],
"sddCoreBlacklist": [],
"usableForSct": true,
"sddCoreKnownUniqueMandateReference": [],
"isActive": true,
"createdDate": "2024-11-21 08:05:56",
"modifiedDate": "2024-11-21 08:05:56",
"metadata": {
"iban": "FR1130003000305928344XXXXX"
}
}
]
}
```
---
---
url: /guide/dashboard/templates.md
description: >-
Customize your templates directly with the Dashboard code editor. Preview the
final rendering of your PDF account documents and email templates on the
interface.
---
# Templates
Templates allow you to customize some of the API-generated documents, that you provide to your end users on request.
**Reading – Templates are powered by Twig 3.x templating engine**
Learn more in the [Templates](/guide/api-basics/templates) article.
## Accessing templates
In the *Administration section*, select the *Templating management* section to view the templates.
In the drop-down list, the following templates are available:
| Template | Type | Description |
|--- |--- |--- |
| Onboarding confirmation (html) | Email | Customizes the email sent to users to confirm their onboarding. Linked to [Delegated authentication](/guide/api-basics/using-treezor-as-oauth-identity-provider). |
| Onboarding confirmation (text) | Email | Customizes the message sent to confirm their onboarding (preferred format if a mobile phone number is provided). Linked to [Delegated authentication](/guide/api-basics/using-treezor-as-oauth-identity-provider). |
| Forgot password (html) | Email | Customizes the email sent to reset their password. Linked to [Delegated authentication](/guide/api-basics/using-treezor-as-oauth-identity-provider). |
| Forgot password (text) | Email | Customizes the message sent to users to reset their password (preferred format if a mobile phone number is provided). Linked to [Delegated authentication](/guide/api-basics/using-treezor-as-oauth-identity-provider). |
| Wallet details (pdf) | Document | Customizes the [Account details](/guide/wallets/account-documents). This document can be download from the *Wallets* tab, [*Wallets list*](/guide/dashboard/wallets#navigating-the-wallet-s-information) section, when clicking on the "More" button and selecting the "Account details" option. |
| Wallet statement (pdf) | Document | Customizes the [Account statement](/guide/wallets/account-documents) document. This document can be download from the *Wallets* tab, [*Wallets list*](/guide/dashboard/wallets#navigating-the-wallet-s-information) section, when clicking on the "More" button and selecting the "Statement" option. |
| Proof of payout (pdf) | Document | Customizes the [Proof of payout](/guide/transfers/proof-of-payout) document. |
| Wallet closure certificate (pdf) | Document | Customizes the [Closure certificate](/guide/wallets/account-documents) document. |
| Wallet balance certificate (pdf) | Document | Customizes the [Balance certificate](/guide/wallets/account-documents) document. |
| Wallet domiciliation certificate (pdf) | Document | Customizes the [Domiciliation](/guide/wallets/account-documents) document. |
## Managing templates
The Dashboard allows you to:
* [Render templates in real-time](#rendering-templates-in-real-time)
* [Make the most out of the template variables](#making-the-most-out-of-template-variables)
### Rendering templates in real-time
Templates are rendered in real time in the Dashboard while you edit them.
You can use the left-hand side of the view to edit, and see the results directly in the right-hand side.
Once all your modifications are done, you can click on the "Save Changes" button in the upper right corner of the view.
### Making the most out of template variables
A list of available variables is provided for each template. These variables can be used in compliance with [the Twig templating language](/guide/api-basics/templates).
To access the variables, click on the "Variables" button located next to the picklist. As a result, a dialog box is prompted, providing information about the variables you can use.
---
---
url: /guide/webhooks/testing-in-sandbox.md
description: >-
Test Treezor API webhooks in your Sandbox environment. This guide provides
methods for receiving and processing webhooks during development, including
using port forwarding services (Ngrok, RequestCatcher) and manual setup, to
validate your integration.
---
# Testing webhooks
During the [development phase](https://treezor.zendesk.com/hc/en-us/sections/360002673359-Validating-your-implementation) in [Sandbox](/guide/api-basics/environments#sandbox), you need to receive and process webhooks, just like you would in [Production](/guide/api-basics/environments#production).
Receiving and processing webhooks is essential to validating that your code will behave as expected once pushed into production.
**Security – Development exposure**
You should consider the security implications of exposing your development environment to the internet.
There are two main ways of achieving this:
* [Using a port forwarding service](#using-a-port-forwarding-service)
* [Manually setting-up port forwarding](#manually-setting-up-port-forwarding)
## Using a port forwarding service
Some commercial services can offer you a customized domain name, and redirect requests sent to this domain, towards your development machine or server, allowing for the reception of webhooks. These have the advantage of **being able to run behind a firewall, and do not require any changes to your router configuration or DNS zone**.
**Security – Webhook exposure**
You should consider the security implications of having webhooks transit through a third party's infrastructure. Careful reading of their TCU is recommended.
### [NGRok](https://ngrok.com/)
Ngrok exposes your development machine or server to the public internet over a secure tunnel, using a locally installed helper program.
**Webhooks are forwared to your development machine or server.**
* [Download and run a program](https://ngrok.com/download) on your development machine or server and [provide it the port](https://ngrok.com/docs) of your web application (`./ngrok http {portOfYourApplication}`).
* The application automatically configures and provides you with a domain name that redirects to your development machine.
* Traffic is relayed through to the ngrok process running on your machine and then on to your web application.
### [RequestCatcher](https://requestcatcher.com/)
RequestCatcher exposes requests sent to a subdomain directly in your browser. It doesn't require the creation of an account or the installation of a helper program.
**Webhooks are visible to you, but are not forwarded to your development machine or server.**
* Go to [the webpage](https://requestcatcher.com/) and enter a subdomain of your choice
* The webpage automatically updates to display all requests sent to this subdomain
### [Mocklab](https://get.mocklab.io/)
Mocklab allows you to graphically program an API (such as accepting POST requests and [answering with `200` HTTP Status Code](./integrity-checks#what-should-my-application-return)), and display any request sent to it in your Mocklab dashboard.
**Webhooks are visible to you, but are not forwarded to your development machine or server.**
### Subscribe to webhooks
You can follow the [normal subscription procedure](./subscription-management) using the domain name provided by one of these services as the webhook endpoint.
The [AWS certificate verifications steps](./subscription-management#manually-check-the-confirmation-request-signature) of the subscription procedure are a nice to have but can be skipped.
## Manually setting up port forwarding
This is a manual process, whereby, somebody with access to your router configuration, exposes your development machine or server to internet, allowing for the reception of webhooks.
**Prerequisites – To manually set up port forwarding**
* Your internet link must have a [static IP](https://en.wikipedia.org/wiki/IP_address) address (often provided with pro-grade links). If you don't have a static IP, you may resort to a [Dynamic DNS](https://en.wikipedia.org/wiki/Dynamic_DNS) service such as [No-IP](https://www.noip.com/).
* You must have administrator access to your router
* You must have access to your domain's DNS zone
### Configure a domain name
#### Using your own domain (static IP)
You need to connect to your domain name customer interface, go to the DNS zone, and add an `A` type entry (such as `sandbox.{my-domain-name.io} => 12.345.6.789`), pointing to your internet access' IP. Your domain name provider likely has a detailed documentation regarding this step.
#### Using a Dynamic DNS service (dynamic IP)
If you use a Dynamic DNS service, you need to connect to your Dynamic DNS customer interface, where you will be asked to choose or customize a domain name.
The second step is to install a helper program on your development machine or server. This program will notify the Dynamic DNS service of any IP address change. The Dynamic DNS service will then automatically update the DNS zone to point the domain to your new IP address.
### Configure port forwarding
You need to connect to your router, go to the NAT rules, and add an inbound NAT forwarding rule
* from the port `443`
* to the port `443`
* to the IP of your development machine or server.
Your router manufacturer likely has a detailed documentation regarding this step.
### Subscribe to webhooks
You can follow the [normal subscription procedure](./subscription-management) using your newly created domain name as the webhook endpoint.
The [AWS certificate verifications steps](./subscription-management#manually-check-the-confirmation-request-signature) of the subscription procedure are a nice to have but can be skipped.
---
---
url: /guide/transfers/error-codes.md
description: >-
Troubleshoot and handle transfer-related issues using the Treezor API's
complete list of error codes, messages, reason codes and their corresponding
meanings.
---
# Errors
This page lists both common error codes from the Treezor API and the reason codes for SEPA R-transactions as defined by the European Payment Council.
**Caution – Only the legacy API sends the error code in HTTP errors**
When handling errors with Connect, only the `message` attribute is returned.
## Transfer reason codes
Find below the list of reason codes to handle SEPA Credit Transfer R-transactions (i.e., rejects, returns, and recalls). This list is regularly updated on the [EPC website](https://www.europeanpaymentscouncil.eu/document-library/clarification-paper/guidance-reason-codes-sepa-credit-transfer-r-transactions). This also applies to [International Transfers](./international.md).
| Code | Definition | Reason |
|:---: |--- |--- |
| `AC01` | Incorrect Account Number | Account identifier invalid or incorrect (i.e., invalid IBAN or account number does not exist) *Type of R-trans: Reject, Return* |
| `AC03` | Invalid Creditor Account Number | Wrong unique identifier of the Beneficiary account *Type of R-trans: RFRO* |
| `AC04` | Closed Account Number | Account closed *Type of R-trans: Return, Negative answer to a Recall or to a RFRO* |
| `AC06` | Blocked Account | Account blocked *Type of R-trans: Return* |
| `ACNR` | Accepted Claim No Receipt | Inter-PSP positive response to Claim Non-Receipt *Type of R-trans: Positive answer to SCT Inquiry “Claim Non- Receipt”* |
| `ACVA` | Accepted Value Date Adjustment | Inter-PSP positive response to Claim for Value Date Correction *Type of R-trans: Positive answer to SCT Inquiry “Claim for Value Date Correction”* |
| `AG01` | Transaction Forbidden | Credit transfer forbidden on this account (e.g., savings account) *Type of R-trans: Return* |
| `AG02` | Invalid Bank Operation Code | Operation code/transaction code incorrect, invalid file format *Type of R-trans: Reject, Return* |
| `AM04` | Insufficient funds on the account | Insufficient funds on the account *Type of R-trans: Negative answer to a Recall or to a RFRO* |
| `AM05` | Duplication | Duplicate payment *Type of R-trans: Reject, Return* |
| `AM09` | Wrong amount | Wrong amount *Type of R-trans: RFRO* |
| `ARDT` | The Transaction Has Already Been Returned | Already returned transaction *Type of R-trans: Negative answer to a Recall or to a RFRO; Negative answer to SCT Inquiry “Claim Non- Receipt”* |
| `ARJT` | Already Rejected Transaction | Already rejected transaction *Type of R-trans: Negative answer to SCT Inquiry “Claim Non- Receipt”* |
| `BE04` | Missing Creditor Address | Account address invalid. The address is required if the beneficiary bank is based in a non-EEA SEPA country. *Type of R-trans: Return* |
| `CERI` | Check ERI | The credit transfer is not tagged as an Extended Remittance Information (ERI) transaction but contains ERI *Type of R-trans: Reject* |
| `CNOR` | Creditor Bank is Not Registered | Beneficiary PSP is not registered under this BIC in the CSM *Type of R-trans: Reject, Return* |
| `CUST` | Requested By Customer | a. By request of Customer the Originator without any reason specified. b. Refusal by the Beneficiary *Type of R-trans: a. RFRO. b. Negative answer to a Recall or to a RFRO* |
| `CVAA` | Correct value date already applied | Inter-PSP negative response to Claim for Value Date Correction *Type of R-trans: Negative answer to SCT Inquiry “Claim for Value Date Correction”* |
| `DNOR` | Debtor bank is not registered | Originator PSP is not registered *Type of R-trans: Reject* |
| `DUPL` | Duplicate payment | Duplicate sending *Type of R-trans: Recall* |
| `ED05` | Settlement failed | Settlement of the SEPA Credit Transfer failed *Type of R-trans: Reject* |
| `ERIN` | ERI Option Not Supported | The Extended Remittance Information (ERI) option is not supported *Type of R-trans: Reject, Return* |
| `FF01` | Invalid File Format | Operation/ transaction code incorrect, invalid file format *Type of R-trans: Reject* |
| `FOCR` | Following Cancellation Request | Positive answer to the Recall *Type of R-trans: Positive answer to a recall or to a RGRO* |
| `FRAD` | Fraudulent Origin | Fraudulent originated credit transfer *Type of R-trans: Recall* |
| `LEGL` | Legal Decision | Legal reasons *Type of R-trans: Negative answer to a Recall or to a RFRO* |
| `MD07` | End Customer Deceased | Beneficiary deceased *Type of R-trans: Return* |
| `MODI` | Modified As Per Request | Inter-PSP confirmed positive response to Claim for Value Date Correction *Type of R-trans: Confirmed positive answer to SCT Inquiry “Claim for Value Date Correction”* |
| `MS02` | Not Specified Reason Customer Generated | By order of the Beneficiary *Type of R-trans: Return* |
| `MS03` | Not Specified Reason | Reason not specified *Type of R-trans: Reject, Return* |
| `NERI` | No ERI | The SEPA Credit Transfer is tagged as an Extended Remittance Information (ERI) transaction but does not contain ERI *Type of R-trans: Reject* |
| `NOAS` | No Answer From Customer | No response from Beneficiary *Type of R-trans: Negative answer to a Recall or to a RFRO* |
| `NOOR` | No Original Transaction Received | Original Credit Transfer never received *Type of R-trans: Negative answer to a Recall or to a RFRO; Negative answer to SCT Inquiry “Claim Non- Receipt”* |
| `RC01` | Bank Identifier Incorrect | PSP identifier incorrect (i.e., invalid BIC) *Type of R-trans: Reject, Return* |
| `RJNR` | Rejected Claim Non- Receipt | Inter-PSP negative response to Claim Non-Receipt *Type of R-trans: Negative answer to SCT Inquiry “Claim Non- Receipt”* |
| `RJVA` | Rejected Value Date Adjustment | Inter-PSP negative response to Claim for Value Date Correction *Type of R-trans: Negative answer to SCT Inquiry “Claim for Value Date Correction”* |
| `RNPR` | Original Transaction Received but not processable | Original Transaction Received but Not Processable *Type of R-trans: Negative answer to SCT Inquiry “Claim Non- Receipt”* |
| `RR01` | Missing Debtor Account Or Identification | Regulatory Reason *Type of R-trans: Reject, Return* |
| `RR02` | Missing Debtor’s Name Or Address | Regulatory Reason *Type of R-trans: Reject, Return* |
| `RR03` | Missing Creditor’s Name Or Address | Regulatory Reason *Type of R-trans: Reject, Return* |
| `RR04` | Regulatory Reason | Regulatory Reason *Type of R-trans: Reject, Return; Negative answer to SCT Inquiry “Claim Non- Receipt”* |
| `TECH` | Technical Problem | Technical problems Recall. resulting in erroneous SCTs *Type of R-trans: Recall* |
| `TM01` | Cut Off Time | File received after Cut-off Time *Type of R-trans: Reject* |
## SCT Inst reason codes
Find below the list of reason codes to handle SCT Inst R-transactions (i.e., rejects, returns, and recalls). This list is regularly updated on the [EPC website](https://www.europeanpaymentscouncil.eu/document-library/guidance-documents/guidance-reason-codes-sepa-instant-credit-transfer-r-0).
| Code | Definition | Reason |
|:---: |--- |--- |
| `AB05` | Timeout Creditor Agent | Transaction stopped due to timeout at the Creditor Agent. *Type of R-trans: Reject* |
| `AB06` | Timeout Instructed Agent | Transaction stopped due to timeout at the Instructed Agent. *Type of R-trans: Reject* |
| `AB07` | Offline Agent | Agent of message is not online. Generic usage if it cannot be determined who exactly is not online. *Type of R-trans: Reject* |
| `AB08` | Offline Creditor Agent | Creditor Agent is not online *Type of R-trans: Reject* |
| `AB09` | Error Creditor Agent | Transaction stopped due to error at the Creditor Agent *Type of R-trans: Reject* |
| `AB10` | Error Instructed Agent | Transaction stopped due to error at the Instructed Agent *Type of R-trans: Reject* |
| `AC01` | Incorrect Account Number | Account identifier invalid or incorrect (i.e., invalid IBAN or account number does not exist). *Type of R-trans: Reject* |
| `AC03` | Invalid Creditor Account Number | Wrong unique identifier of the Beneficiary account. *Type of R-trans: RFRO* |
| `AC04` | Closed Account Number | Account closed. *Type of R-trans: Reject, Negative answer to a Recall or to a RFRO* |
| `AC06` | Blocked account | Account blocked *Type of R-trans: Reject* |
| `AG01` | Trnsaction Forbidden | Credit transfer forbidden on this account. *Type of R-trans: Reject* |
| `AG02` | Invalid Bank Operation Code | Operation code/transaction code incorrect, invalid file format *Type of R-trans: Reject* |
| `AG09` | Payment Not Received | Original payment never received *Type of R-trans: Reject* |
| `AG10` | Agent Suspended | Agent of message is suspended from the Real Time Payment system. *Type of R-trans: Reject* |
| `AG11` | Creditor Agent Suspended | Creditor Agent of message is suspended from the Real Time Payment system. *Type of R-trans: Reject* |
| `AM02` | Not Allowed Amount | Amount exceeds the maximum authorized amount for SCT Inst. *Type of R-trans: Reject* |
| `AM04` | Insufficient Funds | Insufficient funds on the account. *Type of R-trans: Negative answer to a Recall or to a RFRO.* |
| `AM05` | Duplication | Duplicate payment. *Type of R-trans: Reject* |
| `AM09` | Wrong Amount | Wrong amount. *Type of R-trans: RFRO* |
| `AM23` | Aount Exceeds Settlement Limit | Transaction amount exceeds settlement limit. *Type of R-trans: Reject* |
| `ARDT` | The Transaction Has Already Been Returned | Already returned transaction. *Type of R-trans: Negative answer to a Recall or to a RFRO.* |
| `BE04` | Missing Creditor Address | Account address invalid. The address is required if the beneficiary bank is based in a non-EEA SEPA country. *Type of R-trans: Reject* |
| `CNOR` | Creditor Bank Is Not Registered. | Beneficiary PSP is not registered under this BIC in the CSM. *Type of R-trans: Reject* |
| `CUST` | Request By Customer | a. By request of Customer the Originator without any reason specified. b. Refusal by the Beneficiary *Type of R-trans: a. RFRO. b. Negative answer to a Recall or to a RFRO* |
| `DNOR` | Debtor Bank Is Not Registered | Originator PSP is not registered under this BIC in the CSM. *Type of R-trans: Reject* |
| `DUPL` | Duplicate Payment | Duplicate Sending *Type of R-trans: Recall* |
| `FF01` | Invalid File Format | Operation/ transaction code incorrect, invalid file format. *Type of R-trans: Reject* |
| `FOCR` | Following Cancellation Request | Positive answer to the Recall. *Type of R-trans: Positive answer to a Recall or to a RFRO* |
| `FRAD` | Fraudulent Origin | *Type of R-trans: Recall* |
| `LEGL` | Legal Decision | Legal reasons. *Type of R-trans: Negative answer to a Recall or to a RFRO* |
| `MD07` | End Customer Deceased | Beneficiary deceased. *Type of R-trans: Reject* |
| `MS02` | Not Specified Reason Customer Generated | By order of the Beneficiary. *Type of R-trans: Reject* |
| `MS03` | Not Specificed Reason Agent Generated | Reason not specified. *Type of R-trans: Reject* |
| `NOAS` | No Answer From Customer | No response from Beneficiary. *Type of R-trans: Negative answer to a Recall or to RFRO* |
| `NOOR` | No Original Transaction Received | Original SEPA Instant Credit Transfer never received. *Type of R-trans: Negative answer to a Recall or to RFRO* |
| `RC01` | Bank Identifier Incorrect | PSP identifier incorrect (i.e., invalid BIC). *Type of R-trans: Reject* |
| `RR01` | Missing Debtor Account Or Identification | Regulatory Reason. *Type of R-trans: Reject* |
| `RR02` | Missing Debtor's Name Or Address | Regulatory Reason. *Type of R-trans: Reject* |
| `RR03` | Missing Creditor's Name Or Address | Regulatory Reason. *Type of R-trans: Reject* |
| `RR04` | Regulatory Reason | Regulatory Reason. *Type of R-trans: Reject* |
| `TECH` | Technical Problem | Technical problems resulting in erroneous SCT Inst transactions *Type of R-trans: Recall* |
| `TM01` | Invalid Cut Off Time | Time-out – maximum execution time has been exceeded *Type of R-trans: Reject* |
| `DS14` | Unknown User on Server | The user is unknown on the server. *Type of R-trans: Reject* |
| `DT01` | Invalid Date | Invalid Date. *Type of R-trans: Reject* |
| `E001` | Duplication in Identity ID Not Allowed | Duplication in identity ID is not allowed. *Type of R-trans: Reject* |
| `E002` | Unavailability Periods Overlap | Overlap of unavailability periods not allowed. *Type of R-trans: Reject* |
| `E003` | Unknown BIC | Unknown BIC. *Type of R-trans: Reject* |
| `E004` | Wrong Time | Wrong Time. *Type of R-trans: Reject* |
| `E005` | Unavailability Too Far | Unavailability too far. *Type of R-trans: Reject* |
| `E006` | Daily Threshold Passed | Daily threshold passed. *Type of R-trans: Reject* |
| `E007` | No Matching Available | No matching available. *Type of R-trans: Reject* |
| `E008` | Cancel Not Allowed In The Past | Cancel not allowed in the past. *Type of R-trans: Reject* |
| `E009` | Invalid Value | Invalid value. *Type of R-trans: Reject* |
| `L001` | Unknown Creditor/Creditor Account | Unknown Creditor or Creditor Account. *Type of R-trans: Reject* |
| `L002` | Unknown Debtor/Debtor Account | Unknown Debtor or Debtor Account. *Type of R-trans: Reject* |
| `L003` | Currency Differs from Account/RTGS | Currency of incoming flow differs from Account currency or RTGS System not configured. *Type of R-trans: Reject* |
| `L004` | Creditor/Creditor Account Blocked | The Creditor or the Creditor Account is blocked. *Type of R-trans: Reject* |
| `L005` | Debtor/Debtor Account Blocked | The Debtor or the Debtor Account is blocked. *Type of R-trans: Reject* |
| `L006` | Duplicate Outbound/Inbound Submission | Outbound or Inbound submission is a duplicate. *Type of R-trans: Reject* |
| `L007` | Settlement Failure (Insufficient Cash) | Failure of the settlement attempt of the instruction due to insufficient cash balance. *Type of R-trans: Reject* |
| `L008` | RTGS System is Closed | RTGS system is closed. *Type of R-trans: Reject* |
| `L009` | Invalid RTGS Status Content | Invalid content of the field RTGS Status. *Type of R-trans: Reject* |
| `L010` | Unknown RTGS System DN | Unknown RTGS System DN. *Type of R-trans: Reject* |
| `L011` | Order Not Found | Order not found. *Type of R-trans: Reject* |
| `L012` | Amount is Lower or Equal to Zero | The amount is lower or equal to zero. *Type of R-trans: Reject* |
| `L014` | Intra-service LT Not Allowed | Intra-service LT not allowed. *Type of R-trans: Reject* |
| `MS01` | Reason Not Specified | Reason not specified. *Type of R-trans: Reject* |
| `PY01` | Unknown BIC in Routing Table | Unknown BIC in routing table. *Type of R-trans: Reject* |
| `PY03` | Unknown BIC in TIPS Directory | Unknown BIC in TIPS Directory. *Type of R-trans: Reject* |
| `R001` | Restriction Type for Actor Not Allowed | Restriction Type for Actor not allowed. *Type of R-trans: Reject* |
| `R002` | Party Not Existing | Party not existing. *Type of R-trans: Reject* |
| `R003` | Party Type Not Allowed for Blocking | Party Type not allowed for blocking/unblocking operations. *Type of R-trans: Reject* |
| `R005` | Restriction Type for Account/CMB Not Allowed | Restriction Type for account/CMB not allowed. *Type of R-trans: Reject* |
| `R006` | Account/CMB Not Existing | Account/CMB not existing. *Type of R-trans: Reject* |
| `R007` | Currency Not Correct | Currency not correct. *Type of R-trans: Reject* |
| `R008` | User Not Allowed to Block/Unblock | User not allowed to block/unblock. *Type of R-trans: Reject* |
| `R020` | CMB Not Existing | CMB not existing. *Type of R-trans: Reject* |
| `R021` | User Not Allowed to Change Limit | User not allowed to change the Limit. *Type of R-trans: Reject* |
| `R099` | Duplicate Instruction | Duplicate instruction. *Type of R-trans: Reject* |
| `S001` | Request Not Allowed | Request not allowed. *Type of R-trans: Reject* |
| `S002` | Data Not Available | Data not available. *Type of R-trans: Reject* |
| `TBL1` | Debtor/Debtor Account Blocked | The owner of the debtor account or the debtor account/CMB is blocked. *Type of R-trans: Reject* |
| `TBL2` | Creditor/Creditor Account Blocked | The owner of the creditor account or the creditor account/CMB is blocked. *Type of R-trans: Reject* |
| `XD19` | Invalid IBAN Format | Invalid IBAN format. *Type of R-trans: Reject* |
| `XD20` | Invalid Account Number | Invalid Account Number. *Type of R-trans: Reject* |
| `XD21` | Invalid Account Owner | Invalid Account Owner. *Type of R-trans: Reject* |
| `XD22` | Invalid Settlement Method | Invalid settlement method for either Debtor Agent or Creditor Agent. *Type of R-trans: Reject* |
| `XT04` | Insufficient Liquidity (System) | Insufficient liquidity for processing the transaction on the System. *Type of R-trans: Reject* |
| `XT06` | Invalid Acceptance Time | Invalid AccptTime, Rejected by the CSM to Originator PSP upon exceeding tolerance period for the Acceptance Date\&Time. *Type of R-trans: Reject* |
| `XT10` | Transaction Inflight | Transaction inflight. *Type of R-trans: Reject* |
| `XT13` | Unsupported XML Field | Unsupported XML field. *Type of R-trans: Reject* |
| `XT33` | Invalid Data Format | Invalid data format. *Type of R-trans: Reject* |
| `XT73` | Invalid Country Code | Invalid country code. *Type of R-trans: Reject* |
| `XT75` | Invalid Original Transaction Status | Invalid original transaction status, action not required. *Type of R-trans: Reject* |
| `XT77` | Original Amount Mismatch | Original Amount mismatch. *Type of R-trans: Reject* |
| `XT79` | Debtor Agent Not Allowed/Sender Participant Not Allowed | The Debtor Agent is not allowed to send SCT Inst transactions (pacs.008) and consequently to send Payment Status Request (pacs.028) and Recalls (camt.056). It is also not allowed to receive NRR and PRR. The sender Participant is not allowed to send liquidity transfer order. *Type of R-trans: Reject* |
## SDD reason codes
Find below the list of reason codes to handle SDD R-transactions (i.e., rejects, returns, and recalls). This list is regularly updated on the [EPC website](https://www.europeanpaymentscouncil.eu/document-library/guidance-documents/guidance-reason-codes-sepa-direct-debit-r-transactions).
| Code | Definition | Reason |
|:---: |--- |--- |
| `AC01` | Incorrect Account Number | Account Identifier incorrect (i.e., invalid IBAN of the Debtor) *Type of R-trans: Reject, Return* |
| `AC04` | Closed Account Number | Account closed *Type of R-trans: Reject, Return* |
| `AC06` | Blocked Account | Account blocked *Type of R-trans: Reject, Return* |
| `AC13` | Invalid Debtor Account Type | Debtor account is a consumer account **(For SDD B2B collections only)** *Type of R-trans:Reject, Return* |
| `AG01` | Transaction Forbidden | Direct Debit forbidden on this account for regulatory reasons *Type of R-trans: Reject, Return* |
| `AG02` | Invalid Bank Operation Code | Operation code/ transaction code/ sequence type incorrect, invalid file format *Type of R-trans:Reject, Return* |
| `AM04` | Insufficient Funds | Insufficient funds *Type of R-trans: Reject, Return* |
| `AM05` | Duplication | Duplicate collection *Type of R-trans: Reject, Return, Revers* |
| `BE05` | Unrecognised initiating party | Identifier of the Creditor Incorrect *Type of R-trans: Reject, Return* |
| `CNOR` | Debtor Bank is not registered | Creditor PSP is not registered under this BIC in the CSM *Type of R-trans: Reject* |
| `DNOR` | Debtor Bank is not registered | Debtor PSP is not registered under this BIC in the CSM *Type of R-trans: Reject* |
| `ED05` | Settlement Failed | Settlement of the collection failed *Type of R-trans: Reject* |
| `FF01` | Invalid File Format | Invalid file format *Type of R-trans: Reject* |
| `MD01` | No Mandate | No valid mandate **(For SDD Core collections only)** No mandate or unable to obtain mandate confirmation from the Debtor; **(For SDD B2B collections only)** Unauthorised transaction. **(For Refunds of SDD Core collections only)** *Type of R-trans: Reject, Return, Refund* |
| `MD02` | Missing Mandatory Mandate Information in Mandate | Mandate data missing or incorrect *Type of R-trans: Reject* |
| `MD06` | Refund Request By End Customer | Disputed authorized transaction. **(For SDD Core collections only)** *Type of R-trans: Refund* |
| `MD07` | End Customer Deceased | Debtor Deceased *Type of R-trans: Reject, Return* |
| `MS02` | Not Specified Reason Customer Generated | Refusal by the Debtor *Type of R-trans: Reject, Return, Reversal* |
| `MS03` | Not Specified Reason Agent Generated | Reason not specified *Type of R-trans: Reject, Return, Reversal* |
| `RC01` | Bank Identifier Incorrect | PSP identifier incorrect (i.e., invalid BIC) *Type of R-trans: Reject, Return* |
| `RR01` | Missing Debtor Account Or Identification | Regulatory Reason *Type of R-trans: Reject, Return* |
| `RR02` | Missing Debtor Name Or Address | Regulatory Reason *Type of R-trans: Reject, Return* |
| `RR03` | Missing Creditor Name Or Address | Regulatory Reason *Type of R-trans: Reject, Return* |
| `RR04` | Regulatory Reason | Regulatory Reason *Type of R-trans: Reject, Return* |
| `SL01` | Specific Service Offered By Debtor Agent | Due to specific service offered by the Debtor PSP *Type of R-trans: Reject, Return* |
## Transfer errors
The following API errors can be encountered regarding [Eletronic Money Wallets](/guide/wallets/introduction#electronic-money-wallet-type-9).
| Code | Message | Description |
|:---: |--- |--- |
| `120018` | Impossible to create the payout SCTE | SCTE payouts are not allowed (e.g., anonymous electronic money) |
| `120020` | Impossible to create the operation, the authorization amount exceed the max amount limit | Amount of the operation exceeds the limit |
| `120021` | Impossible to create the operation, the authorization amount added to the account limit exceed the max account amount limit | Balance of the account exceeds the limit |
| `120019` | Impossible to create the operation, the total debit exceed the max total debit limit on sliding period | Sum of the debit operations in the past 30 days exceeds the limit |
| `120026` | Impossible to create the operation, the total credit exceed the max total credit limit on sliding period | Sum of the credit operations in the past 30 days exceeds the limit |
| `120022` | Impossible to create the operation, the transfer creditor user is invalid | User of the wallet receiving the credit is an anonymous user and doesn’t have a relationship parent/child with the creditor’s user |
| `120023` | Impossible to create the operation, the transfer debitor user is invalid | User crediting the wallet is an anonymous user and doesn’t have a relationship parent/child with the wallet’s user |
| `15016` | Impossible to create the transfer, the BICs of the provided wallets are not the same | The Wallet-to-Wallet transfers is not compatible with [Local IBAN](/guide/wallets/iban), a SEPA Transfer can be initiated instead. |
## Beneficiary errors
The following API errors can be encountered with beneficiaries.
| Code | Message | Additional information |
|:---: |--- |--- |
| `75001` | IBAN Validation failed | |
| `75002` | sddB2bWhitelist validation failed | |
| `75003` | userId validation failed | |
| `75004` | sepaCreditorIdentifier is missing | |
| `75005` | sddB2bWhitelist is missing | |
| `75006` | sddCoreBlacklist validation failed | |
| `75007` | Beneficiary ID does not exist | |
| `75008` | Another beneficiary has already used this userId or sepa\_creditor\_identifier | |
| `75009` | userId is empty or missing | |
| `75010` | sepaCreditorIdentifier is empty or missing | |
| `75011` | BIC IBAN - Invalid country code | See [Accepted countries](/guide/transfers/beneficiaries#accepted-countries) for more information. |
| `180001` | The beneficiaryName is required | |
| `180002` | The beneficiaryIBAN is required | |
| `180003` | The beneficiaryIBAN is invalid | |
| `180050` | The beneficiaryValidationId does not exist | |
## Payout errors
The following API errors can be encountered with payouts.
| Code | Message
|:---: |--- |
| `16010` | Impossible to cancel Payout, this Payout is already CANCELED |
| `16011` | Impossible to cancel Payout, this Payout does not exist |
| `16012` | Impossible to cancel Payout, Database Error. |
| `16045` | Unable to cancel the Payout. |
| `16046` | The label type is not correct, it must be a string |
| `16047` | Label contains invalid chars. Only allowed : 'a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 / - ? : ( ) . , ' + Space |
| `16048` | Label contains invalid chars. Must not start or end with / |
| `16049` | Label contains invalid chars. Must not contain // |
## Mass Payout errors
| Code | Message |
|:---: |--- |
| `16050` | The payoutTag is required |
| `16051` | The payoutTag must be unique |
| `16052` | The massPayout request must contain at least two payouts |
| `16053` | Mass Payout is limited to userTypeId 2, 3, 4, or self-employed users (userTypeId 1 with a self-employed legalForm) |
| `16054` | The user must have subscribed to the opt-out service |
| `16055` | The file size exceeds the limit |
| `16056` | The massPayoutTag is required |
| `16057` | The massPayoutTag must be unique |
| `16058` | All payouts must originate from the same walletId |
| `16061` | The massPayoutId is invalid |
## Mandate errors
| Code | Message |
|:---------:|--------------------------------------------------------------------------------------------------------------|
| `22002` | Unable to create the mandate. The name of the debtor is not valid. |
| `22003` | Unable to create the mandate. The address of the debtor is mandatory. |
| `22004` | Unable to create the mandate. The city of the debtor is mandatory. |
| `22005` | Unable to create the mandate. The zip code of the debtor is mandatory. |
| `22006` | Unable to create the mandate. The country of the debtor is mandatory. |
| `22007` | Unable to create the mandate. The sequence type is mandatory. |
| `22008` | Unable to create the mandate. The IBAN of the debtor is mandatory. |
| `22009` | Unable to create the mandate. The payment type value must be 'OOFF' (one-off) or 'RCUR' (recurrent). |
| `22010` | Unable to create the mandate. The IBAN is not valid. |
| `22011` | Unable to create Mandate. Database Error during the creation of the One-time password. |
| `22012` | Mandate does not exist or is already signed up. |
| `22013` | Unable to sign up the mandate. Wrong OTP. It has been sent again via SMS. |
| `22014` | Unable to update the mandate. Database error during the signing up. |
| `22015` | The mandate you want to cancel does not exist. |
| `22017` | Unable to sign up the mandate. Database error during the signature. |
| `22018` | Unable to create the mandate. The userId is required. |
| `22019` | Unable to create the mandate. The mobile of the debtor is mandatory. |
| `22020` | Unable to create the mandate. An error occurred during the One-time password sending. |
| `22021` | An error occurred during the One-time password sending. |
| `22022` | Error during OTP checking. |
| `22023` | Error during OTP checking. |
| `22024` | mandateId is mandatory. |
| `22025` | Unable to create the mandate. debtorBic is mandatory. |
| `22026` | Unable to create the mandate. User does not have a SEPA creditor identifier. |
| `22028` | Database Error |
| `22029` | Error. The SMS has not been sent to the user. |
| `22030` | Unable to create the mandate. The user does not have an SCI number yet. |
| `22031` | The mandate is already revoked. |
| `22032` | Origin is mandatory. |
| `22033` | Origin can be 'CREDITOR' or 'DEBITOR'. |
| `22034` | Unable to create the mandate. The last name of the debtor is mandatory.|
| `22035` | Unable to create the mandate. The creditor userId does not have a title.|
| `22036` | Unable to create the mandate. The creditor userId does not have a first name.|
| `22037` | Unable to create the mandate. The creditor userId does not have a last name. |
| `22038` | Unable to create the mandate. The creditor userId does not have an address1. |
| `22039` | Unable to create the mandate. The creditor userId does not have a post code. |
| `22040` | Unable to create the mandate. The creditor userId does not have a city. |
| `22041` | Unable to create the mandate. The creditor userId does not have a country. |
| `22042` | Unable to create the mandate. The creditor userId does not have a legal name. |
| `22043` | Unable to create the mandate. The mobile of the debtor must begin by + or 00 followed by the phone country code (e.g., 0033 for France). |
| `22044` | Currently, we only allow paper mandates. |
| `22045` | This type of SDD is not authorized yet. |
| `22046` | OTP is mandatory. |
| `22047` | signatureDate is mandatory. |
| `22048` | The PUT method is not available. |
| `22049` | The signature date is malformatted. |
| `22050` | The userId provided in the request does not exist. |
| `22050` | The userIdUltimateCreditor provided in the request does not exist. |
| `22051` | The Third Party Creditor mode is not activated for your account. Please contact the Treezor Team to ask for activation. |
| `22052` | In third-party creditor mode, the userId of the wallet credited must be equal to the property userIdUltimateCreditor of the mandate. |
---
---
url: /guide/transfers/events.md
description: >-
Reference a comprehensive list of transfer, beneficiaries, and mandates events
for Treezor API webhooks, detailing each event's structure and payload for
integration.
---
# Events
This article lists the [Webhooks](/guide/webhooks/introduction) you may receive when regarding transfers.
## Beneficiary events
To initiate a fund transfer to external accounts, a beneficiary must be created first.
When receiving [SDDR](/guide/transfers/direct-debit#received-direct-debits-sddr), a [Beneficiary](beneficiaries) is automatically created, representing the originator.
### `beneficiary.create`
```json [JSON]
{
"webhook": "beneficiary.create",
"webhook_id": "21410028",
"object": "beneficiary",
"object_id": "131680",
"object_payload": {
"beneficiaries": [
{
"id": 131680,
"tag": "",
"userId": 854084,
"nickName": "",
"name": "XXXX",
"address": "XXXX",
"iban": "",
"bic": "",
"sepaCreditorIdentifier": "XXXX",
"sddB2bWhitelist": [
{
"uniqueMandateReference": "adc2e1ac4024457baf844064ebed4166",
"isRecurrent": false,
"walletId": 334886
}
],
"sddCoreBlacklist":[
],
"usableForSct": false,
"sddCoreKnownUniqueMandateReference": [
],
"isActive": true,
"createdDate": "2021-04-22 10:03:35",
"modifiedDate": "2021-04-22 10:03:35"
}
]
},
"object_payload_signature": "5rG4Xs3vi64p\/r65mcREY0fB0ZDhaYvOA7aQ6bVNhqw="
}
```
### `beneficiary.update`
```json [JSON]
{
"webhook": "beneficiary.update",
"webhook_id": "21410027",
"object": "beneficiary",
"object_id": "120757",
"object_payload": {
"beneficiaries": [
{
"id": 120757,
"tag": "",
"userId": 854084,
"nickName": "",
"name": "creditorName",
"address": "XXXX",
"iban": "",
"bic": "",
"sepaCreditorIdentifier": "XXXX",
"sddB2bWhitelist": [
],
"sddCoreBlacklist": [
"*",
"EDEA7D89D8A34726A02BB09A4F1C3AA1"
],
"usableForSct": false,
"sddCoreKnownUniqueMandateReference": [
],
"isActive": true,
"createdDate": "2021-02-24 13:48:35",
"modifiedDate": "2021-04-22 10:03:35"
}
]
},
"object_payload_signature": "whE26wjEpLekI5PFf+QvlPtD8mPXT8zraMd49LZY0T8="
}
```
## Mandate events
Mandates allow for [SDDE](/guide/transfers/direct-debit#emitted-direct-debits-sdde) payins.
### `mandate.create`
```json [JSON]
{
"messageId": "4d33xxxx-6xxc-5xx4-806a-33fxxxxx7c01",
"webhookId": "bfxxxx02-axxa-4xx0-8xx9-272xxxxx0fe2",
"webhook": {
"webhook": "mandate.create",
"object": "mandate",
"object_id": "7004",
"object_payload": {
"mandates": [
{
"mandateId": 7004,
"title": "M",
"legalInformations": "Compagnie",
"uniqueMandateReference": "39FF[...]E64C1F423",
"mandateStatus": "PENDING",
"userId": 35xxxx3,
"debtorName": "Nom du Debiteur",
"debtorAddress": "33 avenue Wagram",
"debtorCity": "Paris",
"debtorZipCode": "75017",
"debtorCountry": "FR",
"debtorIban": "FR7616[...]xx20",
"debtorBic": "TRZOFR21XXX",
"sequenceType": "one-off",
"creditorName": "Compagnie",
"sepaCreditorIdentifier": "FR123TEST456",
"creditorAddress": "99 rue de test ",
"creditorCity": "Paris",
"creditorZipCode": "75001",
"creditorCountry": "FR",
"signatureDate": "2022-10-22",
"debtorSignatureIp": "",
"signed": 0,
"revocationSignatureDate": null,
"debtorIdentificationCode": "",
"debtorReferencePartyName": "",
"debtorReferenceIdentificationCode": "",
"creditorReferencePartyName": "",
"creditorReferenceIdentificationCode": "",
"contractIdentificationNumber": "",
"contractDescription": "",
"createdDate": null,
"codeStatus": 220001,
"informationStatus": "Mandat complété",
"isPaper": true,
"sddType": "core",
"createdIp": "10.xx.x.37",
"userIdUltimateCreditor": 0
}
]
},
"webhook_created_at": 16661913868587,
"webhook_id": "bfxxxx02-axxa-4xx0-8xx9-xx2dxx2xxfe2",
"object_payload_signature": "8Hv4[...]PnE="
},
"clientId": "878950"
}
```
## Transfer events
[Transfers](/guide/transfers/wallet-to-wallet) are internal, they are from [Wallet](/guide/wallets/introduction) to Wallet.
### `transfer.create`
```json [JSON]
{
"webhook": "transfer.create",
"webhook_id": "10XXXXXX",
"object": "transfer",
"object_id": "3XXXXX",
"object_payload": {
"transfers": [
{
"transferId": "3XXXXX",
"transferTypeId": "3",
"transferTag": "\"=DZm&_h+iT%4\"sS[ABC",
"transferStatus": "PENDING",
"walletId": "5XXXXX",
"foreignId": "0",
"walletTypeId": "10",
"beneficiaryWalletId": "5XXXXX",
"beneficiaryWalletTypeId": "10",
"amount": "21600.00",
"currency": "EUR",
"label": "",
"partnerFee": "0",
"createdDate": "2020-05-19 10:44:20",
"modifiedDate": "0000-00-00 00:00:00",
"walletEventName": "Main",
"walletAlias": "c6ade708-3dfc-48ba-92ac-35b48bbfdb46-5ec24ae1bXOXO",
"beneficiaryWalletEventName": "Main",
"beneficiaryWalletAlias": "33b98677-3487-431b-8b2b-00981ba174d0-5ebe86655XAXA",
"codeStatus": "150001",
"informationStatus": ""
}
]
},
"object_payload_signature": "tUq1WPaRdlapmUl6/ObZGXR1a757XUWeB2erJNUSASAS"
}
```
### `transfer.update`
```json [JSON]
{
"webhook": "transfer.update",
"webhook_id": "10XXXXXX",
"object": "transfer",
"object_id": "32XXXX",
"object_payload": {
"transfers": [
{
"transferId": "32XXXX",
"transferTypeId": "3",
"transferTag": "m_^./![+d8J2NaHiXXXX",
"transferStatus": "VALIDATED",
"walletId": "5XXXXX",
"foreignId": "0",
"walletTypeId": "10",
"beneficiaryWalletId": "5XXXXX",
"beneficiaryWalletTypeId": "10",
"amount": "21600.00",
"currency": "EUR",
"label": "",
"partnerFee": "0",
"createdDate": "2020-05-19 10:16:37",
"modifiedDate": "2020-05-19 10:16:37",
"walletEventName": "Main",
"walletAlias": "eef8bc9d-15d9-42c8-8a3d-e74da26097cc-5ec2428XXXXXX",
"beneficiaryWalletEventName": "Main",
"beneficiaryWalletAlias": "33b98677-3487-431b-8b2b-00981ba174d0-5ebe866XXXXXX",
"codeStatus": "150005",
"informationStatus": ""
}
]
},
"object_payload_signature": "uPTyXZHnG0YyL0CTe3OoWMup7qLU6I5UFJtjHfmXXXXX"
}
```
### `transfer.cancel`
```json [JSON]
{
"webhook": "transfer.cancel",
"webhook_id": "1xxxxxxxx",
"object": "transfer",
"object_id": "3xxxxx",
"object_payload": {
"transfers": [
{
"transferId": "3xxxxx",
"transferTypeId": "1",
"transferTag": "",
"transferStatus": "CANCELED",
"walletId": "4xxxxx",
"foreignId": "0",
"walletTypeId": "10",
"beneficiaryWalletId": "4xxxxx",
"beneficiaryWalletTypeId": "10",
"amount": "1xxx.00",
"currency": "EUR",
"label": "label",
"partnerFee": "0",
"createdDate": "2020-05-05 23:45:30",
"modifiedDate": "2020-05-05 23:45:38",
"walletEventName": "wallet of second ",
"walletAlias": "aaaaa-5e99cc3161a61",
"beneficiaryWalletEventName": "aaaaa ",
"beneficiaryWalletAlias": "aaaaa-5e99cc88d0000",
"codeStatus": "150003",
"informationStatus": ""
}
]
},
"object_payload_signature": "XNYa62cf3z8RIL2NTATK3yNqQ4l6sXSzsaJRBxWz0000"
}
```
## SDDR webhooks
Find below the series of webhooks you may receive during the processing of a received SEPA Direct Debit.
### `sepa_sddr.reception`
#### SDDR Core
```json [JSON]
{
"messageId": "efab78b5-d90f-5fcb-9111-2xxxxxxxxxx",
"webhookId": "36a6ab15-62ca-4f98-bxx3-8xxxxxxxxxx",
"webhook": {
"webhook": "sepa_sddr.reception",
"object_payload": {
"sepaSddr": {
"wallet_id": 123456789,
"virtual_iban_id": null,
"beneficiary_id": 445566,
"transaction_id": "00950N2202482123456796",
"interbank_settlement_amount": "98.77",
"requested_collection_date": {
"date": "2024-11-21 00:00:00",
"timesone_type": 3,
"timezone": "UTC"
},
"local_instrument": "CORE",
"mandate_id": "XXXXXX",
"creditor_scheme_id": "FR11ZZZ12346",
"debitor_name": "TREE CIE",
"debitor_address": "",
"debitor_country": "",
"creditor_name": "CREDITOR NAME",
"creditor_address": "CREDITOR ADDRESS 75006 PARIS FR",
"creditor_country": "FR",
"creditor_bic": "SOGEFRPPXXX",
"creditor_iban": "FR7630003009500006711111111",
"unstructured_field": "XXXX",
"created_date": {
"date": "2024-11-20 15:15:27",
"timesone_type": 3,
"timezone": "UTC"
}
}
},
"object_id": "8311386",
"object": "sepa_sddr",
"webhook_created_at": 17321555274116,
"webhook_id": "36a6ab15-62ca-4f98-b783-8656ee555556",
"object_payload_signature": "ecIAA53k4nWGVtG97g4hDBEOxxxVUUx9cKUQDNejl5M="
},
"clientId": "12345"
}
```
#### SDDR B2B
```json [JSON]
{
"messageId": "9e8c9d92-86fe-528f-9f8a-c22xxxxxxbf",
"webhookId": "c602365b-03fd-495d-a6ea-1xxxxxa92b6",
"webhook": {
"webhook": "sepa_sddr.reception",
"object_payload": {
"sepaSddr": {
"wallet_id": 123456,
"virtual_iban_id": null,
"beneficiary_id": 0,
"transaction_id": "COMD981234595294XXX",
"interbank_settlement_amount": "90.00",
"requested_collection_date": {
"date": "2024-11-21 00:00:00",
"timesone_type": 3,
"timezone": "UTC"
},
"local_instrument": "B2B",
"mandate_id": "nn844244566DGFIP2023684XXXX",
"creditor_scheme_id": "FR11ZZZ12345",
"debitor_name": "DEBITOR NAME",
"debitor_address": "adresse inconnue adresse inconnue",
"debitor_country": "FR",
"creditor_name": "CREDITOR NAME",
"creditor_address": "",
"creditor_country": "",
"creditor_bic": "BDXXXXX",
"creditor_iban": "FR6930001007034520X12345640",
"unstructured_field": "",
"created_date": {
"date": "2024-11-19 18:18:05",
"timesone_type": 3,
"timezone": "UTC"
}
}
},
"object_id": "8312389",
"object": "sepa_sddr",
"webhook_created_at": 17320402855364,
"webhook_id": "c602365b-03fd-495d-a6ea-12e22512345",
"object_payload_signature": "VDW+mMThl4azQ5FXixxxxVX80Bts+bl3Cpor0g53Rnw="
},
"clientId": "191294"
}
```
### `sepa.reject_sddr_core`
```json [JSON]
{
"webhook": "sepa.reject_sddr_core",
"webhook_id": "35XXXX370",
"object": "sepaSddr",
"object_id": "2xxxxx7",
"object_payload": {
"sepaSddrs": [
{
"wallet_id": 123456,
"virtual_iban_id": null,
"transaction_id": "20155xxxxxx00434",
"sequence_type": "RCUR",
"reject_reason_code": "MS02",
"interbank_settlement_amount": "33.97",
"requested_collection_date": "2020-06-08",
"mandate_id": "700xxxxxxxxxx66",
"sepa_creditor_identifier": "FRXXXXXXX3",
"date_of_signature": "2020-02-06",
"debitor_name": "XXXX",
"debitor_address": null,
"debitor_country": null,
"creditor_name": "XXXX",
"creditor_address": "XXXX",
"creditor_country": "FR",
"unstructured_field": "XXXX",
"bankaccount_id": null,
"beneficiary_id": 1000089
}
]
},
"object_payload_signature": "6ZEv505Swg5QsAnGBcuEOs2CvXHmUMF2ObzXkgudyl8="
}
```
### `sepa.reject_sddr_b2b`
```json [JSON]
{
"webhook": "sepa.reject_sddr_b2b",
"webhook_id": "35XXXX29",
"object": "sepaSddr",
"object_id": "21XXXX0",
"object_payload": {
"sepaSddrs": [
{
"wallet_id": 23456,
"virtual_iban_id": null,
"transaction_id": "20155XXXXXX50",
"sequence_type": "RCUR",
"reject_reason_code": "AM04",
"interbank_settlement_amount": "2495",
"requested_collection_date": "2020-06-05",
"mandate_id": "nnABCDEFGHIJKLMOXXXXXXYTJ5",
"sepa_creditor_identifier": "FR46XXXXXX02",
"date_of_signature": "2019-02-05",
"debitor_name": "TREE CIE",
"debitor_address": "",
"debitor_country": null,
"creditor_name": "CREDITOR NAME",
"creditor_address": "",
"creditor_country": null,
"unstructured_field": "IS-052020-2572",
"bankaccount_id": null,
"beneficiary_id": null
}
]
},
"object_payload_signature": "amXZewtaB2KcFTX15xnOxxxxx/980HZvgBfo3jSIKo="
}
```
### `beneficiary.create`
#### SDDR Core
```json [JSON]
{
"messageId": "0937c153-38e2-5b25-ad62-9exxxxxe96",
"webhookId": "cfe12dbe-ede6-43de-953d-0ebxxxxd8a95",
"webhook": {
"webhook": "beneficiary.create",
"object_payload": {
"beneficiaries": [
{
"id": 123456789,
"tag": "",
"userId": 11111144,
"nickName": "",
"name": "TREE S.A.",
"address": "FR",
"iban": "FR76177890000119999999737",
"bic": "DEUXXXXPXXX",
"sepaCreditorIdentifier": "FR03SXXX02381",
"sddB2bWhitelist": [],
"sddCoreBlacklist": null,
"usableForSct": false,
"sddCoreKnownUniqueMandateReference": null,
"isActive": true,
"createdDate": "2024-11-06 08:15:43",
"modifiedDate": "2024-11-06 08:15:43"
}
]
},
"object_id": "1234567",
"object": "beneficiary",
"webhook_created_at": 17308809434537,
"webhook_id": "cfe12dbe-ede6-43de-953d-xxxx49d8a95",
"object_payload_signature": "gHOGPMeuWQr9m/Dwlx9J111xxxoXILE7nc4QBCigwHg="
},
"clientId": "12345"
}
```
#### SDDR B2B
```json [JSON]
{
"messageId": "683f5597-92f3-539f-80a2-0a9xxxxx2d0b",
"webhookId": "1431c1f1-dddd-4bbe-a2f9-1184xxxxx6",
"webhook": {
"webhook": "beneficiary.create",
"object": "beneficiary",
"object_id": "3974948",
"object_payload": {
"beneficiaries": [
{
"id": 123456,
"tag": "",
"userId": 123456789,
"nickName": "",
"name": "TREE CIE",
"address": "15 ROSEWOOD LANE",
"iban": "",
"bic": "",
"sepaCreditorIdentifier": "FR44ZZZ123456",
"sddB2bWhitelist": [
{
"uniqueMandateReference": "nn539565911DGFIP2111111347LY454WW7",
"isRecurrent": true
}
],
"sddCoreBlacklist": [],
"usableForSct": false,
"sddCoreKnownUniqueMandateReference": [],
"isActive": true,
"createdDate": "2024-07-08 14:03:41",
"modifiedDate": "2024-07-08 14:03:41"
}
]
},
"webhook_created_at": 17204474219169,
"webhook_id": "1431c1f1-xxxx-xxxx-xxxx-1184b5c2b076",
"object_payload_signature": "Yvd4c8X3H/WeL7eCBRKWX/hW/anZhnXTLXXXXX2DeQ="
},
"clientId": "12345"
}
```
### `sepa.return_sddr`
#### SDDR Core
```json [JSON]
{
"messageId": "a76cbdb5-xxxx-xxxx-xxxx-e203bf6f144a",
"webhookId": "b2b23d28-xxxx-xxxx-xxxx-d5c649955ea0",
"webhook": {
"webhook": "sepa.return_sddr",
"object_payload": {
"sepaSddrs": [
{
"wallet_id": 123456,
"virtual_iban_id": null,
"transaction_id": "REPSDD241XXXX1FR45549720562",
"sequence_type": "RCUR",
"reject_reason_code": null,
"reason_code": "AM04",
"interbank_settlement_amount": "46.72",
"requested_collection_date": "2024-11-19 00:00:00",
"mandate_id": "00S017745232",
"sepa_creditor_identifier": "FRXXXXXX",
"date_of_signature": "2022-05-31 00:00:00",
"debitor_name": "Debitor Name",
"debitor_address": "14 ROSEWOOD LANE",
"debitor_country": "FR",
"creditor_name": "BLUE TREE S.A.",
"creditor_address": "FR",
"creditor_country": "FR",
"unstructured_field": "",
"bankaccount_id": null,
"beneficiary_id": 123456
}
]
},
"object_id": "123",
"object": "sepa_sddr",
"webhook_created_at": 17320365151141,
"webhook_id": "b2b23d28-1111-xxxx-11111-d5c649955ea0",
"object_payload_signature": "JVCCqpKBps/6atnn0o2Rsdv/2b+xxxxc/qOuNjSlu8o="
},
"clientId": "12345"
}
```
#### SDDR B2B
```json [JSON]
{
"messageId": "0da13ff4-xxxx-1111-xxxx-60436e0a2b48",
"webhookId": "79aad3d5-1111-xxxx-1111-5fbbad0b1a00",
"webhook": {
"webhook": "sepa.return_sddr",
"object_payload": {
"sepaSddrs": [
{
"wallet_id": 12345,
"virtual_iban_id": null,
"transaction_id": "COMD98G90112345XXX",
"sequence_type": "RCUR",
"reject_reason_code": null,
"reason_code": "AM04",
"interbank_settlement_amount": "278",
"requested_collection_date": "2024-11-20 00:00:00",
"mandate_id": "nn482136264DGFIP20212345LO6WTI8C",
"sepa_creditor_identifier": "FR46ZZZ005002",
"date_of_signature": "2023-10-26 00:00:00",
"debitor_name": "TREE COMPANY",
"debitor_address": "ROSEWOOD LANE 75012 PARIS",
"debitor_country": "FR",
"creditor_name": "CREDITOR NAME",
"creditor_address": "",
"creditor_country": "",
"unstructured_field": "",
"bankaccount_id": null,
"beneficiary_id": 123456
}
]
},
"object_id": "8384450",
"object": "sepa_sddr",
"webhook_created_at": 17321121144920,
"webhook_id": "79aad3d5-xxxx-xxxx-xxxx-5fbbad0b1a00",
"object_payload_signature": "WigBc/JUKTYnk/8PsAv123654/b1Z+3FaBbkZQ3X4="
},
"clientId": "12345"
}
```
### `sepa.refund_sddr`
```json [JSON]
{
"webhook": "sepa.refund_sddr",
"webhook_id": "4XXXXXX5",
"object": "sepaSddr",
"object_id": "21XXXX0",
"object_payload": {
"sepaSddrs": [
{
"wallet_id": 600007,
"virtual_iban_id": null,
"transaction_id": "20155XXXXXX50",
"sequence_type": "RCUR",
"reject_reason_code": null,
"reason_code": "MD06",
"interbank_settlement_amount": "2495",
"requested_collection_date": "2020-06-05",
"mandate_id": "nnABCDEFGHIJKLMONPJRRWYTJ5",
"sepa_creditor_identifier": "FR46XXXXXX02",
"date_of_signature": "2019-02-05",
"debitor_name": "MA SOCIETE",
"debitor_address": " ",
"debitor_country": null,
"creditor_name": "DGFIP",
"creditor_address": " ",
"creditor_country": null,
"unstructured_field": "IS-052020-2572",
"bankaccount_id": null,
"beneficiary_id": null
}
]
},
"object_payload_signature": "123xyztaB2KcFTX15xnOVQ86ek/980HZvfgto3jSIKo="
}
```
### `payout.create`
#### SDDR Core
```json [JSON]
{
"messageId": "41897072-44444-55555-66666-2fc474aee947",
"webhookId": "9676e0cb-7777-99999-88888-7c87e9780c16",
"webhook": {
"webhook": "payout.create",
"object_payload": {
"payouts": [
{
"payoutId": "123456789",
"payoutTag": "",
"payoutStatus": "VALIDATED",
"payoutTypeId": "2",
"payoutType": "Direct Debit",
"walletId": "123456",
"payoutDate": "2024-11-19",
"walletEventName": "WALLET NAME",
"walletAlias": "wallet-name-5bbb97ed9f75d",
"userLastname": "OAK",
"userFirstname": "ALEX",
"userId": "123456789",
"bankaccountId": "123654",
"beneficiaryId": "789654",
"uniqueMandateReference": "5MAXXX54W2FUU",
"bankaccountIBAN": "",
"label": "XXXX/ADD TO BALANCE",
"amount": "30.00",
"currency": "EUR",
"partnerFee": "",
"createdDate": "2024-11-19 08:00:38",
"modifiedDate": "",
"virtualIbanId": null,
"virtualIbanReference": null,
"codeStatus": "160005",
"informationStatus": "Validated",
"supportingFileLink": "",
"endToEndId": "12345678963",
"reasonCode": null,
"reasonDescription": null,
"metadata": null,
"totalRows": 1
}
]
},
"object_id": "20440330",
"object": "payout",
"webhook_created_at": 17320032389643,
"webhook_id": "9676e0cb-xxxx-eeee-rrrr-7c87e9780c16",
"object_payload_signature": "8Zf6k5tVfxGwZeUP7iagDdjsffffEwHO7kppSBagMS/M="
},
"clientId": "123456"
}
```
#### SDDR B2B
```json [JSON]
{
"messageId": "3eeb07b1-aaaa-zzzz-rrrr-5806a3c01443",
"webhookId": "754f2204-vvvv-nnnn-ssss-f4d58a6c5688",
"webhook": {
"webhook": "payout.create",
"object_payload": {
"payouts": [
{
"payoutId": "123456789",
"payoutTag": "",
"payoutStatus": "VALIDATED",
"payoutTypeId": "2",
"payoutType": "Direct Debit",
"walletId": "123456",
"payoutDate": "2024-11-20",
"walletEventName": "Wallet Name",
"walletAlias": "wallet-name-61dffb46b1fae",
"userLastname": "",
"userFirstname": "",
"userId": "123654",
"bankaccountId": "987456",
"beneficiaryId": "258963",
"uniqueMandateReference": "nn909003626DGFIP2022906XXXXXK8S8F",
"bankaccountIBAN": "",
"label": "TVA-XXXXX-3310CA3",
"amount": "4514.00",
"currency": "EUR",
"partnerFee": "",
"createdDate": "2024-11-20 08:01:44",
"modifiedDate": "",
"virtualIbanId": null,
"virtualIbanReference": null,
"codeStatus": "160005",
"informationStatus": "Validated",
"supportingFileLink": "",
"endToEndId": "22075712999999333457",
"reasonCode": null,
"reasonDescription": null,
"metadata": null,
"totalRows": 1
}
]
},
"object_id": "20151121926",
"object": "payout",
"webhook_created_at": 17320897049707,
"webhook_id": "754f2204-xxx-xxxx-xxxx-f4d58a6c5688",
"object_payload_signature": "xYgn0KTD/iL+mfP74/AP9Udbe125ffffffffYGBDPlQ="
},
"clientId": "123456"
}
```
### `transaction.create`
#### SDDR Core
```json [JSON]
{
"messageId": "1f34be62-aaaa-aaaa-aaaa-e1d48d4b1265",
"webhookId": "608e6ceb-cccc-cccc-cccc-aea3afc9e446",
"webhook": {
"webhook": "transaction.create",
"object_payload": {
"transactions": [
{
"transactionId": "12345",
"walletDebitId": "32165",
"walletCreditId": "9",
"transactionType": "Payout",
"foreignId": "123654",
"name": "111111",
"description": "Prélèvement 123654",
"valueDate": "2024-11-19",
"executionDate": "2024-11-19",
"amount": "30.00",
"walletDebitBalance": "1368.21",
"walletCreditBalance": "0.00",
"currency": "EUR",
"createdDate": "2024-11-19 09:00:38"
}
]
},
"object_id": "99999999",
"object": "transaction",
"webhook_created_at": 17320032389078,
"webhook_id": "608e6ceb-xxxx-xxxx-xxxx-aea3afc9e446",
"object_payload_signature": "5YDh3HrB8IM7eMaOE4f9cl7jI/e1d48d4b1265="
},
"clientId": "123456"
}
```
#### SDDR B2B
```json [JSON]
{
"messageId": "672f7914-xxxx-xxxx-xxxx-26a35280b07c",
"webhookId": "1ad05bba-xxxx-xxxx-xxxx-1429c9182b39",
"webhook": {
"webhook": "transaction.create",
"object_payload": {
"transactions": [
{
"transactionId": "123456",
"walletDebitId": "654789",
"walletCreditId": "9",
"transactionType": "Payout",
"foreignId": "654789",
"name": "XXXX",
"description": "Prélèvement XXXX",
"valueDate": "2024-11-20",
"executionDate": "2024-11-20",
"amount": "4514.00",
"walletDebitBalance": "109673.64",
"walletCreditBalance": "0.00",
"currency": "EUR",
"createdDate": "2024-11-20 09:01:44"
}
]
},
"object_id": "870584566",
"object": "transaction",
"webhook_created_at": 17320897048636,
"webhook_id": "1ad05bba-eeee-eeee-eeee-1429c9182b39",
"object_payload_signature": "MAJr6N1YxFPg9Nn+DFFFE+TWdQZl4ep5kQCk="
},
"clientId": "12345"
}
```
### `payoutRefund.create`
```json [JSON]
{
"messageId": "a1b2c3d4-e5f6-54g7-8h9i-j0k1l2m3n4o5",
"webhookId": "b2c3d4e5-f6g7-4h8i-9j0k-l1m2n3o4p5q6",
"webhook": {
"webhook": "payoutRefund.create",
"object": "payoutRefund",
"object_id": "59760",
"object_payload": {
"payoutRefunds": [
{
"id": "59760",
"payoutRefundTag": "",
"codeStatus": 790001,
"informationStatus": "PENDING",
"payoutId": "19686689",
"requestAmount": "20.00",
"requestCurrency": "EUR",
"requestComment": "",
"reasonCode": "MD06",
"refundAmount": "",
"refundCurrency": "",
"refundDate": null,
"refundComment": "",
"negativeResponseReasonCode": "",
"createdDate": "2024-10-01 13:17:47",
"modifiedDate": null
}
]
},
"webhook_created_at": 17277886676171,
"webhook_id": "b2c3d4e5-f6g7-4h8i-9j0k-l1m2n3o4p5q6",
"object_payload_signature": "WUySz+2mVHTIyzyp3XNP5i2NSu3y8fhowxuv+K4Vx00="
},
"clientId": "12345"
}
```
### `payoutRefund.update`
```json [JSON]
{
"messageId": "a1b2c3d4-e5f6-5g7h-8i9j-k0l1m2n3o4p5",
"webhookId": "b2c3d4e5-f6g7-4h8i-9j0k-l1m2n3o4p5q6",
"webhook": {
"webhook": "payoutRefund.update",
"object": "payoutRefund",
"object_id": "59760",
"object_payload": {
"payoutRefunds": [
{
"id": "59760",
"payoutRefundTag": "",
"codeStatus": 790003,
"informationStatus": "VALIDATED",
"payoutId": "19686689",
"requestAmount": "20.00",
"requestCurrency": "EUR",
"requestComment": "",
"reasonCode": "MD06",
"refundAmount": "20",
"refundCurrency": "EUR",
"refundDate": "2024-10-01",
"refundComment": "",
"negativeResponseReasonCode": "",
"createdDate": "2024-10-01 13:17:47",
"modifiedDate": "2024-10-01 17:15:16"
}
]
},
"webhook_created_at": 17278029168100,
"webhook_id": "c3d4e5f6-g7h8-4i9j-0k1l-m2n3o4p5q6r7",
"object_payload_signature": "nDESXRVXi9VuUXqF9+FsPbDXcs5ND322ODtAN54D/04="
},
"clientId": "12345"
}
```
## SDDE webhooks
Find below the series of webhooks you may receive during the processing of an emitted SEPA Direct Debit.
### `payin.create`
```json [JSON]
{
"messageId": "aca2ac41-xxxx-xxxx-xxxx-f3dfba7c57f9",
"webhookId": "7a65a4da-xxxx-xxxx-xxxx-d6ff82919991",
"webhook": {
"webhook": "payin.create",
"object": "payin",
"object_id": "12369999",
"object_payload": {
"payins": [
{
"payinId": "12365478",
"payinTag": "540afcb0-xxxx-xxxx-xxxx-95717e8ffaf8",
"walletId": "123456",
"userId": "3",
"payinStatus": "PENDING",
"paymentMethodId": "21",
"messageToUser": "",
"subtotalItems": "0.00",
"subtotalServices": "0.00",
"subtotalTax": "0.00",
"amount": "424.51",
"currency": "EUR",
"createdDate": "2024-11-01 01:00:02",
"walletEventName": "Wallet Name",
"walletAlias": "wallet-name-2-6406c12315bef",
"userFirstname": "Alex",
"userLastname": "Oak",
"codeStatus": "140001",
"informationStatus": "",
"refundAmount": null,
"DbtrIBAN": null,
"forwardUrl": null,
"paymentAcceptedUrl": null,
"paymentRefusedUrl": null,
"paymentWaitingUrl": null,
"paymentExceptionUrl": null,
"paymentCanceledUrl": null,
"payinDate": "2024-11-07",
"mandateId": "52850",
"creditorName": null,
"creditorAddressLine": null,
"creditorCountry": null,
"creditorIban": null,
"creditorBIC": null,
"virtualIbanId": null,
"virtualIbanReference": null,
"additionalData": "",
"totalRows": 1,
"paymentHtml": null
}
]
},
"webhook_created_at": 17304192026804,
"webhook_id": "7a65a4da-xxx-xxxx-xxxx-d6ff82919991",
"object_payload_signature": "LYSu34X59tE9EukD+KS/fwxxxxxyAmwamYBQjZu8Kds="
},
"clientId": "908165"
}
```
### `payin.update`
```json [JSON]
{
"messageId": "3a5e1eb4-xxxx-xxxx-xxxx-4113b64e094b",
"webhookId": "0e7495ac-xxxx-xxxx-xxxx-805f5dc745bf",
"webhook": {
"webhook": "payin.update",
"object_payload": {
"payins": [
{
"payinId": "123456",
"payinTag": "540afcb0-xxxx-xxxx-xxxx-95717e8ffaf8",
"walletId": "123456789",
"userId": "3",
"paymentMethodId": "21",
"messageToUser": "A",
"subtotalItems": "",
"subtotalServices": "",
"subtotalTax": "",
"amount": "424.51",
"currency": "",
"createdDate": "2024-11-01 01:00:02",
"walletEventName": "Wallet Name",
"walletAlias": "wallet-name-6406c123456bef",
"userFirstname": "",
"userLastname": "",
"payinStatus": "VALIDATED",
"codeStatus": "140005",
"informationStatus": "VALIDATED",
"refundAmount": null,
"ibanFullname": "",
"DbtrIBAN": "FR761027806013000XXXX30225",
"ibanBic": "",
"ibanTxEndToEndId": "",
"ibanTxId": "",
"forwardUrl": null,
"paymentAcceptedUrl": null,
"paymentRefusedUrl": null,
"paymentWaitingUrl": null,
"paymentExceptionUrl": null,
"paymentCanceledUrl": null,
"payinDate": "2024-11-07",
"mandateId": "52850",
"creditorName": "Creditor Name",
"creditorAddressLine": "15 ROSEWOOD ROAD",
"creditorCountry": "FR",
"creditorIban": "FR761679800001000XXXX15604",
"creditorBIC": "TRZOFR21XXX",
"virtualIbanId": null,
"virtualIbanReference": null,
"additionalData": "",
"ibanId": "",
"totalRows": 0,
"paymentHtml": null
}
]
},
"object_id": "123456987",
"object": "payin",
"webhook_created_at": 17310062402680,
"webhook_id": "0e7495ac-xxxx-xxxx-xxxx-805f5dc745bf",
"object_payload_signature": "0cu82+3JNuYpZx5QPpqqNeV123654Cgz5ekBPvGmfZ1k="
},
"clientId": "12345"
}
```
### `payin.cancel`
```json [JSON]
{
"messageId": "8ee5e015-xxxx-xxxx-xxxx-bfb30697058d",
"webhookId": "edce11f7-xxxx-xxxx-xxxx-6267d3b17992",
"webhook": {
"webhook": "payin.cancel",
"object_payload": {
"payins": [
{
"payinId": "123456",
"payinTag": "987654",
"walletId": "654789",
"userId": "456123",
"paymentMethodId": "21",
"messageToUser": "",
"subtotalItems": "",
"subtotalServices": "",
"subtotalTax": "",
"amount": "9688.72",
"currency": "EUR",
"createdDate": "2024-11-04 19:01:52",
"walletEventName": "Wallet Name",
"walletAlias": "wallet-Name-6296165c10f1d",
"userFirstname": "Tree Cie",
"userLastname": "Tree Cie",
"payinStatus": "CANCELED",
"codeStatus": "150115",
"informationStatus": "MS02",
"refundAmount": null,
"ibanFullname": "",
"DbtrIBAN": "FR7613335000400412345692550",
"ibanBic": "",
"ibanTxEndToEndId": "",
"ibanTxId": "",
"forwardUrl": null,
"paymentAcceptedUrl": null,
"paymentRefusedUrl": null,
"paymentWaitingUrl": null,
"paymentExceptionUrl": null,
"paymentCanceledUrl": null,
"payinDate": "2024-11-04 19:01:52 +0000 UTC",
"mandateId": "38217",
"creditorName": "Creditor name",
"creditorAddressLine": "10 WILLOW LANE 75008 Paris",
"creditorCountry": "FR",
"creditorIban": "FR761679800001098745610308",
"creditorBIC": "TRZOFR21XXX",
"virtualIbanId": null,
"virtualIbanReference": null,
"additionalData": "",
"ibanId": "",
"totalRows": 0,
"paymentHtml": null
}
]
},
"object_id": "31771605",
"object": "payin",
"webhook_created_at": 17309826676945,
"webhook_id": "edce11f7-xxxx-xxxx-xxxx-6267d3b17992",
"object_payload_signature": "LYbuxxxxxlQnZTgD1lCfFrFMJBpuxzSS2M/hiA5EIM="
},
"clientId": "12345"
}
```
### `transaction.create`
```json [JSON]
{
"messageId": "213bdfe8-ffff-ffff-ffff-804f8892b101",
"webhookId": "39dc5126-ffff-ffff-ffff-f0cea7aaae6d",
"webhook": {
"webhook": "transaction.create",
"object_payload": {
"transactions": [
{
"transactionId": "10232569",
"walletDebitId": "9",
"walletCreditId": "321654",
"transactionType": "Payin",
"foreignId": "852369741",
"name": "222222",
"description": "sdde payin_id 12345669",
"valueDate": "2024-11-07",
"executionDate": "2024-11-07",
"amount": "424.51",
"walletDebitBalance": "0.00",
"walletCreditBalance": "539.92",
"currency": "EUR",
"createdDate": "2024-11-07 20:01:00"
}
]
},
"object_id": "863333120",
"object": "transaction",
"webhook_created_at": 17310060608928,
"webhook_id": "39dc5126-xxxx-xxxx-xxxx-f0cea7aaae6d",
"object_payload_signature": "ATCVsw0AVyUWcuIlj/gATPIrKvDsFU123456vpddutAY="
},
"clientId": "12345"
}
```
### `payinrefund.create`
```json [JSON]
{
"messageId": "c23a16e7-hhhh-hhhh-hhhh-4992bdf70c2e",
"webhookId": "6ef4154d-hhhh-hhhh-hhhh-ff1796e2a69e",
"webhook": {
"webhook": "payinrefund.create",
"object_payload": {
"payinrefunds": [
{
"payinrefundId": "123654",
"payinrefundTag": null,
"payinrefundStatus": "PENDING",
"walletId": "10203040",
"payinId": "30201040",
"payinrefundDate": "0000-00-00",
"amount": "18.42",
"currency": "EUR",
"createdDate": "2024-10-01 10:30:59",
"modifiedDate": "0000-00-00 00:00:00",
"codeStatus": "170001",
"informationStatus": "AM04",
"reasonTms": null
}
]
},
"object_id": "32145",
"object": "payinrefund",
"webhook_created_at": 17277669259687,
"webhook_id": "6ef4154d-xxxx-xxxx-xxxx-ff1796e2a69e",
"object_payload_signature": "9Dsct7JSBvbDco1236547nm44icy5DbKUq/7y1GnQnaU0="
},
"clientId": "12345"
}
```
### `payinrefund.update`
```json [JSON]
{
"messageId": "e0f6134e-xxxx-xxxx-xxxx-4c3b6ef7b243",
"webhookId": "cfbe862d-xxxx-xxxx-xxxx-1bc11f2c8284",
"webhook": {
"webhook": "payinrefund.update",
"object_payload": {
"payinrefunds": [
{
"payinrefundId": "123654",
"payinrefundTag": null,
"payinrefundStatus": "VALIDATED", // or ACCEPTED
"walletId": "3214569",
"payinId": "6547896",
"payinrefundDate": "2024-10-01",
"amount": "18.42",
"currency": "EUR",
"createdDate": "2024-10-01 10:30:59",
"modifiedDate": "2024-10-01 10:30:59",
"codeStatus": "170005",
"informationStatus": "AM04",
"reasonTms": null
}
]
},
"object_id": "33333",
"object": "payinrefund",
"webhook_created_at": 17277669260404,
"webhook_id": "cfbe862d-ffff-ffff-ffff-1bc11f2c8284",
"object_payload_signature": "nYL4fstR7jl5llllll1H04P+rp4+D69rqLWNyjWSb7Hc="
},
"clientId": "206135"
}
```
## SCTE webhooks
Find below the series of webhooks you may receive during the processing of an emitted SEPA Credit Transfer.
### `payout.create`
```json [JSON]
{
"messageId": "b73e9f12-c8d4-5a1b-9e3f-d2c7b8a9f0e1",
"webhookId": "f5e6d7c8-b9a0-4d2e-a1b2-c3d4e5f6a7b8",
"webhook": {
"webhook": "payout.create",
"object": "payout",
"object_id": "20356891",
"object_payload": {
"payouts": [
{
"payoutId": "123456",
"payoutTag": "",
"payoutStatus": "PENDING",
"payoutTypeId": "1",
"payoutType": "Credit Transfer",
"walletId": "7654321",
"bankaccountId": "0",
"beneficiaryId": "987650",
"endToEndId": null,
"uniqueMandateReference": null,
"label": "",
"payoutDate": "0000-00-00",
"amount": "1000.00",
"currency": "EUR",
"partnerFee": "0",
"createdDate": "2024-12-06 23:58:33",
"modifiedDate": "0000-00-00 00:00:00",
"walletEventName": "Main",
"walletAlias": "a1b2c3d4-e5f6-47g8-9h0i-j1k2l3m4n5o6",
"userLastname": "",
"userFirstname": "",
"userId": "5432176",
"bankaccountIBAN": null,
"virtualIbanId": null,
"virtualIbanReference": null,
"codeStatus": "160001",
"informationStatus": "Demande de remboursement saisie",
"supportingFileLink": "",
"reasonCode": "",
"reasonDescription": "",
"totalRows": 1
}
]
},
"webhook_created_at": 17335259137789,
"webhook_id": "f5e6d7c8-b9a0-4d2e-a1b2-c3d4e5f6a7b8",
"object_payload_signature": "G1MiRO4x1ZVcCrXLMxNraacj6g9lWvWXpvK0foZY22I="
}
}
```
### `payout.update`
#### Pending
```json [JSON]
{
"messageId": "c13754fd-xxxx-xxxx-xxxx-0b63abaac0e4",
"webhookId": "9cd4163f-xxxx-xxxx-xxxx-61206810c8ce",
"webhook": {
"webhook": "payout.update",
"object_payload": {
"payouts": [
{
"payoutId": "1234567",
"payoutTag": "",
"payoutStatus": "PENDING",
"payoutTypeId": "1",
"payoutType": "Credit Transfer",
"walletId": "54321",
"payoutDate": "2024-09-30",
"walletEventName": "Wallet 319158",
"walletAlias": "wallet-319158-59f0d43680747",
"userLastname": "",
"userFirstname": "",
"userId": "987654",
"bankaccountId": "0",
"beneficiaryId": "456789",
"uniqueMandateReference": "",
"bankaccountIBAN": "FR3140031000010000393123456",
"label": "",
"amount": "10.69",
"currency": "EUR",
"partnerFee": "0",
"createdDate": "2024-09-30 10:36:57",
"modifiedDate": "2024-11-01 10:34:12",
"virtualIbanId": null,
"virtualIbanReference": null,
"codeStatus": "160014",
"informationStatus": "Virement sortant envoyé en compensation, en attente de l'accusé de réception",
"supportingFileLink": "",
"endToEndId": null,
"reasonCode": null,
"reasonDescription": null,
"metadata": null,
"totalRows": 1
}
]
},
"object_id": "19673123",
"object": "payout",
"webhook_created_at": 17304536521193,
"webhook_id": "9cd4163f-xxxx-xxxx-xxxx-61206810c8ce",
"object_payload_signature": "9/LLDq1yrJCvjm4QyP0F4vA6XXBKFT9QSvoAUoA1IBs="
},
"clientId": "12345"
}
```
#### Validated
```json [JSON]
{
"messageId": "17f6cb9a-xxxx-xxxx-xxxx-9404a161b12c",
"webhookId": "42b2183a-xxxx-xxxx-xxxx-38ed1949c7f9",
"webhook": {
"webhook": "payout.update",
"object": "payout",
"object_id": "19673327",
"object_payload": {
"payouts": [
{
"payoutId": "123456",
"payoutTag": "",
"payoutStatus": "VALIDATED",
"payoutTypeId": "1",
"payoutType": "Credit Transfer",
"walletId": "12345",
"bankaccountId": "0",
"beneficiaryId": "98765",
"endToEndId": null,
"uniqueMandateReference": null,
"label": "",
"payoutDate": "2024-11-01",
"amount": "10.69",
"currency": "EUR",
"partnerFee": "0",
"createdDate": "2024-09-30 10:36:57",
"modifiedDate": "2024-11-01 12:29:31",
"walletEventName": "Wallet 319158",
"walletAlias": "wallet-319158-59f0d43680747",
"userLastname": "",
"userFirstname": "",
"userId": "708922",
"bankaccountIBAN": null,
"virtualIbanId": null,
"virtualIbanReference": null,
"codeStatus": "160004",
"informationStatus": "Envoyé en banque",
"supportingFileLink": "",
"reasonCode": "",
"reasonDescription": "",
"totalRows": 1
}
]
},
"webhook_created_at": 17304605714246,
"webhook_id": "42b2183a-xxxx-xxxx-xxxx-38ed1949c7f9",
"object_payload_signature": "IveNdWaxRQEk9hvQCfwTguAXXXXs1F3knlTm+ohwXx8="
},
"clientId": "12345"
}
```
### `payout.cancel`
```json [JSON]
{
"messageId": "b34b2bd9-xxxx-xxxx-xxxx-744643027cc7",
"webhookId": "859077ee-xxxx-xxxx-xxxx-66de5bf7c8ba",
"webhook": {
"webhook": "payout.cancel",
"object": "payout",
"object_id": "99975645",
"object_payload": {
"payouts": [
{
"payoutId": "123456",
"payoutTag": "",
"payoutStatus": "CANCELED",
"payoutTypeId": "1",
"payoutType": "Credit Transfer",
"walletId": "987654",
"bankaccountId": "0",
"beneficiaryId": "456789",
"endToEndId": null,
"uniqueMandateReference": null,
"label": "",
"payoutDate": "0000-00-00",
"amount": "1000.00",
"currency": "EUR",
"partnerFee": "0",
"createdDate": "2024-11-01 23:54:30",
"modifiedDate": "2024-11-01 23:58:03",
"walletEventName": "Wallet",
"walletAlias": "wallet-66cd835xxe4be",
"userLastname": "",
"userFirstname": "",
"userId": "87652436",
"bankaccountIBAN": null,
"virtualIbanId": null,
"virtualIbanReference": null,
"codeStatus": "160006",
"informationStatus": "Annulé par le User",
"supportingFileLink": "",
"reasonCode": "",
"reasonDescription": "",
"totalRows": 1
}
]
},
"webhook_created_at": 17305018831485,
"webhook_id": "859077ee-xxxx-xxxx-xxxx-66de5bf7c8ba",
"object_payload_signature": "fmxqIvroNav1gly0SWomkKxxxDRWQ8y+WVke30EOzA="
},
"clientId": "12345"
}
```
### `transaction.create`
```json [JSON]
{
"messageId": "3aab4601-xxxx-xxxx-xxxx-199f0d1379e0",
"webhookId": "aace45a4-xxxx-xxxx-xxxx-6c00c3213e2d",
"webhook": {
"webhook": "transaction.create",
"object": "transaction",
"object_id": "858804036",
"object_payload": {
"transactions": [
{
"transactionId": "12345",
"walletDebitId": "654321",
"walletCreditId": "9",
"transactionType": "Payout",
"foreignId": "098765",
"name": "name",
"description": "Virement 19673327",
"valueDate": "2024-11-01",
"executionDate": "2024-11-01",
"amount": "10.69",
"walletDebitBalance": "0.00",
"walletCreditBalance": "0.00",
"currency": "EUR",
"createdDate": "2024-11-01 12:29:31"
}
]
},
"webhook_created_at": 17304605712375,
"webhook_id": "aace45a4-xxxx-xxxx-xxxx-6c00c3213e2d",
"object_payload_signature": "IV15tQ5GG6FyMRF5tgNbt0Lsssss0eV+1YCu+u3TZv08="
},
"clientId": "12345"
}
```
### `payoutRefund.create`
```json [JSON]
{
"messageId": "6913bf25-xxxx-xxxx-xxxx-e0505cd8d363",
"webhookId": "b212c94d-xxxx-xxxx-xxxx-4c503f28c9ca",
"webhook": {
"webhook": "payoutRefund.create",
"object_payload": {
"payoutRefunds": [
{
"id": "12345",
"codeStatus": 790001,
"informationStatus": "PENDING",
"payoutId": "987654",
"payoutRefundTag": "",
"requestAmount": "43.20",
"requestCurrency": "EUR",
"requestComment": "",
"reasonCode": "AC01",
"refundAmount": "",
"refundCurrency": "",
"refundDate": "",
"refundComment": "",
"createdDate": "2024-10-01 10:30:23",
"modifiedDate": "",
"negativeResponseReasonCode": ""
}
]
},
"object_id": "9876",
"object": "payoutRefund",
"webhook_created_at": 17277669265064,
"webhook_id": "b212c94d-xxxx-xxxx-xxxx-4c503f28c9ca",
"object_payload_signature": "XCKBNNMlLK/UY+XMd39xxxEQpTZ7UKwQHXo5E5Sz1ks="
},
"clientId": "12345"
}
```
### `payoutRefund.update`
```json [JSON]
{
"messageId": "02e2fd0c-xxxx-xxxx-xxxx-a2792b5c87de",
"webhookId": "31f0e3bf-xxxx-xxxx-xxxx-ea7324c67545",
"webhook": {
"webhook": "payoutRefund.update",
"object_payload": {
"payoutRefunds": [
{
"id": "12345",
"codeStatus": 790003,
"informationStatus": "VALIDATED",
"payoutId": "987664",
"payoutRefundTag": "",
"requestAmount": "43.20",
"requestCurrency": "EUR",
"requestComment": "",
"reasonCode": "AC01",
"refundAmount": "43.20",
"refundCurrency": "EUR",
"refundDate": "2024-10-01",
"refundComment": "",
"createdDate": "2024-10-01 10:30:23",
"modifiedDate": "2024-10-01 10:30:23",
"negativeResponseReasonCode": ""
}
]
},
"object_id": "7654",
"object": "payoutRefund",
"webhook_created_at": 17277669265803,
"webhook_id": "31f0e3bf-xxxx-xxxx-xxxx-ea7324c67545",
"object_payload_signature": "kw90uW6/raDwMRrBIwiD9F7qY9xxx8O8eiLgZsqLQxQ="
},
"clientId": "12345"
}
```
### `payoutRefund.cancel`
```json [JSON]
{
"messageId": "a5f6f11e-xxxx-xxxx-xxxx-aea9ca60e864",
"webhookId": "7337ec42-xxxx-xxxx-xxxx-731227c91cd6",
"webhook": {
"webhook": "payoutRefund.cancel",
"object_payload": {
"payoutRefunds": [
{
"id": "12345",
"codeStatus": 790002,
"informationStatus": "CANCELED",
"payoutId": "987654",
"payoutRefundTag": "",
"requestAmount": "20.00",
"requestCurrency": "EUR",
"requestComment": "",
"reasonCode": "FRAD",
"refundAmount": "0.00",
"refundCurrency": "EUR",
"refundDate": "2024-11-20 09:15:29",
"refundComment": "LEGL - ATR053/RECALLSCT-1111111",
"createdDate": "2024-10-28 16:36:59",
"modifiedDate": "2024-11-20 09:15:29",
"negativeResponseReasonCode": "LEGL"
}
]
},
"object_id": "68833",
"object": "payoutRefund",
"webhook_created_at": 17320905292189,
"webhook_id": "7337ec42-xxxx-xxxx-xxxx-731227c91cd6",
"object_payload_signature": "Uo9ogL6r5CSiLTy5iUsm0xxx5DqY0JSLZoo6oqj1BA="
},
"clientId": "12345"
}
```
## SCTE Inst. webhooks
Find below the series of webhooks you may receive during the processing of an emitted instant SEPA Credit Transfer.
### `payout.create`
```json [JSON]
{
"messageId": "b4d2f1a8-7c39-5bd6-9e84-af0521d8c6e2",
"webhookId": "fc28eba5-3a67-489d-b1f5-7c9a4e2d8f3b",
"webhook": {
"webhook": "payout.create",
"object_payload": {
"payouts": [
{
"payoutId": "23bcd9f1-8e5a-4d7c-96b3-45f2a1c8d7e9",
"payoutTag": "",
"payoutStatus": "PENDING",
"payoutTypeId": "3",
"payoutType": "Instant Credit Transfer",
"walletId": "3600677",
"payoutDate": "2024-11-21 10:37:01",
"walletEventName": "Event_test",
"walletAlias": "event-test-673efef123318",
"userLastname": "Oak",
"userFirstname": "Alex",
"userId": "101121231",
"bankaccountId": "",
"beneficiaryId": "12345",
"uniqueMandateReference": "",
"bankaccountIBAN": "FR7616798000010000360055555",
"label": "",
"amount": "20.00",
"currency": "EUR",
"partnerFee": "0",
"createdDate": "2024-11-21 10:37:01",
"modifiedDate": "",
"virtualIbanId": null,
"virtualIbanReference": null,
"codeStatus": "160001",
"informationStatus": "PENDING",
"supportingFileLink": "",
"endToEndId": "23bcd9f18e5a4d7c96b345f2123457e9",
"reasonCode": "",
"reasonDescription": "",
"metadata": null,
"totalRows": 0
}
]
},
"object_id": "23bcd9f1-8e5a-4d7c-96b3-45f2a1c8d7e9",
"object": "payout",
"webhook_created_at": 17321818239625,
"webhook_id": "fc28eba5-3a67-489d-b1f5-7c9a4e2d8f3b",
"object_payload_signature": "7KuqFc+ZTYxZz7BufoYkN1nrG3kP/qGoekmFaV/1dFE="
},
"clientId": "12345"
}
```
### `payout.update`
```json [JSON]
{
"messageId": "a1b2c3d4-e5f6-50g7-8h9i-j0k1l2m3n4o5",
"webhookId": "b2c3d4e5-f6g7-4h8i-9j0k-l1m2n3o4p5q6",
"webhook": {
"webhook": "payout.update",
"object_payload": {
"payouts": [
{
"payoutId": "c3d4e5f6-g7h8-4i9j-0k1l-m2n3o4p5q6r7",
"payoutTag": "",
"payoutStatus": "VALIDATED",
"payoutTypeId": "3",
"payoutType": "Instant Credit Transfer",
"walletId": "7654321",
"payoutDate": "2024-11-21 10:37:01",
"walletEventName": "Event_test",
"walletAlias": "event-test-123abcdef4567",
"userLastname": "Oak",
"userFirstname": "Alex",
"userId": "987654321",
"bankaccountId": "",
"beneficiaryId": "246810",
"uniqueMandateReference": "",
"bankaccountIBAN": "FR7612345678901234567890123",
"label": "",
"amount": "20.00",
"currency": "EUR",
"partnerFee": "0",
"createdDate": "2024-11-21 10:37:01",
"modifiedDate": "2024-11-21 10:37:05",
"virtualIbanId": null,
"virtualIbanReference": null,
"codeStatus": "160004",
"informationStatus": "VALIDATED",
"supportingFileLink": "",
"endToEndId": "d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9",
"reasonCode": "",
"reasonDescription": "",
"metadata": null,
"totalRows": 0
}
]
},
"object_id": "e5f6g7h8-i9j0-4k1l-m2n3-o4p5q6r7s8t9",
"object": "payout",
"webhook_created_at": 17321818259045,
"webhook_id": "f6g7h8i9-j0k1-4l2m-n3o4-p5q6r7s8t9u0",
"object_payload_signature": "9ezRxcdRKT3KwqfJNDNBXHoeUacVWbaHa8VWwPABM7k="
},
"clientId": "123456"
}
```
### `transaction.create`
```json [JSON]
{
"messageId": "a1b2c3d4-e5f6-5g7h-8i9j-k0l1m2n3o4p5",
"webhookId": "b2c3d4e5-f6g7-4h8i-9j0k-l1m2n3o4p5q6",
"webhook": {
"webhook": "transaction.create",
"object_payload": {
"transactions": [
{
"transactionId": "7891234",
"walletDebitId": "4500789",
"walletCreditId": "9",
"transactionType": "payout SCTE instant",
"foreignId": "8765",
"name": "c3d4e5f6-g7h8-4i9j-0k1l-m2n3o4p5q6r7",
"description": "ip c3d4e5f6-g7h8-4i9j-0k1l-m2n3o4p5q6r7",
"valueDate": "2024-11-21",
"executionDate": "2024-11-21",
"amount": "20.00",
"walletDebitBalance": "181.25",
"walletCreditBalance": "0.00",
"currency": "EUR",
"createdDate": "2024-11-21 10:37:05"
}
]
},
"object_id": "7891234",
"object": "transaction",
"webhook_created_at": 17321818258386,
"webhook_id": "d4e5f6g7-h8i9-4j0k-l1m2-n3o4p5q6r7s8",
"object_payload_signature": "R7bXmPq9Yz2AxCvNwDfEhGjKlMnOpQrStUvWxYz1234="
},
"clientId": "12345"
}
```
### `payoutRefund.create`
```json [JSON]
{
"messageId": "a1b2c3d4-e5f6-5g7h-8i9j-k0l1m2n3o4p5",
"webhookId": "b2c3d4e5-f6g7-4h8i-9j0k-l1m2n3o4p5q6",
"webhook": {
"webhook": "payoutRefund.create",
"object_payload": {
"payoutRefunds": [
{
"id": "c3d4e5f6-g7h8-4i9j-0k1l-m2n3o4p5q6r7",
"codeStatus": 790001,
"informationStatus": "PENDING",
"payoutId": "d4e5f6g7-h8i9-4j0k-l1m2-n3o4p5q6r7s8",
"payoutRefundTag": "test",
"requestAmount": "20.00",
"requestCurrency": "EUR",
"requestComment": "",
"reasonCode": "DUPL",
"refundAmount": "20.00",
"refundCurrency": "EUR",
"refundDate": "",
"refundComment": "",
"createdDate": "2024-11-21 10:44:21",
"modifiedDate": "",
"negativeResponseReasonCode": ""
}
]
},
"object_id": "e5f6g7h8-i9j0-4k1l-m2n3-o4p5q6r7s8t9",
"object": "payoutRefund",
"webhook_created_at": 17321822620807,
"webhook_id": "f6g7h8i9-j0k1-4l2m-n3o4-p5q6r7s8t9u0",
"object_payload_signature": "aBcDeFgHiJkLmNoPqRsTuVwXyZ1234567890AbCdEf="
},
"clientId": "123456"
}
```
### `payoutRefund.update`
```json [JSON]
{
"messageId": "a1b2c3d4-e5f6-5g7h-8i9j-k0l1m2n3o4p5",
"webhookId": "b2c3d4e5-f6g7-4h8i-9j0k-l1m2n3o4p5q6",
"webhook": {
"webhook": "payoutRefund.update",
"object_payload": {
"payoutRefunds": [
{
"id": "c3d4e5f6-g7h8-4i9j-0k1l-m2n3o4p5q6r7",
"codeStatus": 790003,
"informationStatus": "VALIDATED",
"payoutId": "d4e5f6g7-h8i9-4j0k-l1m2-n3o4p5q6r7s8",
"payoutRefundTag": "test",
"requestAmount": "20.00",
"requestCurrency": "EUR",
"requestComment": "",
"reasonCode": "DUPL",
"refundAmount": "20.00",
"refundCurrency": "EUR",
"refundDate": "",
"refundComment": "",
"createdDate": "2024-11-21 10:44:21",
"modifiedDate": "",
"negativeResponseReasonCode": ""
}
]
},
"object_id": "e5f6g7h8-i9j0-4k1l-m2n3-o4p5q6r7s8t9",
"object": "payoutRefund",
"webhook_created_at": 17321822644721,
"webhook_id": "f6g7h8i9-j0k1-4l2m-n3o4-p5q6r7s8t9u0",
"object_payload_signature": "aBcDeFgHiJkLmNoPqRsTuVwXyZ1234567890AbCdEf="
},
"clientId": "123456"
}
```
### `payoutRefund.cancel`
```json [JSON]
{
"messageId": "a7b3c9d1-e2f4-5g6h-8i9j-k0l1m2n3o4p5",
"webhookId": "b8c9d0e1-f2g3-4h5i-6j7k-l8m9n0p1q2r3",
"webhook": {
"webhook": "payoutRefund.cancel",
"object_payload": {
"payoutRefunds": [
{
"id": "c1d2e3f4-g5h6-7i8j-9k0l-m1n2o3p4q5r6",
"codeStatus": 790002,
"informationStatus": "CANCELED",
"payoutId": "d2e3f4g5-h6i7-8j9k-0l1m-n2o3p4q5r6s7",
"payoutRefundTag": "",
"requestAmount": "10.00",
"requestCurrency": "EUR",
"requestComment": "",
"reasonCode": "TECH",
"refundAmount": "10.00",
"refundCurrency": "EUR",
"refundDate": "",
"refundComment": "",
"createdDate": "2024-10-21 19:02:12",
"modifiedDate": "",
"negativeResponseReasonCode": "AC06"
}
]
},
"object_id": "e3f4g5h6-i7j8-9k0l-1m2n-o3p4q5r6s7t8",
"object": "payoutRefund",
"webhook_created_at": 17295301355064,
"webhook_id": "f4g5h6i7-j8k9-0l1m-2n3o-p4q5r6s7t8u9",
"object_payload_signature": "G7YQwz3Xn1mF9bV5cR8tL6pK2jH4dS0aE6uI7yO3fA8="
},
"clientId": "12345"
}
```
## SCTR webhooks
Find below the series of webhooks you may receive during the processing of a received SEPA Credit Transfer.
### `payin.create`
```json [JSON]
{
"messageId": "02e3c6b4-xxxx-xxxx-xxxx-99025662153a",
"webhookId": "3ae934ad-xxxx-xxxx-xxxx-c26e1a545415",
"webhook": {
"webhook": "payin.create",
"object_payload": {
"payins": [
{
"payinId": "123456",
"payinTag": "",
"walletId": "11530716",
"userId": "8103200",
"paymentMethodId": "20",
"messageToUser": "",
"subtotalItems": "13.00",
"subtotalServices": "0.00",
"subtotalTax": "0.00",
"amount": "13.00",
"currency": "EUR",
"createdDate": "2024-11-19 10:01:13",
"walletEventName": "Main wallet",
"walletAlias": "main-wallet-63b33xxee1061",
"userFirstname": "Alex",
"userLastname": "Oak",
"payinStatus": "PENDING",
"codeStatus": "140001",
"informationStatus": "",
"refundAmount": null,
"ibanFullname": "Tree Cie",
"DbtrIBAN": "FR52219440000XXXXXX",
"ibanBic": "MPAYFRP1XXX",
"ibanTxEndToEndId": "8d03d882fc744ae69420cxcvb1f7f94d",
"ibanTxId": "2432360481234511",
"forwardUrl": null,
"paymentAcceptedUrl": null,
"paymentRefusedUrl": null,
"paymentWaitingUrl": null,
"paymentExceptionUrl": null,
"paymentCanceledUrl": null,
"payinDate": "0000-00-00",
"mandateId": "0",
"creditorName": "Alex Oak",
"creditorAddressLine": "116 Willow road",
"creditorCountry": "FR",
"creditorIban": "FR7616798000010002222271616",
"creditorBIC": "TRZOFR21XXX",
"virtualIbanId": null,
"virtualIbanReference": null,
"additionalData": "",
"ibanId": "be667e072f2b7112490560c0e1236544e51d93db",
"totalRows": 1,
"paymentHtml": null
}
]
},
"object_id": "31964985",
"object": "payin",
"webhook_created_at": 17320068736433,
"webhook_id": "3ae934ad-xxxx-xxxx-xxxx-c26e1a545415",
"object_payload_signature": "yRo0000000000000000000000000000000000"
},
"clientId": "12345"
}
```
### `payin.update`
```json [JSON]
{
"messageId": "25df01f7-xxxx-xxxx-xxxx-5e4f4af4216c",
"webhookId": "39e99ce0-xxxx-xxxx-xxxx-29a43039bb84",
"webhook": {
"webhook": "payin.update",
"object_payload": {
"payins": [
{
"payinId": "123456",
"payinTag": "",
"walletId": "321654",
"userId": "987456",
"paymentMethodId": "20",
"messageToUser": "",
"subtotalItems": "36.72",
"subtotalServices": "0.00",
"subtotalTax": "0.00",
"amount": "36.72",
"currency": "EUR",
"createdDate": "2024-11-21 09:20:55",
"walletEventName": "Main Wallet",
"walletAlias": "main-wallet-64123ffd0a7e7",
"userFirstname": "Alex ",
"userLastname": "Oak",
"payinStatus": "VALIDATED",
"codeStatus": "140005",
"informationStatus": "",
"refundAmount": null,
"ibanFullname": "ALEX OAK",
"DbtrIBAN": "ES96123456123456686249",
"ibanBic": "CAIXESBBXXX",
"ibanTxEndToEndId": "NOTPROVIDED",
"ibanTxId": "A2141TI999999999",
"forwardUrl": null,
"paymentAcceptedUrl": null,
"paymentRefusedUrl": null,
"paymentWaitingUrl": null,
"paymentExceptionUrl": null,
"paymentCanceledUrl": null,
"payinDate": "0000-00-00",
"mandateId": "0",
"creditorName": "ALEX OAK",
"creditorAddressLine": "3 CALLE DES LOS ARBOLES",
"creditorCountry": "ES",
"creditorIban": "FR761679800001000123655555",
"creditorBIC": "TRZOFR21XXX",
"virtualIbanId": null,
"virtualIbanReference": null,
"additionalData": "",
"ibanId": "b47dc58116105724f666d70c7777777b5b3dc510",
"totalRows": 1,
"paymentHtml": null
}
]
},
"object_id": "31989128",
"object": "payin",
"webhook_created_at": 17321772560387,
"webhook_id": "39e99ce0-xxxx-xxxx-xxxx-29a43039bb84",
"object_payload_signature": "yRo0000000000000000000000000000000000"
},
"clientId": "12345"
}
```
### `payin.cancel`
```json [JSON]
{
"webhook": "payin.cancel",
"object": "payin",
"object_id": "12345",
"object_payload": {
"payins": [
{
"payinId": "12345",
"payinTag": "",
"walletId": "8766543",
"userId": "09876123",
"payinStatus": "CANCELED",
"paymentMethodId": "20",
"messageToUser": "",
"subtotalItems": "0.00",
"subtotalServices": "0.00",
"subtotalTax": "0.00",
"amount": "101.25",
"currency": "EUR",
"createdDate": "2025-03-06 09:48:46",
"walletEventName": "Main account",
"walletAlias": "main-account-67c9616de90b8",
"userFirstname": "Alex",
"userLastname": "Oak",
"codeStatus": "140004",
"informationStatus": "",
"refundAmount": null,
"ibanFullname": null,
"DbtrIBAN": null,
"ibanBic": null,
"ibanTxEndToEndId": null,
"ibanTxId": null,
"forwardUrl": null,
"paymentAcceptedUrl": null,
"paymentRefusedUrl": null,
"paymentWaitingUrl": null,
"paymentExceptionUrl": null,
"paymentCanceledUrl": null,
"payinDate": "0000-00-00",
"mandateId": "0",
"creditorName": null,
"creditorAddressLine": null,
"creditorCountry": null,
"creditorIban": null,
"creditorBIC": null,
"virtualIbanId": null,
"virtualIbanReference": null,
"additionalData": "",
"ibanId": "8e5522e9ccd084d54ef7b897af495xxx333ca617c",
"totalRows": 1
}
]
},
"webhook_created_at": 17412509271748,
"webhook_id": "47186faa-xxxx-xxxx-xxxx-fb7a1d5e62a1",
"object_payload_signature": "y+ZUmlX2OxPBVf2lkuQgjDnxo/LVIpZNgMx1zG0sPlQ="
}
```
### `transaction.create`
```json [JSON]
{
"messageId": "b3b8b5d1-xxxx-xxxx-xxxx-ea6759eb35ff",
"webhookId": "095a10c0-xxxx-xxxx-xxxx-a1e224e5065e",
"webhook": {
"webhook": "transaction.create",
"object_payload": {
"transactions": [
{
"transactionId": "123456789",
"walletDebitId": "9",
"walletCreditId": "654123",
"transactionType": "Payin",
"foreignId": "987456321",
"name": "5555555",
"description": "sctr id 55555",
"valueDate": "2024-11-19",
"executionDate": "2024-11-19",
"amount": "13.00",
"walletDebitBalance": "0.00",
"walletCreditBalance": "16.84",
"currency": "EUR",
"createdDate": "2024-11-19 10:01:13"
}
]
},
"object_id": "869988392",
"object": "transaction",
"webhook_created_at": 17320068737656,
"webhook_id": "095a10c0-xxxx-xxxx-xxxx-a1e224e5065e",
"object_payload_signature": "yRo0000000000000000000000000000000000"
},
"clientId": "12345"
}
```
### `sepa.return_sctr `
```json [JSON]
{
"webhook": "sepa.return_sctr",
"webhook_id": "4XXXXX",
"object": "sepaSctr",
"object_id": "5XXXXX",
"object_payload": {
"sepaSctrs": [
{
"wallet_id": "2XXXX",
"virtual_iban_id": null,
"transaction_id": "010XXXXX",
"interbank_settlement_amount": "48.10",
"debitor_name": "SXXXXX",
"debitor_address": "XXXXXXXXX ",
"debitor_country": null,
"creditor_name": "XXXX XXXX",
"creditor_address": "XXXXXXXX ",
"creditor_country": null,
"unstructured_field": "XXXXXXX",
"return_reason_code": "AC04"
}
]
},
"object_payload_signature": "yRo0000000000000000000000000000000000"
}
```
### `recallR.need_response`
```json [JSON]
{
"webhook": "recallR.need_response",
"webhook_id": "15000700",
"object": "recallR",
"object_id": "9",
"object_payload": {
"recallrs": [
{
"id": 9,
"cxl_id": "987",
"status_id": 3,
"status_label": "PENDING ANSWER REQUESTED",
"reason_code": "TECH", // see available reasons in the Recall article
"additional_information": null,
"user_id": 1321404,
"user_name": "XXXX",
"user_status_id": 9,
"wallet_id": 714744, // related wallet id
"wallet_status_id": 5,
"wallet_activation_date": "2020-10-30 00:00:00",
"wallet_desactivation_date": null,
"sctr_id": 397, // related SCTR id
"sctr_tx_id": "pPgx9rB0RJFkJt5A",
"sctr_amount": "3011.00", // related SCTR amount
"sctr_currency": "EUR",
"sctr_settelment_date": "2020-11-30 00:00:00",
"sctr_dbtr_name": "Test name debitor",
"received_date": null,
"payinrefund_id": 3521 // related Payin created to block the Authorized Balance
}
]
}
}
```
### `payinrefund.create`
```json [JSON]
{
"messageId": "4e3c1b82-xxxx-xxxx-xxxx-4435158fce0e",
"webhookId": "a94927ca-xxxx-xxxx-xxxx-db6470df39c9",
"webhook": {
"webhook": "payinrefund.create",
"object": "payinrefund",
"object_id": "49338",
"object_payload": {
"payinrefunds": [
{
"payinrefundId": "123456",
"payinrefundTag": null,
"payinrefundStatus": "PENDING",
"walletId": "321654",
"payinId": "897456",
"payinrefundDate": "0000-00-00",
"amount": "375.00",
"currency": "EUR",
"createdDate": "2024-11-20 13:20:40",
"modifiedDate": "0000-00-00 00:00:00",
"codeStatus": "170001",
"informationStatus": "",
"reasonTms": null,
"totalRows": 1
}
]
},
"webhook_created_at": 17321052400640,
"webhook_id": "a94927ca-xxxx-xxxx-xxxx-db6470df39c9",
"object_payload_signature": "yRo0000000000000000000000000000000000"
},
"clientId": "12345"
}
```
### `payinrefund.update`
```json [JSON]
{
"messageId": "a352c3dd-xxxx-xxxx-xxxx-9c6afd8e1e93",
"webhookId": "fee81a6d-xxxx-xxxx-xxxx-30164466efcd",
"webhook": {
"webhook": "payinrefund.update",
"object": "payinrefund",
"object_id": "49334",
"object_payload": {
"payinrefunds": [
{
"payinrefundId": "654789",
"payinrefundTag": null,
"payinrefundStatus": "VALIDATED", // or ACCEPTED
"walletId": "123456",
"payinId": "987456",
"payinrefundDate": "0000-00-00",
"amount": "4998.00",
"currency": "EUR",
"createdDate": "2024-11-19 16:20:40",
"modifiedDate": "2024-11-20 05:15:21",
"codeStatus": "170005",
"informationStatus": "",
"reasonTms": null,
"totalRows": 1
}
]
},
"webhook_created_at": 17320797217512,
"webhook_id": "fee81a6d-xxxx-xxxx-xxxx-30164466efcd",
"object_payload_signature": "yRo0000000000000000000000000000000000"
},
"clientId": "12345"
}
```
### `payinrefund.cancel`
```json [JSON]
{
"messageId": "ca8cc285-xxxx-xxxx-xxxx-9d306c98f20c",
"webhookId": "a55090df-xxxx-xxxx-xxxx-ceb1f1db34dc",
"webhook": {
"webhook": "payinrefund.cancel",
"object": "payinrefund",
"object_id": "49261",
"object_payload": {
"payinrefunds": [
{
"payinrefundId": "1234556",
"payinrefundTag": null,
"payinrefundStatus": "CANCELED",
"walletId": "654321",
"payinId": "987654",
"payinrefundDate": "0000-00-00",
"amount": "2900.00",
"currency": "EUR",
"createdDate": "2024-11-18 11:22:09",
"modifiedDate": "2024-11-18 17:11:26",
"codeStatus": "170003",
"informationStatus": "",
"reasonTms": null,
"totalRows": 1
}
]
},
"webhook_created_at": 17319462865000,
"webhook_id": "a55090df-xxxx-xxxx-xxxx-ceb1f1db34dc",
"object_payload_signature": "yRo0000000000000000000000000000000000"
},
"clientId": "12345"
}
```
## SCTR Inst. webhooks
Find below the series of webhooks you may receive during the processing of a received instant SEPA Credit Transfer.
### `payin.create`
```json [JSON]
{
"messageId": "a7b8c9d0-e1f2-53g4-h5i6-j7k8l9m0n1o2",
"webhookId": "b8c9d0e1-f2g3-4h5i-6j7k-l8m9n0p1q2r3",
"webhook": {
"webhook": "payin.create",
"object_payload": {
"payins": [
{
"payinId": "c9d0e1f2-g3h4-556i-j7k8-l9m0n1o2p3q4",
"payinTag": "DEUTDEFF24112100009683400000001|DEUTDEFF211124108223410000001",
"walletId": "15678901",
"userId": "3",
"payinStatus": "VALIDATED",
"paymentMethodId": "27",
"messageToUser": "BLG-PRDLE12PYFZZ",
"subtotalItems": "",
"subtotalServices": "",
"subtotalTax": "",
"amount": "50.00",
"currency": "EUR",
"createdDate": "2024-11-21 09:59:18",
"walletEventName": "MAIN",
"walletAlias": "main-670c0f8f3b968",
"userFirstname": "Alex",
"userLastname": "Oak",
"codeStatus": "140005",
"informationStatus": "",
"refundAmount": "",
"ibanFullname": "ALEX OAK",
"DbtrIBAN": "DE39350400380605802800",
"ibanBic": "DEUTDEFFXXX",
"ibanTxEndToEndId": "d1e2f3g4h5i6j7k8l9m0n1o2p3q4r5s6",
"ibanTxId": "DEUTDEFF211124108223410000001",
"forwardUrl": "",
"paymentAcceptedUrl": "",
"paymentRefusedUrl": "",
"paymentWaitingUrl": "",
"paymentExceptionUrl": "",
"paymentCanceledUrl": "",
"payinDate": "",
"mandateId": "0",
"creditorName": "ALEX OAK",
"creditorAddressLine": "",
"creditorCountry": "",
"creditorIban": "FR7616798000010001567890167",
"creditorBIC": "TRZOFR21XXX",
"virtualIbanId": "",
"virtualIbanReference": "",
"additionalData": "",
"ibanId": "e1f2g3h4i5j6k7l8m9n0o1p2q3r4s5t6u7v8w9x0"
}
]
},
"object_id": "c9d0e1f2-g3h4-556i-j7k8-l9m0n1o2p3q4",
"object": "payin",
"webhook_created_at": 17321795586841,
"webhook_id": "b8c9d0e1-f2g3-4h5i-6j7k-l8m9n0p1q2r3",
"object_payload_signature": "GjGCKYuskU/RqEHjohfK/CXa9GIzz6zbOduaf3fIJeI="
},
"clientId": "373826"
}
```
### `transaction.create`
```json [JSON]
{
"messageId": "a7b8c9d0-e1f2-53g4-h5i6-j7k8l9m0n1o2",
"webhookId": "b8c9d0e1-f2g3-4h5i-6j7k-l8m9n0p1q2r3",
"webhook": {
"webhook": "transaction.create",
"object_payload": {
"transactions": [
{
"transactionId": "871387155",
"walletDebitId": "9",
"walletCreditId": "16423670",
"transactionType": "Payin",
"foreignId": "7156118",
"name": "c9d0e1f2-g3h4-5i6j-k7l8-m9n0p1q2r3s4",
"description": "Payment SCTr inst c9d0e1f2-g3h4-5i6j-k7l8-m9n0p1q2r3s4",
"valueDate": "2024-11-21",
"executionDate": "2024-11-21",
"amount": "50.00",
"walletDebitBalance": "0.00",
"walletCreditBalance": "50.00",
"currency": "EUR",
"createdDate": "2024-11-21 09:59:18"
}
]
},
"object_id": "871387155",
"object": "transaction",
"webhook_created_at": 17321795585276,
"webhook_id": "d0e1f2g3-h4i5-6j7k-8l9m-n0p1q2r3s4t5",
"object_payload_signature": "AbCdEfGhIjKlMnOpQrStUvWxYz1234567890aBcDeF="
},
"clientId": "12345"
}
```
### `sepaSctrInst.reject_sctr_inst`
```json [JSON]
{
"webhook": "sepaSctrInst.reject_sctr_inst",
"webhook_id": "15000700",
"object": "sepaSctrInst",
"object_id": "f51d656c-1919-57ae-8416-760165f4c2c6",
"object_payload" :
{
"sepaSctrInsts" :
[
{
"walletId": "379601",
"messageId": "aad9cfef-575e-11ec-b2f5-9a8693508ae7",
"transactionEndToEndId": "032021153210009999999999",
"transactionId": "04322NA202169999999999",
"settlementAmount": 3225.55,
"settlementDate": "2021-06-02",
"debtorIban": "FR7630003043220008888888888",
"debtorBic": "SOGEFRPP",
"debitorName": "DEBTOR NAME",
"debitorAddressLine": "DEBTOR ADDRESS",
"debitorCountry": "",
"creditorIban": "FR7616798000010009999999999",
"creditorBIC": "TRZOFR21",
"creditorName": "REDACTED",
"creditorAddressLine": null,
"creditorCountry": null,
"remittanceInformation": "",
"return_reason_code": "AC04",
"virtualIbanId": null,
"virtualIbanReference": null,
}
]
}
}
```
### `separecallsctrinst.reception`
```json [JSON]
{
"webhook": "separecallsctrinst.reception",
"object_payload": {
"recallId": "dea754f8-f8bd-4b80-a3f6-42f72d1234681", // Unique identifier (UUID)
"creationDateTime": "2024-07-24T08:48:35.426Z", // Date and time of recall request by the originator
"statusLabel": "PENDING", // Status of the recall request.
"cxlId": "BIPT242060212345772", // Unique and unambiguous identifier of a cancellation request, defined by the assigner
"reasonCode": "FRAD", // Can be: FRAD, TECH, DUPL, AM09, CUST, AC03
"additionalInformation": "",
"sctrDbtrIBAN": "FR7613485008000416151234543", // IBAN of the debtor
"sctrDbtrBIC": "CEPAFRXXXX", // BIC of the debtor
"sctrDbtrName": "ALEX OAK", // Name of the debtor
"sctrDbtrAddress": "15 Rosewood road", // Postal address of the debtor
"sctrDbtrCountry": "FR",
"sctrCdtrIBAN": "FR7616798000010001571234573", // IBAN of the creditor
"sctrCdtrBIC": "TRZOFR21XXX", // BIC of the creditor
"sctrCdtrName": "CHRIS PINE", // Name of the creditor
"sctrCdtrAddress": "23 Willow lane", // Postal address of the debtor
"sctrCdtrCountry": "",
"sctrMsgId": "1720396248916-7-1481234", // MsgId of the original transaction
"sctrInstrId": "2000000028fe81000712345404d5347", // Instruction Id of the original transaction
"sctrTxId": "BIPT241900200XXXXX6", // Transaction Id of the original transaction
"sctrE2EID": "Bankwire of A OAK", // End To end id of the original transaction
"sctrAmount": "500.00", // Amount of the original transaction
"sctrSettlementDate": "2024-07-08T00:00:00Z", // Settlement date of the original transaction
"sctrRemittanceInformation": "", // Remittance information of the original transaction
"sctrTrzId": "80adc46a-3367-5c35-b53c-ef7b852345e6", // Unique identifier of the original transaction
"sctrExternalId": "SG24190IP0ZDFP7324190IP0ZDF345000", // ttis payment id of the original transaction
"clientId": 12345,
"userId": 1234567,
"walletId": 123456789, // Wallet that received the of the original transaction
"receivedDate": "2024-07-24T08:48:36Z", // Date and time of the recall request reception
"payinRefundId": 0,
"responseType": -1, // Response to the recall request. Can be: 1 (positive) or 0 (negative)
"negativeResponseReasonCode": "", // Reason code of the response to the pending recall request received. Can be: AC04, AM04, ARDT, CUST, LEGL, NOAS, NOOR
"negativeResponseAdditionalInformation": "", // Available for reason code LEGL, FRAD and AC03
"responseComment": "", // To be used by your teams or Treezor's
"automaticResponse": "pendingRecall", // Yes or No. To flag when a response was given automatically
"createdDate": "2024-07-24T08:48:36Z", // Date and time at which the recall was created in Treezor database
"updatedDate": null
},
"object_id": "dea754f8-f8bd-4b80-a3f6-42f7xxxx2681",
"object": "separecallsctrinst",
"webhook_created_at": 17218109179396,
"webhook_id": "5adf9788-3521-43aa-a954-abxxxxeb84c2",
"object_payload_signature": "rKf2lk5vZ5bHmEx9Ix/wtrDosvpi8Gdxxxxay2hq4Ds="
}
```
### `payinrefund.create`
```json [JSON]
{
"messageId": "a7b8c9d0-e1f2-53g4-h5i6-j7k8l9m0n1o2",
"webhookId": "b8c9d0e1-f2g3-4h5i-6j7k-l8m9n0p1q2r3",
"webhook": {
"webhook": "payinrefund.create",
"object_payload": {
"payinrefunds": [
{
"payinrefundId": "c9d0e1f2-g3h4-5i6j-k7l8-m9n0p1q2r3s4",
"payinrefundTag": null,
"payinrefundStatus": "PENDING",
"walletId": "15678901",
"payinId": "d1e2f3g4-h5i6-7j8k-9l0m-n1o2p3q4r5s6",
"payinrefundDate": "2024-11-18 09:07:11",
"amount": "11000.00",
"currency": "EUR",
"createdDate": "2024-11-18 09:07:09",
"modifiedDate": "",
"codeStatus": "170001",
"informationStatus": "Demande de remboursement de participation",
"reasonTms": null
}
]
},
"object_id": "e3f4g5h6-i7j8-9k0l-1m2n-o3p4q5r6s7t8",
"object": "payinrefund",
"webhook_created_at": 17319208317442,
"webhook_id": "f5g6h7i8-j9k0-1l2m-3n4o-p5q6r7s8t9u0",
"object_payload_signature": "AbCdEfGhIjKlMnOpQrStUvWxYz1234567890aBcDeF="
},
"clientId": "12345"
}
```
### `payinrefund.update`
```json [JSON]
{
"messageId": "a7b8c9d0-e1f2-53g4-h5i6-j7k8l9m0n1o2",
"webhookId": "b8c9d0e1-f2g3-4h5i-6j7k-l8m9n0p1q2r3",
"webhook": {
"webhook": "payinrefund.update",
"webhook_created_at": 17316611944485,
"object_id": "c9d0e1f2-g3h4-5i6j-k7l8-m9n0p1q2r3s4",
"object": "payinrefund",
"object_payload": {
"payinrefunds": [
{
"payinrefundId": "c9d0e1f2-g3h4-5i6j-k7l8-m9n0p1q2r3s4",
"payinrefundTag": null,
"payinrefundStatus": "VALIDATED", // or ACCEPTED
"payinrefundDate": "2024-11-15 09:59:53",
"walletId": "16732256",
"payinId": "d1e2f3g4-h5i6-7j8k-9l0m-n1o2p3q4r5s6",
"amount": "10",
"currency": "EUR",
"createdDate": "2024-11-15 09:59:53",
"modifiedDate": "2024-11-15 09:59:53",
"profile": "00001344879",
"userId": "101923629",
"codeStatus": "150125",
"informationStatus": "Refunded",
"reasonTms": null
}
]
},
"webhook_id": "b8c9d0e1-f2g3-4h5i-6j7k-l8m9n0p1q2r3",
"object_payload_signature": "AbCdEfGhIjKlMnOpQrStUvWxYz1234567890aBcDeF="
},
"clientId": "12345"
}
```
### `payinrefund.cancel`
```json [JSON]
{
"messageId": "a7b8c9d0-e1f2-53g4-h5i6-j7k8l9m0n1o2",
"webhookId": "b8c9d0e1-f2g3-4h5i-6j7k-l8m9n0p1q2r3",
"webhook": {
"webhook": "payinrefund.cancel",
"object_payload": {
"payinrefunds": [
{
"payinrefundId": "c9d0e1f2-g3h4-5i6j-k7l8-m9n0p1q2r3s4",
"payinrefundTag": "",
"payinrefundStatus": "REJECTED",
"walletId": "15678901",
"payinId": "d1e2f3g4-h5i6-7j8k-9l0m-n1o2p3q4r5s6",
"payinrefundDate": "2024-09-23 11:23:37",
"amount": "128.45",
"currency": "EUR",
"createdDate": "2024-09-23 11:23:35",
"modifiedDate": "",
"codeStatus": "170004",
"informationStatus": "Annulé par un opérateur",
"reasonTms": ""
}
]
},
"object_id": "e3f4g5h6-i7j8-9k0l-1m2n-o3p4q5r6s7t8",
"object": "payinrefund",
"webhook_created_at": 17271728589428,
"webhook_id": "f5g6h7i8-j9k0-1l2m-3n4o-p5q6r7s8t9u0",
"object_payload_signature": "AbCdEfGhIjKlMnOpQrStUvWxYz1234567890aBcDeF="
},
"clientId": "12345"
}
```
## Received International Transfers webhooks
Find below the series of webhooks you may receive during the processing of a received International Transfer.
### `payin.create`
```json [JSON]
{
"messageId": "79ca17f6-3a7e-5402-8397-76cb1a4c7eaf",
"webhookId": "13008c8a-2cc5-452a-a787-ad641fd1e2bc",
"webhook": {
"webhook": "payin.create",
"object_payload": {
"payins": [
{
"DbtrIBAN": "FR7628233000019773294444444",
"additionalData": "{\"fees\":[{\"currency\":\"CAD\",\"type\":\"conversion\",\"value\":0.01},{\"currency\":\"CAD\"},{\"currency\":\"CAD\"}],\"exchange\":{\"instructed_currency\":\"CAD\",\"exchange_rate\":0.615915,\"instructed_value\":2}}",
"amount": "1.23",
"cartId": "",
"codeStatus": "",
"createdDate": "2025-09-11 21:07:21",
"creditorAddressLine": "15 Roselane 75008 Paris",
"creditorBIC": "1",
"creditorCountry": "FR",
"creditorIban": "FR7616798000010001661666666",
"creditorName": "",
"currency": "EUR",
"distributorFee": "",
"forwardUrl": "",
"ibanBic": "BIC-REVOFRP2XXX",
"ibanFullname": "ALEX OAK",
"ibanId": "",
"ibanTxEndToEndId": "aa002083-1705-00fg-11cf-04a5bb467afc",
"ibanTxId": "",
"mandateId": "",
"messageToUser": "",
"payinDate": "0000-00-00",
"payinId": "0049e4d5-7510-4765-974e-66fba3345a06",
"payinStatus": "PENDING",
"payinTag": "",
"paymentAcceptedUrl": "",
"paymentCanceledUrl": "",
"paymentExceptionUrl": "",
"paymentHtml": "",
"paymentLanguage": "",
"paymentMethodId": "28",
"paymentPostUrl": "",
"paymentRefusedUrl": "",
"paymentWaitingUrl": "",
"refundAmount": "",
"subtotalItems": "",
"subtotalServices": "",
"subtotalTax": "",
"userFirstname": "Chris",
"userId": "100368137",
"userLastname": "Willow",
"virtualIbanId": "",
"virtualIbanReference": "",
"walletAlias": "main-account-1-2-671fc6d79cc33",
"walletEventName": "main account",
"walletId": "16614938"
}
]
},
"object_id": "0049e4d5-7510-xxxx-xxxx-66fba1233a06",
"object": "payin",
"webhook_created_at": 17576176495755,
"webhook_id": "13008c8a-2cc5-xxxx-xxxx-ad641fd1e2bc",
"object_payload_signature": "KVrNE/V5zo/PR+cgAaJrwXVn12345vmmMkeMg6OhVhs="
},
"clientId": "12345"
}
```
### `payin.update`
```json [JSON]
{
"messageId": "51792e3c-f0b3-56b3-b78e-4f7f8fe50cfc",
"webhookId": "778952e1-ecff-4ff4-915e-62577e22f7eb",
"webhook": {
"webhook": "payin.update",
"object_payload": {
"payins": [
{
"DbtrIBAN": "FR7628233000019773294444444",
"additionalData": "{\"fees\":[{\"currency\":\"CAD\",\"type\":\"conversion\",\"value\":0.01},{\"currency\":\"CAD\"},{\"currency\":\"CAD\"}],\"exchange\":{\"instructed_currency\":\"CAD\",\"exchange_rate\":0.615915,\"instructed_value\":2}}",
"amount": "1.23",
"cartId": "",
"codeStatus": "",
"createdDate": "2025-09-11 21:07:21",
"creditorAddressLine": "15 ROSEWOOD LANE/PARIS 75017",
"creditorBIC": "1",
"creditorCountry": "FR",
"creditorIban": "FR7616798000010001661111111",
"creditorName": "",
"currency": "EUR",
"distributorFee": "",
"forwardUrl": "",
"ibanBic": "BIC-REVOFRP2XXX",
"ibanFullname": "ALEX OAK",
"ibanId": "",
"ibanTxEndToEndId": "aa002083-1705-xxxx-xxxx-04a5bb467afc",
"ibanTxId": "",
"mandateId": "",
"messageToUser": "",
"payinDate": "2025-09-11",
"payinId": "0049e4d5-7510-4765-974e-66fba1233a06",
"payinStatus": "VALIDATED",
"payinTag": "",
"paymentAcceptedUrl": "",
"paymentCanceledUrl": "",
"paymentExceptionUrl": "",
"paymentHtml": "",
"paymentLanguage": "",
"paymentMethodId": "28",
"paymentPostUrl": "",
"paymentRefusedUrl": "",
"paymentWaitingUrl": "",
"refundAmount": "",
"subtotalItems": "",
"subtotalServices": "",
"subtotalTax": "",
"userFirstname": "Chris",
"userId": "100368137",
"userLastname": "Oak",
"virtualIbanId": "",
"virtualIbanReference": "",
"walletAlias": "main_account-1-2-671fc6d79cc33",
"walletEventName": "main_account",
"walletId": "16614938"
}
]
},
"object_id": "0049e4d5-7510-xxxx-xxxx-66fba1233a06",
"object": "payin",
"webhook_created_at": 17580352210419,
"webhook_id": "778952e1-ecff-4ff4-915e-62577e22f7eb",
"object_payload_signature": "OJ1C5wdLMuYBc6Ci12345k7CSPRbyltA++hEcZGbSTg="
},
"clientId": "12345"
}
```
### `payin.cancel`
```json [JSON]
{
"messageId": "51224686-145f-5784-b892-27xx110c316",
"webhookId": "a0f0c310-780c-460f-be1e-333ccc22809c",
"webhook": {
"webhook": "payin.cancel",
"object_payload": {
"payins": [
{
"DbtrIBAN": "FR762823300001977XXXXXXXXXX",
"additionalData": "{\"fees\":[{\"currency\":\"CAD\",\"type\":\"conversion\",\"value\":0.01},{\"currency\":\"CAD\"}],\"exchange\":{\"instructed_currency\":\"CAD\",\"exchange_rate\":0.610455,\"instructed_value\":2}}",
"amount": "1.21",
"cartId": "",
"codeStatus": "",
"createdDate": "2025-10-03 18:08:25",
"creditorAddressLine": ", Paris, 75017, Paris, FR",
"creditorBIC": "1",
"creditorCountry": "FR",
"creditorIban": "FR7616798000010001661494691",
"creditorName": "",
"currency": "EUR",
"distributorFee": "",
"forwardUrl": "",
"ibanBic": "BIC-REVOFRP2XXX",
"ibanFullname": "Alex Oak",
"ibanId": "",
"ibanTxEndToEndId": "e9fbca88-160d-4413-befc-c4fxxxxx705a",
"ibanTxId": "",
"informationStatus": "AC06",
"mandateId": "",
"messageToUser": "Sent from Revolut",
"payinDate": "0000-00-00",
"payinId": "eec80c2c-a771-4790-94a9-b24b38xxxx40",
"payinStatus": "CANCELED",
"payinTag": "",
"paymentAcceptedUrl": "",
"paymentCanceledUrl": "",
"paymentExceptionUrl": "",
"paymentHtml": "",
"paymentLanguage": "",
"paymentMethodId": "28",
"paymentPostUrl": "",
"paymentRefusedUrl": "",
"paymentWaitingUrl": "",
"refundAmount": "",
"subtotalItems": "",
"subtotalServices": "",
"subtotalTax": "",
"userFirstname": "Chris",
"userId": "100368137",
"userLastname": "Willow",
"virtualIbanId": "",
"virtualIbanReference": "",
"walletAlias": "wallet-test-1-3-671fc7048c0612024-11-05 10:03:13",
"walletEventName": "wallet_test_1.3",
"walletId": "16614946"
}
]
},
"object_id": "eec80c2c-a771-4790-94a9-b24b31xxxa0",
"object": "payin",
"webhook_created_at": 17600900464795,
"webhook_id": "a0f0c310-780c-460f-be1e-3333exxx809c",
"object_payload_signature": "OJyFGXYWKrtaSk+Jo7VXpGA1VBCJxxxxvqT1zLnHro="
},
"clientId": "123456"
}
```
### `transaction.create`
```json [JSON]
{
"messageId": "a6ea8473-d215-xxxx-xxxx-e530ad43ddb4",
"webhookId": "d29b71fc-ad09-xxxx-xxxx-a24ed4a1f577",
"webhook": {
"webhook": "transaction.create",
"object_payload": {
"transactions": [
{
"transactionId": "1033717416",
"walletDebitId": "9",
"walletCreditId": "16614938",
"transactionType": "International Transfer Reception",
"foreignId": "1717978130",
"name": "0049e4d5-7510-4765-974e-66fba1233a06",
"description": "PayinID [0049e4d5-7510-4765-974e-66fba1233a06| [2025-09-11T19:07:21Z]",
"valueDate": "2025-09-16",
"executionDate": "2025-09-16",
"amount": "1.23",
"walletDebitBalance": "0.00",
"walletCreditBalance": "3.82",
"currency": "EUR",
"createdDate": "2025-09-16 17:07:00"
}
]
},
"object_id": "1033717416",
"object": "transaction",
"webhook_created_at": 17580352209183,
"webhook_id": "d29b71fc-ad09-xxxx-xxxx-a24ed4a1f577",
"object_payload_signature": "KeLw5E2PdDuX7sSLnjAAAA3xZT6FkY0Xdr9Migp8OPo="
},
"clientId": "12345"
}
```
### `balance.update`
```json [JSON]
{
"messageId": "60bbe31c-04fe-xxxx-xxxx-825f7ba84a6a",
"webhookId": "41ee6001-6c9b-xxxx-xxxx-2fdd539a5c90",
"webhook": {
"webhook": "balance.update",
"object_payload": {
"balances": [
{
"walletId": "16614938",
"currentBalance": "3.82",
"authorizations": "0.00",
"authorizedBalance": "3.82",
"currency": "EUR",
"calculationDate": "2025-09-16 17:07:00"
}
]
},
"object_id": "16614938",
"object": "balance",
"webhook_created_at": 17580352210083,
"webhook_id": "41ee6001-6c9b-xxxx-xxxx-2fdd539a5c90",
"object_payload_signature": "bX6f06BaHeQGlQ+TzAAA7EIDwJYDHdAWanenCs2lLU="
},
"clientId": "12345"
}
```
---
---
url: /guide/transfers/faking-operations.md
description: >-
Learn how to simulate payins, verification of payee (VoP), and payouts within
the Sandbox environment for development and API integration testing.
---
# Emulation
Emulation features are only available in `Sandbox` [environment](/guide/api-basics/environments).
**Tip – You can also rely on webhooks**
For operations that cannot be emulated in the Sandbox, [webhook examples](events) are provided.
## SEPA Direct Debit reception (SDDR)
SDDR Core can be emulated by using the dedicated [`/simulation/payout-sddr`](/api-reference/api-endpoints.html#tag/Payouts/SimulateSDDR){target="\_self"} endpoint.
This is a Payout operation; simulating an SDDR debits the Treezor Wallet.
### Parameters
| Attribute | Type | Description |
| --- | --- | --- |
| `debitorIban` | string | IBAN or Virtual IBAN of the debited Wallet. |
| `amount` | integer | Amount of the SDD (will be divided by the `nbTxs`). **Decimal amounts are not supported.** |
| `typeSDD` | string | Either `CORE` (default) or `B2B`. |
| `typeReject` | string | The type of error returned if the SDDR fails. Can be: `rejected` (default), `returned`, `refunded`, or `today` (specifies that we want the SDDR to be executed today). |
| `sci` | string | The SEPA Credit Identifier of the user. In the case of simulation, this defaults to a random string. |
| `nbTxs` | integer | The number of transactions for the SDD. Defaults to `1`. |
| `mandateId` | integer | The Beneficiary Mandate unique identifier. This field is optional. |
| `executeAfterParse` | integer | When set to `1`, launch the job to execute pending SDDRs on the due date (must be used in combination with `typeReject` = `today`). |
### Request
```bash [CURL]
curl -X POST '{baseUrl}/simulation/payout-sddr' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"amount": "26",
"debitorIban": "FR7616798000010000071474474",
"sci": "FR44ZZZ332801",
"typeSDD": "CORE",
"typeReject": "today",
"executeAfterParse": 1
}
```
Response example (if `executeAfterParse` is set to `1`):
```json [JSON]
{
"messages":[
"[Simulation] [POST /payoutSddr] CORE SDDR created",
"[Simulation] batchExecuteSddr() launched"
]
}
```
## SEPA Direct Debit emission (SDDE)
SDDE can be emulated by using the [`/v1/payins`](/api-reference/api-endpoints.html#tag/Payins/postPayin){target="\_self"} endpoint.
This is a Payin operation; simulating an SDDE credits the Treezor Wallet.
**Prerequisites – SDDE emulation requires a KYC-validated legal entity with:**
* **A signed [Mandate](/guide/transfers/mandates)** – Must be the correct [`sddType`](mandates#mandatory-parameters).
* **A SEPA Creditor Identifier (SCI)** – To enable a SCI, please contact your *Treezor Account Manager*.
### Mandatory parameters
| Attribute | Type | Description |
| --- | --- | --- |
| `walletId` | integer | The unique identifier of the Wallet to credit. |
| `paymentMethodId` | integer | Set this value to `21` for crediting funds in Sandbox only. |
| `amount` | number | The amount to credit. Must end with `1.25` to emulate a `VALIDATED` result. |
| `currency` | string | The currency of the transfer. Must be `EUR`. |
| `mandateId` | integer | The unique identifier of the [Mandate](/guide/transfers/mandates). |
### Request
Here is an example of `{payload}`:
```json [JSON]
{
"walletId": "{walletId}",
"userId": "{userId}",
"paymentMethodId": 21,
"amount": 1.25,
"currency": "EUR",
"mandateId": "{mandateId}"
}
```
Returns the Payin object.
```json [JSON]
{
"payins": [
{
"payinId": "",
"payinTag": "",
"payinStatus": "",
"codeStatus": "",
"informationStatus": "",
"walletId": "", // id of the wallet to credit
"userId": "",
"amount": "",
"currency": "",
[...] // some attributes are hidden
}
]
}
```
**Note – Funds availability latency**
Funds are usually available in the Wallet within 5 minutes following the request.
## SEPA Credit Transfer reception (SCTR)
SCTR can be emulated by using the dedicated [`/simulation/payin-sct`](/api-reference/api-endpoints.html#tag/Payins/simulateSctReception){target="\_self"} endpoint.
This is a Payin operation; simulating an SCTR credits the Treezor Wallet.
### Parameters
The following parameters are required.
| Attribute | Type | Description |
| --- | --- | --- |
| `iban` | string | The IBAN of the Wallet to credit. |
| `amount` | integer | The amount to credit. Decimal amounts are not supported. |
### Request
Endpoint: [`/simulation/payin-sct`](/api-reference/api-endpoints.html#tag/Payins/simulateSctReception){target="\_self"}
```bash [CURL]
curl -X POST '{baseUrl}/simulation/payin-sct' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`
```json [JSON]
{
"iban": "FR7616798000010001726649397",
"amount": 20
}
```
Returns the id of the SCTR, its `txId` (transaction id) and its `payinId`.
```json [JSON]
{
"sctrs": [
{
"id": 10022,
"txId": "xxCN7gLRpqmjS6p5",
"payinId": 1234567,
"returnReasonCode": null
}
]
}
```
**Tip – The `returnReasonCode` provides more information**
The `returnReasonCode` can inform you of [the reason](/guide/transfers/error-codes#transfer-reason-codes) for a rejection, in which case the `payinId` will be `null`.
### Accepted SCTR
* The IBAN must be valid **and**,
* The [Wallet](/guide/wallets/introduction) must be validated **and**,
* The [User](/guide/users/introduction) must have its [KYC validated](/guide/user-verification/introduction) **except** when the [SCTR is used as an additional vigilance measure](/guide/user-verification/introduction#additional-vigilance-measures).
### Refused SCTR
* The IBAN can be erroneous (you can for example use `FR76169999999999999999999`) **or**,
* The User [KYC status](/guide/user-verification/introduction) can be `NONE`/`PENDING` **or**,
* The [Wallet](/guide/wallets/modification#delete) status can be `PENDING` or `CANCELED`
### Legacy
SCTR Emulation can also be achieved using the same procedure as for [SDDE](#sepa-direct-debit-emission-sdde), by changing the `paymentMethodId` to `20`.
## Instant SEPA Credit Transfer reception
[SCTR Inst](/guide/transfers/credit-transfer-inst#emitted-instant-credit-transfers-sctr-inst) can be emulated by using the dedicated [`/simulation/sct-inst/payin`](/api-reference/api-endpoints.html#tag/Payins/simulateSctInstReception){target="\_self"} endpoint.
```bash [CURL]
curl -X POST '{baseUrl}/simulation/sct-inst/payin' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"name": "M. Firstname LASTNAME", // Name of the recipient (User)
"bic": "TRZOFR21XXX", // BIC of the recipient (User)
"iban": "FR76167980019999999999999", // IBAN of the recipient (Wallet)
"currency": "EUR",
"amount": 10.0
}
```
Returns the `paymentID` and `sctInstID`.
```json [JSON]
{
"sctInstID": "2333c7a8-25c5-54ff-a06e-7ed2bd8c2f66",
"paymentID": "RECEPTION_6cde3d9f-58d2-11ec-8593-86285561c46d"
}
```
The `sctInstID` can be used to retrieve the payin using the [`/v1/payins/{sctInstId}`](/api-reference/api-endpoints.html#tag/payin/getPayins){target="\_self"} endpoint.
### Accepted SCTR Inst
For an emulated SCTR Inst to be **accepted**:
* The IBAN must be valid **and**,
* The [Wallet](/guide/wallets/introduction) must be validated.
### Refused SCTR Inst
The emulated SCTR Inst may be **refused** if:
* The IBAN is erroneous (e.g., you can use `FR76169999999999999999999`), or
* The [Wallet](/guide/wallets/modification#delete) status can be `PENDING` or `CANCELED`
* The SCTR Inst amount can be greater that €10,000 in a B2C context or greater than €50,000 in a B2B context
In which case, you receive a [`sepaSctrInst.reject_sctr_inst`](events#sepa-reject-sctr-inst) webhook.
## SCTR Recalls
To initiate an SCTR Recall, you can use the following request.
**Prerequisites – You need an SCTR first**
Use the [`/simulation/payin-sct`](/api-reference/api-endpoints.html#tag/Payins/simulateSctReception){target="\_self"} endpoint to create a valid [SCTR emulation](#sepa-credit-transfer-reception-sctr) beforehand.
### Parameters
| Attribute | Type | Description |
| --- | --- | --- |
| `cxlId` | string | The unique identifier of the Recall. We recommend that you use the SCTR's id. |
| `statusId` | integer | The status of the recall resource. For simulation purposes, you must set this to `2` (PENDING\_PAYIN\_REFUND\_CREATED). |
| `sctrId` | integer | The SCTR's id as provided by the [SCTR simulation endpoint](/guide/transfers/faking-operations#sctr). |
| `txId` | string | The `txId` value returned by the [SCTR simulation endpoint](/guide/transfers/faking-operations#sctr). |
| `reasonCode` | string | Reason code of the recall request [see available values](/guide/transfers/sepa-recalls#types-of-recalls-reasoncode). |
| `createPayinRefund` | boolean | Creates a payinrefund resource and receives the corresponding webhooks if set to `true`. |
### Request
```bash [CURL]
curl -X POST '{baseUrl}/simulation/recall-r' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"cxlId": "401",
"statusId": 2,
"sctrId": 401,
"txId": "401",
"reasonCode": "TECH",
"createPayinRefund": true
}
```
Returns the `id` of the Recall.
```json [JSON]
{
"recalls": {
"id": 10
}
}
```
## SCTR Inst Recalls
To initiate an SCTR Inst Recall, you can use the following request.
**Prerequisites – You need an SCTR Inst first**
A valid SCTR Inst must [have been emulated](#instant-sepa-credit-transfer-reception) beforehand.
### Parameters
| Attribute | Type | Description |
| --- | --- | --- |
| `sctInstId` | string | The SCTR Inst's id as provided by the [SCTR Inst simulation endpoint](/guide/transfers/faking-operations#sctr-inst). |
| `demandDate` | string | The date of the recall request. |
| `reasonCode` | string | The reason code of the recall request [see available values](/guide/transfers/sepa-recalls#types-of-recalls-reasoncode). |
| `additionalInformation` | string | Information on top of the recall reason code you want to receive (can only be used with `reasonCode` of type `FRAD`). |
### Request
```bash [CURL]
curl -X POST '{baseUrl}/simulation/sct-inst/recall' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is a `{payload}` example:
```json [JSON]
{
"sctInstId": "1380aeca-963b-5497-aef4-a9532086653c",
"demandDate": "2022-11-24",
"reasonCode": "FRAD",
"additionalInformation": ""
}
```
Returns the `id` for the Recall:
```json [JSON]
{
"sctInstId": "c8457258-b18c-5647-9950-9ba3c99a9543",
"recallrId": "f3f6a9c8-2f4b-5906-9ac7-2d908d04b681"
}
```
## Beneficiary Validation (`result`)
You can emulate the [validation result](./beneficiaries#validation-result-result) (`result`) of the beneficiary by using the specific request payloads below.
### Prerequisite: Create beneficiary
We recommend you create a Beneficiary aligned with the beneficiary validation (name and IBAN). Otherwise, you will trigger the `"Inconsistencies between beneficiary and beneficiaryValidation objects"` HTTP 400 error when attempting a payout.
Endpoint: [`/v1/beneficiaries`](/api-reference/api-endpoints.html#tag/Beneficiaries/postBeneficiary){target="\_self"}
```bash [CURL]
curl -X POST '{baseUrl}/v1/beneficiaries' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"userId": "{userId}",
"name": "Sophie Weber",
"nickName": "Test treezor",
"address": "Test Bank address",
"iban": "DE28503399002244668800",
"bic": "TRZODEB2XXX",
"usableForSct": true
}
```
### Use mock values for validation results
Endpoint: [`/v1/beneficiaries/validation`](/api-reference/api-endpoints.html#tag/Beneficiaries/postBeneficiaryVerification){target="\_self"}
```bash [CURL]
curl -X POST '{baseUrl}/v1/beneficiaries/validation' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here are the `{payload}` examples for each result:
```json [MTCH]
{
"beneficiaryName": "Sophie Weber",
"beneficiaryIBAN": "DE28503399002244668800"
}
```
```json [CMTC]
{
"beneficiaryName": "Sophy Weber",
"beneficiaryIBAN": "DE28503399002244668800"
}
```
```json [NMTC]
{
"beneficiaryName": "Alex Oak",
"beneficiaryIBAN": "DE28503399002244668800"
}
```
```json [NOAP]
{
"beneficiaryName": "Sophy Weber",
"beneficiaryIBAN": "DE82503399000000062899"
}
```
## SEPA Credit Transfer emission (SCTE)
The emulation of an SCTE in Sandbox occurs in 2 steps:
1. [`/v1/payouts`](/api-reference/api-endpoints.html#tag/Payouts/postPayout){target="\_self"} – Create an SCTE (`payoutTypeId` of `1`).
2. [`/simulation/payouts/{payoutId}`](/api-reference/api-endpoints.html#tag/Payouts/putSimuScte){target="\_self"} – Update the `payoutStatus` to either accept or reject the payout in Sandbox.
**Prerequisites**
* You have created an active [Beneficiary](beneficiaries)
* You have requested a [Beneficiary Validation](#beneficiary-validation-result)
### 1. Create the SCTE payout
Endpoint: [`/v1/payouts`](/api-reference/api-endpoints.html#tag/Payouts/postPayout){target="\_self"}
Here is an example of `{payload}`:
```json [JSON]
{
"walletId": {walletId},
"beneficiaryId": {beneficiaryId},
"beneficiaryValidationId": "{beneficiaryValidationId}",
"amount": 1000,
"currency": "EUR"
}
```
Returns the Payout object, with its `payoutStatus` set to `PENDING`.
### 2. Update the SCTE payout in Sandbox
Endpoint: [`/simulation/payouts/{payoutId}`](/api-reference/api-endpoints.html#tag/Payouts/putSimuScte){target="\_self"}
```bash [CURL]
curl -X PUT '{baseUrl}/simulation/payouts/{payoutId}' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is a `{payload}` example.
```json [JSON]
{
"payoutStatus": "VALIDATED" // or CANCELED
}
```
Returns the following information if successful.
```json [JSON]
{
"payoutId": "12345",
"payoutStatus": "VALIDATED",
"payoutTypeId": 1,
"payoutTag": "string"
}
```
Treezor also sends a [`payout.update`](/guide/transfers/events#payout-update) webhook.
### Update SCTE payouts in bulk
You can also update the status of multiple SCTE at once in Sandbox.
Endpoint: [`/simulation/payouts/bulk`](/api-reference/api-endpoints.html#tag/Payouts/putSimuScteBulk){target="\_self"}
```bash [CURL]
curl -X PUT '{baseUrl}/simulation/payouts/bulk' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is a `{payload}` example.
```json [JSON]
{
"updates": [
{
"payoutIds": [
"123456",
"234567",
"345678",
"456789"
],
"payoutStatus": "VALIDATED"
},
{
"payoutIds": [
"5678910"
],
"payoutStatus": "CANCELED"
}
]
}
```
Returns the following information if successful.
```json [JSON]
{
"updates": [
{
"payoutId": "123456",
"payoutStatus": "VALIDATED",
"payoutTypeId": 0,
"payoutTag": "string"
},
{
"payoutId": "234567",
"payoutStatus": "VALIDATED",
"payoutTypeId": 0,
"payoutTag": "string"
},
{
"payoutId": "456789",
"payoutStatus": "VALIDATED",
"payoutTypeId": 0,
"payoutTag": "string"
},
{
"payoutId": "5678910",
"payoutStatus": "CANCELED",
"payoutTypeId": 0,
"payoutTag": "string"
}
],
"errors": [
{
"code": "string",
"message": "string"
}
]
}
```
Treezor sends as many [`payout.update`](/guide/transfers/events#payout-update) webhooks as there are successful updates.
### Legacy SCTE validation emulation
Emulating SCTE in Sandbox only requires you use your regular payout endpoint. Any amount will return a `PENDING` status (and the Wallet Balance will be updated the day after around 10:30 AM Paris time), except for amounts ending in `1.25`.
For the later, retrieving the Payout shortly after will return a `VALIDATED` result, and the debited Wallet Balance is updated at the same time.
This method is now replaced by the [`/simulation/payouts/{payoutId}`](/api-reference/api-endpoints.html#tag/Payouts/putSimuScte){target="\_self"} and will be discontinued in the near future.
## Instant SEPA Credit Transfer emission (SCTE Inst)
Emulating SCTE in Sandbox only requires you use your regular payout endpoint.
Prerequisites:
* User must be KYC validated.
* Beneficiary `userId` and Wallet owner must be the same User.
* Necessary funds must be available on the debited Wallet.
* You have requested a [Beneficiary Validation](#beneficiary-validation-result).
### Mandatory parameters
| Attribute | Type | Description |
| --- | --- | --- |
| `payoutTypeId` | integer | Must be `3` for an SCTE Inst. |
| `walletId` | integer | The unique identifier of the debited Wallet. |
| `beneficiaryId` | integer | The unique identifier of the Beneficiary of the credit transfer. You must have created the [Beneficiary](./beneficiaries) object beforehand. |
| `beneficiaryValidationId` | string | The unique identifier of the Beneficiary Validation of the credit transfer. You must have created the [Beneficiary](./beneficiaries#sepa-beneficiaries) object beforehand. |
| `amount` | number | The amount of the credit transfer, which value defines the result of the emulation: `VALIDATED` – Provide an amount strictly **below** `1000.00``CANCELED` – Provide an amount strictly **above** `1000.00` |
| `currency` | string | The currency of the credit transfer. Must be `EUR`. |
### Request
Here is an example of `{payload}`:
```json [JSON]
{
"payoutTypeId": 3,
"walletId": {walletId},
"beneficiaryId": {beneficiaryId},
"beneficiaryValidationId": "{beneficiaryValidationId}",
"amount": 800.00,
"currency": "EUR"
}
```
Returns a Payout object.
```json [JSON]
{
"payouts": [
{
"payoutId": "8929329c-b4a5-4bb9-b792-0e9e9d98xxxa",
"payoutTag": "",
"payoutStatus": "PENDING",
"payoutTypeId": 3,
"payoutType": "Instant Credit Transfer",
"walletId": 3059736,
"payoutDate": "2024-06-26 10:15:17",
"walletEventName": "Name of the Wallet",
"walletAlias": "name-of-the-wallet-667bcd66d546b",
"userFirstname": "Alex",
"userLastname": "Oak.validated",
"userId": 965725,
"beneficiaryId": 40963,
"uniqueMandateReference": "",
"bankaccountIBAN": "FR761679800001000030XXXXXX3",
"label": "",
"amount": "800.00",
"currency": "EUR",
"partnerFee": "0",
"createdDate": "2024-06-26 10:15:17",
"modifiedDate": "",
"virtualIbanId": null,
"virtualIbanReference": null,
"codeStatus": "160001",
"informationStatus": "PENDING",
"supportingFileLink": "",
"endToEndId": "2dbb81b26db94db3b530988b4189aad7",
"reasonCode": null,
"reasonDescription": null,
"internationalBeneficiaryId": null,
"quotationId": null,
"metadata": null,
"totalRows": null,
"beneficiaryValidationId": null
}
]
}
```
You can use the [`/v1/payouts/{payoutId}`](/api-reference/api-endpoints.html#tag/Payouts/getPayout){target="\_self"} endpoint to view the updated payout with its `VALIDATED` status.
```json [JSON] {6,28}
{
"payouts": [
{
"payoutId": "8929329c-b4a5-4bb9-b792-0e9e9d98xxxa",
"payoutTag": "",
"payoutStatus": "VALIDATED",
"payoutTypeId": 3,
"payoutType": "Instant Credit Transfer",
"walletId": 3059736,
"payoutDate": "2024-06-26 10:15:17",
"walletEventName": "Name of the Wallet",
"walletAlias": "name-of-the-wallet-667bcd66d546b",
"userFirstname": "Alex",
"userLastname": "Oak.validated",
"userId": 965725,
"beneficiaryId": 40963,
"uniqueMandateReference": "",
"bankaccountIBAN": "FR761679800001000030XXXXXX3",
"label": "",
"amount": "800.00",
"currency": "EUR",
"partnerFee": "0",
"createdDate": "2024-06-26 10:15:17",
"modifiedDate": "",
"virtualIbanId": null,
"virtualIbanReference": null,
"codeStatus": "160004",
"informationStatus": "VALIDATED",
"supportingFileLink": "",
"endToEndId": "2dbb81b26db94db3b530988b4189aad7",
"reasonCode": null,
"reasonDescription": null,
"internationalBeneficiaryId": null,
"quotationId": null,
"metadata": null,
"totalRows": null,
"beneficiaryValidationId": null
}
]
}
```
---
---
url: /guide/dashboard/transfers.md
description: >-
Let your team provide support regarding your end users operations (payouts,
wallet-to-wallet) using the Treezor Dashboard.
---
# Transfers
In the Dashboard, funds can be moved from a Wallet in the following ways:
* [**Payouts**](#transfers-from-wallet-to-external-bank-account) – Transfers money from the Wallet to an external bank account (i.e., [Beneficiary](beneficiaries))
* [**Wallet-to-Wallet**](#transfers-from-wallet-to-wallet) – Transfers money from one [Wallet](wallets) to another in your Treezor ecosystem
## Transfers from Wallet to external Bank Account
From the [*Wallets*](./wallets) tab, you can transfer funds from one wallet to an external bank account through the SEPA network. You must create a [Beneficiary](beneficiaries) prior to making this type of transfer.
In the *User details* view, once the user is selected, select the *Wallets* tab and click the "Make a payment" button to select the "Create payout" option.
The *Payout* popup is displayed for you to:
* Select the source wallet (belongs to the currently selected user)
* Select the target external bank account (Beneficiary)
* Define the payout type, amount, and reason
* Add a supporting file if needed.
**Feature Activation – Instant Payments are not available by default**
Please contact Treezor if you're interested in this feature.
Once done, you may click on the "Preview Payout" button. Make sure all the information is relevant before confirming.
**Tip – Internal reasons picklist available on request**
A custom picklist can be configured, for categorizing the transfers, or identifying they've been emitted from the Dashboard, for instance. This picklist relies on the `payoutTag` field. Contact Treezor for more information.
## Transfers from Wallet to Wallet
From the *Wallets* tab, you can transfer funds from one wallet to another. This operation is instantaneous.
In the *User details* view, once the user is selected, select the *Wallets* tab and click the "Make a payment" button to select the "Wallet-to-Wallet Transfer" option.
The *Wallet to Wallet Transfer* popup is displayed for you to:
* Select the source wallet (belongs to the currently selected user)
* Select the target wallet (either from favorites, currently selected user, or by search)
* Define the transfer amount and reason
* Make sure all the information is relevant prior to confirming the transfer
When all the steps are completed, a popup indicates the operation is successful and the corresponding operation is displayed in the *Operations* section of both Wallets.
---
---
url: /api-reference/postman.md
description: >-
Quickly get started with the Treezor API using our Postman Collection, to
explore common API use cases for rapid integration understanding. This guide
explains how to set up and use the collection, providing step-by-step
instructions and the official link.
---
# Documentation Postman Collection
Treezor Documentation has its own [Postman Collection](https://learning.postman.com/docs/collections/collections-overview/) to help you understand how to use the Treezor API.
This collection is:
* **Connect-oriented** – It doesn’t take into account legacy API services.
* **Sandbox-oriented** – It doesn’t provide production-only features.
* **Non-exhaustive** – It’s only meant to get you started, with key endpoints and attributes.
Before using the collection, ensure you already have the credentials for your Sandbox from Treezor.
If you’re new to Postman, the sections below may help you get started:
* [Fork the collection](#fork-the-collection)
* [Set up your environment](#set-up-your-environment)
* [Pull the collection changes](#pull-collection-changes)
**Reading – Postman Documentation**
The [Postman Documentation](https://learning.postman.com/docs/introduction/overview/) may provide more information on how to take advantage of the collection!
## Fork the collection
By clicking on the Run with Postman button, you’ll be invited to fork the collection. It consists of duplicating the collection to play with it without impacting the source collection and other users.
**Tip – Watch collection**
Make sure you tick the “Watch original collection” checkbox. You’ll be notified when the collection is updated so you can pull the changes into your collection.
Once the copy of the collection is available in your Postman workspace, you may set up your environment.
## Set up your environment
You need to create an environment to start using your collection.
In the Postman Environment section, you can either:
* Create a new environment, in which you will add the relevant variables listed below, or
* Import [this environment](https://www.postman.com/restless-crater-540300/workspace/treezor-doc-public/environment/35140470-eec9e7d5-c109-4d8e-97c7-d399260a7561?action=share\&creator=35140470) that you can download. It contains empty variables for you to fill in.
Then enter your environment URL and your credentials sent to you by Treezor in the variables:
| Variable | Description |
| --- | --- |
| `baseUrl` | Your Sandbox environment URL. |
| `client_id` | Your API authentication credentials provided to you by Treezor. |
| `client_secret` | Your API authentication credentials provided to you by Treezor. |
In addition, the following variables are necessary for some features:
| Variable | Description |
| --- | --- |
| `cardPrint` | If you plan on issuing cards, you will need this value provided upon setting up your Card Program. |
As you use the collection, the environment variables will automatically be defined by the scripts included in each request.
## Structure of the collection
The collection is organized for you to navigate through the various illustrated uses.
| Folder | Description |
| --- | --- |
| **Authentication** | Contains the `POST /oauth/token` endpoint for you to generate the access token necessary to authenticate all the Treezor API requests. We made it easily accessible as your token expires after 1 hour. |
| **Starter endpoints** | Contains some of the essential endpoints to get started with the Treezor API. For more advanced features, please contact Treezor or refer to the API Documentation. |
| **Quickstart** | Contains the endpoints for the [Quickstart](/guide/overview/tinker.html) article, guiding you through your first testing of the Treezor API. |
| **Use cases** | Contains the endpoints to run the step-by-step guides available in the [Use Cases](/guide/use-cases/prerequisites/introduction) section of the documentation. |
## Pull collection changes
The collection is constantly updated as the Treezor API and the documentation evolve.
If you’re watching the collection, you may have received a notification in Postman or an email indicating that the collection has been modified.
To retrieve the modification, you may use the pull changes command for your collection. A tab opens in your forked collection to import all the changes made to your collection. More information is available in the [Postman Documentation](https://learning.postman.com/docs/collaborating-in-postman/using-version-control/forking-elements/#pull-updates-from-a-parent-element).
---
---
url: /api-reference/api-endpoints.md
description: >-
The complete Treezor API Reference. Explore all endpoints with detailed
specifications, request/response examples, and schema definitions in an
interactive OpenAPI 3.0.1 powered interface.
---
---
---
url: /content-updates/content-updates.md
description: Keep track of the Treezor API documentation\'s latest content updates
---
# Latest content updates
Stay informed about the latest improvements to the Treezor documentation. This page tracks major documentation changes and additions over the **last 3 months**.
Please note that these updates are not exhaustive. Are included:
* Major content additions and rewrites.
* New articles and endpoints (feature integration guides).
* Significant updates to the **API Reference**.
***
title: Documentation updates
description: The main updates published on the Treezor documentation on March 05, 2026.
date: 2026-03-05
----------------
**Wallets – Events** Added more context regarding wallet events, including where to find the attribute descriptions and which endpoint triggers an event.
**Links**: [Wallet events](/guide/wallets/events) article
**Payouts – Payout refunds** Added for which reason codes a payout refund can be requested.
**Links**: [Refunding an SDDR](/guide/transfers/direct-debit#refunding-an-sddr) article | [Refunding an SDDR](/guide/transfers/sepa-recalls#emitting-sct-recalls) article
**SCA – SCA Wallets** Some endpoints displayed the wrong scope. This issue has been fixed.
**Links**: [SCA Wallets life cycle](/guide/strong-customer-authentication/sca-wallet-lifecycle) article | [SCA Wallets](/api-reference/api-endpoints.html#tag/SCA){target="\_self"} endpoints
**Webhooks – Race conditions** Moved the "race conditions" article to the introduction to optimize the information structure and navigation.
**Links**: [Webhooks introduction](/guide/webhooks/introduction#race-conditions) article
***
title: Documentation updates
description: The main updates published on the Treezor documentation on February 26, 2026.
date: 2026-02-26
----------------
**Checks – Cancellation** Added a dedicated section to clarify check cashing cancellation.
**Links**: [Check cashing](/guide/cheques/cashing#cancellation) article
**Documentation – New content updates page** Added dedicated page to highlight major documentation changes.
**Links**: [Content updates](/content-updates/content-updates) page
**Wallets – Balance** Optimized content by removing glossary item and improving the Balances article.
**Links**: [Balances](/guide/wallets/balances) article
***
title: Documentation updates
description: The main updates published on the Treezor documentation on February 12, 2026.
date: 2026-02-12
----------------
**Verification of Payee – Mandatory messages** Added the mandatory message to display when the verification service is unavailable.
**Links**: [Verification of Payee](/guide/transfers/beneficiaries#validation-result-result) article
**Payouts – Idempotency** Added specific maximum character limit for SCTE `accessTag`.
**Links**: [Emitted SEPA Credit Transfers](/guide/transfers/credit-transfer#parameters) article | [`/v1/payouts`](/api-reference/api-endpoints.html#tag/Payouts/postPayout){target="\_self"} endpoint
**Cards – Multi-Criteria Dynamic Card** Added an example for single-use card.
**Links**: [MDC Help Center](https://treezor.zendesk.com/hc/en-us/articles/13231619074844-Multi-Criteria-Dynamic-Card-MDC) article
**Dashboard – Audit trail** Added information regarding how to access the new *Audit Trail* view for Admins and Managers.
**Links**: [Dashboard users](/guide/dashboard/dashboard-users) article
***
title: Documentation updates
description: The main updates published on the Treezor documentation on February 5, 2026.
date: 2026-02-05
----------------
**SCA – PCI DSS endpoints data to sign** Added the PCI DSS endpoints to the list of endpoints requiring SCA, as well as the `cardId` as data to sign.
**Links**: [Securing endpoints](/guide/strong-customer-authentication/securing-endpoints) article
**Payouts – Mass Payouts** The `massPayoutTag` parameter wasn't indicated as required. This issue has been fixed.
**Links**: [Mass Payouts](/guide/strong-customer-authentication/user-enrollment#web-native-enrollment) article | [`/v1/massPayouts`](/api-reference/api-endpoints.html#tag/Payouts/postMassPayout){target="\_self"} endpoint
***
title: Documentation updates
description: The main updates published on the Treezor documentation on January 29, 2026.
date: 2026-01-29
----------------
**Dashboard – Card Security** Updated the card 3DS enrollment sections to fit the new experience.
**Links**: [Cards, Enroll Card for 3DS](/guide/dashboard/cards#enroll-card-for-3ds) article | [Gift Cards](/guide/use-cases/gift-cards/nocode-guide#enroll-3ds) no-code use case
**Payouts – Standard Emitted SEPA Credit Transfer** Updated the list of parameters to put forward the `label` and `endToEndId` attributes.
**Links**: [Emitted Credit Transfers (SCTE)](/guide/transfers/credit-transfer#emitted-credit-transfers-scte) article
***
title: Documentation updates
description: The main updates published on the Treezor documentation on January 22, 2026.
date: 2026-01-22
----------------
**Cards – Multi-Criteria Dynamic Card (MDC)** Added the new `merchant_data_pos_terminal_id` fact to the list. The corresponding `posTerminalId` was added to the Card Transaction simulation in the API Reference as well.
**Links**: [MDC Help Center](https://treezor.zendesk.com/hc/en-us/articles/13231619074844-Multi-Criteria-Dynamic-Card-MDC) article | [`/simulation/cardtransaction/authorization`](/api-reference/api-endpoints.html#tag/Card%20Transactions/simuTransacAuthorization){target="\_self"} endpoint
**User verification – Verification solutions** Added the 90-day link expiry delay of the QES and Video Conference solutions.
**Links**: [Qualified eSignature (QES)](/guide/user-verification/qes) & [Video conference](/guide/user-verification/videoconf) articles | [Verification Solutions](/api-reference/api-endpoints.html#tag/Verification%20Solutions%20\(KYC\)){target="\_self"} endpoints
***
title: Documentation updates
description: The main updates published on the Treezor documentation on January 15, 2026.
date: 2026-01-15
----------------
**Cards – New transaction simulation** Added the new card transaction simulation endpoints to the documentation.
**Links**: [Emulation](/guide/cards/faking-operations) article | [Card Transactions](/api-reference/api-endpoints.html#tag/Card%20Transactions){target="\_self"} endpoints | [Dashboard Wallets](/guide/dashboard/wallets#wallet-commands) article | [2026 Product updates #1](https://treezor.zendesk.com/hc/en-us/articles/25024318670492-21-01-2026-PROD-Product-updates-2026-1#h_01KFN6SA3WSJKVYQH5A5E6VPAP)
**Users – Status simulation** Updated the new methods to simulate the user status and verification statuses in Sandbox.
**Links**: [Emulation (Users)](/guide/users/faking-operations) article | [Emulation (User Verification)](/guide/users/faking-operations) article | [2026 Product updates #1](https://treezor.zendesk.com/hc/en-us/articles/25024318670492-21-01-2026-PROD-Product-updates-2026-1#h_01KFN6V6S0Z3NSAA6E8W5R8T9T)
***
title: Documentation updates
description: The main updates published on the Treezor documentation on January 8, 2026.
date: 2026-01-08
----------------
**Wallet documents – Confirmation letter** Added this new type of document and related endpoints in the documentation.
**Links**: [Account documents](/guide/wallets/account-documents) article | [Account Documents](/api-reference/api-endpoints.html#tag/Account%20Documents){target="\_self"} endpoints | [Dashboard Wallets](/guide/dashboard/wallets#wallet-commands) article | [Dashboard Q4 evolutions](https://treezor.zendesk.com/hc/en-us/articles/25023247516956-15-01-2026-DASHBOARD-Your-Dashboard-evolutions-Q4-2025#h_01KFN4X22G8CXVD7XZG2H74Q31)
**SCA – WebAuthn** Added the `userVerification` option for Web Native enrollment.
**Links**: [Web Native enrollment](/guide/strong-customer-authentication/user-enrollment#web-native-enrollment) article
**Dashboard – Cards view** Updated all card-related articles due to recent redesign.
**Links**: [Dashboard Q4 evolutions](https://treezor.zendesk.com/hc/en-us/articles/25023247516956-15-01-2026-DASHBOARD-Your-Dashboard-evolutions-Q4-2025#h_01KFN4X22G8CXVD7XZG2H74Q31)
***
title: Documentation updates
description: The main updates published on the Treezor documentation on December 18, 2025.
date: 2025-12-18
----------------
**Cards – Digitized Cards** The scopes for the digitized cards endpoints were missing. This issue has been fixed.
**Links**: [X-Pay](/guide/cards/x-pay-google-apple) article | [Digitized Cards](/api-reference/api-endpoints.html#tag/Digitized%20Cards){target="\_self"} endpoints
**Beneficiary – Verification of Payee (VoP)** Added prerequisites to VoP emulation.
**Links**: [Emulation, Beneficiary Validation](/guide/transfers/faking-operations#beneficiary-validation-result) article
***
title: Documentation updates
description: The main updates published on the Treezor documentation on December 11, 2025.
date: 2025-12-11
----------------
**Cards – Delivery Address** The fields related to the card delivery address (`deliveryTitle`, `deliveryLastName`, `deliveryAddress1`, etc.) are now fully documented in all the responses.
**Links**: [Cards](/api-reference/api-endpoints.html#tag/Cards){target="\_self"} endpoints
**Cards – Renewal** Added new optional fields to the renewal details request body.
**Links**: [`/v1/cards/{cardId}/renewalDetails`](/api-reference/api-endpoints.html#tag/Cards/updateRenewalDetails){target="\_self"} endpoint
**Cards – Batch Delivery** Added precision to the timeline for creating cards that are to be sent in the same batch.
**Links**: [Card creation, Batch Delivery](/guide/cards/creation#batch-delivery-batchdeliveryid) article
**Users – LegalForms** Added new items to the list of values for Italian and German users.
**Links**: [Legal Forms](/guide/users/introduction#legal-forms-legalform) article | [2025 Product updates #12](https://treezor.zendesk.com/hc/en-us/articles/23657196117276-13-11-2025-PROD-Product-Updates-12#h_01KC8WJJVYA6V8DBM24RXC5ZRY)
***
title: Documentation updates
description: The main updates published on the Treezor documentation on December 4, 2025.
date: 2025-12-04
----------------
**Payouts – Simulation** The new endpoint to simulate the approval or refusal of multiple standard emitted SEPA Credit Transfers (SCTE) is now available in the documentation.
**Links**: [Emulation](/guide/transfers/faking-operations.html#update-scte-payouts-in-bulk) article | [`/simulation/payouts/bulk`](/api-reference/api-endpoints.html#tag/Payouts/putSimuScteBulk){target="\_self"} endpoint
**Cards – Customization** Unsupported extensions for `logoId` & `logoBackId` were displayed in the dedicated article. This issue has been fixed.
**Links**: [Customization](/guide/cards/creation#customization) article
**Transfers – SEPA Credit Transfers** For SCT, the list of codes has been updated with the codes that can be returned depending on the network.
**Links**: [SCT Inst reason codes](/guide/transfers/error-codes.html#sct-inst-reason-codes) article
**Users – Tax Residence** Added the error returned when the User status doesn't allow for the update of the tax residence.
**Links**: [Errors](/guide/users/error-codes) article
**Users – Self-employed users KYC** Added the exact list of parameters required for KYC in the specific case of self-employed users.
**Links**: [Self-employed users](/guide/users/physical##self-employed-users) article
---
---
url: /api-reference/pci-dss-dev.md
description: >-
The PCI DSS Treezor API Reference. Explore PCI DSS-specific endpoints with
detailed specifications, request/response examples, and schema definitions in
an interactive OpenAPI 3.0.1 powered interface.
---
---
---
url: /guide/acquiring/_components/card-acq-codestatus.md
---
| `codeStatus` | Description |
|--- |--- |
| `150109` | Authentication Failed |
| `150110` | Blocked |
| `150111` | Denied |
| `150112` | Authorized and Pending |
| `150113` | Refused |
| `150114` | Expired |
| `150115` | Canceled |
| `150116` | Authorized |
| `150117` | Capture Requested |
| `150118` | Captured |
| `150119` | Partially Captured |
| `150126` | Partially Refunded |
| `150142` | Authorization Requested |
| `150143` | Authorization Cancelled |
| `151116` | Authorized - Direct Validation at Authorization |
| `151117` | Capture Requested - Direct Validation at Authorization |
| `151118` | Captured - Direct Validation at Authorization |
---
---
url: /guide/cards/_components/card-limits.md
---
Ensure you fill in all the limits below by setting:
* All values you don't need to `0` to deactivate them
* At least one ATM daily, weekly, or monthly limit to another value than `0`
* At least one Payment daily, weekly, or monthly limit to another value than `0`
**Information – Limits can't be expressed in cents**
Limits only accept integer values, which means you can't have limits with decimals (except for `paymentDailyLimit`).
| Attribute | Type | Description |
| --- | --- | --- |
| `limitPaymentAll` | integer | Lifetime payment limit |
| `limitPaymentYear` | integer | Yearly payment limit |
| `limitPaymentMonth` | integer | Monthly payment limit |
| `limitPaymentWeek` | integer | Weekly payment limit |
| `limitPaymentDay` | integer | Daily payment limit |
| `paymentDailyLimit` | number | Daily payment limit (for food vouchers use cases) |
| `limitAtmAll` | integer | Lifetime withdrawal limit |
| `limitAtmYear` | integer | Yearly withdrawal limit |
| `limitAtmMonth` | integer | Monthly withdrawal limit |
| `limitAtmWeek` | integer | Weekly withdrawal limit |
| `limitAtmDay` | integer | Daily withdrawal limit |
---
---
url: /guide/cards/_components/card-register-3ds.md
---
3D Secure provides an enhanced level of security for online (e-commerce) [payments](/guide/cards/transactions-lifecycle) by adding the possibility to authenticate the cardholder. This a **mandatory fallback** with a one-time password (OTP) sent by SMS; the card must be enrolled for [Out of Band (OOB) authentication](/guide/strong-customer-authentication/securing-endpoints#enrolling-to-out-of-band-authentication) first.
**Registering the card for 3D Secure requires a mobile phone number**. The cardholder then receives a secure code on their mobile phone when an authentication is required for an online payment. This code is unique for each payment and needs to be entered on the merchant's website or mobile application when prompted.
**Prior to this step, your must ensure the User was created with a [mobile phone number](/guide/api-basics/data-format#phones)**. Otherwise, the [User](/guide/users/introduction) must be updated with a mobile phone number.
Endpoint: [`/v1/cards/Register3DS`](/api-reference/api-endpoints.html#tag/Cards/post3ds){target="\_self"}
```bash [CURL]
curl -X POST '{baseUrl}/v1/cards/Register3DS' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{
"cardId": 123456
}'
```
This returns a Card object, but doesn't specify the 3D Secure enrolling status. Treezor also sends a [`card.register3DS`](/guide/cards/events#cardregister3ds) webhook.
**Configuration – By default, 3DS SMS are sent under the name "Secure3DS"**
You can contact Treezor and provide a new sender name that:
* Contains only alphanumeric characters (no spaces)
* Starts with a letter
* Is less than 12-character long
---
---
url: /guide/cards/_components/card-status.md
---
| Code | Plaintext value | Description | Lock type |
| :---: | --- | --- | --- |
| `0` | `UNLOCK` | The card is unlocked and can be used (if no other options or limits prevent it). | N/A |
| `1` | `LOCK` | The card is locked and cannot be used. | Reversible |
| `2` | `LOST` | The card is lost and cannot be used. | Permanent |
| `3` | `STOLEN` | The card is stolen and cannot be used. | Permanent |
| `4` | `DESTROYED` | The card is terminated and cannot be used. | Permanent |
| `5` | `LOCK_INTERNAL` | The card is locked by Treezor and cannot be used, only Treezor is able to unlock it. | Reversible |
| `6` | `EXPIRED` | Automatically set value indicating the card has expired. The card was either renewed or the expiry date passed. Treezor sends the following webhooks: [`card.expiryAlert`](/guide/cards/events#card-expiryalert) – The card expires at the end of the next month; you can anticipate [Renewal](/guide/cards/renewal). [`card.update`](/guide/cards/events#card-update) – The card expired. | Permanent |
| `7` | `CUSTOM_LOCK` | Secondary lock; the card is locked and cannot be used. This is the same mechanism as `LOCK`, providing you more flexibility to manage cards (e.g., reporting reasons, preventing cardholders to unlock the card themselves). | Reversible |
---
---
url: /guide/cards/_components/country-restriction-group.md
---
| Attribute | Type | Description |
|--- |--- |--- |
| `name` | string | The name of the restriction group |
| `isWhitelist` | boolean | Indicates the kind of restriction: `true` (default) – Allows only a specified list of countries (whitelist)`false` – Allows all countries except the specified list (blacklist) |
| `countries` | array of strings | The list of countries (each country is a string featuring a Country Code in the [ISO 3166-1 numeric format 3-digit code](https://en.wikipedia.org/wiki/ISO_3166-1_numeric)). |
| `status` | string | One of the following values:`VALIDATED` – The restriction is active.`PENDING` (default) – The restriction is created but not yet active.`CANCELED` – The restriction has been deactivated (this is irreversible). |
| `startDate` | string | The date and time at which the restriction starts. Defaults to the date and time of creation. |
---
---
url: /guide/cards/_components/mcc-restriction-group.md
---
| Attribute | Type | Description |
|--- |--- |--- |
| `name` | string | The name of the restriction group. |
| `isWhitelist` | boolean | Indicates the kind of restriction: `true` (default) – Allows only a specified list of merchant categories (whitelist)`false` – Allows all merchant categories except the specified list (blacklist) |
| `mcc` | array | The list of MCCs (each MCC is an integer). |
| `status` | string | One of the following values:`VALIDATED` – The restriction is active.`PENDING` (default) – The restriction is created but not yet active.`CANCELED` – The restriction has been deactivated (this is irreversible). |
| `startDate` | string | The date and time at which the restriction starts. Defaults to the date and time of creation. |
---
---
url: /guide/cards/_components/mid-restriction-group.md
---
| Attribute | Type | Description |
|--- |--- |--- |
| `name` | string | The name of the restriction group |
| `isWhitelist` | boolean | Indicates the kind of restriction: `true` (default) – Allows only a specified list of merchants (whitelist)`false` – Allows all merchants except the specified list (blacklist) |
| `merchants` | array of strings | The list of MIDs (each MID is a string). |
| `status` | string | One of the following values:`VALIDATED` – The restriction is active.`PENDING` (default) – The restriction is created but not yet active.`CANCELED` – The restriction has been deactivated (this is irreversible). |
| `startDate` | string | The date and time at which the restriction starts. Defaults to the date and time of creation. |
---
---
url: /guide/cards/_components/tx-authentication-steps.md
---
When a [Card Transaction](/guide/cards/transactions) goes through SCA, the following occurs:
1. **Treezor notifies you** by sending a [`card3DSv2Authentication.create`](/guide/cards/events-tx#card3DSv2authentication-create) webhook.
2. **You authenticate your end user** using [the SDK](/guide/strong-customer-authentication/sdk) and an SCA method.
3. **You inform Treezor** of the authentication result using [the dedicated endpoint](/guide/cards/transactions-authentication#notification-of-authentication-result).
4. **Treezor notifies you** of the final transaction status by sending a [`card3DSv2Authentication.update`](/guide/cards/events-tx#card3DSv2authentication-update) webhook.
---
---
url: /guide/dashboard/_components/interface.md
---
| # | Section | Description |
| :---: | --- | --- |
| | Navigation menu | Located on the left-hand side, this foldable menu allows you to navigate to the different views:*Dashboard* views, which focus on the features.*Configuration* views, which are about setting up your Dashboard. |
| | Main toolbar | In the upper part of each view, the Main toolbar contains the search field, the list of favorites, the language selection, and the account drop-down, for you to log out or access your *Account* page. |
| | Main view | Main content, which depends on the selected view. By default, the *Users* view is displayed. |
| | Environment | In the bottom left corner, you’ll find information about your environment and the version of the Dashboard. |
---
---
url: /guide/strong-customer-authentication/_components/sca_wallet.md
---
**Caution – The SDK uses the term *Wallet* differently from Treezor**
In the [SDK](/guide/strong-customer-authentication/sdk), the term *Wallet* or *SCA Wallet* describes the secure enclave on a mobile device, not [Treezor Wallets](/guide/wallets/introduction).
---
---
url: /guide/users/_components/kyc-form.md
---
**Information – Refer to your KYC Form for declarative data**
Declarative data to submit depends on the type of user, the country you're operating in, the regulations linked to your use case, etc. Treezor Compliance team provides you with your KYC Form listing what needs to be submitted.
---
---
url: /guide/wallets/_components/wallet_type_tip.md
---
**Tip – The Wallet type is editable up to the first operation**
Once the first transaction occurred, the `walletTypeId` can no longer be updated.
---
---
url: /guide/cards/modification.md
description: >-
Technical guide for updating cards via the Treezor API, including blocking,
PIN & CVV management, and dynamic card account selection for multi-wallet.
Includes required parameters, request structure, and response examples.
---
# Modification
In addition to the card life cycle and [options](./restrictions-limits), Treezor offers a series of features to manage your cards on the day-to-day basis.
| Feature | Description |
| --- | --- |
| **Lock/Unlock** | Ability to update the card status, hence unlocking and locking the card temporarily or permanently. |
| **PIN code** | Ability to change the PIN code, or unlock a card which has been blocked due to erroneous PIN code entries. |
| **CVV unlock** | Ability to unblock a card which has been blocked due to erroneous CVV entries. |
| **Regeneration** | Ability to recreate the virtual card image if your branding changes for instance. |
## Block a card
If you suspect fraud or misuse, the API allows you to temporarily or permanently block a card, effective immediately.
This feature can also be used with special cards that must expire at a specific date (such as a one-year valid gift card). You will have to lock the card on the expiration day.
**Best practice – Allowing your end users to block their cards**
While blocking a card temporarily is no issue, you should not allow end users to permanently block their cards without thorough confirmation steps (as fees may apply to issue a replacement card).
### Lock status parameter
The `lockStatus` integer allows you to update `statusCode` attribute of a Card. They are mapped as follows.
| Code | Plaintext value | Description | Lock type |
| :---: | --- | --- | --- |
| `0` | `UNLOCK` | The card is unlocked and can be used (if no other options or limits prevent it). | N/A |
| `1` | `LOCK` | The card is locked and cannot be used. | Reversible |
| `2` | `LOST` | The card is lost and cannot be used. | Permanent |
| `3` | `STOLEN` | The card is stolen and cannot be used. | Permanent |
| `4` | `DESTROYED` | The card is terminated and cannot be used. | Permanent |
| `5` | `LOCK_INTERNAL` | The card is locked by Treezor and cannot be used, only Treezor is able to unlock it. | Reversible |
| `6` | `EXPIRED` | Automatically set value indicating the card has expired. The card was either renewed or the expiry date passed. Treezor sends the following webhooks: [`card.expiryAlert`](/guide/cards/events#card-expiryalert) – The card expires at the end of the next month; you can anticipate [Renewal](/guide/cards/renewal). [`card.update`](/guide/cards/events#card-update) – The card expired. | Permanent |
| `7` | `CUSTOM_LOCK` | Secondary lock; the card is locked and cannot be used. This is the same mechanism as `LOCK`, providing you more flexibility to manage cards (e.g., reporting reasons, preventing cardholders to unlock the card themselves). | Reversible |
**Caution – A lost or stolen card can't be reactivated**
If the cardholder wants a replacement card, a new card will have to be ordered.
### Request example
You can use the following request to change the card lock status, with the `cardId` as a path parameter and the `lockStatus` in the body.
```bash [CURL]
curl -X PUT '{baseUrl}/v1/cards/{cardId}/LockUnlock' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json'
```
Here is an example of `{payload}` which specifies a `lockStatus` of `2`, declaring the Card as `LOST` and locking it permanently.
```json [JSON]
{
"lockStatus":2
}
```
Returns a Card object, with a `statusCode` attribute set to either `UNLOCK`, `LOCK`, `LOST`, `STOLEN`, `DESTROYED`, `CUSTOM_LOCK`.
```json [JSON] {7,9}
{
"cardId": 999894949,
"userId": 100198207,
"walletId": 2728965,
"publicToken": "105603415",
"cardTag": "string",
"statusCode": "LOST",
"isLive": 1,
"cancellationNumber": "19532590" // Generated for LOST & STOLEN Cards only
// [...] some attributes are hidden
}
```
Although you provide the `lockStatus` as an integer, it is returned as a plaintext value.
Treezor also sends a [`card.lockunlock`](./events#cardlockunlock) webhook.
## Card account selection
The Card Account Selection feature allows you to implement multi-wallet capabilities on a single card. For a given card, you can route each transaction to a different Wallet. This is particularly useful for centralizing various services (e.g., employee benefits and food vouchers) on a unique card.
**Configuration – Feature not enabled by default**
Please contact Treezor to activate the Card account selection feature.
Assigning the card to a Wallet can be done as often as you wish to, and either:
* **[Manually](#manual-selection)** – The user chooses the Wallet to debit prior to the transaction.
* **[Dynamically](#dynamic-selection)** – The [MDC](/guide/cards/transactions-rules-engine) or [external validation](/guide/cards/transactions-external-validation) feature selects the Wallet when the transaction is initiated.
This feature is only compatible with the following [types of Wallet](/guide/wallets/introduction): `9`, `10`, `15`.
**Information – The behavior is transparent in the transaction life cycle**
Even if the wallet assigned to the card changes, the wallet of a given card transaction remains the same during the whole transaction life cycle. The debited wallet value is available in the [`card.transaction`](./events-tx#card-transaction-events) webhook.
### Manual selection
In this case, the cardholder manually selects the Wallet to be debited before initiating the transaction.
#### Parameters
| Attribute | Type | Description |
| --- | --- | --- |
| `cardId` | query | The unique identifier of the card to assign. |
| `walletId` | integer | The unique identifier of the wallet to which the card is to be assigned. The wallet must have the same `userId` value as the card if the `walletTypeId` is `9` or `10`. |
#### Request example
```bash [CURL]
curl -X PUT '{baseUrl}/v1/cards/{cardId}/assignWallet' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"walletId":123456
}
```
Returns the Card object with the updated `walletId` value, and sends the [`card.assignwallet`](./events#card-assignwallet) webhook.
```json [JSON] {4}
{
"cardId": 999894949,
"userId": 100198207,
"walletId":123456,
"publicToken": "105603415",
"cardTag": "string",
"statusCode": "UNLOCK",
"isLive": 1,
// [...] some attributes are hidden
}
```
### Dynamic selection
You can take advantage of the [Multi-Criteria Dynamic Card (MDC)](/guide/cards/transactions-rules-engine) or the [external validation](/guide/cards/transactions-external-validation) feature to automatically debit the relevant Wallet when a transaction is initiated.
The steps are the following:
1. The User initiates a payment with their card.
2. The [Multi-Criteria Dynamic Card (MDC)](/guide/cards/transactions-rules-engine) rules engine or your [external validation](/guide/cards/transactions-external-validation) system determines the wallet to use.
3. The Wallet is debited by the card transaction.
### Specific cases
#### Offline transactions
When a transaction occurs offline, there is no information regarding the assigned Wallet yet. In that case, the last assigned Wallet is debited when using manual selection.
When relying on MDC or external authorization for dynamic selection though, you can create rules for the relevant wallet to be selected for offline transactions.
#### Recurring transactions
For recurring transactions, the same Wallet is debited as the initial transaction.
## Change PIN
If a Card is in the `UNLOCK` [status](#card-/guide/cards/introduction#card-status-statuscode) and not [PIN-locked](#unlock-pin), you can define its PIN code. There are 2 ways to proceed:
| Context | Endpoint | Usage |
| --- | --- | --- |
| **[Without the previous PIN](#without-the-previous-pin)** | [`/v1/cards/{cardId}/setPIN`](/api-reference/api-endpoints.html#tag/Cards/setPin){target="\_self"}| Machine-oriented |
| **[Requiring the previous PIN](#with-the-previous-pin)** | [`/v1/cards/{cardId}/changePIN`](/api-reference/api-endpoints.html#tag/Cards/changePin){target="\_self"} | End user-oriented |
| Context | Endpoint | Usage |
| --- | --- | --- |
| **[Without the previous PIN](#without-the-previous-pin)** | [`/cards/{cardId}/setPIN`](/api-reference/pci-dss-dev.html#tag/Cards/putSetPin){target="\_self"}| Machine-oriented |
| **[Requiring the previous PIN](#with-the-previous-pin)** | [`/cards/{cardId}/changePIN`](/api-reference/pci-dss-dev.html#tag/Cards/putChangePin){target="\_self"} | End user-oriented |
Once set, you mustn't store the PIN code on your infrastructure.
You cannot retrieve a PIN code using the Treezor API unless you have migrated to the [PCI DSS services](./pci-dss). In such case, you can use the [`/cards/{cardId}/pin`](/api-reference/pci-dss-dev.html#tag/Cards/getPIN){target="\_self"} endpoint.
We recommend you let your end users choose their PIN code when ordering a new card.
### End user ATM action required
When changing the PIN code via the API, there is no immediate way to relay the information to the physical card. **The cardholder must make a withdrawal or balance inquiry at an ATM** for the change to take effect.
This method works even if the Card program doesn't include withdrawals. Indeed, a rejected withdrawal updates the card too.
### Without the previous PIN
This is the initial situation upon Card creation.
#### Parameters
In addition to the `cardId` passed as a path parameter, the following parameters are required.
| Attribute | Type | Description |
| --- | --- | --- |
| `newPIN` | string | The new PIN code of the card. Must be a string to allow for leading zeroes. |
| `confirmPIN` | string | Confirmation of the new PIN code of the card. Must be a string to allow for leading zeroes. |
#### Request example
```bash [CURL]
curl -X PUT '{baseUrl}/v1/cards/{cardId}/setPIN' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"newPIN": "1234",
"confirmPIN": "1234"
}
```
Returns a Card object and sends the [`card.setpin`](./events#card-setpin) webhook.
```json [JSON]
{
"cards": [
{
"cardId": 999994169,
"userId": 100642533,
"walletId": 3151814,
"walletCardtransactionId": 3159200,
"mccRestrictionGroupId": 0,
"merchantRestrictionGroupId": 0,
"countryRestrictionGroupId": 0,
"publicToken": "105501272",
"cardTag": "black",
"statusCode": "UNLOCK",
"isLive": 0,
"pinTryExceeds": 0,
"maskedPan": "548821******6605",
"embossedName": "ALEX OAK",
"expiryDate": "2027-07-31",
"CVV": "370",
"startDate": "2024-07-24",
"endDate": "0000-00-00",
"countryCode": "FR",
"currencyCode": "EUR",
"lang": null,
"deliveryTitle": "M",
"deliveryLastname": "OAK",
"deliveryFirstname": "ALEX",
"deliveryAddress1": "07323 WOODLANE",
"deliveryAddress2": "",
"deliveryAddress3": "",
"deliveryCity": "PARIS",
"deliveryPostcode": "75017",
"deliveryCountry": "FR",
"mobileSent": "+336XXXXXXXX",
"limitsGroup": "TRZ-VL-001",
"permsGroup": "TRZ-CU-012",
"cardDesign": "1234",
"virtualConverted": 0,
"physical": 0,
"optionAtm": 0,
"optionForeign": 1,
"optionOnline": 1,
"optionNfc": 1,
"limitAtmYear": 0,
"limitAtmMonth": 0,
"limitAtmWeek": 2000,
"limitAtmDay": 1000,
"limitAtmAll": 0,
"limitPaymentYear": 0,
"limitPaymentMonth": 0,
"limitPaymentWeek": 3000,
"limitPaymentDay": 2000,
"limitPaymentAll": 0,
"paymentDailyLimit": 500.0,
"totalAtmYear": 0,
"totalAtmMonth": 0,
"totalAtmWeek": null,
"totalAtmDay": null,
"totalAtmAll": 0,
"totalPaymentYear": 0,
"totalPaymentMonth": 0,
"totalPaymentWeek": null,
"totalPaymentDay": null,
"totalPaymentAll": 0,
"createdBy": 929252,
"createdDate": "2024-07-24 11:13:15",
"modifiedBy": 929252,
"modifiedDate": "2024-09-13 15:13:26",
"totalRows": null,
"designCode": null,
"cardLanguages": "",
"eventName": "Name of the Wallet",
"eventAlias": "name-of-the-wallet-669f4218dfbff",
"restrictionGroupLimits": null,
"cancellationNumber": "",
"metadata": null,
"renewalDate": null,
"renewalType": null,
"originalCardId": null,
"logoId": "",
"logoBackId": "",
"packageId": "",
"customizeInfo": "",
"letterCustomizedInfo": "",
"freeCustomizedInfo": "",
"deliveryMethod": null,
"pinMailer": null,
"batchDeliveryId": null,
"sendToParent": 0,
"isTemporary": false
}
]
}
```
#### Parameters
In addition to the `cardId` passed as a path parameter, the following parameters are required.
| Attribute | Type | Description |
| --- | --- | --- |
| `userId` | string | The unique identifier of the cardholder. |
| `newPIN` | string | The new PIN code of the card. Must be a string to allow for leading zeroes. |
| `confirmPIN` | string | Confirmation of the new PIN code of the card. Must be a string to allow for leading zeroes. |
| `sca` | string | The `scaProof` (required if not in delegated mode). |
#### Request example
```bash [CURL]
curl -X PUT '{pciBaseUrl}/cards/{cardId}/setPIN' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"userId": "100642533",
"newPIN": "1234",
"confirmPIN": "1234",
"sca": "eyJh_UxfQ.nNIH_n9kA"
}
```
Returns an HTTP 204 No Content and sends the [`card.setpin`](./events#card-setpin) webhook.
#### Locked PIN error
If the card is [PIN-locked](#unlock-pin) (`pinTryExceeds` value set to `1`), the request fails with a 400 HTTP status code and the following error.
```json [JSON]
{
"errors": [
{
"type": "invalid_request",
"code": "input_validation_error",
"message": "Card blocked.",
"docUrl": "https://docs.treezor.com/guide/api-basics/response-codes.html#error-attributes",
"requestId": "20ba6d1c-f903-4ab8-918b-341ee13b59b8"
}
]
}
```
You must [PIN Unlock](#unlock-pin) before setting the PIN code.
### With the previous PIN
#### Parameters
In addition to the `cardId` passed as a path parameter, the following parameters are required.
| Attribute | Type | Description |
| --- | --- | --- |
| `currentPIN` | string | The current PIN code of the card. Must be a string to allow for leading zeroes. |
| `newPIN` | string | The new PIN code of the card. Must be a string to allow for leading zeroes. |
| `confirmPIN` | string | Confirmation of the new PIN code of the card. Must be a string to allow for leading zeroes. |
#### Request example
```bash [CURL]
curl -X PUT '{baseUrl}/v1/cards/{cardId}/ChangePIN' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"currentPIN": "4321",
"newPIN": "1234",
"confirmPIN": "1234"
}
```
Returns a Card object and sends the [`card.changepin`](./events#card-changepin) webhook.
```json [JSON]
{
"cards": [
{
"cardId": 999994169,
"userId": 100642533,
"walletId": 3151814,
"walletCardtransactionId": 3159200,
"mccRestrictionGroupId": 0,
"merchantRestrictionGroupId": 0,
"countryRestrictionGroupId": 0,
"publicToken": "105501272",
"cardTag": "black",
"statusCode": "UNLOCK",
"isLive": 0,
"pinTryExceeds": 0,
"maskedPan": "548821******6605",
"embossedName": "ALEX OAK",
"expiryDate": "2027-07-31",
"CVV": "370",
"startDate": "2024-07-24",
"endDate": "0000-00-00",
"countryCode": "FR",
"currencyCode": "EUR",
"lang": null,
"deliveryTitle": "M",
"deliveryLastname": "OAK",
"deliveryFirstname": "ALEX",
"deliveryAddress1": "07323 WOODLANE",
"deliveryAddress2": "",
"deliveryAddress3": "",
"deliveryCity": "PARIS",
"deliveryPostcode": "75017",
"deliveryCountry": "FR",
"mobileSent": "+336XXXXXXXX",
"limitsGroup": "TRZ-VL-001",
"permsGroup": "TRZ-CU-012",
"cardDesign": "1234",
"virtualConverted": 0,
"physical": 0,
"optionAtm": 0,
"optionForeign": 1,
"optionOnline": 1,
"optionNfc": 1,
"limitAtmYear": 0,
"limitAtmMonth": 0,
"limitAtmWeek": 2000,
"limitAtmDay": 1000,
"limitAtmAll": 0,
"limitPaymentYear": 0,
"limitPaymentMonth": 0,
"limitPaymentWeek": 3000,
"limitPaymentDay": 2000,
"limitPaymentAll": 0,
"paymentDailyLimit": 500.0,
"totalAtmYear": 0,
"totalAtmMonth": 0,
"totalAtmWeek": null,
"totalAtmDay": null,
"totalAtmAll": 0,
"totalPaymentYear": 0,
"totalPaymentMonth": 0,
"totalPaymentWeek": null,
"totalPaymentDay": null,
"totalPaymentAll": 0,
"createdBy": 929252,
"createdDate": "2024-07-24 11:13:15",
"modifiedBy": 929252,
"modifiedDate": "2024-09-13 15:13:26",
"totalRows": null,
"designCode": null,
"cardLanguages": "",
"eventName": "Name of the Wallet",
"eventAlias": "name-of-the-wallet-669f4218dfbff",
"restrictionGroupLimits": null,
"cancellationNumber": "",
"metadata": null,
"renewalDate": null,
"renewalType": null,
"originalCardId": null,
"logoId": "",
"logoBackId": "",
"packageId": "",
"customizeInfo": "",
"letterCustomizedInfo": "",
"freeCustomizedInfo": "",
"deliveryMethod": null,
"pinMailer": null,
"batchDeliveryId": null,
"sendToParent": 0,
"isTemporary": false
}
]
}
```
#### Parameters
In addition to the `cardId` passed as a path parameter, the following parameters are required.
| Attribute | Type | Description |
| --- | --- | --- |
| `userId` | string | The unique identifier of the cardholder. |
| `currentPIN` | string | The current PIN code of the card. Must be a string to allow for leading zeroes. |
| `newPIN` | string | The new PIN code of the card. Must be a string to allow for leading zeroes. |
| `confirmPIN` | string | Confirmation of the new PIN code of the card. Must be a string to allow for leading zeroes. |
| `sca` | string | The `scaProof` (required if not in delegated mode). |
#### Request example
```bash [CURL]
curl -X PUT '{pciBaseUrl}/cards/{cardId}/ChangePIN' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"userId": "100642533",
"currentPIN": "4321",
"newPIN": "1234",
"confirmPIN": "1234",
"sca": "eyJh_UxfQ.nNIH_n9kA"
}
```
Returns an HTTP 204 No Content and sends the [`card.changepin`](./events#card-changepin) webhook.
#### Locked PIN error
If the card is [PIN-locked](#unlock-pin) (`pinTryExceeds` value set to `1`), the request fails with a 400 HTTP status code and the following error.
```json [JSON]
{
"errors": [
{
"type": "invalid_request",
"code": "input_validation_error",
"message": "Card blocked.",
"docUrl": "https://docs.treezor.com/guide/api-basics/response-codes.html#error-attributes",
"requestId": "20ba6d1c-f903-4ab8-918b-341ee13b59b8"
}
]
}
```
You must [PIN Unlock](#unlock-pin) the card before changing the PIN code.
## Unlock PIN
Entering 3 erroneous PIN codes in a row blocks the PIN and sets the `pinTryExceeds` to `1`.
As the card is blocked on the server side, you can unblock it instantaneously using a dedicated endpoint. When unlocking a PIN, the PIN code remains unchanged.
**Note – You can't change a locked PIN**
If the PIN is blocked you **must** unlock the PIN before being able to [change it](#change-pin).
### Request example
Only the `cardId` passed as a path parameter is required to use the following request.
```bash [CURL]
curl -X PUT '{baseUrl}/v1/cards/{cardId}/UnblockPIN' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json'
```
Returns a Card object and sends a [`card.unblockpin`](./events#cardunblockpin) webhook with the `pinTryExceeds` parameter set to `0`.
```json [JSON] {15}
{
"cards": [
{
"cardId": 999994169,
"userId": 100642533,
"walletId": 3151814,
"walletCardtransactionId": 3159200,
"mccRestrictionGroupId": 0,
"merchantRestrictionGroupId": 0,
"countryRestrictionGroupId": 0,
"publicToken": "105501272",
"cardTag": "black",
"statusCode": "UNLOCK",
"isLive": 0,
"pinTryExceeds": 0,
"maskedPan": "548821******6605",
"embossedName": "ALEX OAK",
"expiryDate": "2027-07-31",
"CVV": "370",
"startDate": "2024-07-24",
"endDate": "0000-00-00",
"countryCode": "FR",
"currencyCode": "EUR",
"lang": null,
"deliveryTitle": "M",
"deliveryLastname": "OAK",
"deliveryFirstname": "ALEX",
"deliveryAddress1": "07323 WOODLANE",
"deliveryAddress2": "",
"deliveryAddress3": "",
"deliveryCity": "PARIS",
"deliveryPostcode": "75017",
"deliveryCountry": "FR",
"mobileSent": "+336XXXXXXXX",
"limitsGroup": "TRZ-VL-001",
"permsGroup": "TRZ-CU-012",
"cardDesign": "1234",
"virtualConverted": 0,
"physical": 0,
"optionAtm": 0,
"optionForeign": 1,
"optionOnline": 1,
"optionNfc": 1,
"limitAtmYear": 0,
"limitAtmMonth": 0,
"limitAtmWeek": 2000,
"limitAtmDay": 1000,
"limitAtmAll": 0,
"limitPaymentYear": 0,
"limitPaymentMonth": 0,
"limitPaymentWeek": 3000,
"limitPaymentDay": 2000,
"limitPaymentAll": 0,
"paymentDailyLimit": 500.0,
"totalAtmYear": 0,
"totalAtmMonth": 0,
"totalAtmWeek": null,
"totalAtmDay": null,
"totalAtmAll": 0,
"totalPaymentYear": 0,
"totalPaymentMonth": 0,
"totalPaymentWeek": null,
"totalPaymentDay": null,
"totalPaymentAll": 0,
"createdBy": 929252,
"createdDate": "2024-07-24 11:13:15",
"modifiedBy": 929252,
"modifiedDate": "2024-09-13 15:13:26",
"totalRows": null,
"designCode": null,
"cardLanguages": "",
"eventName": "Name of the Wallet",
"eventAlias": "name-of-the-wallet-669f4218dfbff",
"restrictionGroupLimits": null,
"cancellationNumber": "",
"metadata": null,
"renewalDate": null,
"renewalType": null,
"originalCardId": null,
"logoId": "",
"logoBackId": "",
"packageId": "",
"customizeInfo": "",
"letterCustomizedInfo": "",
"freeCustomizedInfo": "",
"deliveryMethod": null,
"pinMailer": null,
"batchDeliveryId": null,
"sendToParent": 0,
"isTemporary": false
}
]
}
```
## Unlock CVV
The Card [CVV](/guide/overview/glossary#card-verification-code-cvc) can get locked if the cardholder enters multiple times in a row an erroneous CVV while attempting an e-commerce payment. The number of attempts is configurable, and is usually set to 3 or 5.
When this happens, the [`cardtransaction.create`](/guide/cards/events#declined-insufficient-funds) webhook contains an [`authorizationNote`](/guide/cards/authorization-notes) valued to `DR: CVC2 tries exceeded`.
As the card is blocked on the server side, you can unblock it instantaneously using a dedicated endpoint.
```bash [CURL]
curl -X PUT '{baseUrl}/v1/cards/{cardId}/unblockcvc2' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json'
```
It returns a 204 HTTP response with the following description: `successfully unblocked`. Also sends a [`card.unblockcvc2`](./events#card-unblockcvc2) webhook.
**Tip – Unlocking only available on Connect**
If you haven't migrated to [Connect](/guide/overview/getting-started#treezor-api), or if the feature is not yet available to you, you must [open a ticket](https://treezor.zendesk.com/hc/en-us/articles/4403978479634-How-to-create-a-Zendesk-ticket) to unlock a CVV.
## Unlock 3DS
The [3DS](/guide/overview/glossary#_3d-secure-3ds) feature of a Card can get locked if the cardholder fails 3 times the 3DS authentication using One Time Password while attempting an e-commerce payment.
When using the [Strong Customer Authentication](/guide/strong-customer-authentication/introduction) instead of One Time Password, a failure to authenticate doesn't increment the 3DS failure count and will not lock the 3DS feature.
If the SCA feature [cannot be used](/guide/cards/transactions-authentication#payload) and the fallback to One Time Password via SMS is used, then a locking can still occur.
To unlock the 3DS feature, you must [open a ticket](https://treezor.zendesk.com/hc/en-us/articles/4403978479634-How-to-create-a-Zendesk-ticket) as no API endpoint currently allows you to unlock the 3DS feature.
## Regenerate
If your brand changes its graphical identity (e.g., new logo, colors, layout, etc.), you can ask Treezor to set up a new card design, and then re-generate Virtual Card images without altering their actual PAN, CVC, or expiration date.
Endpoint: [`/v1/cards/{cardId}/Regenerate`](/api-reference/api-endpoints.html#tag/Cards/regenerateCard){target="\_self"}
```bash [CURL]
curl -X PUT '{baseUrl}/v1/cards/{cardId}/Regenerate' \
--header 'Authorization: Bearer {accessToken}'
```
Returns the Card object and sends a [`card.regenerate`](./events#cardregenerate) webhook.
```json [JSON]
{
"cards": [
{
"cardId": 999994169,
"userId": 100642533,
"walletId": 3151814,
"walletCardtransactionId": 3159200,
"mccRestrictionGroupId": 0,
"merchantRestrictionGroupId": 0,
"countryRestrictionGroupId": 0,
"publicToken": "105501272",
"cardTag": "black",
"statusCode": "UNLOCK",
"isLive": 0,
"pinTryExceeds": 0,
"maskedPan": "548821******6605",
"embossedName": "ALEX OAK",
"expiryDate": "2027-07-31",
"CVV": "370",
"startDate": "2024-07-24",
"endDate": "0000-00-00",
"countryCode": "FR",
"currencyCode": "EUR",
"lang": null,
"deliveryTitle": "M",
"deliveryLastname": "OAK",
"deliveryFirstname": "ALEX",
"deliveryAddress1": "07323 WOODLANE",
"deliveryAddress2": "",
"deliveryAddress3": "",
"deliveryCity": "PARIS",
"deliveryPostcode": "75017",
"deliveryCountry": "FR",
"mobileSent": "+336XXXXXXXX",
"limitsGroup": "TRZ-VL-001",
"permsGroup": "TRZ-CU-012",
"cardDesign": "1234",
"virtualConverted": 0,
"physical": 0,
"optionAtm": 0,
"optionForeign": 1,
"optionOnline": 1,
"optionNfc": 1,
"limitAtmYear": 0,
"limitAtmMonth": 0,
"limitAtmWeek": 2000,
"limitAtmDay": 1000,
"limitAtmAll": 0,
"limitPaymentYear": 0,
"limitPaymentMonth": 0,
"limitPaymentWeek": 3000,
"limitPaymentDay": 2000,
"limitPaymentAll": 0,
"paymentDailyLimit": 500.0,
"totalAtmYear": 0,
"totalAtmMonth": 0,
"totalAtmWeek": null,
"totalAtmDay": null,
"totalAtmAll": 0,
"totalPaymentYear": 0,
"totalPaymentMonth": 0,
"totalPaymentWeek": null,
"totalPaymentDay": null,
"totalPaymentAll": 0,
"createdBy": 929252,
"createdDate": "2024-07-24 11:13:15",
"modifiedBy": 929252,
"modifiedDate": "2024-09-13 15:13:26",
"totalRows": null,
"designCode": null,
"cardLanguages": "",
"eventName": "Name of the Wallet",
"eventAlias": "name-of-the-wallet-669f4218dfbff",
"restrictionGroupLimits": null,
"cancellationNumber": "",
"metadata": null,
"renewalDate": null,
"renewalType": null,
"originalCardId": null,
"logoId": "",
"logoBackId": "",
"packageId": "",
"customizeInfo": "",
"letterCustomizedInfo": "",
"freeCustomizedInfo": "",
"deliveryMethod": null,
"pinMailer": null,
"batchDeliveryId": null,
"sendToParent": 0,
"isTemporary": false
}
]
}
```
Endpoint: [`/cards/{cardId}/cardImage`](/api-reference/pci-dss-dev.html#tag/Cards/postCardImage){target="\_self"}
```bash [CURL]
curl -X POST '{pciBaseUrl}/cards/{cardId}/cardImage' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"userId": "100642533"
}
```
Returns an HTTP 204 No Content if successful.
---
---
url: /guide/users/modifications.md
description: >-
Technical guide for updating and deleting users via the Treezor API. Includes
required parameters, request structure, and response examples.
---
# Modification
Users' declarative data evolve as they use your services. It's not uncommon to have to update the user's address or contact information for instance.
**For [KYC-validated](/guide/user-verification/introduction) Users, most modifications trigger a new KYC review.**
**Tip – Attribute updates that don't result in KYC review**
`address3`, `phone`, `mobile`, `activityOutsideEu`, `economicSanctions`, `residentCountriesSanctions`, `involvedSanctions`, `timezone`.
## Updating
Endpoint: [`/v1/users/{userId}`](/api-reference/api-endpoints.html#tag/Users/putUser){target="\_self"}
Here is a `{payload}` example:
```json [JSON]
{
"address1": "new address",
"address2": "new address continuated",
"postcode": "75001",
"city": "Paris"
}
```
Returns the updated User object with the modified fields.
```json [JSON] {19-22}
{
"users": [
{
"userId": 100147235,
"userTypeId": 1,
"userStatus": "VALIDATED",
"userTag": "user test Treezor",
"parentUserId": 0,
"parentType": "",
"controllingPersonType": 0,
"employeeType": 0,
"specifiedUSPerson": 0,
"title": "MX",
"firstname": "Alex",
"lastname": "Oak",
"middleNames": "",
"birthday": "1982-05-31",
"email": "190john.smith725@test.com",
"address1": "new address",
"address2": "new address continuated",
"postcode": "75001",
"city": "Paris",
// [...] some attributes are hidden
}
]
}
```
Treezor also sends a [`user.update`](./events#user-update) webhook, and a [`card.update`](/guide/cards/events#card-update) webhook if the cardholder's information was modified.
## Deletion
For legal reasons, Users cannot be deleted. They are permanently “Canceled” instead.
**Prerequisites – To Deactivate a User**
* The Balance of all of their Wallets must be `0`
* No card transaction authorization can be pending
To cancel a User you can use the following request, and provide an `origin` which can either be:
* `OPERATOR`– When you are at the origin of the deactivation.
* `USER` – When the end user is at the origin of the deactivation.
Endpoint: [`/v1/users/{userId}`](/api-reference/api-endpoints.html#tag/user/deleteUser){target="\_self"}
Here is an example of `{payload}`:
Returns a User object if successful, with the `userStatus` set to `CANCELED`:
Treezor also sends a [`user.cancel`](./events#user-cancel) webhook.
Once deleted, no action can be made on the user. You can re-create the user, using the same email if needed, as the rule for [unique emails](./introduction#using-unique-and-valid-email-addresses) doesn't apply to canceled user.
---
---
url: /guide/wallets/modification.md
description: >-
Technical guide for updating wallets via the Treezor API. Includes required
parameters, request structure, and response examples.
---
# Modification
## Update Wallet
### Parameters
Below are the specific set of information that can be updated.
| Attribute | Type | Description |
|--- |--- |--- |
| `walletTypeId` | integer | Either `9` or `10`. Available [types](/guide/wallets/introduction#types-of-wallets) depend on your agreement with Treezor. |
| `walletTag` | integer | Custom attribute to use as you see fit. Learn more in the [Object tags](/guide/api-basics/objects-tags#objects-tags) article. Max length: 250 characters Format: hc characters and `/` `!` `-` `_` `.` `*` `'` `(` `)` |
| `eventName` | string | The name of the Wallet. |
| `eventMessage` | string | Can be used to describe the Wallet. |
**Tip – The Wallet type is editable up to the first operation**
Once the first transaction occurred, the `walletTypeId` can no longer be updated.
**API – API Reference available**
For a complete list of Wallet attributes, check the [Wallets](/api-reference/api-endpoints.html#tag/Wallets){target="\_self"} section of the API Reference.
### Request
Endpoint: [`/v1/wallets/{walletId}`](/api-reference/api-endpoints.html#tag/Wallets/putWallet){target="\_self"}
```bash [CURL]
curl -X PUT '{baseUrl}/v1/wallets/{walletId}' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
```
Here is an example of `{payload}`:
```json [JSON]
{
"walletTag": "Updated Tag",
"eventName": "Main Account",
"eventMessage": "My Payment Account Wallet"
}
```
Returns the Wallet object with the updated information.
```json [JSON] {6}
{
"wallets": [
{
"walletId": 2585102,
"walletTypeId": 10,
"walletStatus": "VALIDATED",
"codeStatus": 120005,
"informationStatus": "",
"walletTag": "Updated Tag",
"userId": 100060463,
"userLastname": "Alex",
"userFirstname": "Oak",
"jointUserId": 0,
"tariffId": 136,
"eventName": "Main Account",
"eventAlias": "main-account-659d1cdd12c892024-01-09 11:16:59",
"eventDate": "2024-01-16",
"eventMessage": "My Payment Account Wallet",
"eventPayinStartDate": "2024-01-09",
"eventPayinEndDate": "0000-00-00",
"contractSigned": 0,
"bic": "TRZOFR21XXX",
"iban": "FR7616798000010000XXXXXXXXX",
"urlImage": "",
"currency": "EUR",
"createdDate": "2024-01-09 11:15:57",
"modifiedDate": "2024-10-09 11:16:59",
"payinCount": 0,
"payoutCount": 0,
"transferCount": 0,
"solde": 0,
"authorizedBalance": 0,
"totalRows": 1,
"country": "FR"
}
]
}
```
Treezor also sends the [`wallet.update`](/guide/wallets/events#wallet-update) webhook.
## Delete Wallet
For safety and legal reasons Wallets cannot be deleted, they are **permanently deactivated** instead.
Once deactivated, no operations can be made to or from the Wallet.
**Prerequisites – To Deactivate a Wallet**
* The Balance must be equal to `0`
* No operations can be pending
### Parameters
| Attribute | Type | Description |
|--- |--- |--- |
| `id` | integer | The unique identifier of the Wallet to deactivate. |
| `origin` | string | The origin of the request for cancelling the Wallet, which can be one of the following: `OPERATOR` – When **you** are at the origin of the deactivation.`USER` – When the **end user** is at the origin of the deactivation.|
### Request
Endpoint: [`/v1/wallets/{walletId}`](/api-reference/api-endpoints.html#tag/Wallets/deleteWallet){target="\_self"}
```bash [CURL]
curl -X DELETE '{baseUrl}/v1/wallets/{walletId}?origin={origin}' \
--header 'Authorization: Bearer {accessToken}'
```
Returns the Wallet object with the `walletStatus` attribute set to `CANCELED`.
```json [JSON] {6}
{
"wallets": [
{
"walletId": 2585102,
"walletTypeId": 10,
"walletStatus": "CANCELED",
"codeStatus": 120003,
"informationStatus": "",
"walletTag": "",
"userId": 100060463,
"userLastname": "Alex",
"userFirstname": "Oak",
"jointUserId": 0,
"tariffId": 136,
"eventName": "Account 1",
"eventAlias": "test-delete-659d1cdd12c892024-01-09 11:16:59",
"eventDate": "2024-01-16",
"eventMessage": "",
"eventPayinStartDate": "2024-01-09",
"eventPayinEndDate": "0000-00-00",
"contractSigned": 0,
"bic": "TRZOFR21XXX",
"iban": "FR7616798000010000XXXXXXXXX",
"urlImage": "",
"currency": "EUR",
"createdDate": "2024-01-09 11:15:57",
"modifiedDate": "2024-01-09 11:16:59",
"payinCount": 0,
"payoutCount": 0,
"transferCount": 0,
"solde": 0,
"authorizedBalance": 0,
"totalRows": 1,
"country": "FR"
}
]
}
```
Treezor also sends the [`wallet.cancel`](/guide/wallets/events#wallet-cancel) webhook.
---
---
url: /guide/users/error-codes.md
description: >-
Troubleshoot and handle user-related issues using the Treezor API's complete
list of error codes, messages, and their corresponding meanings.
---
# Errors
**Caution – Only the legacy API sends the error code in HTTP errors**
When handling errors with Connect, only the `message` attribute is returned.
## User errors
The following API errors can be encountered when dealing with users.
| Code | Message |
|:---:|---|
| `28` | User's assets are freezed |
| `10012` | User Canceled |
| `10023` | UserId is in pending state |
| `10025` | UserId is in invalid state |
| `11002` | Unable to update the user. User does not exist |
| `11008` | The email is required. |
| `11009` | The email is not valid. |
| `11014` | Impossible to cancel, the user does not exist. |
| `11015` | Impossible to cancel, the origin not specified or incorrect. |
| `11016` | Impossible to cancel user, he is already in canceled status. |
| `11017` | Impossible to cancel user. Wrong userId. |
| `11018` | Impossible to cancel user. Database error |
| `11019` | The email is already used |
| `11020` | Impossible to create user. The parent type must be provided |
| `11021` | Impossible to create user. Value available for Parent Type : shareholder, employee, leader |
| `11022` | Impossible to create user. Parent User does not exist |
| `11023` | Impossible to update the kyc review. User does not exist. |
| `11038` | userTypeId is required. |
| `11041` | user does not exist. |
| `11042` | kycReview is required. |
| `11043` | kycReview value is incorrect. |
| `11044` | kycReviewComment is required. |
| `11046` | userIdKyc is required. |
| `11047` | user does not exist. |
| `11048` | kycLevel is required. |
| `11049` | kycLevel value is incorrect. |
| `11053` | legalForm does not exist |
| `11054` | legalNumberOfEmployeeRange is not correct. Values authorized : |
| `11055` | legalNetIncomeRange is not correct. Values authorized : |
| `11056` | legalAnnualTurnOver is not correct. Values authorized : |
| `11057` | title is not correct. Values authorized |
| `11059` | birthCountry is not in the right format. Format ISO 3166-1 alpha-2 |
| `11061` | nationalityOther is not in the right format. Format ISO 3166-1 alpha-2 |
| `11062` | Impossible to update the kyc review. KYC entity is not created |
| `11063` | Impossible to update the kyc review. Phone number can not contains a space character. It can begin by the |
| `11077` | sci must be between 17 and 35 characters |
| `11078` | The language provided does not comply with ISO 639 (alpha-2) norm. |
| `11080` | The field 'personalAssets' must have a value compliant with the documentation |
| `11081` | The format must follow the norm : ISO-3166-1 alpha-2 |
| `11085` | The field 'personalAssets' is provided but the value does not comply with provided enum values |
| `11086` | User is not found in the database |
| `11087` | Wrong format for phone number. |
| `11088` | Wrong format for mobile number. |
| `11089` | User's address1 has a line breaker |
| `11090` | User's address2 has a line breaker |
| `11092` | User's address3 has a line breaker |
| `11093` | User is not found in the database |
| `11094` | User is not found in the database |
| `11096` | employeeType is invalid |
| `11097` | controllingPersonType is invalid |
| `11100` | specifiedUSPerson is provided but are not between 0 and 1 |
| `11101` | entityType is invalid |
| `11102` | activityOutsideEu is provided but are not between 0 and 1 |
| `11103` | economicSanctions is provided but are not between 0 and 1 |
| `11104` | residentCountriesSanctions is provided but are not between 0 and 1 |
| `11105` | involvedSanctions is provided but are not between 0 and 1 |
| `11109` | timezone is not in the right format. Format type tz database. Ex : Europe/Paris |
| `11110` | User's city has a line breaker |
| `11111` | User's country has a line breaker |
| `11112` | Error during the user's cards update, please try again later |
| `11113` | Wrong value of legalForm for user type NATURAL PERSON, legalForm can only be 1000. |
| `11114` | BirthDepartementCode is not in the right format. Format type : 5 digits. Ex : 75008 |
| `11115` | legalRegistrationDate Year is too old (before 1800) |
| `11116` | legalForm is not valid. |
| `11117` | User's email is too long, it must not exceed 50 characters |
| `11118` | User's secondary address1 has a line breaker |
| `11119` | User's secondary address2 has a line breaker |
| `11120` | occupation field must be a string |
| `11121` | The format must follow the norm : ISO-3166-1 alpha-2 |
| `11126` | User's secondary address3 has a line breaker |
| `11127` | isOnStockExchange is provided but are not between 0 and 1 |
| `11128` | occupationType is not correct. Values authorized : self\_employed, public\_sector\_employees, private\_sector\_employees, retired\_people\_and\_students, without\_any\_professional\_activity |
| `11129` | sourceOfFunds is not correct. Values authorized : donation, inheritance, loan, lottery, pension, proceeds\_from\_investment, proceeds\_from\_sale, salary, saving |
| `11133` | Impossible to update Legal Freeze field. |
| `11134` | legalSectorType is not correct. Values authorized : NAF, NACE |
| `11135` | legalSector is not in the correct format for a legalSectorType code : NAF => \[0-9]\[0-9]\[0-9]\[0-9]\[A-Z] or NACE => \[0-9]\[0-9]\[0-9]\[0-9] |
| `11141` | Impossible to cancel user, pending card authorization. |
| `11141` | not a valid French city |
| `11142` | An error occurred while processing cancel request, aborting. |
| `11142` | incoherent French city and postcode |
| `11143` | not a valid French postcode |
| `11144` | A legal user can't give the firstname |
| `11145` | A legal user can't give the lastname |
| `11146` | A legal user can't give the middleNames |
| `11148` | firstname is too long |
| `11149` | lastname is too long |
| `11151` | firstname is invalid |
| `11152` | lastname is invalid |
| `11153` | middleNames is invalid |
| `11177` | Impossible to submit KYC request due to user status |
| `11181` | too many characters for the placeOfBirth field |
| `11182` | characters not accepted for placeOfBirth |
| `11183` | too many characters for an address field |
| `11184` | too many characters for an address2 field |
| `11185` | too many characters for an address3 field |
| `11186` | characters not accepted for an address field |
| `11187` | characters not accepted for an address2 field |
| `11188` | characters not accepted for an address3 field |
| `11189` | Birthday is not valid |
| `11191` | city or postCode does not exist |
| `11192` | city and postCode are not consistent |
| `11194` | A legal user can't give birthday |
| `11196` | legalName is not valid |
| `11197` | The legalName field is not applicable for NATURAL user |
| `11201` | The occupation field is not applicable for legal users |
| `11202` | occupation is not valid |
| `101209` | The distributionCountry must follow the ISO-3166-1 alpha-2 format |
| `101210` | The distributionCountry is required |
| `101211` | The DistributionCountry needs to be listed on the client side |
| `101212` | Client DistributionCountry is missing |
| `101302` | not an acceptable value for personalAssetsRange |
## User restriction errors
The following API errors can be encountered when dealing with [Restricted Users](/guide/users/restricted-users).
| Code | Message |
|:---:|---|
| `11064` | Impossible to Freeze Assets. userId is mandatory. |
| `11065` | Impossible to Freeze Assets. userIdFreezed does not exist. |
| `11066` | Impossible to Freeze Assets. isFrozen is mandatory. |
| `11067` | User's assets already freezed |
| `11068` | User's assets already not freezed |
| `11069` | Impossible to Freeze Assets. comment is mandatory. |
| `11130` | User's assets already legally frozen |
| `11131` | User's assets already not legally frozen |
| `11132` | IsLegalFrozen is provided but are not between 0 and 1 |
| `11133` | Impossible to update Legal Freeze field. |
## Tax Residence errors
| Code | Message |
|:---------:|------------------------------------------------------------------------------------------------------------|
| `101001` | taxPayerId and liabilityWaiver are both present |
| `101002` | taxResidence doesn't exist |
| `101003` | Country is not in the following format: ISO 3166-1 alpha 2 |
| `101004` | taxPayerId is invalid |
| `101005` | taxResidence is deleted, impossible to update this taxResidence |
| `101006` | taxPayerId and liabilityWaiwer at least one must be present |
| `101200` | liabilityWaiver cannot be false if taxPayerId is null or empty |
| `101201` | liabilityWaiver cannot be true if taxPayerId is not null or not empty |
| `101202` | a taxPayerId is required if country is US or a US territory |
| `101203` | the country must have a ISO 3166-1 alpha 2 format\
| `101204` | a tax residence in the US or a US teritory must be declared for the user if specifiedUSPerson = 1 |
| `101205` | specifiedUSPerson must be 1 if at least one of the following fields is the US or a US territory: nationality, nationalityOther, birthCountry, country, secondaryCountry |
| `101206` | specifiedUSPerson must be 1 if a tax residence was declared in the US or a US territory |
| `101207` | a user must have at least one tax residence declared |
| `101208` | The user can't waive liability, taxPayerId is required. |
| `101213` | The user can't waive liability, taxPayerId is required. |
| `101214` | An Italian taxPayerId already exists for this user. |
| `101215` | Updating the userId is not allowed. |
| `101216` | Updating the country is not allowed. |
| `101217` | Tax Residence can't be deleted, the taxPayerId is required for the associated User. |
| `101218` | The taxPayerId from the Tax Residence object is mandatory for Italian users. |
| `101303` | A tax residence already exists for this user in this country |
| `101304` | The \[firstName, lastName, birthday, title, placeOfBirth, birthCountry] fields are required to control TIN (taxPayerId) |
| `101308` | Impossible to update the Tax Residence due to user status |
---
---
url: /guide/users/events.md
description: >-
Reference a comprehensive list of user events for Treezor API webhooks,
detailing each event's structure and payload for integration.
---
# Events
This article lists the [Webhooks](/guide/webhooks/introduction) you may receive when regarding Users.
## User events
### `user.create`
```json [JSON]
{
"webhook": "user.create",
"object_payload": {
"users": [
{
"userId": "123456789",
"userTypeId": "1",
"userStatus": "VALIDATED",
"clientId": "222222",
"userTag": "97a25cae-8027-4cec-b6db-97b48b12345",
"parentUserId": "987654321",
"parentType": "leader",
"title": "",
"firstname": "Alex",
"lastname": "Oak",
"middleNames": "",
"birthday": "1970-01-06",
"email": "a.oak@texample.com",
"address1": "1600 Willow road",
"address2": "",
"address3": null,
"postcode": "75000",
"city": "Paris",
"state": "",
"country": "FR",
"countryName": "France",
"distributionCountry": "FR",
"phone": "+33606060606",
"mobile": "",
"nationality": "FR",
"nationalityOther": "",
"placeOfBirth": "Paris",
"birthCountry": "FR",
"secondaryAddress1": null,
"secondaryAddress2": null,
"secondaryAddress3": null,
"secondaryPostcode": null,
"secondaryCity": null,
"secondaryState": null,
"secondaryCountry": null,
"occupation": "director",
"incomeRange": "36-56", // Deprecated
"legalName": "",
"legalNameEmbossed": "",
"legalRegistrationNumber": "",
"legalTvaNumber": "",
"legalRegistrationDate": "0000-00-00",
"legalForm": "",
"legalShareCapital": "0",
"legalSector": "",
"legalAnnualTurnOver": "",
"legalNetIncomeRange": "",
"legalNumberOfEmployeeRange": "",
"effectiveBeneficiary": "0.00",
"position": "",
"personalAssets": "0-2", // Deprecated
"personalAssetsRange": "3",
"taxResidence": "", // Deprecated
"taxNumber": "", // Deprecated
"kycLevel": "0",
"kycReview": "0",
"kycReviewComment": "",
"isFreezed": "0",
"language": null,
"specifiedUSPerson": "0",
"employeeType": "0",
"entityType": "0",
"controllingPersonType": "3",
"activityOutsideEu": null,
"economicSanctions": null,
"residentCountriesSanctions": null,
"involvedSanctions": null,
"entitySanctionsQuestionnaire": null,
"sanctionsQuestionnaireDate": null,
"timezone": null,
"occupationType": null, // Deprecated
"isOnStockExchange": null,
"IsLegalFrozen": "0",
"sourceOfFunds": null,
"legalSectorType": null,
"createdDate": "2024-01-08 11:00:42",
"modifiedDate": "0000-00-00 00:00:00",
"codeStatus": "110009",
"informationStatus": "",
"sepaCreditorIdentifier": null,
"walletCount": "0",
"payinCount": "0",
"occupationCategory": "5",
"totalRows": "1",
"monthlyIncomeRange": "2"
}
]
},
"object_id": "100060123",
"object": "user",
"webhook_created_at": 17047116429943,
"webhook_id": "9a430c8b-1165-4ddf-a479-7a436f4d1234",
"object_payload_signature": "r+V/RP/0QkeH56QXfaRz5/QpcifrgnXrfZhHXXXXXXM="
}
```
### `user.update`
```json [JSON]
{
"webhook": "user.update",
"object_payload": {
"users": [
{
"userId": "123456789",
"userTypeId": "1",
"userStatus": "VALIDATED",
"clientId": "929253",
"userTag": "",
"parentUserId": null,
"parentType": null,
"title": "",
"firstname": "Sam",
"lastname": "Willow",
"middleNames": "",
"birthday": "0000-00-00",
"email": "swillow@example.com",
"address1": "",
"address2": "",
"address3": null,
"postcode": "",
"city": "",
"state": "",
"country": "",
"countryName": null,
"distributionCountry": null,
"phone": "",
"mobile": "",
"nationality": "FR",
"nationalityOther": "",
"placeOfBirth": "",
"birthCountry": "",
"secondaryAddress1": null,
"secondaryAddress2": null,
"secondaryAddress3": null,
"secondaryPostcode": null,
"secondaryCity": null,
"secondaryState": null,
"secondaryCountry": null,
"occupation": "director",
"incomeRange": "36-56", // Deprecated
"legalName": "",
"legalNameEmbossed": "",
"legalRegistrationNumber": "",
"legalTvaNumber": "",
"legalRegistrationDate": "0000-00-00",
"legalForm": "",
"legalShareCapital": "0",
"legalSector": "",
"legalAnnualTurnOver": "",
"legalNetIncomeRange": "",
"legalNumberOfEmployeeRange": "",
"effectiveBeneficiary": "0.00",
"position": "",
"personalAssets": "0-2", // Deprecated
"personalAssetsRange": "3",
"taxResidence": "", // Deprecated
"taxNumber": "", // Deprecated
"kycLevel": "0",
"kycReview": "0",
"kycReviewComment": "",
"isFreezed": "0",
"language": null,
"specifiedUSPerson": "0",
"employeeType": "0",
"entityType": "0",
"controllingPersonType": "3",
"activityOutsideEu": null,
"economicSanctions": null,
"residentCountriesSanctions": null,
"involvedSanctions": null,
"entitySanctionsQuestionnaire": null,
"sanctionsQuestionnaireDate": null,
"timezone": null,
"occupationType": null, // Deprecated
"isOnStockExchange": null,
"IsLegalFrozen": "0",
"sourceOfFunds": null,
"legalSectorType": null,
"createdDate": "2024-01-08 11:00:42",
"modifiedDate": "2024-02-08 11:00:42",
"codeStatus": "110009",
"informationStatus": "",
"sepaCreditorIdentifier": null,
"walletCount": "0",
"payinCount": "0",
"occupationCategory": "5",
"totalRows": "1",
"monthlyIncomeRange": "2"
}
]
},
"object_id": "100060789",
"object": "user",
"webhook_created_at": 17047224279950,
"webhook_id": "e77663b0-0c4f-49c3-be53-96f39001234",
"object_payload_signature": "abcDZ6MeUFRIjNoRDMN4KFjNJ0yR2Eok+MFrEq1k2/ho="
}
```
### `user.cancel`
```json [JSON]
{
"webhook": "user.cancel",
"object": "user",
"object_id": "100060789",
"object_payload": {
"users": [
{
"userId": "100060789",
"userTypeId": "1",
"userStatus": "CANCELED",
"clientId": "929252",
"userTag": "",
"parentUserId": null,
"parentType": null,
"title": "",
"firstname": "Sam",
"lastname": "Willow",
"middleNames": "",
"birthday": "0000-00-00",
"email": "swillow@example.com",
"address1": "",
"address2": "",
"address3": null,
"postcode": "",
"city": "",
"state": "",
"country": "",
"countryName": null,
"distributionCountry": null,
"phone": "",
"mobile": "",
"nationality": "FR",
"nationalityOther": "",
"placeOfBirth": "",
"birthCountry": "",
"secondaryAddress1": null,
"secondaryAddress2": null,
"secondaryAddress3": null,
"secondaryPostcode": null,
"secondaryCity": null,
"secondaryState": null,
"secondaryCountry": null,
"occupation": "director",
"incomeRange": "36-56", // Deprecated
"legalName": "",
"legalNameEmbossed": "",
"legalRegistrationNumber": "",
"legalTvaNumber": "",
"legalRegistrationDate": "0000-00-00",
"legalForm": "",
"legalShareCapital": "0",
"legalSector": "",
"legalAnnualTurnOver": "",
"legalNetIncomeRange": "",
"legalNumberOfEmployeeRange": "",
"effectiveBeneficiary": "0.00",
"position": "",
"personalAssets": "0-2", // Deprecated
"personalAssetsRange": "3",
"taxResidence": "", // Deprecated
"taxNumber": "", // Deprecated
"kycLevel": "0",
"kycReview": "0",
"kycReviewComment": "",
"isFreezed": "0",
"language": null,
"specifiedUSPerson": "0",
"employeeType": "0",
"entityType": "0",
"controllingPersonType": "3",
"activityOutsideEu": null,
"economicSanctions": null,
"residentCountriesSanctions": null,
"involvedSanctions": null,
"entitySanctionsQuestionnaire": null,
"sanctionsQuestionnaireDate": null,
"timezone": null,
"occupationType": null, // Deprecated
"isOnStockExchange": null,
"IsLegalFrozen": "0",
"sourceOfFunds": null,
"legalSectorType": null,
"createdDate": "2024-01-08 11:00:42",
"modifiedDate": "2024-02-08 11:00:42",
"codeStatus": "110006",
"informationStatus": "",
"sepaCreditorIdentifier": null,
"walletCount": "0",
"payinCount": "0",
"occupationCategory": "5",
"totalRows": "1",
"monthlyIncomeRange": "2"
}
]
},
"webhook_created_at": 17047241698952,
"webhook_id": "e4b40b36-db07-4af0-9c57-a4429fc01234",
"object_payload_signature": "1ABCDmDZMqv/pZ5gA9E1xq9CvivJp+K7ngW2hh7mvF0="
}
```
---
---
url: /guide/users/parent-children.md
description: >-
Technical guide for creating hierarchical relations between users, such as
family relationships and company structures (e.g., employer/employee,
company/shareholders). Includes required parameters, request structure, and
response examples.
---
# Parent-Children relations
Hierarchical relations can exist between *Users* (with a maximum depth of 2).
Parent-children relations can be used in [multiple scenarios](#use-cases). It is mandatory for:
* Family relations between [Physical Users](physical) (actual **parent** and **children**)
* Hierarchical relations between [Legal Entities](legal-entity) (*employer*, **parent**) and [Physical Users](physical) (*employee*, **children**)
* Ownership relations between [Legal Entities](legal-entity) (*company*, **parent**) and [Physical Users](physical) (*shareholders/legal representatives*, **children**)
It can optionally be used for other types of hierarchical relations related to your own business activity.
**Best practice – Make sure you create relevant hierarchical relations**
Always abide by the rules Treezor sets out for you. Otherwise, you may have technical or legal issues.
## Key attributes
The hierarchical relation to a parent User is defined by the following attributes:
| Attribute | Type | Description |
| --- | --- | --- |
| `parentUserId` | integer | The unique identifier of the User who is the parent of the current one. |
| `controllingPersonType` | integer | The type of relation with the parent, used with Shareholders and Legal representatives. See [list of values](#controlling-person-types-controllingpersontype) |
| `parentType` | string | The type of relationship between the parent and the current user. See [list of values](#parent-types-parenttype) |
| `effectiveBeneficiary` | integer | Percentage of ownership for an Effective Beneficiary, if applicable (`25` for 25%, `100` for 100%, etc.) |
| `employeeType` | integer | The type of employee. See [list of values](#employee-types-employeetype). |
### Parent Types (`parentType`)
The following parent types are available. They may take different meanings depending on [your implementation](#use-cases).
* `shareholder`
* `leader`
* `employee`
**Information – `parentType` can't be updated**
Once this value is set upon creating a user, it cannot be changed later on.
### Controlling Person Types (`controllingPersonType`)
* `0` **None**
* `1` **Shareholder** of a [Legal Entity](/guide/users/legal-entity)
* `2` **Other\_relationship**
* `3` **Legal representative** of a [Legal Entity](/guide/users/legal-entity)
### Employee Types (`employeeType`)
* `0` **None** (not an employee)
* `1` **Leader** (legal representative)
* `2` **Employee** (employee)
## How to use parent relations
It is recommended that you **create your users from the top** of the hierarchical tree (starting with the top-most parent) and take a look at [use cases](#use-cases).
The following example illustrates the creation of a company and one of its employees.
We first create **"Example Company"**, a [Legal Entity](/guide/users/legal-entity) that will act as the parent.
```bash [CURL]
curl -X POST '{baseUrl}/v1/users' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{
"userTypeId": 2,
"specifiedUSPerson": 0,
"legalName": "An Awesome Company"
# [...]
}'
```
Returns a User, with its `id` (111222333).
```json [JSON]
{
"userId": 111222333,
"userTypeId": 2, // 2 corresponds to Business Users
"parentUserId": null, // this User does not have a parent
"parentType": null, // as it does not have a parent, it cannot have a parent type either
"legalName": "Example Company",
// [...] some attributes are hidden for clarity
}
```
We then create **"Alex"**, a Physical User,
* associate it to the parent company (`parentUserId`),
* define the relation as an *employee* relation (`parentType`).
All in one step.
```bash [CURL]
curl -X POST '{baseUrl}/v1/users' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{
"userTypeId": 1, # 1 = physical user
"specifiedUSPerson": 0, # 0 = Non-US citizen
"firstname": "Alex",
"parentUserId": 111222333, # associates to the parent companys ID created above
"parentType": "employee" # defines the type of relation
# [...]
}'
```
Returns a *User*, with `parentUserId` and `parentType` populated as specified above.
```json [JSON]
{
"userId": 444555666,
"userTypeId": 1,
"parentUserId": 111222333,
"parentType": "employee",
"firstname": "Alex"
// [...] some attributes are hidden for clarity
}
```
## Use Cases
The most reliable way to identify how to implement your parent-children relation is to find a suitable Use Case below.
### Company and Employee
This use case describes a parent company ([Legal Entity](legal-entity)) and an employee ([Physical User](physical)) of the parent company.
#### Parent
```json [JSON]
{
"userTypeId": 2,
"parentType": null,
"parentUserId": null
}
```
#### Children
```json [JSON]
{
"userTypeId": 1,
"parentType": "employee",
"parentUserId": {idOfTheParentUser},
}
```
***
### Company and Legal Representative
This use case describes a parent company ([Legal Entity](legal-entity)) and a legal representative ([Physical User](physical)) of the parent company.
#### Parent
```json [JSON]
{
"userTypeId": 2,
"controllingPersonType": null,
"parentUserId": null
}
```
#### Children
```json [JSON]
{
"userTypeId": 1,
"controllingPersonType": 3,
"parentType": "leader",
"parentUserId": {idOfTheParentUser}
}
```
***
### Company and Shareholder
This use case describes a parent company ([Legal Entity](legal-entity)) and a shareholder ([Physical User](physical)) of the parent company.
#### Parent
```json [JSON]
{
"userTypeId": 2,
"controllingPersonType": null,
"parentUserId": null
}
```
#### Children
```json [JSON]
{
"userTypeId": 1,
"controllingPersonType": 1,
"parentType": "shareholder",
"parentUserId": {idOfTheParentUser},
"effectiveBeneficiary": 30 // shares (%)
}
```
***
### Company and Legal Representative who is also a Shareholder
This use case describes a parent company ([Legal Entity](legal-entity)) and a [Physical User](physical) who is both the legal representative and a shareholder of the parent company.
In such cases:
* The Physical User is created as a Legal Representative and,
* The `effectiveBeneficiary` field must include the shares of the company.
#### Parent
```json [JSON]
{
"userTypeId": 2,
"controllingPersonType": null,
"parentUserId": null
}
```
#### Children
```json [JSON]
{
"userTypeId": 1,
"controllingPersonType": 3,
"parentType": "leader",
"parentUserId": {idOfTheParentUser},
"effectiveBeneficiary": 30 // shares (%)
}
```
***
### Natural Parent and Minor (using Electronic Money)
This use case describes a natural parent ([Physical User](physical)) and their natural minor children ([Physical User](physical)).
#### Key aspects of this Use Case
* It is used with [Electronic Money](/guide/wallets/introduction#electronic-money-wallet-type-9) Wallets.
* The Wallets are associated (`Wallet.userId`) to the natural parents.
* When the [Electronic Money](/guide/wallets/introduction#electronic-money-wallet-type-9) threshold of €150 is reached, a [KYC](/guide/user-verification/introduction) is required on the natural parent exclusively.
#### Parent
```json [JSON]
{
"userTypeId":1,
"parentType":null,
"parentUserId":null
}
```
#### Children
```json [JSON]
{
"userTypeId": 1,
"parentType": "leader",
"parentUserId": {idOfTheParentUser}
}
```
***
### Natural Parent and Minor (using Payment Account)
This use case describes a natural parent ([Physical User](physical)) and their natural minor children ([Physical User](physical)).
#### Key aspects of this Use Case
* It is used with [Payment Account](/guide/wallets/introduction#payment-account-wallet-type-10) Wallets.
* The Wallets are associated (`Wallet.userId`) to the minor children.
* A [KYC](/guide/user-verification/introduction) is required on both the natural parent and the minor children.
#### Parent
```json [JSON]
{
"userTypeId": 1,
"parentType": null,
"parentUserId": null
}
```
#### Children
```json [JSON]
{
"userTypeId": 1,
"parentType": "shareholder",
"parentUserId": {idOfTheParentUser}
}
```
***
### Individual and Assisted Individual
This use case describes a parent individual ([Physical User](physical)) and an assisted individual ([Physical User](physical)) under their legal responsibility (such as under guardianship).
#### Key aspects of this Use Case
* It is used with [Payment Account](/guide/wallets/introduction#payment-account-wallet-type-10) Wallets.
* The Wallets are associated (`Wallet.userId`) to the assisted individuals.
* A [KYC](/guide/user-verification/introduction) is required on both the parent individual and the assisted individual.
* The parent is required to produce an additional [KYC Document](/guide/user-verification/documents) (form of proxy) allowing them access to the children's Wallet.
#### Parent
```json [JSON]
{
"userTypeId": 1,
"parentType": null,
"parentUserId": null
}
```
#### Children
```json [JSON]
{
"userTypeId": 1,
"parentType": "leader",
"parentUserId": {idOfTheParentUser}
}
```
---
---
url: /guide/user-verification/live-verification.md
description: >-
Technical guide for verifying users (KYC) with live verification via the
Treezor API. Includes required parameters, request structure, and response
examples.
---
# Live verification
Live verification consists of verifying the user’s identity remotely through a live video. This feature contributes to mitigating fraud risk while optimizing the user experience.
**Configuration – Environment configuration by Treezor**
Contact Treezor to use one of the live verification features.
Treezor relies on a live verification provider which offers two ways to verify user identity. You can use only one of these two methods.
| Method | Description |
| --- | --- |
| **Liveness** | Requires a video of the end user, their identity proof, and a SEPA transfer into their Treezor Wallet as an [extra validation step](/guide/user-verification/introduction#additional-vigilance-measures). |
| **Certified video ([PVID](/guide/overview/glossary#remote-identity-verification-providers-pvid))** | Requires a video of the end users and their identity proof. It contains challenges for the user to complete, so no extra validation step is necessary. PVID is [ANSSI-certified](/guide/overview/glossary#french-cybersecurity-agency-anssi).
Both features use the same endpoint with a transparent behavior.
**Tip – The KYC live verification interface is customizable**
Contact Treezor to change the colors, logo, redirection URL once the process ends, etc.
## Process
1. You initiate a live verification for the User – [`/v1/users/{userId}/kycliveness`](/api-reference/api-endpoints.html#tag/Verification%20Solutions%20\(KYC\)/postKycliveness){target="\_self"}
2. Treezor answers with the live verification URL (`identification-url`).
3. You redirect the User to the `identification-url`.
4. The User follows the step-by-step live verification process, hence uploading the document.
5. Treezor keeps you informed of the documents processing with the [KYC Liveness](/guide/users/events#kyc-liveness) webhooks.
6. Once the [`kycliveness.update`](./events.md#kycliveness-update) webhook returns a `kyc-status` set to `processed` with a `score` of `1`, you may request a KYC review: a. [Retrieve the documents](#retrieve-the-documents) – [`/v1/users/{userId}/kycliveness`](/api-reference/api-endpoints.html#tag/Verification%20Solutions%20\(KYC\)/put-kyc-liveness){target="\_self"} b. [Request a KYC review](#request-a-review-of-the-user) – [`/v1/users/{userId}/Kycreview`](/api-reference/api-endpoints.html#tag/User%20KYC%20Review/putKycreview){target="\_self"}
7. Treezor sends you the [`user.kycreview`](events#user-kycreview) webhook upon validation or refusal.
Note that the live verification process may take some time.
Please don't call the [`/v1/users/{userId}/kycliveness`](/api-reference/api-endpoints.html#tag/Users/postKycliveness){target="\_self"} endpoint for a given user before the previous live verification is completed. When this situation occurs:
* The newer request replaces the previous one.
* Trying to upload documents for the first live verification results in an HTTP error.
## Key attributes (webhooks)
Live verification relies exclusively on webhooks to provide you with information regarding the process:
* [`kycliveness.create`](/guide/user-verification/events#kycliveness-create) – Received when the end user completes (or abandons) the live verification process.
* [`kycliveness.update`](/guide/user-verification/events#kycliveness-update) – Received when Treezor identity verification partner completes the verification.
Below are some of the key attributes you may find in these webhooks.
| Attribute | Type | Description |
| --- | --- | --- |
| `kyc-status` | string | The status of the live verification process. See the `redirectURL` [query parameters](#parameters). |
| `comment` | string | Comment from Treezor providing additional information regarding the live verification process. |
| `reasons` | array | List of reason codes and messages indicating why the user has been refused. See the list of [reason codes](#reason-codes-reason-code) below. |
### Reason codes (reason-code)
When using the live verification feature (either Liveness or Certified video), the [`kycliveness.update`](/guide/user-verification/events#kyc-liveness) webhook returns the `reason-code` and the corresponding `reason-message`, providing insights on the refusal.
Some of these errors are sensitive regarding [AML/CFT](/guide/overview/glossary#anti-money-laundering-and-countering-the-financing-of-terrorism-aml-cft), please remember not to share the reasons for refusal with your end users when that’s the case.
| Code | Message |
| :---: | --- |
| 1201 | Applicant did not have a sufficient connexion |
| 1301 | Applicant’s document video is too blurry (mostly due to too much movement but if this error persists the camera quality might be at fault) |
| 1302 | Applicant has not presented the front of the document |
| 1303 | Applicant has not presented the back of the document |
| 1304 | Applicant hides part of the document |
| 1305 | Applicant did not present a dynamic view of the document |
| 1310 | Applicant’s video of their face is too blurry (mostly due to too much movement but if this error persists the camera quality might be at fault) |
| 1311 | Applicant has not presented a face |
| 1312 | Applicant did not show the full front view of their face |
| 1313 | Applicant did not move to prove the liveness |
| 1320 | Applicant performed their id verification under poor lighting conditions |
| 1901 | Internal non-categorizable error |
| 1911 | The received videos cannot be played |
| 2101 | Applicant presented an expired document |
| 2102 | Applicant presented a document which is not accepted |
| 2103 | Applicant has submitted a damaged document |
| 2201 | Applicant presented a photocopy of the document |
| 2202 | Applicant presented the document on a screen |
| 2301 | Applicant has submitted a counterfeit or falsification |
| 2302 | Applicant presented a document declared as stolen or lost |
| 2303 | Applicant presented the front and back of two different documents |
| 2304 | Applicant is not the rightful owner of the document |
| 2305 | Applicant presented another person's face |
| 2306 | Applicant has altered his/her appearance |
| 2307 | Applicant has digitally altered the videos |
| 2399 | Generic code when a fraud has been detected within a certified identity verification |
| 2401 | Applicant’s identity does not match with the expected one |
| 2402 | Applicant used a device that has been technically altered |
| 2403 | Applicant seems to have performed the check against his will |
| 2404 | The applicant has recently performed a fraud attempt |
## Initiate a live verification
Before initiating the live verification process, the User must be created with the relevant attributes (as required by Treezor Compliance).
At least the `firstname`, `lastname`, and `birthday` of the user must be populated, otherwise, the API call returns an HTTP 428 error.
### Parameters
You can optionally override the default URL to which the user will be redirected after the live verification.
| Attribute | Type | Description |
| --- | --- | --- |
| `redirectUrl` | string | The URL to which the User will be redirected after the live verification. |
Additional information is added to the defined redirect URL in the form of query parameters. This can help the end user understand why a live verification process has been aborted.
The query parameters provided with the `redirectUrl` are the following:
| Parameter | Description |
| --- | --- |
| `identification_id` | The unique identifier of the live verification process. |
| `status` | The status of the live verification, which in this case can be either `processing` in case of success or `aborted` for failures. |
| `return_reason` | The reason for the live verification process abortion. |
| `error_type` | Indicates the type of error that led to the live verification process abortion. |
If you take the following URL:
`redirect_url?identification_id=123&status=aborted&return_reason=error&error_type=device_not_found`
You can deduce that the identification process `123` was aborted due to an error; the device was not found (i.e., the device did not have any camera).
Here is the list of values for the query parameters:
| status | return\_reason | error\_type | description |
|:------------:|---------------|--------------------|---------------------------------------------------|
| `processing` | none | none | The user completed their verification. |
| `aborted` | refusal | none | The user refused to perform the verification now. |
| `aborted` | no\_document | none | The user did not have their document available to them. |
| `aborted` | verify\_later | none | The user refused to start the verification process. |
| `aborted` | focus-lost | none | The user switched tabs/application while performing the id verification. |
| `aborted` | connections\_issue | bad\_connexion | The connection was not good enough. |
| `aborted` | doc\_instructions\_not\_followed | challenge\_timeout | The user did not follow the instruction for the document challenge. |
| `aborted` | face\_instructions\_not\_followed | challenge\_timeout | The user did not follow the instruction for the face challenge. |
| `aborted` | error | bad\_connexion | The connection was not good enough. |
| `aborted` | error | no\_SMS | The user did not receive the SMS. |
| `aborted` | error | publish | Error during video connection. |
| `aborted` | error | device\_not\_allowed | The user refused to give access to their camera. |
| `aborted` | error | browser-not-supported | The browser was not supported. |
| `aborted` | error | device\_not\_found | The user’s device did not have any camera. |
| `aborted` | error | wrong\_phone\_number | The user wanted to change their phone number and were not allowed to for security reasons. |
### Request
You can use the following request to initiate the live verification process.
```bash [CURL]
curl -X POST '{baseUrl}/v1/users/{userId}/kycliveness' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{"redirectUrl": "https://www.my-domain.tld"}'
```
Answers with a 201 HTTP Status Code and returns the identifier of the verification process and the `identification-url`. The latter is where the end user is to be redirected to go through the live verification process.
```json [JSON]
{
"identification": {
"identification-id": "f8048bee-3182-48dc-93e5-7eef9db77050",
"identification-url": "https://id.ubble.ai/f8048bee-3182-48dc-93e5-7eef9db77050",
"type": "video_certified"
}
}
```
Once redirected, end users have **15 minutes** to complete the steps for the relevant live verification feature. After this delay, the `identification-url` expires.
**Information – The redirection link may not be supported by the end user's device**
See the `redirectURL` [query parameters](#parameters) to know which error is returned when this occurs.
### End user live verification
Once redirected, end users are guided through the live verification steps:
* Which differ depending on the live verification type.
* Which documents vary depending on the country of the end user.
After the last step:
* The user is redirected to the `redirectUrl` or the URL configured with Treezor.
* Treezor sends you a [`kycliveness.create`](./events) webhook with a `kyc-status` set to `processing`.
## Retrieve the live verification document
Once you have received the [`kycliveness.update`](./events.md#kycliveness-update) webhook with a `kyc-status` set to `processed` and a `score` of `1` (validated), you must retrieve the documents from the live verification provider for them to be uploaded to Treezor.
Below is the meaning of each value the `score` attribute of the [`kycliveness.update`](./events.md#kycliveness-update) can return.
| Score | Description |
| :---: | --- |
| `1` | Validated. The live verification is processed, and the user was successfully identified. |
| `0` | Refused. The live verification is processed, and the live verification provider couldn't verify the user (e.g., expired document). |
| `-1` | Failed. The live verification couldn't be properly processed. Can be due to errors, the end user abandoning the process, or failure to present the document for example. |
These documents include documents uploaded by the end user during the process and the live verification process synthesis document, which is either:
* **Liveness result** for the liveness process (`documentTypeId` = `26`).
* **Certified Liveness Result** for the certified video process (`documentTypeId` = `34`).
To retrieve the documents, use the following request.
```bash [CURL]
curl -X PUT '{baseUrl}/v1/users/{userId}/kycliveness' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json'
```
Answers with an HTTP 200 status code and makes the documents available for download.
Treezor sends you as many `document.create` webhooks as there are documents for the user’s live verification. You can make your [KYC Review request](#request-a-kyc-review-for-the-user) only once you've received all the document creation webhooks.
## Download the live verification documents
If you're eligible, you may be able to collect some of the uploaded documents whose `documentTypeId` allows for it.
**Configuration – Download is not enabled by default**
Please contact Treezor to request access to this feature.
Downloading a document is a 2-step process, in which you:
1. [Request the download URL](#request-the-download-url)
2. [Download the document within 30 seconds](#download-the-document)
### Request the download URL
To request the download URL, you need the corresponding `documentId` (available in the `document.create` webhook for instance).
```bash [CURL]
curl -X GET '{baseUrl}/v1/documents/{documentId}/download' \
--header 'Authorization: Bearer {accessToken}' \
```
Returns the URL to download the document, with all the necessary query parameters for the next step.
```json [JSON]
{
"url": "{documentDownloadUrl}"
}
```
### Download the document
You have 30 seconds to download the document from the moment the URL has been generated in the previous step.
```bash [CURL]
curl -X GET '{documentDownloadUrl}'
```
The document is returned in its initial format.
## Request a KYC Review for the User
Before requesting a KYC review from Treezor, please make sure all the information and documents are properly updated for the user.
You can use the dedicated endpoint:
* [`/v1/users/{userId}/Kycreview`](/api-reference/api-endpoints.html#tag/User%20KYC%20Review/putKycreview){target="\_self"}
**Alert – Documents must be uploaded for children users too**
When there are [parent-children hierarchical relationship](/guide/users/parent-children), in most cases, the KYC Review must only be requested for the parent user. But you may need to upload [Documents](./documents) for the children before that. Please abide by the Treezor Compliance team recommendation for a smooth experience.
Learn more in the [KYC Request](./kyc-request) article.
## Endpoints
| Endpoint |[Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/v1/users/{userId}/kycliveness`](/api-reference/api-endpoints.html#tag/Verification%20Solutions%20\(KYC\)/postKycliveness){target="\_self"} Initiate the user [Live verification](/guide/user-verification/introduction) process | `read_write` |
| [`/v1/documents/{documentId}/download`](/api-reference/api-endpoints.html#tag/User%20Documents/getDocumentDownloadUrl){target="\_self"} Retrieve a document download URL | `read_only` |
| [`/v1/users/{userId}/kycliveness`](/api-reference/api-endpoints.html#tag/Verification%20Solutions%20\(KYC\)/put-kyc-liveness){target="\_self"} Upload the documents once the Live verification is completed. | `read_write` |
| [`/v1/users/{userId}/Kycreview`](/api-reference/api-endpoints.html#tag/User%20KYC%20Review/putKycreview){target="\_self"} Initiate the user [KYC review](/guide/user-verification/introduction) process | `read_write` |
---
---
url: /guide/users/faking-operations.md
description: >-
Learn how to simulate Treezor User validation within the Sandbox environment
for development and API integration testing.
---
# Emulation
Emulation features are only available in `Sandbox` [environment](/guide/api-basics/environments).
## Simulate user validation
Some actions, like creating specific types of Wallets, require the user to be in a `VALIDATED` status.
In Sandbox, you can validate the user for testing purposes by adding the `.userStatusValidated` suffix to the User's `lastname` (or `legalName` for legal entities).
You can do so with the following requests:
* [`/v1/users`](/api-reference/api-endpoints.html#tag/Users/postUser){target="\_self"}
* [`/v1/users/{userId}`](/api-reference/api-endpoints.html#tag/Users/putUser){target="\_self"}
**Tip – Compatible with KYC emulation**
You can cumulate the suffixes to achieve both status and [KYC emulation](/guide/user-verification/faking-operations) at once. For instance: `lastname.refused.userStatusValidated`.
### Example
Let's update a User's `lastname` to set the status to `VALIDATED`.
```bash [CURL]
curl -X PUT '{baseUrl}/v1/users' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
With a `{payload}` containing the suffixed `lastname`:
```json [JSON]
{
"lastname": "Oak.userStatusValidated"
}
```
Returns the updated user with the new `userStatus`:
```json {6} [JSON]
{
"users": [
{
"userId": 101391362,
"userTypeId": 1,
"userStatus": "VALIDATED",
"userTag": "",
"parentUserId": 0,
"parentType": "",
"controllingPersonType": 0,
"employeeType": 0,
"specifiedUSPerson": 0,
"title": "M",
"firstname": "Alex",
"lastname": "Oak.userStatusValidated",
"middleNames": "",
"birthday": "1982-05-30",
"email": "Waino.Cole@gmail.com",
"address1": "8214 Kris Turnpike",
"address2": "",
"postcode": "75017",
"city": "Paris",
"state": "",
"country": "FR",
"countryName": "France",
"phone": "+33141358530",
"mobile": "",
"nationality": "FR",
"nationalityOther": "",
"placeOfBirth": "Paris",
"birthCountry": "FR",
"occupation": "",
"incomeRange": "0-18",
"legalName": "",
"legalNameEmbossed": "",
"legalRegistrationNumber": "",
"legalTvaNumber": "",
"legalRegistrationDate": "0000-00-00",
"legalForm": "",
"legalShareCapital": 0,
"entityType": 0,
"legalSector": "",
"legalAnnualTurnOver": "",
"legalNetIncomeRange": "",
"legalNumberOfEmployeeRange": "",
"effectiveBeneficiary": 0,
"kycLevel": 2,
"kycReview": 0,
"kycReviewComment": "",
"isFreezed": 0,
"isFrozen": null,
"language": "",
"optInMailing": null,
"sepaCreditorIdentifier": "",
"taxNumber": "",
"taxResidence": "",
"position": "",
"personalAssets": "",
"createdDate": "2025-01-17 09:39:21",
"modifiedDate": "2025-01-17 10:39:45",
"walletCount": 0,
"payinCount": 0,
"totalRows": "1",
"activityOutsideEu": null,
"economicSanctions": null,
"residentCountriesSanctions": null,
"involvedSanctions": null,
"address3": null,
"timezone": null,
"occupationType": "",
"isOnStockExchange": 0,
"secondaryAddress1": "",
"secondaryAddress2": "",
"secondaryAddress3": "",
"secondaryPostcode": "",
"secondaryCity": "",
"secondaryState": "",
"secondaryCountry": "",
"clientId": "929252",
"sanctionsQuestionnaireDate": null,
"codeStatus": "110009",
"informationStatus": "",
"legalSectorType": "",
"sourceOfFunds": "",
"distributionCountry": null,
"entitySanctionsQuestionnaire": 0,
"monthlyIncomeRange": null,
"personalAssetsRange": null,
"occupationCategory": null,
"birthCityCode": null
}
]
}
```
---
---
url: /guide/user-verification/errors.md
description: >-
Troubleshoot and handle KYC, Documents, and verification solution issues using
the Treezor API's complete list of error codes, messages, and their
corresponding meanings.
---
# Errors
The following API errors can be encountered when dealing with user verification.
**Caution – Only the legacy API sends the error code in HTTP errors**
When handling errors with Connect, only the `message` attribute is returned.
## KYC request errors
| Code | Message |
|:-------:|---------------------|
| `1` | Generic Error |
| `3` | A database error has occured |
| `6` | An Exception has been raised |
| `11` | One filter given in the request is empty, you should provide a filter value at least |
| `31` | The same request is already running |
| `55` | The request accessTag is too long |
| `1029` | Non-existent client for the given user |
| `10009` | Request UserId does not belong to Oauth2 ClientId |
| `10029` | Non-existent client for the given document |
| `10030` | SCI must be between 8 and 35 characters |
| `10034` | SCI must start with a valid ISO country code |
| `10035` | Invalid SCI checksum |
| `11004` | Title is required |
| `11005` | Civility value must be either 'M' or 'MME' or 'MLLE' |
| `11006` | Firstname is required. |
| `11007` | The lastname is required. |
| `11011` | The post code is required. |
| `11012` | The city is required. |
| `11013` | The country is required. Format ISO 3166-1 alpha-2 |
| `11019` | The email is already used |
| `11025` | legalRegistrationNumber is required. |
| `11026` | legalRegistrationDate is required (format : YYYY-MM-DD) |
| `11027` | legalName is required. |
| `11028` | legalForm is required. |
| `11029` | legalShareCapital is required |
| `11030` | phone is required. |
| `11031` | legalSector is required. |
| `11032` | legalNumberOfEmployeeRange is required. |
| `11033` | legalNetIncomeRange is required. |
| `11034` | legalAnnualTurnOver is required. |
| `11035` | placeOfBirth is required. |
| `11036` | birthCountry is required. Format ISO 3166-1 alpha-2 |
| `11037` | nationality is required. |
| `11039` | birthday is required (format : YYYY-MM-DD) |
| `11040` | userIdKyc is required. |
| `11041` | user does not exist. |
| `11042` | kycReview is required. |
| `11043` | kycReview value is incorrect. |
| `11044` | kycReviewComment is required. |
| `11046` | userIdKyc is required. |
| `11047` | user does not exist. |
| `11048` | kycLevel is required. |
| `11049` | kycLevel value is incorrect. |
| `11051` | nationalityOther is not in the right format. Format ISO 3166-1 alpha-2 |
| `11058` | birthday is not in the right format. Format YYYY-MM-DD |
| `11060` | nationality is not in the right format. Format ISO 3166-1 alpha-2 |
| `11073` | incomeRange is required. |
| `11074` | userId is missing. |
| `11075` | userId does not exist for the client. |
| `11076` | sci is empty |
| `11095` | employeeType is missing |
| `11098` | controllingPersonType is missing |
| `11099` | specifiedUSPerson is missing |
| `11113` | Wrong value of legalForm for user type NATURAL PERSON, legalForm can only be 1000. |
| `11115` | legalRegistrationDate Year is too old (before 1800) |
| `11122` | The secondary address is required |
| `11123` | The secondary country is required |
| `11124` | The secondary postcode is required |
| `11125` | The secondary city is required |
| `11177` | Impossible to submit KYC request due to user status |
| `11179` | one of the associated user is invalid |
| `11193` | A legal representative and majority shareholder must be declared. |
| `101300` | the business user and each effective beneficiary attached to it need to have at least one tax residence declared |
| `101301` | the business user and each effective beneficiary attached to it need to have at least one valid tax residence declared |
| `101208` | specifiedUSPerson must be 0 or 1 |
## Document errors
| Code | Message |
|:------:|------------------------------------------------------------------------------------------------------------------|
| `60000` | The user does not exist or he is in canceled status |
| `60001` | File not uploaded. The file is empty |
| `60002` | The file type is not permitted |
| `60003` | This document type is not permitted |
| `60004` | Impossible to save the document |
| `60005` | Impossible to connect to the file server |
| `60006` | Impossible to upload the document into the container |
| `60007` | Impossible to read the file into the container |
| `60008` | Impossible to update the document into database |
| `60009` | Error when reading document |
| `60010` | Impossible to cancel this Document, already in CANCELED status |
| `60011` | Impossible to update this Document, not exists |
| `60012` | statusId incorrect. |
| `60013` | Impossible to verify canceled status |
| `60014` | Impossible to update this document |
| `60017` | Image is empty |
| `60019` | documentId is mandatory. |
| `60020` | documentStatusId is mandatory. |
| `60021` | The document must be in a PENDING status |
| `60024` | The documentTypeId is empty or you provide a wrong documentTypeId value |
| `60025` | Wrong value for documentStatusId |
| `60026` | documentId not valid |
| `60027` | statusId is mandatory. |
| `60028` | When the document is a taxStatement or an exemptionStatement, the field residenceId is mandatory |
| `60029` | When the document is not a taxStatement nor an exemptionStatement, the field residenceId should not be provided |
| `60030` | The residenceId you provided does not match a valid entry in the taxResidence database |
| `60031` | The residenceId you provided has been deleted |
| `60032` | userId is missing |
| `60033` | Impossible to create the document, The number of objects is exceeded or the quota of your space is saturated |
| `60034` | Impossible to update the status, this document is canceled |
| `60035` | Impossible to get URL, this document does not exist |
| `60036` | The document source is not valid or not in the list |
| `60038` | name is mandatory. |
| `60039` | Document not found in database. |
| `60040` | Update document status with error |
| `60041` | fileExtension is missing |
| `60042` | FileExtension is not valid or not in the list |
| `60043` | The request must contain documentHash when documentId is in params . |
| `60044` | Document already cancel or validate, this document, this document is not pending status |
| `60045` | The documentHash is invalid |
| `60046` | fileExtension is not correct |
| `60049` | fileSize is too large |
| `60050` | fileSize is missing |
| `60051` | fileHash is missing |
| `60052` | document already created |
| `60053` | invalid hex-encoded hash |
---
---
url: /guide/user-verification/events.md
description: >-
Reference a comprehensive list of KYC, documents, and verification solution
events for Treezor API webhooks, detailing each event's structure and payload
for integration.
---
# Events
This article lists the [Webhooks](/guide/webhooks/introduction) you may receive when regarding user verification.
## KYC events
### `user.kycrequest`
```json [JSON]
{
"messageId": "04b61286-2cb1-555c-a62e-49836482c5b8",
"webhookId": "fd895029-22e5-49ed-a2c8-093c07dc053c",
"webhook": {
"webhook": "user.kycrequest",
"object": "user",
"object_id": "6461762",
"object_payload": {
"users": [
{
"userId": "6461762",
"userTypeId": "1",
"userStatus": "VALIDATED",
"clientId": "516899",
"userTag": "",
"parentUserId": null,
"parentType": null,
"title": "M",
"firstname": "Alex",
"lastname": "Oak",
"middleNames": "",
"birthday": "1989-00-00",
"email": "a.oak@example.com",
"address1": "12 Willow Lane",
"address2": "",
"address3": "",
"postcode": "75000",
"city": "Paris",
"state": "Paris",
"country": "FR",
"countryName": "France",
"phone": "+xxxxxxxxxxxxx",
"mobile": "+xxxxxxxxxxxxx",
"nationality": "FR",
"nationalityOther": "",
"placeOfBirth": "Caen",
"birthCountry": "FR",
"occupation": "",
"incomeRange": "28-35",
"legalName": "",
"legalNameEmbossed": "",
"legalRegistrationNumber": "",
"legalTvaNumber": "",
"legalRegistrationDate": "0000-00-00",
"legalForm": "",
"legalShareCapital": "0",
"legalSector": "",
"legalAnnualTurnOver": "",
"legalNetIncomeRange": "",
"legalNumberOfEmployeeRange": "",
"effectiveBeneficiary": "0.00",
"position": "",
"personalAssets": "0-2",
"taxResidence": "FR",
"taxNumber": "",
"kycLevel": "0",
"kycReview": "1",
"kycReviewComment": "",
"isFreezed": "0",
"language": null,
"specifiedUSPerson": "0",
"employeeType": "0",
"entityType": "0",
"controllingPersonType": "0",
"activityOutsideEu": null,
"economicSanctions": null,
"residentCountriesSanctions": null,
"involvedSanctions": null,
"entitySanctionsQuestionnaire": null,
"sanctionsQuestionnaireDate": null,
"timezone": null,
"createdDate": "2022-05-18 12:21:04",
"modifiedDate": "2022-05-18 12:21:12",
"codeStatus": "110009",
"informationStatus": "",
"sepaCreditorIdentifier": null,
"walletCount": "1",
"payinCount": "0",
"totalRows": "1"
}
]
},
"webhook_created_at": 16532945786168,
"webhook_id": "fd895029-22e5-49ed-a2c8-093c07dc053c",
"object_payload_signature": "pVzBUAM2mgVtCNxw6u4fdaZqktAlStk\/yGlfA1v2JQs="
},
"clientId": "516899"
}
```
### `user.kycreview`
This event is sent when Treezor validates or refuses a User.
```json [JSON]
{
"messageId": "db99d40f-0840-5945-bfab-8f01daf65ac1",
"webhookId": "8f3577ec-c126-4e94-a3df-1bdccfb0b89f",
"webhook": {
"webhook": "user.kycreview",
"object": "user",
"object_id": "6461762",
"object_payload": {
"users": [
{
"userId": "6461762",
"userTypeId": "1",
"userStatus": "VALIDATED",
"clientId": "516899",
"userTag": "",
"parentUserId": null,
"parentType": null,
"title": "M",
"firstname": "Alex",
"lastname": "Oak",
"middleNames": "",
"birthday": "1989-00-00",
"email": "a.oak@example.com",
"address1": "xxxxxxxxxxx",
"address2": "",
"address3": "",
"postcode": "75000",
"city": "Paris",
"state": "Paris",
"country": "FR",
"countryName": "France",
"phone": "+00000000000",
"mobile": "+00000000000",
"nationality": "FR",
"nationalityOther": "",
"placeOfBirth": "Caen",
"birthCountry": "FR",
"occupation": "",
"incomeRange": "28-35",
"legalName": "",
"legalNameEmbossed": "",
"legalRegistrationNumber": "",
"legalTvaNumber": "",
"legalRegistrationDate": "0000-00-00",
"legalForm": "",
"legalShareCapital": "0",
"legalSector": "",
"legalAnnualTurnOver": "",
"legalNetIncomeRange": "",
"legalNumberOfEmployeeRange": "",
"effectiveBeneficiary": "0.00",
"position": "",
"personalAssets": "0-2",
"taxResidence": "FR",
"taxNumber": "",
"kycLevel": "2",
"kycReview": "2",
"kycReviewComment": "30-05-2022 - 16:11:02Level : REGULAR et Review : VALIDATED",
"isFreezed": "0",
"language": null,
"specifiedUSPerson": "0",
"employeeType": "0",
"entityType": "0",
"controllingPersonType": "0",
"activityOutsideEu": null,
"economicSanctions": null,
"residentCountriesSanctions": null,
"involvedSanctions": null,
"entitySanctionsQuestionnaire": null,
"sanctionsQuestionnaireDate": null,
"timezone": null,
"createdDate": "2022-05-18 12:21:04",
"modifiedDate": "2022-05-18 12:21:12",
"codeStatus": "110009",
"informationStatus": "",
"sepaCreditorIdentifier": null,
"walletCount": "1",
"payinCount": "0",
"totalRows": "1"
}
]
},
"webhook_created_at": 16539198620721,
"webhook_id": "8f3577ec-c126-4e94-a3df-1bdccfb0b89f",
"object_payload_signature": "Kg\/+Np3zU7vW9f6HbMCU0ueIIACCRfGKCiWa+PiLvzM="
},
"clientId": "516899"
}
```
## Document events
### `document.create`
```json [JSON]
{
"webhook": "document.create",
"webhook_id": "10XXXXXX",
"object": "document",
"object_id": "8XXXX",
"object_payload": {
"documents": [
{
"documentId": "8XXXX",
"documentTag": "LP'6C7`VGnREXXXXXXXX",
"clientId": "4XXXX",
"userId": "1XXXXXX",
"userFirstname": "Victoria",
"userLastname": "Perin",
"name": "Merged_Passport.pdf",
"documentStatus": "PENDING",
"documentTypeId": "17",
"documentType": "PASSPORT",
"fileName": "8XXXX.pdf",
"thumbFileName": "",
"createdDate": "2020-05-19 10:34:21",
"modifiedDate": "0000-00-00 00:00:00",
"codeStatus": "600003",
"informationStatus": "",
"residenceId": "0"
}
]
},
"object_payload_signature": "bJaKKq6y4Ah5RhlZMIgHwClWMxGIxpBB4xdMJXddXXXX"
}
```
### `document.update`
```json [JSON]
{
"webhook": "document.update",
"webhook_id": "1XXXXXXX",
"object": "document",
"object_id": "8XXXX",
"object_payload": {
"documents": [
{
"documentId": "8XXXX",
"documentTag": "draftedstatutes",
"clientId": "9XXXX",
"userId": "1XXXXXX",
"userFirstname": "MICHELE",
"userLastname": "CRESSIN",
"name": "draftedstatutes_2192.pdf",
"documentStatus": "PENDING",
"documentTypeId": "23",
"documentType": "LEGAL_STATUS",
"fileName": "80009.pdf",
"thumbFileName": "",
"createdDate": "2020-05-13 16:22:03",
"modifiedDate": "2020-05-13 18:28:43",
"codeStatus": "600003",
"informationStatus": "",
"residenceId": "0"
}
]
},
"object_payload_signature": "q53Gk3QsSuOurHDECo9CZZ4cs9GRMg8I81L21M6+XOXO"
}
```
You can check the list of `codeStatus` in the [Documents](/guide/user-verification/documents#status-documentstatus) article.
### `document.cancel`
```json [JSON]
{
"webhook": "document.cancel",
"webhook_id": "1XXXXXX",
"object": "document",
"object_id": "8XXXX",
"object_payload": {
"documents": [
{
"documentId": "8XXXX",
"documentTag": "0000000",
"clientId": "1XXXXX",
"userId": "0000000",
"userFirstname": "Marie",
"userLastname": "bela",
"name": "XXXXXX_doc",
"documentStatus": "CANCELED",
"documentTypeId": "21",
"documentType": "PAYSLIP",
"fileName": "AAAAA.jpg",
"thumbFileName": "",
"createdDate": "2020-05-18 22:55:13",
"modifiedDate": "2020-05-18 20:55:24",
"codeStatus": "600004",
"informationStatus": "",
"residenceId": "0"
}
]
},
"object_payload_signature": "OfyL8/fpm1FX33ubIWdPqG+bNsQlhCFm4yN0Zl8XXXXX"
}
```
## KYC Liveness events
Treezor sends the following webhooks for Live Verification (whether it is Liveness or Certified video).
### `kycliveness.create`
```json [JSON]
{
"webhook": "kycliveness.create",
"webhook_id": "42424224-442z5-42ce9-8242-513d80c15142",
"object": "identification",
"object_id": "9dac1414-6733-46ae-b5a9-1b3aa39ea4bd",
"object_payload": {
"kyc-status": "processing",
"comment": "Some additional elements need to be verified. You will be notified by webhook when the final answer is ready.",
"user_id": "2440234",
"started-at": "2020-06-30T07:10:47.824723Z",
"updated-at": "2020-06-30T07:15:18.856843Z",
"score": 1,
"identity": {
"last-name": "OAK",
"first-name": "ALEX",
"birth-date": "1942-11-19",
"gender": "M",
"issuing-place": "",
"birthplace": "PARIS"
},
},
"object_payload_signature": "5Hfi\/ywu2fjtw0Exm22rJJwyZEej4Qp4BfPsamXAP\/42"
}
```
### `kycliveness.update`
```json [JSON]
{
"webhook": "kycliveness.update",
"webhook_id": "42424224-442z5-42ce9-8242-513d80c11111",
"object": "identification",
"object_id": "9dac1414-6733-46ae-b5a9-1b3aa39ea4xx",
"object_payload": {
"updated-at": "2024-03-08T05:37:26.076003Z",
"started-at": "2024-03-08T05:32:37.100594Z",
"identity": {
"last-name": "OAK",
"first-name": "ALEX",
"birth-date": "1990-07-18",
"gender": "M",
"issuing-place": "",
"birthplace": "PARIS"
},
"kyc-status": "processed",
"comment": "Applicant did not show the full front view of their face, Applicant performed their id verification under poor lighting conditions, Applicant's identity does not match with the expected one",
"refusal-details": {
"meta": {
"count": 3
},
"reasons": [
{
"reason-code": "1312",
"reason-message": "Applicant did not show the full front view of their face"
},
{
"reason-code": "1320",
"reason-message": "Applicant performed their id verification under poor lighting conditions"
},
{
"reason-code": "2401",
"reason-message": "Applicant's identity does not match with the expected one"
}
]
},
"user_id": "100196123",
"score": 0
},
"object_payload_signature": "5Hfi\/ywu2fjtw0Exm22rJJwyZEej4Qp4BfPxxxXXX\/42"
}
```
## Qualified eSignature events
The following webhooks are sent for qualified electronic signature (QES) verification.
### `qes.created`
```json [JSON]
{
"webhook": "qes.created",
"object_payload": {
"userId": "4137216",
"result": "STARTED",
"identificationTime": "",
"identId": "TST-TWLYB",
"transactionNumber": "b00ecdec-b721-55c4-8e20-ef3625616926",
"type": "APP"
},
"object_id": "b00ecdec-b721-55c4-8e20-ef3625616926",
"object": "identification",
"webhook_created_at": 17194724399022,
"webhook_id": "af5a6c9e-4dc8-4d58-a245-e26dc27xx9aa",
"object_payload_signature": "WUuvXuGyAL4dw9C12K3HxxRmUi3hMxxy8+4kMaRhLDo="
}
```
### `qes.processing`
```json [JSON]
{
"webhook": "qes.processing",
"object_payload": {
"userId": "4137216",
"result": "CHECK_PENDING",
"identificationTime": "2024-06-27T09:16:23+02:00",
"identId": "TST-TWLYB",
"transactionNumber": "b00ecdec-b721-55c4-8e20-ef3625616926",
"type": "APP"
},
"object_id": "b00ecdec-b721-55c4-8e20-ef3625616926",
"object": "identification",
"webhook_created_at": 17194725841286,
"webhook_id": "5fa78cf6-c85b-46c2-b950-a7ad7e974291",
"object_payload_signature": "WDeMRi95hkJhllJZBwfhc2xxRdF1aymVcDhybMzDsig="
}
```
### `qes.aborted`
```json [JSON]
{
"webhook": "qes.aborted",
"object_payload": {
"userId": "100438239",
"result": "ABORTED",
"identificationTime": "2024-06-15T10:58:02+02:00",
"identId": "TST-ARJBA",
"transactionNumber": "3606323f-345e-5105-bfb6-7ca324a69945",
"type": "APP",
"reason": {
"reasonDetails": {
"reasonCode": "3002",
"reasonMessage": "USER_CANCELLATION_DOCUMENT_EXPIRED"
}
}
},
"object_id": "3606323f-345e-5105-bfb6-7ca324a69945",
"object": "identification",
"webhook_created_at": 17184418842212,
"webhook_id": "696b7f9e-020b-4b60-b91a-c7fab0a4940f",
"object_payload_signature": "yNd+4XWx6bIeJn1/lzWliCb//Vwl8BkxxJ4y3+qwL4E="
}
```
### `qes.finalized`
The structure of the webhook differs depending on its `result`.
```json [JSON (success)]
{
"webhook": "qes.finalized",
"object_payload": {
"userId": "4137216",
"result": "SUCCESS_DATA_CHANGED",
"identificationTime": "2024-06-27T09:16:23+02:00",
"identId": "TST-TWLYB",
"transactionNumber": "b00ecdec-b721-55c4-8e20-ef3625616926",
"type": "APP",
"identity": {
"firstname": "ALEX",
"lastname": "OAK",
"birthday": "1983-08-12",
"gender": "OTHER",
"issuingPlace": "STADT KÖLN",
"birthplace": "BERLIN"
}
},
"object_id": "b00ecdec-b721-55c4-8e20-ef3625616926",
"object": "identification",
"webhook_created_at": 17194726044907,
"webhook_id": "8a7dfe6b-d44a-4b54-92a7-cc02c3d43eb8",
"object_payload_signature": "svoHId/5xu940i24cJV82+nCYnzUDv4a9cxxAj9GvJo="
}
```
```json [JSON (canceled)]
{
"webhook": "qes.finalized",
"object_payload": {
"userId": "4137216",
"result": "CANCELED",
"identificationTime": "2024-06-27T09:16:23+02:00",
"identId": "TST-TWLYB",
"transactionNumber": "b00ecdec-b721-55c4-8e20-ef3625616926",
"type": "APP",
"identity": {
"firstname": "ALEX",
"lastname": "OAK",
"birthday": "1983-08-12",
"gender": "OTHER",
"issuingPlace": "STADT KÖLN",
"birthplace": "BERLIN"
},
"reason": {
"reasonDetails": {
"reasonCode": "3201",
"reasonMessage": "WARNING_SELFIE_REAL_PERSON"
}
}
},
"object_id": "b00ecdec-b721-55c4-8e20-ef3625616926",
"object": "identification",
"webhook_created_at": 17194726044907,
"webhook_id": "8a7dfe6b-d44a-4b54-92a7-cc02c3d43eb8",
"object_payload_signature": "svoHId/5xu940ixxcJV82+nCYnzUDv4a9cmYAj9GvJo="
}
```
## Video Conference events
The following webhooks are sent for video conference verification.
### `videoConference.created`
```json [JSON]
{
"webhook": "videoConference.created",
"object_payload": {
"userId": "4137216",
"result": "STARTED",
"identificationTime": "",
"identId": "TST-TWLYB",
"transactionNumber": "b00ecdec-b721-55c4-8e20-ef3625616926",
"type": "APP"
},
"object_id": "b00ecdec-b721-55c4-8e20-ef3625616926",
"object": "identification",
"webhook_created_at": 17194724399022,
"webhook_id": "af5a6c9e-4dc8-4d58-a245-e26dc27xx9aa",
"object_payload_signature": "WUuvXuGyAL4dw9C12K3HxxRmUi3hMxxy8+4kMaRhLDo="
}
```
### `videoConference.processing`
```json [JSON]
{
"webhook": "videoConference.processing",
"object_payload": {
"userId": "100764422",
"result": "REVIEW_PENDING",
"identificationTime": "2024-08-27T15:23:03+02:00",
"identId": "TS2-FEJYN",
"transactionNumber": "bd17f3e1-05fe-5b12-929c-0d4b9b27c4a2",
"type": "WEB"
},
"object_id": "bd17f3e1-05fe-5b12-929c-0d4bxxxc4a",
"object": "identification",
"webhook_created_at": 1724061955000,
"webhook_id": "8a7dfe6b-d44a-4b54-92a7-cc02cxxx3eb8",
"object_payload_signature": "svoHId/5xu940i24cJV82+nCYnzUDxxx9cxxAj9GvJo="
}
```
### `videoConference.aborted`
```json [JSON]
{
"webhook": "videoConference.aborted",
"object_payload": {
"userId": "4137216",
"result": "ABORTED",
"identificationTime": "2024-08-01T01:33:00+02:00",
"identId": "TS2-KWYGX",
"transactionNumber": "26dd014c-33f2-56f6-9ebc-bec12caxx2bf",
"type": "WEB",
"reason": {
"reasonDetails": { "reasonCode": "", "reasonMessage": "STALLED_TIMEOUT" }
}
},
"object_id": "26dd014c-33f2-56f6-9ebc-bec1xxa162bf",
"object": "identification",
"webhook_created_at": 1724061955000,
"webhook_id": "8a7dfe6b-d44a-4b54-92a7-cc02c3xx3eb8",
"object_payload_signature": "svoHId/5xu940i24cJV82+nCYnzxx4a9cxxAj9GvJo="
}
```
### `videoConference.finalized`
The structure of the webhook differs depending on its `result`.
```json [JSON (success)]
{
"webhook": "videoConference.finalized",
"object_payload": {
"userId": "100689821",
"result": "SUCCESS_DATA_CHANGED",
"identificationTime": "2024-08-19T10:05:55+02:00",
"identId": "TS2-HGWTV",
"transactionNumber": "11a08a9a-b05a-5127-b727-b32fa01616bc",
"type": "WEB",
"identity": {
"firstname": "ALEX",
"lastname": "OAK",
"birthday": "1983-10-30",
"gender": "F",
"issuingPlace": "ISSUER",
"birthplace": "BIRTHPLACE"
}
},
"object_id": "11a08a9a-b05a-5127-b727-b32fxxx16bc",
"object": "identification",
"webhook_created_at": 1724061955000,
"webhook_id": "8a7dfe6b-d44a-4b54-92a7-cc02cxx3eb8",
"object_payload_signature": "svoHId/5xu940i24cJV82+nCYnzUDv4a9cxxx9GvJo="
}
```
```json [JSON (canceled)]
{
"webhook": "videoConference.finalized",
"object_payload": {
"userId": "4137216",
"result": "CANCELED",
"identificationTime": "2024-06-27T09:16:23+02:00",
"identId": "TST-TWLYB",
"transactionNumber": "b00ecdec-b721-55c4-8e20-ef3625616926",
"type": "APP",
"identity": {
"firstname": "ALEX",
"lastname": "OAK",
"birthday": "1983-08-12",
"gender": "OTHER",
"birthplace": "BERLIN"
},
"reason": {
"reasonDetails": {
"reasonCode": "3201",
"reasonMessage": "WARNING_SELFIE_REAL_PERSON"
}
}
},
"object_id": "b00ecdec-b721-55c4-8e20-ef3625616926",
"object": "identification",
"webhook_created_at": 17194726044907,
"webhook_id": "8a7dfe6b-d44a-4b54-92a7-cc02c3d43eb8",
"object_payload_signature": "svoHId/5xu940ixxcJV82+nCYnzUDv4a9cmYAj9GvJo="
}
```
---
---
url: /guide/dashboard/users.md
description: >-
Let your team provide support regarding your end users using the Treezor
Dashboard.
---
# Users
Users refer to your end users, whether they represent legal entities or physical persons. They can be directly created and managed from your Dashboard.
## Accessing your users
You may access your user information by:
* Taking advantage of the main [*Search field*](#search-field).
* Navigating the [*Users*](#users-view) view.
### Search field
The Dashboard main toolbar provides a search field, whose searchable attribute becomes dynamically available depending on what you enter.
Here are the attributes for you to search users:
* **User ID** – The `userId` automatically generated by Treezor when creating a user.
* **User Tag** – The [`userTag`](/guide/api-basics/objects-tags), a field you can populate to suit your needs.
* **Email** – The `email` provided during the user creation.
* **Name** – Takes into account the `firstName`, `lastName`, `legalName`, and `email` provided during the user creation.
After validating your search for a given user attribute, the [*Users*](#users-view) view is displayed, filtered on the corresponding User for you to select.
### Users view
The *Users* view lists all your users with their key information. Clicking on arrow icon for a user switches the view to the corresponding profile in the [*User details*](#user-details-view) view.
To help you navigate through the list, the following filters are available:
* **User status** – Display only users with the selected status (Pending, Validated, Canceled).
* **Flag** – Display only users who are US tax residents.
* **Creation date** – Display only users created on, before, after, or between specific dates.
In addition, the secondary Search field allows you to search users by the same attributes as the [main search](#search-field).
## Navigating the user details
### User details view
The *User details* view is displayed as soon as you have selected a user.
As you keep navigating the Dashboard, there will be as many tabs as there are selected users above the main view, so you can easily come back to the user details.
### User information
In the *User details* view, information is broken down into tabs for you to easily manage.
| | Tab | Description |
| --- | --- | --- |
| | **Overview** | All the key information about the user, summarized. If the KYC tab isn't displayed, you can also access the *Edit user* popup by clicking on the "Edit" button in the upper-right corner. |
| | **KYC / KYB** | For you to update user information, manage documents, and go through the user KYC/KYB process. |
| | **Children Users** /**Company members** | The list of [Children Users](#children-users) attached to the currently selected user. When clicking on the "Add Child" button, the [*Create User*](/guide/dashboard/users#creating-users) view is displayed and set up with the child creation path, with the currently selected user already defined as a parent. |
| | **Wallets** | All the user Wallets for you to manage. Find out more in the [Wallets](/guide/wallets/introduction) article. |
| | **Cards** | All the user Cards for you to manage. Find out more in the [Cards](/guide/cards/introduction) article. |
| | **Beneficiaries** | All the user external accounts, sorted by usage. Find out more in the [Beneficiaries](/guide/transfers/beneficiaries) article. |
### User Overview
The user *Overview* tab displays information that depends on your activated features and the selected user type. You can see the main information at a glance and then use the links to dive into the details of the user's wallets and cards for instance.
#### Wallets section
The overview *Wallets* section displays the first few wallets, but also the overall [Balances](/guide/wallets/balances), that is to say the sum of balances of all the user's wallets.
For each displayed wallet, the following commands are available:
| | Action | Description |
| --- | --- | --- |
| | **Star** | Adds wallet as favorite. |
| | **Unstar** | Remove from favorites. |
| | **More** | Provide access to the **Download document** command, which allows you to select a PDF document to download. Learn more in the [Wallet commands](./wallets#wallet-commands) section. |
| | **Details** | Switches the view to the [*Wallets*](./wallets#navigating-the-wallet-s-information) tab, with the corresponding wallet details displayed. |
The "See all wallets" button is displayed in the bottom right corner if there are more wallets than the ones displayed in the overview. It indicates the total number of wallets and switches the view to the [*Wallets*](./wallets#navigating-the-wallet-s-information) tab when clicking on it.
#### Cards section
The overview *Cards* section displays the first few cards, with all their key information.
Clicking on the details arrow switches the view to the [*Cards*](./cards#profiles-board-view-cards-tab) tab with the selected card details displayed.
The "See all cards" button is displayed in the bottom right corner if there are more cards than the ones displayed in the overview. It indicates the total number of cards and switches the view to the [*Cards*](./cards#profiles-board-view-cards-tab) tab when clicking on it.
### Children users
Hierarchical relations can exist between users, such as:
* Family relations (a parent and actual children, usually minor).
* Ownership relations between a company and its shareholders and representative.
* Company relations with their employees.
Because declarative data changes depending on the use case, the Dashboard offers as much context as possible, with specific tab names ("Children users" for physical users, "Company members" for legal entities), and the relevant [user creation path](/guide/dashboard/users#creating-users) when clicking on the "Add Child" button.
A few [use case examples](/guide/users/parent-children#use-cases) are available in the API Guides.
## Creating users
There are multiple buttons across the Dashboard to access the *Create User* view. This offers a series of creation paths tailored to the context.
The creation paths are exhaustive so you can fill in all the information at once, including:
* Fill declarative data
* Upload documents
* Declare tax residence
* Create children users (company numbers, employees, parent-children relations, etc.)
Information to fill in may differ depending on the creation path and your own model. Please note that non-required information and documents may be updated after the user creation (but before requesting a KYC Review).
### Specific options
Here are a few specific features that may be available depending on your path.
| Options | Physical | Business | Self-Employed |
| --- | :---: | :---: | :---: |
| **Select parent** Enter the parent user ID to create hierarchical relation. | | | |
| **Prefill data** Use legal registration number to prefill data. | | | |
| **Add company members** Create hierarchical relations and declare shareholders and legal representatives. | | | |
## Deleting a User
When a User is not in business with you anymore, you may [delete](/guide/users/introduction#deletion) them.
**Prerequisites – To delete a User**
* The Balance of all of their Wallets must be `0`
* No card transaction authorization can be pending
To delete a user, you can use the "Delete user" button accessible from their profile. This action is irreversible.
A success message is then displayed in the top of the view and the user status becomes "Deleted".
**Note – Users can't be removed**
For regulatory reasons, users can't be removed. Once deleted, they will still be displayed in the user list, with a "Deleted" status.
## Managing SCA devices
The Dashboard allows you to manage the devices used by the end user for [Strong Customer Authentication (SCA)](/guide/strong-customer-authentication/introduction).
You may find information about SCA devices in the *User details* view, *Profile* tab, if enabled in the Configuration. Each device corresponds to a created [SCA Wallet](/guide/strong-customer-authentication/introduction#sca-wallet-object) for the selected user on either:
* A mobile device ([SDK implementation](/guide/strong-customer-authentication/sdk))
* A web browser ([Web Native implementation](/guide/strong-customer-authentication/introduction#web-native))
The following information is available regarding the SCA devices: status, creation date, device information (web or mobile), and the tag (custom information).
The following device statuses can be displayed:
* **Passcode missing** – User has to set their PIN (initially or after reset request).
* **Active** – User has set their PIN. The device may be used for SCA.
* **Locked** – The device has been locked.
Available commands depend on the device status and your [User Role](/guide/dashboard/dashboard-users):
| | Command | Description |
| :---: | --- | --- |
| | **Reset PIN** | Allows you to send a request to the end user to reset their SCA PIN code. For mobile devices only. Should only be done if you're sure of the user identity. |
| | **Secure SCA** | Allows you to [lock the device](#securing-sca-on-a-device), hence not allowing the user go through strong customer authentication. |
| | **Unlock SCA** | Allows you to unlock the device. Should only be done if you're sure of the user identity. |
| | **Delete SCA** | Allows you to delete the device. |
You can use the status filter to access the list of all the devices that used to be enrolled. This may prove useful for customer services and fraud analysis for instance.
### Securing SCA on a device
You may lock the device used for Strong Customer Authentication by using the "Secure SCA on this device" command.
When doing so, you are prompted to select a reason for securing the device, and you can add a securing message.
As a result, the device is "Blocked" and the entered information is displayed in the "Lock reason" and "Message" fields.
**Security – End user information must be verified prior to unlocking**
The "Unlock SCA for this device" and "Reset PIN" commands are available, but should be used with caution. It is your responsibility to make sure the user information is accurate to avoid any kind of fraudulent behavior.
---
---
url: /guide/user-verification/qes.md
description: >-
Technical guide for verifying users (KYC) with qualified eSignature (QES) via
the Treezor API. Includes required parameters, request structure, and response
examples.
---
# Qualified eSignature (QES)
Some countries (such as Germany) enforce stricter standards on user verification. One way to follow such standards is by using a [Qualified Electronic Signature (QES)](/guide/overview/glossary#qualified-electronic-signature-qes). For Germany, this option requires a SEPA transfer into the user's Wallet as an extra validation step.
Treezor relies on a user verification provider for QES services. In this process, you redirect end users to a URL where they follow the verification steps. The identity document uploaded during these steps is digitally signed according to QES standards.
**Configuration – Environment configuration by Treezor**
Contact Treezor to use the qualified eSignature feature.
## Process
1. You initiate QES verification for the User: [`/v1/users/{userId}/qes`](/api-reference/api-endpoints.html#tag/Verification%20Solutions%20\(KYC\)/postKycqes){target="\_self"}
2. Treezor answers with the QES URL (`identificationURL`).
3. You redirect the User to the `identificationURL`
4. The User follows the step-by-step QES verification process, hence uploading the document.
5. Treezor informs you of the documents processing with the [QES](/guide/user-verification/events#qualified-esignature) webhooks.
6. Once the [`qes.finalized`](/guide/user-verification/events#qes-finalized) webhook returns a success `Result`, you may request a [KYC review](#request-a-review-of-the-user): [`/v1/users/{userId}/Kycreview`](/api-reference/api-endpoints.html#tag/User%20KYC%20Review/putKycreview){target="\_self"}
7. Treezor sends you the [`user.kycreview`](events#user-kycreview) webhook upon validation or refusal.
## Key attributes (webhooks)
QES verification relies on webhooks to provide you with information regarding the process:
* [`qes.created`](/guide/user-verification/events#qes-created) – Received when the user completes the QES verification process.
* [`qes.processing`](/guide/user-verification/events#qes-processing) – Received when the QES verification process is under review on the verification provider side.
* [`qes.aborted `](/guide/user-verification/events#qes-aborted) – Received when the user abandons the QES process (see [Aborted reasons](#aborted-reasons) list for more details).
* [`qes.finalized`](/guide/user-verification/events#qes-finalized) – Received when the verification process is done on the verification provider side, either successful or canceled (see [Canceled reasons](#canceled-reasons) list for more details).
Below some of the key attributes you may find in these webhooks.
| Attribute | Type | Description |
| --- | --- | --- |
| `result` | string | Indicates whether the user was successfully verified on the provider side. Can be: `START` – The verification process has started.`CHECK_PENDING` – The user is currently being verified.`FRAUD_SUSPICION_PENDING` – Further verifications are made due to fraud suspicions.`ABORTED` – The end user abandoned the QES verification process.`SUCCESS` – The end user's identity is verified.`SUCCESS_DATA_CHANGE` – The end user's identity is verified with data adjustments from provider.`FRAUD_SUSPICION_CONFIRMED` – The user identity is verified and is suspected of committing fraud.`CANCELED` – The verification couldn't be carried out by the provider. |
| `reason` | object | Details about the result when necessary. See [Reasons list](#reasons) below. |
### Reasons
The reason object of the webhook contains a `reasonCode` and a `reasonMessage` for you to better understand the result of the QES verification.
#### Aborted reasons
Here are the reasons you may find for aborted QES.
| Code | Message | Description |
|-------------|----------------|-------------|
| `3001` | `USER_CANCELLATION_DOCUMENT_NOT_ACCEPTED` | User's ID document is not accepted for the verification process |
| `3002` | `USER_CANCELLATION_DOCUMENT_EXPIRED` | User cannot continue the verification process due to an expired ID document |
| `3003` | `USER_CANCELLATION_UNDERAGE` | User is underage and is not allowed to continue the verification process |
| `3004` | `USER_CANCELLATION_CAMERA_ACCESS_DENIED` | User does not allow camera permission in the app |
| `3005` | `USER_CANCELLATION_TERMS_DENIED` | User does not accept the terms and conditions |
| `3006` | `USER_CANCELLATION_SELFIE_NOT_READY` | User is not ready for a selfie |
| `3007` | `USER_CANCELLATION_APP_NOT_SCANNING` | User aborts as the app is not scanning the document |
| `3008` | `USER_CANCELLATION_ESIGNING_REJECTED` | User does not accept the esigning request |
| `3009` | `USER_CANCELLATION_ESIGNING_NAME_CONFIRMATION_REJECTED` | User's name is specified incorrectly (This applies only to the QES/Signing flow) |
| `3010` | `USER_CANCELLATION_INCORRECT_PHONE_NUMBER` | User cancels as the phone number is specified incorrectly |
| `3011` | `USER_CANCELLATION_IDENTIFY_LATER` | User wants to identify later |
| `3012` | `USER_CANCELLATION_USER_NOT_INTERESTED` | User is not interested in performing the identity verification |
| `3013` | `USER_CANCELLATION_APP_NOT_RESPONDING` | User aborts because the app is not responding |
| `3014` | `USER_CANCELLATION_PRIVACY_CONCERNS` | User aborts due to privacy concerns |
| `3015` | `USER_CANCELLATION_DOCUMENT_NOT_AVAILABLE` | User does not have the ID document available and aborts |
| `3016` | `USER_CANCELLATION_OTHER` | User aborts the identification process in app for any other unspecified reason |
| `3017` | `APP_CANCELLATION_APPROVAL_PHRASE_RETRY_LIMIT_REACHED` | This is used in the QES/esign flow when the app is unable to retrieve the approval phrases from the back end after multiple retries |
| `3018` | `APP_CANCELLATION_APPROVAL_PHRASE_NO_CONTRACT` | App encounters a technical error in the Approval Phrases step in QES/esign |
| `3019` | `APP_CANCELLATION_APPROVAL_PHRASE_INSUFFICIENT_DOCUMENT_COUNT` | In the Approval Phrases step for QES/esign, the required number of documents to be signed are not received from back end |
| `3020` | `APP_CANCELLATION_OTP_MATCH_LIMIT_REACHED` | In the OTP Authentication step, the user has reached the allowed limit for number of OTP entries and cannot try again |
| `3021` | `APP_CANCELLATION_TSP_TECHNICAL_EXCEPTION` | App encounters a technical error from the TSP side. If this error state does not resolve after multiple automatic retries, the user cannot proceed further and the ident is aborted with this reason |
#### Canceled reasons
Here are the reasons you may find for canceled QES.
| Code | Message | Description |
|-------------|----------------|-------------|
| `3101` | `ID_BLURRY` | Document is blurry and mandatory data cannot be read due to the blur. |
| `3102` | `ID_GLARE` | Document has glare and mandatory data cannot be read due to the glare. |
| `3103` | `ID_DARKNESS` | Pictures of the document are dark and it is not possible to read the mandatory data or verify the authenticity of the document. |
| `3104` | `ID_DATA_COVERED` | Mandatory data is covered by the user while taking the picture |
| `3105` | `ID_PERSPECTIVE` | Document is positioned at such an angle that mandatory data cannot be read or document cannot be verified |
| `3106` | `ID_DATA` | Mandatory data cannot be read on the document |
| `3107` | `ID_DATA_OTHER` | Any other reason due to which mandatory data cannot be read |
| `3108` | `ID_NOT_SUPPORTED` | Document used during the identification is not supported for the customer's use case |
| `3109` | `ID_EXPIRED` | Document used during the identification is expired. |
| `3110` | `ID_WRONG_SIDE` | Wrong side of the document is scanned during the process. |
| `3111` | `ID_OUTWORN` | Document is worn out. Either data cannot be read out or the document cannot be verified. |
| `3112` | `ID_HAS_STICKER` | Document has such stickers which are not acceptable and the document used is considered as damaged document. |
| `3113` | `ID_WRITTEN_ON` | Document has text written over it which makes the document not readable or not verifiable. If the sticker is legit one and added by the authorities while issuing the document then the document will be acceptable and not cancelled due to this reason. |
| `3114` | `ID_BROKEN` | Document used during the identification is broken. |
| `3115` | `ID_DAMAGED` | Document used during identification is a damaged document. |
| `3116` | `ID_DAMAGED_OTHER` | Any other reason for a damaged document. |
| `3117` | `ID_SECURITY_FEATURE_NOT_VISIBLE_NOT_FRAUD` | Security features of the document are not visible because user did not move the document correctly. |
| `3118` | `ID_SECURITY_FEATURE_VIDEO_SHORT` | Security feature video is too short to detect if there are holograms in the document. |
| `3119` | `ID_SECURITY_FEATURE_VIDEO_CANNOT_BE_PLAYED` | Security feature video cannot be played for the agent to review holograms. |
| `3120` | `ID_SECURITY_FEATURE_OTHER` | Any other issues with the security feature video. |
| `3121` | `ID_SECOND_DOCUMENT` | If two documents are required for the identification process, the user needs to photograph two different documents (i.e. ID + Driver's license) - If the second required ID document is not available, the ident will be cancelled. |
| `3122` | `ID_SECOND_DOCUMENT_BAD_PHOTO_QUALITY` | Photo quality of the additional document in the process is not acceptable. |
| `3123` | `ID_SECOND_DOCUMENT_DAMAGED` | Additional document used in the identification process is severely outworn, written or drawn on, ripped or broken. |
| `3124` | `ID_SECOND_DOCUMENT_EXPIRED` | Additional document used in the identification process is an expired document. |
| `3125` | `ID_SECOND_DOCUMENT_OTHER` | Any other issues with the additional document used in the identification process. |
| `3126` | `ID_NEED_ADDITIONAL_DOCUMENT` | Additional document like Driver's License is missing in the identification process but it was required. |
| `3127` | `ID_OTHER` | Any other issues with the document used in the identification process. |
| `3128` | `USER_INVOICE_MISSING` | Customer needs proof of address from the user as the additional document but user did not provide it in the identification process. |
| `3129` | `USER_OBSCURED` | User has covered the face during the face comparison process unintentionally like wearing the face mask. |
| `3130` | `SELFIE_BLURRY` | Selfie taken by the user is blurry and cannot be used to compare the face with the identification document. |
| `3131` | `SELFIE_GLARE` | Photo of the user on the ID document has glares and selfie cannot be compared with it. |
| `3132` | `SELFIE_DARKNESS` | Selfie taken by the user is too dark to compare the face of the person with the photo on the identification document. |
| `3133` | `SELFIE_PERSPECTIVE` | Selfie taken by the user is on such an angle that it is not possible to compare it with the photo on the identification document. |
| `3134` | `SELFIE_OTHER` | Any other issues with the selfie which restrict ident specialist to compare the selfie of the user with the photo on the identification document. |
| `3135` | `IDENT_CANNOT_BE_COMPLETED` | Due to a technical reason, ident specialist cannot finish the identity verification process. |
| `3136` | `IDENT_DISPLAY_ERROR` | Due to a technical reason, ident specialist cannot see the data submitted by the user in the identification process. |
| `3137` | `IDENT_OTHER` | Any other reason due to which the identification process cannot be completed by the ident specialist. |
| `3138` | `TSP_WRONG_CONFIRMATION_TOKEN` | A wrong signing code was entered by the user during the signing step. |
| `3139` | `TSP_SIGNING_FAILED` | The signing process failed due to any technical error. |
| `3140` | `TSP_CERTIFICATE_EXPIRED` | Signing certificates are valid for an hour. The final signing step took more than an hour from the time of certificate generation. |
| `3141` | `ID_SECURITY_FEATURE_VIDEO_FILE_MISSING` | If enabled, the system automatically cancels an ident when the 'Security Features' (Hologram) video is not saved due to any technical error, and is hence missing from the final result (zip) file. |
#### Fraud suspicion reasons
**Important – Don't communicate fraud suspicion to end users**
For legal reasons, you mustn't indicate to end users that they are suspected of fraud.
Here are the reasons you may find for fraud suspicions.
| Code | Message | Description |
|-------------|----------------|-------------|
| `3201` | `WARNING_SELFIE_REAL_PERSON` | User that performed the identification is a real person but the selfie does not match with the face on the document. |
| `3202` | `WARNING_SELFIE_NO_REAL_PERSON` | Selfie taken in the identification person is not of a real person. For example, the selfie taken is a photo of a picture. |
| `3203` | `WARNING_SELFIE_DISGUISED` | User intentionally disguised the face by wearing a mask or in some other way. |
| `3204` | `WARNING_MANIPULATED_DATA` | Data is manipulated on the Identification document. |
| `3205` | `WARNING_MANIPULATED_PHOTO` | Photo of the person is manipulated on the Identification document. |
| `3206` | `WARNING_FAKED_SECURITY_FEATURES` | Security features like holograms on the Identification document are not real. |
| `3207` | `WARNING_PAPER_PRINT` | The Identification document is not real but a printout taken on a paper. |
| `3208` | `WARNING_DIGITAL_DOCUMENT` | Identification document image is taken from a digital screen (from laptop, from mobile or from any other screen). |
| `3209` | `WARNING_FAKED_SPECIMEN` | Identification document is a specimen document and not real document. |
| `3210` | `WARNING_USER_UNDERAGE` | User is below the age required to access the customer's service. |
| `3211` | `WARNING_DIGITAL_SELFIE` | Selfie is taken from a digital screen (from laptop, from mobile or from any other screen). |
| `3212` | `WARNING_MONEY_MULE` | User is duped by fraudster to perform identification on fraudster's behalf. |
| `3213` | `WARNING_NAME_COMPARISON` | Considerable inconsistency between user's name and document. |
| `3214` | `WARNING_SCAN` | Identification document is a facsimile. |
| `3215` | `WARNING_FRAUD_OTHER` | Any other type of fraud identified during the verification process by Ident specialist. |
## Initiate QES verification
Before initiating the QES verification process, the User must be created with the relevant attributes (as required by Treezor Compliance).
At least the `firstname`, `lastname`, `email`, `country`, and `phone` fields of the user must be populated, otherwise, the API call returns an HTTP 428 error.
### Parameters
You can optionally override the default URL to which the user will be redirected after the QES verification.
| Attribute | Type | Description |
| --- | --- | --- |
| `redirectUrl` | string | The URL to which the User will be redirected after the QES verification. |
### Request
You can use the following request to initiate the QES verification process.
```bash [CURL]
curl -X POST '{baseUrl}/v1/users/{userId}/qes' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{"redirectUrl": "https://www.my-domain.tld"}'
```
Answers with a 201 HTTP Status Code and returns the identifier of the verification process and the `identificationURL`. The latter is where the end user is to be redirected to go through the qualified electronic signature process.
```json [JSON]
{
"identification": {
"identificationId": "{identification-id}",
"identificationURL": "https://go.idnow.de/app/treezoramlauto/identifications/{identification-id}/identification/routing/start",
}
}
```
Once redirected, end users are guided through the QES verification steps, in which they present a verification document. End users have 90 days to complete the steps; after this delay, the `identificationURL` expires.
### End user QES verification
Once redirected, end users are guided through the QES steps.
After the last step:
* The user is redirected to the `redirectUrl` or the URL configured with Treezor.
* Treezor sends you a `qes.created` webhook.
* The verification documents are automatically created once the `qes.finalized` webhook is received.
## Download the QES documents
If you're eligible, you may be able to collect some of the uploaded documents whose `documentTypeId` allows for it.
**Configuration – Download is not enabled by default**
Please contact Treezor to request access to this feature.
Downloading a document is a 2-step process, in which you:
1. [Request the download URL](#request-the-download-url)
2. [Download the document within 30 seconds](#download-the-document)
### Request the download URL
To request the download URL, you need the corresponding `documentId` (available in the `document.create` webhook for instance).
```bash [CURL]
curl -X GET '{baseUrl}/v1/documents/{documentId}/download' \
--header 'Authorization: Bearer {accessToken}'
```
Returns the URL to download the document, with all the necessary query parameters for the next step.
```json [JSON]
{
"url": "{documentDownloadUrl}"
}
```
### Download the document
You have 30 seconds to download the document from the moment the presigned URL has been generated in the previous step.
```bash [CURL]
curl -X GET '{documentDownloadUrl}'
```
The document is returned in its initial format.
## Request a KYC Review for the User
Before requesting a KYC review from Treezor, please make sure all the information and documents are properly updated for the user.
You can use the dedicated endpoint:
* [`/v1/users/{userId}/Kycreview`](/api-reference/api-endpoints.html#tag/User%20KYC%20Review/putKycreview){target="\_self"}
**Alert – Documents must be uploaded for children users too**
When there are [parent-children hierarchical relationship](/guide/users/parent-children), in most cases, the KYC Review must only be requested for the parent user. But you may need to upload [Documents](./documents) for the children before that. Please abide by the Treezor Compliance team recommendation for a smooth experience.
Learn more in the [KYC Request](./kyc-request) article.
## Endpoints
| Endpoint |[Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/v1/users/{userId}/qes`](/api-reference/api-endpoints.html#tag/Verification%20Solutions%20\(KYC\)/postKycqes){target="\_self"} Initiate the user [QES verification](/guide/user-verification/introduction) process | `read_write` |
| [`/v1/documents/{documentId}/download`](/api-reference/api-endpoints.html#tag/User%20Documents/getDocumentDownloadUrl){target="\_self"} Retrieve a document download URL | `read_only` |
| [`/v1/users/{userId}/Kycreview`](/api-reference/api-endpoints.html#tag/User%20KYC%20Review/putKycreview){target="\_self"} Initiate the user [KYC review](/guide/user-verification/introduction) process | `read_write` |
---
---
url: /guide/user-verification/videoconf.md
description: >-
Technical guide for verifying users (KYC) with Video Conference via the
Treezor API. Includes required parameters, request structure, and response
examples.
---
# Video Conference
The Video Conference feature verifies the user through an online video call with an expert. The expert reviews the ID card and asks key questions to the end user to ensure they are who they claim to be.
Treezor relies on a user verification provider for Video Conference services. In this process, you redirect end users to a URL where they follow verification steps, including a video conference with an agent.
**Configuration – Environment configuration by Treezor**
Contact Treezor to use the video conference feature.
## Process
1. You initiate video conference verification for the User: [`/v1/users/{userId}/videoconference`](/api-reference/api-endpoints.html#tag/Verification%20Solutions%20\(KYC\)/postKycVconf){target="\_self"}
2. Treezor answers with the video conference URL (`identificationURL`).
3. You redirect the User to the `identificationURL`
4. The User follows the step-by-step process, hence uploading the document (ID) while online with the expert.
5. Treezor informs you of the documents processing with the [Video Conference](/guide/user-verification/events#video-conference) webhooks.
6. Once the [`videoConference.finalized`](/guide/user-verification/events#video-conference) webhook returns a success `Result`, you may request a [KYC review](#request-a-review-of-the-user): [`/v1/users/{userId}/Kycreview`](/api-reference/api-endpoints.html#tag/User%20KYC%20Review/putKycreview){target="\_self"}
7. Treezor sends you the [`user.kycreview`](events#user-kycreview) webhook upon validation or refusal.
## Key attributes (webhooks)
Video conference relies on webhooks to provide you with information regarding the process:
* [`videoConference.created`](/guide/user-verification/events#videoconference-created) – Received when the user completes the video conference verification process.
* [`videoConference.processing`](/guide/user-verification/events#videoconference-processing) – Received when the video conference verification process is under review on the verification provider side.
* [`videoConference.aborted`](/guide/user-verification/events#videoconference-aborted) – Received when the user abandons the video conference process (see [Aborted reasons](#aborted-reasons) list for more details).
* [`videoConference.finalized`](/guide/user-verification/events#videoconference-finalized) – Received when the verification process is done on the verification provider side, either successful or canceled (see [Canceled reasons](#canceled-reasons) list for more details).
| Attribute | Type | Description |
| --- | --- | --- |
| `result` | string | Indicates whether or not the user was successfully verified on the provider side. Can be: `START` – The verification process has started.`REVIEW_PENDING` – The user is currently being verified.`FRAUD_SUSPICION_PENDING` – Further verifications are made due to fraud suspicions.`ABORTED` – The end user abandoned the verification process.`SUCCESS` – The end user's identity is verified.`SUCCESS_DATA_CHANGE` – The end user's identity is verified with data adjustments from provider.`FRAUD_SUSPICION_CONFIRMED` – The user identity is verified and is suspected of committing fraud.`CANCELED` – The verification couldn't be carried out by the provider. |
| `reason` | object | Details about the result when necessary. See [Reasons list](#reasons) below. |
### Reasons
The reason object of the webhook contains a `reasonCode` and a `reasonMessage` for you to better understand the result of the Video Conference verification.
#### Aborted reasons
Here are the reasons you may find for aborted video conference.
| Code | Message | Description |
|-------|------------|------------------|
| `4001`| `USER_CANCELLATION_DOCUMENT_NOT_ACCEPTED`| User's ID document is not accepted for the verification process. |
| `4002`| `USER_CANCELLATION_DOCUMENT_EXPIRED` | User cannot continue the verification process due to an expired ID document.|
| `4003`| `USER_CANCELLATION_UNDERAGE` | User is underage and is not allowed to continue the verification process. |
| `4004`| `USER_CANCELLATION_CAMERA_ACCESS_DENIED` | User does not allow camera permission in the app. |
| `4005`| `USER_CANCELLATION_TERMS_DENIED` | User does not accept the terms and conditions. |
| `4006`| `USER_CANCELLATION_SELFIE_NOT_READY` | User is not ready for a selfie. |
| `4007`| `USER_CANCELLATION_APP_NOT_SCANNING` | User aborts as the app is not scanning the document. |
| `4008`| `USER_CANCELLATION_INCORRECT_PHONE_NUMBER` | User cancels as the phone number is specified incorrectly. |
| `4009`| `USER_CANCELLATION_IDENTIFY_LATER` | User wants to identify later. |
| `4010`| `USER_CANCELLATION_USER_NOT_INTERESTED` | User is not interested in performing the identity verification. |
| `4011`| `USER_CANCELLATION_APP_NOT_RESPONDING` | User aborts because the app is not responding. |
| `4012`| `USER_CANCELLATION_PRIVACY_CONCERNS` | User aborts due to privacy concerns. |
| `4013`| `USER_CANCELLATION_DOCUMENT_NOT_AVAILABLE` | User does not have the ID document available and aborts. |
| `4014`| `APP_CANCELLATION_OTP_MATCH_LIMIT_REACHED` | User has reached the allowed limit for number of OTP entries and cannot try again. |
| `4015`| `USER_CANCELLATION_AGENT_BEHAVIOUR` | User does not feel comfortable to continue identification due to the agent's behaviour. |
#### Canceled reasons
Here are the reasons you may find for canceled video conference.
| Code | Message | Description |
|-------|---------------|---------------|
| `4101`| `ID_BLURRY` | Document is blurry and mandatory data cannot be read due to the blur. |
| `4102`| `ID_GLARE` | Document has glare and mandatory data cannot be read due to the glare. |
| `4103`| `ID_DARKNESS` | Pictures of the document are dark and it is not possible to read the mandatory data or verify the authenticity of the document. |
| `4104`| `ID_DATA_COVERED` | Mandatory data is covered by the user while taking the picture. |
| `4105`| `ID_PERSPECTIVE` | Document is positioned at such an angle that mandatory data cannot be read or document cannot be verified. |
| `4106`| `ID_DATA_OTHER` | Any other reason due to which mandatory data cannot be read. |
| `4107`| `ID_NOT_SUPPORTED` | Document used during the identification is not supported for the customer's use case. |
| `4108`| `ID_EXPIRED` | Document used during the identification is expired. |
| `4109`| `ID_WRONG_SIDE` | Wrong side of the document is scanned during the process. |
| `4110`| `ID_OUTWORN` | Document is worn out. Either data cannot be read out or the document cannot be verified. |
| `4111`| `ID_HAS_STICKER` | Document has such stickers which are not acceptable and the document used is considered as damaged document. |
| `4112`| `ID_WRITTEN_ON` | Document has text written over it which makes the document not readable or not verifiable. If the sticker is legit one and added by the authorities while issuing the document then the document will be acceptable and not cancelled due to this reason. |
| `4113`| `ID_BROKEN` | Document used during the identification is broken. |
| `4114`| `ID_DAMAGED_OTHER` | Any other reason for a damaged document. |
| `4115`| `ID_SECURITY_FEATURE_NOT_VISIBLE_NOT_FRAUD` | Security features of the document are not visible because user did not move the document correctly. |
| `4116`| `ID_SECURITY_FEATURE_VIDEO_SHORT` | Security feature video is too short to detect if there are holograms in the document. |
| `4117`| `ID_SECURITY_FEATURE_VIDEO_CANNOT_BE_PLAYED` | Security feature video cannot be played for the agent to review holograms. |
| `4118`| `ID_SECURITY_FEATURE_OTHER` | Any other issues with the security feature video. |
| `4119`| `ID_SECOND_DOCUMENT_BAD_PHOTO_QUALITY` | Photo quality of the additional document in the process is not acceptable. |
| `4120`| `ID_SECOND_DOCUMENT_DAMAGED` | Additional document used in the identification process is severely outworn, written or drawn on, ripped or broken. |
| `4121`| `ID_SECOND_DOCUMENT_EXPIRED` | Additional document used in the identification process is an expired document. |
| `4122`| `ID_NEED_ADDITIONAL_DOCUMENT` | Additional document like Driver's License is missing in the identification process but it was required. |
| `4123`| `ID_SECOND_DOCUMENT_OTHER` | Any other issues with the additional document used in the identification process. |
| `4124`| `ID_OTHER` | Any other issues with the document used in the identification process. |
| `4125`| `USER_INVOICE_MISSING`| Customer needs proof of address from the user as the additional document but user did not provide it in the identification process. |
| `4126`| `USER_OBSCURED` | User has covered the face during the face comparison process unintentionally like wearing the face mask. |
| `4127`| `SELFIE_BLURRY` | Selfie taken by the user is blurry and cannot be used to compare the face with the identification document. |
| `4128`| `SELFIE_GLARE` | Photo of the user on the ID document has glares and selfie cannot be compared with it. |
| `4129`| `SELFIE_DARKNESS` | Selfie taken by the user is too dark to compare the face of the person with the photo on the identification document. |
| `4130`| `SELFIE_PERSPECTIVE` | Selfie taken by the user is on such an angle that it is not possible to compare it
#### Final reasons
Here are the reasons you may find for finalized video conference.
| Code | Message | Description |
|-------|------------------------------------|-------------------------------------------------------------------------------------------------|
| `4201`| `WARNING_SELFIE_REAL_PERSON` | User that performed the identification is a real person but the selfie does not match with the face on the document. |
| `4202`| `WARNING_SELFIE_NO_REAL_PERSON` | Selfie taken in the identification process is not of a real person. For example, the selfie taken is a photo of a picture. |
| `4203`| `WARNING_SELFIE_DISGUISED` | User intentionally disguised the face by wearing a mask or in some other way. |
| `4204`| `WARNING_MANIPULATED_DATA` | Data is manipulated on the Identification document. |
| `4205`| `WARNING_MANIPULATED_PHOTO` | Photo of the person is manipulated on the Identification document. |
| `4206`| `WARNING_FAKED_SECURITY_FEATURES` | Security features like holograms on the Identification document are not real. |
| `4207`| `WARNING_PAPER_PRINT` | The Identification document is not real but a printout taken on a paper. |
| `4208`| `WARNING_DIGITAL_DOCUMENT` | Identification document image is taken from a digital screen (from laptop, from mobile or from any other screen). |
| `4209`| `WARNING_FAKED_SPECIMEN` | Identification document is a specimen document and not a real document. |
| `4210`| `WARNING_USER_UNDERAGE` | User is below the age required to access the customer's service. |
| `4211`| `WARNING_DIGITAL_SELFIE` | Selfie is taken from a digital screen (from laptop, from mobile or from any other screen). |
| `4212`| `WARNING_MONEY_MULE` | User is duped by fraudster to perform identification on fraudster's behalf. |
| `4213`| `WARNING_NAME_COMPARISON` | Considerable inconsistency between user's name and document. |
| `4214`| `WARNING_SCAN` | Identification document is a facsimile. |
| `4215`| `WARNING_FRAUD_OTHER` | Any other type of fraud identified during the verification process by Ident specialist. |
## Initiate Video conference verification
Before initiating the video conference verification process, the User must be created with the relevant attributes (as required by Treezor Compliance).
At least the `firstname`, `lastname`, `email`, `country`, and `phone` fields of the user must be populated, otherwise, the API call returns an HTTP 428 error.
### Parameters
You can optionally override the default URL to which the user will be redirected after the video conference verification.
| Attribute | Type | Description |
| --- | --- | --- |
| `redirectUrl` | string | The URL to which the User will be redirected after the video conference verification. |
### Request
You can use the following request to initiate the video conference verification process.
```bash [CURL]
curl -X POST '{baseUrl}/v1/users/{userId}/videoconference' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{"redirectUrl": "https://www.my-domain.tld"}'
```
Answers with a 201 HTTP Status Code and returns the identifier of the verification process and the `identificationURL`. The latter is where the end user is to be redirected to go through the video conference verification process.
```json [JSON]
{
"identification": {
"identificationId": "{identification-id}",
"identificationURL": "https://go.idnow.de/app/treezoramlauto/identifications/{identification-id}/identification/routing/start",
}
}
```
Once redirected, end users have 90 days to complete the steps. After this delay, the `identificationURL` expires.
### End user video verification
Once redirected, end users are guided through the video conference verification steps, in which they present a verification document while talking online with the expert.
## Download the documents
If you're eligible, you may be able to collect some of the uploaded documents whose `documentTypeId` allows for it.
**Configuration – Download is not enabled by default**
Please contact Treezor to request access to this feature.
Downloading a document is a 2-step process, in which you:
1. [Request the download URL](#request-the-download-url)
2. [Download the document within 30 seconds](#download-the-document)
### Request the download URL
To request the download URL, you need the corresponding `documentId` (available in the `document.create` webhook for instance).
```bash [CURL]
curl -X GET '{baseUrl}/v1/documents/{documentId}/download' \
--header 'Authorization: Bearer {accessToken}'
```
Returns the URL to download the document, with all the necessary query parameters for the next step.
```json [JSON]
{
"url": "{documentDownloadUrl}"
}
```
### Download the document
You have 30 seconds to download the document from the moment the presigned URL has been generated in the previous step.
```bash [CURL]
curl -X GET '{documentDownloadUrl}'
```
The document is returned in its initial format.
## Request a KYC Review for the User
Before requesting a KYC review from Treezor, please make sure all the information and documents are properly updated for the user.
You can use the dedicated endpoint:
* [`/v1/users/{userId}/Kycreview`](/api-reference/api-endpoints.html#tag/User%20KYC%20Review/putKycreview){target="\_self"}
**Alert – Documents must be uploaded for children users too**
When there are [parent-children hierarchical relationship](/guide/users/parent-children), in most cases, the KYC Review must only be requested for the parent user. But you may need to upload [Documents](./documents) for the children before that. Please abide by the Treezor Compliance team recommendation for a smooth experience.
Learn more in the [KYC Request](./kyc-request) article.
## Endpoints
| Endpoint |[Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/v1/users/{userId}/videoconference`](/api-reference/api-endpoints.html#tag/Verification%20Solutions%20\(KYC\)/postKycVconf){target="\_self"} Initiate the user Video Conference verification process | `read_write` |
| [`/v1/documents/{documentId}/download`](/api-reference/api-endpoints.html#tag/User%20Documents/getDocumentDownloadUrl){target="\_self"} Retrieve a document download URL | `read_only` |
| [`/v1/users/{userId}/Kycreview`](/api-reference/api-endpoints.html#tag/User%20KYC%20Review/putKycreview){target="\_self"} Initiate the user [KYC review](/guide/user-verification/introduction) process | `read_write` |
---
---
url: /guide/wallets/error-codes.md
description: >-
Troubleshoot and handle wallet-related issues using the Treezor API's complete
list of error codes, messages, and their corresponding meanings.
---
# Errors
**Caution – Only the legacy API sends the error code in HTTP errors**
When handling errors with Connect, only the `message` attribute is returned.
## Wallets
The following API errors can be encountered when dealing with wallets.
| Code | Message | Additional information |
|:---: |--- |--- |
| `12001` | Impossible to read Wallet | |
| `12002` | Impossible to create Wallet | |
| `12010` | Impossible to update Wallet | |
| `12011` | Impossible to update Wallet, the wallet is already canceled | |
| `12012` | eventPayinStartDate format is not valid | |
| `12013` | eventPayinEndDate format is not valid | |
| `12014` | eventPayinStartDate cannot be earlier than the creation date of the wallet | |
| `12015` | eventPayinStartDate can't succeed eventPayinEndDate | |
| `12016` | eventPayinEndDate cannot be earlier than eventPayinStartDate | |
| `12018` | Impossible to change eventPayinStartDate when a gift is already offered | |
| `12020` | Impossible to Cancel Wallet. The wallet does not exist | |
| `12021` | Impossible to create Wallet image repository | |
| `12022` | Impossible to create Wallet image file | |
| `12023` | Impossible to create Wallet, Tarif is not comform | |
| `12024` | Impossible to create Wallet, Tarif does not exist | |
| `12025` | Impossible to create Wallet, Alias is not unique | |
| `12026` | Unable to create Wallet. The unicity of the alias can't be checked. | |
| `12027` | Impossible to update Wallet, eventPayinEndDate can't be lower than today | |
| `12028` | Impossible to update Wallet, WalletId is not valid | |
| `12029` | Impossible to Cancel Wallet, WalletId is not valid | |
| `12030` | Impossible to Cancel Wallet, The wallet is already in status CANCELLED | |
| `12031` | Impossible to create Wallet, User Id required | |
| `12032` | Impossible to create Wallet, User Id not permitted | |
| `12033` | Impossible to create Wallet, Joint User Id not valid | |
| `12034` | Impossible to create Wallet, Currency must be EUR | |
| `12035` | Unable to create the wallet. eventPayinEndDate cannot be earlier than eventPayinStartDate | |
| `12036` | Impossible to create Wallet, Name is required | |
| `12037` | Unable to create wallet. The event Payin Start Date is mandatory. | |
| `12038` | Unable to create wallet. The event Payin End Date is mandatory. | |
| `12039` | Unable to create wallet. The origin is not correct | |
| `12040` | Unable to Cancel wallet. The origin is not correct | |
| `12041` | Unable to Cancel wallet. Balance is not null. | |
| `12042` | Unable to retrieve a wallet in the Database | |
| `12043` | No status retrieved for wallet in Database | |
| `12044` | The status linked to the wallet has no name | |
| `12045` | The wallet has no user linked impossible to continue | |
| `12046` | The wallet has no Tariff | |
| `12047` | The wallet has no Tariff specified for an incoming SCTR | |
| `12048` | The wallet has no Tariff specified for an incoming SDDR | |
| `12049` | The walletTypeId is missing | |
| `12050` | The walletTypeId must be 9 (Electronic Money Wallet), or 10 (Payment Account Wallet), or 13 (Mirror Account) | |
| `12051` | Impossible to change the type of the wallet due to presence of transactions for this wallet | |
| `12052` | The walletId is missing | |
| `12053` | The beneficiaryName is missing | |
| `12054` | The beneficiaryAddress is missing | |
| `12055` | The beneficiaryIban is missing | |
| `12056` | The beneficiaryBic is missing | |
| `12057` | No status retrieved for wallet in Database | |
| `12058` | The beneficiaryName is not valid | |
| `12059` | The beneficiaryAddress is not valid | |
| `12060` | The beneficiaryIban is not valid | |
| `12061` | The wallet cannot be closed yet | |
| `12062` | The wallet is already closed | |
| `12063` | The wallet have not cards which linked to | |
| `12064` | Error during block card linked to the wallet | |
| `12065` | The request must contains at least one of those inputs : walletId, eventAlias, userId, walletTypeId | |
| `12066` | Impossible to Cancel Wallet, The wallet has pending payin refunds | |
| `12067` | No wallet retrieved | |
| `12068` | Impossible to create Wallet, the user is freezed | Blocked users can't have new wallets. |
| `12069` | Impossible to create Wallet, the user is legal frozen | Users whose assets are frozen can't have new wallets. |
| `12070` | Impossible to cancel the wallet, technical card wallets cannot be canceled | |
| `12071` | Impossible to create the wallet, field bic should not be empty when provided | |
| `12072` | Impossible to create the wallet, the provided bic is not correct | |
| `12073` | Impossible to create the wallet, the provided bic met too much possible candidate | |
| `12074` | Impossible to create the wallet, please provide a valid bic | |
| `12075` | Impossible to create the wallet, invalid payment institution bic | |
| `12076` | Impossible to create the wallet, the bic provided is not authorized | |
| `12077` | Impossible to create the wallet, the iban could not be generated | |
| `12078` | Impossible to create wallet due to user status | Users must be validated to own a wallet. You need to wait until the status is no longer `PENDING`. |
| `12079` | Impossible to create wallet. A legal representative and majority shareholder must be declared. | Create physical users hierarchically attached to the legal entity owning the wallet to declare the legal representative. |
## Anonymous Electronic Money Wallets
Exceeding *Electronic Money Wallets* limitations or restrictions will produce the following errors.
### In Requests
| Context | Endpoint | Code | Message |
|--- |--- |--- |--- |
| SDDE | `/payins` | `14058` | You attempt to create a payin of type SDD Core, The wallet is not of type compte de paiement, impossible to continue |
| Payouts | `/payouts` | `16027` | Impossible to create Payout due to incoherent KYC level |
| Transfers | `/transfers` | `120019` | Impossible to create the operation, the total debit exceed the max total debit limit on sliding period |
| Transfers, Payins | `/transfers`, `/payins` | `120020` | Impossible to create the operation, the authorization amount exceed the max amount limit |
| Transfers, Payins | `/transfers`, `/payins` | `120021` | Impossible to create the operation, the authorization amount added to the account limit exceed the max account amount limit |
| Transfers | `/transfers` | `120022` | Impossible to create the operation, the transfer creditor user is invalid |
| Transfers | `/transfers` | `120023` | Impossible to create the operation, the transfer debitor user is invalid |
| Transfers, Payins | `/transfers`, `/payins` | `120026` | Impossible to create the operation, the total credit exceed the max total credit limit on sliding period |
### In Webhooks
| Context | Webhook | Error | Message (if any) |
|--- |--- |--- |--- |
| SDDR | `sepa.reject_sddr_core` | `reject_reason_code`=`AG01` | |
| SDDR | `sepa.reject_sddr_b2b` | `reject_reason_code`=`AG01` | |
| SDDR | `sepa.return_sddr` | `reject_reason_code`=`AG01` | |
| SCTR | `sepa.return_sctr` | `return_reason_code`=`AG01` | |
| SCTR | `sepa.return_sctr` | `return_reason_code`=`RR04` | |
| SCTR Inst | `sepaSctrInst.reject_sctr_inst` | `return_reason_code`=`RR04` | |
| Card Payment | `cardtransaction.create` | `authorizationResponseCode`=`57` | Electronic Money : transaction not permitted to cardholder |
| Card Payment | `cardtransaction.create` | `authorizationResponseCode`=`57` | Electronic Money : cumulative amount authorized exceeded |
| Card Payment | `cardtransaction.create` | `authorizationResponseCode`=`57` | Electronic Money : amount exceeds the authorized amount |
| Card Payment | `cardtransaction.create` | `authorizationResponseCode`=`57` | Electronic Money : payment is not permitted in this country |
| Card Payment | `cardtransaction.create` | `authorizationResponseCode`=`57` | Electronic Money : refused due to error |
## Balances
| Code | Message |
|:---------:|-------------------------------------------------------------------------------------------------------------|
| `24000` | No balance corresponds to your search. |
| `24001` | Exception while attempting to update authorizations |
| `24002` | Impossible to continue operation. Balance data on wallet were not retrieved |
| `24003` | walletId is mandatory |
| `24004` | You must provide at least one argument: walletId or userId |
## Virtual IBANs
The following API errors can be encountered when dealing with [virtual IBANs](/guide/wallets/iban##virtual-iban).
| Code | Message |
|:------:|------------------------------------------------------------------------------------------------------------------|
| `71001` | No Wallet Linked to the Virtual IBAN |
| `71002` | The wallet linked to the IBAN has no status |
| `71003` | Wallet linked to the Virtual Iban has a not permitted Status |
| `71004` | Currency of operation does not match the currency of wallet linked to the virtualIban |
| `71005` | This transaction type is not supported by the virtual IBAN System |
| `71006` | Transaction type not specified in virtual Iban Object impossible to check validity of virtual Iban regarding operation |
| `71007` | Transaction type of operation is not supported by the virtual Iban |
| `71008` | Impossible to add a new transaction for this virtualIban, number of transactions will be exceeded |
| `71009` | Impossible to add a new transaction for this virtualIban, max amount will be exceeded |
| `71010` | Validity date of this virtual Iban is KO |
| `71011` | The virtual iban with the id provided does not exist |
| `71012` | Impossible to create an iban |
| `71013` | The field walletId must be provided |
| `71014` | The field validFrom is lower than current date |
| `71015` | The field validTo is lower than date validFrom |
| `71016` | The field reference has a limit of 255 characters |
| `71017` | The field tag has a limit of 255 characters |
| `71018` | The field maxUsage must be higher than 1 |
| `71019` | The field maxUsage must be higher than the number of transactions made by the virtualIban |
| `71020` | The field maxAmount must be higher than 1 |
| `71021` | The field maxAmount must be higher than the cumulated amount |
| `71022` | The field maxAmount must follow this format: '2.15' |
| `71023` | The field virtualibanId must be provided |
| `71024` | The typeId is required |
| `71025` | The typeId is invalid |
| `71026` | Unable to create virtual IBAN. Database Error. |
| `71027` | Wallet linked to the Virtual Iban has a not permitted type |
## Transactions
The following API errors can be encountered when dealing with [transactions](/guide/wallets/transactions).
| Code | Message |
|:---------:|--------------------------------------------------------------------------------------------------------------------------------------------------------|
| `23000` | Impossible to read Transaction. Database Error. |
| `23001` | Card transaction already in transaction. |
| `23003` | The request must contain at least one of these inputs: walletId, transactionId, executionDate, valueDate. |
| `23004` | createdDateFrom must be a valid YYYY-MM-DD HH:MM:SS date. |
| `23005` | createdDateTo must be a valid YYYY-MM-DD HH:MM:SS date. |
| `23006` | createdDateTo cannot be lower than createdDateFrom. |
| `23007` | transactionTypeId and transactionType do not refer to the same TransactionType. |
| `23008` | transactionType should be a string. |
| `23009` | transactionTypeId should be numeric (string or integer). |
---
---
url: /guide/wallets/events.md
description: >-
Reference a comprehensive list of wallet events for Treezor API webhooks,
detailing each event's structure and payload for integration.
---
# Events
This article lists the [Webhooks](/guide/webhooks/introduction) you may receive when regarding Wallets.
**API – See the [Wallets](/api-reference/api-endpoints.html#tag/Wallets){target="\_self"} API Reference for attributes description**
The detailed information of the Wallet attributes are available in the of the [Wallets](/api-reference/api-endpoints.html#tag/Wallets){target="\_self"} API Reference. Webhooks `object_payload` is identical to the API object.
## Wallet events
### `wallet.create`
Notifies the creation of a Wallet, usually triggered by the [`/v1/wallets`](/api-reference/api-endpoints.html#tag/Wallets/postWallets){target="\_self"} endpoint.
```json [JSON]
{
"webhook": "wallet.create",
"webhook_id": "648614636",
"object": "wallet",
"object_id": "4330619",
"object_payload": {
"wallets": [
{
"walletId": "4330619",
"walletTypeId": "9",
"walletStatus": "VALIDATED",
"userId": "3691057",
"jointUserId": "0",
"walletTag": "62090",
"currency": "EUR",
"eventDate": "2021-04-29",
"eventMessage": "",
"eventAlias": "XXXX",
"eventPayinStartDate": "2021-04-22",
"eventPayinEndDate": "0000-00-00",
"contractSigned": "0",
"urlImage": "",
"createdDate": "2021-04-22 14:54:14",
"modifiedDate": "0000-00-00 00:00:00",
"tariffId": "59",
"eventName": "XXXX",
"userFirstname": "XXXX",
"userLastname": "XXXX",
"codeStatus": "120005",
"informationStatus": "",
"payinCount": "0",
"payoutCount": "0",
"transferCount": "0",
"solde": null,
"authorizedBalance": null,
"bic": "TRZOFR21XXX",
"iban": "XXXX",
"totalRows": 1
}
]
},
"object_payload_signature": "eYIDFtDa3Ai9T+0vRgIFwU0oDYZ2WkcILLRDOBWLAY8="
}
```
### `wallet.update`
Notifies the modification of a Wallet, usually triggered by the [`/v1/wallets/{walletId}`](/api-reference/api-endpoints.html#tag/Wallets/putWallet){target="\_self"} endpoint.
```json [JSON]
{
"webhook": "wallet.update",
"webhook_id": "644808221",
"object": "wallet",
"object_id": "3858134",
"object_payload": {
"wallets": [
{
"walletId": "3858134",
"walletTypeId": "9",
"walletStatus": "VALIDATED",
"userId": "3384099",
"jointUserId": "0",
"walletTag": "",
"currency": "EUR",
"eventDate": "2021-03-02",
"eventMessage": "",
"eventAlias": "XXXX",
"eventPayinStartDate": "2021-02-23",
"eventPayinEndDate": "0000-00-00",
"contractSigned": "0",
"urlImage": "",
"createdDate": "2021-02-23 02:05:24",
"modifiedDate": "2021-04-19 19:16:46",
"tariffId": "25",
"eventName": "XXXX",
"userFirstname": "XXXX",
"userLastname": "SAS",
"codeStatus": "120005",
"informationStatus": "",
"payinCount": "0",
"payoutCount": "0",
"transferCount": "0",
"solde": "0.00",
"authorizedBalance": "0.00",
"bic": "TRZOFR21XXX",
"iban": "XXXX"
}
]
},
"object_payload_signature": "h+0FXlKloXIrFHpY\/PMMIoIQbUBTp5W1HlXZnqCNHx4="
}
```
### `wallet.cancel`
Notifies the deletion of a Wallet, usually triggered by the [`/v1/wallets/{walletId}`](/api-reference/api-endpoints.html#tag/Wallets/deleteWallet){target="\_self"} endpoint.
```json [JSON]
{
"webhook": "wallet.cancel",
"webhook_id": "21419123",
"object": "wallet",
"object_id": "860377",
"object_payload": {
"wallets": [
{
"walletId": "860377",
"walletTypeId": "10",
"walletStatus": "CANCELED",
"userId": "1622006",
"jointUserId": "0",
"walletTag": "",
"currency": "EUR",
"eventDate": "2021-04-29",
"eventMessage": "",
"eventAlias": "XXXX",
"eventPayinStartDate": "2021-04-22",
"eventPayinEndDate": "0000-00-00",
"contractSigned": "0",
"urlImage": "",
"createdDate": "2021-04-22 14:55:33",
"modifiedDate": "2021-04-22 14:55:33",
"tariffId": "83",
"eventName": "XXXX",
"userFirstname": "",
"userLastname": "",
"codeStatus": "120003",
"informationStatus": "",
"payinCount": "0",
"payoutCount": "0",
"transferCount": "0",
"solde": "0.00",
"authorizedBalance": "0.00",
"bic": "TRZOFR21XXX",
"iban": "XXXX"
}
]
},
"object_payload_signature": "UhRUkiWyKTptpF\/mbeiN20+XRBM2igEXM8JoUSrQZMs="
}
```
## Balance events
* [`balance.update`](#balance-update) is sent to you any time **the balance of a Wallet changes**
### `balance.update`
```json [JSON]
{
"webhook": "balance.update",
"webhook_id": "382069610",
"object": "balance",
"object_id": "2xxxxx7",
"object_payload": {
"balances": [
{
"walletId": "2xxxxx7",
"currentBalance": "4819188.18", // updated Current Balance
"authorizations": "407973.44",
"authorizedBalance": "4411214.74", // updated Authorized Balance
"currency": "EUR",
"calculationDate": "2020-07-03 11:14:38"
}
]
},
"object_payload_signature": "Rd8sLKMet9oPVYiEMLR5p5idGcOTBLhbZ7xnKvTOr3o="
}
```
---
---
url: /guide/wallets/iban.md
description: >-
Learn to create and manage Treezor Wallet IBANs via the API, including support
for local IBANs and virtual IBANs, to optimize account functionalities.
---
# IBAN
The International Bank Account Number (IBAN) is the unique identifier of a bank account as agreed upon by international standards.
An IBAN and a [BIC](/guide/overview/glossary#bank-identifier-code-bic) code are automatically assigned to every newly created Wallet. They are either Treezor BIC or your own BIC if you are a [Regulated Institution](/guide/overview/glossary#regulated-institution).
Treezor offers 2 IBAN-related services:
* [Virtual IBAN](#virtual-iban) - Add additional IBANs to a Wallet.
* [Local IBAN](#local-iban) - Create Wallets for specific countries.
IBAN features are compatible with transfers as follows:
| Transfer | Virtual IBAN | Local IBAN |
|---------|:--------------:|:-------------:|
| [Received SEPA Direct Debit (SDDR)](/guide/transfers/direct-debit#received-direct-debits-sddr) | | |
| [Emitted SEPA Direct Debit (SDDE)](/guide/transfers/direct-debit#emitted-direct-debits-sdde) | | |
| [Received SEPA Credit Transfer (SCTR)](/guide/transfers/credit-transfer#received-credit-transfers-sctr) | | |
| [Emitted SEPA Credit Transfer (SCTE)](/guide/transfers/credit-transfer#emitted-credit-transfers-scte) | | |
| [Received SEPA Instant Credit Transfer](/guide/transfers/credit-transfer-inst#received-instant-credit-transfers-sctr-inst) | | |
| [Emitted SEPA Instant Credit Transfer](/guide/transfers/credit-transfer-inst#emitted-instant-credit-transfers-scte-inst) | | |
| [Wallet-to-Wallet](/guide/transfers/wallet-to-wallet) | | |
In addition, the Virtual IBAN and Local IBAN features are compatible with each other. You can create virtual IBANs for wallets with a local IBAN.
## Virtual IBAN
You can add Virtual IBANs to a Wallet besides the automatically assigned IBAN. There is no limitation on the number of Virtual IBANs per Wallet.
**Feature Activation – Virtual IBANs are not available by default**
Please reach out to your *Treezor Account Manager* to learn more about the conditions for using this service.
### Use cases
Virtual IBAN offers capabilities and restrictions that are not available with the Wallet main IBAN. Therefore, they allow for a more granular handling of operations.
| Capability | Benefits |
|----------|---------|
| **Usage restriction** | Restricting the usage of a Virtual IBAN to specific users or usage allows you to better categorize funds movements. |
| **Virtual IBAN deactivation** | Deactivating the Virtual IBAN without closing the Wallet facilitates of litigation handling, for instance. |
Virtual IBANs include operation limitations to prevent abuses:
* **Single direction** – Support either outgoing ([SDDR](/guide/transfers/direct-debit)) or incoming ([SCTR](/guide/transfers/credit-transfer)) funds.
* **Time frame** – Limit a Virtual IBAN usage between two specified dates.
* **Number of transaction** – Set a maximum number of transactions for a Virtual IBAN.
* **Maximum amount** – Set a maximum cumulated amount for a Virtual IBAN.
**Note – Declined transfers don't impact limits**
A declined [SCT](/guide/transfers/credit-transfer) or [SDD](/guide/transfers/direct-debit) is ignored by Virtual IBAN limits (its doesn't count towards `maxUsage` or `maxAmount` restrictions).
### Creating a Virtual IBAN
#### Parameters
| Attribute | Type | Description |
| --- | --- | ---- |
| `walletId` | integer | The unique identifier of the Wallet to which the Virtual IBAN is associated. Must be a `walletType` of `9` or `10`. |
| `typeId` | integer | The type of IBAN, allowing for a specific transfer direction. Can be: `1` for `SDDR` [SEPA Direct Debit](/guide/transfers/direct-debit)`2` for `SCTR` [SEPA Credit Transfer](/guide/transfers/credit-transfer) |
| `validFrom` | string | The date from which the Virtual IBAN validity starts. Defaults to today's date and must be set in the future. Format: YYYY-MM-DD |
| `validTo` | string | The date from which the Virtual IBAN validity ends. Must be set after the `validFrom` date. Format: YYYY-MM-DD |
| `maxUsage` | integer | The maximum number of transactions allowed (`0` = unlimited). |
| `maxAmount` | string (number) | The maximum cumulated [amount](/guide/api-basics/data-format#amounts) of all transactions (`"0.00"` = unlimited). |
| `reference` | string | Custom field for your internal reference of the Virtual IBAN. Max. length: 255 characters. |
| `tag` | string | Custom attribute that you can use as you see fit. Learn more in the [Object tags](/guide/api-basics/objects-tags) article. |
#### Request example
Endpoint: [`/v1/virtualibans`](/api-reference/api-endpoints.html#tag/Virtual%20IBANs/postVirtualIban){target="\_self"}
```bash [CURL]
curl -X POST '{baseUrl}/v1/virtualibans' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"walletId":{walletId},
"typeId":2
}
```
Returns a Virtual IBAN object, containing its `id`, the IBAN itself and additional information.
```json [JSON]
{
"virtualibans": [
{
"virtualibanId": 123456,
"walletId": 0123456,
"typeId": 2,
"tag": "Test vIBAN",
"reference": "",
"validFrom": "2024-01-31",
"validTo": null,
"maxUsage": 10, // 0 means there is no limit
"maxAmount": "0.00", // "0.00" means there is no limit
"iban": "FR761679800001100000123455678",
"createdDate": "2024-01-31 09:28:06",
"numberOfTransactions": 0,
"cumulatedAmount": "0.00",
"updatedDate": null
}
]
}
```
**Tip – All your Virtual IBANs have the same BIC**
All IBANs emitted by Treezor have the following BIC `TRZOFR21XXX` unless you are a Payment Institution or more broadly a , in which case, you have your own BIC.
### Retrieving a Virtual IBAN
You can use the following request with the `virtualIbanId` as a path parameter to retrieve a Virtual IBAN.
```bash [CURL]
curl -X GET '{baseUrl}/v1/virtualibans/{virtualIbanId}' \
--header 'Authorization: Bearer {accessToken}' \
```
Returns the corresponding Virtual IBAN object.
```json [JSON]
{
"virtualibans": [
{
"virtualibanId": 123456,
"walletId": 0123456,
"typeId": 2,
"tag": "Test vIBAN",
"reference": "",
"validFrom": "2024-01-31",
"validTo": null,
"maxUsage": 10,
"maxAmount": "0.00",
"iban": "FR761679800001100000123455678",
"createdDate": "2024-01-31 09:28:06",
"numberOfTransactions": 0,
"cumulatedAmount": "0.00",
"updatedDate": null
}
]
}
```
### Deleting a Virtual IBAN
For legal reasons, Virtual IBANs cannot be deleted. The only way to do so is for the Virtual IBAN to go past its `validTo` date.
Although the `validTo` date can't be set in the past, you can update it to be in the near-future by using the [`/v1/virtualibans/{virtualIbanId}`](/api-reference/api-endpoints.html#tag/Virtual%20IBANs/putVirtualIban){target="\_self"} request.
```bash [CURL]
curl -X PUT '{baseUrl}/v1/virtualibans/{virtualIbanId}' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{
"validTo": "" # The expiration date (YYYY-MM-DD)
}'
```
Returns the updated Virtual IBAN object.
```json [JSON]
{
"virtualibans": [
{
"virtualibanId": 123456,
"walletId": 0123456,
"typeId": 2,
"tag": "Test vIBAN",
"reference": "",
"validFrom": "2024-01-31",
"validTo": null,
"maxUsage": 10,
"maxAmount": "0.00",
"iban": "FR761679800001100000123455678",
"createdDate": "2024-01-31 09:28:06",
"numberOfTransactions": 0,
"cumulatedAmount": "0.00",
"updatedDate": null
}
]
}
```
### Endpoints
| Endpoint |[Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/v1/virtualibans`](/api-reference/api-endpoints.html#tag/Virtual%20IBANs/postVirtualIban){target="\_self"} Create a Virtual IBAN | `read_write` |
| [`/v1/virtualibans`](/api-reference/api-endpoints.html#tag/Virtual%20IBANs/getvirtualibans){target="\_self"} Search Virtual IBANs | `read_only` |
| [`/v1/virtualibans/{virtualIbanId}`](/api-reference/api-endpoints.html#tag/Virtual%20IBANs/getvirtualiban){target="\_self"} Retrieve a specific Virtual IBAN | `read_only` |
| [`/v1/virtualibans/{virtualIbanId}`](/api-reference/api-endpoints.html#tag/Virtual%20IBANs/putVirtualIban){target="\_self"} Update a Virtual IBAN | `read_write` |
## Local IBAN
Bank accounts are country-specific, which is reflected by the first 2 characters of the IBAN (country code). You can create accounts with a BIC and IBAN based in the user’s [`distributionCountry`](/guide/users/introduction#distribution-country-distributioncountry).
**Configuration – Environment configuration by Treezor**
Please contact Treezor to set up your [distribution countries](/guide/users/introduction#distribution-country-distributioncountry) and available IBANs per country. Required fields upon creating a Wallet change depending on your setup.
Local IBANs are compatible with all Treezor transaction flows.
In the specific case of [Wallet-to-Wallet transfers](/guide/transfers/wallet-to-wallet), transfers are only possible when the wallets have IBANs of the same country. Otherwise, you need to make a SEPA Credit Transfer instead.
### Available countries (`bic`)
While by default, Treezor provides French IBAN, the following countries are available: Germany, Italy, and Spain.
Find below the available `bic` values structure per country. These [BICs](/guide/overview/glossary#bank-identifier-code-bic) are to be adapted depending on the value Treezor provided you.
| Country code | `bic` structure |
| --- | --- |
| FR | TRZOFR21XXX |
| DE | TRZODEB2XXX |
| IT | TRZOITM2XXX |
| ES | TRZOESM2XXX |
### Creating a Local IBAN
Treezor generates the IBAN when creating a Wallet. Depending on your configuration, you may specify the location of the IBAN by either:
* Relying on the `distributionCountry` of the wallet owner
* Specifying the `bic` value
In most cases, however, the `bic` country must be aligned with wallet owner's `distributionCountry`.
#### Parameters
Below are the main parameters to create a wallet with a local IBAN.
| Attribute | Type | Description |
|--- |--- |--- |
| `walletTypeId` | integer | The type of Wallet. Allowed values are: `9` – Electronic Money Wallet`10`– Payment Account Wallet|
| `bic` | string | The country in which the wallet is domiciled. The BIC is required depending on your configuration; it can default to the configured value only if there is only one allowed `bic` value authorized for a given `distributionCountry`. Contact Treezor for more information about your configuration. |
| `userId` | integer | The unique identifier of the User who owns the Wallet. |
| `currency` | string | The currency of the Wallet. Can only be `EUR`. |
| `eventName` | string | The name of the Wallet. |
**API – API Reference available**
For a complete list of Wallet attributes, check the [Wallets](/api-reference/api-endpoints.html#tag/Wallets){target="\_self"} section of the API Reference.
#### Request example
Endpoint: [`/v1/wallets`](/api-reference/api-endpoints.html#tag/Wallets/postWallets){target="\_self"}
Here is an example of `{payload}`:
```json [JSON]
{
"walletTypeId": 10,
"bic": "TRZODEB2XXX",
"userId": 123456,
"currency": "EUR",
"eventName": "Wallet DE"
}
```
Returns the Wallet object with the BIC and IBAN localized in the desired country.
```json [JSON] {22,23}
{
"wallets": [
{
"walletId": 3445765,
"walletTypeId": 10,
"walletStatus": "VALIDATED",
"codeStatus": 120005,
"informationStatus": "",
"walletTag": "",
"userId": 100962903,
"userLastname": "Oak",
"userFirstname": "Alex",
"jointUserId": 0,
"tariffId": 136,
"eventName": "Wallet DE",
"eventAlias": "wallet-de-67093a222d23a",
"eventDate": "2024-10-18",
"eventMessage": "",
"eventPayinStartDate": "2024-10-11",
"eventPayinEndDate": "0000-00-00",
"contractSigned": 0,
"bic": "TRZODEB2XXX",
"iban": "DE72100102000003445765",
"urlImage": "",
"currency": "EUR",
"createdDate": "2024-10-11 16:45:54",
"modifiedDate": "0000-00-00 00:00:00",
"payinCount": 0,
"payoutCount": 0,
"transferCount": 0,
"solde": 0,
"authorizedBalance": 0,
"totalRows": 1,
"country": "FR"
}
]
}
```
---
---
url: /guide/wallets/operations.md
description: >-
Get a foundational understanding of Treezor operations (card, payins, payouts,
and transfers). Includes key attributes, JSON structure, and related endpoints
list.
---
# Operations
Operations stand for banking operations originating from or targeting a [Wallet](/guide/wallets/introduction) (i.e., Card Transactions, Payins, Payouts, and Transfers) and their refunds. Each Operation summarizes the initial transaction with read-only information such as the nature, status, amount, origin, and destination.
Therefore, you may use Operations as a single source of information. They are what end users generally expect to see as a table or timeline when they log into their bank website/app.
**Tip – Operations are available in CSV format**
You can also export the information using the [Reports](/guide/wallets/operations#generate-operations-reports) feature.
## Available operations (`operationType`)
The `operationType` attribute allows you to identify what kind of banking operation is concerned.
The following operation types are available:
| `operationType` | Initial operation |
| --- | --- |
| `bankDirectDebit` | [SEPA Direct Debit (SDD)](/guide/transfers/direct-debit) |
| `bankTransfer` | [SEPA Transfer](/guide/transfers/credit-transfer) |
| `cardTopup` | [Incoming funds from Card](/guide/acquiring/introduction) |
| `cardTransaction` | [Outgoing Card payment](/guide/cards/transactions) |
| `check` | [Check](/guide/cheques/introduction) |
| `creditNote` | [Wallet-to-wallet Transfers](/guide/transfers/introduction#from-wallet-to-wallet) with a `transferTypeId` value of `4`. Such transfers allow you to handle reimbursement of charges. |
| `fees` | [Wallet-to-wallet Transfers](/guide/transfers/introduction#from-wallet-to-wallet) with a `transferTypeId` value of `3`. Such transfers allow you to debit fees from end users wallets. They are identified as such in Account Statements. |
| `instantBankTransfer` | [Instant SEPA Transfer](/guide/transfers/credit-transfer-inst) |
| `walletTransfer` | [Wallet-to-wallet Transfers](/guide/transfers/introduction#from-wallet-to-wallet) |
```mermaid
flowchart LR
Operations(Operations)
Check(check)
CardTopUp(cardTopup)
BankDirectDebit(bankDirectDebit)
BankTransfer(bankTransfer)
CardTransaction(cardTransaction)
Payins(Payins)
Payouts(Payouts)
Transfers(Transfers)
CardTransactions(CardTransactions)
Operations --- Check
Operations --- CardTopUp
Operations --- BankDirectDebit
Operations --- BankTransfer
Operations --- CardTransaction
Check <--> Payins
CardTopUp <--> Payins
BankDirectDebit <--> Payins
BankTransfer <--> Payins
BankDirectDebit <--> Payouts
BankTransfer <--> Payouts
BankTransfer <--> Transfers
CardTransaction <--> CardTransactions
class Operations MermaidNeutralAlternate
class Payins MermaidNeutral
class Payouts MermaidNeutral
class Transfers MermaidNeutral
class CardTransactions MermaidNeutral
```
## Key attributes
Below are a few of the most important attributes.
| Attribute | Type | Description |
|---|---|---|
| `operationType` | array | The type of bank operation, providing functional context about the initial operation. |
| `initialFlow` | string | Provides technical context about the initial operation: `payin`, `payinRefund`, `payout`, `payoutRefund`, `transfer`, `cardTransaction`, `chargeback`. You can fetch the initial operation by making the corresponding request (using the `objectId` as a path parameter). |
| `amount` | integer | The amount of the operation in cents (e.g., `100` stands for 1). |
| `walletId` | integer | The unique identifier of the wallet associated with the operation. |
| `direction` | string | Direction of the operation, which can either be: `CREDIT` – The funds are credited to the Wallet`DEBIT` – The funds are debited from the Wallet |
| `objectId` | string | The unique identifier of the object the operation relates to (e.g., the initial `cardTransaction`). |
| `label` | string | Information that you can expose to your end users. The label content differs depending on the context. |
| `metadata` | object | Details about the initial operation. |
| `status` | string | The status of the operation, which can be: `AUTHORIZED`, `DECLINED`, `SETTLED`, or `CANCELED`. |
| `creation` | string | The date and time at which the object the operation relates to was created. *Format: RFC3339 standard.* |
| `settlement` | string | The date and time at which the object the operation relates to was settled on the Wallet. *Format: RFC3339 standard.* |
**API Reference – Refer to endpoint documentation**
For a complete list of Operation attributes, check the [Operations](/api-reference/api-endpoints.html#tag/operations){target="\_self"} endpoint in the API Reference.
### Metadata
The `metadata` object contains key information about the initial operation. This content differs depending on the operation.
#### Transfers
```json [JSON]
"metadata": {
"label": "string || null",
"codeStatus": "string",
"tag": "string || null",
"informationStatus": "string || null",
"creditorWalletId": "string",
"creditorFirstName": "string", // Encrypted if cryptography is activated
"creditorLastName": "string", // Encrypted if cryptography is activated
"creditorLegalName": "string", // Encrypted if cryptography is activated
"creditorWalletEventName": "string",
"debtorWalletId": "string", // Encrypted if cryptography is activated
"debtorFirstName": "string", // Encrypted if cryptography is activated
"debtorLastName": "string", // Encrypted if cryptography is activated
"debtorLegalName": "string",
"debtorWalletEventName": "string"
}
```
#### Card Transactions
```json [JSON]
"metadata": {
"maskedPan": "519872******4839", // Encrypted if cryptography is activated
"mcc": {
"code": 123456,
},
"mid": {
"value": "3256", // MerchantId, Encrypted if cryptography is activated
"name": "Merchant Name", // MerchantName, Encrypted if cryptography is activated
"city": "", // MerchantCity, Encrypted if cryptography is activated
"country": "",
"address": null
},
"localAmount": {
"amount": 1790,
"currency": "978"
},
"authorizationNote": "", // Encrypted if cryptography is activated
"authorisationResponseCode": {
"action": "Approved",
"description": "APPROVED",
"value": 08
},
"paymentLifeCycle": [ // for each Cardtransactions::PaymentStatus = S
{
"authorizationIssuerTime": "2024-04-16 08:23:20",
"valueDate": "string",
"paymentAmount": 0,
"paymentLocalAmount": 0,
"paymentCurrency": "string"
}
],
"paymentCountry": "FRA",
"cardId": "999997173",
"publicToken": "string",
"is3DS": "0",
"3dsExemptionType": "string || null",
"optimizedMerchantName": "string || null",
"merchantLogo": "string || null",
"merchantCategory": "string || null",
"merchantCategoryGroup": "string || null",
"merchantCategoryType": "string || null",
"transactionSubtype": "string || null",
}
```
#### Payins
```json [JSON]
"metadata": {
"payinId": "string",
"payinTag": "string || null", // Encrypted if cryptography is activated
"messageToUser": "string || null", // Encrypted if cryptography is activated
"codeStatus": "string",
"informationStatus": "string || null",
"paymentMethodId": 0,
"ibanFullName": "string || null",
"dbtrIBAN": "******1319", // Encrypted if cryptography is activated
"ibanTxEndToEndId": "string || null",
"mandateId": "string || null",
"debtorName": "string || null",
"uniqueMandateReference": "string || null",
"additionalData": ["string"], // Encrypted if cryptography is activated
}
```
#### PayinRefunds
```json [JSON]
"metadata": {
"payinId": "string",
"payinTag": "string || null", // Encrypted if cryptography is activated
"messageToUser": "string || null", // Encrypted if cryptography is activated
"codeStatus": "string",
"informationStatus": "string || null",
"paymentMethodId": 0,
"ibanFullName": "string || null",
"dbtrIBAN": "string || null", // Encrypted if cryptography is activated
"ibanTxEndToEndId": "string || null",
"mandateId": "string || null",
"debtorName": "string || null",
"uniqueMandateReference": "string || null",
"reasonTms": "string || null",
"additionalData": ["string"] // Encrypted if cryptography is activated
}
```
#### Payouts
```json [JSON]
"metadata": {
"payoutTag": "string || null",
"beneficiaryId": "string",
"label": "string || null",
"codeStatus": "string",
"informationStatus": "string || null",
"payoutTypeId": 0,
"supportingFileLink": "string || null",
"reasonCode": "string || null",
"reasonDescription": "string || null",
"endToEndId": "string || null", // SCT only
"uniqueMandateReference": "string || null", // SDD only
"beneficiaryName": "string || null"
}
```
#### PayoutRefunds
```json [JSON]
"metadata": {
"codeStatus": "string",
"informationStatus": "string || null",
"requestComment": "string || null",
"reasonCode": "string || null",
"refundDate": "string || null",
"refundComment": "string || null",
"payoutId": "string || null",
"payoutRefundTag": "string || null",
"beneficiaryName": "string || null",
"label": "string || null",
"endToEndId": "string || null", // SCT only
"uniqueMandateReference": "string || null", // SDD only
"payoutTypeId": 0,
"beneficiaryId": "string || null",
"payoutTag": "string"
}
```
#### Chargebacks
Chargebacks of card top up payins.
```json [JSON]
"metadata": {
"payinId" : "string",
"payinTag": "string || null", // Encrypted if cryptography is activated
"payinrefundId": "string",
"additionalData": "string", // Encrypted if cryptography is activated
"chargebackReason": "string",
"transactionReference": "string",
}
```
### Labels
You can expose the `label` field values to your end users to provide more information.
The information displayed depends on the context and the table below relies on the latest version of the Operations feature.
| Context | Exposed data | String example |
|---|---|---|
| Card Top Up | Indicates the name of the cardholder, along with the masked PAN of the card. | Alex Oak 553896XXXXXX8893 |
| Cancelled Card Top Up | Indicates the name of the cardholder, along with the masked PAN of the card. | Alex Oak 553896XXXXXX8893 |
| Chargeback on Card Top Up | Indicates the name of the cardholder and the card masked PAN. | Alex Oak 553896XXXXXX8893 |
| Bank Transfer (Payin) | Indicates the IBAN full name, along with the `messageToUser` (custom field). | Alex Oak messageToUserExample |
| Refund of Bank Transfer (Payin) | Indicates the IBAN full name, along with the `messageToUser` (custom field). | Alex Oak messageToUserExample |
| Bank Transfer (Payout) | Indicates the Beneficiary name, along with the Payout `label`. | |
| Refund of Bank Transfer (Payout) | Indicates the Beneficiary name, along with the Payout `label`. | |
| Bank Direct Debit (Payin) | Indicates the debtor's name, along with the `messageToUser` (custom field), and the Unique Mandate Reference. | |
| Refund of Bank Direct Debit (Payin) | Indicates the debtor's name, along with the `messageToUser` (custom field), and the Unique Mandate Reference. | |
| Bank Direct Debit (Payout) | Indicates the Beneficiary name, the Payout `label`, and the Unique Mandate Reference. | Alex Oak rlabel96 UMR: 65c32b8dc64xx |
| Refund of Bank Direct Debit (Payout) | Indicates the Beneficiary name, the Payout `label`, and the Unique Mandate Reference. | Alex Oak rlabel96 UMR: 65c32b8dc64xx |
| Check | Indicates the user's name, along with the `messageToUser` (custom field), and the CMC7 A. | |
| Refund of a Check | Indicates the user's name, along with the `messageToUser` (custom field), and the CMC7 A. | |
| Transfer (wallet-to-wallet) | Indicates the user's name, along with the transfer `label`. | messageToUserExample Alex Oak |
| Transfer (if `fees` or `creditNote`) | Indicates the Transfer `label` (custom field). | |
| Card Transaction | Indicates the merchant's name and the masked PAN. If the currency of the transaction differs from the Wallet currency, also indicates the `paymentLocalAmount`. | Tree Cie(978 91.78) Card 734837\*\*\*\*\*\*9403 |
## Retrieve operations
When requesting a list of operations, the following query parameters are required.
| Parameter | Description |
| --- | --- |
| `walletId` | The unique identifier of the Wallet for which the operations are to be retrieved. |
| `dateFrom` | The date and time from which the operations are to be retrieved. This parameter takes into account the `createdDate` for Payin, Payout, and Transfer objects, and the `authorizationIssuerTime` (Europe/London timezone) for Card Transactions. Format: HTML-encoded RFC 339 date-time. |
| `dateTo` | The date and time up to which the operations are to be retrieved. This parameter takes into account the `createdDate` for Payin, Payout, and Transfer objects, and the `authorizationIssuerTime` (Europe/London timezone) for Card Transactions. Format: HTML-encoded RFC 339 date-time. |
**Note – 3-month time frame support**
The `dateTo` and `dateFrom` fields must be less than 3 months apart.
To get the list of operations, use the following request (which supports [cursor-based pagination](/guide/api-basics/pagination#cursor-based-pagination)). The dates are to be HTML encoded (e.g., 2024-01-11T11:25:36+01:00 becomes `2024-01-11T11:25:36%2B01:00`).
```bash [CURL]
curl -X GET '{baseUrl}/core-connect/operations?walletId={walletId}&dateFrom={dateFrom}&dateTo={dateTo}' \
--header 'Authorization: Bearer {accessToken}' \
```
Here is an example of a response. It returns an array of Operation objects along with a cursor and sorted by creation date.
```json [JSON]
{
"cursor": {
"prev": null,
"current": null,
"next": null
},
"data": [
{
"amount": {
"amount": 1000,
"currency": "EUR"
},
"walletId": 2647244,
"operationType": "bankDirectDebit",
"direction": "DEBIT",
"status": "SETTLED",
"objectId": "181212",
"label": "Alex Oak rlabel96 UMR: 65c32b8dc64xx",
"metadata": {
"payoutTag": "65c32b8dc64xx|lFCS7WW4OugijXXX",
"beneficiaryId": "429387",
"beneficiaryName": "Alex Oak",
"label": "rlabel96",
"codeStatus": "160005",
"informationStatus": "Remboursement par virement Validé",
"payoutTypeId": 0,
"uniqueMandateReference": "65c32b8dc64xx",
"supportingFileLink": "",
"reasonCode": null,
"reasonDescription": null,
"endToEndId": null
},
"date": {
"creation": "2024-02-07T08:04:48+01:00",
"settlement": "2024-02-07T00:00:00+01:00"
},
"initialFlow": "payout"
}
]
}
```
## Generate Operation Reports
Operation Reports are CSV exports that include all operations for a given Wallet on a given period. They are mainly intended for administrative and back end use.
Creating an operation report is a 2-step process:
1. [Request the Report](#request-a-report)
2. [Retrieve the Report](#retrieve-a-report)
### Request a Report
To request a CSV report, you can use the following request.
```bash [CURL]
curl -X POST '{baseUrl}/core-connect/operations/{walletId}/report' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is a `{payload}` example:
```json [JSON]
{
"dateFrom": "2022-06-05T00:00:00+02:00",
"dateTo": "2023-06-15T00:00:00+02:00"
}
```
Answers with a `201` HTTP Status code.
### Retrieve a Report
To check on a report creation and obtain the download URL, you can use the following request.
**Note – Parameters are expected in query string**
As opposed to the POST request, the `dateFrom` and `dateTo` are expected as query parameters. The dates are to be html encoded (e.g., 2024-01-11T11:25:36+01:00 becomes `2024-01-11T11:25:36%2B01:00`).
```bash [CURL]
curl -X GET '{baseUrl}/core-connect/operations/{walletId}/report?dateFrom={dateFrom}&dateTo={dateTo}' \
--header 'Authorization: Bearer {accessToken}' \
```
Returns the following when the report is still being generated.
```json [JSON]
{
"status": "CREATED",
"url": null
}
```
Returns the following when the report is ready for download.
```json [JSON]
{
"status": "COMPLETED",
"url": "https://dev-connect-files.s3.eu-west-3.amazonaws.com/operation/report/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx.csv"
}
```
**Information – Report creation can time out**
If 15 minutes after the initial Report request you are still getting the `CREATED` status, then the Report creation process has timed out.
### Operation Report data
Find below the list of fields included in the operation report .csv.
| Field | Description |
| --- | --- |
| `ceationDate` | The date and time at which the object the operation relates to was created. |
| `valueDate` | The date and time at which the object the operation relates to was settled on the wallet. |
| `label` | Information that you can expose to your end users. The label content differs depending on the operation. |
| `walletId` | The unique identifier of the wallet associated with the operation. |
| `amount` | The amount of the operation in cents (e.g., `100` stands for 1). |
| `currency` | The currency of the operation (e.g., `EUR`). |
| `direction` | Direction of the operation, which can either be: `CREDIT` – The funds are credited to the Wallet`DEBIT` – The funds are debited from the Wallet |
| `objectId` | The unique identifier of the object the operation relates to (e.g., the initial `cardTransaction`). |
| `operationType` | The type of bank operation, providing functional context about the initial operation. |
| `status` | The status of the operation, which can be: `AUTHORIZED`, `DECLINED`, `SETTLED`, or `CANCELED`. |
| `initialFlow` | Provides technical context about the initial operation: `payin`, `payinRefund`, `payout`, `payoutRefund`, `transfer`, `cardTransaction`, `chargeback`. |
| `beneficiaryId` | The unique identifier of the beneficiary (payouts, payout refunds). |
| `creditorWalletId` | The unique identifier of the credited wallet for wallet-to-wallet transfers. |
| `debtorWalletId` | The unique identifier of the debited wallet for wallet-to-wallet transfers. |
| `tag` | The custom tag (transfers, payouts, payins). |
| `mcc` | The card transaction's merchant category code. |
| `mid` | The card transaction's merchant Id. |
| `localAmount` | The card transaction's amount in the local currency in cents. |
| `localCurrency` | The card transaction's local currency (e.g., `978`). |
| `authorizationNote` | Contains detailed information regarding a declined card transaction. See the [Authorization notes](/guide/cards/authorization-notes) article for examples. |
| `authorisationResponseCodeAction` | The action from the authorization response (e.g., declined or accepted), as listed in the [corresponding article](/guide/cards/authorization-notes#authorization-response-codes). |
| `authorisationResponseCodeDescription` | The description of the authorization response code, as listed in the [corresponding article](/guide/cards/authorization-notes#authorization-response-codes). |
| `authorisationResponseCodeValue` | The authorization response code, as listed in the [corresponding article](/guide/cards/authorization-notes#authorization-response-codes). |
## Operation object
```json [JSON]
{
"operationType": "bankTransfer",
"initialFlow": "payout",
"amount": {
"amount": 6300,
"currency": "EUR",
},
"walletId": 630632,
"direction": "DEBIT",
"objectId": "408265455",
"label": "Theo West Virement de M Alex Oak",
"metadata": {
"payoutTag": "VO - 1234554321",
"beneficiaryId": "404897",
"label": "Virement de M Alex Oak",
"codeStatus": "140005",
"informationStatus": "",
"supportingFileLink": "",
"reasonCode": null,
"reasonDescription": null,
"beneficiaryName": "Yvy Sala"
},
"status": "AUTHORIZED",
"date": {
"creation": "2023-08-19T06:08:23+02:00",
"settlement": null
}
}
```
## Endpoints
| Endpoint | [Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/core-connect/operations`](/api-reference/api-endpoints.html#tag/Operations/getOperations){target="\_self"} Search Operations | `read_only` |
| [`/core-connect/operations/{walletId}/report`](/api-reference/api-endpoints.html#tag/Operations/postOperationsReport){target="\_self"} Create a Report | `read_only` |
| [`/core-connect/operations/{walletId}/report`](/api-reference/api-endpoints.html#tag/Operations/getOperationsReport){target="\_self"} Get a Report | `read_only` |
| [`/simulation/operations`](/api-reference/api-endpoints.html#tag/Operations/simulateOperations){target="\_self"} Simulate operations | `read_write` |
---
---
url: /guide/wallets/faking-operations.md
description: >-
Learn how to update and manage Treezor Wallet statuses within the Sandbox
environment for development and API integration testing.
---
# Emulation
Emulation features are only available in `Sandbox` [environment](/guide/api-basics/environments).
**Tip – You can also rely on webhooks**
For operations that cannot be emulated in the Sandbox, [webhook examples](events) are provided.
## Credit funds
To credit funds, check out the [transfer emulations](/guide/transfers/faking-operations) page.
## Operations
You can emulate [Operations](./operations) in [Sandbox](/guide/api-basics/environments#sandbox) for a given month. This is a prerequisite to test the [Account Statements](account-documents).
### Parameters
| Attribute | Type | Description |
|---|---|---|
| `walletId` | string | The Wallet for which you wish to emulate operations. |
| `date` | string | The month for which the operations are going to be emulated. Please note that you can't emulate operations multiple times for the same month. |
| `operations` | object | In this object, you can list the number of operations to generate per operation as [in the example](#request-example). As Treezor generates operations with random values (including for types and statuses), it is recommended to have a reasonably high number of payins and payouts for data diversity. |
### Request example
Endpoint: [`/simulation/operations`](/api-reference/api-endpoints.html#tag/Operations/simulateOperations){target="\_self"}
Here is an example of `{payload}`:
```json [JSON]
{
"walletId": "{walletId}",
"date": "2023-10",
"operations": {
"payin": 5,
"payinrefund": 2,
"payout": 6,
"payoutrefund": 1,
"transfer": 3,
"cardtransaction": 7,
"transferfees": 2,
"transfercreditnote": 1
}
}
```
Returns an HTTP `201 Created` status code. You can now view your operations by either:
* Generating an account statement [`/core-connect/statements/{walletId}/raw`](/api-reference/api-endpoints.html#tag/Account%20Statements/getRawStatement){target="\_self"}
* Retrieving operations [`/core-connect/operations`](/api-reference/api-endpoints.html#tag/Operations/getOperations){target="\_self"}
## Status
Wallets are [created](creation) in a pending status that is usually very shortly after validated.
To emulate a different status, prefix the Wallet `eventName` attribute with the following characters.
| Prefix | `walletStatus` | `codeStatus` | Description |
|:-: |- | - |- |
| `p.1` | `PENDING` | `120001` | Information control |
| `p.2` | `PENDING` | `120002` | Late information control |
| `c.3` | `CANCELED` | `120003` | Wallet was closed internally |
| `c.4` | `CANCELED` | `120004` | Wallet was closed by the User |
| `v.5` | `VALIDATED` | `120005` | Wallet is valid |
Wait a few minutes and make a `GET /v1/wallets` request for the Wallet you've just created. The API returns the Wallet with the emulated status.
### Example
Let's take an example in which we'd like to simulate a Wallet closed by the User.
With a `{payload}` containing the prefixed `eventName`:
```json [JSON] {6}
{
"walletTypeId": "10",
"userId": 100113410,
"currency": "EUR",
"eventName": "c.4Test Wallet"
}
```
The request returns the validated Wallet for now.
You need to retrieve the Wallet a few moments after the creation with the following request:
```bash [CURL]
curl -X GET '{baseUrl}/v1/wallets/{WalletId}' \
--header 'Authorization: Bearer {accessToken}' \
```
The Wallet object returned is `CANCELED`, with the mocked `codeStatus`:
```json [JSON] {6,7}
{
"wallets": [
{
"walletId": 2643119,
"walletTypeId": 9,
"walletStatus": "CANCELED",
"codeStatus": 120003,
"informationStatus": "",
"walletTag": "",
"userId": 100113410,
"userLastname": "Alex",
"userFirstname": "Oak",
"tariffId": 136,
"eventName": "c.3test",
"eventMessage": "",
"contractSigned": 0,
"bic": "TRZOFR21XXX",
"iban": "FR7616798000010000264311929",
"currency": "EUR",
"createdDate": "2024-02-06 06:57:56",
"modifiedDate": "2024-02-06 06:58:16",
"payinCount": 0,
"payoutCount": 0,
"transferCount": 0,
"solde": 0.0,
"authorizedBalance": 0.0,
"totalRows": 1,
"country": "FR"
}
]
}
```
---
---
url: /guide/wallets/transactions.md
description: >-
Retrieve read-only representation of banking operations of a given Wallet.
Includes required parameters, request structure, and response examples.
---
# Transactions
Transactions are a read-only representation of banking operations on a [Wallet](./introduction).
**Best practice – Use the [Operations](/guide/wallets/operations) feature for a real-time view**
Transactions represent settled operations. Detailed [Operations](/guide/wallets/operations) are more adequate to show real-time cashflow, with pending fund movements.
## Key attributes
| Attribute | Type | Description |
| --- | --- | --- |
| `transactionId` | integer | The unique identifier of the transaction. |
| `createdDate` | string | The date and time at which the transaction was created. |
| `valueDate` | string | The date on which the payment was applied. |
| `executionDate` | string| The date on which the transaction was executed. |
| `transactionType` | string | The name of the transaction type. See [Transaction Types list](#transaction-types-transactiontypes). |
| `name` | string | The name of the transaction. |
| `foreignId` | integer | The unique identifier of the initial operation that created the Transaction (e.g., `payinId`, `payoutId`, etc.) |
| `walletDebitBalance` | string | The balance of the debited Wallet (if any). |
| `walletCreditBalance` | string | The balance of the credited Wallet (if any). |
| `walletDebitId` | integer | The unique identifier of the debited Wallet (if any). |
| `walletCreditId` | integer | The unique identifier of the credited Wallet (if any). |
| `amount` | string | The amount of the transaction. |
| `currency` | string | The currency of the transaction (format: ISO-4217). |
**API – API Reference available**
For a complete list of Transaction attributes, check the [Transactions](/api-reference/api-endpoints.html#tag/Transactions){target="\_self"} section of the API Reference.
### Transaction Types (`transactionType`)
Below the list of possible values for the `transactionType` attribute.
| Id | Name | Additional information |
| :---: | --- | --- |
| `1` | Payin | Transaction from an external account into a Treezor Wallet. |
| `2` | Payout | Transaction from a Wallet to an external account. |
| `3` | Transfer | Wallet-to-Wallet transfer. |
| `5` | Payin Refund | Refund of a past transaction made into a Treezor Wallet. |
| `10` | Card Transaction | Learn more in the [Card transactions](/guide/cards/transactions) section of the documentation. |
| `11` | Payout Refund | Refund of a past transaction made from a Wallet to an external account. |
| `13` | Payin Acquiring | Transaction capturing funds from a third-party card to credit a Treezor Wallet. [Learn more](/guide/acquiring/introduction). |
| `14` | Payin Refund Acquiring | Refund of a card top-up. [Learn more](/guide/acquiring/refunds). |
| `15` | SCTR Inst | [Received SEPA Instant Credit Transfer](/guide/transfers/credit-transfer-inst#received-instant-credit-transfers-sctr-inst) |
| `17` | Payin SCT Instant Recall | Learn more in the [Recalls & RROs](/guide/transfers/sepa-recalls#sctr-inst-recalls) article. |
| `18` | Payout SCT Instant Emit | [Emitted SEPA Instant Credit Transfer](/guide/transfers/credit-transfer-inst#emitted-instant-credit-transfers-scte-inst) |
| `19` | Payin SCT Instant Emit Recall | Learn more in the [Recalls & RROs](/guide/transfers/sepa-recalls#sctr-inst-recalls) article. |
| `20` | Credit Transfer Returned | SCT Return. |
| `21` | Check Payin | [Check cashing](/guide/cheques/introduction) |
| `22` | SDDE | [Emitted SEPA Direct Debit](/guide/transfers/direct-debit#emitted-direct-debits-sdde) |
| `23` | SDDR | [Received SEPA Direct Debit](/guide/transfers/direct-debit#received-direct-debits-sddr) |
| `24` | SDDR Reversal | SDDR refused after effective date. |
| `25` | SCTR Recall | Learn more in the [Recalls & RROs](/guide/transfers/sepa-recalls#sctr-inst-recalls) article. |
| `26` | Check Refund | Refund of a check cashing. |
| `27` | SCTR | [Received SEPA Credit Transfer](/guide/transfers/credit-transfer#received-credit-transfers-sctr) |
| `28` | International Credit Transfer | [Received International Transfer](/guide/transfers/international#received-international-transfers) |
## Transaction object
```json [JSON]
{
"transactionId": 0,
"walletDebitId": 0,
"walletCreditId": 0,
"transactionType": "string",
"foreignId": 0,
"name": "string",
"description": "string",
"valueDate": "string",
"executionDate": "string",
"amount": "string",
"walletDebitBalance": "string",
"walletCreditBalance": "string",
"currency": "string",
"createdDate": "string",
"totalRows": 0
}
```
## Retrieving transactions
The [`/v1/transactions`](/api-reference/api-endpoints.html#tag/Transactions/getTransactions){target="\_self"} endpoint allows you to retrieve lists of transaction.
The following example searches for `Payin` Transactions per `userId`.
```bash [CURL]
curl -X GET '{baseUrl}/v1/transactions?userId={userId}&transactionType=Payin' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json'
```
Returns an array of Transaction objects.
```json [JSON]
{
"transactions": [
{
"transactionId": 4823484,
"walletDebitId": 9,
"walletCreditId": 2540896,
"transactionType": "Payin",
"foreignId": "1234626",
"name": "1234626",
"description": "Payin bank transfer",
"valueDate": "2023-12-21",
"executionDate": "2023-12-21",
"amount": "101.25",
"walletDebitBalance": "0.00",
"walletCreditBalance": "50203.75",
"currency": "EUR",
"createdDate": "2023-12-21 12:11:34",
"totalRows": "2"
},
{
"transactionId": 4823455,
"walletDebitId": 9,
"walletCreditId": 2540896,
"transactionType": "Payin",
"foreignId": "1234606",
"name": "1234606",
"description": "Payin bank transfer",
"valueDate": "2023-12-21",
"executionDate": "2023-12-21",
"amount": "101.25",
"walletDebitBalance": "0.00",
"walletCreditBalance": "50102.50",
"currency": "EUR",
"createdDate": "2023-12-21 12:05:40",
"totalRows": ""
}
]
}
```
## Retrieving a transaction
Endpoint: [`/v1/transactions/{transactionId}`](/api-reference/api-endpoints.html#tag/Transactions/getTransaction){target="\_self"}
```bash [CURL]
curl -X GET '{baseUrl}/v1/transactions/{transactionId}' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
```
Returns the corresponding Transaction object.
```json [JSON]
{
"transactions": [
{
"transactionId": 4823455,
"walletDebitId": 9,
"walletCreditId": 2540896,
"transactionType": "Payin",
"foreignId": "1234606",
"name": "1234606",
"description": "Paiement ",
"valueDate": "2023-12-21",
"executionDate": "2023-12-21",
"amount": "101.25",
"walletDebitBalance": "0.00",
"walletCreditBalance": "50102.50",
"currency": "EUR",
"createdDate": "2023-12-21 12:05:40",
"totalRows": "1"
}
]
}
```
## Endpoints
| Endpoint |[Scope](/guide/api-basics/authentication#available-scopes) |
| --- | --- |
| [`/v1/transactions`](/api-reference/api-endpoints.html#tag/Transactions/getTransactions){target="\_self"} Search for transactions | `read_write` |
| [`/v1/transactions/{transactionId}`](/api-reference/api-endpoints.html#tag/Transactions/getTransaction){target="\_self"} Retrieve a transaction | `read_write` |
---
---
url: /guide/dashboard/wallets.md
description: >-
Let your team provide support regarding your end users wallets using the
Treezor Dashboard.
---
# Wallets
Wallets are similar to bank accounts, each User at Treezor requires one to make any kind of banking operation.
## Accessing Wallets
You may access wallet information by:
* Taking advantage of the main [*Search field*](#search-field).
* Navigating the [*Wallets*](#wallets-view) view.
* Navigating the *User details* view, [*Wallets*](#user-details-view-wallets-tab) tab once a user is selected.
### Search field
The Dashboard main toolbar provides a search field, whose searchable attribute becomes dynamically available depending on what you enter.
Make sure you enter the full `walletId` of the [Wallet](/guide/wallets/introduction) before selecting the corresponding option.
After validating your search for a given wallet, the [*Wallets*](#wallets-view) view is displayed, filtered on the corresponding Wallet for you to select.
### Wallets view
The *Wallets* view provides the list of all the wallets by type. Up to 3 tabs can be available depending on your model:
* **Electronic Money** – List of electronic money wallets (type 9)
* **Payment Account** – List of payment account wallets (type 10)
* **Master wallets** – List of master wallets (type 15)
To help you navigate through the list, the following filters are available:
* **Wallet status** – Display only wallets with the selected status.
* **Creation date** – Display only wallets created on, before, after, or between specific dates.
In addition, the Search field allows you to search wallets by `walletId` or by `iban`.
Clicking on arrow icon for a wallet switches the view to the corresponding wallet in the [*User details*](#user-details-view-wallets-tab) view.
### User details view, Wallets tab
Once you've accessed a *User details* view, click on the *Wallets* tab to view all the wallets attached to the user.
The view is divided into 2 sections:
* [**Wallets list**](#wallets-list-section) – On the left-hand side, you can navigate and manage the user wallets.
* [**Operations**](#wallet-operations-section) – On the right-hand side, you can view the operations of the selected wallet.
## Navigating the Wallet's information
### Wallets list section
The *Wallets* tab displays the list of Wallets owned by the selected user.
The following information is displayed for each wallet: *Status*, *Name*, *ID*, *[Current Balance](/guide/wallets/balances)*, *[Authorized Balance](/guide/wallets/balances)*, and *[IBAN](/guide/wallets/iban)*.
You may also add the Wallet as a favorite for later operations:
| | Name | Description |
|:---: |--- |--- |
| | Star | Add as favorite. |
| | Unstar | Remove from favorites. |
Please note that you can either use the filters (by ID, Name, or IBAN) or pagination to navigate the list of wallets. The option available depends on whether there are more than 50 wallets for the selected user.
#### Wallet commands
When clicking on the "More" button (vertical ellipsis), the following commands are available:
| | Name | Description |
|:---: |--- |--- |
| | **Download document** | Provides access to the following commands to download your [templated PDFs](./templates): **Domiciliation certificate** – Attestation proving the account registered address.**Balance certificate** – Attestation proving the current balance on the account.**Closure certificate** - Attestation proving the account was closed.**Account details** – The account details (i.e., user name and address, the wallet IBAN, BIC, and account number).**Statement** – The [Statement](/guide/wallets/account-documents) for the selected month and year.**Lettre de circularisation** – Attestation containing all balances at the end of the fiscal year, for legal entities only. |
| | **Simulate** | Provides access to the following commands (Sandbox only): **Incoming bank transfer** – Prompts you to enter an amount to simulate an incoming bank transfer (SCTR)**Operations** – Allows you to populate the view with operations, for a given month and year. |
| | **See wallet details** | Opens the *Wallet Details* popup, which displays all the information about the Wallet. |
| | **Edit Wallet** | Opens the *Edit Wallet* popup, allowing you to update the Wallet name, tag, and description. The wallet type can also be changed as long as no operation occurred yet. |
| | **Deactivate Wallet** | [Deactivates the wallet](#deactivating-a-wallet). This action is irreversible. |
Please note available options may differ depending on the wallet status and your Dashboard User role.
### Wallet operations section
Once a wallet is selected, the corresponding [Operations](/guide/wallets/operations) (if any) are displayed in the right-hand side of the view.
The list of operations can be sorted, filtered, and customized as you see fit.
| | Option | Description |
|:---: |--- |--- |
| | **Date range** | Define after (From) and/or before (To) which dates the operations are considered. Any operation whose date is not in the defined time frame is filtered out. |
| | **Amount range** | Define the minimum and maximum amounts for the operations to be considered. Any transaction outside the frame is filtered out. |
| | **Status** | Only display operations whose status is selected. |
| | **Initial flow** | Only display operations whose initial flow is selected. |
| | **Operation type** | Only display operations whose type is selected. |
| | **Direction** | Only display operations whose direction is selected. |
| | **Clear** | Resets all the sorting and filtering options. |
| | **Organize columns** | Opens a panel for you to select which columns to display and in which order (drag & drop). You may save your changes or reset to the initial display by using the corresponding buttons. |
In addition, the following commands are available at the operation level:
| | Name | Description |
|:---: |--- |--- |
| | **Download proof of payout** | Generates and downloads the proof of payout PDF. This command is only available for outgoing SEPA Credit Transfers (standard and instantaneous) with an Authorized or Settled status. |
| | **Details** | Opens the *Operation detail* popup, which contains all the information regarding the operation in read-only. |
## Creating a Wallet
Upon clicking on the "Add Wallet" button at the top of the Wallets list section, the *Create wallet* popup is displayed.
In this popup, you can enter the Wallet name and [type](/guide/wallets/introduction#types-of-wallets). If you're operating in multiple countries, you may need to select the BIC too (in accordance with the user's distribution country).
**Note – More Wallet types may be available depending on your model**
Each wallet type has specific rules. Ensure you select the one matching your use case.
## Managing Wallets
### Deactivating a Wallet
You can [deactivate](/guide/wallets/introduction#deletion) a wallet using the *Deactivate Wallet* command available when clicking on the Wallet "More" button.
A Wallet can only be deactivated if:
* There is no pending operation, and
* The balance equals to EUR 0.00.
Once the Wallet deactivated, it displays a "Closed" status and no operation can be done with this wallet.
### Downloading operations
Operations stand for banking operations originating from or targeting a Wallet (i.e., Card Transactions, Payins, Payouts, and Transfers) and their refunds.
You can download the operations (CSV format) of the selected wallet by clicking on the "Download Operations" button located in the upper right corner of the *Wallets* tab.
In the *Download operations* popup, 2 options are available.
| Option | Description |
| --- | --- |
| **Download view** | Downloads the operations currently displayed in the *Operations* section while matching the filtering criteria. In this case, the operations amount will be displayed in euros (decimals). |
| **Download within date range** | Downloads all operations in a defined date range. In this case, the operations amount will be displayed in cents. |
**Reading – Learn about transferring funds**
You can make payouts and wallet-to-wallet transfers from the Dashboard. See the [Transfers](transfers) article for more information.
---
---
url: /guide/dashboard/webhooks.md
description: >-
Configure your webhook URL and subscribe to events for webhook notifications
directly from the comfort of Treezor Dashboard interface.
---
# Webhooks
Webhooks allow Treezor to send to a URL of your choice information regarding that event.
**Configuration – This Dashboard view is not available by default**
Please contact Treezor if you're interested in this feature.
## Navigating the Webhooks view
The *Webhooks* view displays the list of subscriptions for your Treezor environment.
For each subscription, you can view the status ("Enabled", or "Pending"), the URL events are sent to, and the list of Events if specified.
The following commands are available:
| Command | Description |
| --- | --- |
| **Add webhook** | Prompts the *Add a new webhook* popup, allowing you to enter a URL to which events will be sent. |
| **Update** | Prompts the *Update a webhook* popup, allowing you to define which specific events to subscribe. |
| **Delete** | Allows you to delete a subscription. |
## Managing subscriptions
### Subscribing to events
You can create a new subscription by clicking on the "Add Webhook" button.
In the prompted *Add a new webhook* popup, enter the URL to which the event notifications are to be sent.
The created webhook subscription is then added to the list, with a "Pending" status.
### Specifying event subscription
By default, you subscribe to all events upon creating a webhook.
You can specify to which events to subscribe by clicking on the "Update" button. The *Update a webhook* popup is displayed, allowing you to select the desired events.
**Reading – Learn more about Webhooks**
Please refer to the [Webhooks](/guide/webhooks/introduction) section of the documentation to learn more about available events and the information they provide.
Once the desired events selected, click on the "Save changes" button to update the subscription.
---
---
url: /guide/webhooks/events-descriptions.md
description: >-
Explore all Treezor API webhook events. This guide provides a comprehensive
list of event names, their triggering actions, and payload structures,
categorized by feature for complete event-driven integration.
---
# Events description
If you wish to receive only a subset of webhooks, please contact your *Treezor Account Manager*.
## Categories
Each documentation section has an article dedicated to the events triggered by a feature. Find below the list of categories of events.
| Category | Events |
| --- | --- |
| [**Users**](/guide/users/introduction) | [User events](/guide/users/events#user-events) – [Document events](/guide/user-verification/events#document-events) – [KYC and verification solution events](/guide/user-verification/events) |
| [**Wallets**](/guide/wallets/introduction) | [Wallet events](/guide/wallets/events#wallet-events) – [Balance events](/guide/wallets/events#balance-events) |
| [**Cards**](/guide/cards/introduction) | [Card events](/guide/cards/events#card-events) – [Card Transaction events](/guide/cards/events-tx#card-transaction-events) – [3DSecure events](/guide/cards/events#_3dsecure-events) – [Country Group events](/guide/cards/events#country-group) – [MCC Group events](/guide/cards/events#mcc-group) – [MID Group events](/guide/cards/events#mid-group) |
| [**Transfers**](/guide/transfers/introduction) | [Payin/Payout events](/guide/transfers/events) – [Mandate events](/guide/transfers/events#mandate-events) – [Beneficiary events](/guide/transfers/events#beneficiary-events) – [Transfer events](/guide/transfers/events#transfer-events) |
| [**Checks**](/guide/cheques/introduction) | [Check events](/guide/cheques/events#check-payin-events) |
## Descriptions
| Event name | Triggering action | Payload |
|- |- |- |
| `authorization.create` | A card topup authorization was created. | `authorization` ([Structure](/guide/acquiring/events#authorization-create)) |
| `authorization.update` | A card topup authorization was updated. | `authorization` ([Structure](/guide/acquiring/events#authorization-update)) |
| `authorization.cancel` | A card topup authorization was canceled. | `authorization` ([Structure](/guide/acquiring/events#authorization-cancel)) |
| `balance.update` | A Wallet Balance has changed. | `balance` ([Structure](/guide/wallets/events#wallets)) |
| `beneficiary.create` | A Beneficiary has been created. | `beneficiary` ([Structure](/guide/transfers/events#beneficiary-create)) |
| `beneficiary.update` | A Beneficiary has been modified. | `beneficiary` ([Structure](/guide/transfers/events#beneficiary-update)) |
| `card3DSv2Authentication.create` | A cardholder must be identified with 3DS authentication. | `card3DSv2Authentication` ([Structure](/guide/cards/events-tx#card3DSv2authentication-create)) |
| `card3DSv2Authentication.update` | Indicates the final result of cardholder 3DS authentication. | `card3DSv2Authentication` ([Structure](/guide/cards/events-tx#card3DSv2authentication-update))|
| `card.requestphysical` | A Physical Card has been requested. | `card` ([Structure](/guide/cards/events#card-requestphysical)) |
| `card.createvirtual` | A Virtual Card has been created. | `card` ([Structure](/guide/cards/events#card-createvirtual)) |
| `card.convertvirtual` | A Virtual Card has been converted to a physical one. | `card` ([Structure](/guide/cards/events#card-convertvirtual)) |
| `card.expeditionTracking` | The manufacturer mailed the card. | `card` ([Structure](/guide/cards/events#card-expeditiontracking)) |
| `card.changepin` | A Card PIN has been changed. | `card` ([Structure](/guide/cards/events#card-changepin)) |
| `card.activate` | A Card has been activated. | `card` ([Structure](/guide/cards/events#card-activate)) |
| `card.register3DS` | A Card has been register for 3DS. | `card` ([Structure](/guide/cards/events#card-register3ds)) |
| `card.expiryAlert` | A Card expires the next month. | `card` ([Structure](/guide/cards/events#card-expiryalert)) |
| `card.renew` | A Card has been renewed (the previous one has expired). | `card` ([Structure](/guide/cards/events#card-renew)) |
| `card.regenerate` | A Card Image has been regenerated. | `card` ([Structure](/guide/cards/events#card-regenerate))|
| `card.update` | A Card `mccRestristionGroupId`, `merchantRestrictionGroupId` and `countryRestrictionGroupId` have been updated. | `card` ([Structure](/guide/cards/events#card-update)) |
| `card.limits` | A Card limits have been updated. | `card` ([Structure](/guide/cards/events#card-limits)) |
| `card.options` | A Card options have been updated. | `card` ([Structure](/guide/cards/events#card-options)) |
| `card.assignwallet` | A Card has been assigned to a new wallet. | `card` ([Structure](/guide/cards/events#card-assignwallet)) |
| `card.setpin` | A Card PIN has been set. | `card` ([Structure](/guide/cards/events#card-setpin)) |
| `card.unblockpin` | A Card PIN has been unblocked. | `card` ([Structure](/guide/cards/events#card-unblockpin)) |
| `card.unblockcvc2` | A Card CVC has been unblocked. | `card` ([Structure](/guide/cards/events#card-unblockcvc2)) |
| `cardBulkUpdate.create` | A Card Bulk Update has been created. | `cardBulkUpdate` ([Structure](/guide/cards/events#cardbulkupdate-create)) |
| `cardBulkUpdate.update` | A Card Bulk Update has been updated (e.g., processing complete). | `cardBukUpdate` ([Structure](/guide/cards/events#cardbulkupdate-update)) |
| `card.lockunlock` | A Card has been locked, unlocked, lost, stolen, or destroyed. | `card` ([Structure](/guide/cards/events#card-lockunlock)) |
| `cardDigitalization.request` | **Production only.** | `cardDigitalization` ([Structure](/guide/cards/events#carddigitalization-request)) |
| `cardDigitalization.update` | **Production only.** | `cardDigitalization` ([Structure](/guide/cards/events#carddigitalization-update)) |
| `cardDigitalization.activation` | **Production only.** | `cardDigitalization` ([Structure](/guide/cards/events#carddigitalization-activation)) |
| `cardDigitalization.complete` | **Production only.** | `cardDigitalization` ([Structure](/guide/cards/events#carddigitalization-complete)) |
| `cardDigitalization.deactivated` | **Production only.** | ([Structure](/guide/cards/events#carddigitalization-deactivated)) |
| `cardtransaction.create` | A Card Transaction has been initiated. | `cardtransaction` ([Structure](/guide/cards/events-tx#cardtransaction-create)) |
| `card.acquiring.chargeback.create ` | A chargeback had been received. | `card.acquiring` ([Structure](/guide/acquiring/events#card-acquiring-chargeback-create)) |
| `countryGroup.create` | A country restriction group has been created. | `countryGroup` ([Structure](/guide/cards/events#countrygroup-create)) |
| `countryGroup.update` | A country restriction group has been updated. | `countryGroup` ([Structure](/guide/cards/events#countrygroup-update)) |
| `countryGroup.cancel` | A country restriction group has been cancelled. | `countryGroup` ([Structure](/guide/cards/events#countrygroup-cancel)) |
| `document.create` | A Document has been created. | `document` ([Structure](/guide/user-verification/events#document-create)) |
| `document.update` | A Document has been modified. | `document` ([Structure](/guide/user-verification/events#document-update)) |
| `document.cancel` | A Document has been deleted. | `document` ([Structure](/guide/user-verification/events#document-cancel)) |
| `kycliveness.create` | A User has sent documents through the live verification process. | `kycliveness` ([Structure](/guide/user-verification/events#kycliveness-create)) |
| `kycliveness.update` | The Live verification provided has analyzed the documents provided by the user. | `kycliveness` ([Structure](/guide/user-verification/events#kycliveness-update)) |
| `mandate.create` | A Mandate has been created. | `mandate` ([Structure](/guide/transfers/events#mandate-create)) |
| `mccGroup.create` | A MCC restriction group has been created. | `mccGroup` ([Structure](/guide/cards/events#mccgroup-create)) |
| `mccGroup.update` | A MCC restriction group has been updated. | `mccGroup` ([Structure](/guide/cards/events#mccgroup-update)) |
| `mccGroup.cancel` | A MCC restriction group has been canceled. | `mccGroup` ([Structure](/guide/cards/events#mccgroup-cancel))|
| `merchantIdGroup.create` | A MID restriction group has been created. | `merchantIdGroup` ([Structure](/guide/cards/events#merchantidgroup-create)) |
| `merchantIdGroup.update` | A MID restriction group has been updated. | `merchantIdGroup` ([Structure](/guide/cards/events#merchantidgroup-update))|
| `merchantIdGroup.cancel` | A MID restriction group has been canceled. | `merchantIdGroup` ([Structure](/guide/cards/events#merchantidgroup-cancel)) |
| `payin.create` | A payin object has been created. | `payin` ([Structure](/guide/transfers/events#payin-create)) |
| `payin.update` | A payin object has been updated. | `payin` ([Structure](/guide/transfers/events#payin-update)) |
| `payin.cancel` | A payin object has been canceled. | `payin` ([Structure](/guide/transfers/events#payin-cancel)) |
| `payinrefund.create` | A Refund for a payin has been created. | `payinrefund` ([Structure](/guide/transfers/events#payinrefund-create))|
| `payinrefund.update` | A Refund for a payin has been updated. | `payinrefund` ([Structure](/guide/transfers/events#payinrefund-update))|
| `payinrefund.cancel` | A Refund for a payin has been canceled. | `payinrefund` ([Structure](/guide/transfers/events#payinrefund-cancel))|
| `payout.create` | A payout object has been created. | `payout` ([Structure](/guide/transfers/events#payout-create)) |
| `payout.update` | A payout object has been updated. | `payout` ([Structure](/guide/transfers/events#payout-update)) |
| `payout.cancel` | A payout object has been canceled. | `payout` ([Structure](/guide/transfers/events#payout-cancel)) |
| `payoutRefund.create` | A Refund for a payout has been created. | `payoutRefund` ([Structure](/guide/transfers/events#payoutrefund-create)) |
| `payoutRefund.update` | A Refund for a payout has been updated. | `payoutRefund` ([Structure](/guide/transfers/events#payoutrefund-update)) |
| `payoutRefund.cancel` | A Refund for a payout has been canceled. | `payoutRefund` ([Structure](/guide/transfers/events#payoutrefund-cancel)) |
| `qes.created` | The user completed the QES verification process. | `qes` ([Structure](/guide/user-verification/events#qes-created)) |
| `qes.processing` | The QES verification process is under review on the verification provider side. | `qes` ([Structure](/guide/user-verification/events#qes-processing)) |
| `qes.aborted` | The user abandoned the QES process. | `qes` ([Structure](/guide/user-verification/events#qes-aborted)) |
| `qes.finalized` | The QES process is done on the verification provider side, either successful or canceled. | `qes` ([Structure](/guide/user-verification/events#qes-finalized)) |
| `recallR.need_response` | | `recallr` ([Structure](/guide/transfers/events#recallr-need-response)) |
| `sca.wallet.create` | An SCA Wallet has been created. | `scaWallet` ([Structure](/guide/strong-customer-authentication/events#sca-wallet-create)) |
| `sca.wallet.update` | An SCA Wallet has been activated. | `scaWallet` ([Structure](/guide/strong-customer-authentication/events#sca-wallet-update)) |
| `sca.wallet.delete` | An SCA Wallet has been deleted. | `scaWallet` ([Structure](/guide/strong-customer-authentication/events#sca-wallet-delete)) |
| `sca.wallet.lock` | An SCA Wallet has been locked. | `scaWallet` ([Structure](/guide/strong-customer-authentication/events#sca-wallet-lock)) |
| `sca.wallet.resetPin` | An SCA Wallet has been created. | `scaWallet` ([Structure](/guide/strong-customer-authentication/events#sca-wallet-resetpin)) |
| `sca.wallet.swap` | An SCA Wallet has been swapped. | `scaWallet` ([Structure](/guide/strong-customer-authentication/events#sca-wallet-swap)) |
| `sca.wallet.unlock` | An SCA Wallet has been unlocked. | `scaWallet` ([Structure](/guide/strong-customer-authentication/events#sca-wallet-unlock)) |
| `sepaSctrInst.reject_sctr_inst` | | `sepaSctrInst` ([Structure](/guide/transfers/events#sepasctrinst-reject-sctr-inst)) |
| `sepa.refund_sddr` | A SEPA Direct Debit (SDDR) has been refunded. | `sepaSddr` ([Structure](/guide/transfers/events#sepa-refund-sddr)) |
| `sepa.reject_sddr_core` | A SEPA Direct Debit (SDDR) has been rejected. | `sepaSddr` ([Structure](/guide/transfers/events#sepa-reject-sddr-core)) |
| `sepa.reject_sddr_b2b` | A SEPA Direct Debit (SDDR B2B) has been rejected. | `sepaSddr` ([Structure](/guide/transfers/events#sepa-reject-sddr-b2b)) |
| `sepa.return_sctr` | **Production only.** | `sepaSctr` ([Structure](/guide/transfers/events#sepa-return-sctr)) |
| `sepa.return_sddr` | A SEPA Direct Debit (SDDR) has been returned. | `sepaSdde` ([Structure](/guide/transfers/events#sepa-return-sddr)) |
| `separecallsctrinst.reception` | | `separecallsctrinst` ([Structure](/guide/transfers/events#separecallsctrinst-reception)) |
| `sepa_sddr.reception` | | `sepa_sddr` ([Structure](/guide/transfers/events#sepa-sddr-reception)) |
| `topupCard.validate`| A Card Topup has been validated. | `topupCard` ([Structure](/guide/acquiring/events#topupcard-validate)) |
| `topupCard.cancel`| A Card Topup has been canceled. | `topupCard` ([Structure](/guide/acquiring/events#topupcard-cancel)) |
| `transaction.create` | A Transaction was created. | `transaction` ([Structure](/guide/transfers/events#transaction-create)) |
| `transfer.create` | A Wallet-to-Wallet Transfer has been created. | `transfer` ([Structure](/guide/transfers/events#transfer-create)) |
| `transfer.update` | A Wallet-to-Wallet Transfer has been updated. | `transfer` ([Structure](/guide/transfers/events#transfer-update)) |
| `transfer.cancel` | A Wallet-to-Wallet Transfer has been canceled. | `transfer` ([Structure](/guide/transfers/events#transfer-cancel)) |
| `user.create` | A User has been created. | `user` ([Structure](/guide/users/events#user-create)) |
| `user.update` | A User has been modified. | `user` ([Structure](/guide/users/events#user-update)) |
| `user.cancel` | A User has been deactivated. | `user` ([Structure](/guide/users/events#user-cancel))|
| `user.kycreview` | Treezor has validated or refused the User KYC. | `user` ([Structure](/guide/user-verification/events#user-kycreview)) |
| `user.kycrequest` | A User requested a KYC Review. | `user` ([Structure](/guide/user-verification/events#user-kycrequest)) |
| `videoConference.created` | The user completed the video conference verification process. | `videoConference` ([Structure](/guide/user-verification/events#videoconference-created)) |
| `videoConference.processing` | The video conference verification process is under review on the verification provider side. | `videoConference` ([Structure](/guide/user-verification/events#videoconference-processing)) |
| `videoConference.aborted` | The user abandoned the video conference process. | `videoConference` ([Structure](/guide/user-verification/events#videoconference-aborted)) |
| `videoConference.finalized` | The verification process is done on the verification provider side, either successful or canceled. | `videoConference` ([Structure](/guide/user-verification/events#videoconference-finalized)) |
| `wallet.create` | A Wallet has been created. | `wallet` ([Structure](/guide/wallets/events#wallets)) |
| `wallet.update` | A Wallet has been modified. | `wallet` ([Structure](/guide/wallets/events#wallet-update)) |
| `wallet.cancel` | A Wallet has been deactivated. | `wallet` ([Structure](/guide/wallets/events#wallet-cancel)) |
---
---
url: /guide/webhooks/integrity-checks.md
description: >-
Ensure Treezor API webhook authenticity and integrity. This guide details how
to verify payloads using the relevant fields, covering signature generation
(HMAC-SHA256) and secure handling of webhook responses.
---
# Enforcing integrity
Every `object_payload` you receive is accompanied by an `object_payload_signature`.
This signature (or [hash](https://en.wikipedia.org/wiki/Hash_function)) allows you to make sure that:
* **The payload was emitted by Treezor**
* **The payload has not been altered**
**Security – Check for integrity**
You MUST check the integrity of the payload against the `object_payload_signature` before trusting it.
## How to check the payload integrity
For each received webhook, follow these steps:
* **Flatten** the received JSON payload
* **Convert** UTF-8 characters to their Unicode sequence equivalent (`é` to `\u00e9`, `è` to `\u00e8`, etc.)
* **Generate** the cryptographic signature of the payload (HMAC using the secret)
* **Convert** the binary signature to base64
* **Compare** your signature to the one provided along with the webhook
* **Respond** according to the comparison result
### Generate your own signature of the payload
To verify the integrity of the webhooks, Treezor provided you with a `webhook_secret` string.
**Security – Keep your secret string safe**
If a third-party were to access this secret string, they could send you fake events and your application would trust them.
This secret is used as a [salt](https://en.wikipedia.org/wiki/Salt_\(cryptography\)) to hash the payload of each event.
```js [JavaScript]
// dependencies
const fs = require('fs');
const crypto = require('crypto');
// declare a function to encode UTF-8 characters to their unicode sequence equivalent (\uxxxx)
let encodeUTF8ToCodePoint = (s) => {
return s.replace(
/[^\x20-\x7F]/g,
x => "\\u" + ("000"+x.codePointAt(0).toString(16)).slice(-4)
)
}
// function to compute the signature
const computedSignature = crypto.createHmac('sha256', WEBHOOK_SECRET)
.update(
encodeUTF8ToCodePoint(
JSON.stringify(body.object_payload).replace(/\//g, '\\/')
)
)
.digest('base64');
```
```python [Python]
# function to compute the signature
def compute_signature(secret, payload):
payload = json.dumps(payload, separators=(",", ":"))
payload = payload.replace("\\/", "/") # Json dump escape / twice
payload = payload.replace("\\/", "/") # remove all \
payload = payload.replace("/", "\\/") # add \
hmac_sha256 = hmac.new(
secret.encode("utf-8"),
payload=payload.encode("utf-8"),
digestmod=hashlib.sha256
)
return base64.b64encode(hmac_sha256.digest()).decode("utf-8")
```
```ruby [Ruby]
# dependencies
require 'json'
require 'openssl'
# Function to encode UTF-8 characters to their unicode sequence equivalent (\uxxxx)
def encode_utf8_to_code_point(s)
s.gsub('/', '\\/').gsub(/[^ -~]/) { |m| "\\u%04x" % m.ord }
end
# Function to compute the signature
def compute_signature(secret, object_payload)
digest = OpenSSL::Digest.new('sha256')
hmac = OpenSSL::HMAC.digest(digest, secret, encode_utf8_to_code_point(object_payload.to_json))
base64_signature = [hmac].pack('m0') # Base64 encoding
end
```
```java [Java]
// dependencies
import java.util.regex.Pattern;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
// Function to encode UTF-8 characters to their unicode sequence equivalent (\uxxxx)
public static String encodeUTF8ToCodePoint(String s) {
Pattern pattern = Pattern.compile("[^\\x20-\\x7E]");
return pattern.matcher(s).replaceAll(match -> {
String hex = Integer.toHexString(match.group().codePointAt(0));
return "\\u" + ("0000" + hex).substring(hex.length());
});
}
// Function to compute the signature
public static String computeSignature(String secret, String objectPayload) throws Exception {
// Initialize HMAC with SHA256
Mac sha256_Hmac = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKey = new SecretKeySpec(secret.getBytes(StandardCharsets.US_ASCII), "HmacSHA256");
sha256_Hmac.init(secretKey);
// Encode payload and replace characters
String encodedPayload = encodeUTF8ToCodePoint(objectPayload).replace("/", "\\/");
byte[] payloadBytes = encodedPayload.getBytes(StandardCharsets.UTF_8);
// Compute HMAC data
byte[] hmacData = sha256_Hmac.doFinal(payloadBytes);
// Convert to Base64 string
return Base64.getEncoder().encodeToString(hmacData);
}
```
```php [PHP]
// generate your own version of the signature
function compute_signature(string $secret, array $object_payload) :string {
return base64_encode(
hash_hmac(
'sha256',
// In PHP, there is no need to encode UTF-8 characters to their unicode sequence
// since PHP's json_encode() function already does that automatically
json_encode($object_payload),
$secret, // as provided by your Treezor Account Manager
true
)
);
}
```
**Information – Convert your signature UTF-8 characters to unicode**
Treezor generates the `object_payload_signature` after converting all UTF-8 characters into the corresponding unicode sequences. You **must** do the same, otherwise you will produce mismatching signatures. (e.g., `é` must become `\u00e9`, `è` becomes `\u00e8`).
### Compare your signature with the webhook's signature
```php [PHP]
// compare the newly generated signature with the webhook's signature
if(strcomp(
$payload_local_signature,
// decode the payload and extract the provided signature from it
json_decode(file_get_contents("php://input"), true)['object_payload_signature']
) === 0) {
// signature are identical, we can trust the payload
// proceed...
}
else {
// signatures differ, we cannot trust the payload
Throw new Exception('Mismatching signatures', 500);
}
```
## What should my application return?
### Signatures are identical
You should return a `200` HTTP Status Code.
**Best practice – Defer the verified webhook in a queueing system for async processing**
Without asynchroneous processing, if your code fails to process the webhook, Treezor would not attempt to deliver the webhook again as you have already answered with a `200` HTTP Status Code. This could lead to data inconsistency on your side.
### Signatures don't match
You should return an HTTP Status Code in the `500` range.
Either way, there is no need to populate the response any further.
When your server answers with a Status Code higher than `499` or when it takes more than **150ms** to answer, Treezor sends you the webhook again every minute (maximum of 30 attempts). If the 30 attempts limit is reached, then:
* No more attempts are made
* An incident notification is sent to Treezor
Treezor will get in touch with you to diagnose the issue. Once the issue is resolved, webhook are sent normally again.
## Increased security
Treezor offers several ways to increase the security of webhooks:
### IP Restriction
You **may** request that they be sent to you from a fixed IP. This allows your code to check the source IP in addition to webhooks signatures. To request a fixed IP, please get in touch with your *Treezor Account Manager*.
By default webhooks are sent from dynamic IP and don't allow for such checks.
### Amazon Web Services SQS
If your infrastructure is built on AWS, you **should** get in touch with your *Treezor Account Manager* so that we can set up Amazon SQS instead of relying on webhook signatures.
---
---
url: /guide/webhooks/retry.md
description: >-
Learn how to resend up to 20,000 webhooks per batch from a pre-generated CSV
file. Includes required parameters, request structure, and response examples.
---
# Retry webhooks
Treezor provides a series of endpoints to resend webhooks.
**Prerequisites – Service starting in October 2025**
You can only retry webhooks emitted after October 1st 2025. Please contact Treezor through the [Support Center](https://treezor.zendesk.com/hc/en-us/articles/4403978479634-How-to-create-a-Zendesk-ticket) for requests anterior to that date.
Resending webhooks is a 3-step process:
1. **Generate webhook history CSV file** for a given time frame.
2. **Request execution of the file** to resend the events contained generated .CSV file (up to 20,000 events).
3. **Retrieve the execution status** of the resent events batch.
**Information – The `{webhooksBaseUrl}` variable isn't your [`{baseUrl}`](/guide/api-basics/environments)**
* `https://webhook.sandbox.treezor.co` in [Sandbox](/guide/api-basics/environments#sandbox)
* `https://webhook.api.treezor.co` in [Production](/guide/api-basics/environments#production)
## Generate webhook history CSV
You first need to generate the .CSV file containing the webhook events you wish to resend.
### Parameters
| Attribute | Type | Description |
| --- | --- | --- |
| `startAt` | string | The date and time from which to retrieve the webhooks. Format: RFC3339. |
| `endAt` | string | The date and time up to which to retrieve the webhooks. Format: RFC3339. |
| `webhook` | string | Filter for a specific event, if need be. Example: `wallet.create`. See the [Events description](./events-descriptions) article for the list of events. |
### Request example
Endpoint: [`/retry/query`](/api-reference/webhook-endpoints.html#tag/Webhook%20Retry/webhookQueryRetry){target="\_self"}
```bash [CURL]
curl -X POST '{webhooksBaseUrl}/retry/query' \
--header 'authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`.
```json [JSON]
{
"startAt": "2025-06-10T12:10:00+02:00",
"endAt": "2025-07-08T00:00:00+02:00",
"webhook": "merchantIdGroup.create"
}
```
Returns the following object:
```json [JSON]
{
"queryId": "2bd5740a-528d-451d-a726-7f57c6d82008",
"link": "https://your.csv.link",
"expireIn": 300
}
```
If the .CSV file contains more than 20,000 events, you must adjust the time frame until you reach 20,000 or lower in order to move to step 2.
## Resend events batch
Now that a .CSV file with a maximum number of 20,000 events has been generated, you can use the execution endpoint to resend all the events contained in the file.
### Parameters
| Attribute | Type | Description |
| --- | --- | --- |
| `queryId` | string | The unique identifier of the query obtained in the first step. |
| `delay` | integer | The time between each webhook retry attempts in seconds, in order to not overload your servers. Can't exceed 1 hour (`3600`). |
### Request example
Endpoint: [`/retry/exec`](/api-reference/webhook-endpoints.html#tag/Webhook%20Retry/webhookExecRetry){target="\_self"}
```bash [CURL]
curl -X POST '{webhooksBaseUrl}/retry/exec' \
--header 'authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`.
```json [JSON]
{
"queryId": "2bd5740a-528d-451d-a726-7f57c6d82008",
"delay": 10
}
```
Returns the following object:
```json [JSON]
{
"executionId": "12345678-1234-1234-1234-123456789abc",
"status": "IN_PROGRESS"
}
```
## Retrieve the execution status
You can check whether the resend batch is completed using the dedicated request below with the `executionId` from the previous step.
### Request example
Endpoint: [`/retry/exec/{executionId}`](/api-reference/webhook-endpoints.html#tag/Webhook%20Retry/checkWebhookRetryStatus){target="\_self"}
```bash [CURL]
curl -X GET '{webhooksBaseUrl}/retry/exec/{executionId}' \
--header 'authorization: Bearer {accessToken}'
```
Returns the following object, with the `status` valued to either `IN_PROGRESS` or `DONE`.
```json [JSON] {3}
{
"executionId": "12345678-1234-1234-1234-123456789abc",
"status": "DONE",
"lastEventAt": "2025-04-23T10:30:00Z"
}
```
---
---
url: /guide/webhooks/subscription-management.md
description: >-
Manage your Treezor API webhook subscriptions. This guide details how to
register webhook endpoints, set up your back end to receive events, and manage
subscribed events (list, update, unsubscribe) for tailored real-time
notifications.
---
# Subscription management
Webhook reception requires you subscribe to them first. While a single subscription allows you to receive all webhooks, you can also register multiple endpoints to receive different events.
During the subscription, if you don't specify an explicit list of webhooks that you whish to receive, you will automatically subscribe to all events.
**Information – The `{webhooksBaseUrl}` variable isn't your [`{baseUrl}`](/guide/api-basics/environments)**
* `https://webhook.sandbox.treezor.co` in [Sandbox](/guide/api-basics/environments#sandbox)
* `https://webhook.api.treezor.co` in [Production](/guide/api-basics/environments#production)
**Configuration – You may need assistance for your `{accessToken}`**
While the `{accessToken}` should be either your BaaS API key or your [Connect JWT token](/guide/api-basics/authentication), webhook subscription may require an action from Treezor. Contact your *Treezor Implementation Manager* for more information.
## Declare a POST route in your back end
In your back end, you should define a route that accepts HTTP POST requests.
Below is an example using node.js/express:
```js [JavaScript]
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
// parse the application/json
app.use(bodyParser.json());
// expose a POST endpoint
app.post('/webhook', function (req, res) {
// log each call (will be necessary to manually confirm the endpoint, step 3)
console.log(JSON.stringify(req.body));
});
// start listering for webhooks
app.listen(3000, function () {
console.log('Example app listening on port 3000!')
});
```
Then deploy this endpoint to a server:
* Which is reachable from internet
* On which you can consult the logs (to confirm your subscription at a later stage)
**Tip – Making your development server reachable from internet**
Several options are available to you to make your development server reachable from internet. See the [Testing in Sandbox](/guide/webhooks/testing-in-sandbox) article for more information.
## Register a hook endpoint
The second step is to register your newly created endpoint using the following request.
Endpoint: [`/settings/hooks`](/api-reference/webhook-endpoints.html#tag/Subscriptions/createSubscription){target="\_self"}
```bash [CURL]
curl -X POST '{webhooksBaseUrl}/settings/hooks' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{"url":"{urlOfYourEndpoint}"}'
```
Returns the list of webhooks including the newly created one **with a temporary `uuid`** in a pending status. The `uuid` changes when the subscription is validated later on.
```json [JSON]
{
"hooks": [
{
"uuid": "d956cff0-04a2-530f-810b-66a5130e0e4a",
"url": "{urlOfYourEndpoint}",
"status": "PENDING"
}
]
}
```
You are now receiving new events.
## List your webhooks subscriptions
You can list your subscriptions using the following request.
Endpoint: [`/settings/hooks`](/api-reference/webhook-endpoints.html#tag/Subscriptions/getSubscriptions){target="\_self"}
```bash [CURL]
curl -X GET '{webhooksBaseUrl}/settings/hooks' \
--header 'Authorization: Bearer {accessToken}'
```
Returns the list of subscriptions, with their `uuid` and `status`.
```json [JSON]
{
"hooks":[
{
"uuid": "44c37ba5-f1fe-4d8a-ac2b-xxxxx6a2ae67",
"url": "https:\/\/0***l.execute-api.eu-west-3.amazonaws.com\/dev\/aHR...3Q=",
"status": "ENABLED"
},
{
"uuid": "cd98d460-f344-4c05-a192-xxxxxf6c0a4a",
"url": "https:\/\/alexoak:****@0***l.execute-api.eu-west-3.amazonaws.com\/dev\/aHR...3Q=",
"status": "ENABLED"
},
{
"uuid": "46a508cb-1c72-48be-a42d-xxxxxa704cec",
"url": "https:\/\/alexoak:****@0***l.execute-api.eu-west-3.amazonaws.com\/dev\/aHR...Hk=",
"status": "ENABLED"
},
{
"uuid": "0fae6471-25c3-4492-bc0d-xxxxx82e51ec",
"url": "https:\/\/alexoak:****@trz.requestcatcher.com\/example",
"status": "ENABLED"
}
]
}
```
## Retrieve details about a subscription
You can retrieve the list of events to which a webhook is subscribed to, using the following request.
Endpoint: [`/settings/hooks/{hookUuid}/events`](/api-reference/webhook-endpoints.html#tag/Events/getHookEvents){target="\_self"}
```bash [CURL]
curl -X GET '{webhooksBaseUrl}/settings/hooks/{hookUuid}/events' \
--header 'Authorization: Bearer {accessToken}'
```
Returns a list of [events](./events-descriptions#descriptions) to which you have subscribed.
```json [JSON]
{
"events":[
"payoutRefund.cancel",
"payoutRefund.create",
"payoutRefund.update"
]
}
```
**Note – An empty array is returned when you subscribed to all webhooks**
The list of events is only relevant when you subscribed to specific webhooks.
## Update a subscription
### Update events list
Specify the list of events in the payload (including the ones you've already subscribed to if any).
Endpoint: [`/settings/hooks/{hookUuid}/events`](/api-reference/webhook-endpoints.html#tag/Events){target="\_self"}
```bash [CURL]
curl -X POST '{webhooksBaseUrl}/settings/hooks/{hookUuid}/events' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
Here is an example of `{payload}`:
```json [JSON]
{
"events":[
"payoutRefund.cancel",
"payoutRefund.create",
"payoutRefund.update",
"beneficiary.update",
"beneficiary.create"
]
}
```
Returns the list of subscribed events as listed in the payload.
```json [JSON]
{
"events":[
"payoutRefund.cancel",
"payoutRefund.create",
"payoutRefund.update",
"beneficiary.update",
"beneficiary.create"
]
}
```
### Remove an event
You can remove one event at a time, specifying its name in the URL.
Endpoint: [`/settings/hooks/{hookUuid}/events/{eventToDelete}`](/api-reference/webhook-endpoints.html#tag/Events/deleteHookEvents){target="\_self"}
```bash [CURL]
curl -X DELETE '{webhooksBaseUrl}/settings/hooks/{hookUuid}/events/{eventToDelete}' \
--header 'Authorization: Bearer {accessToken}'
```
Returns the list of subscribed events, without the one just removed.
```json [JSON]
{
"events":[
"payoutRefund.create",
"payoutRefund.update",
"beneficiary.update",
"beneficiary.create"
]
}
```
---
---
url: /api-reference/webhook-endpoints.md
description: >-
The Treezor Webhooks API Reference. Explore the endpoints dedicated to
webhooks with detailed specifications, request/response examples, and schema
definitions in an interactive OpenAPI 3.0.1 powered interface.
---