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

# Mint Identity

> Create a new ZKScore identity with a unique ZKS ID

## Overview

Mint a new identity NFT (SBT) with a unique ZKS ID. This creates a non-transferable identity token that can be activated to become soulbound. Once minted, the identity can be used across the ZKScore ecosystem.

<Note>
  Identity names must be unique across the platform. Use the [Check Availability](/api-reference/identity/check-availability) endpoint to verify name availability before minting.
</Note>

## Request Body

<ParamField body="name" type="string" required>
  The desired ZKS ID name (without .zks suffix). Must be 3-32 characters, lowercase letters, numbers, and hyphens only. Cannot start or end with a hyphen.
</ParamField>

<ParamField body="walletAddress" type="string" required>
  The Ethereum wallet address that will own this identity. Must be a valid address format.
</ParamField>

<ParamField body="metadata" type="object">
  Optional metadata for the identity

  <Expandable title="properties">
    <ParamField body="avatar" type="string">
      URL to avatar image
    </ParamField>

    <ParamField body="bio" type="string">
      Short biography (max 500 characters)
    </ParamField>

    <ParamField body="socialLinks" type="object">
      Social media links (twitter, github, discord, etc.)
    </ParamField>
  </Expandable>
</ParamField>

## Response

<ResponseField name="success" type="boolean">
  Indicates if the minting was successful
</ResponseField>

<ResponseField name="identity" type="object">
  <Expandable title="properties">
    <ResponseField name="tokenId" type="number">
      The NFT token ID of the minted identity
    </ResponseField>

    <ResponseField name="name" type="string">
      The ZKS ID name (without .zks suffix)
    </ResponseField>

    <ResponseField name="ownerAddress" type="string">
      The wallet address that owns this identity
    </ResponseField>

    <ResponseField name="isActivated" type="boolean">
      Whether the identity is activated (always false after minting)
    </ResponseField>

    <ResponseField name="createdAt" type="string">
      ISO 8601 timestamp of when the identity was minted
    </ResponseField>

    <ResponseField name="transactionHash" type="string">
      The blockchain transaction hash
    </ResponseField>
  </Expandable>
</ResponseField>

## Examples

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.onzks.com/v1/identity/mint \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "alice",
      "walletAddress": "0x742d35Cc6635C0532925a3b844D1FF4e1321",
      "metadata": {
        "avatar": "https://example.com/avatar.png",
        "bio": "DeFi enthusiast and protocol researcher"
      }
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api.onzks.com/v1/identity/mint', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      name: 'alice',
      walletAddress: '0x742d35Cc6635C0532925a3b844D1FF4e1321',
      metadata: {
        avatar: 'https://example.com/avatar.png',
        bio: 'DeFi enthusiast and protocol researcher'
      }
    })
  });

  const data = await response.json();
  console.log('Identity minted:', data.identity);
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      'https://api.onzks.com/v1/identity/mint',
      headers={
          'Authorization': 'Bearer YOUR_API_KEY',
          'Content-Type': 'application/json'
      },
      json={
          'name': 'alice',
          'walletAddress': '0x742d35Cc6635C0532925a3b844D1FF4e1321',
          'metadata': {
              'avatar': 'https://example.com/avatar.png',
              'bio': 'DeFi enthusiast and protocol researcher'
          }
      }
  )

  data = response.json()
  print(f"Identity minted: {data['identity']}")
  ```
</CodeGroup>

## Response Example

```json theme={null}
{
  "success": true,
  "identity": {
    "tokenId": 12345,
    "name": "alice",
    "ownerAddress": "0x742d35cc6635c0532925a3b844d1ff4e1321",
    "isActivated": false,
    "createdAt": "2024-01-15T10:30:00Z",
    "transactionHash": "0xabc123..."
  }
}
```

## Error Responses

<ResponseExample>
  ```json 400 Bad Request - Invalid Name theme={null}
  {
    "success": false,
    "error": "INVALID_NAME_FORMAT",
    "message": "Name must be 3-32 characters, lowercase letters, numbers, and hyphens only"
  }
  ```

  ```json 409 Conflict - Name Taken theme={null}
  {
    "success": false,
    "error": "NAME_ALREADY_TAKEN",
    "message": "The name 'alice' is already taken",
    "suggestions": ["alice1", "alice-zk", "alice2024"]
  }
  ```

  ```json 400 Bad Request - Invalid Address theme={null}
  {
    "success": false,
    "error": "INVALID_WALLET_ADDRESS",
    "message": "Invalid Ethereum address format"
  }
  ```

  ```json 429 Too Many Requests theme={null}
  {
    "success": false,
    "error": "RATE_LIMIT_EXCEEDED",
    "message": "Too many mint requests. Please try again later."
  }
  ```
</ResponseExample>

## Name Validation Rules

### Valid Names

✅ **Accepted formats:**

* `alice` - Simple name
* `defi-master` - With hyphen
* `user123` - With numbers
* `my-identity-2024` - Multiple hyphens and numbers

### Invalid Names

❌ **Rejected formats:**

* `al` - Too short (minimum 3 characters)
* `-alice` - Starts with hyphen
* `alice-` - Ends with hyphen
* `Alice` - Contains uppercase
* `alice.eth` - Contains period
* `alice@zks` - Contains special characters
* `this-name-is-way-too-long-to-be-valid` - Too long (maximum 32 characters)

## Use Cases

### 1. User Onboarding

Create an identity during user registration:

```javascript theme={null}
async function onboardUser(walletAddress, desiredName) {
  try {
    // Check availability first
    const available = await checkAvailability(desiredName);
    
    if (!available) {
      throw new Error('Name not available');
    }

    // Mint identity
    const identity = await mintIdentity({
      name: desiredName,
      walletAddress: walletAddress
    });

    console.log(`Identity created: ${identity.name}.zks`);
    return identity;
  } catch (error) {
    console.error('Onboarding failed:', error);
    throw error;
  }
}
```

### 2. Batch Identity Creation

Create multiple identities for a team or organization:

```javascript theme={null}
async function createTeamIdentities(teamMembers) {
  const identities = [];
  
  for (const member of teamMembers) {
    const identity = await mintIdentity({
      name: member.username,
      walletAddress: member.address,
      metadata: {
        bio: member.role,
        socialLinks: member.socials
      }
    });
    
    identities.push(identity);
    
    // Rate limiting: wait 1 second between requests
    await new Promise(resolve => setTimeout(resolve, 1000));
  }
  
  return identities;
}
```

### 3. Identity with Custom Metadata

Create an identity with rich metadata:

```javascript theme={null}
const identity = await mintIdentity({
  name: 'defi-trader',
  walletAddress: '0x742d35Cc6635C0532925a3b844D1FF4e1321',
  metadata: {
    avatar: 'https://cdn.example.com/avatars/trader.png',
    bio: 'Professional DeFi trader specializing in yield farming',
    socialLinks: {
      twitter: 'https://twitter.com/defitrader',
      github: 'https://github.com/defitrader',
      discord: 'defitrader#1234'
    }
  }
});
```

## Best Practices

### 1. Check Availability First

Always check name availability before attempting to mint:

```javascript theme={null}
const available = await checkAvailability('alice');
if (available) {
  await mintIdentity({ name: 'alice', walletAddress: address });
}
```

### 2. Handle Errors Gracefully

Provide helpful feedback when minting fails:

```javascript theme={null}
try {
  const identity = await mintIdentity({ name, walletAddress });
} catch (error) {
  if (error.code === 'NAME_ALREADY_TAKEN') {
    // Show suggestions to user
    console.log('Try these names:', error.suggestions);
  } else if (error.code === 'INVALID_NAME_FORMAT') {
    // Show validation rules
    console.log('Name must be 3-32 characters, lowercase only');
  }
}
```

### 3. Store Transaction Hash

Save the transaction hash for verification:

```javascript theme={null}
const identity = await mintIdentity({ name, walletAddress });
await database.save({
  userId: user.id,
  tokenId: identity.tokenId,
  transactionHash: identity.transactionHash,
  createdAt: identity.createdAt
});
```

### 4. Activate After Minting

Remember to activate the identity to make it soulbound:

```javascript theme={null}
// Step 1: Mint
const identity = await mintIdentity({ name, walletAddress });

// Step 2: Activate (makes it soulbound)
await activateIdentity({ tokenId: identity.tokenId });
```

## Next Steps

After minting an identity:

1. **[Activate Identity](/api-reference/identity/activate-identity)** - Make the identity soulbound
2. **[Get Identity](/api-reference/identity/get-identity)** - Retrieve identity information
3. **[Get Score](/api-reference/scores/get-score)** - Check the user's ZKScore

## Related Endpoints

* [Activate Identity](/api-reference/identity/activate-identity) - Activate a minted identity
* [Check Availability](/api-reference/identity/check-availability) - Check if a name is available
* [Get Identity](/api-reference/identity/get-identity) - Retrieve identity information

## Troubleshooting

### "Name already taken"

**Cause**: The requested name is already registered by another user.

**Solution**:

* Use the suggestions provided in the error response
* Try a different name with numbers or hyphens
* Check availability before minting

### "Invalid name format"

**Cause**: The name doesn't meet validation requirements.

**Solution**:

* Ensure name is 3-32 characters
* Use only lowercase letters, numbers, and hyphens
* Don't start or end with a hyphen

### "Transaction failed"

**Cause**: Blockchain transaction failed or was reverted.

**Solution**:

* Check wallet has sufficient gas
* Verify wallet address is correct
* Try again after a few minutes
* Contact support if issue persists

## Rate Limits

Identity minting is subject to rate limits:

* **Free tier**: 10 mints per hour
* **Starter tier**: 100 mints per hour
* **Professional tier**: 1,000 mints per hour
* **Enterprise tier**: Custom limits

Exceeded rate limits will return a `429 Too Many Requests` error.
