> ## Documentation Index
> Fetch the complete documentation index at: https://developer.utgl.io/llms.txt
> Use this file to discover all available pages before exploring further.

# External ID and Metadata

> Use external identifiers and metadata to enhance resource management and integration workflows

The Issuing API supports two optional fields for enhancing resource management: `xid` (external identifier) and `xmetadata` (external metadata). These fields allow you to attach your own identifiers and structured data to resources, simplifying integration and eliminating the need for complex ID mapping between your platform and UTGL.

***

## Overview

Both `xid` and `xmetadata` are optional fields that can be attached to resources during creation or updates. They are included in all API responses and webhook events, making them ideal for:

* **Resource Mapping** - Map UTGL resources to your internal systems
* **Context Storage** - Store additional structured information about resources
* **Search and Query** - Use `xid` to search for resources
* **Integration Tracking** - Track resources across systems without maintaining separate mapping tables

***

## External Identifier (xid)

The `xid` field allows you to attach your own unique identifier to resources created through the Issuing API.

### Characteristics

* **Type:** String
* **Max Length:** 256 characters
* **Uniqueness:** Must be unique across all resources created under your account
* **Visibility:** Visible in the UTGL platform user interface
* **Included In:** All API responses and webhook events

### Use Cases

* **Internal System Mapping** - Map UTGL resource IDs to your internal database IDs
* **Cross-Platform References** - Reference resources using your own identifiers
* **Search and Filtering** - Query resources by your external identifiers
* **Audit Trails** - Track resources using your own reference system

### Example Usage

**Creating a resource with xid:**

```json theme={null}
{
  "name": "My Account",
  "currency": "USD",
  "xid": "account-12345-internal-ref"
}
```

**Response includes xid:**

```json theme={null}
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "xid": "account-12345-internal-ref",
  "name": "My Account",
  "currency": "USD"
}
```

**Webhook event includes xid:**

```json theme={null}
{
  "event": "account.created",
  "id": "evt_abc123",
  "time": "2025-01-15T10:30:00Z",
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "xid": "account-12345-internal-ref",
    "name": "My Account"
  }
}
```

### Best Practices

* **Use Consistent Format** - Establish a consistent naming convention for your `xid` values
* **Include Context** - Use prefixes or patterns that indicate resource type (e.g., `account-`, `card-`, `transfer-`)
* **Avoid Sensitive Data** - Don't include sensitive information in `xid` values
* **Keep It Readable** - Use human-readable identifiers for easier debugging and support

***

## External Metadata (xmetadata)

The `xmetadata` field allows you to attach structured key-value pairs to resources for storing additional context and information.

### Characteristics

* **Type:** Object with string key-value pairs
* **Max Keys:** 25 key-value pairs per resource
* **Key Constraints:**
  * Max length: 40 characters
  * Must be strings
* **Value Constraints:**
  * Max length: 1024 characters per value
  * Must be strings or arrays of strings
* **Nested Objects:** Not supported
* **Visibility:** Visible in the UTGL platform user interface

### Schema Definition

```json theme={null}
{
  "xmetadata": {
    "key1": "value1",
    "key2": ["value2.1", "value2.2"],
    "key3": "value3"
  }
}
```

Each value can be either:

* A string (up to 1024 characters)
* An array of strings (each string up to 1024 characters)

### Use Cases

* **Routing Information** - Store SMS or OTP routing preferences for cards
* **Business Context** - Attach department, project, or cost center information
* **Integration Data** - Store references to related resources in your system
* **Custom Attributes** - Add domain-specific metadata for your use case
* **Workflow State** - Track processing status or workflow stages

### Example Usage

**Creating a card with metadata:**

```json theme={null}
{
  "cardAccountId": "acc_1234567890",
  "cardholder": {
    "firstName": "John",
    "lastName": "Doe"
  },
  "xmetadata": {
    "sms_routing": "twilio",
    "department": "sales",
    "cost_center": "CC-2024-Q1",
    "tags": ["premium", "vip"]
  }
}
```

**Response includes merged metadata:**

If both parent and child resources have metadata, they are merged:

```json theme={null}
{
  "id": "card_abc123",
  "cardAccountId": "acc_1234567890",
  "xmetadata": {
    "account_department": "finance",
    "card_sms_routing": "twilio",
    "card_department": "sales",
    "cost_center": "CC-2024-Q1"
  }
}
```

**Querying with metadata:**

Metadata is included in all resource responses, allowing you to filter and process resources based on metadata values:

```json theme={null}
{
  "id": "card_abc123",
  "xid": "card-internal-456",
  "xmetadata": {
    "department": "sales",
    "region": "us-east"
  }
}
```

### Metadata Merging

When a parent resource (e.g., card account) and child resource (e.g., card) both contain metadata, the metadata is merged in responses:

**Parent Resource (Card Account):**

```json theme={null}
{
  "id": "acc_123",
  "xmetadata": {
    "account_type": "premium",
    "department": "finance"
  }
}
```

**Child Resource (Card):**

```json theme={null}
{
  "id": "card_456",
  "cardAccountId": "acc_123",
  "xmetadata": {
    "card_type": "virtual",
    "department": "sales"
  }
}
```

**Merged Response:**

```json theme={null}
{
  "id": "card_456",
  "cardAccountId": "acc_123",
  "xmetadata": {
    "account_type": "premium",
    "account_department": "finance",
    "card_type": "virtual",
    "card_department": "sales"
  }
}
```

<Note>
  **Metadata Merging:** When metadata keys conflict between parent and child resources, both values are preserved with prefixed keys to avoid overwriting.
</Note>

### Limitations

| Constraint                | Limit                    |
| ------------------------- | ------------------------ |
| Maximum keys              | 25 key-value pairs       |
| Key length                | 40 characters            |
| Value length (string)     | 1024 characters          |
| Value length (array item) | 1024 characters per item |
| Nested objects            | Not supported            |

### Best Practices

* **Use Descriptive Keys** - Choose clear, descriptive key names that indicate purpose
* **Keep Values Concise** - Stay within the 1024 character limit per value
* **Avoid Sensitive Data** - Never store sensitive information in metadata
* **Plan Key Names** - Establish a naming convention to avoid conflicts
* **Document Your Schema** - Document your metadata structure for your team

***

## Security Considerations

<Warning>
  **Never store sensitive information in `xid` or `xmetadata` fields.**

  Examples of what NOT to store:

  * Personal Identifiable Information (PII)
  * Bank account numbers
  * Card details (PAN, CVV, expiry)
  * Passwords or credentials
  * API keys or secrets
  * Social Security Numbers
  * Authentication tokens
</Warning>

These fields are:

* Visible in the UTGL platform user interface
* Included in all API responses
* Included in all webhook events
* Accessible to anyone with API access to your account

Use these fields only for non-sensitive operational data, routing information, and integration references.

***

## Code Examples

### JavaScript/TypeScript

```typescript theme={null}
// Create account with xid and metadata
const createAccount = async () => {
  const response = await fetch('https://access.utgl.io/v1/accounts', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${token}`
    },
    body: JSON.stringify({
      name: 'Business Account',
      currency: 'USD',
      xid: 'account-internal-ref-12345',
      xmetadata: {
        department: 'operations',
        cost_center: 'CC-2024-Q1',
        region: 'us-east'
      }
    })
  });
  
  const account = await response.json();
  console.log('Created account:', account.xid);
  console.log('Metadata:', account.xmetadata);
};
```

### Python

```python theme={null}
import requests

def create_account():
    url = 'https://access.utgl.io/v1/accounts'
    headers = {
        'Content-Type': 'application/json',
        'Authorization': f'Bearer {token}'
    }
    data = {
        'name': 'Business Account',
        'currency': 'USD',
        'xid': 'account-internal-ref-12345',
        'xmetadata': {
            'department': 'operations',
            'cost_center': 'CC-2024-Q1',
            'region': 'us-east'
        }
    }
    
    response = requests.post(url, json=data, headers=headers)
    account = response.json()
    print(f'Created account: {account["xid"]}')
    print(f'Metadata: {account["xmetadata"]}')
```

### Using xid for Resource Lookup

```javascript theme={null}
// Search for account by xid
const findAccountByXid = async (xid) => {
  const response = await fetch(
    `https://access.utgl.io/v1/accounts?xid=${encodeURIComponent(xid)}`,
    {
      headers: {
        'Authorization': `Bearer ${token}`
      }
    }
  );
  
  const accounts = await response.json();
  return accounts.data.find(acc => acc.xid === xid);
};
```

***

## Common Patterns

### Pattern 1: Internal Reference Mapping

Use `xid` to maintain a direct mapping between your internal IDs and UTGL resources:

```javascript theme={null}
// Store mapping: internal_id -> utgl_resource_id
const resourceMap = {
  'internal-account-123': '550e8400-e29b-41d4-a716-446655440000',
  'internal-card-456': '660e8400-e29b-41d4-a716-446655440001'
};

// Or use xid directly
const account = await createAccount({
  name: 'Account',
  xid: 'internal-account-123' // Use your internal ID
});
```

### Pattern 2: Routing Configuration

Store routing preferences in metadata:

```json theme={null}
{
  "xmetadata": {
    "sms_provider": "twilio",
    "sms_phone": "+1234567890",
    "email_provider": "sendgrid",
    "email_address": "user@example.com"
  }
}
```

### Pattern 3: Business Context

Attach business context to resources:

```json theme={null}
{
  "xmetadata": {
    "department": "sales",
    "region": "us-east",
    "cost_center": "CC-2024-Q1",
    "project_id": "project-abc-123"
  }
}
```

### Pattern 4: Integration References

Store references to related resources in your system:

```json theme={null}
{
  "xmetadata": {
    "user_id": "user-12345",
    "order_id": "order-67890",
    "subscription_id": "sub-abc-def"
  }
}
```

***

## API Endpoints Supporting xid and xmetadata

Most POST endpoints support `xid` and `xmetadata`:

* Account creation
* Card account creation
* Card issuance
* Transfer creation
* Payout creation
* Fee charging
* And more...

Check individual endpoint documentation in the [API Reference](/api-reference) for specific support.

***

## Troubleshooting

### Common Issues

**Issue: xid already exists**

* **Solution:** Ensure `xid` values are unique across all resources. Use a prefix or namespace to avoid conflicts.

**Issue: Metadata key too long**

* **Solution:** Keep key names under 40 characters. Use abbreviations if necessary.

**Issue: Metadata value too long**

* **Solution:** Split long values into multiple keys or use arrays for related values.

**Issue: Too many metadata keys**

* **Solution:** Consolidate related information into fewer keys. Maximum is 25 key-value pairs.

**Issue: Metadata not appearing in response**

* **Solution:** Verify metadata was included in the creation request. Check that you're reading the correct resource response.

***

## Next Steps

* Review [API Reference](/api-reference) for endpoint-specific `xid` and `xmetadata` support
* Learn about [Webhook Events](/issuing/guides/webhook-events-1) to see how metadata is included in events
* Explore [Resource Management](/issuing/getting-started/overview) for more integration patterns
