# Enroll Card

### Endpoint

```
POST /v1/tokens/enroll
```

{% hint style="info" %}
**Important**: This endpoint requires a previously created Firstoken permanent token. The token must contain valid card information before enrollment.
{% endhint %}

### Environments

**Production:**

```
https://api.firstoken.co/v1/tokens/enroll
```

**Sandbox (Testing):**

```
https://api.firstoken-staging.co/v1/tokens/enroll
```

### Authentication

All requests require the `x-api-key` header with your API key:

```
x-api-key: <YOUR_API_KEY>
```

#### Creating an API Key

To use the Network Token Enrollment API, you need to create an API key in the Firstoken Console:

1. **Access the Console**: Log into your Firstoken Console
2. **Navigate to Keys**: Go to the Keys module in the left sidebar
3. **Create New Key**: Click "Create Access Key"
4. **Configure Key**:
   * Enter a name for your key (e.g., "Network Token API Key")
   * Add an optional description
   * **Important**: Select the "Payment Request" permission under the Request section
5. **IP Whitelist**: Add your server's IP addresses to the whitelist for security
6. **Create Key**: Click "Create Access Key" to generate your key

#### Service Activation

After creating your API key with Payment Request permissions, contact our team to activate the Network Token service for your API key. The service activation is required before you can start using the enrollment endpoint.

{% hint style="warning" %}
**Note**: Make sure your API key has the correct permissions and your IP addresses are whitelisted before requesting service activation.
{% endhint %}

#### **Webhook Configuration (Recommended)**

After enrollment, provisioning happens asynchronously in the background. To receive real-time notifications when provisioning is complete and when token status changes occur, configure a webhook endpoint:

1. **Access Integrations**: Navigate to Integrations > Webhooks in the Firstoken Console
2. **Create Webhook**: Click "Create Webhook"
3. **Configure Webhook**:
   * **URL Destination**: Enter your webhook endpoint URL where you'll receive notifications
   * **Permissions**: Select "Network Token Events" to receive network token lifecycle notifications
4. **Save Configuration**: Click "Save" to activate the webhook

Your webhook endpoint will receive notifications for:

* Token provisioning completion (`status: "ACTIVE"`)
* Token updates via lifecycle management (`status: "ACTIVE"`)
* Token suspension (`status: "SUSPENDED"`)
* Token deletion (`status: "DELETED"`)

If you don't configure a webhook, you can poll the Get Payment Credentials endpoint to check if provisioning is complete, though this is less efficient than using webhooks.

### Request Parameters

<table><thead><tr><th width="213.984375">Parameter</th><th width="118.9375">Type</th><th width="112.73828125">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>transaction_info.type</code></td><td>string</td><td>Yes</td><td>Must be <code>"enroll_card"</code></td></tr><tr><td><code>card.number</code></td><td>string</td><td>Yes</td><td>Firstoken token reference (use detokenize syntax)</td></tr><tr><td><code>card.expiration_date</code></td><td>string</td><td>Yes</td><td>Card expiration date (use detokenize syntax)</td></tr><tr><td><code>card.security_code</code></td><td>string</td><td>No</td><td>Card security code (can use temporal detokenize syntax)</td></tr><tr><td><code>bill_to.address_1</code></td><td>string</td><td>Yes</td><td>Primary billing address</td></tr><tr><td><code>bill_to.address_2</code></td><td>string</td><td>No</td><td>Secondary billing address</td></tr><tr><td><code>bill_to.city</code></td><td>string</td><td>Yes</td><td>Billing city</td></tr><tr><td><code>bill_to.state</code></td><td>string</td><td>Yes</td><td>Billing state/province</td></tr><tr><td><code>bill_to.postal_code</code></td><td>string</td><td>Yes</td><td>Billing postal code</td></tr><tr><td><code>bill_to.country</code></td><td>string</td><td>Yes</td><td>Billing country code (ISO 3166-1 alpha-2)</td></tr></tbody></table>

### Request Example

```bash
curl --location 'https://api.firstoken-staging.co/v1/tokens/enroll' \
--header 'Content-Type: application/json' \
--header 'x-api-key: <YOUR_API_KEY>' \
--data '{
  "transaction_info": {
    "type": "enroll_card"
  },
  "card": {
    "number": "{{ TOKEN_ID: detokenize }}",
    "expiration_date": "{{ TOKEN_ID: detokenize }}",
    "security_code": {{ TEMPORAL_TOKEN_ID: transaction}}"
  },
  "bill_to": {
    "address_1": "Carrera 140",
    "address_2": "Carrera 140",
    "city": "Bogotá DC",
    "state": "Bogotá",
    "postal_code": "110001",
    "country": "CO"
  }
}'
```

### Response Parameters

<table><thead><tr><th width="340.20703125">Parameter</th><th width="106.10546875">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>status</code></td><td>string</td><td>Response status (<code>"success"</code> or <code>"fail"</code>)</td></tr><tr><td><code>message</code></td><td>string</td><td>Human-readable response message</td></tr><tr><td><code>data.transaction_info.type</code></td><td>string</td><td>Response type (<code>"enroll_card_response"</code>)</td></tr><tr><td><code>data.transaction_info.reference_code</code></td><td>string</td><td>Unique reference code for the enrollment request</td></tr><tr><td><code>data.transaction_info.request_id</code></td><td>string</td><td>Internal request identifier</td></tr><tr><td><code>data.transaction_info.status</code></td><td>string</td><td>Enrollment status (see status values below)</td></tr><tr><td><code>data.transaction_info.created_at</code></td><td>string</td><td>ISO 8601 timestamp of the request</td></tr><tr><td><code>data.error_info.reason</code></td><td>string</td><td>Error reason code (only present in error responses)</td></tr><tr><td><code>data.error_info.message</code></td><td>string</td><td>Error message (only present in error responses)</td></tr></tbody></table>

#### Enrollment Status Values

<table><thead><tr><th width="227.44140625">Status</th><th>Description</th></tr></thead><tbody><tr><td><code>Enrolled</code></td><td>Card successfully enrolled in network tokenization</td></tr><tr><td><code>Not_enrolled</code></td><td>Card enrollment failed (see error_info for details)</td></tr><tr><td><code>Already_enrolled</code></td><td>Card was previously enrolled</td></tr></tbody></table>

### Response Examples

#### Success Response (200 OK)

```json
{
  "status": "success",
  "message": "Network token successfully stored",
  "data": {
    "transaction_info": {
      "type": "enroll_card_response",
      "reference_code": "bfe68a02-51cd-4d66-b2ad-56fc55527e45",
      "request_id": "0001770745387125160590",
      "status": "Enrolled",
      "created_at": "2026-02-10T17:43:07.407Z"
    }
  }
}
```

#### Already Enrolled Response (409 Conflict)

```json
{
  "status": "success",
  "message": "Network token already exists",
  "data": {
    "transaction_info": {
      "type": "enroll_card_response",
      "reference_code": "126e084f-5537-4d6c-8e6c-b6877b431b25",
      "request_id": "0001770744802919290552",
      "status": "Already_enrolled",
      "created_at": "2026-02-10T17:33:23.660Z"
    }
  }
}
```

#### Network Token Unavailable (409 Conflict)

```json
{
  "status": "success",
  "message": "Network token is unavailable",
  "data": {
    "transaction_info": {
      "type": "enroll_card_response",
      "reference_code": "fd43e006-e6ad-48d8-beea-11bcda414af2",
      "request_id": "0001770745085323008850",
      "status": "Not_enrolled",
      "created_at": "2026-02-10T17:38:05.913Z"
    },
    "error_info": {
      "reason": "Unprovisioned",
      "message": "INVALID_REQUEST"
    }
  }
}
```

#### Workflow Not Implemented (409 Conflict)

```json
{
  "status": "success",
  "message": "Workflow not implemented",
  "data": {
    "transaction_info": {
      "type": "enroll_card_response",
      "reference_code": "fd43e006-e6ad-48d8-beea-11bcda414af2",
      "request_id": "0001770745085323008850",
      "status": "Not_enrolled",
      "created_at": "2026-02-10T17:38:05.913Z"
    },
    "error_info": {
      "reason": "Unprovisioned",
      "message": "INVALID_REQUEST"
    }
  }
}
```

#### Bad Request (400)

```json
{
  "status": "fail",
  "message": "Invalid request",
  "data": {
    "description": "Some fields are missing in the request",
    "path": "card.number"
  }
}
```

#### Internal Server Error (500)

```json
{
  "status": "fail",
  "message": "Internal server error",
  "data": {
    "description": "An unexpected error occurred while processing the request"
  }
}
```

### Error Handling

| Status Code | Description                                                  | Action Required                                        |
| ----------- | ------------------------------------------------------------ | ------------------------------------------------------ |
| 200         | Enrollment successful                                        | Network token is provisioned and ready to use          |
| 400         | Invalid request                                              | Check request parameters and try again                 |
| 409         | Conflict (already enrolled, unavailable, or not implemented) | Check the specific message and error\_info for details |
| 500         | Internal server error                                        | Contact support if the issue persists                  |
