Create Token
Create a new token for the Tenant.
POST
https://api.basistheory.com/tokens
Permissions
token:create
Request
- cURL
- Node
- JavaScript (legacy)
- C#
- Java
- Python
- Go
curl "https://api.basistheory.com/tokens" \
-H "BT-API-KEY: <API_KEY>" \
-H "Content-Type: application/json" \
-X "POST" \
-d '{
"type": "token",
"data": "Sensitive Value",
"mask": "{{ data | reveal_last: 4 }}",
"containers": [ "/general/high/" ],
"metadata": {
"nonSensitiveField": "Non-Sensitive Value"
},
"search_indexes": [
"{{ data }}",
"{{ data | last4 }}"
],
"fingerprint_expression": "{{ data }}",
"deduplicate_token": true,
"expires_at": "8/26/2030 7:23:57 PM -07:00"
}'
await client.tokens.create({
type: "token",
data: "Sensitive Value",
mask: "{{ data | reveal_last: 4 }}",
containers: ["/general/high/"],
metadata: {
nonSensitiveField: "Non-Sensitive Value",
},
searchIndexes: ["{{ data }}", "{{ data | last4 }}"],
fingerprintExpression: "{{ data }}",
deduplicateToken: true,
expiresAt: "8/26/2030 7:23:57 PM -07:00",
}
);
import { BasisTheory } from "@basis-theory/basis-theory-js";
const bt = await new BasisTheory().init("<API_KEY>");
const token = await bt.tokens.create({
type: "token",
data: "Sensitive Value",
mask: "{{ data | reveal_last: 4 }}",
containers: ["/general/high/"],
metadata: {
nonSensitiveField: "Non-Sensitive Value",
},
searchIndexes: ["{{ data }}", "{{ data | last4 }}"],
fingerprintExpression: "{{ data }}",
deduplicateToken: true,
expiresAt: "8/26/2030 7:23:57 PM -07:00",
});
await client.Tokens.CreateAsync(new CreateTokenRequest
{
Type = "token",
Data = "Sensitive Value",
Mask = "{{ data | reveal_last: 4 }}",
Containers = ["/general/high/"],
Metadata = new Dictionary<string, string?>
{
{ "nonSensitiveField", "Non-Sensitive Value" }
},
SearchIndexes = ["{{ data }}", "{{ data | last4 }}"],
FingerprintExpression = "{{ data }}",
DeduplicateToken = true,
ExpiresAt = "8/26/2030 7:23:57 PM -07:00",
});
Token token = new TokensClient(ClientOptions.builder().build())
.create(Token.builder()
.type("token")
.data("Sensitive Value")
.mask("{{ data | reveal_last: 4 }}")
.containers(Arrays.asList("/general/high/"))
.metadata(new HashMap<String, String>() {{
put("nonSensitiveField", "Non-Sensitive Value");
}})
.searchIndexes(Arrays.asList("{{ data }}", "{{ data | last4 }}"))
.fingerprintExpression("{{ data }}")
.deduplicateToken(true)
.build());
client.tokens.create(
type="token",
data="Sensitive Value",
mask="{{ data | reveal_last: 4 }}",
metadata={
"nonSensitiveField": "Non-Sensitive Value"
},
containers=["/general/high/"],
search_indexes=[
"{{ data }}",
"{{ data | last4 }}"
],
fingerprint_expression="{{ data }}"
)
token, err := client.Tokens.Create(ctx, &basistheory.CreateTokenRequest{
Type: "token",
Data: "Sensitive Value",
Mask: "{{ data | reveal_last: 4 }}",
Containers: []string{"/general/high/"},
Metadata: map[string]string{
"nonSensitiveField": "Non-Sensitive Value",
},
SearchIndexes: []string{
"{{ data }}",
"{{ data | last4 }}",
},
FingerprintExpression: "{{ data }}",
DeduplicateToken: true,
ExpiresAt: "8/26/2030 7:23:57 PM -07:00",
})
Request Parameters
| Attribute | Required | Type | Default | Description |
|---|
id | false | string | null | A value or expression specifying the token's ID. If not specified, a UUID will be assigned. |
type | false | string | null | Token type of the token. |
data | false | any | null | Token data. Can be an object, array, or any primitive type such as an integer, boolean, or string |
token_intent_id | false | string | null | The ID of a Token Intent to Convert to a Token |
mask | false | any | Depends on the token type | Token data mask. Can be an object, array, or any primitive type such as an integer, boolean, or string. See mask expressions. |
containers | false | array | Depends on the token type | Array of containers to place this token within. Each container is a path representing a logical grouping of tokens. See Token Containers for details. |
metadata | false | map<string, string> | null | A key-value map of strings containing non-sensitive data. |
search_indexes | false | array | null | Array of expressions used to generate indexes to be able to search against. |
fingerprint_expression | false | string | {{ data | stringify }} | Expressions used to fingerprint your token. |
deduplicate_token | false | bool | null | Whether the token is deduplicated on creation. |
expires_at | false | string | null | ISO8601 compatible Token expiration DateTime. See Token Expiration for more details. |
encrypted | false | string | null | An encrypted payload that contains the token data. See Encrypted Token Creation for more details. |
Either type and data are required to create a new token from the given data, or token_intent_id is required to convert an existing token intent to a token.
Never reveal sensitive information in the
id of your token. See the documentation on
Aliasing to learn more about best practices when specifying your own token ID.
Never store sensitive plaintext information in the metadata of your token.
Response
Returns a token if the token was created. Returns an error if there were validation errors, or the token failed to create.
{
"id": "c06d0789-0a38-40be-b7cc-c28a718f76f1",
"tenant_id": "77cb0024-123e-41a8-8ff8-a3d5a0fa8a08",
"type": "token",
"data": "XXXXXXXXXXXalue",
"mask": "{{ data | reveal_last: 4 }}",
"containers": ["/general/high/"],
"metadata": {
"nonSensitiveField": "Non-Sensitive Value"
},
"search_indexes": ["{{ data }}", "{{ data | last4 }}"],
"fingerprint": "AKCUXS83DokKo4pDRKSAy4d42t9i8dcP1X2jijwEBCQH",
"fingerprint_expression": "{{ data }}",
"created_by": "fb124bba-f90d-45f0-9a59-5edca27b3b4a",
"created_at": "2020-09-15T15:53:00+00:00",
"expires_at": "2030-08-26T19:23:57-07:00",
"_extras": {
"deduplicated": false
}
}
For security reasons, the
data and
metadata attributes are redacted from the response when a token is deduplicated, unless the API Key has
token:read permission in the targeted container.
Click here to learn more about this behavior.
List Tokens v2
Most tokens are listable within seconds after creation, although it may take up to a few minutes.
Get a list of tokens for the Tenant sorted by container and created_at, descending. If you need to perform a search on token data, see Search Tokens.
GET
https://api.basistheory.com/v2/tokens
Permissions
token:read
Request
- cURL
- Node
- JavaScript (legacy)
- C#
- Java
- Python
- Go
curl "https://api.basistheory.com/v2/tokens" \
-H "BT-API-KEY: <PRIVATE_API_KEY>"
const response = await client.tokens.listV2();
for await (const item of response) {
console.log(item);
}
const page = await client.tokens.listV2();
while (page.hasNextPage()) {
page = page.getNextPage();
}
import { BasisTheory } from "@basis-theory/basis-theory-js";
const bt = await new BasisTheory().init("<PRIVATE_API_KEY>");
const tokens = await bt.tokensV2.list();
await client.Tokens.ListAsyncV2(new TokensListRequest());
Page<Token> page = new TokensClient(ClientOptions.builder().build())
.listV2();
response = client.tokens.list_v2()
for item in response:
yield item
for page in response.iter_pages():
yield page
tokens, err := client.Tokens.ListV2(ctx, &basistheory.TokensListRequest{})
Query Parameters
| Parameter | Required | Type | Description |
|---|
container | false | string | Filters the results to only include tokens within the given container, or its child containers. |
type | false | string | Filters the results to only include tokens of the given type. |
fingerprint | false | string | Filters the results to only include tokens with the given fingerprint. |
metadata.[key] | false | string | Filters the results to only include tokens with the given metadata key and value, expressed as ?metadata.key=value |
- Each query parameter can appear at most once within a single request.
- The
container query parameter can be combined with other supported parameters.
- This can be used to limit the scope of the search to a single container and its child containers.
- If
container is specified, the application must have token:read permission to the given container.
- If
container is not specified, the response will include tokens from all containers the application has token:read permission to.
- Except for
container, multiple query parameters cannot be combined within the same request.
- Metadata will be searched for a case-sensitive, exact match on both key and value.
Response
Returns a cursor paginated object with the data property containing an array of tokens sorted by container and created_at, descending.
Token data will be returned according to the transform
applied within the requesting Application's Access Controls.
Returns an error if tokens could not be retrieved.
{
"pagination": {...},
"data": [
{
"id": "c06d0789-0a38-40be-b7cc-c28a718f76f1",
"type": "token",
"tenant_id": "77cb0024-123e-41a8-8ff8-a3d5a0fa8a08",
"data": "secret data",
"containers": ["/general/high/"],
"metadata": {
"nonSensitiveField": "Non-Sensitive Value"
},
"created_by": "fb124bba-f90d-45f0-9a59-5edca27b3b4a",
"created_at": "2021-03-01T08:23:14+00:00"
},
{...},
{...}
]
}
Get a Token
Get a token by ID in the Tenant.
GET
https://api.basistheory.com/tokens/{id}
Permissions
token:read
Request
- cURL
- Node
- JavaScript (legacy)
- C#
- Java
- Python
- Go
curl "https://api.basistheory.com/tokens/c06d0789-0a38-40be-b7cc-c28a718f76f1" \
-H "BT-API-KEY: <PRIVATE_API_KEY>"
await client.tokens.get("id");
import { BasisTheory } from "@basis-theory/basis-theory-js";
const bt = await new BasisTheory().init("<PRIVATE_API_KEY>");
const token = await bt.tokens.retrieve("c06d0789-0a38-40be-b7cc-c28a718f76f1");
await client.Tokens.GetAsync("id");
Token token = new TokensClient(ClientOptions.builder().build())
.get("id");
client.tokens.get(
id="id",
)
token, err := client.Tokens.Get(ctx, "id")
URI Parameters
| Parameter | Required | Type | Default | Description |
|---|
id | true | string | null | The ID of the token |
Response
Returns a token with the id provided.
Token data will be returned according to the transform
applied within the requesting Application's Access Controls.
Returns an error if the token could not be retrieved.
{
"id": "c06d0789-0a38-40be-b7cc-c28a718f76f1",
"type": "token",
"tenant_id": "77cb0024-123e-41a8-8ff8-a3d5a0fa8a08",
"data": "secret data",
"containers": ["/general/high/"],
"metadata": {
"nonSensitiveField": "Non-Sensitive Value"
},
"created_by": "fb124bba-f90d-45f0-9a59-5edca27b3b4a",
"created_at": "2021-03-01T08:23:14+00:00"
}
Update Token
Update an existing token for the Tenant.
PATCH
https://api.basistheory.com/tokens/{id}
Permissions
token:update
The Update Tokens endpoint uses a different content-type to support merge-patch operations. Requests need the
Content-Type header to be set to
application/merge-patch+json. Requests made with a different
Content-Type header value will receive a
415 Unsupported Media Type response code. For more information on merge-patch, see
RFC 7386.
Request
- cURL
- Node
- JavaScript (legacy)
- C#
- Java
- Python
- Go
curl "https://api.basistheory.com/tokens/c06d0789-0a38-40be-b7cc-c28a718f76f1" \
-H "BT-API-KEY: <PRIVATE_API_KEY>" \
-H "Content-Type: application/merge-patch+json" \
-X "PATCH" \
-d '{
"data": "Sensitive Value",
"mask": "{{ data | reveal_last: 4 }}",
"metadata": {
"nonSensitiveField": "Non-Sensitive Value"
},
"search_indexes": [
"{{ data }}",
"{{ data | last4 }}"
],
"fingerprint_expression": "{{ data }}",
"deduplicate_token": true,
}'
await client.tokens.update(token.id!, {
data: "Sensitive Value",
mask: "{{ data | reveal_last: 4 }}",
metadata: {
nonSensitiveField: "Non-Sensitive Value",
},
searchIndexes: ["{{ data }}", "{{ data | last4 }}"],
fingerprintExpression: "{{ data }}",
deduplicateToken: true,
});
import { BasisTheory } from "@basis-theory/basis-theory-js";
const bt = await new BasisTheory().init("<API_KEY>");
const token = await bt.tokens.update("c06d0789-0a38-40be-b7cc-c28a718f76f1", {
data: "Sensitive Value",
mask: "{{ data | reveal_last: 4 }}",
metadata: {
nonSensitiveField: "Non-Sensitive Value",
},
searchIndexes: ["{{ data }}", "{{ data | last4 }}"],
fingerprintExpression: "{{ data }}",
deduplicateToken: true,
});
await client.Tokens.UpdateAsync(
token.Id,
new UpdateTokenRequest
{
Data = "Sensitive Value",
Mask = "{{ data | reveal_last: 4 }}",
Containers = ["/general/high/"],
Metadata = new Dictionary<string, string?>
{
{ "nonSensitiveField", "Non-Sensitive Value" }
},
SearchIndexes = ["{{ data }}", "{{ data | last4 }}"],
FingerprintExpression = "{{ data }}",
DeduplicateToken = true,
}
);
Token updatedToken = new TokensClient(ClientOptions.builder().build())
.update("id", Token.builder()
.data("Sensitive Value")
.mask("{{ data | reveal_last: 4 }}")
.containers(Arrays.asList("/general/high/"))
.metadata(new HashMap<String, String>() {{
put("nonSensitiveField", "Non-Sensitive Value");
}})
.searchIndexes(Arrays.asList("{{ data }}", "{{ data | last4 }}"))
.fingerprintExpression("{{ data }}")
.deduplicateToken(true)
.build());
client.tokens.update(
id="id",
type="token",
data="Sensitive Value",
mask="{{ data | reveal_last: 4 }}",
metadata={
"nonSensitiveField": "Non-Sensitive Value"
},
containers=["/general/high/"],
search_indexes=[
"{{ data }}",
"{{ data | last4 }}"
],
fingerprint_expression="{{ data }}"
)
token, err := client.Tokens.Update(ctx, "id", &basistheory.UpdateTokenRequest{
Data: "Sensitive Value",
Mask: "{{ data | reveal_last: 4 }}",
Metadata: map[string]string{
"nonSensitiveField": "Non-Sensitive Value",
},
SearchIndexes: []string{
"{{ data }}",
"{{ data | last4 }}",
},
FingerprintExpression: "{{ data }}"
})
Request Parameters
| Attribute | Required | Type | Behavior | Description |
|---|
data | false | any | Merge Patch (see RFC 7386) | Token data. Can be an object, array, or any primitive type such as an integer, boolean, or string |
mask | false | any | Merge Patch (see RFC 7386) | Token data mask. Can be an object, array, or any primitive type such as an integer, boolean, or string. See mask expressions. |
metadata | false | map<string, string> | Merge Patch (see RFC 7386) | A key-value map of strings containing non-sensitive data. |
containers | false | array | Replace | Array of containers to place this token within. Each container is a path representing a logical grouping of tokens. See Token Containers for details. |
search_indexes | false | array | Replace | Array of expressions used to generate indexes to be able to search against. |
fingerprint_expression | false | string | Replace | Expressions used to fingerprint your token. |
deduplicate_token | false | bool | Replace | Whether the token is deduplicated on creation. |
expires_at | false | string | Replace | ISO8601 compatible Token expiration DateTime. See Token Expiration for more details. |
Response
Returns the updated token if successful. Returns an error if there were validation errors, or the token failed to create.
{
"id": "c06d0789-0a38-40be-b7cc-c28a718f76f1",
"tenant_id": "77cb0024-123e-41a8-8ff8-a3d5a0fa8a08",
"type": "token",
"data": "XXXXXXXXXXXalue",
"mask": "{{ data | reveal_last: 4 }}",
"containers": ["/general/high/"],
"metadata": {
"nonSensitiveField": "Non-Sensitive Value"
},
"search_indexes": ["{{ data }}", "{{ data | last4 }}"],
"fingerprint": "AKCUXS83DokKo4pDRKSAy4d42t9i8dcP1X2jijwEBCQH",
"fingerprint_expression": "{{ data }}",
"created_by": "fb124bba-f90d-45f0-9a59-5edca27b3b4a",
"created_at": "2020-09-15T15:53:00+00:00"
}
If the updated token results in a duplicate of an existing token and the application does not have the original token's read permission, the data,metadata, fingerprint_expression, search_indexes and mask attributes will be redacted.
Delete Token
Delete a token by ID in the Tenant.
DELETE
https://api.basistheory.com/tokens/{id}
Permissions
token:delete
The data associated with a deleted token will be removed forever.
Request
- cURL
- Node
- JavaScript (legacy)
- C#
- Java
- Python
- Go
curl "https://api.basistheory.com/tokens/c06d0789-0a38-40be-b7cc-c28a718f76f1" \
-H "BT-API-KEY: <PRIVATE_API_KEY>" \
-X "DELETE"
await client.tokens.delete("id");
import { BasisTheory } from "@basis-theory/basis-theory-js";
const bt = await new BasisTheory().init("<PRIVATE_API_KEY>");
await bt.tokens.delete("c06d0789-0a38-40be-b7cc-c28a718f76f1");
await client.Tokens.DeleteAsync("id");
new TokensClient(ClientOptions.builder().build())
.delete("id");
client.tokens.delete(
id="id",
)
err := client.Tokens.Delete(ctx, "id")
URI Parameters
| Parameter | Required | Type | Default | Description |
|---|
id | true | string | null | The ID of the token |
Response
Returns an error if the token failed to delete.
Token Object
| Attribute | Type | Description |
|---|
id | string | Unique identifier of the token which can be used to get a token |
tenant_id | uuid | The Tenant ID which owns the token |
type | string | Token type |
data | any | Token data |
mask | any | An expression defining the mask to apply when retrieving token data with restricted permissions. |
enrichments | object | Available when tokenizing, detokenizing and with expressions.
An object containing the enrichments applied to this token. See Token Enrichments for available enrichements. |
card | object | Only available when token type is card or card_number
An object containing the card data. See Card Details for more information. |
bank | object | The Bank Details when type is bank, otherwise null. |
network_token | object | Only available when token type is network_token
An object containing the card data. See Card Details for more information. |
fingerprint | string | Uniquely identifies the contents of this token. See Token Types for the default expression for each token type. |
containers | array | Array of containers to place this token within. Each container is a path representing a logical grouping of tokens. See Token Containers for details. |
metadata | map<string, string> | A key-value map of strings containing non-sensitive data. |
search_indexes | array | (Optional) Array of search index expressions used when creating the token. |
fingerprint_expression | string | (Optional) An expression defining the value to fingerprint when creating the token. |
expires_at | string | (Optional) The token expiration date. |
created_by | uuid | The Application ID which created the token |
created_at | date | Created date of the token in ISO 8601 format |
modified_by | uuid | (Optional) The Application ID which last modified the token |
modified_at | date | (Optional) Last modified date of the token in ISO 8601 format |
_extras | object | (Response-Only) An object containing information regarding the tokenization process |
| Attribute | Type | Description |
|---|
deduplicated | boolean | Indicates if the token was deduplicated during tokenization |
deduplication_behavior | string | Indicates the behavior of the deduplication process, either read_existing or update_existing. See Deduplication Behavior for more information. |
network_token_ids | array | A list of network token IDs that were created based on the current token |
Card Details
| Attribute | Type | Nullable | Description |
|---|
bin | string | No | Six to eight digit BIN of the card |
last4 | string | No | Last four digits of the card |
expiration_month | number | No | The 2-digit expiration month of the card |
expiration_year | number | No | The 4-digit expiration year of the card |
brand | string | Yes | The primary card brand |
funding | string | Yes | The primary funding type of the card |
segment | string | Yes | The segmentation of the card (eg., Consumer, Commercial) |
issuer | object | Yes | Describes the country and issuing bank. See Issuer for details |
issuer_country | object | Yes | Describes the issuing country. See Issuer Country for details |
authentication | string | Yes | The authentication type required for this card |
additional | array | Yes | Contains additional details associated to the same BIN number. See Card Additional below for details. |
Card properties shows the primary card details, while Card.additional provides additional card details found for the same BIN.
If a card number does not correspond to any
supported card brand or known
BIN Details, then
brand,
funding,
segment,
issuer,
issuer_country, and
authentication will default to
null and the
default BIN will be returned.
Card Additional
| Attribute | Type | Description |
|---|
brand | string | An additional card brand |
funding | string | An additional funding type of the card |
authentication | string | An additional authentication type required for this card |
issuer | object | Describes the country and issuing bank. See Issuer for details |
Authentication Types
| Authentication Type | Description |
|---|
sca_required | Indicates that Strong Customer Authentication (SCA) is required (e.g. 3DS) |
Card Brands
The following card brands are supported in the card property (primary details). Please note that the additional property may contain extra card brands not listed in this table.
| Brand | Description |
|---|
american-express | American Express |
diners-club | Diners Club |
discover | Discover |
ebt | EBT |
elo | Elo |
hipercard | Hipercard |
jcb | JCB |
mastercard | Mastercard |
mir | MIR |
private-label | Private Label |
proprietary | Proprietary |
unionpay | UnionPay |
visa | Visa |
Card Funding Types
| Funding Type | Description |
|---|
credit | Credit Card |
debit | Debit Card |
prepaid | Prepaid Card |
Issuer
| Attribute | Type | Description |
|---|
country | string | Issuing country ISO3166 alpha country code |
name | string | Issuing bank name |
Issuer Country
| Attribute | Type | Description |
|---|
alpha2 | string | Issuing country ISO3166 alpha country code |
numeric | string | Issuing country ISO3166 numeric country code |
name | string | Issuing country name |
Bank Details
| Attribute | Type | Description |
|---|
routing_number | string | The routing number of the bank account |
account_number_last4 | string | Last four digits of the bank account number |
Token Data Validations
Bank Object
| Attribute | Required | Type | Default | Description |
|---|
routing_number | true | string | null | Nine-digit ABA routing number. Its checksum is validated. |
account_number | true | string | null | Account number up to seventeen-digits |
Card Object
| Attribute | Required | Type | Default | Description |
|---|
number | true | string | null | The card number without any separators |
expiration_month | false | integer | null | Number representing the card's expiration month |
expiration_year | false | integer | null | Four-digit number representing the card's expiration year |
cvc | false | string | null | Three or four-digit card verification code with automatic expiration |
See Test Card Numbers for suggested test data when using cards.
The cvc property automatically expires and is deleted based on your CVC Retention Quota, with a default of one hour in order to comply with PCI requirements.
If you have a business case that requires retaining
cvc for longer than the default "CVC Retention"
Quota of one hour, it may be possible to extend the expiration time while maintaining PCI compliance. Please request a change to the
CVC Retention Quota in the Quota Page for your Tenant.
Token Expiration
By default a created token will not expire, however, users can optionally set the expires_at property with an ISO8601 timestamp to specify its expiration.
An expired token will no longer be accessible immediately after expiration, and the token will be asynchronously deleted from the tenant.
Tokens are typically deleted within a few minutes, but may be delayed up to 48 hours, at which time a token.expired event will be emitted.
| Format | Example |
|---|
| ISO8601 in UTC | 2030-04-23T13:24:28Z |
| ISO8601 with offset | 2030-04-23T17:24:28-04:00 |