---
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. Read more about the different kind of balances in the [Balance definition](/guide/overview/glossary#balance) of the Glossary.
## 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"}
::: code-group
```bash [CURL]
curl -X GET '{baseUrl}/v1/balances?walletId={walletId}' \
--header 'Authorization: Bearer {accessToken}'
```
:::
Returns the Balance object, with both the [Authorized Balance](/guide/overview/glossary#balance) (`authorizedBalance`) and [Balance](/guide/overview/glossary#balance) (`currentBalance`).
::: code-group
```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"}
::: code-group
```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).
::: code-group
```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"}
::: code-group
```bash [CURL]
curl -X GET '{baseUrl}/core-connect/balances/{walletId}?dateFrom=2021-11-01&dateTo=2022-10-01' \
--header 'Authorization: Bearer {accessToken}'
```
:::
::: code-group
```json [JSON]
{
"2021-03-31T09:50:02+00:00": {
"solde": 51.25,
"authorizedBalance": 51.25,
"currency": "EUR"
},
"2021-02-04T13:20:02+00:00": {
"solde": 170.00,
"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]
Cheque
Beneficiary
Mandate
Transfer["Wallet to Wallet"]
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
SCTE --- Beneficiary
SDDR --- Beneficiary
SDDE --- Mandate
MassSCTE --- SCTE
Beneficiary -.- ExternalAccount
%% Cheque Relations
Wallet -- Payin --- Cheque
%% 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
::: code-group
```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.
::: code-group
```bash [CURL]
curl -X GET '{baseUrl}/customization/templates' \
-H 'Authorization: Bearer {accessToken}' \
-H 'Content-Type: application/json'
```
:::
Returns the list of customizable templates.
::: code-group
```json [JSON]
{
"templates":[
"email.user.onboarding_confirmation_html",
"email.user.onboarding_confirmation_text",
"wallet.address_details",
"wallet.balance_certificate",
"wallet.closure_certificate",
"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.
::: code-group
```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`).
::: code-group
```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
::: code-group
```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.
::: code-group
```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.
::: code-group
```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.
::: code-group
```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.
::: code-group
```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.
::: code-group
```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`.
::: code-group
```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
::: code-group
```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
::: code-group
```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` 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).
::: code-group
```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(`Authentification failed with error code ${error.response.status}`);
}
}
}
authenticate();
```
:::
The following JSON object is returned if successful, your JWT being the `access_token`:
::: code-group
```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.
::: code-group
```bash [CURL]
curl -X GET '{baseUrl}/example/of/endpoint' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content: 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 only possible with *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:
::: code-group
```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
::: code-group
```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"' \ # mandatory
--form 'client_id="{yourClientId}"' \ # mandatory
--form 'client_secret="{yourClientSecret}"' \ # mandatory
--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 (**so be careful!**).
```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 navigating the *Profile Boards* view, *Beneficiaries* tab [once a user is selected](/guide/dashboard/users#accessing-your-users).
The view is broken down into 3 sub-tabs:
* **[SEPA Credit Transfer](#sepa-credit-transfer-sub-tab)** – Lists beneficiary bank accounts to which you can make an [SCTE payout](/guide/transfers/credit-transfer#emitted-credit-transfers-scte).
* **[SEPA Direct Debit (B2C)](#sepa-direct-debit-b2c-sub-tab)** – Lists beneficiary bank account from which you can make an [SDDR payout](/guide/transfers/direct-debit#received-direct-debits-sddr) (Core).
* **[SEPA Direct Debit (B2B)](#sepa-direct-debit-b2b-sub-tab)** – Lists beneficiary bank account from which you can make an [SDDR payout](/guide/transfers/direct-debit#received-direct-debits-sddr) (B2B).
### 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.
For each beneficiary, the following fields are available:
* **Status** – Either "Activated" or "Deactivated"
* **Name** – Displays the name of the beneficiary followed by the Tag in parentheses.
* **IBAN**
* **BIC**
The following commands are available:
| | Action | Description |
| :---: | --- | --- |
| | **View** | Displays the *Beneficiary details* popup. |
| | **Edit** | Displays the *Edit Beneficiary* popup. |
### SEPA Direct Debit (B2C) sub-tab
The *SEPA Direct Debit (B2C)* 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 in this tab are automatically created when debiting a Wallet using a SEPA Direct Debit (SDDR).
For each beneficiary, the following fields are available:
* **Status** – Either "Activated" or "Deactivated"
* **Name** – Displays the name of the beneficiary followed by the Tag in parentheses.
* **IBAN**
* **BIC**
* **[SEPA Creditor Identifier](/guide/overview/glossary#sepa-creditor-identifier-sci)** – The unique reference of an SDDR.
* **Whitelist** – List of [Unique Mandate Reference (UMR)](/guide/overview/glossary#unique-mandate-reference-umr) that have debited the user.
* **Blacklist** – List of [Unique Mandate Reference (UMR)](/guide/overview/glossary#unique-mandate-reference-umr) that are revoked.
The following commands are available:
| | Action | Description |
| :---: | --- | --- |
| | **View** | Displays the *Beneficiary details* popup. |
| | **Edit** | Displays the *Edit Beneficiary* popup. |
### SEPA Direct Debit (B2B) sub-tab
The *SEPA Direct Debit (B2B)* 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).
A beneficiary must be created first in order to be able to receive SEPA Direct Debit in B2B context. Indeed, the unique mandate reference is necessary for the reception of a SEPA Direct Debit.
For each beneficiary, the following fields are available:
* **Status** – Either "Activated" or "Deactivated"
* **Name** – Displays the name of the beneficiary followed by the Tag in parentheses.
* **IBAN**
* **BIC**
* **[SEPA Creditor Identifier](/guide/overview/glossary#sepa-creditor-identifier-sci)** – The unique reference of an SDDR.
* **Whitelist** – List of allowed [Unique Mandate Reference (UMR)](/guide/overview/glossary#unique-mandate-reference-umr), which is mandatory for B2B Direct Debit.
The following commands are available:
| | Action | Description |
| :---: | --- | --- |
| | **View** | Displays the *Beneficiary details* popup. |
| | **Edit** | Displays the *Edit Beneficiary* 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 later.
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).
::: code-group
```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:
::: code-group
```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.
::: code-group
```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.
::: code-group
```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}`:
::: code-group
```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.
::: code-group
```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
::: code-group
<<< @/guide/transfers/snippets/create\_payin.bash \[CURL]
:::
Here is an example of `{payload}`:
::: code-group
```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.
::: code-group
```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.
---
---
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.
::: code-group
```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.
::: code-group
```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":"{{temp_walletId}}",
"3":"{{temp_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 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.
::: code-group
```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.
::: code-group
```bash [CURL]
# encode your public credentials in base64
hipayPublicCredentials=`echo "mypublicuser:mypublicpassword" | base64 -`
# tokenize the card
curl -X GET '{hiPayTokenizationBaseUrl}/rest/v1/transaction?orderId={orderid}' \
--header 'Authorization: Basic {hipayPublicCredentials}' \ # as encoded above
--header 'Accept: application/json'
```
:::
Returns the following:
::: code-group
```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
::: code-group
```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}`:
::: code-group
```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.
::: code-group
```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 they can the payment. |
| `cancel_url` | string | The URL to which the user is to be redirected in case of |
| `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
::: code-group
```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}`.
::: code-group
```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":"{{temp_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.
::: code-group
```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
::: code-group
```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 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#payingrefund-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.
::: code-group
```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:
::: code-group
```json [JSON]
{
"status":"117",
"amount":34.56,
"user_id": "{{userId}}",
"wallet_id":"{{walletId}}",
"currency":"EUR",
"payment_product":"mastercard"
}
```
:::
Returns the following:
::: code-group
```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
::: code-group
```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}`:
::: code-group
```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.
::: code-group
```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 |
::: code-group
```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:
::: code-group
```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.
::: code-group
```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 |
::: code-group
```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:
::: code-group
```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:
::: code-group
```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 |
::: code-group
```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:
::: code-group
```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.
::: code-group
```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.
::: code-group
```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:
::: code-group
```json [JSON]
{
"transactionReference": "{transactionReference}"
}
```
:::
Returns an object containing the `chargebackId`:
::: code-group
```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.
::: code-group
```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.
::: code-group
```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":"{{temp_walletId}}",
"3":"{{temp_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.
::: code-group
```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.
::: code-group
```bash [CURL]
# encode your public credentials in base64
hipayPublicCredentials=`echo "mypublicuser:mypublicpassword" | base64 -`
# tokenize the card
curl -X GET '{hiPayBaseUrl}/rest/v1/transaction?orderId={orderid}' \
--header 'Authorization: Basic {hipayPublicCredentials}' \ # as encoded above
--header 'Accept: application/json'
```
:::
Returns the following Transaction, with the `token` available in the `paymentMethod` object.
::: code-group
```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
::: code-group
```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}`:
::: code-group
```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.
::: code-group
```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.
::: code-group
```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.
::: code-group
```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
::: code-group
```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.
::: code-group
```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.
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:
::: details 1. Project configuration
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.
:::
::: details 2. Implementation of card digitization with Treezor
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.
:::
::: details 3. Wallet provider certifications
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.
::: details Button examples
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. Additional information may be necessary for Apple Pay.
Endpoint: [`/issuerInitiatedDigitizationDatas`](/api-reference/api-endpoints.html#tag/issuerInitiatedDigitizationData/tavRequestPOST){target="\_self"}
::: code-group
```bash [CURL]
curl -X POST '{baseUrl}/v1/issuerInitiatedDigitizationDatas' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
:::
::: details PCI DSS endpoints
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:
::: code-group
```json [JSON]
{
"cardId": 0,
"tokenRequestor": "APPLE",
"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.
::: code-group
```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}`.
::: code-group
```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.
::: details Merchants usually initiate a tokenization request:
* 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 suspend or deactivate the card token as well.
However, if you're using the most recent services for card digitization, when the card status is set to `DESTROYED`, 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 | string | Description |
| --- | --- | --- |
| `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/digitalizedCard/{id}`](/api-reference/api-endpoints.html#tag/Digitized%20Cards/putDigitalized){target="\_self"}
::: code-group
```bash [CURL]
curl -X PUT '{baseUrl}/v1/digitalizedCard/{id}' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
:::
Here is an example of `{payload}`:
::: code-group
```json [JSON] {6}
{
"status": "suspend",
"reasonCode": "L"
}
```
:::
Returns the digitized card object, with the `status` set to `S`.
::: code-group
```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).
To do so, use the following request, with the [`reasonCode`](#reason-codes-reasoncode) as a query parameter (for the Mastercard scheme only).
#### Request example
Endpoint: [`/v1/digitalizedCard/{id}`](/api-reference/api-endpoints.html#tag/Digitized%20Cards/deleteDigitalized){target="\_self"}
::: code-group
```bash [CURL]
curl -X DELETE '{baseUrl}/v1/digitalizedCard/{id}?reasonCode={C}' \
--header 'Authorization: Bearer {accessToken}'
```
:::
Returns the digitized card object, with the `status` set to `X`.
::: code-group
```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
::: code-group
```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/digitalizedCard/{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/{cardId}/digitalizedCards`](/api-reference/api-endpoints.html#tag/Digitized%20Cards){target="\_self"} List digitalized cards for a given `cardId` | N/A |
| [`/v1/digitalizedCard/{id}`](/api-reference/api-endpoints.html#tag/Digitized%20Cards/getPaymentToken){target="\_self"} Retrieve a payment token | N/A |
| [`/v1/digitalizedCard/{id}`](/api-reference/api-endpoints.html#tag/Digitized%20Cards/putDigitalized){target="\_self"} Update a payment token status | N/A |
| [`/v1/digitalizedCard/{id}`](/api-reference/api-endpoints.html#tag/Digitized%20Cards/deleteDigitalized){target="\_self"} Deactivate a payment token | N/A |
::: details Deprecated
| 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.
## Cards
### `card.requestphysical`
::: code-group
```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"
}
]
},
"webhook_created_at": 17213000682093,
"webhook_id": "056b1e6d-17b3-4796-89e0-653f3cxxxx03",
"object_payload_signature": "wqGsyqDmHOnkrkyY/mjf+AuWeTlaxhraUxxxxxwMGs="
}
```
:::
### `card.createvirtual`
::: code-group
<<< @/guide/cards/snippets/event-card-createvirtual.json\[JSON]
:::
### `card.convertvirtual`
::: code-group
<<< @/guide/cards/snippets/event-card-convert.json\[JSON]
:::
### `card.changepin`
::: code-group
<<< @/guide/cards/snippets/event-card-changepin.json\[JSON]
:::
### `card.activate`
::: code-group
<<< @/guide/cards/snippets/event-card-activate.json\[JSON]
:::
### `card.renew`
::: code-group
```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"
}
]
},
"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`.
::: code-group
```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"
}
]
},
"webhook_created_at": 17213044534278,
"webhook_id": "6b0aee69-87c8-45df-a0d9-42xxxx9f38b",
"object_payload_signature": "WTFf7nbDnCoT6EVMRaTTTSHkA87BxxxxxdPCU30Usmo="
}
```
:::
### `card.limits`
::: code-group
```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"
}
]
},
"webhook_created_at": 17213046655230,
"webhook_id": "09cc975d-d9f8-4a61-a85d-c027022xx9e5",
"object_payload_signature": "zXK+EMoIk88fQ4xxxxxJaMhS9RPDteRAifLZxF8fd8="
}
```
:::
### `card.options`
::: code-group
```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"
}
]
},
"webhook_created_at": 17213047836871,
"webhook_id": "54517817-3ec9-4c65-8f56-0a9xxb2e68c",
"object_payload_signature": "6/pvFUoCdhyrhidvC2j+YihNZF9E0exxxxpEiDu72E="
}
```
:::
### `card.assignwallet`
::: code-group
```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"
}
]
},
"webhook_created_at": 17213044534278,
"webhook_id": "6b0aee69-87c8-45df-a0d9-42xxxx9f38b",
"object_payload_signature": "WTFf7nbDnCoT6EVMRaTTTSHkA87BxxxxxdPCU30Usmo="
}
```
:::
### `card.setpin`
::: code-group
<<< @/./guide/cards/snippets/event-card-setpin.json\[JSON]
:::
### `card.unblockpin`
::: code-group
```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`
::: code-group
```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"
}
]
},
"webhook_created_at": 17213013210351,
"webhook_id": "755c4496-ad53-4a29-9d27-2d9xxxx5b0f",
"object_payload_signature": "5hPGRs+h6eF+Un2VIUJ/V5KFlN4CxxxcjmDHxh0gLQU="
}
```
:::
### `card.lockunlock`
::: code-group
```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"
}
]
},
"webhook_created_at": 17213013210351,
"webhook_id": "755c4496-ad53-4a29-9d27-2d9xxxx5b0f",
"object_payload_signature": "5hPGRs+h6eF+Un2VIUJ/V5KFlN4CxxxcjmDHxh0gLQU="
}
```
:::
### `card.regenerate`
::: code-group
```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`
::: code-group
```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"
}
]
},
"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.
::: code-group
```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="
}
```
:::
### `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).
::: code-group
```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 Updates
### `cardBulkUpdate.create`
::: code-group
```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`
::: code-group
```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
### `cardDigitalization.request`
Webhook [TAR](x-pay-google-apple#glossary).
::: code-group
```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 in case of "ACCEPTED", populated in case of a "DECLINED"
"cardId": 6127,
"correlationId":""
},
"object_payload_signature": "++++++++++++++++++++++++++++++++++++++++++++"
}
```
:::
### `cardDigitalization.update`
::: code-group
```json [JSON]
{
"webhook": "cardDigitalization.update",
"object": "cardDigitalization",
"object_id": "11",
"object_payload": {
"id":123,
"cardId": 32134,
"status":"S",
"createdDate":"2022-10-19 15:12:50",
"modifiedDate":"2022-10-24 15:44:30",
"tokenServiceProvider": "Visa",
"updateType":""
},
"object_payload_signature": "++++++++++++++++++++++++++++++++++++++++++++"
}
```
:::
### `cardDigitalization.activation`
::: code-group
```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`
::: code-group
```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`
::: code-group
```json [JSON]
{
"messageId": "7e233828-a947-5fcd-8d27-xxxxxxxxxxxxxx",
"webhookId": "2b562cd5-b1ef-4962-8109-xxxxxxxxxxxxxx",
"webhook": {
"webhook": "cardDigitalization.deactivated",
"object": "cardDigitalization",
"object_id": "2773123",
"object_payload": {
"cardDigitalizations": [
{
"id": 2773123,
"cardId": 5390123,
"status": "X",
"createdDate": "2024-02-05 16:22:20",
"modifiedDate": "2024-02-15 11:49:17"
}
]
},
"webhook_created_at": 17079941571098,
"webhook_id": "2b562cd5-b1ef-4962-8109-xxxxxxxxxxxxxx",
"object_payload_signature": "++++++++++++++++++++++++++++++++++++++++++++"
}
}
```
:::
## MID Group
### `merchantIdGroup.create`
::: code-group
```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`
::: code-group
```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`
::: code-group
```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
### `mccGroup.create`
::: code-group
```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`
::: code-group
```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`
::: code-group
```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
### `countryGroup.create`
::: code-group
```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`
::: code-group
```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`
::: code-group
```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. |
| `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.
::: code-group
```[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:
::: code-group
```[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)).
::: code-group
```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 their 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/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`
**Tip – Get notified when a card is about to expire**
The [`card.expiryAlert`](/guide/cards/events#card-expiryalert) webhook helps you anticipate the card expiration.
### 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"}
::: code-group
```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:
::: code-group
```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"}
::: code-group
```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}`:
::: code-group
```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:
::: code-group
```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
}
]
}
```
:::
#### 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.
::: code-group
```bash [CURL]
curl -X PUT '{baseUrl}/v1/cards/{cardId}/renewalDetails' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
:::
There is an example of `{payload}`:
::: code-group
```json [JSON]
{
"renewalType": "A"
}
```
:::
Returns the Card Renewal Details object if successful:
::: code-group
```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/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.
::: code-group
```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}`:
::: code-group
```json [JSON]
{
"atm":1,
"online":1,
"nfc":1,
"foreign":0
}
```
:::
Returns the Card object, with the updated options and [`permsGroup`](#permission-groups-permsgroup):
::: code-group
```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 disable entirely a specific limit.**
To do so, set its value to `0`, but at least one of the following values must be greater than `0`: `limitPaymentDay`, `paymentDailyLimit`, `limitPaymentWeek`, `limitPaymentMonth`. The same applies for ATM limits (one of `limitAtmMonth`, `limitAtmWeek` or `limitAtmDay` 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.
::: code-group
```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}`:
::: code-group
```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.
::: code-group
```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. |
**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.
::: code-group
```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:
::: code-group
```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`.
::: code-group
```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.create`](./events#cardbulkupdate-create) – 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.
::: code-group
```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`.
::: code-group
```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`.
::: details Card object total spent amount
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 dayly 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
### Request
To create MCC restrictions, you can use the following request:
::: code-group
```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}`:
::: code-group
```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).
::: code-group
```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
**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:
::: code-group
```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}`:
::: code-group
```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).
::: code-group
```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
### Request
To create MID restrictions, you can use the following request:
::: code-group
```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}`:
::: code-group
```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).
::: code-group
```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).
::: code-group
```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}`.
::: code-group
```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.
::: code-group
```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.
::: code-group
```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}`.
::: code-group
```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.
::: code-group
```bash [CURL]
curl -X GET '{baseUrl}/core-connect/mid/metadata' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json'
```
:::
Returns all the MID metadata object you've created.
::: code-group
```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 a text, and instantly copy it. This applies to the card PIN, number (PAN), and verification code (CVV).
You must use asymmetrical **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 for 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 asymmetrical 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 asymmetrical key pair once consulted by cardholder
```
## 1. Generate an asymmetrical key pair on the end user’s device
Asymmetrical 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 can’t be shared
**Security – Generate at least 1 key pair by 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.
::: code-group
```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.
::: code-group
```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 on 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"} ).
::: code-group
```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.
::: code-group
```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 users' 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.
::: code-group
```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.
::: code-group
```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.
::: code-group
```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 asymmetrical 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
::: code-group
```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
::: code-group
```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/overview/glossary#balance) of the cardholder but leaves the [Balance](/guide/overview/glossary#balance) 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/overview/glossary#balance) nor the [Authorized Balance](/guide/overview/glossary#balance).
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) |
::: details Example
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/overview/glossary#balance).
**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/overview/glossary#balance) 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/overview/glossary#balance).
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/overview/glossary#balance) 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).
## 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.
::: code-group
```bash [CURL]
curl -X PUT '{baseUrl}/v1/auth-requests/{authRequestId}/result' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content: application/json' \
-d '{payload}'
```
:::
Here is a `{payload}` example.
::: code-group
```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.
::: code-group
```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.
::: code-group
```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.
::: code-group
```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
::: code-group
```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/overview/glossary#balance) 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/overview/glossary#balance) 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\_ID |
| `10` | | Approve | PARTIAL\_APPROVAL |
| `87` | | Approve | PURCHASE\_AMOUNT\_ONLY\_NO\_CASH\_BACK\_ALLOWED |
| `98` | | Approve | REFUND\_GIVEN\_TO\_CUSTOMER |
| `85` | | Approve | NOT\_DECLINED\_VALID\_FOR\_ALL\_ZERO\_AMOUNT\_TRANSACTIONS |
| `01` | | Call-Issuer | REFER\_TO\_CARD\_ISSUER |
| `70` | | Call-issuer | CONTACT\_CARD\_ISSUER |
| `41` | | Capture | LOST\_CARD |
| `43` | | Capture | STOLEN\_CARD |
| `02` | | Decline | CARD\_NOT\_YET\_ACTIVATED |
| `03` | | Decline | INVALID\_MERCHANT |
| `04` | | Decline | CAPTURE\_CARD\_CAPTURE |
| `05` | | Decline | DO\_NOT\_HONOR |
| `06` | | Decline | ERROR (REVERSAL ONLY) |
| `12` | | Decline | INVALID\_TRANSACTION |
| `13` | | Decline | INVALID\_AMOUNT |
| `14` | | Decline | INVALID\_CARD\_NUMBER |
| `15` | | Decline | INVALID\_ISSUER |
| `30` | | Decline | FORMAT\_ERROR |
| `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 |
| `61` | | Decline | EXCEEDS\_WITHDRAWAL\_AMOUNT\_LIMIT |
| `62` | | Decline | RESTRICTED\_CARD |
| `63` | | Decline | SECURITY\_VIOLATION |
| `65` | | Decline | EXCEEDS\_WITHDRAWAL\_COUNT\_LIMIT |
| `71` | | Decline | PIN\_NOT\_CHANGED |
| `75` | | Decline | ALLOWABLE\_NUMBER\_OF\_PIN\_TRIES\_EXCEEDED |
| `76` | | Decline | INVALID\_TO\_ACCOUNT\_SPECIFIED |
| `77` | | Decline | INVALID\_FROM\_ACCOUNT\_SPECIFIED |
| `78` | | Decline | INVALID\_ACCOUNT\_SPECIFIED\_GENERAL |
| `81` | | Decline | DOMESTIC\_DEBIT\_TRANSACTION\_NOT\_ALLOWED\_REGIONAL\_USE\_ONLY |
| `83` | | Decline | CARD\_DESTROYED |
| `84` | | Decline | INVALID\_AUTHORIZATION\_LIFE\_CYCLE |
| `86` | | Decline | PIN\_VALIDATION\_NOT\_POSSIBLE |
| `88` | | Decline | CRYPTOGRAPHIC\_FAILURE |
| `89` | | Decline | UNACCEPTABLE\_PIN\_\_TRANSACTION\_DECLINED\_\_RETRY |
| `91` | | Decline | AUTHORIZATION\_PLATFORM\_OR\_ISSUER\_SYSTEM\_INOPERATIVE |
| `92` | | Decline | UNABLE\_TO\_ROUTE\_TRANSACTION |
| `94` | | Decline | DUPLICATE\_TRANSMISSION\_DETECTED |
| `96` | | Decline | SYSTEM\_ERROR |
| `99` | | Decline | CARD\_VOIDED |
---
---
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 Transactions
### Authorized `cardtransaction.create`
::: code-group
```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",
"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",
"optimizedMerchantName": "string",
"merchantLogo": "http://yourmerchantlogo.png",
"merchantCategory": "string",
"transactionSubtype": "PRE",
"receiverData": "0104ENZO0308LUVIBILA",
"senderData": "0114Capital Com SV0314Capital Com SV0450LOPHITIS BUSINESS CENTER II, Floor 6,, 28 OKTOVRIO0508Limassol0703CYP080430351106205838",
"transactionTypeIdentifier": "C07",
"localMerchantId": "12345678900001"
}
]
},
"webhook_created_at":17132761057381,
"webhook_id":"32d41919-8390-4431-b74e-04f6c3xxx9a4",
"object_payload_signature":"/qTn7yr+xxx9e8Qx/DTTY+2a0mTKLnj5BQ0GT/snIvk="
}
```
:::
### Settled `cardtransaction.create`
::: code-group
```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",
"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",
"optimizedMerchantName": "string",
"merchantLogo": "string",
"merchantCategory": "string",
"transactionSubtype": "PRE",
"receiverData": "0104ENZO0308LUVIBILA",
"senderData": "0114Capital Com SV0314Capital Com SV0450LOPHITIS BUSINESS CENTER II, Floor 6,, 28 OKTOVRIO0508Limassol0703CYP080430351106205838",
"transactionTypeIdentifier": "C07",
"localMerchantId": "12345678900001"
}
]
},
"webhook_created_at":17132761057381,
"webhook_id":"32d41919-8390-4431-b74e-04f6c3xxx9a4",
"object_payload_signature":"/qTn7yr+xxx9e8Qx/DTTY+2a0mTKLnj5BQ0GT/snIvk="
}
```
:::
### Declined `cardtransaction.create`
::: code-group
```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",
"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",
"optimizedMerchantName": "string",
"merchantLogo": "string",
"merchantCategory": "string",
"transactionSubtype": "PRE",
"receiverData": "0104ENZO0308LUVIBILA",
"senderData": "0114Capital Com SV0314Capital Com SV0450LOPHITIS BUSINESS CENTER II, Floor 6,, 28 OKTOVRIO0508Limassol0703CYP080430351106205838",
"transactionTypeIdentifier": "C07",
"localMerchantId": "12345678900001"
}
]
},
"webhook_created_at":17132761057381,
"webhook_id":"32d41919-8390-4431-b74e-04f6c3xxx9a4",
"object_payload_signature":"/qTn7yr+xxx9e8Qx/DTTY+2a0mTKLnj5BQ0GT/snIvk="
}
```
:::
## 3DSecure
### `card3DSv2Authentication.create`
::: code-group
```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`
::: code-group
```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/overview/glossary#balance) and [Authorized Balance](/guide/overview/glossary#balance) 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.
::: code-group
```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**
You can request access to this feature by contacting your *Treezor Account Manager*.
## 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.
## 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 request.
### Parameters
| Attribute | Type | Description |
| --- | --- | --- |
| `publicToken` | string | The public token of the Card to use for the Card Transaction. |
| `transLink` | string | A unique reference used to associate the Card Transaction with a `paymentId`. Must be `100000000000000` or greater. |
| `paymentStatus` | string | The type of CardTransaction, which for simulation purposes can be `A` or `S`. See [list of values](./transactions#statuses-paymentstatus). |
| `date` | string | The date of the CardTransaction, as seen in the `authorizationIssuerTime` attribute. |
| `amount` | number | The amount of the CardTransaction, as seen it the `paymentAmount` and `paymentLocalAmount` attributes. |
| `mcc` | string | The Merchant Category Code for this CardTransaction, allowing you to check [your Card MCC restrictions](./modification#mcc-restrictions). |
| `merchantId` | string | The Merchant's ID for this CardTransaction, allowing you to check [your Card MID restrictions](./modification#mid-restrictions). |
| `merchantName` | string | The name of the merchant. |
**Tip – You can emulate a complete flow**
To emulate a [complete flow](./transactions-lifecycle), set a `paymentStatus` = `A` followed by `S` while specifying the same `transLink` for both requests.
Learn more about the different transaction flows in the [Transaction examples](./transactions-examples) article.
### Request
::: code-group
```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:
::: code-group
```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 and sends a [`cardtransaction.create`](./events-tx#cardtransaction-create) webhook.
**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.
## 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"}
::: code-group
```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:
::: code-group
```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.
::: code-group
```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"}
::: code-group
```bash [CURL]
curl -X PUT '{baseUrl}/v1/auth-requests/{authRequestId}/result' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content: application/json' \
-d '{payload}'
```
:::
Here is a `{payload}` example:
::: code-group
```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/overview/glossary#balance) 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/overview/glossary#balance) impact | [AuthorizedBalance](/guide/overview/glossary#balance) 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 Transaction object
::: code-group
```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/overview/glossary#balance) 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.
::: code-group
```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.
::: code-group
```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.
::: code-group
```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)
}
```
:::
## 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 toolbar*
* Navigating the *Profile Boards* view, *Cards* tab once a user is selected
### Search toolbar
The Dashboard main toolbar provides a series of search fields, most of them being based on user attributes.
Among those fields, the **Card Token** one takes into account the `cardId` or the `publicToken` of the [Card](/guide/cards/introduction).
**Tip – Find out more about the filters**
You may read the [Search toolbar](/guide/dashboard/users#search-toolbar) article to learn everything you need to know about the search fields.
Once you've clicked on the "Search" button for a given card, you are redirected to the corresponding user Profile, *Cards* tab.
### Profiles Board view, Cards tab
Once you've accessed a user Profile, you may click on the *Cards* tab in order to view all the cards attached to the user.
The view is divided into two sections:
* **Cards** – On the left-hand side, you can navigate and manage the user cards.
* **Transactions** – 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 Card" 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.
The following card information is available in the preview: card type (whether it is virtual, physical or converted to virtual), cardholder's name, card status, partially masked [PAN](/guide/overview/glossary#primary-account-number-pan), expiration date, unique identifier and public token.
The following commands can be available (depending on the situation):
* **Create card** – Takes you through the card creation process, where you define the card main information and select the restrictions and limits.
* **Block Card** – Opens the *Card settings* popup, [*Block Card*](#block-a-card) tab
* **More** – Provides access to the following options:
* Card settings – Opens the *Card settings* popup. This popup may be read-only if the card is in an inactive status.
* Wallet redirect – Switches the view to the *Wallets* tab, with the wallet to which the card is attached displayed.
* **Details** – Switches to the detailed fields of the card, providing additional fields and renewal information if relevant.
The card display is different depending on its status:
| Status | Description | Card display |
|--- | --- | --- |
| **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. | |
### 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 |
|:---: |--- |--- |
| | Date range | Allows you to define after (From) and/or before (To) which dates the transactions are considered. Any transaction whose authorization date is not in the defined time frame is filtered out. |
| | Amount range | Allows you to define the minimum and maximum amounts for the transactions to be considered. Any transaction outside the frame is filtered out. |
| | Merchant Id | Allows you to enter a Merchant Id. Only transactions with this MID are then displayed. |
| | Payment Type | Allows you to select whether to display only withdrawals or payments (i.e., online, in-person and NFC). |
| | Payment Status | Allows you to select the transactions to be displayed based on their Status (e.g., Accepted, Declined, etc.) |
| | Clear | Resets all the sorting and filtering options. |
| | Organize columns | Opens a panel that allows 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. |
## Creating a Card
You can create a new card for a user from the *Profile Boards* 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**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 *Profile Boards* view, *Cards* tab for any selected user. Most options are available in the *Card Settings* popup, available upon clicking on the "More" button and selecting the "Card settings" option.
You'll 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 in the right-hand side of the user Profile, *Cards* tab. The following confirmation popup will be displayed for you to activate the card.
**Best practice – Enhance the customer experience by having cardholders activating their cards**
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 |
| --- | --- |
| **[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. |
| **[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. |
**Tip – Cards can be enrolled with both methods at the same time**
This allows you to request a fallback to the SMS method if the Out of Band authentication is not possible during a card transaction.
To enable 3DS, go to the *Card Settings* popup, click on the "Enroll 3DS" button available in the *Card* section and select the enrollment options that suit your need.
**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 *Card Settings* popup, *Settings* tab, *Options* section, the following settings are available for you to update:
* **Online** – Enables e-commerce payments
* **NFC** – Enables contactless payments
* **ATM** – Enables ATM withdrawals
* **International** – Enables usage outside of the cardholder's country
### Update Card limits
You can modify both the **Payment limits** and **Withdrawal (ATM) limits** of a Card in the *Card settings* popup, *Limits* tab.
**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. |
### Manage Card restrictions
Card restrictions allow you to define in which countries and for which merchants a card may be used.
In the *Card Settings* popup, *Restrictions* tab, you can enable or prevent the use of the card for an individual or a set of:
* **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)
**Tip – Restriction groups can be predefined**
If you have the relevant [Role](/guide/dashboard/dashboard-users#dashboard-user-roles), you can predefine a series of restriction groups in the Administration *Predef Restriction Groups* view. Otherwise, you may ask your administrator.
#### Select the type of restriction to add or update
In order to update the card restriction, select a restriction category on the left-hand side of the view. The display is different depending on whether a restriction group already applies or if there are no restrictions for the category.
#### Define the restrictions
Once a restriction category selected, you need to choose between the following options:
* **Use a predefined list** – Update an existing predefined list by adding new elements
* **Create a list manually** – Create a new list manually
* **Upload a CSV** – Upload a CSV file to update your restrictions.
#### Remove restrictions
You may use the "Delete" option available upon clicking on the "More" button of a selected restriction in order to remove it. You're then free to replace it.
### Block a Card
The Dashboard lets you block a card in case of a security issue.
In the *Card settings* popup, *Block Card* tab, you can manage the card blocked status. Options available depends on the current card status:
| Action | Description |
| --- | --- |
| **Secure the card** | Temporarily lock (or custom lock) the card, you may unblock it afterward. |
| **Card Opposition** | Declare the card as stolen or lost. This action is irreversible. |
| **Close Card** | Blocks permanently the card, at the end of the relationship with the end user for instance. This action is irreversible. |
| **Unlock Card** | Unlock the card. Only available when the card has been temporarily locked. |
Once the relevant option selected, click on the "Save Changes" button to apply your choice.
### Unblock PIN code
The card can be blocked when the end user enters 3 erroneous PIN codes in a row.
You can unblock a card CVC in the *Card settings* popup, *Unblock PIN/CVC* tab, *Unblock PIN* section. The button is only displayed 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 *Card settings* popup, *Unblock PIN/CVC* tab, *Unblock CVC* section.
**You must ensure 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 *Card Settings* popup and click on the "Convert to Physical Card" button available in the *Card* section on the left-hand side.
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 *Card Settings* 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 could be reactivated if need be.
* **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.
## Payins
### `payin.create`
::: code-group
```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`
::: code-group
```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`
::: code-group
```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:
::: code-group
```bash [CURL]
curl -X POST '{baseUrl}/payins' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
:::
Here is an example of `{payload}`:
::: code-group
```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.
::: code-group
```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
## 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: /use-cases/prerequisites/creating-your-company.md
description: >-
Get some context regarding the necessity to create and verify your company
before starting your implementation. 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:
### No-code guide
Recommended for people who wish to get started with no development effort.
Once in possession of your credentials to access your Dashboard, you’re good to go!
[Start your no-code implementation →](/use-cases/prerequisites/create-your-company-nc)
### API guide (coming soon)
Recommended for people with experience working with APIs.
Once you’ve got your credentials, you’re good to set up your favorite development and testing tools (e.g., set up our Postman Collection).
**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 refers to the single wallet attached to a company through which all the funds transit.
You may also find the term [*Titres Spéciaux de Paiements*](/guide/wallets/introduction#titres-speciaux-de-paiement-type-15).
---
---
url: /guide/transfers/beneficiaries.md
description: >-
Technical guide for creating and managing beneciaries, 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 and SEPA Credit Transfers), and are necessarily attached to a User.
**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 transfers fund in and out, both parties must be in 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 before 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 identical Beneficiary, it can either be duplicated or [associated to a parent user](/guide/users/parent-children).
## Beneficiary object
::: code-group
```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).
### Example
To create a Beneficiary, use the following request:
::: code-group
```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}`:
::: code-group
```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.
::: code-group
```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.
## Endpoints
| 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` |
---
---
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 processes of Card creation, delivery, and activation.
**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, you can't know which one was used for a given transaction.
## Process
### Mandatory creation steps
* **Create** a [Physical](#physical-card-creation) or [Virtual Card](#virtual-card-creation) associated to a Wallet.
* **Register 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 creation of the card, avoiding 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 at the company's address by setting `sendToParent` value to `true`. If so, the envelope bears the children's complete name and the parent 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-udpate) with `EXPIRED` status – Indicates the card expired.
## 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 in the form of 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 or not. |
| `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. |
**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"}
::: code-group
<<< @/guide/cards/snippets/create-card-virtual.bash \[CURL]
:::
Here is an example of `{payload}`:
::: code-group
```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)).
::: code-group
```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
}
]
}
```
:::
Endpoint: [`/cards`](/api-reference/pci-dss-dev.html#tag/Cards/createCard){target="\_self"}
::: code-group
<<< @/guide/cards/snippets/create-card-pci.bash \[CURL]
:::
Here is an example of `{payload}`:
::: code-group
```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)).
::: code-group
```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
}
]
}
```
:::
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"}
::: code-group
```bash [CURL]
curl -X GET '{baseUrl}/v1/cardimages?cardId={cardId}' \
--header 'Authorization: Bearer {accessToken}'
```
:::
It returns the Card Image object if successful:
::: code-group
```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"}
::: code-group
```bash [CURL]
curl -X GET '{pciBaseUrl}/cards/{cardId}/cardImage' \
--header 'Authorization: Bearer {accessToken}'
```
:::
It returns the Card Image object if successful:
::: code-group
```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 in 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.
::: code-group
```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`.
::: code-group
```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
}
]
}
```
:::
## 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 station, etc. depending on [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 or not. |
| `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 defined 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 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 defined to `1`. |
**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"}
::: code-group
```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}`:
::: code-group
```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).
::: code-group
```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"}
::: code-group
<<< @/guide/cards/snippets/create-card-pci.bash \[CURL]
:::
Here is an example of `{payload}`:
::: code-group
```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).
::: code-group
```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.
**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 or not. |
| `walletTypeId` | integer | The [type of Wallets](/guide/wallets/introduction#types-of-wallets) the cards will be associated to. |
| `createWalletForEach` | boolean | Defines whether to create one Wallet per card. |
| `cardDeliveryAddress1` | string | The first line of the delivery address for physical cards. |
| `cardDeliveryPostCode` | string | The postal code of the delivery address. |
| `cardDeliveryCity` | string | The city of the delivery address. |
| `cardDeliveryCountry` | string | The [country](/guide/api-basics/data-format#countries) of the delivery address. |
| `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. |
::: code-group
```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}`.
::: code-group
```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:
::: code-group
```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 Creation are asynchronous, you therefore 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
::: code-group
```bash [CURL]
curl -X GET '{baseUrl}/core-connect/card/bulk' \
--header 'accept: application/json' \
--header 'authorization: Bearer {accessToken}'
```
:::
Returns the following.
::: code-group
```json [JSON]
[
// this represents a Bulk Creation that completed 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
},
// this represents a Bulk Creation that succeeded without any 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
},
// this represents a Bulk Creation that is still pending
{
"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.
::: code-group
```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`.
::: code-group
```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.
::: code-group
```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
## 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 in the `logoId` parameter. This logo is overlaid to your usual Card Design.
The constraints are as follows:
* **Format**: `.jpeg`, `.pcx` or `.png` (other formats need to be checked for compatibility)
* **Definition**: 600 PPI
* **Maximum size**: depends on your Card Design
* **String**: Can't exceed 30 characters
* **Transparent background** is recommended. In any case, white content will not be printed.
### Back Logo (`logoBackId`)
You can add a customized logo on the backside of the Card by setting its filename in the `logoBackId` parameter. This logo is overlaid to your usual Card Design.
The constraints are as follows:
* **Format**: `.jpeg`, `.pcx` or `.png` (any other format will have to be checked for compatibility)
* **Definition**: 600 PPI
* **Maximum size**: depends on your Card Design
* **String**: Can't exceed 30 characters
* **Transparent background** is recommended. In any case, white content will not be 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** | All the cards must have the same `batchDeliveryId` value (must be between `1` and `238327`). |
| **Address** | All the cards must have the same delivery address. Please keep in mind that the delivery parameters of the card 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 – Batch orders are generated daily**
Treezor usually sends the batch orders to the manufacturer in the afternoon. If cards with the same `batchDeliveryId` are created before and after the cut-off time, they are likely to 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.
### 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 choosen font and on the position of the text on the Card.
### 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 choosen 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.
::: code-group
```bash [CURL]
curl -X POST '{baseUrl}/v1/documents' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}
```
:::
Here is a `{payload}` example:
::: code-group
```json [JSON]
{
"fileContentBase64": "{base64file}",
"userId":123456,
"documentTypeId":9,
"name":"aoak_identity_card.pdf"
}
```
:::
Returns the Document object.
::: code-group
```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.
::: code-group
```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:
::: code-group
```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.
::: code-group
```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.
::: code-group
```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).
::: code-group
```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.
::: code-group
```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.
::: code-group
```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/user-verification/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 |
### 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) |
| `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
::: code-group
```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).
**Information – Specific case of self-employed persons**
Freelancers and self-employed persons (known as *auto-entrepreneur* in France) should be created as [Physical Users](/guide/users/physical) with a `legalForm` set to `1000`.
## 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](/guide/user-verification/tax-residence#the-specific-case-of-us-taxpayers). |
| `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 the [list of legal forms](#legal-forms-legalform). |
| `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. |
### Request example
Endpoint: [`/v1/users`](/api-reference/api-endpoints.html#tag/Users/postUsers){target="\_self"}
::: code-group
<<< @/guide/users/snippets/create\_user.bash \[CURL]
:::
Here is an example of `{payload}`:
::: code-group
```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:
::: code-group
```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
}
]
}
```
:::
Endpoint: [`/users`](/api-reference/pci-dss-dev.html#tag/Users/postUsers){target="\_self"}
::: code-group
<<< @/guide/users/snippets/create\_user\_pci.bash \[CURL]
:::
Here is an example of `{payload}`:
::: code-group
```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:
::: code-group
```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
}
]
}
```
:::
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`:
::: code-group
```bash [CURL]
curl -X GET '{baseUrl}/v1/businesssearchs?country={country}&vatNumber={vatNumber}' \
--header 'Authorization: Bearer {accessToken}'
```
:::
Or alternatively, using the `registrationNumber`:
::: code-group
```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/)).
::: code-group
```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 business legal representatives and majority shareholders (assuming they hold more than 25% worth of shares).
### 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`:
::: code-group
```bash [CURL]
curl -X GET {baseUrl}/v1/businessinformations?country={country}&vatNumber={vatNumber} \
--header 'Authorization: Bearer {accessToken}'
```
:::
Or alternatively, using the `registrationNumber`:
::: code-group
```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.
::: code-group
```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 Business User.
**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 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"}
::: code-group
<<< @/guide/users/snippets/create\_user.bash \[CURL]
:::
Here is an example of `{payload}`:
::: code-group
```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:
::: code-group
```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
}
]
}
```
:::
Endpoint: [`/users`](/api-reference/pci-dss-dev.html#tag/Users/postUsers){target="\_self"}
::: code-group
<<< @/guide/users/snippets/create\_user\_pci.bash \[CURL]
:::
Here is an example of `{payload}`:
::: code-group
```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:
::: code-group
```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
}
]
}
```
:::
Treezor also sends a [`user.create`](./events#user-create) webhook.
## Know Your Customer (KYC)
The legal representatives and majority shareholders of the business must have [Physical Users](/guide/users/physical) created and [associated](/guide/users/parent-children) to the Legal Entity. The Legal Entity can then undergo [KYC review](/guide/user-verification/introduction), **this will trigger the review of all its children** (representatives and shareholders) at the same time.
**Information – The mandatory requirements regarding KYC review of businesses are constantly evolving**
For the most up-to-date information, we recommend that you check the documents Treezor provided you with.
### Types (`userTypeId`)
Below the `userTypeId` values for legal entities.
| Value | Description |
| :---: | --- |
| `2` | Business user |
| `3` | Non-governmental organization |
| `4` | Governmental organization |
**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).
### 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` (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](#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).
---
---
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
::: code-group
```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. |
| `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"}
::: code-group
```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}`:
::: code-group
```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`.
::: code-group
```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 a human individual, identified by a first name, last name, date of birth, address, etc. They have a `userTypeId` of `1`.
## 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/user-verification/tax-residence#the-specific-case-of-us-taxpayers). |
| `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 misses (Mrs.)`MLLE` – Stands for miss`MX` – Gender-neutral title |
| `firstname` (required for KYC) | string | The user's first name. |
| `lastname` (required for KYC) | string | The user's last name. |
| `birthday` (required for KYC) | string | The user's birthdate. 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](#personal-assets-range-personalassets) 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. |
#### 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"}
::: code-group
<<< @/guide/users/snippets/create\_user.bash \[CURL]
:::
Here is an example of `{payload}`:
::: code-group
```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.
::: code-group
```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
}
]
}
```
:::
Endpoint: [`/users`](/api-reference/pci-dss-dev.html#tag/Users/postUsers){target="\_self"}
::: code-group
<<< @/guide/users/snippets/create\_user\_pci.bash \[CURL]
:::
Here is an example of `{payload}`:
::: code-group
```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.
::: code-group
```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
}
]
}
```
:::
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/user-verification/tax-residence#the-specific-case-of-us-taxpayers). |
| `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"}
::: code-group
<<< @/guide/users/snippets/create\_user.bash \[CURL]
:::
Here is an example of `{payload}`:
::: code-group
```json [JSON]
{
"userTypeId": 1,
"specifiedUSPerson": 0,
"email": "anonymous@example.com"
}
```
:::
Returns a User object if successful:
::: code-group
```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"}
::: code-group
<<< @/guide/users/snippets/create\_user\_pci.bash \[CURL]
:::
Here is an example of `{payload}`:
::: code-group
```json [JSON]
{
"userTypeId": 1,
"specifiedUSPerson": 0,
"email": "anonymous@example.com"
}
```
:::
Returns a User object if successful:
::: code-group
```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/user-verification/tax-residence#the-specific-case-of-us-taxpayers). |
| `legalForm` | integer | **Must be `1000`** for self-employed users. |
| `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. |
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/user-verification/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
::: code-group
```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.
::: code-group
<<< @/guide/transfers/snippets/create\_scheduled\_payment.bash \[CURL]
:::
Here is an example of `{payload}`:
::: code-group
```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:
::: code-group
```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.
::: code-group
<<< @/guide/transfers/snippets/create\_scheduled\_payment.bash \[CURL]
:::
Here is an example of `{payload}`:
::: code-group
```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:
::: code-group
```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)).
::: code-group
```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.
::: code-group
```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:
::: code-group
```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`.
::: code-group
```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/user-verification/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 taxpayers](#the-specific-case-of-us-taxpayers) and users whose `distributionCountry` is `IT`).
* The waiver exempting Treezor from liability in case of a missing TIN.
### The specific case of US taxpayers
Every US taxpayer must declare the United States as a tax residence along with the Tax Identification Number (TIN).
This applies to all users as soon as one of the following elements value is `US`:
* **Nationality** – Corresponds to the `nationality` or the `nationalityOther` field for the physical users
* **Birth country** – Corresponds to the `birthCountry` field for physical users
* **Address** – Corresponds to the `country` or `secondaryCountry` field for both physical users and legal entities
In addition, when at least one of these values is `US`, the user `specificiedUSPerson` attribute must be set to `1`.
::: details Is considered a US citizen or resident…
A physical user is presumed to be a citizen of the United States:
* From the moment they have an American passport or
* If they are born on the territory of the United States, even when such a place of birth appears on a passport of another country, or the person also holds another nationality or has their residence in another country.
A physical user is a resident of the United States if:
* They are holding a green card for permanent residence in the United States.
* They are residing permanently in the United States or have spent a sufficient period of time in the United States over the last three years.
:::
## 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](#the-specific-case-of-us-taxpayers) and users whose `distributionCountry` is `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"}
::: code-group
```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}`:
::: code-group
```json [JSON]
{
"userId":100642533,
"country":"FR",
"taxPayerId":"12345",
"liabilityWaiver":false
}
```
:::
Returns the Tax Residence object:
::: code-group
```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.
::: code-group
```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.
::: code-group
```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
::: code-group
```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 fund movements between Treezor Wallets
from the same environment. Includes required parameters, request structure,
and response examples.
---
# Wallet-to-Wallet Transfers
You can transfer funds from Wallet to Wallet, without using the [SEPA network](/guide/overview/glossary#sepa-single-euro-payments-aera), offering much quicker transfers.
Transfers are instantaneous, 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 your 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/overview/glossary#balance) 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"}
::: code-group
```bash [CURL]
curl -X POST '{baseUrl}/v1/transfers' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
:::
Here is a `{payload}` example:
::: code-group
```json [JSON]
{
"walletId":{integer},
"beneficiaryWalletId":{integer},
"transferTypeId":1,
"amount":{amount},
"currency":"EUR"
}
```
:::
Returns the Transfer object if successful:
::: code-group
```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.
Regardless the type of Wallet created, the [`wallet.create`](/guide/wallets/events#wallet-create) webhook is sent upon creation.
**Prerequisites – Ensure the User is fit to have a Wallet**
Users must have a `VALIDATED` status, and Legal Entities must have a legal representative 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 |
|--- |--- |--- |
| `tariffId` | integer | The fees applied to the Wallet, as defined by your contract with Treezor. Usually required, but may have a default value set by Treezor. |
| `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"}
::: code-group
<<< @/guide/wallets/snippets/create\_wallet.bash \[CURL]
:::
Here is an example of `{payload}`:
::: code-group
```json [JSON]
{
"walletTypeId":10,
"tariffId":{tariffId},
"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.
::: code-group
```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 |
|--- |--- |--- |
| `tariffId` | integer | The fees applied to the Wallet, as defined by your contract with Treezor. Usually required, but may have a default value set by Treezor. |
| `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"}
::: code-group
<<< @/guide/wallets/snippets/create\_wallet.bash \[CURL]
:::
Here is an example of `{payload}`:
::: code-group
```json [JSON]
{
"walletTypeId":9,
"tariffId":{tariffId},
"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.
::: code-group
```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: /use-cases/prerequisites/create-your-company-nc.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.
---
# Create and verify your company (no-code)
The no-code guide will take you through the following steps to successfully create and verify your company:
1. [Get to know your Dashboard](#get-to-know-your-dashboard) – Learn how to log into the Dashboard and discover the interface.
2. [Create your company and its members](#select-the-business-user-creation-path) – Create the legal entity, its legal representative and shareholders.
3. [Review KYC Documents](#review-the-kyc-documents) – Make sure the proper documents have been uploaded in accordance with your KYC Form.
4. [Submit your company's KYB](#submit-your-company-s-kyb-to-treezor) – Send the documents to Treezor for verification.
5. [Create your Master Wallet](#create-your-master-wallet) – Create the company's Wallet.
6. [Abide by additional vigilance measures](#abide-by-additional-vigilance-measures) – Make a SEPA Credit Transfer to your Wallet in production if indicated by your KYC Form.
## 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.
You may then enter your email and password or use the SSO feature to log in, depending on the available options.
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 displayed screenshots, depending on:
* Where you’re at in your integration process, if you’re customizing the design
* The [Role](/guide/dashboard/dashboard-users#dashboard-user-roles) of the logged-in user, if you’re not using all of Treezor’s features
### Accessing your users
Once your users created, you may access the detailed information by:
* Taking advantage of the main *Search toolbar*
* Navigating the *All Users* view
Upon selecting a user, the corresponding details will be displayed in the *Profile Boards* view.
#### Search toolbar
The Dashboard main toolbar provides a series of user attributes-based search fields.
You may take advantage of the search fields available in the main toolbar to find a specific user based on its:
* **User Id** – Corresponds to the `userId` automatically generated by Treezor when creating a user.
* **User Tag** – Corresponds to 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.
Once one of the fields is populated, click on the "Search" button to launch the search.
#### All Users view
The *All Users* view provides a table listing all your users with some key information. Upon clicking on a user, it opens the corresponding profile in the *Profiles Board* 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 "Create a new User" in the Navigation menu.
→ 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:
::: details The company is found
→ Click on the "Prefill data" button.
→ Thoroughly check and edit the prefilled information if need be.
:::
::: details Several companies are found
→ 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.
:::
::: details The company is not found
→ 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 *Profile Boards* 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 *Profile Boards* 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 *Profile Boards* 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 *Profiles Board* 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 *Profile Boards* 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 *Creeate 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)** | |
::: details Sequence diagram
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. |
| `requestBy` | string | The User `id` that must sign the operation. This value is either: **Mandatory** if your `{accessToken}` was obtained with `grant_type` = `client_credentials`**Optional** if your `{accessToken}` was obtained with `grant_type` = `delegated_end_user` as the User `id` is already 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).
::: code-group
```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}`:
::: code-group
```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": "postPayouts",
"actionDescription": "Creates a payout",
"requestBy": "",
}
```
:::
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).
::: code-group
```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}`:
::: code-group
```json [JSON]
{
"dataToSign": {
"iat": {currentTimestampInMillisecond},
},
"actionName": "postPayouts",
"actionDescription": "Creates a payout",
"requestBy": "",
}
```
:::
Returns an object containing the UUIDv4 (`scaOperationRequestId`) of the operation, allowing you to [check on its evolution](#checking-for-signature) later on.
::: code-group
```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
::: code-group
```bash [CURL]
curl -X GET '{baseUrl}/core-connect/sca/scaOperations/{scaOperationRequestId}' \
--header 'Authorization: Bearer {accessToken}'
```
:::
Returns the following.
::: code-group
```json [JSON]
{
"scaOperationRequestId": "",
"dataToSign": {},
"actionName": "postPayouts",
"actionDescription": "Creates a payout",
"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`
::: code-group
```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.
::: code-group
```json [JSON]
[
{
"scaOperationRequestId": "",
"dataToSign": {},
"actionName": "",
"actionDescription": "",
"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": "",
}
]
```
:::
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.
::: code-group
```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.
::: code-group
```json{7,8,10} [JSON]
{
"scaOperationRequestId": "",
"dataToSign": {},
"actionName": "postPayouts",
"actionDescription": "Creates a payout",
"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 “Add a new user” button available in the upper right corner.
In the prompted dialog box, you need to fill in the following fields:
* Username (or email), which must be unique
* Role (as described in the table below)
* Password
* 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
::: tabs
\== Dashboard views
| Dashboard views | RO | BE | UM | BM | TM | AR | M | A |
|--- |:---: |:---: |:---: |:---: |:---: | :---: | :---: | :---: |
| Search Users | | | | | | | | |
| Profiles Board | | | | | | | | |
| All Users | | | | | | | | |
| Create a new User | | | | | | | | |
| All Cards | | | | | | | | |
| All Card Transactions | | | | | | | | |
| Bulk Cards | | | | | | | | |
\== Administration views
| Administration views | RO | BE | UM | BM | TM | AR | M | A |
|--- |:---: |:---: |:---: |:---: |:---: | :---: | :---: | :---: |
| Dashboard Users | | | | | | | | |
| Predef Restriction Groups | | | | | | | | |
| Templating management | | | | | | | | |
| Webhooks | | | | | | | | |
:::
### Possible actions per user role
::: tabs
\== Overview
| 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 | | | | | | | | |
\== KYC / KYB
| 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 | | | | | | | | |
\== Children / Company members
| Action | RO | BE | UM | BM | TM | AR | M | A |
|--- |:---: |:---: |:---: |:---: |:---: | :---: | :---: | :---: |
| Add Child User | | | | | | | | |
\== Wallets
| 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 | | | | | | | | |
\== Cards
| Action | RO | BE | UM | BM | TM | AR | M | A |
|--- |:---: |:---: |:---: |:---: |:---: | :---: | :---: | :---: |
| Create card | | | | | | | | |
| Activate card | | | | | | | | |
| Block card | | | | | | | | |
| Update card settings | | | | | | | | |
\== Beneficiaries
| Action | RO | BE | UM | BM | TM | AR | M | A |
|--- |:---: |:---: |:---: |:---: |:---: | :---: | :---: | :---: |
| Create Beneficiary | | | | | | | | |
| Edit Beneficiary | | | | | | | | |
:::
## Manage a Dashboard User
| | Action | Description |
| :---: | --- | --- |
| | **Update** | Edit an existing Dashboard User (using the same dialog box as for the creation). |
| | **Delete** | Remove a Dashboard User. This action is irreversible. |
| | **More** | Provides access to the "Reset 2FA" command. The corresponding user will have to set up their [2FA](./introduction#standard-login-with-2fa) the next time they logged in. |
| | **Unblock** | Unblock a blocked Dashboard User. This action is only available for Dashboard Users who failed to log in 3 times in a row. |
---
---
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).
::: details Examples
* `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 **otherwise**.
Some exceptions such as the card transaction `authorizationIssuerTime` can apply a different timezone. When in doubt, please refer to the [API Reference](/api-reference/api-endpoints).
### Examples
::: code-group
```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 timezones 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.
::: details Examples
* 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
::: code-group
```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
::: code-group
```json [JSON]
{
"userId":18742 // No quotes (legacy ID)
}
```
:::
### Textual example
::: code-group
```json [JSON]
{
"client_id":"" // with quotes
}
```
:::
### UUIDv4 example
::: code-group
```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 |
**Important – Mail carrier limitations**
The table above provides a rough estimate for mail carrier maximum amount of printed characters, as those limitations may change depending on the selected font for instance.
---
---
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.
::: code-group
```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).
::: code-group
```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.
::: code-group
```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.
::: code-group
```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).
::: code-group
```bash [CURL]
base64 -d "eyJpc3MiOiJ0cmVlem9yX2Nvbm5lY3QiLCJpYXQiOjE2MzM1MTMyMjEsImV4cCI6MTYzMzUxNjgyMSwic3ViIjoiNzkwMzdlNmUtYzFlMS00MmYyLWJlOWEtZTI0OWM3NjdjNDc2Iiwic2NvcGUiOlsiYWRtaW4iLCJrZXlzIiwibGVnYWwiLCJyZWFkX29ubHkiLCJyZWFkX3dyaXRlIiwicmVhZF9hbGwiXSwidXNlcklkIjpudWxsLCJjYXJkcyI6W10sIndhbGxldHMiOltdLCJjaGlsZHJlbiI6W10sInVzZXJUeXBlIjoiYXBwbGljYXRpb24iLCJjbGllbnRJZCI6IjkyOTI1MiJ9"
```
:::
Returns the decoded payload.
::: code-group
```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:
::: code-group
```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: /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.
::: details Mobile SCA Wallet example
::: code-group
```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
}
```
:::
::: details Web Native SCA Wallet example
::: code-group
```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.
::: code-group
```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.
::: code-group
```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. This request doesn't return SCA Wallets whose status is `DELETED`.
::: code-group
```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.
::: code-group
```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
::: code-group
<<< @/guide/strong-customer-authentication/snippets/create\_scaWallet.bash \[CURL]
:::
Here is an example of `{payload}`:
::: code-group
```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.
::: code-group
```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
::: tabs
\== Mobile SDK
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.
::: code-group
```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):
::: code-group
```json [JSON]
{
"removeScaWalletId":"5710a5536cf04712b922f04exx9da5e2",
"swapReason": "OTHER",
"sca":"{scaProof}",
"scaWalletTag":"Pixel 6"
}
```
:::
Returns the newly created SCA Wallet object when successful.
::: code-group
```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.
::: code-group
```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):
::: code-group
```json [JSON]
{
"swapReason":"LOST",
"removeScaWalletId":"5710a5536cf04712b922f04exx9da5e2",
"authMethod":["OTP SMS", "ID"],
"scaWalletTag":"iPhone 13"
}
```
:::
Returns the SCA Wallet object when successful.
::: code-group
```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.
### New User enrollment
The device enrollment process pairs the User with their WebAuthn secured passkeys and passcode. 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
3. Forwarding of the public key and encrypted passcode to Treezor to finalize the device enrollment
The following snippet triggers the passkeys creation process using Web Authentication API on the User's device.
::: code-group
```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: '',
},
// 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).
::: code-group
```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.
::: code-group
<<< @/guide/users/snippets/create\_user.bash \[CURL]
:::
Here is an example of `{payload}`:
::: code-group
```json [JSON] {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 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.
::: code-group
```bash [CURL]
curl -X POST '{baseUrl}/core-connect/sca/scawallets' \
--header 'Authorization: Bearer {accessToken}' \
--header 'Content-Type: application/json' \
-d '{payload}'
```
:::
Here is an example of `{payload}`.
::: code-group
```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.
::: code-group
<<< @/guide/strong-customer-authentication/snippets/create\_scaWallet.bash \[CURL]
:::
Treezor expects the following `{payload}`:
::: code-group
```json [JSON]
{
"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.
::: code-group
```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.
::: code-group
```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 one from one environment to the next)
* **Features** (features available in one environment may not be present in the next)
* [**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` when encountering `{baseUrl}` in code examples, replace it with this URL.
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/overview/glossary#balance) 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.
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 3 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. |
| **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
::: code-group
```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}'
```
:::
Returns the JSON version of the document.
::: code-group
```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",
"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",
"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",
"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"
}
```
:::
## Retrieve PDFs
### 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
::: code-group
```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}'
```
:::
Returns an object containing a URL to download the PDF.
::: code-group
```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.
::: code-group
```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 %}