> ## 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.

# Claim Achievement

> Claim an earned achievement and receive rewards

## Overview

Claim an achievement that has been earned by a user. This endpoint verifies that the user has met all requirements, mints the achievement NFT (if applicable), and awards points and score bonuses.

<Tip>
  Use this endpoint to allow users to claim their earned achievements and receive their rewards. Always verify the user has earned the achievement before calling this endpoint.
</Tip>

## Parameters

<ParamField path="identity" type="string" required>
  User identity (ZKS ID or wallet address)

  <Note>
    ZKS ID is recommended for better performance and user experience
  </Note>
</ParamField>

<ParamField path="achievementId" type="string" required>
  Unique identifier of the achievement to claim
</ParamField>

## Request Body

<ParamField body="proof" type="object">
  Proof of achievement completion

  <Expandable title="proof properties">
    <ParamField body="proof.requirements" type="object">
      Evidence that requirements have been met
    </ParamField>

    <ParamField body="proof.timestamp" type="string">
      ISO 8601 timestamp of when requirements were met
    </ParamField>

    <ParamField body="proof.chainId" type="number">
      Blockchain where proof was generated
    </ParamField>

    <ParamField body="proof.transactionHash" type="string">
      Transaction hash that proves completion (if applicable)
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="signature" type="string">
  Cryptographic signature proving ownership of the identity
</ParamField>

<ParamField body="metadata" type="object">
  Additional metadata for the claim

  <Expandable title="metadata properties">
    <ParamField body="metadata.source" type="string">
      Source of the achievement (e.g., "defi\_protocol", "governance\_dao")
    </ParamField>

    <ParamField body="metadata.notes" type="string">
      User notes about the achievement
    </ParamField>

    <ParamField body="metadata.tags" type="array">
      User-defined tags
    </ParamField>
  </Expandable>
</ParamField>

## Response

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

<ResponseField name="message" type="string">
  Success message
</ResponseField>

<ResponseField name="address" type="string">
  Resolved wallet address
</ResponseField>

<ResponseField name="zksId" type="string">
  ZKS ID if available, null otherwise
</ResponseField>

<ResponseField name="achievement" type="object">
  Claimed achievement details

  <Expandable title="achievement properties">
    <ResponseField name="id" type="string">
      Achievement identifier
    </ResponseField>

    <ResponseField name="title" type="string">
      Achievement title
    </ResponseField>

    <ResponseField name="description" type="string">
      Achievement description
    </ResponseField>

    <ResponseField name="category" type="string">
      Achievement category
    </ResponseField>

    <ResponseField name="rarity" type="string">
      Rarity level
    </ResponseField>

    <ResponseField name="points" type="number">
      Points awarded
    </ResponseField>

    <ResponseField name="scoreBonus" type="number">
      ZKScore bonus
    </ResponseField>

    <ResponseField name="icon" type="string">
      URL to achievement icon
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="rewards" type="object">
  Rewards received from claiming

  <Expandable title="rewards properties">
    <ResponseField name="points" type="number">
      Points awarded
    </ResponseField>

    <ResponseField name="scoreBonus" type="number">
      ZKScore bonus
    </ResponseField>

    <ResponseField name="nftTokenId" type="string">
      NFT token ID if achievement is minted as NFT
    </ResponseField>

    <ResponseField name="nftContract" type="string">
      NFT contract address
    </ResponseField>

    <ResponseField name="nftMetadata" type="string">
      URL to NFT metadata
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="totalPoints" type="number">
  User's total points after claiming
</ResponseField>

<ResponseField name="totalScores" type="number">
  User's total ZKScore after claiming
</ResponseField>

<ResponseField name="claimed" type="boolean">
  Whether the achievement was successfully claimed
</ResponseField>

<ResponseField name="celebrate" type="boolean">
  Whether this is a special achievement worth celebrating
</ResponseField>

<ResponseField name="timestamp" type="string">
  ISO 8601 timestamp of the claim
</ResponseField>

## Examples

<CodeGroup>
  ```bash cURL (Basic Claim) theme={null}
  curl -X POST "https://api.onzks.com/v1/achievements/alice.zks/claim/defi-pioneer" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "proof": {
        "requirements": {
          "uniqueProtocols": 50,
          "minimumChains": 3,
          "minimumVolume": "100000"
        },
        "timestamp": "2024-01-20T15:45:00Z",
        "chainId": 1,
        "transactionHash": "0x1234567890abcdef..."
      },
      "signature": "0xabcdef1234567890...",
      "metadata": {
        "source": "defi_protocol",
        "notes": "Completed DeFi journey across multiple chains",
        "tags": ["defi", "pioneer", "multi-chain"]
      }
    }'
  ```

  ```bash cURL (Wallet Address) theme={null}
  curl -X POST "https://api.onzks.com/v1/achievements/0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb/claim/defi-pioneer" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "proof": {
        "requirements": {
          "uniqueProtocols": 50,
          "minimumChains": 3,
          "minimumVolume": "100000"
        },
        "timestamp": "2024-01-20T15:45:00Z",
        "chainId": 1
      },
      "signature": "0xabcdef1234567890..."
    }'
  ```

  ```javascript JavaScript theme={null}
  async function claimAchievement(identity, achievementId, proof, signature, metadata = {}) {
    const requestBody = {
      proof,
      signature,
      metadata
    };

    const response = await fetch(
      `https://api.onzks.com/v1/achievements/${identity}/claim/${achievementId}`,
      {
        method: 'POST',
        headers: {
          'Authorization': 'Bearer YOUR_API_KEY',
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(requestBody)
      }
    );

    const data = await response.json();

    if (data.success) {
      console.log(`🎉 Achievement claimed: ${data.achievement.title}`);
      console.log(`Points awarded: ${data.rewards.points}`);
      console.log(`Score bonus: ${data.rewards.scoreBonus}`);
      console.log(`Total points: ${data.totalPoints}`);
      
      if (data.rewards.nftTokenId) {
        console.log(`NFT minted: Token ID ${data.rewards.nftTokenId}`);
      }
      
      if (data.celebrate) {
        console.log('🎊 This is a special achievement! Congratulations!');
      }
    } else {
      console.error('Failed to claim achievement:', data.message);
    }

    return data;
  }

  // Usage example
  const proof = {
    requirements: {
      uniqueProtocols: 50,
      minimumChains: 3,
      minimumVolume: "100000"
    },
    timestamp: new Date().toISOString(),
    chainId: 1,
    transactionHash: "0x1234567890abcdef..."
  };

  const signature = "0xabcdef1234567890..."; // User's signature

  const metadata = {
    source: "defi_protocol",
    notes: "Completed DeFi journey across multiple chains",
    tags: ["defi", "pioneer", "multi-chain"]
  };

  await claimAchievement('alice.zks', 'defi-pioneer', proof, signature, metadata);
  ```

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

  def claim_achievement(identity, achievement_id, proof, signature, metadata=None):
      if metadata is None:
          metadata = {}
      
      request_body = {
          'proof': proof,
          'signature': signature,
          'metadata': metadata
      }
      
      response = requests.post(
          f'https://api.onzks.com/v1/achievements/{identity}/claim/{achievement_id}',
          headers={
              'Authorization': 'Bearer YOUR_API_KEY',
              'Content-Type': 'application/json'
          },
          json=request_body
      )
      
      data = response.json()
      
      if data['success']:
          print(f"🎉 Achievement claimed: {data['achievement']['title']}")
          print(f"Points awarded: {data['rewards']['points']}")
          print(f"Score bonus: {data['rewards']['scoreBonus']}")
          print(f"Total points: {data['totalPoints']}")
          
          if 'nftTokenId' in data['rewards']:
              print(f"NFT minted: Token ID {data['rewards']['nftTokenId']}")
          
          if data['celebrate']:
              print('🎊 This is a special achievement! Congratulations!')
      else:
          print(f"Failed to claim achievement: {data['message']}")
      
      return data

  # Usage example
  proof = {
      'requirements': {
          'uniqueProtocols': 50,
          'minimumChains': 3,
          'minimumVolume': '100000'
      },
      'timestamp': '2024-01-20T15:45:00Z',
      'chainId': 1,
      'transactionHash': '0x1234567890abcdef...'
  }

  signature = "0xabcdef1234567890..."  # User's signature

  metadata = {
      'source': 'defi_protocol',
      'notes': 'Completed DeFi journey across multiple chains',
      'tags': ['defi', 'pioneer', 'multi-chain']
  }

  claim_achievement('alice.zks', 'defi-pioneer', proof, signature, metadata)
  ```
</CodeGroup>

## Response Example

```json theme={null}
{
  "success": true,
  "message": "Achievement claimed successfully!",
  "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
  "zksId": "alice.zks",
  "achievement": {
    "id": "defi-pioneer",
    "title": "DeFi Pioneer",
    "description": "Interact with 50+ different DeFi protocols across multiple chains",
    "category": "defi",
    "rarity": "legendary",
    "points": 5000,
    "scoreBonus": 500,
    "icon": "https://cdn.onzks.com/achievements/defi-pioneer.png"
  },
  "rewards": {
    "points": 5000,
    "scoreBonus": 500,
    "nftTokenId": "12345",
    "nftContract": "0x1234567890abcdef...",
    "nftMetadata": "https://api.onzks.com/v1/nft/metadata/12345"
  },
  "totalPoints": 25000,
  "totalScores": 2500,
  "claimed": true,
  "celebrate": true,
  "timestamp": "2024-01-20T15:45:00Z"
}
```

## Use Cases

### 1. Achievement Claiming Flow

Complete achievement claiming process:

```javascript theme={null}
async function claimAchievementFlow(identity, achievementId) {
  try {
    // 1. Check if user has earned the achievement
    const progress = await getAchievementProgress(identity, achievementId);
    
    if (progress.progress.earned) {
      console.log('Achievement already claimed');
      return;
    }
    
    if (progress.progress.percentage < 100) {
      console.log('Achievement not yet earned');
      return;
    }
    
    // 2. Generate proof
    const proof = await generateAchievementProof(identity, achievementId);
    
    // 3. Get user signature
    const signature = await getUserSignature(identity, achievementId);
    
    // 4. Claim the achievement
    const result = await claimAchievement(identity, achievementId, proof, signature);
    
    // 5. Show celebration
    if (result.celebrate) {
      showCelebration(result.achievement);
    }
    
    return result;
  } catch (error) {
    console.error('Failed to claim achievement:', error);
    throw error;
  }
}
```

### 2. Batch Achievement Claims

Claim multiple achievements at once:

```javascript theme={null}
async function claimMultipleAchievements(identity, achievementIds) {
  const results = [];
  
  for (const achievementId of achievementIds) {
    try {
      const result = await claimAchievementFlow(identity, achievementId);
      results.push({ achievementId, success: true, result });
    } catch (error) {
      results.push({ achievementId, success: false, error: error.message });
    }
  }
  
  const successful = results.filter(r => r.success);
  const failed = results.filter(r => !r.success);
  
  console.log(`Successfully claimed ${successful.length} achievements`);
  if (failed.length > 0) {
    console.log(`Failed to claim ${failed.length} achievements`);
  }
  
  return results;
}
```

### 3. Achievement Verification

Verify achievement before claiming:

```javascript theme={null}
async function verifyAchievement(identity, achievementId) {
  const progress = await getAchievementProgress(identity, achievementId);
  
  const verification = {
    canClaim: progress.progress.percentage >= 100 && !progress.progress.earned,
    requirements: progress.progress.requirements,
    current: progress.progress.current,
    required: progress.progress.required,
    percentage: progress.progress.percentage
  };
  
  if (verification.canClaim) {
    console.log('✅ Achievement ready to claim');
  } else {
    console.log('❌ Achievement not ready to claim');
    console.log(`Progress: ${verification.percentage}%`);
  }
  
  return verification;
}
```

### 4. Celebration System

Show achievement celebrations:

```javascript theme={null}
function showCelebration(achievement) {
  const celebration = {
    title: achievement.title,
    rarity: achievement.rarity,
    points: achievement.points,
    scoreBonus: achievement.scoreBonus
  };
  
  // Show celebration modal
  const modal = document.createElement('div');
  modal.className = 'celebration-modal';
  modal.innerHTML = `
    <div class="celebration-content">
      <h2>🎉 Achievement Unlocked!</h2>
      <h3>${celebration.title}</h3>
      <p>Rarity: ${celebration.rarity}</p>
      <p>Points: ${celebration.points}</p>
      <p>Score Bonus: ${celebration.scoreBonus}</p>
      <button onclick="closeCelebration()">Awesome!</button>
    </div>
  `;
  
  document.body.appendChild(modal);
  
  // Auto-close after 5 seconds
  setTimeout(() => {
    closeCelebration();
  }, 5000);
}

function closeCelebration() {
  const modal = document.querySelector('.celebration-modal');
  if (modal) {
    modal.remove();
  }
}
```

### 5. NFT Integration

Handle NFT minting for achievements:

```javascript theme={null}
async function handleAchievementNFT(result) {
  if (result.rewards.nftTokenId) {
    const nft = {
      tokenId: result.rewards.nftTokenId,
      contract: result.rewards.nftContract,
      metadata: result.rewards.nftMetadata
    };
    
    console.log('NFT minted for achievement:', nft);
    
    // Add to user's NFT collection
    await addToUserCollection(result.address, nft);
    
    // Show NFT in UI
    displayAchievementNFT(nft);
  }
}

function displayAchievementNFT(nft) {
  const nftElement = document.createElement('div');
  nftElement.className = 'achievement-nft';
  nftElement.innerHTML = `
    <img src="${nft.metadata}" alt="Achievement NFT" />
    <p>Token ID: ${nft.tokenId}</p>
    <p>Contract: ${nft.contract}</p>
  `;
  
  document.getElementById('nft-collection').appendChild(nftElement);
}
```

## Best Practices

### 1. Verify Before Claiming

Always verify the user has earned the achievement:

```javascript theme={null}
async function safeClaimAchievement(identity, achievementId) {
  // Verify achievement is earned
  const progress = await getAchievementProgress(identity, achievementId);
  
  if (!progress.progress.earned && progress.progress.percentage < 100) {
    throw new Error('Achievement not yet earned');
  }
  
  if (progress.progress.earned) {
    throw new Error('Achievement already claimed');
  }
  
  // Proceed with claim
  return await claimAchievement(identity, achievementId, proof, signature);
}
```

### 2. Handle Errors Gracefully

Implement proper error handling:

```javascript theme={null}
async function claimWithErrorHandling(identity, achievementId) {
  try {
    const result = await claimAchievement(identity, achievementId, proof, signature);
    return { success: true, result };
  } catch (error) {
    if (error.message.includes('already claimed')) {
      return { success: false, error: 'Achievement already claimed' };
    } else if (error.message.includes('not earned')) {
      return { success: false, error: 'Achievement not yet earned' };
    } else if (error.message.includes('invalid signature')) {
      return { success: false, error: 'Invalid signature' };
    } else {
      return { success: false, error: 'Unknown error occurred' };
    }
  }
}
```

### 3. Batch Processing

Process multiple claims efficiently:

```javascript theme={null}
async function batchClaimAchievements(identity, achievementIds) {
  const batchSize = 5; // Process 5 at a time
  const results = [];
  
  for (let i = 0; i < achievementIds.length; i += batchSize) {
    const batch = achievementIds.slice(i, i + batchSize);
    const batchPromises = batch.map(id => claimAchievement(identity, id, proof, signature));
    
    const batchResults = await Promise.allSettled(batchPromises);
    results.push(...batchResults);
    
    // Wait between batches to avoid rate limits
    if (i + batchSize < achievementIds.length) {
      await new Promise(resolve => setTimeout(resolve, 1000));
    }
  }
  
  return results;
}
```

### 4. Progress Tracking

Track claim progress:

```javascript theme={null}
function trackClaimProgress(identity, achievementId) {
  const startTime = Date.now();
  
  return {
    start: () => {
      console.log('Starting achievement claim...');
    },
    complete: (result) => {
      const duration = Date.now() - startTime;
      console.log(`Achievement claimed in ${duration}ms`);
      console.log(`Points awarded: ${result.rewards.points}`);
    },
    error: (error) => {
      const duration = Date.now() - startTime;
      console.error(`Claim failed after ${duration}ms:`, error);
    }
  };
}
```

## Related Endpoints

* [Get Achievement Progress](/api-reference/achievements/get-progress) - Check progress before claiming
* [Get User Achievements](/api-reference/achievements/get-user-achievements) - View all user achievements
* [List Achievements](/api-reference/achievements/list-achievements) - Browse available achievements

## Troubleshooting

### "Achievement not earned"

**Cause**: User hasn't met the requirements for the achievement.

**Solution**:

* Check the achievement requirements
* Verify the user's progress
* Wait for the user to complete the requirements

### "Achievement already claimed"

**Cause**: User has already claimed this achievement.

**Solution**:

* Check if the achievement is already in the user's collection
* Don't attempt to claim the same achievement twice

### "Invalid signature"

**Cause**: The signature doesn't match the user's identity.

**Solution**:

* Verify the signature is from the correct wallet
* Check that the message was signed correctly
* Ensure the user is signing with the right account

### "Proof verification failed"

**Cause**: The proof doesn't meet the achievement requirements.

**Solution**:

* Verify all requirements are met
* Check that the proof data is accurate
* Ensure the timestamp is recent

## Rate Limits

Achievement claim requests are subject to rate limits:

* **Free tier**: 10 claims per minute
* **Starter tier**: 50 claims per minute
* **Professional tier**: 200 claims per minute
* **Enterprise tier**: Custom limits

Implement queuing for batch claims to avoid rate limits.
