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

# Quest Integration

> Build complete quest workflows with eligibility verification and status tracking

## Overview

Implement quest systems that handle:

* Quest validation and status checking
* User eligibility verification through credential groups
* Quest discovery and filtering
* Loyalty points tracking

## Basic Quest Operations

### Get Quest Details

```graphql theme={null}
query GetQuest($id: ID!) {
  quest(id: $id) {
    id
    name
    type
    status
    description
    startTime
    endTime
    cap
    participantsCount
    loyaltyPoints
    space {
      id
      name
    }
    chain
  }
}
```

**Response**:

```json theme={null}
{
  "data": {
    "quest": {
      "id": "GChdWUjXX3",
      "name": "Introduction to Web3!",
      "type": "Drop",
      "status": "Active",
      "description": "Welcome to Module 1-Course 1 of Mission Web3!",
      "startTime": 1699200000,
      "endTime": 1699800000,
      "cap": 10000,
      "participantsCount": 234163,
      "loyaltyPoints": 100,
      "space": {
        "id": "40",
        "name": "BNB Chain"
      },
      "chain": "BSC"
    }
  }
}
```

### List Space Quests

```graphql theme={null}
query GetSpaceQuests($spaceId: ID!, $first: Int!, $statuses: [QuestStatus!]) {
  quests(input: {
    spaceId: $spaceId
    first: $first
    statuses: $statuses
  }) {
    totalCount
    pageInfo {
      hasNextPage
      endCursor
    }
    list {
      id
      name
      type
      status
      participantsCount
      loyaltyPoints
      startTime
      endTime
    }
  }
}
```

## Quest Status Reference

| Status       | Description                              | When Used           |
| ------------ | ---------------------------------------- | ------------------- |
| `Draft`      | Quest in development                     | Before publishing   |
| `Active`     | Quest is live and accepting participants | During quest period |
| `NotStarted` | Quest published but not started          | Before start time   |
| `Expired`    | Quest has ended                          | After end time      |
| `CapReached` | Participant limit reached                | When cap is full    |
| `Deleted`    | Quest removed                            | Removed quests      |

## Quest Types

| Type           | Description                |
| -------------- | -------------------------- |
| `Drop`         | NFT drop quest             |
| `MysteryBox`   | Mystery box reward         |
| `Airdrop`      | Token airdrop              |
| `Points`       | Loyalty points reward      |
| `ExternalLink` | External link verification |
| `Bounty`       | Bounty quest               |

## User Eligibility Verification

### Check User Eligibility

```graphql theme={null}
query CheckUserEligibility($questId: ID!, $address: String!) {
  quest(id: $questId) {
    id
    name
    status
    credentialGroups(address: $address) {
      id
      name
      conditionRelation
      conditions {
        expression
        eligible
      }
      rewards {
        expression
        eligible
        rewardType
        rewardCount
      }
    }
  }
}
```

**Key Points**:

* When `conditions.eligible` is `true`, user meets requirements
* When `rewards.eligible` is `true`, user can claim rewards
* `conditionRelation` can be `ALL` (must meet all) or `ANY` (meet at least one)

## Basic Implementation

### Quest Validation

```javascript theme={null}
async function validateQuest(questId, accessToken) {
  const response = await fetch('https://graphigo-business.prd.galaxy.eco/query', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'access-token': accessToken
    },
    body: JSON.stringify({
      query: `query GetQuest($id: ID!) {
        quest(id: $id) {
          id
          name
          status
          startTime
          endTime
          participantsCount
          cap
        }
      }`,
      variables: { id: questId }
    })
  });
  
  const data = await response.json();
  const quest = data.data.quest;
  
  if (!quest) throw new Error('Quest not found');
  
  // Check quest status
  if (quest.status === 'Draft') throw new Error('Quest is in draft mode');
  if (quest.status === 'Deleted') throw new Error('Quest has been deleted');
  if (quest.status === 'Expired') throw new Error('Quest has expired');
  if (quest.status === 'CapReached') throw new Error('Quest capacity reached');
  
  // Check timing for active quests
  if (quest.status === 'Active' && quest.startTime && quest.endTime) {
    const now = Math.floor(Date.now() / 1000);
    if (now < quest.startTime) throw new Error('Quest has not started yet');
    if (now > quest.endTime) throw new Error('Quest has ended');
  }
  
  return quest;
}
```

### Check User Eligibility

```javascript theme={null}
async function checkUserEligibility(questId, userAddress, accessToken) {
  const response = await fetch('https://graphigo-business.prd.galaxy.eco/query', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'access-token': accessToken
    },
    body: JSON.stringify({
      query: `query CheckUserEligibility($questId: ID!, $address: String!) {
        quest(id: $questId) {
          id
          name
          status
          credentialGroups(address: $address) {
            id
            name
            conditionRelation
            conditions {
              expression
              eligible
            }
            rewards {
              expression
              eligible
              rewardType
              rewardCount
            }
          }
        }
      }`,
      variables: { questId, address: userAddress }
    })
  });
  
  const data = await response.json();
  const quest = data.data.quest;
  
  if (!quest) throw new Error('Quest not found');
  
  const eligibilityResults = quest.credentialGroups.map(group => {
    // Check conditions based on relation (ALL or ANY)
    const conditionsMet = group.conditionRelation === 'ALL' 
      ? group.conditions.every(c => c.eligible)
      : group.conditions.some(c => c.eligible);
    
    const eligibleRewards = group.rewards.filter(r => r.eligible);
    
    return {
      groupId: group.id,
      groupName: group.name,
      conditionsMet,
      eligibleRewards
    };
  });
  
  const isEligible = eligibilityResults.some(r => r.conditionsMet && r.eligibleRewards.length > 0);
  
  return {
    questId,
    userAddress,
    isEligible,
    eligibilityDetails: eligibilityResults,
    questName: quest.name,
    questStatus: quest.status
  };
}
```

### Get Space Quests

```javascript theme={null}
async function getSpaceQuests(spaceId, accessToken, options = {}) {
  const { 
    limit = 20, 
    cursor = null, 
    statuses = ['Active']
  } = options;
  
  const response = await fetch('https://graphigo-business.prd.galaxy.eco/query', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'access-token': accessToken
    },
    body: JSON.stringify({
      query: `query GetSpaceQuests($input: ListQuestInput!) {
        quests(input: $input) {
          totalCount
          pageInfo {
            hasNextPage
            endCursor
          }
          list {
            id
            name
            type
            status
            participantsCount
            loyaltyPoints
            startTime
            endTime
            cap
          }
        }
      }`,
      variables: {
        input: {
          spaceId,
          first: limit,
          after: cursor,
          statuses
        }
      }
    })
  });
  
  const data = await response.json();
  return data.data.quests;
}
```

## Quest Status Helpers

### Check Quest Phase

```javascript theme={null}
function getQuestPhase(quest) {
  switch (quest.status) {
    case 'NotStarted':
      return 'not_started';
    case 'Active':
      if (quest.startTime && quest.endTime) {
        const now = Math.floor(Date.now() / 1000);
        if (now < quest.startTime) return 'scheduled';
        if (now > quest.endTime) return 'ended_pending';
      }
      return 'active';
    case 'Expired':
      return 'expired';
    case 'CapReached':
      return 'full';
    case 'Draft':
      return 'draft';
    case 'Deleted':
      return 'deleted';
    default:
      return 'unknown';
  }
}

function isQuestParticipable(quest) {
  if (quest.status !== 'Active') return false;
  
  // Check capacity
  if (quest.cap > 0 && quest.participantsCount >= quest.cap) return false;
  
  // Check timing
  if (quest.startTime && quest.endTime) {
    const now = Math.floor(Date.now() / 1000);
    if (now < quest.startTime || now > quest.endTime) return false;
  }
  
  return true;
}
```

## Usage Examples

### Basic Quest Validation

```javascript theme={null}
// Validate quest before showing UI
const accessToken = process.env.GALXE_ACCESS_TOKEN;

try {
  const quest = await validateQuest('GChdWUjXX3', accessToken);
  console.log(`Quest "${quest.name}" is ${quest.status}`);
  console.log(`Participants: ${quest.participantsCount}`);
  
  const phase = getQuestPhase(quest);
  const canParticipate = isQuestParticipable(quest);
  
  console.log(`Phase: ${phase}`);
  console.log(`Can participate: ${canParticipate}`);
} catch (error) {
  console.error('Quest validation failed:', error.message);
}
```

### User Eligibility Check

```javascript theme={null}
// Check if user can participate
const userAddress = '0x1234567890123456789012345678901234567890';
const eligibility = await checkUserEligibility('GChdWUjXX3', userAddress, accessToken);

if (eligibility.isEligible) {
  console.log('User is eligible for quest');
  console.log('Available rewards:', eligibility.eligibilityDetails
    .flatMap(group => group.eligibleRewards)
    .map(reward => reward.expression)
  );
} else {
  console.log('User is not eligible for this quest');
  console.log('Missing requirements:', eligibility.eligibilityDetails
    .filter(group => !group.conditionsMet)
    .map(group => group.groupName)
  );
}
```

### Quest Discovery

```javascript theme={null}
// Get active quests for a space
const spaceQuests = await getSpaceQuests('40', accessToken, {
  statuses: ['Active'],
  limit: 10
});

console.log(`Found ${spaceQuests.totalCount} active quests`);
console.log('Quest list:');
spaceQuests.list.forEach(quest => {
  console.log(`- ${quest.name} (${quest.loyaltyPoints} points, ${quest.participantsCount} participants)`);
});
```

### Complete Quest Check

```javascript theme={null}
async function createQuestDashboard(spaceId, userAddress, accessToken) {
  // Get active quests
  const quests = await getSpaceQuests(spaceId, accessToken, {
    statuses: ['Active'],
    limit: 10
  });
  
  // Check eligibility for top quests
  const eligibilityChecks = await Promise.all(
    quests.list.slice(0, 5).map(quest => 
      checkUserEligibility(quest.id, userAddress, accessToken)
        .then(result => ({ ...quest, eligibility: result }))
        .catch(error => ({ ...quest, eligibility: { error: error.message } }))
    )
  );
  
  const eligibleQuests = eligibilityChecks.filter(q => q.eligibility.isEligible);
  const totalPoints = eligibleQuests.reduce((sum, q) => sum + q.loyaltyPoints, 0);
  
  return {
    space: { id: spaceId },
    totalQuests: quests.totalCount,
    checkedQuests: eligibilityChecks.length,
    eligibleQuests: eligibleQuests.length,
    potentialPoints: totalPoints,
    quests: eligibilityChecks
  };
}
```

## Best Practices

1. **Status Validation**: Always check quest status before showing participation UI
2. **Error Handling**: Handle cases where quests are not found or access is denied
3. **Rate Limiting**: Add delays when processing multiple quests or users
4. **Caching**: Cache quest details for 1-5 minutes to reduce API calls
5. **Capacity Monitoring**: Check both status and participant count vs cap

## Quest Lifecycle

| Status       | User Actions                   | Next Status               |
| ------------ | ------------------------------ | ------------------------- |
| `Draft`      | None (not visible)             | `NotStarted` or `Active`  |
| `NotStarted` | View details, set reminders    | `Active`                  |
| `Active`     | Participate, check eligibility | `Expired` or `CapReached` |
| `CapReached` | View results only              | `Expired`                 |
| `Expired`    | View results only              | N/A                       |
| `Deleted`    | None (hidden)                  | N/A                       |

## Common Integration Patterns

* **Quest Discovery**: Filter by space, status, and type
* **Eligibility Pre-check**: Verify user can participate before showing UI
* **Status Monitoring**: Track quest lifecycle changes
* **Reward Tracking**: Monitor available rewards and claim status
* **Points Calculation**: Track potential loyalty points earnings

## Next Steps

* **[Quest API Reference](/galxe-integration/api-reference/quest)** - Complete API documentation
* **[Credential Integration](/galxe-integration/guides/user-verification)** - User verification workflows
* **[Loyalty Program](/galxe-integration/guides/loyalty-program)** - Points and rewards integration
