# API Endpoint

TESTNET / MAINNET

For your projects, we provide two different API endpoints based on the network you intend to utilize:

### **Mainnet API Endpoint**

This endpoint is specifically designed for integration with the mainnet network. It enables you to interact with the PLYR API in a production environment, where real transactions and operations occur. You should use the Mainnet API Endpoint when your project is ready for deployment and needs to interact with the live blockchain network.

<https://api.plyr.network/api>

### Testnet API Endpoint

This endpoint is intended for use on the testnet network. The testnet environment allows you to experiment and test your integration with the ZooGames API without utilizing real funds or affecting the live blockchain network. It provides a sandbox-like environment for developers to ensure the functionality and reliability of their applications before transitioning to the mainnet.

<https://api-testnet.plyr.network/api>

You can request Testnet PLYR and GAMR [here](https://core.app/tools/testnet-faucet/?subnet=plyr\&token=plyr)

> Please ensure that you select the appropriate API endpoint based on your project's requirements and the desired network environment.

{% hint style="info" %}
We recommend testing on the Testnet environment first.\
Throughout the documentation, we use "**apiEnpoint**" to represent the API Endpoint you choose to use.\
Replace it with the appropriate Testnet or Mainnet URL as needed.
{% endhint %}


# API Quickstart

Things to know before using an API

### Prerequisite

* You need to signup PLYR\[ID] first on both [Mainnet ](https://pgu.plyr.network/signup/)and [Testnet](https://pgu-testnet.vercel.app/dashboard/). This PLYR\[ID] gonna be a "Developer account and Game ID". Please set a name to be related with your game name.
* API KEY and SECRET KEY — After you signup the PLYR\[ID]. You can request us to generate API KEY Pair.

### **Basic to Call our API**

We use **"Timestamp + Body Payload"** and signs with **SECRET KEY** as  a **HMAC (SHA256) signature**. You need to include custom header apikey, signature, timestamp every time to call our API.

## Base Headers

Every API request must include these base headers:

```typescript
{
    apikey: string; // Your API key obtained from the developer portal
    signature: string; // HMAC signature of the request
    timestamp: string; // Current timestamp in milliseconds (Date.now().toString())
}
```

## Header Requirements

Format Requirements:

```
- Headers are case-sensitive
- Values must be strings
- Timestamp must be in milliseconds
```

## HMAC Signature Generation

```typescript
// Example signature generation
const timestamp = Date.now().toString();
const payload = JSON.stringify(requestBody);
const message = timestamp + payload;
const signature = crypto.createHmac('sha256', secretKey).update(message).digest('hex');
```

{% hint style="warning" %}
Always keep your API key and secret key secure. Never expose them in client-side code or public repositories.
{% endhint %}

### **Example 1: GET Method API without Body Payload.**

Let see the example of "userInfo" API endpoint.

{% tabs %}
{% tab title="Javascript" %}

```javascript
// Generate HMAC signature from timestamp + body //
const crypto = require('crypto');
const axios = require("axios");

const APIKEY = ''; // your api key
const SECRETKEY = ''; // you api secret key 

function generateHmacSignature(timestamp, body, secretkey) {
  const bodyString = JSON.stringify(body);
  const data = timestamp + bodyString;
  return crypto
    .createHmac('sha256', secretkey)
    .update(data)
    .digest('hex');
}

const timestamp = Date.now().toString();
const apiEndpoint = 'https://api-testnet.plyr.network/api';
const searchText = 'cyptofennec'; // PLYR[ID]
let hmac = generateHmacSignature(timestamp, {}, SECRETKEY); // If API required body payload (POST method) just pass the object //
let ret = await axios.get(
            apiEndpoint + "/api/user/info/" + searchTxt + '/',
            {
                headers: {
                    apikey: APIKEY,
                    signature: hmac,
                    timestamp: timestamp,
                },
            }
        );
console.log("ret data",ret.data);
```

{% endtab %}

{% tab title="Result" %}

```json
{
  plyrId: "cyptofennec",
  mirrorAddress: "0x4eaf4CE71c42758b2D4B4C23E543e1D98c8dE9C6",
  primaryAddress: "0x6Ab499c8E2f3CBc9C99034b6e2912149212bE770",
  chainId: 62831,
  avatar: "https://ipfs.plyr.network/ipfs/QmfMhXz8vqBDMHVVstnK8tykmhAN6oXv5xZunC3SXR1NWL",
  createdAt: "2024-08-05T12:48:30.429Z",
  ippClaimed: false,
  isIPP: false
}
```

{% endtab %}
{% endtabs %}

### **Example 2: POST Method API with Body Payload.**

Let see the example of "getAvatars" API endpoint.

{% tabs %}
{% tab title="Javascript" %}

```javascript
// Generate HMAC signature from timestamp + body //
const crypto = require('crypto');
const axios = require("axios");

const APIKEY = ''; // your api key
const SECRETKEY = ''; // you api secret key 

function generateHmacSignature(timestamp, body, secretkey) {
  const bodyString = JSON.stringify(body);
  const data = timestamp + bodyString;
  return crypto
    .createHmac('sha256', secretkey)
    .update(data)
    .digest('hex');
}

const timestamp = Date.now().toString();
const apiEndpoint = 'https://api-testnet.plyr.network/api';
let body = {
    plyrIds: ['fennec2', 'cyptofennec']
}
let hmac = generateHmacSignature(timestamp, body, SECRETKEY);
let ret = await axios.post(
            apiEndpoint + "/api/user/avatars",
            body,
            {
                headers: {
                    apikey: APIKEY,
                    signature: hmac,
                    timestamp: timestamp,
                },
            }
        );
console.log("ret data",ret.data);
```

{% endtab %}

{% tab title="Result" %}

```json
{
  avatars: [
    {
      plyrId: "cyptofennec",
      avatar: "https://ipfs.plyr.network/ipfs/QmfMhXz8vqBDMHVVstnK8tykmhAN6oXv5xZunC3SXR1NWL"
    },
    {
      plyrId: "fennec2",
      avatar: "https://ipfs.plyr.network/ipfs/QmYHv8HJ6SDGbGkMDwfVfXehpNNGvPrB8W2dXnd26CpPYL"
    }
  ]
}
```

{% endtab %}
{% endtabs %}


# Users


# Authentication

{% hint style="info" %}
For detailed information about required headers and their format, please see the [Headers](/api-quickstart#base-headers) page.
{% endhint %}

## Authentication Methods

There are two ways to authenticate:

1. PlyrID Authentication
   * Requires PlyrID and 2FA token
   * Returns a session JWT valid for 24 hours by default
2. InstantPlayPass Authentication
   * Quick authentication for instant play
   * No registration required

## Common Flows

### Standard Authentication Flow

1. Authenticate using PlyrID or InstantPlayPass
2. Store received sessionJwt
3. Authenticate with sessionJwt for subsequent requests


# PLYR\[ID]


# Login

User login endpoint

{% hint style="info" %}
Authenticate a user and get a session JWT token.
{% endhint %}

**Endpoint:** `/user/login`\
**Method:** POST

{% tabs %}
{% tab title="Request Body" %}

```typescript
{
    plyrId: string;     // Player ID (lowercase)
    otp: string;        // 2FA token
    expiresIn?: number; // Session expiration in seconds (optional, defaults to 86400s/24hrs)
    gameId: string;     // Game identifier
}
```

{% endtab %}

{% tab title="Success Response (200)" %}

```typescript
{
    sessionJwt: string;
    plyrId: string;
    nonce: string;
    gameId: string;
    primaryAddress: string;
    mirrorAddress: string;
}
```

{% endtab %}

{% tab title="Error Response (400)" %}

```typescript
{
    error: string;
}
```

{% endtab %}
{% endtabs %}

## Example Usage

```javascript
const timestamp = Date.now().toString();
const body = {
    plyrId: 'player123',
    otp: '123456', // 2FA token from authenticator app
    expiresIn: 3600, // Session will expire in 1 hour
    gameId: 'game123' // Your game's identifier
};

const hmac = generateHmacSignature(timestamp, body, secretKey);

const response = await axios.post(apiEndpoint + '/user/login', body, {
    headers: {
        apikey: apiKey,
        signature: hmac,
        timestamp: timestamp
    }
});

// Store session information securely
const {
    sessionJwt, // JWT token for future API calls
    plyrId, // Player's ID
    nonce, // Unique nonce for this session
    gameId, // Game identifier
    primaryAddress, // User's primary wallet address
    mirrorAddress // User's mirror wallet address
} = response.data;

// Use sessionJwt for subsequent authenticated API calls
```

{% hint style="warning" %}
Store the session JWT securely and never expose it in client-side code or logs.
{% endhint %}

{% hint style="info" %}
The session JWT is required for most API endpoints and should be included in the request headers.
{% endhint %}


# Login and Approve

User login with token approval endpoint

{% hint style="info" %}
Authenticate a user and approve token spending in a single request.
{% endhint %}

**Endpoint:** `/user/loginAndApprove`\
**Method:** POST

{% tabs %}
{% tab title="Request Body" %}

```typescript
{
    plyrId: string;     // Player ID (lowercase)
    gameId: string;     // Game identifier
    otp: string;        // 2FA token
    tokens: string[];      // Token names to approve
    amounts: number[];     // Amounts to approve
    expiresIn?: number; // Session expiration in seconds (optional, defaults to 86400s/24hrs)
}
```

{% endtab %}

{% tab title="Success Response (200)" %}

```typescript
{
    sessionJwt: string;
    plyrId: string;
    nonce: string;
    gameId: string;
    primaryAddress: string;
    mirrorAddress: string;
}
```

{% endtab %}

{% tab title="Error Response (400)" %}

```typescript
{
    error: string;
}
```

{% endtab %}
{% endtabs %}

## Example Usage

```javascript
const timestamp = Date.now().toString();
const body = {
    plyrId: 'player123',
    gameId: 'game123',
    otp: '123456', // 2FA token from authenticator app
    tokens: ['TOKEN1', 'TOKEN2'], // Token names to approve for spending
    amounts: [1000, 2000], // Amounts to approve
    expiresIn: 3600 // Session will expire in 1 hour
};

const hmac = generateHmacSignature(timestamp, body, secretKey);

const response = await axios.post(apiEndpoint + '/user/loginAndApprove', body, {
    headers: {
        apikey: apiKey,
        signature: hmac,
        timestamp: timestamp
    }
});

// Store session information securely
const {
    sessionJwt, // JWT token for future API calls
    plyrId, // Player's ID
    nonce, // Unique nonce for this session
    gameId, // Game identifier
    primaryAddress, // User's primary wallet address
    mirrorAddress // User's mirror wallet address
} = response.data;

// Use sessionJwt for subsequent authenticated API calls
// Token approval is already processed
```

{% hint style="info" %}
This endpoint combines login and token approval into a single atomic operation, making it more efficient than separate calls.
{% endhint %}

{% hint style="warning" %}
Store the session JWT securely and never expose it in client-side code or logs.
{% endhint %}

{% hint style="warning" %}
The approved amounts represent the maximum amounts that can be spent per token. The actual spending may be less.
{% endhint %}


# Logout

Logout endpoint documentation

{% hint style="info" %}
End a user session.
{% endhint %}

**Endpoint:** `/user/logout`\
**Method:** POST

{% tabs %}
{% tab title="Request Body" %}

```typescript
{
    sessionJwt: string; // Active session JWT
}
```

{% endtab %}

{% tab title="Success Response (200)" %}

```typescript
{
    message: string;
}
```

{% endtab %}

{% tab title="Error Response (404)" %}

```typescript
{
    error: string;
}
```

{% endtab %}
{% endtabs %}

## Example Usage

```javascript
const timestamp = Date.now().toString();
const body = {
    sessionJwt: 'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9...' // Active session JWT
};

const hmac = generateHmacSignature(timestamp, body, secretKey);

const response = await axios.post(apiEndpoint + '/user/logout', body, {
    headers: {
        apikey: apiKey,
        signature: hmac,
        timestamp: timestamp
    }
});
```

{% hint style="info" %}
After logout, the session JWT becomes invalid and cannot be used for further API calls.
{% endhint %}

{% hint style="warning" %}
Always clean up session data in your application after a successful logout.
{% endhint %}


# InstantPlayPass


# RegisterIPP

Register Instant PlayPass endpoint documentation

{% hint style="info" %}
Register a new Instant PlayPass session with specified tokens.
{% endhint %}

**Endpoint:** `/instantPlayPass/register`\
**Method:** POST

{% tabs %}
{% tab title="Request Body" %}

```typescript
{
    tokens: string[]; // Array of tokens (e.g. ['plyr', 'gamr'])
    sync?: boolean; // Optional sync flag
}
```

{% endtab %}

{% tab title="Success Response (200)" %}

```typescript
{
    sessionJwt: string; // Session JWT token
    plyrId: string; // Player ID
    gameId: string; // Game ID
    primaryAddress: string; // Primary wallet address
    mirrorAddress: string; // Mirror wallet address
    avatar: string; // Avatar URL
    ippClaimed: boolean; // Whether IPP is claimed
    isIPP: boolean; // Whether this is an IPP session
}
```

{% endtab %}

{% tab title="Error Response" %}

```typescript
{
    error: string;
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
After successful registration, use the "Reveal Claiming Code" endpoint to get the code for the user.
{% endhint %}

## Example Usage

```javascript
const timestamp = Date.now().toString();
const body = {
    tokens: ['plyr', 'gamr'], // Tokens to include in the PlayPass
    sync: true // Optional: synchronize tokens
};

const hmac = generateHmacSignature(timestamp, body, secretKey);

const response = await axios.post(apiEndpoint + '/instantPlayPass/register', body, {
    headers: {
        apikey: apiKey,
        signature: hmac,
        timestamp: timestamp
    }
});

// Use the session JWT from the response
const sessionJwt = response.data.sessionJwt;

// You can now proceed with revealing the claiming code using the sessionJwt
```


# RevealClaimingCode

Reveal Claiming Code endpoint documentation

{% hint style="info" %}
Reveal the claiming code for an Instant PlayPass session.
{% endhint %}

**Endpoint:** `/instantPlayPass/reveal/claimingCode`\
**Method:** POST

{% tabs %}
{% tab title="Request Body" %}

```typescript
{
    sessionJwt: string; // IPP Session JWT token
}
```

{% endtab %}

{% tab title="Success Response (200)" %}

```typescript
{
    claimingCode: string; // The revealed claiming code
}
```

{% endtab %}

{% tab title="Error Response" %}

```typescript
{
    error: string;
}
```

{% endtab %}
{% endtabs %}

## Example Usage

```javascript
const timestamp = Date.now().toString();
const body = {
    sessionJwt: 'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9...' // IPP Session JWT from registration
};

const hmac = generateHmacSignature(timestamp, body, secretKey);

const response = await axios.post(apiEndpoint + '/instantPlayPass/reveal/claimingCode', body, {
    headers: {
        apikey: apiKey,
        signature: hmac,
        timestamp: timestamp
    }
});

// Get the claiming code
const { claimingCode } = response.data;
```


# VerifyClaimingCode

Verify Claiming Code endpoint documentation

{% hint style="info" %}
Verify the validity of an Instant PlayPass claiming code.
{% endhint %}

**Endpoint:** `/instantPlayPass/verify/claimingCode/{claimingCode}`\
**Method:** GET

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    claimingCode: string; // The claiming code to verify
}
```

{% endtab %}

{% tab title="Success Response (200)" %}

```typescript
{
    valid: boolean; // Whether the claiming code is valid
    status: string; // Status of the claiming code
}
```

{% endtab %}

{% tab title="Error Response" %}

```typescript
{
    error: string;
}
```

{% endtab %}
{% endtabs %}

## Example Usage

```javascript
const timestamp = Date.now().toString();
const claimingCode = 'ABC123XYZ'; // The claiming code to verify

// Since this is a GET request with no body, pass null as the body for HMAC
const hmac = generateHmacSignature(timestamp, null, secretKey);

const response = await axios.get(apiEndpoint + `/instantPlayPass/verify/claimingCode/${claimingCode}`, {
    headers: {
        apikey: apiKey,
        signature: hmac,
        timestamp: timestamp
    }
});

// Check the validity and status of the claiming code
const { valid, status } = response.data;

if (valid) {
    console.log('Claiming code is valid');
    console.log('Status:', status);
    // Proceed with the claiming process
} else {
    console.log('Claiming code is invalid or expired');
    // Handle invalid code (e.g., ask user to try again)
}
```

{% hint style="warning" %}
Claiming codes can only be used once.
{% endhint %}


# PLYR\[CONNECT]

{% hint style="info" %}
UNDER DEVELOPMENT
{% endhint %}

The easiest way to authenticate users via Browser / In-App browser with various ways to give back authenticated data.

### Endpoint of PLYR\[CONNECT]

Mainnet : <https://connect.plyr.network/>

Testnet: <https://connect-testnet.plyr.network/>

### **The required params to send to endpoint**

**Example of Login**\
<https://connect-testnet.plyr.network/?action=manageIPP&requestData=eyJnYW1lSWQiOiJ0ZXN0ZXIiLCJtb2RlIjoicmVkaXJlY3QiLCJjYWxsYmFja1VybCI6Imh0dHBzOi8vY29ubmVjdC10ZXN0bmV0LnBseXIubmV0d29yay90ZXN0LyJ9>

| Parameter Name | Description                                             | Remark                                |
| -------------- | ------------------------------------------------------- | ------------------------------------- |
| action         | <p>login<br>approve<br>loginAndApprove<br>manageIPP</p> |                                       |
| requestData    | base64 encoded string of json.                          | Each action has itself json structure |

### The Action's requestData json structure

{% tabs %}
{% tab title="login" %}

```json
{
    "gameId": "tester",
    "expiresIn": "86400",
    "mode": "redirect",
    "callbackString": "callbackStringOfMyGame",
    "callbackUrl": "https://connect-testnet.plyr.network/test/"
}
```

{% endtab %}

{% tab title="approve" %}

<pre class="language-json"><code class="lang-json">{
    "gameId": "tester",
    "plyrId": "fennec2",
    "tokens": [
        "plyr",
        "gamr"
    ],
    "amounts": [
        "2222",
        "3333"
    ],
<strong>    "expiresIn": "86400",
</strong>    "mode": "redirect",
    "callbackString": "callbackStringOfMyGame",
    "callbackUrl": "https://connect-testnet.plyr.network/test/"
}
</code></pre>

{% endtab %}

{% tab title="loginAndApprove" %}

```json
{
    "gameId": "tester",
    "tokens": [
      "plyr",
      "gamr"
    ],
    "amounts": [
      "4444",
      "5555"
      ],
    "expiresIn": "86400",
    "mode": "redirect",
    "callbackString": "callbackStringOfMyGame",
    "callbackUrl": "https://connect-testnet.plyr.network/test/"
}
```

{% endtab %}

{% tab title="mangeIPP" %}

```json
{
    "gameId": "tester",
    "mode": "redirect",
    "callbackUrl": "https://connect-testnet.plyr.network/test/"
}
```

{% endtab %}
{% endtabs %}

### How to select Mode

**Redirect**&#x20;

Open a new tab of browser. After authenticated, it will redirect to "callbackUrl".

If you want to do a polling interval to wait user to authenticate themself. you can do it by adding an extra param "uid" and pass the random UUID or any. and callbackUrl can be "/over" to show that authentication is successful

and you can use /auth/read/\[uid] endpoint to check the result every interval you want. (recommended 2 - 5 seconds)

**Callback**&#x20;

Opena new tab of browser. After authenticated, it will callback (Server side to callbackUrl)

**Opener**&#x20;

You can do a popup browser window. It will use "window\.opener.postMessage" to callback the origin / opener.

It will do a postMessage with the following structure

```json
{ 
   "vendor": "plyrconnect",
   "action": "login", 
   "callbackString": "YouEnteredStringFromRequestData",
   "callbackData": "base64 encoded json data from PLYR API"
}   
```

After Authenticated you can addEventlistener('message') to capture the callbacked data

```javascript
window.addEventListener('message', (e: any) => {
   if (e.data.vendor === 'plyrconnect') {
      console.log('callbackString:',e.data.callbackString)
      console.log('callbackData:', JSON.parse(atob(e.data.callbackData)))
   }
});
```

**Iframe**&#x20;

You can do an iframe. It will use "window\.parent.postMessage" to callback the parent.

It will do a postMessage with the following structure

```json
{ 
   "vendor": "plyrconnect",
   "action": "login", 
   "callbackString": "YouEnteredStringFromRequestData",
   "callbackData": "base64 encoded json data from PLYR API"
}
```

After Authenticated you can addEventlistener('message') to capture the callbacked data

```javascript
window.addEventListener('message', (e: any) => {
   if (e.data.vendor === 'plyrconnect') {
      console.log('callbackString:',e.data.callbackString)
      console.log('callbackData:', JSON.parse(atob(e.data.callbackData)))
   }
});
```


# Check Session JWT

Check session JWT validity endpoint

{% hint style="info" %}
Verify if a session JWT is valid and get associated user information.
{% endhint %}

**Endpoint:** `/user/session/verify`\
**Method:** POST

{% tabs %}
{% tab title="Request Body" %}

```typescript
{
    sessionJwt: string; // JWT token to verify
}
```

{% endtab %}

{% tab title="Success Response (200)" %}

```typescript
{
    isValid: boolean;
    plyrId?: string;
    walletAddress?: string;
}
```

{% endtab %}

{% tab title="Error Response (400)" %}

```typescript
{
    error: string;
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
For local JWT verification without making an API call, see the "Verify JWT Locally" documentation.
{% endhint %}

{% hint style="warning" %}
Session JWTs have an expiration time. Always verify JWTs before using them in critical operations.
{% endhint %}

## Example Usage

```javascript
const timestamp = Date.now().toString();
const body = {
    sessionJwt: 'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9...' // JWT to verify
};

const hmac = generateHmacSignature(timestamp, body, secretKey);

const response = await axios.post(apiEndpoint + '/user/session/verify', body, {
    headers: {
        apikey: apiKey,
        signature: hmac,
        timestamp: timestamp
    }
});
```


# Get Basic User Info

Get basic user information endpoint

{% hint style="info" %}
Retrieve basic user information. Can query by PLYR ID or primary wallet address.
{% endhint %}

**Endpoint:** `/user/info/{identifier}`\
**Method:** GET

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    identifier: string; // PLYR ID or primary wallet address
}
```

{% endtab %}

{% tab title="Success Response (200)" %}

```typescript
{
    plyrId: string;
    username: string;
    walletAddress: string;
    avatarUrl: string;
}
```

{% endtab %}

{% tab title="Error Response (404)" %}

```typescript
{
    error: string;
}
```

{% endtab %}
{% endtabs %}

## Example Usage

```javascript
const timestamp = Date.now().toString();
// Can use either PLYR ID or wallet address
const identifier = 'player123'; // or '0x742d35Cc6634C0532925a3b844Bc454e4438f44e'

// Since this is a GET request with no body, pass null as the body for HMAC
const hmac = generateHmacSignature(timestamp, null, secretKey);

const response = await axios.get(apiEndpoint + `/user/info/${identifier}`, {
    headers: {
        apikey: apiKey,
        signature: hmac,
        timestamp: timestamp
    }
});

// Response will contain basic user information
const { plyrId, username, walletAddress, avatarUrl } = response.data;
```

{% hint style="info" %}
The identifier can be either a PLYR ID or a wallet address. The API will automatically detect which type it is and return the corresponding user information.
{% endhint %}


# Get Avatar

Get multiple users' avatars endpoint

{% hint style="info" %}
Retrieve avatar image URLs for multiple users.
{% endhint %}

**Endpoint:** `/user/avatar`\
**Method:** POST

{% tabs %}
{% tab title="Request Body" %}

```typescript
{
    plyrIds: string[]; // Array of player unique identifiers
}
```

{% endtab %}

{% tab title="Success Response (200)" %}

```typescript
{
    [plyrId: string]: string; // Map of plyrId to avatarUrl
}
```

{% endtab %}

{% tab title="Error Response (400)" %}

```typescript
{
    error: string;
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
This endpoint is optimized for retrieving single or multiple avatars in a single request.
{% endhint %}

## Example Usage

```javascript
const timestamp = Date.now().toString();
const body = {
    plyrIds: ['player123', 'player456', 'player789'] // Array of PLYR IDs
};

const hmac = generateHmacSignature(timestamp, body, secretKey);

const response = await axios.post(apiEndpoint + '/user/avatar', body, {
    headers: {
        apikey: apiKey,
        signature: hmac,
        timestamp: timestamp
    }
});

// Response will contain avatar URLs for each PLYR ID
const { avatars } = response.data;

// Process avatar URLs
Object.entries(avatars).forEach(([plyrId, avatarUrl]) => {
    console.log(`Avatar URL for ${plyrId}:`, avatarUrl);
    // Use avatarUrl in your application (e.g., display avatar image)
});
```


# Game room

## Overview

Game rooms are virtual spaces where players can participate in games. They are managed through a series of atomic operations that ensure data consistency and reliable gameplay experiences. Don't forget that each operation request requires proper headers (see [Headers](/api-quickstart#base-headers) for header requirements).

## Available Operations

* **Create Game Room**: Initialize a new game room with specific configurations
* **Join Game Room**: Allow players to enter an existing game room
* **Pay Game Room**: Process payments for game room participation
* **Earn Game Room**: Distribute tokens to players from the game room
* **Leave Game Room**: Players can exit the game room
* **End Game Room**: Terminate the game room session

## Operation Flow

### 1. Creating and Joining Game Rooms

You have two options:

#### a) Atomic Operation (Recommended)

* Use `/game/createJoinPay` endpoint
* Single API call that:
  * Creates the game room
  * Joins all players
  * Handles payments
* Ensures data consistency through automatic rollback if any step fails
* Reduces network overhead and complexity

#### b) Separate Operations

1. Create game room
2. Join players individually or in groups
3. Process payments for each participant

### 2. Game Room Management

Once a game room is created:

* **Player Management**
  * Players can join (if game room capacity allows)
  * Players can leave at any time
  * Track player status and participation
* **Token Management**
  * Process initial payments (Pay operation)
  * Distribute rewards (Earn operation)
  * Support multiple tokens per transaction

### 3. Payment Integration

The system supports flexible payment handling:

* **Payment Timing**
  * During game room creation (atomic operation)
  * After game room creation (separate operation)
  * Pre-game or post-game payments
* **Payment Features**
  * Multiple token support
  * Variable amounts per player
* **Token Distribution**
  * Distribute rewards to multiple players
  * Support for different token types
  * Batch distribution capabilities
  * Synchronous or asynchronous processing

## Error Handling

All operations implement robust error handling:

* **Atomic Transactions**
  * Data consistency guaranteed
  * No partial state changes
* **Error Responses**
  * Detailed error messages
  * Error codes for programmatic handling
  * Actionable error resolution steps

## Operation Types

### Synchronous Operations

* Immediate response
* Best for quick operations
* Real-time feedback

### Asynchronous Operations

* Returns task ID
* Status polling available
* Suitable for long-running operations
* Prevents timeout issues

{% hint style="info" %}
Use asynchronous operations for actions that might take longer to complete.
{% endhint %}

## Best Practices

1. **Validation**
   * Verify game room state before operations
   * Validate player eligibility
   * Check payment requirements
   * Ensure sufficient token balances
2. **Error Management**
   * Implement proper error recovery
   * Handle edge cases
   * Log important events
3. **Operation Flow**
   * Use atomic operations when possible
   * Monitor async task status
   * Implement proper retry logic
4. **Security**
   * Always validate authentication
   * Check permissions
   * Protect sensitive data
   * Verify token distributions
5. **Performance**
   * Monitor operation timing
   * Implement rate limiting
   * Cache when appropriate
   * Batch token operations


# Create Game Room

Create a new game room

{% hint style="info" %}
Creates a new game room with specified expiration time.
{% endhint %}

**Endpoint:** `/game/create`\
**Method:** POST

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    expiresIn?: number; // Room expiration time in seconds (default: 86400 - 24 hours)
    sync?: boolean; // When true, returns direct response. When false/undefined, returns a task ID for polling status
}
```

{% endtab %}

{% tab title="Success Response (200)" %}
When sync=false (default):

```typescript
{
    task: {
        id: string; // Task ID for checking status
    }
}
```

When sync=true:

```typescript
{
    roomId: string; // The created room ID
    roomAddress: string; // The room's blockchain address
}
```

{% endtab %}

{% tab title="Error Response (400)" %}

```typescript
{
    error: string;
}
```

{% endtab %}
{% endtabs %}

## Example Usage

```javascript
// Sync=true usage
const timestamp = Date.now().toString();
const body = {
    expiresIn: 3600, // Room will expire in 1 hour
    sync: true // or omit for task-based response
};

const hmac = generateHmacSignature(timestamp, body, secretKey);

const response = await axios.post(apiEndpoint + '/game/create', body, {
    headers: {
        apikey: apiKey,
        signature: hmac,
        timestamp: timestamp
    }
});
```


# Join Game Room

Join players to a game room

{% hint style="info" %}
Adds one or more players to an existing game room using their session JWTs.
{% endhint %}

**Endpoint:** `/game/join`\
**Method:** POST

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    roomId: string; // The ID of the room to join
    sessionJwts: string[]; // Array of session JWTs for players joining the room
    sync?: boolean; // When true, returns direct response. When false/undefined, returns a task ID for polling status
}
```

{% endtab %}

{% tab title="Success Response (200)" %}
When sync=false (default):

```typescript
{
    task: {
        id: string; // Task ID for checking status
    }
}
```

When sync=true:

```typescript
{
    roomId: string;
    plyrIds: string[]; // Array of player IDs that joined
}
```

{% endtab %}

{% tab title="Error Response (400)" %}

```typescript
{
    error: string;
}
```

{% endtab %}
{% endtabs %}

## Example Usage

```javascript
// Task=true usage
const timestamp = Date.now().toString();
const body = {
    roomId: '123',
    sessionJwts: ['jwt1', 'jwt2'], // Can add multiple session JWTs
    sync: true // or omit for task-based response
};

const hmac = generateHmacSignature(timestamp, body, secretKey);

const response = await axios.post(apiEndpoint + '/game/join', body, {
    headers: {
        apikey: apiKey,
        signature: hmac,
        timestamp: timestamp
    }
});
```


# Pay Game Room

Pay tokens to a game room

{% hint style="info" %}
Processes token payments from one or more players to a game room.
{% endhint %}

**Endpoint:** `/game/pay`\
**Method:** POST

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    roomId: string; // The ID of the room to pay to
    sessionJwts: string[]; // Array of session JWTs for players making payments
    tokens: string[]; // Array of token names/symbols
    amounts: number[]; // Array of amounts to pay (corresponding to tokens array)
    sync?: boolean; // When true, returns direct response. When false/undefined, returns a task ID for polling status
}
```

{% endtab %}

{% tab title="Success Response (200)" %}
When sync=false (default):

```typescript
{
    task: {
        id: string; // Task ID for checking status
    }
}
```

When sync=true:

```typescript
{
    // Payment details
}
```

{% endtab %}

{% tab title="Error Response (400)" %}

```typescript
{
    error: string;
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
The arrays \`sessionJwts\`, \`tokens\`, and \`amounts\` must have corresponding lengths.
{% endhint %}

## Example Usage

```javascript
// Sync=true usage
const timestamp = Date.now().toString();
const body = {
    roomId: '123',
    sessionJwts: ['playerJwt1', 'playerJwt1', 'playerJwt2'], // First player paying 2 tokens, second player paying 1
    tokens: ['TOKEN1', 'TOKEN2', 'TOKEN1'], // Token types to pay
    amounts: [100, 50, 75], // Corresponding amounts
    sync: true // or omit for task-based response
};

const hmac = generateHmacSignature(timestamp, body, secretKey);

const response = await axios.post(apiEndpoint + '/game/pay', body, {
    headers: {
        apikey: apiKey,
        signature: hmac,
        timestamp: timestamp
    }
});
```


# Earn Game Room

Distribute tokens from a game room to players

{% hint style="info" %}
Distributes tokens from a game room to one or more players.
{% endhint %}

**Endpoint:** `/game/earn`\
**Method:** POST

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    roomId: string; // The ID of the room to distribute from
    plyrIds: string[]; // Array of player IDs to receive tokens
    tokens: string[]; // Array of token names/symbols
    amounts: number[]; // Array of amounts to distribute (corresponding to tokens array)
    sync?: boolean; // When true, returns direct response. When false/undefined, returns a task ID for polling status
}
```

{% endtab %}

{% tab title="Success Response (200)" %}
When sync=false (default):

```typescript
{
    task: {
        id: string; // Task ID for checking status
    }
}
```

When sync=true:

```typescript
{
    roomId: string;
    distributions: {
        plyrId: string;
        token: string;
        amount: number;
    }
    [];
}
```

{% endtab %}

{% tab title="Error Response (400)" %}

```typescript
{
    error: string;
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
The arrays \`plyrIds\`, \`tokens\`, and \`amounts\` must have corresponding lengths.
{% endhint %}

## Example Usage

```javascript
// Sync=true usage
const timestamp = Date.now().toString();
const body = {
    roomId: 'room123',
    plyrIds: ['player1', 'player2'], // Multiple players can receive tokens
    tokens: ['TOKEN1', 'TOKEN2'], // Different tokens can be distributed
    amounts: [100, 200], // Corresponding amounts for each token
    sync: true // or omit for task-based response
};

const hmac = generateHmacSignature(timestamp, body, secretKey);

const response = await axios.post(apiEndpoint + '/game/earn', body, {
    headers: {
        apikey: apiKey,
        signature: hmac,
        timestamp: timestamp
    }
});
```

{% hint style="info" %}
The arrays \`plyrIds\`, \`tokens\`, and \`amounts\` must have corresponding lengths. For example, if distributing multiple tokens to a single player, repeat the plyrId in the array.
{% endhint %}


# Leave Game Room

Remove players from a game room

{% hint style="info" %}
Removes one or more players from an existing game room using their session JWTs.
{% endhint %}

**Endpoint:** `/game/leave`\
**Method:** POST

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    roomId: string; // The ID of the room to leave
    sessionJwts: string[]; // Array of session JWTs for players leaving the room
    sync?: boolean; // When true, returns direct response. When false/undefined, returns a task ID for polling status
}
```

{% endtab %}

{% tab title="Success Response (200)" %}
When sync=false (default):

```typescript
{
    task: {
        id: string; // Task ID for checking status
    }
}
```

When sync=true:

```typescript
{
    roomId: string;
    plyrIds: string[]; // Array of player IDs that left
}
```

{% endtab %}

{% tab title="Error Response (400)" %}

```typescript
{
    error: string;
}
```

{% endtab %}
{% endtabs %}

## Example Usage

```javascript
// Sync=true usage
const timestamp = Date.now().toString();
const body = {
    roomId: '123',
    sessionJwts: ['playerJwt1', 'playerJwt2'], // Multiple players can leave at once
    sync: true // or omit for task-based response
};

const hmac = generateHmacSignature(timestamp, body, secretKey);

const response = await axios.post(apiEndpoint + '/game/leave', body, {
    headers: {
        apikey: apiKey,
        signature: hmac,
        timestamp: timestamp
    }
});
```


# End Game Room

End a game room session

{% hint style="info" %}
Ends a game room session and cleans up associated resources.
{% endhint %}

**Endpoint:** `/game/end`\
**Method:** POST

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    roomId: string; // The ID of the room to end
    sync?: boolean; // When true, returns direct response. When false/undefined, returns a task ID for polling status
}
```

{% endtab %}

{% tab title="Success Response (200)" %}
When sync=false (default):

```typescript
{
    task: {
        id: string; // Task ID for checking status
    }
}
```

When sync=true:

```typescript
{
    roomId: string; // The ID of the ended room
}
```

{% endtab %}

{% tab title="Error Response (400)" %}

```typescript
{
    error: string;
}
```

{% endtab %}
{% endtabs %}

## Example Usage

```javascript
// Sync=true usage
const timestamp = Date.now().toString();
const body = {
    roomId: '123',
    sync: true // or omit for task-based response
};

const hmac = generateHmacSignature(timestamp, body, secretKey);

const response = await axios.post(apiEndpoint + '/game/end', body, {
    headers: {
        apikey: apiKey,
        signature: hmac,
        timestamp: timestamp
    }
});
```


# Helpers

Helper endpoints for game room operations

This section contains helper endpoints that combine multiple game room operations for convenience.

## Helpers

### Is Joined Game Room

Checks if a player is currently joined to a game room. [View Details](/api-reference/game-room/helpers/is-joined-game-room)

### Join and Pay

Handles player joining and payment processing together. [View Details](/api-reference/game-room/helpers/join-pay)

### Earn and Leave

Processes earnings and player leaving in a single call. [View Details](/api-reference/game-room/helpers/earn-leave)

### Create, Join and Pay

Combines room creation, player joining, and payment processing in one call. [View Details](/api-reference/game-room/helpers/create-join-pay)

### Earn, Leave and End

Handles earning distribution, player leaving, and room end in one operation. [View Details](/api-reference/game-room/helpers/earn-leave-end)


# Is Joined Game Room

Check if a player has joined a game room

{% hint style="info" %}
Checks if a specific player has joined a game room.
{% endhint %}

**Endpoint:** `/game/isJoined`\
**Method:** GET

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    roomId: string; // The ID of the room to check
    plyrId: string; // The player ID to check
}
```

{% endtab %}

{% tab title="Success Response (200)" %}

```typescript
{
    isJoined: boolean; // true if player has joined the room, false otherwise
}
```

{% endtab %}

{% tab title="Error Response (400)" %}

```typescript
{
    error: string;
}
```

{% endtab %}
{% endtabs %}

## Example Usage

```javascript
const timestamp = Date.now().toString();
const hmac = generateHmacSignature(timestamp, {}, secretKey);

const response = await axios.get(apiEndpoint + '/game/isJoined?roomId=' + roomId + '&plyrId=' + plyrId, {
    headers: {
        apikey: apiKey,
        signature: hmac,
        timestamp: timestamp
    }
});

const isJoined = response.data.data.isJoined;
```


# Join and Pay

Join a game room and pay tokens in a single operation

{% hint style="info" %}
Combines joining a game room and paying tokens into a single atomic operation.
{% endhint %}

**Endpoint:** `/game/joinPay`\
**Method:** POST

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    gameId: string; // The game ID
    roomId: string; // The ID of the room to join and pay to
    sessionJwts: string[]; // Array of session JWTs for players joining and paying
    tokens: string[]; // Array of token names/symbols
    amounts: number[]; // Array of amounts to pay (corresponding to tokens array)
    sync?: boolean; // When true, returns direct response. When false/undefined, returns a task ID for polling status
}
```

{% endtab %}

{% tab title="Success Response (200)" %}
When sync=false (default):

```typescript
{
    task: {
        id: string; // Task ID for checking status
    }
}
```

When sync=true:

```typescript
{
        roomId: string;
        plyrIds: string[]; // Array of player IDs that joined
        payments: {
            plyrId: string;
            token: string;
            amount: number;
        }[];
}
```

{% endtab %}

{% tab title="Error Response (400)" %}

```typescript
{
    error: string;
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
The arrays \`sessionJwts\`, \`tokens\`, and \`amounts\` must have corresponding lengths. The operation is atomic - if either joining or paying fails, the entire operation is rolled back.
{% endhint %}

## Example Usage

```javascript
// Sync=true usage
const timestamp = Date.now().toString();
const body = {
    gameId: 'game_xyz',
    roomId: '123',
    sessionJwts: ['playerJwt1', 'playerJwt2'],
    tokens: ['TOKEN1', 'TOKEN2'],
    amounts: [100, 50],
    sync: true // or omit for task-based response
};

const hmac = generateHmacSignature(timestamp, body, secretKey);

const response = await axios.post(apiEndpoint + '/game/joinPay', body, {
    headers: {
        apikey: apiKey,
        signature: hmac,
        timestamp: timestamp
    }
});
```


# Earn and Leave

Distribute tokens and remove players from a game room in a single operation

{% hint style="info" %}
Combines distributing tokens to players and removing them from a game room into a single atomic operation.
{% endhint %}

**Endpoint:** `/game/earnLeave`\
**Method:** POST

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    roomId: string; // The ID of the room
    plyrIds: string[]; // Array of player IDs to receive tokens and leave
    tokens: string[]; // Array of token names/symbols
    amounts: number[]; // Array of amounts to distribute (corresponding to tokens array)
    sync?: boolean; // When true, returns direct response. When false/undefined, returns a task ID for polling status
}
```

{% endtab %}

{% tab title="Success Response (200)" %}
When sync=false (default):

```typescript
{
    task: {
        id: string; // Task ID for checking status
    }
}
```

When sync=true:

```typescript
{
        roomId: string;
        plyrIds: string[]; // Array of player IDs that received tokens and left
        distributions: {
            plyrId: string;
            token: string;
            amount: number;
        }[];
}
```

{% endtab %}

{% tab title="Error Response (400)" %}

```typescript
{
    error: string;
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
The arrays \`plyrIds\`, \`tokens\`, and \`amounts\` must have corresponding lengths. The operation is atomic - if either earning or leaving fails, the entire operation is rolled back.
{% endhint %}

## Example Usage

```javascript
// Sync=true usage
const timestamp = Date.now().toString();
const body = {
    roomId: '123',
    plyrIds: ['player1', 'player1', 'player2'], // First player receiving 2 tokens, second player receiving 1
    tokens: ['TOKEN1', 'TOKEN2', 'TOKEN1'], // Token types to distribute
    amounts: [100, 50, 75], // Corresponding amounts
    sync: true // or omit for task-based response
};

const hmac = generateHmacSignature(timestamp, body, secretKey);

const response = await axios.post(apiEndpoint + '/game/earnLeave', body, {
    headers: {
        apikey: apiKey,
        signature: hmac,
        timestamp: timestamp
    }
});
```


# Create, Join and Pay

Create a game room, join players, and process payments in a single operation

{% hint style="info" %}
Combines creating a game room, joining players, and processing payments into a single atomic operation.
{% endhint %}

**Endpoint:** `/game/createJoinPay`\
**Method:** POST

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    sessionJwts: string[]; // Array of session JWTs for players to join and pay
    tokens: string[]; // Array of token names/symbols
    amounts: number[]; // Array of amounts to pay (corresponding to tokens array)
    sync?: boolean; // When true, returns direct response. When false/undefined, returns a task ID for polling status
}
```

{% endtab %}

{% tab title="Success Response (200)" %}
When sync=false (default):

```typescript
{
    task: {
        id: string; // Task ID for checking status
    }
}
```

When sync=true:

```typescript
{
    roomId: string; // The created room ID
    plyrIds: string[]; // Array of player IDs that joined
    payments: {
        plyrId: string;
        token: string;
        amount: number;
    }[];
}
```

{% endtab %}

{% tab title="Error Response (400)" %}

```typescript
{
    error: string;
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
The arrays \`sessionJwts\`, \`tokens\`, and \`amounts\` must have corresponding lengths. The operation is atomic - if any step (create, join, or pay) fails, the entire operation is rolled back.
{% endhint %}

## Example Usage

```javascript
// Sync=true usage
const timestamp = Date.now().toString();
const body = {
    sessionJwts: ['jwt1', 'jwt2'], // Multiple players can join and pay
    tokens: ['TOKEN1', 'TOKEN2'], // Different tokens can be paid
    amounts: [100, 200], // Corresponding amounts for each token
    sync: true // or omit for task-based response
};

const hmac = generateHmacSignature(timestamp, body, secretKey);

const response = await axios.post(apiEndpoint + '/game/createJoinPay', body, {
    headers: {
        apikey: apiKey,
        signature: hmac,
        timestamp: timestamp
    }
});
```

{% hint style="info" %}
The arrays \`sessionJwts\`, \`tokens\`, and \`amounts\` must have corresponding lengths. The operation is atomic - if any step (create, join, or pay) fails, the entire operation is rolled back.
{% endhint %}


# Earn, Leave and End

Distribute tokens, remove players, and end a game room in a single operation

{% hint style="info" %}
Combines distributing tokens to players, removing them from a game room, and ending the room into a single atomic operation.
{% endhint %}

**Endpoint:** `/game/earnLeaveEnd`\
**Method:** POST

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    roomId: string; // The ID of the room
    plyrIds: string[]; // Array of player IDs to receive tokens and leave
    tokens: string[]; // Array of token names/symbols
    amounts: number[]; // Array of amounts to distribute (corresponding to tokens array)
    sync?: boolean; // When true, returns direct response. When false/undefined, returns a task ID for polling status
}
```

{% endtab %}

{% tab title="Success Response (200)" %}
When sync=false (default):

```typescript
{
    task: {
        id: string; // Task ID for checking status
    }
}
```

When sync=true:

```typescript
{
    roomId: string; // The room that was processed
    plyrIds: string[]; // Array of player IDs that received tokens and left
    distributions: {
        plyrId: string;
        token: string;
        amount: number;
    }[];
}
```

{% endtab %}

{% tab title="Error Response (400)" %}

```typescript
{
    error: string;
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
The arrays \`plyrIds\`, \`tokens\`, and \`amounts\` must have corresponding lengths. The operation is atomic - if any step (earn, leave, or end) fails, the entire operation is rolled back.
{% endhint %}

{% hint style="warning" %}
This operation will end the game room, making it unavailable for further operations. Use this when you want to finalize all game room activities.
{% endhint %}

## Example Usage

```javascript
// Sync=true usage
const timestamp = Date.now().toString();
const body = {
    roomId: '123',
    plyrIds: ['player1', 'player1', 'player2'], // First player receiving 2 tokens, second player receiving 1
    tokens: ['TOKEN1', 'TOKEN2', 'TOKEN1'], // Token types to distribute
    amounts: [100, 50, 75], // Corresponding amounts
    sync: true // or omit for task-based response
};

const hmac = generateHmacSignature(timestamp, body, secretKey);

const response = await axios.post(apiEndpoint + '/game/earnLeaveEnd', body, {
    headers: {
        apikey: apiKey,
        signature: hmac,
        timestamp: timestamp
    }
});
```


# Assets


# Tokens ( ERC-20 )

## Standard Token Operations

* [Get PLYR L1 Token List](/api-reference/assets/tokens-erc-20/get-plyr-l1-token-list)
* [Get User Token Balance](/api-reference/assets/tokens-erc-20/get-user-token-balance)
* [Get User Token Allowance](/api-reference/assets/tokens-erc-20/get-user-token-allowance)
* [Approve User Token Spending](/api-reference/assets/tokens-erc-20/approve-user-token-spending)
* [Revoke User Token Allowance](/api-reference/assets/tokens-erc-20/revoke-user-token-allowance)

## In-Game Chips

In-Game Chips are specialized ERC-20 tokens that can be used within games on the PLYR platform. For more information, see the [In-Game Chips Overview](/api-reference/assets/tokens-erc-20/in-game-chips-overview).

* [Create Chip](/api-reference/assets/tokens-erc-20/in-game-chips-overview/create-chip)
* [Mint Chip](/api-reference/assets/tokens-erc-20/in-game-chips-overview/mint-chip)
* [Burn Chip](/api-reference/assets/tokens-erc-20/in-game-chips-overview/burn-chip)
* [Transfer Chip](/api-reference/assets/tokens-erc-20/in-game-chips-overview/transfer-chip)
* [Get Chip Balance](/api-reference/assets/tokens-erc-20/in-game-chips-overview/get-chip-balance)
* [Get Chip Info](/api-reference/assets/tokens-erc-20/in-game-chips-overview/get-chip-info)


# Get PLYR L1 Token List

Get list of available PLYR L1 tokens and their details including prices and metadata

{% hint style="info" %}
Retrieve the list of available PLYR L1 tokens with detailed information including prices, metadata, and chain information.
{% endhint %}

**Endpoint:** `/tokenlist`\
**Method:** GET

{% tabs %}
{% tab title="Success Response (200)" %}

```typescript
{
    name: string,
    timestamp: string,
    version: {
      major: number,
      minor: number,
      patch: number
    },
    tokens: Array<{
      chainId: number,
      address: string,
      name: string,
      symbol: string,
      decimals: number,
      logoURI: string,
      apiId: string,
      cmcURL: string,
      cmcId: string,
      cgURL: string,
      cgId: string,
      website: string,
      category: string,
      shortDescription: string,
      nativeChainId: number,
      nativeChainName: string,
      nativeChainLogoURI: string,
      nativeContractAddress: string,
      isGameStake: boolean,
      price: number,
      updatedAt: string,
      nextUpdatedAt: string
    }>
 }
```

{% endtab %}

{% tab title="Error Response (404)" %}

```typescript
{
    error: string;
}
```

{% endtab %}
{% endtabs %}

### Response Fields Description

* `name`: Name of the token list
* `timestamp`: Last update timestamp
* `version`: Semantic version of the token list
* `tokens`: Array of token objects with the following properties:
  * `chainId`: ID of the blockchain network
  * `address`: Token contract address
  * `name`: Token name
  * `symbol`: Token symbol
  * `decimals`: Number of decimal places
  * `logoURI`: URL to token's logo image
  * `apiId`: Unique identifier for the token in the API
  * `cmcURL`: CoinMarketCap URL
  * `cmcId`: CoinMarketCap ID
  * `cgURL`: CoinGecko URL
  * `cgId`: CoinGecko ID
  * `website`: Official token website
  * `category`: Token category
  * `shortDescription`: Brief description of the token
  * `nativeChainId`: ID of the token's native blockchain
  * `nativeChainName`: Name of the token's native blockchain
  * `nativeChainLogoURI`: URL to native chain's logo
  * `nativeContractAddress`: Token's contract address on its native chain
  * `isGameStake`: Whether the token can be used for game staking
  * `price`: Current token price in USD
  * `updatedAt`: Last price update timestamp
  * `nextUpdatedAt`: Next scheduled price update timestamp


# Get User Token Balance

Get user balance endpoint

{% hint style="info" %}
Retrieve token balance for a user. Can query by PLYR ID or primary wallet address.
{% endhint %}

**Endpoint:** `/user/balance/{identifier}/{tokenName?}`\
**Method:** GET

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    identifier: string;  // PLYR ID or primary wallet address
    tokenName?: string; // Optional token name filter
}
```

{% endtab %}

{% tab title="Success Response (200)" %}

```typescript
{
  balances: {
      [tokenName: string]: string // Map of token name to balance
    }
 }
```

{% endtab %}

{% tab title="Error Response (404)" %}

```typescript
{
  error: "User not found",
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
If no token name is provided, the endpoint returns balances for all tokens the user holds.
{% endhint %}

## Example Usage

```javascript
const timestamp = Date.now().toString();
// Can use either PLYR ID or wallet address
const identifier = 'player123'; // or '0x742d35Cc6634C0532925a3b844Bc454e4438f44e'
const tokenName = 'TOKEN1'; // Optional: specific token to query

// Since this is a GET request with no body, pass null as the body for HMAC
const hmac = generateHmacSignature(timestamp, null, secretKey);

// Build URL based on whether tokenName is provided
const url = `/user/balance/${identifier}/${tokenName}`;

const response = await axios.get(apiEndpoint + url, {
    headers: {
        apikey: apiKey,
        signature: hmac,
        timestamp: timestamp
    }
});

// Response will contain token balances
const { balances } = response.data;

// Process balances
Object.entries(balances).forEach(([tokenName, balance]) => {
    console.log(`Balance for ${tokenName}:`, balance);
    // Use balances in your application
});
```


# Get User Token Allowance

Get user token allowance for a game

{% hint style="info" %}
Retrieves the current token allowance for a player in a specific game.
{% endhint %}

**Endpoint:** `/game/allowance/{plyrId}/{gameId}/{token}`\
**Method:** GET

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    plyrId: string; // The player ID
    gameId: string; // The game ID
    token: string; // Token name/symbol
}
```

{% endtab %}

{% tab title="Success Response (200)" %}

```typescript
{
    allowance: string; // Current token allowance amount
    expiresAt: string; // ISO timestamp when the allowance expires
}
```

{% endtab %}

{% tab title="Error Response (400)" %}

```typescript
{
    error: string;
}
```

{% endtab %}
{% endtabs %}

## Example Usage

```javascript
const timestamp = Date.now().toString();
const hmac = generateHmacSignature(timestamp, {}, secretKey);

const response = await axios.get(apiEndpoint + '/game/allowance/' + plyrId + '/' + gameId + '/' + tokenName, {
    headers: {
        apikey: apiKey,
        signature: hmac,
        timestamp: timestamp
    }
});

const allowance = response.data.data.allowance;
const expiresAt = response.data.data.expiresAt;
```


# Approve User Token Spending

Approve user token spending for a game

{% hint style="info" %}
Approves a specific amount of tokens for use in a game.
{% endhint %}

**Endpoint:** `/game/approve`\
**Method:** POST

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    plyrId: string; // The player ID
    gameId: string; // The game ID
    otp: string; // One-time password for authorization
    token: string; // Token name/symbol
    amount: number; // Amount to approve
    expiresIn: number; // Approval expiration time in seconds
}
```

{% endtab %}

{% tab title="Success Response (200)" %}

```typescript
{
    // Approval details
}
```

{% endtab %}

{% tab title="Error Response (400)" %}

```typescript
{
    error: string;
}
```

{% endtab %}
{% endtabs %}

## Example Usage

```javascript
// Setup request parameters
const timestamp = Date.now().toString();
const body = {
    plyrId: 'player_abc123', // The player's ID
    gameId: 'game_xyz789', // The game's ID
    otp: '123456', // One-time password
    token: 'USDC', // Token to approve
    amount: 1000, // Amount to approve (in token's smallest unit)
    expiresIn: 3600 // Approval expires in 1 hour
};

// Generate HMAC signature
const hmac = generateHmacSignature(timestamp, body, secretKey);

// Make the API request
const response = await axios.post(apiEndpoint + '/game/approve', body, {
    headers: {
        apikey: apiKey,
        signature: hmac,
        timestamp: timestamp
    }
});
```


# Revoke User Token Allowance

Revoke user token allowance for a game

{% hint style="info" %}
Revokes a previously granted token allowance for a game.
{% endhint %}

**Endpoint:** `/game/revoke`\
**Method:** POST

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    plyrId: string; // The player ID
    gameId: string; // The game ID
    token: string; // Token name/symbol to revoke
    otp: string; // One-time password for authorization
}
```

{% endtab %}

{% tab title="Success Response (200)" %}

```typescript
{
    // Revocation details
}
```

{% endtab %}

{% tab title="Error Response (400)" %}

```typescript
{
    error: string;
}
```

{% endtab %}
{% endtabs %}

## Example Usage

```javascript
// Setup request parameters
const timestamp = Date.now().toString();
const body = {
    plyrId: 'player_abc123', // The player's ID
    gameId: 'game_xyz789', // The game's ID
    token: 'USDC', // Token to revoke
    otp: '123456' // One-time password
};

// Generate HMAC signature
const hmac = generateHmacSignature(timestamp, body, secretKey);

// Make the API request
const response = await axios.post(apiEndpoint + '/game/revoke', body, {
    headers: {
        apikey: apiKey,
        signature: hmac,
        timestamp: timestamp
    }
});
```


# In-Game Chips

In-Game Chips API Overview

{% hint style="info" %}
In-Game Chips are tokens that can be created, minted, burned, and transferred within games on the PLYR platform.
{% endhint %}

## Overview

In-Game Chips provide a flexible token system for game developers to create and manage in-game currencies or tokens. These tokens exist within the PLYR ecosystem and can be used for various in-game economies.

## Available Operations

* [Create Chip](/api-reference/assets/tokens-erc-20/in-game-chips-overview/create-chip) - Create a new in-game chip type
* [Mint Chip](/api-reference/assets/tokens-erc-20/in-game-chips-overview/mint-chip) - Mint (create) chips for a user
* [Burn Chip](/api-reference/assets/tokens-erc-20/in-game-chips-overview/burn-chip) - Burn (destroy) chips from a user
* [Transfer Chip](/api-reference/assets/tokens-erc-20/in-game-chips-overview/transfer-chip) - Transfer chips between users
* [Get Chip Balance](/api-reference/assets/tokens-erc-20/in-game-chips-overview/get-chip-balance) - Get a user's balance for a specific chip
* [Get Chip Info](/api-reference/assets/tokens-erc-20/in-game-chips-overview/get-chip-info) - Get information about chips for a game


# Create Chip

Create a new in-game chip

{% hint style="info" %}
Creates a new in-game chip with the specified name, symbol, and optional image.
{% endhint %}

**Endpoint:** `/game/chip/create`\
**Method:** POST

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    name: string;    // The name of the chip
    symbol: string;  // The symbol for the chip
    image?: string;  // Optional URL to the chip's image
}
```

{% endtab %}

{% tab title="Success Response" %}

```typescript
{
	taskId: string;
	data: {
		chip: string; // The address of the created chip
	}
	status: string;
}
```

{% endtab %}

{% tab title="Error Response" %}

```typescript
{
  error: string;
  details?: any;
}
```

{% endtab %}
{% endtabs %}

## Example Usage

```javascript
// Setup request parameters
const timestamp = Date.now().toString();
const body = {
	name: 'Gold Coin',
	symbol: 'GOLD',
	image: 'https://example.com/gold-coin.png'
};

// Generate HMAC signature
const hmac = generateHmacSignature(timestamp, body, secretKey);

// Make the API request
const response = await axios.post(apiEndpoint + '/game/chip/create', body, {
	headers: {
		apikey: apiKey,
		signature: hmac,
		timestamp: timestamp
	}
});

// Process the response
console.log('Chip Creation Task ID:', response.data.taskId);
console.log('Created Chip Address:', response.data.data.chip);
```


# Mint Chip

Mint in-game chips for a user

{% hint style="info" %}
Mints (creates) a specified amount of in-game chips for a user.
{% endhint %}

**Endpoint:** `/game/chip/mint`\
**Method:** POST

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    chips: string[];    // Array of chip token addresses
    plyrIds: string[];  // Array of PLYR IDs to mint chips for
    amounts: number[];  // Array of amounts to mint
}
```

{% endtab %}

{% tab title="Success Response" %}

```typescript
{
	taskId: string;
	data: {
		transactionHash: string; // The hash of the mint transaction
	}
	status: string;
}
```

{% endtab %}

{% tab title="Error Response" %}

```typescript
{
  error: string;
  details?: any;
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
The \`chips\`, \`plyrIds\`, and \`amounts\` arrays must have the same length. Each index represents a mint operation.
{% endhint %}

## Example Usage

```javascript
// Setup request parameters
const timestamp = Date.now().toString();
const body = {
	chips: ['0x1234567890123456789012345678901234567890'], // Array of chip token addresses
	plyrIds: ['player123'], // Array of PLYR IDs to mint chips for
	amounts: [100] // Array of amounts to mint
};

// Generate HMAC signature
const hmac = generateHmacSignature(timestamp, body, secretKey);

// Make the API request
const response = await axios.post('/game/chip/mint', body, {
	headers: {
		apikey: apiKey,
		signature: hmac,
		timestamp: timestamp
	}
});

// Process the response
console.log('Mint Task ID:', response.data.taskId);
console.log('Transaction Hash:', response.data.data.transactionHash);
```


# Burn Chip

Burn in-game chips from a user

{% hint style="info" %}
Burns (destroys) a specified amount of in-game chips from a user.
{% endhint %}

**Endpoint:** `/game/chip/burn`\
**Method:** POST

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    chips: string[];    // Array of chip token addresses
    plyrIds: string[];  // Array of PLYR IDs to burn chips from
    amounts: number[];  // Array of amounts to burn
}
```

{% endtab %}

{% tab title="Success Response" %}

```typescript
{
	taskId: string;
	data: {
		transactionHash: string; // The hash of the burn transaction
	}
	status: string;
}
```

{% endtab %}

{% tab title="Error Response" %}

```typescript
{
  error: string;
  details?: any;
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
The \`chips\`, \`plyrIds\`, and \`amounts\` arrays must have the same length. Each index represents a burn operation.
{% endhint %}

## Example Usage

```javascript
// Setup request parameters
const timestamp = Date.now().toString();
const body = {
	chips: ['0x1234567890123456789012345678901234567890'], // Array of chip token addresses
	plyrIds: ['player123'], // Array of PLYR IDs to burn chips from
	amounts: [50] // Array of amounts to burn
};

// Generate HMAC signature
const hmac = generateHmacSignature(timestamp, body, secretKey);

// Make the API request
const response = await axios.post(apiEndpoint + '/game/chip/burn', body, {
	headers: {
		apikey: apiKey,
		signature: hmac,
		timestamp: timestamp
	}
});

// Process the response
console.log('Burn Task ID:', response.data.taskId);
console.log('Transaction Hash:', response.data.data.transactionHash);
```


# Transfer Chip

Transfer in-game chips between users

{% hint style="info" %}
Transfers a specified amount of in-game chips from one user to another.
{% endhint %}

**Endpoint:** `/game/chip/transfer`\
**Method:** POST

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    chips: string[];          // Array of chip token addresses
    plyrIds: string[];        // Array of PLYR IDs (for backward compatibility)
    fromPlyrIds: string[];    // Array of source PLYR IDs
    toPlyrIds: string[];      // Array of destination PLYR IDs
    amounts: number[];        // Array of amounts to transfer
}
```

{% endtab %}

{% tab title="Success Response" %}

```typescript
{
	taskId: string;
	data: {
		transactionHash: string; // The hash of the transfer transaction
	}
	status: string;
}
```

{% endtab %}

{% tab title="Error Response" %}

```typescript
{
  error: string;
  details?: any;
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
The \`chips\`, \`fromPlyrIds\`, \`toPlyrIds\`, and \`amounts\` arrays must have the same length. Each index represents a transfer operation.
{% endhint %}

## Example Usage

```javascript
// Setup request parameters
const timestamp = Date.now().toString();
const body = {
	chips: ['0x1234567890123456789012345678901234567890'], // Array of chip token addresses
	plyrIds: ['player123'], // Array of PLYR IDs (for backward compatibility)
	fromPlyrIds: ['player123'], // Array of source PLYR IDs
	toPlyrIds: ['player456'], // Array of destination PLYR IDs
	amounts: [25] // Array of amounts to transfer
};

// Generate HMAC signature
const hmac = generateHmacSignature(timestamp, body, secretKey);

// Make the API request
const response = await axios.post(apiEndpoint + '/game/chip/transfer', body, {
	headers: {
		apikey: apiKey,
		signature: hmac,
		timestamp: timestamp
	}
});

// Process the response
console.log('Transfer Task ID:', response.data.taskId);
console.log('Transaction Hash:', response.data.data.transactionHash);
```


# Get Chip Balance

Get a user's in-game chip balance

{% hint style="info" %}
Retrieves the balance of a specific in-game chip for a user.
{% endhint %}

**Endpoint:** `/game/chip/balance`\
**Method:** GET

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
	plyrId: string; // The PLYR ID of the user
	chip: string; // The address of the chip token
}
```

{% endtab %}

{% tab title="Success Response" %}

```typescript
{
	balance: string; // The user's balance of the chip token (as a string)
}
```

{% endtab %}

{% tab title="Error Response" %}

```typescript
{
  error: string;
  details?: any;
}
```

{% endtab %}
{% endtabs %}

## Example Usage

```javascript
// Setup request parameters
const timestamp = Date.now().toString();
const plyrId = 'player123';
const tokenAddress = '0x1234567890123456789012345678901234567890';

// For GET requests with no body, pass null as the body for HMAC
const hmac = generateHmacSignature(timestamp, null, secretKey);

// Make the API request
const response = await axios.get(apiEndpoint + `/game/chip/balance?plyrId=${plyrId}&chip=${tokenAddress}`, {
	headers: {
		apikey: apiKey,
		signature: hmac,
		timestamp: timestamp
	}
});

// Process the response
console.log(`User's chip balance: ${response.data.balance}`);
```


# Get Chip Info

Get information about in-game chips for a game

{% hint style="info" %}
Retrieves information about in-game chips associated with a specific game.
{% endhint %}

**Endpoint:** `/game/chip/info`\
**Method:** GET

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
	gameId: string; // The ID of the game
}
```

{% endtab %}

{% tab title="Success Response" %}

```typescript
{
  chips: {
    address: string;     // The address of the chip token
    name: string;        // The name of the chip
    symbol: string;      // The symbol of the chip
    image?: string;      // Optional URL to the chip's image
  }[];
}
```

{% endtab %}

{% tab title="Error Response" %}

```typescript
{
  error: string;
  details?: any;
}
```

{% endtab %}
{% endtabs %}

## Example Usage

```javascript
// Setup request parameters
const timestamp = Date.now().toString();
const gameId = 'game123';

// For GET requests with no body, pass null as the body for HMAC
const hmac = generateHmacSignature(timestamp, null, secretKey);

// Make the API request
const response = await axios.get(apiEndpoint + `/game/chip/info?gameId=${gameId}`, {
	headers: {
		apikey: apiKey,
		signature: hmac,
		timestamp: timestamp
	}
});

// Process the response
response.data.chips.forEach((chip) => {
	console.log(`Chip Name: ${chip.name}`);
	console.log(`Chip Symbol: ${chip.symbol}`);
	console.log(`Chip Address: ${chip.address}`);
	if (chip.image) {
		console.log(`Chip Image: ${chip.image}`);
	}
	console.log('---');
});
```


# NFTs ( ERC-721 )

## Overview

The NFT API provides a comprehensive set of functions for creating and managing ERC-721 tokens (NFTs) within the PLYR ecosystem. These operations allow games to create unique digital assets that can be owned, traded, and used by players.

* [Create NFT](/api-reference/assets/nfts-erc-721/create-nft) - Create a new NFT contract
* [Mint NFT](/api-reference/assets/nfts-erc-721/mint-nft) - Mint a new NFT to a recipient
* [Transfer NFT](/api-reference/assets/nfts-erc-721/transfer-nft) - Transfer an NFT between addresses
* [Burn NFT](/api-reference/assets/nfts-erc-721/burn-nft) - Burn (destroy) an NFT
* [Get NFT Balance](/api-reference/assets/nfts-erc-721/get-nft-balance) - Get a user's NFT balance
* [List NFTs](/api-reference/assets/nfts-erc-721/list-nfts) - List NFTs owned by a user
* [Check NFT Holding](/api-reference/assets/nfts-erc-721/check-nft-holding) - Check if a user is holding a specific NFT
* [Get NFT Credit](/api-reference/assets/nfts-erc-721/get-nft-credit) - Get NFT credit information
* [Get NFT Info](/api-reference/assets/nfts-erc-721/get-nft-info) - Get information about NFTs
* [Get Zoo Genes](/api-reference/assets/nfts-erc-721/get-zoo-genes) - Get ZooGenes NFTs for a user

## Official PLYR NFTs

* [Official PLYR NFTs](/api-reference/assets/nfts-erc-721/official-plyr-nfts)
  * [Get User Zoo Genes](/api-reference/assets/nfts-erc-721/official-plyr-nfts/get-user-zoogenes)
  * [Get User Zoo Boosters](/api-reference/assets/nfts-erc-721/official-plyr-nfts/get-user-zoo-boosters)
  * [Get User Zoo Elixirs](/api-reference/assets/nfts-erc-721/official-plyr-nfts/get-user-zoo-elixirs)


# Create NFT

Create a new NFT contract

{% hint style="info" %}
Creates a new NFT contract with the specified name, symbol, and optional image.
{% endhint %}

**Endpoint:** `/game/nft/create`\
**Method:** POST

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    name: string;       // The name of the NFT contract
    symbol: string;     // The symbol for the NFT contract
    chainId?: string;   // Optional chain ID
    image?: string;     // Optional URL to the collection image
}
```

{% endtab %}

{% tab title="Success Response" %}

```typescript
{
	taskId: string;
	data: {
		nft: string; // The contract address of the created NFT
	}
	status: string;
}
```

{% endtab %}

{% tab title="Error Response" %}

```typescript
{
  error: string;
  details?: any;
}
```

{% endtab %}
{% endtabs %}

## Example Usage

```javascript
// Setup request parameters
const timestamp = Date.now().toString();
const body = {
	name: 'My Game Items',
	symbol: 'GITM',
	chainId: '43114', // Avalanche C-Chain
	image: 'https://google.com' // Optional image URL
};

// Generate HMAC signature
const hmac = generateHmacSignature(timestamp, body, secretKey);

// Make the API request
const response = await axios.post(apiEndpoint + '/game/nft/create', body, {
	headers: {
		apikey: apiKey,
		signature: hmac,
		timestamp: timestamp
	}
});

// Process the response
console.log('NFT Creation Task ID:', response.data.taskId);
console.log('Created NFT Contract Address:', response.data.data.nft);
```


# Mint NFT

Mint a new NFT to a recipient

{% hint style="info" %}
Mints a new NFT to a specified recipient address with associated metadata.
{% endhint %}

**Endpoint:** `/game/nft/mint`\
**Method:** POST

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    nfts: string[];           // Array of NFT contract addresses
    addresses: string[];      // Array of recipient addresses
    metaJsons: object[];      // Array of metadata JSON objects for each NFT
    chainId?: string;         // Optional chain ID (defaults to configured MINT_NFT_CHAIN_ID)
}
```

{% endtab %}

{% tab title="Success Response" %}

```typescript
{
	taskId: string;
	data: {
		transactionHash: string; // The hash of the mint transaction
		tokenId: string; // The ID of the minted token
	}
	status: string;
}
```

{% endtab %}

{% tab title="Error Response" %}

```typescript
{
  error: string;
  details?: any;
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
The \`nfts\`, \`addresses\`, and \`metaJsons\` arrays must have the same length. Each index represents a mint operation.
{% endhint %}

## Example Usage

```javascript
// Setup request parameters
const timestamp = Date.now().toString();
const body = {
	nfts: ['0x1234567890123456789012345678901234567890'], // NFT contract address
	addresses: ['0xabcdef1234567890abcdef1234567890abcdef'], // Recipient address
	metaJsons: [
		{
			name: 'Rare Sword',
			description: 'A powerful sword with magical properties',
			image: 'https://example.com/sword.png',
			attributes: [
				{ trait_type: 'Rarity', value: 'Rare' },
				{ trait_type: 'Damage', value: 50 },
				{ trait_type: 'Element', value: 'Fire' }
			]
		}
	],
	chainId: '43114' // Avalanche C-Chain
};

// Generate HMAC signature
const hmac = generateHmacSignature(timestamp, body, secretKey);

// Make the API request
const response = await axios.post(apiEndpoint + '/game/nft/mint', body, {
	headers: {
		apikey: apiKey,
		signature: hmac,
		timestamp: timestamp
	}
});

// Process the response
console.log('Mint Task ID:', response.data.taskId);
console.log('Transaction Hash:', response.data.data.transactionHash);
console.log('Token ID:', response.data.data.tokenId);
```


# Transfer NFT

Transfer an NFT between addresses

{% hint style="info" %}
Transfers an NFT from one address to another.
{% endhint %}

**Endpoint:** `/game/nft/transfer`\
**Method:** POST

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    nfts: string[];             // Array of NFT contract addresses
    fromAddresses: string[];    // Array of source addresses
    toAddresses: string[];      // Array of destination addresses
    tokenIds: string[];         // Array of token IDs to transfer
    chainId?: string;           // Optional chain ID
}
```

{% endtab %}

{% tab title="Success Response" %}

```typescript
{
	taskId: string;
	data: {
		transactionHash: string; // The hash of the transfer transaction
	}
	status: string;
}
```

{% endtab %}

{% tab title="Error Response" %}

```typescript
{
  error: string;
  details?: any;
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
The \`nfts\`, \`fromAddresses\`, \`toAddresses\`, and \`tokenIds\` arrays must have the same length. Each index represents a transfer operation.
{% endhint %}

## Example Usage

```javascript
// Setup request parameters
const timestamp = Date.now().toString();
const body = {
	nfts: ['0x1234567890123456789012345678901234567890'], // NFT contract address
	fromAddresses: ['0xabcdef1234567890abcdef1234567890abcdef'], // Source address
	toAddresses: ['0x0987654321098765432109876543210987654321'], // Destination address
	tokenIds: ['123'], // Token ID to transfer
	chainId: '43114' // Avalanche C-Chain
};

// Generate HMAC signature
const hmac = generateHmacSignature(timestamp, body, secretKey);

// Make the API request
const response = await axios.post(apiEndpoint + '/game/nft/transfer', body, {
	headers: {
		apikey: apiKey,
		signature: hmac,
		timestamp: timestamp
	}
});

// Process the response
console.log('Transfer Task ID:', response.data.taskId);
console.log('Transaction Hash:', response.data.data.transactionHash);
```


# Burn NFT

Burn (destroy) an NFT

{% hint style="info" %}
Burns (destroys) an NFT, removing it from circulation permanently.
{% endhint %}

**Endpoint:** `/game/nft/burn`\
**Method:** POST

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    nfts: string[];            // Array of NFT contract addresses
    tokenIds: string[];        // Array of token IDs to burn
    chainId?: string;          // Optional chain ID
}
```

{% endtab %}

{% tab title="Success Response" %}

```typescript
{
	taskId: string;
	data: {
		transactionHash: string; // The hash of the burn transaction
	}
	status: string;
}
```

{% endtab %}

{% tab title="Error Response" %}

```typescript
{
  error: string;
  details?: any;
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
The \`nfts\` and \`tokenIds\` arrays must have the same length. Each index represents a burn operation.
{% endhint %}

## Example Usage

```javascript
// Setup request parameters
const timestamp = Date.now().toString();
const body = {
	nfts: ['0x1234567890123456789012345678901234567890'], // NFT contract address
	tokenIds: ['123'], // Token ID to burn
	chainId: '43114' // Avalanche C-Chain
};

// Generate HMAC signature
const hmac = generateHmacSignature(timestamp, body, secretKey);

// Make the API request
const response = await axios.post(apiEndpoint + '/game/nft/burn', body, {
	headers: {
		apikey: apiKey,
		signature: hmac,
		timestamp: timestamp
	}
});

// Process the response
console.log('Burn Task ID:', response.data.taskId);
console.log('Transaction Hash:', response.data.data.transactionHash);
```


# Get NFT Balance

Get a user's NFT balance

{% hint style="info" %}
Retrieves the NFT balance for a specified PLYR ID on a specific chain.
{% endhint %}

**Endpoint:** `/game/nft/balance`\
**Method:** GET

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    plyrId: string;      // The PLYR ID of the user
    chainId?: string;    // Optional chain ID
}
```

{% endtab %}

{% tab title="Success Response" %}

```typescript
{
	balance: string; // The number of NFTs owned by the user
}
```

{% endtab %}

{% tab title="Error Response" %}

```typescript
{
  error: string;
  details?: any;
}
```

{% endtab %}
{% endtabs %}

## Example Usage

```javascript
// Setup request parameters
const timestamp = Date.now().toString();
const plyrId = 'player123';
const chainId = '43114'; // Avalanche C-Chain

// For GET requests with no body, pass null as the body for HMAC
const hmac = generateHmacSignature(timestamp, null, secretKey);

// Make the API request
const response = await axios.get(apiEndpoint + `/game/nft/balance?plyrId=${plyrId}&chainId=${chainId}`, {
	headers: {
		apikey: apiKey,
		signature: hmac,
		timestamp: timestamp
	}
});

// Process the response
console.log(`User's NFT balance: ${response.data.balance}`);
```


# List NFTs

List NFTs owned by a user

{% hint style="info" %}
Retrieves a list of NFTs owned by a specified PLYR ID, with optional filtering by NFT contract address and game ID.
{% endhint %}

**Endpoint:** `/game/nft/list`\
**Method:** GET

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    plyrId: string;        // The PLYR ID of the user
    chainId: string;       // Chain ID (required)
    nft?: string;          // Optional NFT contract address to filter by
    gameId?: string;       // Optional game ID
}
```

{% endtab %}

{% tab title="Success Response" %}

```typescript
{
  tokens: [
    {
      contract: string;    // NFT contract address
      tokenId: string;     // Token ID
      owner: string;       // Owner address
      uri: string;         // Metadata URI
      metadata?: {         // Optional parsed metadata if available
        name: string;
        description: string;
        image: string;
        attributes: Array<{
          trait_type: string;
          value: string | number;
        }>;
        [key: string]: any; // Other metadata fields
      }
    }
  ]
}
```

{% endtab %}

{% tab title="Error Response" %}

```typescript
{
  error: string;
  details?: any;
}
```

{% endtab %}
{% endtabs %}

## Example Usage

```javascript
// Setup request parameters
const timestamp = Date.now().toString();
const plyrId = 'player123';
const chainId = '43114'; // Avalanche C-Chain
const nftAddress = '0x1234567890123456789012345678901234567890'; // Optional
const gameId = 'game456'; // Optional

// For GET requests with no body, pass null as the body for HMAC
const hmac = generateHmacSignature(timestamp, null, secretKey);

// Make the API request with optional filters
let url = apiEndpoint + `/game/nft/list?plyrId=${plyrId}&chainId=${chainId}&gameId=${gameId}&nft=${nftAddress}`;

const response = await axios.get(url, {
	headers: {
		apikey: apiKey,
		signature: hmac,
		timestamp: timestamp
	}
});

// Process the response
console.log(`User has ${response.data.tokens.length} NFTs`);
response.data.tokens.forEach((token) => {
	console.log(`NFT Contract: ${token.contract}`);
	console.log(`Token ID: ${token.tokenId}`);
	if (token.metadata) {
		console.log(`Name: ${token.metadata.name}`);
		console.log(`Description: ${token.metadata.description}`);
		console.log(`Image: ${token.metadata.image}`);
	}
	console.log('---');
});
```


# Check NFT Holding

Check if a user is holding a specific NFT

{% hint style="info" %}
Checks if a user is holding a specific NFT and returns the count of tokens held.
{% endhint %}

**Endpoint:** `/game/nft/count`\
**Method:** GET

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    plyrId: string;        // The PLYR ID of the user
    nft: string;           // The NFT contract address to check
    chainId?: string;      // Optional chain ID
    gameId?: string;       // Optional game ID
}
```

{% endtab %}

{% tab title="Success Response" %}

```typescript
{
	count: number; // The number of tokens the user holds from this NFT contract
	isHolding: boolean; // Whether the user holds any tokens from this NFT contract
}
```

{% endtab %}

{% tab title="Error Response" %}

```typescript
{
  error: string;
  details?: any;
}
```

{% endtab %}
{% endtabs %}

## Example Usage

```javascript
// Setup request parameters
const timestamp = Date.now().toString();
const plyrId = 'player123';
const nftAddress = '0x1234567890123456789012345678901234567890';
const chainId = '43114'; // Avalanche C-Chain
const gameId = 'game456'; // Optional

// For GET requests with no body, pass null as the body for HMAC
const hmac = generateHmacSignature(timestamp, null, secretKey);

// Make the API request
let url = apiEndpoint + `/game/nft/count?plyrId=${plyrId}&nft=${nftAddress}&chainId=${chainId}&gameId=${gameId}`;

const response = await axios.get(url, {
	headers: {
		apikey: apiKey,
		signature: hmac,
		timestamp: timestamp
	}
});

// Process the response
if (response.data.isHolding) {
	console.log(`User is holding ${response.data.count} tokens from this NFT contract`);
} else {
	console.log('User is not holding any tokens from this NFT contract');
}
```


# Get NFT Credit

Get NFT credit information

{% hint style="info" %}
Retrieves credit information for NFT operations on the PLYR platform.
{% endhint %}

**Endpoint:** `/game/nft/credit`\
**Method:** GET

{% tabs %}
{% tab title="Request Parameters" %}
No parameters required.
{% endtab %}

{% tab title="Success Response" %}

```typescript
{
	credit: {
		remaining: number; // Remaining NFT credit
		total: number; // Total NFT credit allowance
		reset: string; // Timestamp when credit will reset
	}
}
```

{% endtab %}

{% tab title="Error Response" %}

```typescript
{
  error: string;
  details?: any;
}
```

{% endtab %}
{% endtabs %}

## Example Usage

```javascript
// Setup request parameters
const timestamp = Date.now().toString();

// For GET requests with no body, pass null as the body for HMAC
const hmac = generateHmacSignature(timestamp, null, secretKey);

// Make the API request
const response = await axios.get(apiEndpoint + '/game/nft/credit', {
	headers: {
		apikey: apiKey,
		signature: hmac,
		timestamp: timestamp
	}
});

// Process the response
console.log(`Remaining NFT credit: ${response.data.credit.remaining}`);
console.log(`Total NFT credit: ${response.data.credit.total}`);
console.log(`Credit reset time: ${response.data.credit.reset}`);
```


# Get NFT Info

Get information about NFTs

{% hint style="info" %}
Retrieves information about NFT contracts, with optional filtering by contract address, chain ID, and game ID.
{% endhint %}

**Endpoint:** `/game/nft/info`\
**Method:** GET

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    nft?: string;          // Optional NFT contract address to filter by
    chainId?: string;      // Optional chain ID
    gameId?: string;       // Optional game ID
}
```

{% endtab %}

{% tab title="Success Response" %}

```typescript
{
  nfts: [
    {
      address: string;      // NFT contract address
      name: string;         // NFT contract name
      symbol: string;       // NFT contract symbol
      chainId: string;      // Chain ID where the NFT exists
      gameId?: string;      // Optional associated game ID
      image?: string;       // Optional URL to the collection image
    }
  ]
}
```

{% endtab %}

{% tab title="Error Response" %}

```typescript
{
  error: string;
  details?: any;
}
```

{% endtab %}
{% endtabs %}

## Example Usage

```javascript
// Setup request parameters
const timestamp = Date.now().toString();
const nftAddress = '0x1234567890123456789012345678901234567890'; // Optional
const chainId = '43114'; // Optional, Avalanche C-Chain
const gameId = 'game456'; // Optional

// For GET requests with no body, pass null as the body for HMAC
const hmac = generateHmacSignature(timestamp, null, secretKey);

// Make the API request with optional filters
let url = apiEndpoint + `/game/nft/info?chainId=${chainId}&nft=${nftAddress}&gameId=${gameId}`;

const response = await axios.get(url, {
	headers: {
		apikey: apiKey,
		signature: hmac,
		timestamp: timestamp
	}
});

// Process the response
console.log(`Found ${response.data.nfts.length} NFT contracts`);
response.data.nfts.forEach((nft) => {
	console.log(`NFT Address: ${nft.address}`);
	console.log(`Name: ${nft.name}`);
	console.log(`Symbol: ${nft.symbol}`);
	console.log(`Chain ID: ${nft.chainId}`);
	if (nft.gameId) console.log(`Game ID: ${nft.gameId}`);
	if (nft.image) console.log(`Image URL: ${nft.image}`);
	console.log('---');
});
```


# Get Zoo Genes

Get ZooGenes NFTs for a user

{% hint style="info" %}
Retrieves ZooGenes NFTs owned by a specified username.
{% endhint %}

**Endpoint:** `/nft/{chainName}/zoogenes/{username}`\
**Method:** GET

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
	username: string; // The username to query
	chainName: string; // Chain name (avalanche or fuji)
}
```

{% endtab %}

{% tab title="Success Response" %}

```typescript
[
  {
    id: string;            // Zoo Gene ID
    name: string;          // Zoo Gene name
    description: string;   // Zoo Gene description
    image: string;         // Zoo Gene image URL
    generation: number;    // Zoo Gene generation
    attributes: Array<{    // Zoo Gene attributes
      trait_type: string;
      value: string | number;
    }>;
    owner: string;         // Owner address
    tokenId: string;       // Token ID
    contract: string;      // Contract address
  }
]
```

{% endtab %}

{% tab title="Error Response" %}

```typescript
{
  error: string;
  details?: any;
}
```

{% endtab %}
{% endtabs %}

## Example Usage

```javascript
// Setup request parameters
const timestamp = Date.now().toString();
const username = 'player123';
const chainName = 'avalanche'; // or 'fuji' for testnet

// For GET requests with no body, pass null as the body for HMAC
const hmac = generateHmacSignature(timestamp, null, secretKey);

// Make the API request
const response = await axios.get(apiEndpoint + `/nft/${chainName}/zoogenes/${username}`, {
	headers: {
		apikey: apiKey,
		signature: hmac,
		timestamp: timestamp
	}
});

// Process the response
console.log(`Found ${response.data.length} ZooGenes NFTs`);
response.data.forEach((zooGene) => {
	console.log(`ID: ${zooGene.id}`);
	console.log(`Name: ${zooGene.name}`);
	console.log(`Generation: ${zooGene.generation}`);
	console.log(`Image: ${zooGene.image}`);
	console.log(`Token ID: ${zooGene.tokenId}`);
	console.log('---');
});
```


# Official PLYR NFTs


# Get User Zoo Genes

Get user's ZooGenes NFTs

{% hint style="info" %}
Retrieve the PLYR ZooGenes NFTs for a specific user.
{% endhint %}

**Endpoint:** `/nft/avalanche/zoogenes/{plyrId}`\
**Method:** GET

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    plyrId: string; // The user's PlyrId
}
```

{% endtab %}

{% tab title="Success Response (200)" %}

```typescript
Array<{
    owner: string;
    uri: string;
    collection: string;
    quantity: string;
    tokenId: string;
    name: string;
    image: string;
    description: string;
    attributes: Array<{
        trait_type: string;
        display_type?: string;
        value: string | number;
        max_value?: number;
    }>;
}>;
```

{% endtab %}

{% tab title="Error Response (404)" %}

```typescript
{
    error: string;
}
```

{% endtab %}
{% endtabs %}

## Example Usage

```javascript
const timestamp = Date.now().toString();
const plyrId = 'player123';

// Since this is a GET request with no body, pass null as the body for HMAC
const hmac = generateHmacSignature(timestamp, null, secretKey);

// Make the API request
const response = await axios.get(apiEndpoint + `/nft/avalanche/zoogenes/${plyrId}`, {
    headers: {
        apikey: apiKey,
        signature: hmac,
        timestamp: timestamp
    }
});

// Response will contain array of ZooGene NFTs with their metadata
const zoogenes = response.data.data;
// Access individual ZooGene properties
zoogenes.forEach((nft) => {
    console.log(`ZooGene #${nft.tokenId}:`);
    console.log(`- Name: ${nft.name}`);
    console.log(`- Image: ${nft.image}`);
    console.log('- Attributes:', nft.attributes);
});
```

{% hint style="info" %}
ZooGenes are special NFTs with unique attributes that can be used in various PLYR games and experiences. \[<https://opensea.io/collection/zoogenes]\\(https://opensea.io/collection/zoogenes)>
{% endhint %}


# Get User Zoo Boosters

Get user's Zoo Booster NFTs


# Get User Zoo Elixirs

Get user's Zoo Elixir NFTs


# Badge

Overview of Badge API endpoints

The Badge API provides endpoints for managing game badges (ERC-721 tokens) in the system. These endpoints allow you to create, mint, transfer, burn, and query badge information.

## Available Endpoints

### Creation

* [Create Badge](/api-reference/assets/badge/create-badge) - Create a new badge
* [Create Badge by Signature](https://github.com/onPlyr/dev-documents-gitbook/blob/main/api-reference/assets/badge/create-badge-by-signature.md) - Create a badge using a signature

### Minting

* [Mint Badge](/api-reference/assets/badge/mint-badge) - Mint a badge to a recipient

### Management

* [Remove Badge](/api-reference/assets/badge/remove-badge) - Remove a badge
* [Remove Badge by Signature](https://github.com/onPlyr/dev-documents-gitbook/blob/main/api-reference/assets/badge/remove-badge-by-signature.md) - Remove a badge using a signature
* [Burn Badge](/api-reference/assets/badge/burn-badge) - Burn a badge
* [Transfer Badge](broken://pages/pYxr9CEGIhzEBvxqP2yx) - Transfer a badge to another address

### Queries

* [Get Badge Balance](broken://pages/8Hc6d8Nvb86DdHMefEkz) - Get badge balance for an address
* [List Badges](/api-reference/assets/badge/list-badges) - List badges owned by an address
* [Get Badge Info](/api-reference/assets/badge/get-badge-info) - Get detailed information about a badge
* [Get Badge Count](broken://pages/LdTgfJ35q1840mGbOBKb) - Get total count of badges
* [Get Badge by ID](broken://pages/Qei02JnCELYwB6TqKLB4) - Get badge information by ID
* [Get Badge Owner](broken://pages/64yGn03k7laIjCE0WItP) - Get the owner of a badge
* [Check Badge Burn Status](broken://pages/dmBuAwpoN7juj06SIwD5) - Check if a badge is burnt

## Authentication

All endpoints require HMAC authentication using the `hmacAuth('user')` middleware. Make sure to include the following headers in your requests:

* `apikey`: Your API key
* `signature`: HMAC signature
* `timestamp`: Current timestamp

## Chain ID

Most endpoints require a chain ID to be specified. This can be done either in the request body or through the `checkChainId` middleware.


# Create Badge

Create a new badge

{% hint style="info" %}
Creates a new badge with specified metadata.
{% endhint %}

**Endpoint:** `/game/badge/create`\
**Method:** POST

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    name: string;             // Name of the badge
    description: string;     // Description of the badge
    slug: slug                // Slug of this badge / Alias name of Badge
    image?: string;          // Optional image URL for the badge
    attributes?: object[];    // Optional array of attributes
}
```

{% endtab %}

{% tab title="Success Response" %}

```typescript
{
    success: true
}
```

{% endtab %}

{% tab title="Error Response" %}

```typescript
{
  error: string;
  details?: any;
}
```

{% endtab %}
{% endtabs %}

## Example Usage

```javascript
// Setup request parameters
const timestamp = Date.now().toString();
const body = {
    name: 'Game Achievement Badge',
    description: 'Badge awarded for game achievements',
    slug: 'gab'
    image: 'https://example.com/badge.png',
    attributes: [
        { trait_type: 'RARITY', value: 'common' },
        { trait_type: 'Version', value: '1.0' }
    ],
};

// Generate HMAC signature
const hmac = generateHmacSignature(timestamp, body, secretKey);

// Make the API request
const response = await axios.post(apiEndpoint + '/game/badge/create', body, {
    headers: {
        apikey: apiKey,
        signature: hmac,
        timestamp: timestamp
    }
});

// Process the response
console.log('Create Task ID:', response.data.taskId);
console.log('Transaction Hash:', response.data.data.transactionHash);
```


# Mint Badge

Mint a new badge to a recipient

{% hint style="info" %}
Mints a new badge to a specified recipient address with associated metadata.
{% endhint %}

**Endpoint:** `/game/badge/mint`\
**Method:** POST

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    slugs: string[];           // Array of badge slugs
    plyrIds: string[];      // Array of recipient PLYR[ID]
}
```

{% endtab %}

{% tab title="Success Response" %}

```typescript
{
    taskId: string;
    result: [{
        gameId: string; 
        from: string; 
        to: string;
        tokenId: string;
        hash: string
    }]
    status: string;
    hash: string;
}
```

{% endtab %}

{% tab title="Error Response" %}

```typescript
{
  error: string;
  details?: any;
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
The \`slugs\`, and \`plyrIds\` arrays must have the same length. Each index represents a mint operation.
{% endhint %}

## Example Usage

```javascript
// Setup request parameters
const timestamp = Date.now().toString();
const body = {
    slugs: ['slugA'], // Badge slugs
    plyrIds: ['fennec'], // Recipient PLYR[ID]
};

// Generate HMAC signature
const hmac = generateHmacSignature(timestamp, body, secretKey);

// Make the API request
const response = await axios.post(apiEndpoint + '/game/badge/mint', body, {
    headers: {
        apikey: apiKey,
        signature: hmac,
        timestamp: timestamp
    }
});

// Process the response
console.log('Mint Task ID:', response.data.taskId);
console.log('Transaction Hash:', response.data.hash);
console.log('Token ID:', response.data.data.tokenId);
```


# Remove Badge

Remove a badge from an address

{% hint style="info" %}
Removes a badge from a specified address.
{% endhint %}

**Endpoint:** `/game/badge/remove`\
**Method:** POST

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    nft: string;              // Badge contract address
    address: string;          // Address to remove badge from
    tokenId: string;          // ID of the badge to remove
    chainId?: string;         // Optional chain ID (defaults to configured chain ID)
}
```

{% endtab %}

{% tab title="Success Response" %}

```typescript
{
    taskId: string;
    data: {
        transactionHash: string; // The hash of the remove transaction
    }
    status: string;
}
```

{% endtab %}

{% tab title="Error Response" %}

```typescript
{
  error: string;
  details?: any;
}
```

{% endtab %}
{% endtabs %}

## Example Usage

```javascript
// Setup request parameters
const timestamp = Date.now().toString();
const body = {
    nft: '0x1234567890123456789012345678901234567890', // Badge contract address
    address: '0xabcdef1234567890abcdef1234567890abcdef', // Address to remove from
    tokenId: '123', // Badge ID to remove
    chainId: '43114' // Avalanche C-Chain
};

// Generate HMAC signature
const hmac = generateHmacSignature(timestamp, body, secretKey);

// Make the API request
const response = await axios.post(apiEndpoint + '/game/badge/remove', body, {
    headers: {
        apikey: apiKey,
        signature: hmac,
        timestamp: timestamp
    }
});

// Process the response
console.log('Remove Task ID:', response.data.taskId);
console.log('Transaction Hash:', response.data.data.transactionHash);
```


# Burn Badge

Burn a badge

{% hint style="info" %}
Permanently burns a badge, removing it from circulation.
{% endhint %}

**Endpoint:** `/game/badge/burn`\
**Method:** POST

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    plyrIds: string[];              // PLYR[ID] of holder
    slugs: string[];          // Slug of the badge to burn
    tokenIds: string[];         // Token ID of Badge
}
```

{% endtab %}

{% tab title="Success Response" %}

```typescript
{
    taskId: string;
    taskData: {
        method: 'burnGameBadge'
    }
    status: string;
    hash: string;
}
```

{% endtab %}

{% tab title="Error Response" %}

```typescript
{
  error: string;
  details?: any;
}
```

{% endtab %}
{% endtabs %}

## Example Usage

```javascript
// Setup request parameters
const timestamp = Date.now().toString();
const body = {
    plyrIds: ['fennec'], 
    slugs: ['SlugA'], 
    tokenIds: ['1']
};

// Generate HMAC signature
const hmac = generateHmacSignature(timestamp, body, secretKey);

// Make the API request
const response = await axios.post(apiEndpoint + '/game/badge/burn', body, {
    headers: {
        apikey: apiKey,
        signature: hmac,
        timestamp: timestamp
    }
});

// Process the response
console.log('Burn Task ID:', response.data.taskId);
console.log('Transaction Hash:', response.data.data.transactionHash);
```


# List Badges

List badges owned by an address

{% hint style="info" %}
Retrieves a list of badges owned by a PLYR\[ID].
{% endhint %}

**Endpoint:** `/game/badge/list`\
**Method:** GET

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    plyrId: string;              // PLYR[ID]
    gameId: string;          // Game ID / PLYR[ID] of game
}
```

{% endtab %}

{% tab title="Success Response" %}

<pre class="language-typescript"><code class="lang-typescript"><strong>[
</strong>  {
    gameId: string,
    slug: string,
    tokenId: string,
    plyrId: string,
    owner: string,
    metaJson: {
      name: string,
      slug: string,
      image: string,
      attributes: [
        { trait_type: string, value: string },
      ]
    },
    createdAt: string,
  }
]
</code></pre>

{% endtab %}

{% tab title="Error Response" %}

```typescript
{
  error: string;
  details?: any;
}
```

{% endtab %}
{% endtabs %}

## Example Usage

```javascript
// Setup request parameters
const timestamp = Date.now().toString();
const params = {
    plyrId: 'fennec', 
    gameId: 'zoono',
};

// Generate HMAC signature
const hmac = generateHmacSignature(timestamp, params, secretKey);

// Make the API request
const response = await axios.get(apiEndpoint + '/game/badge/list', {
    params,
    headers: {
        apikey: apiKey,
        signature: hmac,
        timestamp: timestamp
    }
});

```


# Get Badge Info

Get detailed information about a badge

{% hint style="info" %}
Retrieves detailed information about a specific badge.
{% endhint %}

**Endpoint:** `/game/badge/info`\
**Method:** GET

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    gameId: string;          // Game ID
    slug?: string            // Optional, specificed a slug
}
```

{% endtab %}

{% tab title="Success Response" %}

```typescript
[
    {
    gameId: string,
    contractAddress: string,
    name: string,
    description: string,
    slug: string,
    image: string,
    attributes: [ { trait_type: string, value: string } ],
    createdAt: string,
    holders: number,
    count: number
  },
]
```

{% endtab %}

{% tab title="Error Response" %}

```typescript
{
  error: string;
  details?: any;
}
```

{% endtab %}
{% endtabs %}

## Example Usage

```javascript
// Setup request parameters
const timestamp = Date.now().toString();
const params = {
    gameId: 'zoono',
};

// Generate HMAC signature
const hmac = generateHmacSignature(timestamp, params, secretKey);

// Make the API request
const response = await axios.get(apiEndpoint + '/game/badge/info', {
    params,
    headers: {
        apikey: apiKey,
        signature: hmac,
        timestamp: timestamp
    }
});

// Process the response
console.log('Badge Info:', response.data);
```


# Misc


# Get Session JWT Public Key

Get session JWT public key endpoint

{% hint style="info" %}
Retrieve the public key used to verify session JWTs locally.
{% endhint %}

**Endpoint:** `/jwt/publicKey`\
**Method:** GET

{% tabs %}
{% tab title="Success Response (200)" %}

```typescript
{
    publicKey: string; // Base64 encoded public key
}
```

{% endtab %}

{% tab title="Error Response (400)" %}

```typescript
{
    error: string;
}
```

{% endtab %}
{% endtabs %}

## Example Usage

```typescript
// Fetch the public key
const response = await axios.get(apiEndpoint + '/jwt/publicKey');
const publicKey = response.data.publicKey;

// Verify a JWT locally
const decodedToken = jwt.verify(token, Buffer.from(publicKey, 'base64').toString('utf-8'), { algorithms: ['ES256'] });
```

{% hint style="info" %}
The public key can be used to verify session JWTs locally without making API calls.
{% endhint %}

{% hint style="warning" %}
Cache the public key and reuse it for multiple verifications. Only fetch a new key if verification fails.
{% endhint %}


# Verify JWT Locally

Verify a session JWT locally

{% hint style="info" %}
Verify a session JWT locally using the ES256 algorithm and a public key.
{% endhint %}

## Verification Process

To verify a JWT locally, you'll need:

1. The JWT token to verify
2. The public key in PEM format (base64 encoded)

### Parameters

```typescript
{
  token: string,      // The JWT to verify
  publicKey: string   // Base64 encoded public key (must be decoded to UTF-8 before use)
}
```

### Example Usage

```typescript
try {
    const decodedToken = jwt.verify(token, Buffer.from(base64PublicKey, 'base64').toString('utf-8'), { algorithms: ['ES256'] });
    // JWT is valid, decodedToken contains the payload
} catch (error) {
    // JWT verification failed
    console.error(error.message);
}
```

### Error Cases

Verification will throw an error if:

* The JWT format is invalid
* The signature is invalid
* The token has expired (due to logout for example)
* The algorithm doesn't match (must be ES256)


# Activity Logs

Get user activity logs

{% hint style="info" %}
Retrieve activity logs for a specific user.
{% endhint %}

**Endpoint:** `/activityLogs/{plyrId}`\
**Method:** GET

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
  plyrId: string,     // The player's unique identifier
  startTime?: number, // Start timestamp (optional)
  endTime?: number,   // End timestamp (optional)
  limit?: number      // Maximum number of logs to return (optional)
}
```

{% endtab %}

{% tab title="Success Response (200)" %}

```typescript
{
    logs: Array<{
        timestamp: number;
        action: string;
        details: {
            [key: string]: any;
        };
    }>;
}
```

{% endtab %}

{% tab title="Error Response (400)" %}

```typescript
{
    error: string;
}
```

{% endtab %}
{% endtabs %}


# Get Task Message Status

Get the status of a task message

{% hint style="info" %}
Check the status of an asynchronous task message.
{% endhint %}

**Endpoint:** `/task/status/{taskId}`\
**Method:** GET

{% tabs %}
{% tab title="Request Parameters" %}

```typescript
{
    taskId: string; // The task's unique identifier
}
```

{% endtab %}

{% tab title="Success Response (200)" %}

```typescript
{
    taskId: string;
    taskData: {
        '0': string;
        '1': {
            gameId: string;
            plyrIds?: string[];
            roomId?: string;
            expiresIn?: number; // in seconds and only for createGameRoom
        };
        result?: {
            gameId: string;
            roomId: string;
            roomAddress: string;
        };
    };
    status: 'SUCCESS' | 'PENDING' | 'FAILED' | 'TIMEOUT';
    hash: string;
    errorMessage?: string;
    completedAt: string;
}
```

{% endtab %}

{% tab title="Error Response (404)" %}

```typescript
{
    error: string;
}
```

{% endtab %}
{% endtabs %}

## Example Usage

```javascript
// Setup request parameters
const timestamp = Date.now().toString();
const taskId = 'task_abc123xyz789';

// Generate HMAC signature (empty body for GET request)
const hmac = generateHmacSignature(timestamp, {}, secretKey);

// Make the API request
const response = await axios.get(apiEndpoint + '/task/status/' + taskId, {
    headers: {
        apikey: apiKey,
        signature: hmac,
        timestamp: timestamp
    }
});
```

{% hint style="info" %}
Tasks are asynchronous operations that may take some time to complete. Use this endpoint to check their status.
{% endhint %}

{% hint style="warning" %}
Task status should be polled at reasonable intervals (e.g., every 1-2 seconds) to avoid rate limiting.
{% endhint %}


