AI Agent Guide
This document is published as Markdown for AI agents to read. If you are looking for how to use the API as a person, see Using the API.
This document is written for AI agents, not people, so that an agent can use the NEXON Open API from start to finish on its own. It targets agents capable of tool calling, and the developers who build them. Where the other guides explain what the service provides, this one covers what goes wrong when you call it automatically. The behavior described here was confirmed by making real calls, and "Obligations and limits" restates rules from the official documentation. Because each game offers a different set of endpoints, this page carries only the rules common to every game rather than examples from one of them. The {game} segment in a path is where the game identifier goes. That identifier is the first segment of the paths in the game's spec file (see "Getting the whole specification at once"); do not guess it from the game's name.
How to use this page
- "An API Key is scoped to one game" — confirm which game your key covers first.
- "Obligations and limits" — check the call limits and the data refresh obligation before you design anything.
- "Making a request" — apply the header. Read "The date parameter rule" only when the API you call takes a date parameter. Most APIs do not.
- "Error handling" — separate the codes worth retrying from the ones that are not.
- "Count the calls before you start" — count what one screen needs, then add a cache.
- "Agent checklist" — run the final checklist to catch what is missing.
30-second summary
The minimum an agent needs to remember.
| Item | Value |
|---|---|
| API host | https://open.api.nexon.com. Some static assets such as images are served from another host named in the spec file's servers |
| Authentication | HTTP header x-nxopen-api-key. Open ID APIs use Authorization: Bearer {Access Token}. /static/ metadata needs none |
| Method | GET only |
| Response format | JSON |
| date parameter | Only some APIs take it. If optional, omit it for the latest; if required, omitting it returns 400 |
| Key scope | Per game (application). One key cannot call another game |
| Call limits | Development phase 5 requests/sec and 1,000/day; launch stage 500 requests/sec and 20,000,000/day |
| Data refresh obligation | Data pulled through the API must be updated at least every 30 days |
| Lookup pattern | Games with an identifier lookup API take two steps: name, identifier, details. Games without one call list or search APIs directly |
| Attribution | Data based on NEXON Open API |
The docs site and the API host are different
The documentation lives at https://openapi.nexon.com, while calls go to https://open.api.nexon.com. Mixing them up fails the whole path.
The overall flow
An agent goes through the following steps. Each step fails in a different way, so confirm one before moving to the next.
- Sign in with a NEXON ID and register an application to receive an API Key.
- Check the API list and parameters for the game you will use.
- Convert a name into an identifier. Skip this step for games without an identifier lookup API.
- Request the details with that identifier.
- Read the error code to decide whether to retry or stop.
- Cache the response and show the attribution on screen.
An API Key is scoped to one game
This is the most common thing to get caught on. NEXON Open API registers applications (keys) per game. Calling another game's path with a key rejects the path itself. Calling another game's path with one game's key returns OPENAPI00006, and the reverse is the same. Reading that code only as "a typo in the path" will not lead you to the cause.
| Situation | Response | What the agent should do |
|---|---|---|
| A path for a game the key covers | 200 | Normal |
| A path for a game the key does not cover | 400 OPENAPI00006 | Issue a separate key for that game. Retrying is pointless |
| A path that does not exist | 400 OPENAPI00006 | Same code as above. Check both the path and the key's registration |
When you handle several games
Store a key per game and select the key by looking at the first segment of the request path. If you keep only one key, everything fails silently the moment you add a game. Call quotas are also summed per application, so splitting keys by game splits the quota as well. Diagnostic code must follow the same key-selection rule. Code that checks permissions with only the default key will report "blocked" even when a per-game key exists.
NXOPEN_API_KEY_{gameA}=... use this key when the first path segment is {gameA}
NXOPEN_API_KEY_{gameB}=... use this key when the first path segment is {gameB}
Obligations and limits
These rules come from the official Getting Started page. They matter at design time, so they are restated here.
Data refresh obligation
You must update the data pulled from NEXON Open API at least every thirty (30) days. If you store responses, record when you received them and fetch them again before 30 days pass. Long-lived stored data needs an expiry of its own, separate from any short cache.
Application types and call limits
| Application type | Limit per second | Daily limit |
|---|---|---|
| Development phase | 5 requests | 1,000 requests |
| Launch stage | 500 requests | 20,000,000 requests |
The officially recommended order is to build and test with a development phase application, then register a new launch stage application once your service URL is ready. Moving to the launch stage requires issuing a new API Key.
Issuance rules
- Up to two API Keys can be issued per application.
- Up to three applications can be registered for the same game with one NEXON ID.
Treat the identifier as a secret
The identifier you receive from a name lookup exists to query internal data. It is not a value meant to be shown on screen. In our measurements the identifier length was not consistent — it came back as 32 or 64 characters — and when it was 64 characters, the trailing 32 matched the trailing 32 of the API Key in use. Those 32 characters are tied to the issuing account.
What the identifier looks like
API Key {env}_..............................<32 chars tied to the account>
Identifier <32 chars that differ per target><32 chars tied to the account>
Length is not a reliable test — there are 64-character identifiers that carry no key fragment.
Some games announce that identifiers can change. Do not store identifiers for long; if you store them, keep a path that fetches them again by name.
What to follow
Length is not a reliable test. Rather than trying to tell them apart by length, check the actual value right before you store it.
| Do not | Instead |
|---|---|
| Put identifier values in cache or log file names | Keep only the parameter name and hash the value |
| Leave raw identifiers in logs and error messages | Keep only the first 8 characters |
| Send identifiers to the frontend and put them in URLs | Use them only inside the server |
| Paste real responses into documents or issues | Redact the values first |
Move the check into code
Do not leave the rule to human attention. Right before storing a response, check whether the trailing 32 characters of your API Key appear in the body, and skip the write if they do.
Storage schema
Size identifier columns to at least 64 characters. Fixing them at 32 truncates the values that arrive as 64.
Making a request
Every API is a GET, and request bodies are not used. The authentication header differs per API; the parameter marked in: header in the spec is that API's authentication header.
| Applies to | Header | Value |
|---|---|---|
| Most APIs | x-nxopen-api-key | The API Key you were issued |
| Open ID APIs | Authorization | Bearer {Access Token} |
| Metadata whose path starts with /static/ | None | Fetched without authentication |
Open ID APIs
APIs whose spec category name carries Open ID return data that needs the user's own consent. You call them not with an API Key but with the Access Token issued when the user signs in with NEXON Open ID. Handle Access Tokens only on the server. NEXON Open ID is offered through the Friends Program, and its development guide is visible only after signing in with a NEXON account.
Metadata without authentication, and other hosts
Metadata whose path starts with /static/ is static JSON, so you can fetch it without an API Key. Use it to turn code values in responses into names or images. Even for a game you have no key for, some screens can be built from metadata alone. A placeholder such as {language_code} in a path is a path substitution, not a query parameter. A query string builder will not fill it in, so insert it yourself. Each spec file has its own servers, and some files, such as images, point somewhere other than the API host. Calling those paths on the API host returns 400. Do not drop servers when you merge spec files.
Response format
A successful response is JSON containing the data you asked for. A failure arrives as an error object holding name and message. Do not put message straight into user-facing text — see "What to show the user" below.
{ "error": { "name": "OPENAPI00004", "message": "Please input valid parameter" } }
Parameter encoding
Values that contain non-ASCII text, such as names, need URL encoding. Building the query string with a proper encoder is safer than concatenating strings yourself. The braces in the example below are placeholders. Identifier parameter names differ per game — more than five distinct names are in use across the published specifications. Read them from the specification rather than guessing.
# 1) Get the identifier by name
curl -G 'https://open.api.nexon.com/{game}/v1/id' \
--data-urlencode '{name_parameter}=TARGET_NAME' \
-H 'x-nxopen-api-key: YOUR_API_KEY_HERE'
# 2) Get the details with that identifier. Omit date to get the latest data.
curl -G 'https://open.api.nexon.com/{game}/v1/{resource}' \
--data-urlencode '{identifier_parameter}=RECEIVED_IDENTIFIER' \
-H 'x-nxopen-api-key: YOUR_API_KEY_HERE'
# Parameter names differ by game. Read them from the spec.
The date parameter rule
Only some APIs take a date parameter. Check the spec of the API you call: does it have date, and if so, is it required? The rules differ between optional and required.
"Today" and "yesterday" in the tables below are counted in that API's reference time zone. The time zone is stated in the spec's date description (besides KST, some games use their service region's time, such as SGT or TST), and it can differ between APIs of the same game. Do not compute it from the server's local time.
When date is optional
| date value | Result |
|---|---|
| Omitted | 200. Latest data. The date field in the response is null |
| Yesterday | 200. Snapshot from one day earlier |
| Today | 400 OPENAPI00004 |
| A future date | 400 OPENAPI00004 |
| Before the service opened | 200, but every field except the requested date is null |
When date is required
On APIs where date is required, such as rankings, omitting it returns an error instead of the latest data. Unlike optional-date APIs, they also accept today's date.
| date value | Result |
|---|---|
| Omitted | 400 OPENAPI00004 |
| Yesterday | 200 |
| Today | 200 |
| A future date | 400 OPENAPI00009 |
| Earlier than the first available date | 400 OPENAPI00009 or OPENAPI00004 — differs per API |
Today's date works only after that day's data has been compiled (see "When data becomes available" below). Default to yesterday.
A future date returns OPENAPI00009 (data is being prepared). Some APIs also return 00009 for past dates earlier than the first available date.
When data becomes available
The time from which a day's data can be queried differs per API and is written in the spec's description. Some APIs open the previous day's data only in the early hours of the next day; others open today's rankings during the morning. Before that time, the data for that date does not exist. Code that fills in dates automatically should use the time given in the description, not midnight.
The available range differs per API
How far back you can go differs per API, and the first queryable date is also written in the description. Documented ranges and actual behavior do not always agree, so we recommend calling the boundary values yourself before building a date picker. In some games the queryable range is written only at the top of the spec (info), not on the endpoint — see "Do not take the specification at face value" below.
Error handling
This is the most important section for an agent. Retrying a code that should not be retried only doubles the quota you spend.
| Code | HTTP | Retry | Why |
|---|---|---|---|
| OPENAPI00001 | 500 | Yes | Internal server error. Retry after a backoff |
| OPENAPI00002 | 403 | No | Not permitted. Check the key and the target |
| OPENAPI00003 | 400 | No | Invalid identifier. Sending the same request again does not change the result |
| OPENAPI00004 | 400 | No | Missing parameter, or the target does not exist. This does not change over time |
| OPENAPI00005 | 400 | No | Invalid API Key |
| OPENAPI00006 | 400 | No | A game the key does not cover, or a wrong path |
| OPENAPI00007 | 429 | Yes | Quota exceeded. A backoff is required |
| OPENAPI00009 | 400 | Yes | Data is being prepared. Retry shortly. It also comes for requests with a date or out-of-range input, so stop if one retry returns the same |
| OPENAPI00010 | 400 | Yes | The game is under maintenance |
| OPENAPI00011 | 503 | Yes | The API is under maintenance |
Retry with backoff and jitter
Retrying at a fixed interval bunches requests at the same moment and recreates OPENAPI00007. Use exponential backoff with jitter to spread them out.
What to show the user
Do not put the official description of an error code straight on screen. OPENAPI00004 is described as "missing or invalid parameter", but looking up a name that does not exist returns the same code. If the screen says "invalid parameter", the user reads it as a broken service rather than as their own input. Replace it with wording that fits the situation, such as "We could not find that name".
Do not treat step one as proof of existence
Even when the name lookup returns an identifier, requesting details with that identifier can return OPENAPI00003. You only know whether a lookup is possible after the second step. For that reason, avoid showing "Found it" at the moment step one succeeds.
The same "nothing" arrives in different shapes
All of these mean "nothing", but each looks different. Keep the user-facing wording consistent, such as "No record".
| Situation | Response |
|---|---|
| An item with no record | 200 with the field set to 0 (not always null) |
| An unregistered sub-resource | OPENAPI00004 — not a parameter error |
| No data for that day | 200 with every field null |
| A target outside your permission | OPENAPI00004 or OPENAPI00003 — a permission problem that looks like a parameter error |
| The conditions are valid but nothing matches (including a list lookup for a specific target) | 200 with an empty array |
| A slot with no value | Some games return a placeholder string such as "(Unknown)" instead of null |
When HTTP 200 does not mean success
There are responses that return 200 with no error, yet every field except the requested date is null. Querying a date from before the service opened is one such case. An implementation that checks only the status code and the error code accepts this as normal and stores empty values. Check whether the key fields are null as well.
# A date before the service started returns 200, not an error.
curl -G 'https://open.api.nexon.com/{game}/v1/{resource}' \
--data-urlencode '{identifier_parameter}=RECEIVED_IDENTIFIER' \
--data-urlencode 'date=2023-12-20' \
-H 'x-nxopen-api-key: YOUR_API_KEY_HERE'
# HTTP 200
# { "date": "2023-12-20T00:00+09:00", "<name field>": null, "<level field>": null, ... } ← only the requested date is filled in; everything else is null
#
# An implementation that checks only the status code and the error code accepts this as normal.
# Check whether the key fields are null as well. Do not decide by the date field — a normal response with date omitted also has date null.
There are also parameters where a value outside the enum is silently ignored rather than rejected with 400. A typo or an old name in a filter value comes back as a 200 with the filter dropped — the full, unfiltered result — and this differs per parameter even within one API. Pick filter values only from the spec's enum, and check that the corresponding field in each response row matches what you asked for.
Count the calls before you start
A number like "N requests per second" is hard to reason about. Counting how many calls one screen needs makes it obvious that caching is not optional. Below is a measurement for drawing a single profile card.
| Step | Calls |
|---|---|
| Name to identifier | 1 |
| Basic information | 1 |
| Stats and detail lookups | 6 |
| Total | 8 |
Adding rankings roughly doubles it
The 8 calls above are for a basic profile. Putting ranking badges on the card brings it to 13 to 15 calls, because the ranking API returns one kind of ranking per call. A development-stage key cannot draw even one card in a single pass. Building the cache first is the faster path.
Ask for one target's rank instead of scanning the list
When a list or ranking API has an identifier parameter, passing it returns only that target's row (other filters still apply). Paging through the list to find one target's rank multiplies the calls by hundreds. Be aware, though, that on some APIs the default value of an optional parameter fixes the segment being searched. When a lookup for a specific target returns nothing, ask once more with the segment value that target belongs to before concluding "no record". Defaults are written only in the spec's description.
Cache effect
Game data changes slowly, so a cache keyed by (endpoint, identifier, date) works well. One cache gives a 16x difference. Treat caching as a precondition for using this API, not an optimization. Bound concurrency below the quota with a semaphore or token bucket, and put a timeout on every call. Isolate failures so that one lookup cannot block the whole screen.
| Item | Value |
|---|---|
| Cache miss | 179ms |
| Cache hit | 11ms |
| Sequential throughput | 8.0 req/s (20 in a row, no 429) |
Building aggregates the API does not provide
Values the API does not return directly, such as population by class or a ranking by combat power, have to be counted yourself from several pages of rankings. Two things deserve care.
- The sample is the top N of a ranking, not the whole player base. If you do not state the sample range on screen, readers take it as the overall distribution.
- When the ranking response carries no identifier, attaching detail values costs an extra call per entry. The cost multiplies by the sample size.
Record what the count was based on
Carry the sample range in the response alongside the aggregate. Once only the number survives, nobody can interpret it.
Paging through a list
- page starts at 1. 0 returns OPENAPI00004.
- Past the last page, some games return an empty array and others return OPENAPI00004. Treat both as "the end".
- The number of rows per page is not fixed. Ties make a page larger or smaller than the nominal size. Do not compute the rank as (page−1)×size+i; use the rank field in the response, and do not treat "fewer than the nominal size" as the last page.
- For cursor-based lists, check the sort direction first. If they arrive oldest first, reaching the latest value costs as many calls as there are pages. Some games return OPENAPI00003 for a malformed cursor, and you cannot skip pages.
Response fields that actually caught us
Guessing a field's meaning from its name goes wrong in places.
| Easy to assume | Actual |
|---|---|
A ..._part field is the equipped slot |
It can be the item category. The slot is the ..._slot field |
| No record means null | Some fields return 0. A null check will not catch it |
| Numeric fields hold numbers | Some arrive as strings. Convert before comparing or sorting |
| List-shaped fields are objects | Some are arrays. Look entries up by name |
| Timestamps are in KST | Some games return Z (UTC). See "Time fields in responses" below |
Time fields in responses
The time zone of timestamps in responses differs per game. Some games return +09:00; others return Z (UTC, with milliseconds). If you take the first 10 characters of the string as the date, UTC responses shift by a day. Parse the value, then convert it to the service's reference time zone. For the time zone of the date parameter, see "The date parameter rule".
Do not discard values you do not recognize
A game update can add a new slot or a new grade. Dropping anything missing from an allow-list makes data disappear quietly with every update. Appending unknown values and logging them is safer.
Getting the whole specification at once
Instead of clicking through the documentation per game, download the specification files and read them in one pass so an agent can work with them. Building a list of which endpoints exist for which game removes any need to guess paths.
# The list of games currently offered and their spec files
curl -s 'https://openapi.nexon.com/static/script/specification.json'
# Download each game's OpenAPI spec from the paths in that list.
# With the specs on hand, the agent can read endpoints, parameters, and required flags directly.
# The first segment of the paths in a spec file (/{game}/v1/...) is the game identifier to use in URLs.
#
# Caution: the spec's required flag sometimes cannot express a conditional requirement.
# Even when required is false, follow any condition written in the description.
Do not take the specification at face value
Some parameters are marked required: false but carry a condition in the description. Omitting them on a request that meets the condition returns OPENAPI00004. The specification cannot express "conditionally required". Read the description too when you use a new endpoint. Response schemas can also differ from reality. Field names, numbers versus strings, arrays versus objects, and whether the top level is an array or an object have all come back differently, and fields without a nullable mark still return null. Before writing parsing code, compare one real response per endpoint with the schema, and follow the real response where they differ. Rules that apply to a whole game — the delay before data is reflected, the first queryable date, a notice that identifiers may change — are sometimes written only in info.description at the top of the spec, not on any endpoint. Read info first even for games without date. The dates in info have also been wrong in practice, so confirm boundary values by calling them.
When you download the specification
- No authentication is needed. The index and each specification file are available without a key.
- Keep the bytes exactly as received. Converting line endings makes parser verification meaningless.
- Stop on a parse failure instead of swallowing it. It signals that the published format changed.
Agent checklist
Go through the items below once the implementation is done.
Always do
- Keep the API Key on the server, never in the frontend or a repository.
- On APIs where date is optional, pass it only when you need it and omit it for the latest value. On APIs where date is required, never omit it.
- Retry only on 429, 5xx, and maintenance codes, together with a backoff.
- Check whether the key fields are null even when you receive a 200.
- Cache responses, and keep raw identifiers out of the cache key.
- Show Data based on NEXON Open API in your service.
- If you store responses, fetch them again within 30 days.
- Confirm that the call volume you designed fits within your application type's limits.
- Pick filter values only from the spec's enum, and check that each response row matches the filter you asked for.
Never do
- Leave raw identifiers in logs, file names, or URLs.
- Retry OPENAPI00003, 00004, or 00006.
- Use a successful step-one lookup as proof that the target exists.
- Put the official description of an error code straight into user-facing text.
- Present an aggregate as an overall statistic without stating the sample range.
- Page through a list to find one target's rank. Ask directly with the identifier parameter.
Standard call procedure
1. Pick this game's API Key from the first path segment
2. Name -> identifier (when an identifier lookup API exists; stop immediately on failure; do not retry)
3. Identifier -> details (omit date when you want the latest)
4. Check key fields for null even on a 200
5. Cache the successful response (never put the raw identifier in the key)
6. Show the attribution on screen
Related documents
This page covers only what goes wrong under automated calls. For the service overview and basic usage, see the documents below.
- Getting Started — signing in with a NEXON ID and registering an application
- Using the API — API lookup, testing, and the error code table
- Games — endpoints and parameters per game
- Notices — history of endpoint additions and changes. Check here first when this document and the actual behavior disagree
- Terms of Service — the conditions that apply to what you build
- Apply for the Friends Program — required before you can use Open ID APIs (sign-in required)
Glossary
| Term | Meaning |
|---|---|
| Application | The unit an API Key is issued for. Registered per game |
| API Key | The credential sent in the x-nxopen-api-key header. Issued when you register an application |
| Identifier | The internal lookup value returned from a name lookup. Treat it as a secret |
| Quota | The call limit, summed per application |
| Specification | The OpenAPI document listing endpoints and parameters per game |