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

# MSU OpenAPI Builder Guide

> **Version**: v1rc1<br />**Audience**: Builders (external service/app developers) calling MSU OpenAPI

***

<Tip>
  **Start with AI**

  Paste this prompt into your AI assistant (ChatGPT, Claude, Cursor, etc.) to load this guide as context:

  ```text theme={null}
  Read from https://docs.msu.io/msu-open-api/ai-assistant/msu-openapi-builder-guide.md so I can ask questions about it.
  ```
</Tip>

　

## 1. Overview

MSU OpenAPI provides external builders with character, item, account, and search data from the MSU Marketplace.

| Item                | Value                        |
| ------------------- | ---------------------------- |
| Base URL            | `https://openapi.msu.io`     |
| Protocol            | HTTPS                        |
| Encoding            | JSON (camelCase field names) |
| Version path prefix | `/v1rc1/`                    |

**`asset_key` vs `token_id`**

| Identifier  | Description                                                                                                  |
| ----------- | ------------------------------------------------------------------------------------------------------------ |
| `asset_key` | Internal identifier that always exists regardless of minting status                                          |
| `token_id`  | Issued only after NFT minting. Calling a `by-token-id` endpoint on an unminted target returns `NOT_FOUND(3)` |

　

## 2. Authentication

Pass your API key in the request header for all requests.

```http theme={null}
x-nxopen-api-key: <YOUR_API_KEY>
```

Endpoints requiring user authentication (market, etc.) additionally require a Bearer token.

Token issuance is done through a separate MSU OAuth authentication flow.

```http theme={null}
msu-authorization: <access_token>
```

　

## 3. Response Format

All APIs respond in the following format.

### Success Response

```json theme={null}
{
  "success": true,
  "data": { ... },
  "traceId": "69faa56c000000006debcf3d9f4e0119"
}
```

### Error Response

```json theme={null}
{
  "success": false,
  "error": {
    "code": 3,
    "message": "character not found"
  },
  "traceId": "69faa56c000000006debcf3d9f4e0119"
}
```

| Field           | Type    | Always Present  | Description                                              |
| --------------- | ------- | --------------- | -------------------------------------------------------- |
| `success`       | boolean | ✅               | Whether the request succeeded                            |
| `data`          | object  | On success only | Response data per endpoint                               |
| `error.code`    | integer | On failure only | Error code (see table below)                             |
| `error.message` | string  | On failure only | Error description (human-readable)                       |
| `traceId`       | string  | ✅               | Request trace ID. Always provide when contacting support |

> **Note**: All response field names are camelCase (proto field `asset_key` → JSON `assetKey`).

　

## 4. Error Codes

### Common Errors

| code | Constant                         | HTTP Status | Description                | Common Scenarios                                    | Resolution                     |
| ---- | -------------------------------- | ----------- | -------------------------- | --------------------------------------------------- | ------------------------------ |
| `0`  | `ERROR_CODE_UNSPECIFIED`         | 500         | Unspecified error          | Unexpected server error                             | Contact support with `traceId` |
| `2`  | `ERROR_CODE_INVALID_ARGUMENT`    | 400         | Invalid request argument   | Missing required parameter, format error            | Check request parameters       |
| `3`  | `ERROR_CODE_NOT_FOUND`           | 404         | Requested target not found | Non-existent `assetKey`, `tokenId`, `walletAddress` | Verify identifier value        |
| `4`  | `ERROR_CODE_INTERNAL_ERROR`      | 500         | Internal server error      | Server failure                                      | Retry or contact support       |
| `5`  | `ERROR_CODE_PERMISSION_DENIED`   | 403         | Permission denied          | API key scope exceeded                              | Check API key permissions      |
| `6`  | `ERROR_CODE_FAILED_PRECONDITION` | 412         | Unprocessable state        | Operation not possible in current state             | Check target resource state    |
| `7`  | `ERROR_CODE_ALREADY_PROCESS`     | 409         | Already processed          | Duplicate request                                   | Check for duplicate requests   |
| `9`  | `ERROR_CODE_EXPECTATION_FAILED`  | 417         | Expectation failed         | Server-side precondition not met                    | Check `error.message` content  |
| `10` | `ERROR_CODE_TOO_MANY_REQUEST`    | 429         | Rate limit exceeded        | Per-API-key rate limit exceeded                     | Retry with exponential backoff |
| `11` | `ERROR_CODE_CANCELED`            | 408         | Request canceled/timeout   | Processing time exceeded                            | Retry                          |

### Authentication Errors

| code   | Constant                                | HTTP Status | Description                                         | Common Scenarios                                                                 | Resolution                    |
| ------ | --------------------------------------- | ----------- | --------------------------------------------------- | -------------------------------------------------------------------------------- | ----------------------------- |
| `8`    | `ERROR_CODE_UNAUTHENTICATED`            | 401         | Authentication failed                               | Missing or invalid `x-nxopen-api-key` header                                     | Verify API key                |
| `3001` | `ERROR_CODE_INVALID_AUTH_TOKEN`         | 401         | Invalid MSU auth token                              | Invalid `access_token` provided                                                  | Re-issue token                |
| `4001` | `ERROR_CODE_TOKEN_EXPIRED`              | 401         | Token expired                                       | `access_token` validity period exceeded                                          | Re-issue with `refresh_token` |
| `4002` | `ERROR_CODE_TOKEN_EXPIRED_BY_OTHER_APP` | 401         | Token expired by another app in the same app\_group | Another app in the same `app_group` logged in, invalidating the existing session | Re-login and re-issue token   |

### Domain Errors

| code   | Constant                                      | HTTP Status | Description                           | Common Scenarios                                     | Resolution                           |
| ------ | --------------------------------------------- | ----------- | ------------------------------------- | ---------------------------------------------------- | ------------------------------------ |
| `1001` | `ERROR_CODE_NOT_APPROVE_WALLET`               | 403         | Wallet asset approval not granted     | User has not granted the app access to wallet assets | Request wallet approval from user    |
| `1002` | `ERROR_CODE_NOT_ENOUGH_NESO`                  | 402         | Insufficient on-chain NESO balance    | Insufficient balance for NESO-consuming operations   | Guide user to top up NESO            |
| `2002` | `ERROR_CODE_NOT_FOUND_SYNERGY_APP`            | 404         | Synergy app not found                 | Invalid `client_id` used                             | Verify `client_id`                   |
| `2003` | `ERROR_CODE_NOT_APPROVED_SYNERGY_APP_BY_USER` | 403         | User has not approved the synergy app | User has rejected or canceled app connection         | Request app approval from user again |

### Error Handling Example

```typescript theme={null}
const res = await fetch(url, {
  headers: { 'x-nxopen-api-key': API_KEY }
});
const body = await res.json();

if (!body.success) {
  const { code, message } = body.error;
  switch (code) {
    case 3:    // NOT_FOUND
      console.error('Target not found');
      break;
    case 8:    // UNAUTHENTICATED
      console.error('API key verification needed');
      break;
    case 4001: // TOKEN_EXPIRED
    case 4002: // TOKEN_EXPIRED_BY_OTHER_APP
      await refreshAccessToken();
      break;
    case 10:   // TOO_MANY_REQUEST
      await delay(Math.pow(2, attempt) * 1000); // Exponential Backoff
      break;
    default:
      console.error(`Error (code: ${code}): ${message}`);
      console.error('traceId:', body.traceId); // Always provide when contacting support
  }
}
```

　

## 5. Pagination

Three pagination methods are used depending on the API.

### Cursor Pagination

Used by most list APIs. Page size is fixed per API.

**Request Parameters**

| Parameter | Type   | Description                                                            |
| --------- | ------ | ---------------------------------------------------------------------- |
| `cursor`  | string | `nextCursor` value from the previous response. Omit for the first page |

**Response Fields**

| Field        | Type    | Description                             |
| ------------ | ------- | --------------------------------------- |
| `nextCursor` | string  | Cursor to use for the next page request |
| `hasMore`    | boolean | Whether there is a next page            |

<h3 id="page-number-pagination-page">
  Page Number Pagination
</h3>

Used by Search endpoints.

**Request Parameters (`paginationParam`)**

| Parameter  | Type    | Description                   |
| ---------- | ------- | ----------------------------- |
| `pageNo`   | integer | Page number (starting from 1) |
| `pageSize` | integer | Results per page              |

**Response Fields (`paginationResult`)**

| Field        | Type    | Description                   |
| ------------ | ------- | ----------------------------- |
| `totalCount` | integer | Total result count            |
| `pageSize`   | integer | Results per page              |
| `currPageNo` | integer | Current page number           |
| `isLastPage` | boolean | Whether this is the last page |

### Scroll Pagination

Used for collection queries.

**Request Parameters (`paginationParam`)**

| Parameter  | Type    | Description                                                      |
| ---------- | ------- | ---------------------------------------------------------------- |
| `lastKey`  | string  | `lastKey` from the previous response. Omit for the first request |
| `pageSize` | integer | 1–200 (default: 10)                                              |

**Response Fields (`paginationResult`)**

| Field        | Type    | Description                          |
| ------------ | ------- | ------------------------------------ |
| `totalCount` | integer | Total result count                   |
| `pageSize`   | integer | Results per page                     |
| `lastKey`    | string  | Key to use for the next page request |
| `isLastPage` | boolean | Whether this is the last page        |

　

## 6. Common Types

Type definitions commonly used across multiple endpoints.

### `Category` Object

| Field        | Type         | Description                                 |
| ------------ | ------------ | ------------------------------------------- |
| `categoryNo` | integer      | Category number                             |
| `label`      | string       | Category label                              |
| `tier0`      | CategoryTier | Tier0 classification (NFT / FT / Character) |
| `tier1`      | CategoryTier | Tier1 major classification                  |
| `tier2`      | CategoryTier | Tier2 mid classification                    |
| `tier3`      | CategoryTier | Tier3 minor classification                  |

**CategoryTier Object**

| Field   | Type   | Description         |
| ------- | ------ | ------------------- |
| `label` | string | Classification name |
| `code`  | string | Classification code |

### `TokenType` Enum

| Value                          | Description   |
| ------------------------------ | ------------- |
| `TOKEN_TYPE_UNSPECIFIED` (0)   | Unspecified   |
| `TOKEN_TYPE_NFT_ITEM` (1)      | NFT item      |
| `TOKEN_TYPE_FT_ITEM` (2)       | FT item       |
| `TOKEN_TYPE_NFT_CHARACTER` (3) | NFT character |
| `TOKEN_TYPE_NFT_NICKNAME` (4)  | NFT nickname  |

　

## 7. API Reference

Refer to the links below for detailed API documentation by category.

| Category    | Document Link                                                           | Key APIs                                                          |
| ----------- | ----------------------------------------------------------------------- | ----------------------------------------------------------------- |
| Account     | [account](https://docs.msu.io/msu-builder/ai-assitant/account)          | NESO balance, currencies, collection, item/character list         |
| Character   | [character](https://docs.msu.io/msu-builder/ai-assitant/character)      | Character details, stats, equipped gear, skills, V Matrix, etc.   |
| Item        | [item](https://docs.msu.io/msu-builder/ai-assitant/item)                | NFT item details, history queries                                 |
| Market      | [market](https://docs.msu.io/msu-builder/ai-assitant/market)            | Marketplace item/character/nickname search, keyword autocomplete  |
| GameMeta    | [gamemeta](https://docs.msu.io/msu-builder/ai-assistant/gamemeta)       | Item/skill/set/quest metadata, V Matrix node skills               |
| Enhancement | [enhancement](https://docs.msu.io/msu-builder/ai-assistant/enhancement) | Enhancement price queries                                         |
| Rewards     | [rewards](https://docs.msu.io/msu-builder/ai-assistant/rewards)         | Reward/raffle status, character raffle history, layer static data |
| Resource    | [resource](https://docs.msu.io/msu-builder/ai-assistant/resource)       | MCP proxy requests                                                |

### Account

| API               | Endpoint                                         | Description                                                  |
| ----------------- | ------------------------------------------------ | ------------------------------------------------------------ |
| `GetNeso`         | `GET /v1rc1/accounts/{walletAddress}/neso`       | Get on-chain and off-chain NESO balance for a wallet         |
| `ListCurrency`    | `GET /v1rc1/accounts/{walletAddress}/currencies` | Get list of currency types and balances linked to a wallet   |
| `ListCollection`  | `GET /v1rc1/accounts/{walletAddress}/collection` | Get NFT collection list held by a wallet (scroll pagination) |
| `ListWalletItems` | `GET /v1rc1/accounts/{walletAddress}/items`      | Get item list held by a wallet (cursor pagination)           |
| `ListCharacters`  | `GET /v1rc1/accounts/{walletAddress}/characters` | Get character list linked to a wallet (cursor pagination)    |

### Character

| API                            | Endpoint                                            | Description                                                   |
| ------------------------------ | --------------------------------------------------- | ------------------------------------------------------------- |
| `GetCharacter`                 | `GET /v1rc1/characters/{assetKey}`                  | Get character details (stats, equipped gear, abilities, etc.) |
| `GetCharacter` (by token)      | `GET /v1rc1/characters/by-token-id/{tokenId}`       | Get character details by token ID                             |
| `ListCharacterHoldingItems`    | `GET /v1rc1/characters/{assetKey}/items`            | Get list of items in character's inventory                    |
| `ListCharacterHistoryMissions` | `GET /v1rc1/characters/{assetKey}/history-missions` | Get character history mission list                            |
| `ListCharacterQuests`          | `GET /v1rc1/characters/{assetKey}/quests`           | Get character quest achievement information                   |
| `ListCharacterSkills`          | `GET /v1rc1/characters/{assetKey}/skills`           | Get character skill information                               |
| `ListCharacterHyperSkills`     | `GET /v1rc1/characters/{assetKey}/hyper-skill`      | Get character hyper skill information                         |
| `GetCharacterVMatrix`          | `GET /v1rc1/characters/{assetKey}/vmatrix`          | Get V Matrix slot and V Core information                      |

> `by-token-id` variant endpoints are available identically for each API.

### Item

| API                                        | Endpoint                                                      | Description                                                |
| ------------------------------------------ | ------------------------------------------------------------- | ---------------------------------------------------------- |
| `GetNftItem`                               | `GET /v1rc1/items/{assetKey}`                                 | Get NFT item details (stats, enhancement, potential, etc.) |
| `GetNftItem` (by token)                    | `GET /v1rc1/items/by-token-id/{tokenId}`                      | Get NFT item details by token ID                           |
| `ListNftItemHistoryMissions`               | `GET /v1rc1/items/{assetKey}/history-missions`                | Get full item history mission list                         |
| `ListNftItemHistoryMissionsRepresentative` | `GET /v1rc1/items/{assetKey}/history-missions/representative` | Get representative item history mission list               |

### Market

| API                 | Endpoint                       | Description                                                  |
| :------------------ | :----------------------------- | :----------------------------------------------------------- |
| `ExploreItems`      | `GET /v1rc1/search/items`      | Search marketplace items for sale (filter/sort support)      |
| `ExploreCharacters` | `GET /v1rc1/search/characters` | Search marketplace characters for sale (filter/sort support) |
| `ExploreNicknames`  | `GET /v1rc1/search/nicknames`  | Search marketplace nickname NFTs for sale                    |
| `SuggestKeywords`   | `GET /v1rc1/search/suggest`    | Keyword autocomplete                                         |

### GameMeta

| API                       | Endpoint                                       | Description                                              |
| ------------------------- | ---------------------------------------------- | -------------------------------------------------------- |
| `GetItemMetadata`         | `GET /v1rc1/gamemeta/items/{itemId}`           | Get game metadata by item ID                             |
| `GetItemCategory`         | `GET /v1rc1/gamemeta/items/{itemId}/category`  | Get item category classification information             |
| `GetItemSet`              | `GET /v1rc1/gamemeta/items/{itemId}/set`       | Get set effect information for the item's set            |
| `ListEquipExclusiveItems` | `GET /v1rc1/gamemeta/items/{itemId}/exclusive` | Get list of items that cannot be equipped simultaneously |
| `GetQuestMetadata`        | `GET /v1rc1/gamemeta/quests/{questId}`         | Get quest metadata                                       |
| `GetSkillMetadata`        | `GET /v1rc1/gamemeta/skills/{skillId}`         | Get skill metadata                                       |
| `GetVMatrixNodeSkill`     | `GET /v1rc1/gamemeta/vmatrix/{nodeId}`         | Get V Matrix node skill information                      |

### Enhancement

| API               | Endpoint                                             | Description                                                   |
| ----------------- | ---------------------------------------------------- | ------------------------------------------------------------- |
| `GetCurrentPrice` | `GET /v1rc1/enhancement/items/{itemId}/dynamicprice` | Get current Starforce/Potential enhancement price for an item |

### Rewards

| API                             | Endpoint                                                        | Description                                                              |
| ------------------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------------ |
| `GetRewardInformation`          | `POST /v1rc1/msn/rewards/{worldId}`                             | Get NFT drop probability and inventory status for fields/bosses/content  |
| `GetRewardHistory`              | `POST /v1rc1/msn/rewards/{worldId}/history`                     | Get reward history within 30 days after a raffle                         |
| `GetCharacterRaffleInformation` | `GET /v1rc1/msn/characters/{characterAssetKey}/raffles`         | Get character raffle participation status (before drawing)               |
| `GetCharacterRaffleHistory`     | `GET /v1rc1/msn/characters/{characterAssetKey}/raffles/history` | Get character raffle participation history (up to 30 days after drawing) |
| `GetLayerStaticData`            | `POST /v1rc1/msn/layers/static`                                 | Get layer static data such as level range and name                       |
| `GetServerInformation`          | `GET /v1rc1/msn/server`                                         | Get reward server status by world                                        |

### Resource

| API       | Endpoint                   | Description                              |
| --------- | -------------------------- | ---------------------------------------- |
| `McpCall` | `POST /v1rc1/resource/mcp` | Proxy JSON-RPC 2.0 request to MCP server |

　

## 8. Contact

When reporting an API error, always include the `traceId` from the response.

　

***
