# Quest Platform

# Introduction {% #overview %}

The Quest Platform runs **quests** for your game: rules of the form ***when a player does this, do that***. You describe the rule once. The platform then watches what your players do, remembers how far each of them has got, and when they get there it runs the quest's **actions**: give a reward, email the player, or both.

{% admonition type="info" name="One example, all the way through" %}
*A player who finishes three levels in a week gets a chest in your game.* This page builds that quest from a drawing to JSON, and the guides send it for real.
{% /admonition %}

{% cards columns=3 cardMinWidth=150 %}
{% card title="New to quests" to="/api/quests/quest-anatomy" linkIcon="arrow" %}
Read this page top to bottom.
{% /card %}
{% card title="Publisher" to="/api/quests/publisher-guide" linkIcon="arrow" %}
Onboard your project yourself.
{% /card %}
{% /cards %}

## What a quest looks like {% #quest-anatomy %}

Draw the chest quest on paper and you get three boxes joined by arrows:

{% img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0MDAiIGhlaWdodD0iOTYiIHZpZXdCb3g9IjAgMCA0MDAgOTYiIGZvbnQtZmFtaWx5PSJJbnRlciwgLWFwcGxlLXN5c3RlbSwgJ1NlZ29lIFVJJywgUm9ib3RvLCBzYW5zLXNlcmlmIj48ZGVmcz48bWFya2VyIGlkPSJhIiB2aWV3Qm94PSIwIDAgMTAgMTAiIHJlZlg9IjkiIHJlZlk9IjUiIG1hcmtlcldpZHRoPSI3IiBtYXJrZXJIZWlnaHQ9IjciIG9yaWVudD0iYXV0by1zdGFydC1yZXZlcnNlIj48cGF0aCBkPSJNMCAwTDEwIDVMMCAxMHoiIGZpbGw9IiM4Yjk1YTciLz48L21hcmtlcj48L2RlZnM+PHJlY3QgeD0iMSIgeT0iMiIgd2lkdGg9IjExNiIgaGVpZ2h0PSI2NiIgcng9IjgiIGZpbGw9IiM1MjcwOWEiLz48dGV4dCB4PSI1OS4wIiB5PSIxOCIgZm9udC1zaXplPSIxMCIgbGV0dGVyLXNwYWNpbmc9IjEiIGZpbGw9IiNmZmYiIGZpbGwtb3BhY2l0eT0iLjgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPlRSSUdHRVI8L3RleHQ+PHRleHQgeD0iNTkuMCIgeT0iMzYiIGZvbnQtc2l6ZT0iMTMiIGZvbnQtd2VpZ2h0PSI2MDAiIGZpbGw9IiNmZmYiIHRleHQtYW5jaG9yPSJtaWRkbGUiPkxldmVsPC90ZXh0Pjx0ZXh0IHg9IjU5LjAiIHk9IjUyIiBmb250LXNpemU9IjEzIiBmb250LXdlaWdodD0iNjAwIiBmaWxsPSIjZmZmIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5jb21wbGV0ZWQ8L3RleHQ+PHRleHQgeD0iNTkuMCIgeT0iODgiIGZvbnQtc2l6ZT0iMTIiIGZvbnQtd2VpZ2h0PSI0MDAiIGZpbGw9IiM4Yjk1YTciIHRleHQtYW5jaG9yPSJtaWRkbGUiPndoYXQgc3RhcnRzIGl0PC90ZXh0PjxyZWN0IHg9IjE0MyIgeT0iMiIgd2lkdGg9IjExNiIgaGVpZ2h0PSI2NiIgcng9IjgiIGZpbGw9IiM5MzdhNTIiLz48dGV4dCB4PSIyMDEuMCIgeT0iMTgiIGZvbnQtc2l6ZT0iMTAiIGxldHRlci1zcGFjaW5nPSIxIiBmaWxsPSIjZmZmIiBmaWxsLW9wYWNpdHk9Ii44IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5DT05ESVRJT048L3RleHQ+PHRleHQgeD0iMjAxLjAiIHk9IjM2IiBmb250LXNpemU9IjEzIiBmb250LXdlaWdodD0iNjAwIiBmaWxsPSIjZmZmIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5UaHJlZSBsZXZlbHM8L3RleHQ+PHRleHQgeD0iMjAxLjAiIHk9IjUyIiBmb250LXNpemU9IjEzIiBmb250LXdlaWdodD0iNjAwIiBmaWxsPSIjZmZmIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj50aGlzIHdlZWs8L3RleHQ+PHRleHQgeD0iMjAxLjAiIHk9Ijg4IiBmb250LXNpemU9IjEyIiBmb250LXdlaWdodD0iNDAwIiBmaWxsPSIjOGI5NWE3IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj53aGF0IG11c3QgYmUgdHJ1ZTwvdGV4dD48cGF0aCBkPSJNMTE3IDM1LjAgTDE0MSAzNS4wIiBmaWxsPSJub25lIiBzdHJva2U9IiM4Yjk1YTciIHN0cm9rZS13aWR0aD0iMS42IiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+PHJlY3QgeD0iMjg1IiB5PSIyIiB3aWR0aD0iMTE2IiBoZWlnaHQ9IjY2IiByeD0iOCIgZmlsbD0iIzRkODE2OSIvPjx0ZXh0IHg9IjM0My4wIiB5PSIxOCIgZm9udC1zaXplPSIxMCIgbGV0dGVyLXNwYWNpbmc9IjEiIGZpbGw9IiNmZmYiIGZpbGwtb3BhY2l0eT0iLjgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPkFDVElPTjwvdGV4dD48dGV4dCB4PSIzNDMuMCIgeT0iMzYiIGZvbnQtc2l6ZT0iMTMiIGZvbnQtd2VpZ2h0PSI2MDAiIGZpbGw9IiNmZmYiIHRleHQtYW5jaG9yPSJtaWRkbGUiPkdpdmUgYTwvdGV4dD48dGV4dCB4PSIzNDMuMCIgeT0iNTIiIGZvbnQtc2l6ZT0iMTMiIGZvbnQtd2VpZ2h0PSI2MDAiIGZpbGw9IiNmZmYiIHRleHQtYW5jaG9yPSJtaWRkbGUiPmNoZXN0PC90ZXh0Pjx0ZXh0IHg9IjM0My4wIiB5PSI4OCIgZm9udC1zaXplPSIxMiIgZm9udC13ZWlnaHQ9IjQwMCIgZmlsbD0iIzhiOTVhNyIgdGV4dC1hbmNob3I9Im1pZGRsZSI+d2hhdCBoYXBwZW5zIHRoZW48L3RleHQ+PHBhdGggZD0iTTI1OSAzNS4wIEwyODMgMzUuMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOGI5NWE3IiBzdHJva2Utd2lkdGg9IjEuNiIgbWFya2VyLWVuZD0idXJsKCNhKSIvPjwvc3ZnPgo=" alt="The chest quest: Level completed (trigger), then Three levels this week (condition), then Give a chest (action)" /%}

{% admonition type="info" name="That drawing is the quest" %}
Each box is a **node**: one step that does one thing. Each arrow is a **connection**: it says which node comes next. Everything else in these docs adds to these two ideas.
{% /admonition %}

There are three kinds of node, and the chest quest uses one of each:

{% cards columns=3 cardMinWidth=150 %}
{% card title="Trigger" %}
**Starts the quest** when something happens.

*A player completed a level.*
{% /card %}
{% card title="Condition" %}
**Lets the quest go on** only if something is true.

*At least 3 levels this week.*
{% /card %}
{% card title="Action" %}
**Does something**: gives a reward or sends an email.

*Give the player a chest.*
{% /card %}
{% /cards %}

### Follow one player {% #quest-walkthrough %}

Your game tells the platform what players do by sending **events**: short messages such as "player 42 completed a level", named `level_completed`. Here is one player's week; each day they finish a level and your game sends `level_completed`:

- **Monday: 1 level**

  The trigger starts the quest. The condition counts 1 level this week, not 3, so the quest stops. Nothing is given.

- **Tuesday: 2 levels**

  Same again: still under 3, so the quest stops.

- **Wednesday: 3 levels**

  The condition passes and the action gives the chest. The player has **completed** the quest.

{% admonition type="success" name="You never count levels yourself" %}
Each pass through the quest, from the trigger onwards, is a **run**. The platform keeps each player's **progress** on each quest (`not_started`, `in_progress`, `completed`, or `expired` for an unfinished run once the quest has ended), so your game can show it. A completed quest reads `not_started` again while the player's `per_user` limit still allows another completion. Without a `per_user` limit it stays `completed`.
{% /admonition %}

### Bigger quests are graphs {% #quest-graph %}

A quest doesn't have to be a straight line. A node can lead to several nodes, and each of those to more, so a quest can branch into a tree as wide and as deep as it needs:

{% img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0MDAiIGhlaWdodD0iMjI0IiB2aWV3Qm94PSIwIDAgNDAwIDIyNCIgZm9udC1mYW1pbHk9IkludGVyLCAtYXBwbGUtc3lzdGVtLCAnU2Vnb2UgVUknLCBSb2JvdG8sIHNhbnMtc2VyaWYiPjxkZWZzPjxtYXJrZXIgaWQ9ImEiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iOSIgcmVmWT0iNSIgbWFya2VyV2lkdGg9IjciIG1hcmtlckhlaWdodD0iNyIgb3JpZW50PSJhdXRvLXN0YXJ0LXJldmVyc2UiPjxwYXRoIGQ9Ik0wIDBMMTAgNUwwIDEweiIgZmlsbD0iIzhiOTVhNyIvPjwvbWFya2VyPjwvZGVmcz48cmVjdCB4PSIxIiB5PSIyIiB3aWR0aD0iMTcwIiBoZWlnaHQ9IjY2IiByeD0iOCIgZmlsbD0iIzUyNzA5YSIvPjx0ZXh0IHg9Ijg2LjAiIHk9IjE4IiBmb250LXNpemU9IjEwIiBsZXR0ZXItc3BhY2luZz0iMSIgZmlsbD0iI2ZmZiIgZmlsbC1vcGFjaXR5PSIuOCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+VFJJR0dFUjwvdGV4dD48dGV4dCB4PSI4Ni4wIiB5PSIzNiIgZm9udC1zaXplPSIxMyIgZm9udC13ZWlnaHQ9IjYwMCIgZmlsbD0iI2ZmZiIgdGV4dC1hbmNob3I9Im1pZGRsZSI+TGV2ZWwgY29tcGxldGVkPC90ZXh0PjxyZWN0IHg9IjIyOSIgeT0iMiIgd2lkdGg9IjE3MCIgaGVpZ2h0PSI2NiIgcng9IjgiIGZpbGw9IiM5MzdhNTIiLz48dGV4dCB4PSIzMTQuMCIgeT0iMTgiIGZvbnQtc2l6ZT0iMTAiIGxldHRlci1zcGFjaW5nPSIxIiBmaWxsPSIjZmZmIiBmaWxsLW9wYWNpdHk9Ii44IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5DT05ESVRJT048L3RleHQ+PHRleHQgeD0iMzE0LjAiIHk9IjM2IiBmb250LXNpemU9IjEzIiBmb250LXdlaWdodD0iNjAwIiBmaWxsPSIjZmZmIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5UaHJlZSBsZXZlbHM8L3RleHQ+PHRleHQgeD0iMzE0LjAiIHk9IjUyIiBmb250LXNpemU9IjEzIiBmb250LXdlaWdodD0iNjAwIiBmaWxsPSIjZmZmIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj50aGlzIHdlZWs8L3RleHQ+PHBhdGggZD0iTTE3MSAzNS4wIEwyMjcgMzUuMCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOGI5NWE3IiBzdHJva2Utd2lkdGg9IjEuNiIgbWFya2VyLWVuZD0idXJsKCNhKSIvPjxwYXRoIGQ9Ik0zMTQgNjggTDMxNCA4NCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOGI5NWE3IiBzdHJva2Utd2lkdGg9IjEuNiIvPjxwYXRoIGQ9Ik02MCA4NCBMMzQwIDg0IiBmaWxsPSJub25lIiBzdHJva2U9IiM4Yjk1YTciIHN0cm9rZS13aWR0aD0iMS42Ii8+PHJlY3QgeD0iMSIgeT0iMTAyIiB3aWR0aD0iMTE4IiBoZWlnaHQ9IjUwIiByeD0iOCIgZmlsbD0iIzRkODE2OSIvPjx0ZXh0IHg9IjYwLjAiIHk9IjEzMS41IiBmb250LXNpemU9IjEzIiBmb250LXdlaWdodD0iNjAwIiBmaWxsPSIjZmZmIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5HaXZlIGEgY2hlc3Q8L3RleHQ+PHBhdGggZD0iTTYwIDg0IEw2MCAxMDAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzhiOTVhNyIgc3Ryb2tlLXdpZHRoPSIxLjYiIG1hcmtlci1lbmQ9InVybCgjYSkiLz48cmVjdCB4PSIxNDEiIHk9IjEwMiIgd2lkdGg9IjExOCIgaGVpZ2h0PSI1MCIgcng9IjgiIGZpbGw9IiM0ZDgxNjkiLz48dGV4dCB4PSIyMDAuMCIgeT0iMTIzLjUiIGZvbnQtc2l6ZT0iMTMiIGZvbnQtd2VpZ2h0PSI2MDAiIGZpbGw9IiNmZmYiIHRleHQtYW5jaG9yPSJtaWRkbGUiPkJhZGdlIGluIHRoZTwvdGV4dD48dGV4dCB4PSIyMDAuMCIgeT0iMTM5LjUiIGZvbnQtc2l6ZT0iMTMiIGZvbnQtd2VpZ2h0PSI2MDAiIGZpbGw9IiNmZmYiIHRleHQtYW5jaG9yPSJtaWRkbGUiPkJhY2twYWNrPC90ZXh0PjxwYXRoIGQ9Ik0yMDAgODQgTDIwMCAxMDAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzhiOTVhNyIgc3Ryb2tlLXdpZHRoPSIxLjYiIG1hcmtlci1lbmQ9InVybCgjYSkiLz48cmVjdCB4PSIyODEiIHk9IjEwMiIgd2lkdGg9IjExOCIgaGVpZ2h0PSI1MCIgcng9IjgiIGZpbGw9IiM0ZDgxNjkiLz48dGV4dCB4PSIzNDAuMCIgeT0iMTIzLjUiIGZvbnQtc2l6ZT0iMTMiIGZvbnQtd2VpZ2h0PSI2MDAiIGZpbGw9IiNmZmYiIHRleHQtYW5jaG9yPSJtaWRkbGUiPkVtYWlsIHRoZTwvdGV4dD48dGV4dCB4PSIzNDAuMCIgeT0iMTM5LjUiIGZvbnQtc2l6ZT0iMTMiIGZvbnQtd2VpZ2h0PSI2MDAiIGZpbGw9IiNmZmYiIHRleHQtYW5jaG9yPSJtaWRkbGUiPnBsYXllcjwvdGV4dD48cGF0aCBkPSJNMzQwIDg0IEwzNDAgMTAwIiBmaWxsPSJub25lIiBzdHJva2U9IiM4Yjk1YTciIHN0cm9rZS13aWR0aD0iMS42IiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+PHBhdGggZD0iTTYwIDE1MiBMNjAgMTgwIiBmaWxsPSJub25lIiBzdHJva2U9IiM4Yjk1YTciIHN0cm9rZS13aWR0aD0iMS42IiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+PHJlY3QgeD0iMSIgeT0iMTgyIiB3aWR0aD0iMTE4IiBoZWlnaHQ9IjQwIiByeD0iOCIgZmlsbD0iIzRkODE2OSIvPjx0ZXh0IHg9IjYwLjAiIHk9IjIwNi41IiBmb250LXNpemU9IjEzIiBmb250LXdlaWdodD0iNjAwIiBmaWxsPSIjZmZmIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5UZWxsIHRoZSBwbGF5ZXI8L3RleHQ+PC9zdmc+Cg==" alt="A quest as a graph: the condition leads to three actions, and Give a chest leads on to Tell the player" /%}

{% cards columns=3 cardMinWidth=150 %}
{% card title="Branch out" %}
A node can lead to any number of nodes, and every one of them runs, in the order listed.
{% /card %}
{% card title="Chain" %}
A node runs only after the one before it succeeded, so "Tell the player" comes after the chest.
{% /card %}
{% card title="Gate" %}
A condition decides whether everything after it runs.
{% /card %}
{% /cards %}

{% admonition type="warning" name="Two rules keep a graph predictable" %}
Arrows can't loop back to an earlier node, and the first condition that is not met, or action that fails, ends the run. So put the action that matters most first.
{% /admonition %}

## Writing the quest down {% #quest-json %}

You [create a quest](/api/quests/publisher-api/create-quest-in-project) by sending it to the platform as JSON. The JSON says exactly what the drawing says, in three steps:

**1. Write each box as a node**

Every [node](/api/quests/quest-nodes) has an `id` you make up, a `name`, its kind (`type`), what exactly it does (`subtype`) and its settings (`parameters`):

{% tabs %}
{% tab label="Trigger" %}
**Level completed**: a [dynamic_event](/api/quests/node-dynamic-event) trigger, waiting for `level_completed`.

```json
{
  "id": "0f2c6d1e-3b4a-4c5d-8e9f-101112131415",
  "name": "Level completed",
  "type": "trigger",
  "subtype": "dynamic_event",
  "parameters": {
    "event_name": "level_completed"
  }
}
```
{% /tab %}
{% tab label="Condition" %}
**Three levels this week**: a [custom_attributes_check](/api/quests/node-custom-attributes-check) condition, at least 3 `level_completed` events this week. Its `parameters` are shortened here; the whole quest in step 3 shows them in full.

```json
{
  "id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
  "name": "Three levels this week",
  "type": "condition",
  "subtype": "custom_attributes_check",
  "parameters": {
    "type": "comparison",
    // …
  }
}
```
{% /tab %}
{% tab label="Action" %}
**Give a chest**: an [issue_game_item](/api/quests/node-issue-game-item) action, giving the player 1 × `weekly_chest`.

```json
{
  "id": "2b3c4d5e-6f7a-4b8c-9d0e-1f2a3b4c5d6e",
  "name": "Give a chest",
  "type": "action",
  "subtype": "issue_game_item",
  "parameters": {
    "purpose": "weekly_level_grinder",
    "items": [
      {
        "sku": "weekly_chest",
        "quantity": 1
      }
    ]
  }
}
```
{% /tab %}
{% /tabs %}

[**Quest nodes**](/api/quests/quest-nodes) lists every `subtype` and its parameters.

**2. Draw the arrows as connections**

Each arrow is one entry in [connections](/api/quests/connections): the `id` of the node it starts from, and the `id` of the node it points to.

```json
"connections": {
  "0f2c6d1e-3b4a-4c5d-8e9f-101112131415": [
    {
      "nodeId": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d"
    }
  ],
  "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d": [
    {
      "nodeId": "2b3c4d5e-6f7a-4b8c-9d0e-1f2a3b4c5d6e"
    }
  ]
}
```

Read it as "after *Level completed* comes *Three levels this week*; after that comes *Give a chest*". The last box has no entry, so the quest ends there. A node with several arrows lists several `nodeId`s.

**3. Wrap them in a quest**

Nodes and connections go inside the quest, next to its name, the dates it runs between and its activation limits. [**Chest for three levels a week**](/api/quests/examples-chest-quest) shows the whole quest, exactly as the guides send it.

A quest runs only while its `status` is `active` and the date is between `start_date` and `end_date`. [**Quest guide**](/api/quests/quest-guide) lists every field and rule.

The [**Publisher guide**](/api/quests/publisher-guide) sends this quest in full.

## How you plug it in {% #how-it-works %}

Every integration does the same three things: it creates quests, sends events as players play, and shows players their progress. The platform does everything in between:

{% img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0MDAiIGhlaWdodD0iMzA2IiB2aWV3Qm94PSIwIDAgNDAwIDMwNiIgZm9udC1mYW1pbHk9IkludGVyLCAtYXBwbGUtc3lzdGVtLCAnU2Vnb2UgVUknLCBSb2JvdG8sIHNhbnMtc2VyaWYiPjxkZWZzPjxtYXJrZXIgaWQ9ImEiIHZpZXdCb3g9IjAgMCAxMCAxMCIgcmVmWD0iOSIgcmVmWT0iNSIgbWFya2VyV2lkdGg9IjciIG1hcmtlckhlaWdodD0iNyIgb3JpZW50PSJhdXRvLXN0YXJ0LXJldmVyc2UiPjxwYXRoIGQ9Ik0wIDBMMTAgNUwwIDEweiIgZmlsbD0iIzhiOTVhNyIvPjwvbWFya2VyPjwvZGVmcz48cmVjdCB4PSIxMzQiIHk9IjQiIHdpZHRoPSIyNjUiIGhlaWdodD0iMjk4IiByeD0iMTIiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzhiOTVhNyIgc3Ryb2tlLWRhc2hhcnJheT0iNiA1Ii8+PHRleHQgeD0iMzkwIiB5PSIyMiIgZm9udC1zaXplPSIxMiIgZm9udC13ZWlnaHQ9IjYwMCIgZmlsbD0iIzhiOTVhNyIgdGV4dC1hbmNob3I9ImVuZCI+UXVlc3QgUGxhdGZvcm08L3RleHQ+PHRleHQgeD0iNjAiIHk9IjE0IiBmb250LXNpemU9IjEyIiBmb250LXdlaWdodD0iNDAwIiBmaWxsPSIjOGI5NWE3IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj55b3VyIGJhY2tlbmQ8L3RleHQ+PHJlY3QgeD0iMSIgeT0iMjIiIHdpZHRoPSIxMTgiIGhlaWdodD0iMzQiIHJ4PSI4IiBmaWxsPSIjNWY2ODc4Ii8+PHRleHQgeD0iNjAuMCIgeT0iNDMuNSIgZm9udC1zaXplPSIxMyIgZm9udC13ZWlnaHQ9IjYwMCIgZmlsbD0iI2ZmZiIgdGV4dC1hbmNob3I9Im1pZGRsZSI+Q3JlYXRlIHF1ZXN0PC90ZXh0PjxyZWN0IHg9IjEiIHk9Ijc0IiB3aWR0aD0iMTE4IiBoZWlnaHQ9IjM0IiByeD0iOCIgZmlsbD0iIzVmNjg3OCIvPjx0ZXh0IHg9IjYwLjAiIHk9Ijk1LjUiIGZvbnQtc2l6ZT0iMTMiIGZvbnQtd2VpZ2h0PSI2MDAiIGZpbGw9IiNmZmYiIHRleHQtYW5jaG9yPSJtaWRkbGUiPlNlbmQgZXZlbnRzPC90ZXh0PjxyZWN0IHg9IjE0NiIgeT0iMjIiIHdpZHRoPSIxMjgiIGhlaWdodD0iMzQiIHJ4PSI4IiBmaWxsPSIjNWY2ODc4Ii8+PHRleHQgeD0iMjEwLjAiIHk9IjQzLjUiIGZvbnQtc2l6ZT0iMTMiIGZvbnQtd2VpZ2h0PSI2MDAiIGZpbGw9IiNmZmYiIHRleHQtYW5jaG9yPSJtaWRkbGUiPlF1ZXN0cyAoc3RvcmVkKTwvdGV4dD48cGF0aCBkPSJNMTE5IDM5IEwxNDQgMzkiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzhiOTVhNyIgc3Ryb2tlLXdpZHRoPSIxLjYiIG1hcmtlci1lbmQ9InVybCgjYSkiLz48cmVjdCB4PSIxNDYiIHk9Ijc0IiB3aWR0aD0iMTA4IiBoZWlnaHQ9IjMwIiByeD0iOCIgZmlsbD0iIzVmNjg3OCIvPjx0ZXh0IHg9IjIwMC4wIiB5PSI5My41IiBmb250LXNpemU9IjEzIiBmb250LXdlaWdodD0iNjAwIiBmaWxsPSIjZmZmIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5tYXRjaDwvdGV4dD48cmVjdCB4PSIxNDYiIHk9IjExOCIgd2lkdGg9IjEwOCIgaGVpZ2h0PSIzMCIgcng9IjgiIGZpbGw9IiM1ZjY4NzgiLz48dGV4dCB4PSIyMDAuMCIgeT0iMTM3LjUiIGZvbnQtc2l6ZT0iMTMiIGZvbnQtd2VpZ2h0PSI2MDAiIGZpbGw9IiNmZmYiIHRleHQtYW5jaG9yPSJtaWRkbGUiPmxpbWl0czwvdGV4dD48cGF0aCBkPSJNMjAwLjAgMTA0IEwyMDAuMCAxMTYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzhiOTVhNyIgc3Ryb2tlLXdpZHRoPSIxLjYiIG1hcmtlci1lbmQ9InVybCgjYSkiLz48cmVjdCB4PSIxNDYiIHk9IjE2MiIgd2lkdGg9IjEwOCIgaGVpZ2h0PSIzMCIgcng9IjgiIGZpbGw9IiM1ZjY4NzgiLz48dGV4dCB4PSIyMDAuMCIgeT0iMTgxLjUiIGZvbnQtc2l6ZT0iMTMiIGZvbnQtd2VpZ2h0PSI2MDAiIGZpbGw9IiNmZmYiIHRleHQtYW5jaG9yPSJtaWRkbGUiPmNvbmRpdGlvbnM8L3RleHQ+PHBhdGggZD0iTTIwMC4wIDE0OCBMMjAwLjAgMTYwIiBmaWxsPSJub25lIiBzdHJva2U9IiM4Yjk1YTciIHN0cm9rZS13aWR0aD0iMS42IiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+PHJlY3QgeD0iMTQ2IiB5PSIyMDYiIHdpZHRoPSIxMDgiIGhlaWdodD0iMzAiIHJ4PSI4IiBmaWxsPSIjNWY2ODc4Ii8+PHRleHQgeD0iMjAwLjAiIHk9IjIyNS41IiBmb250LXNpemU9IjEzIiBmb250LXdlaWdodD0iNjAwIiBmaWxsPSIjZmZmIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj5hY3Rpb25zPC90ZXh0PjxwYXRoIGQ9Ik0yMDAuMCAxOTIgTDIwMC4wIDIwNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOGI5NWE3IiBzdHJva2Utd2lkdGg9IjEuNiIgbWFya2VyLWVuZD0idXJsKCNhKSIvPjxyZWN0IHg9IjE0NiIgeT0iMjUwIiB3aWR0aD0iMTA4IiBoZWlnaHQ9IjMwIiByeD0iOCIgZmlsbD0iIzVmNjg3OCIvPjx0ZXh0IHg9IjIwMC4wIiB5PSIyNjkuNSIgZm9udC1zaXplPSIxMyIgZm9udC13ZWlnaHQ9IjYwMCIgZmlsbD0iI2ZmZiIgdGV4dC1hbmNob3I9Im1pZGRsZSI+cHJvZ3Jlc3M8L3RleHQ+PHBhdGggZD0iTTIwMC4wIDIzNiBMMjAwLjAgMjQ4IiBmaWxsPSJub25lIiBzdHJva2U9IiM4Yjk1YTciIHN0cm9rZS13aWR0aD0iMS42IiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+PHBhdGggZD0iTTIwMC4wIDU2IEwyMDAuMCA3MiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOGI5NWE3IiBzdHJva2Utd2lkdGg9IjEuNiIgbWFya2VyLWVuZD0idXJsKCNhKSIvPjxwYXRoIGQ9Ik0xMTkgODkgTDE0NCA4OSIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOGI5NWE3IiBzdHJva2Utd2lkdGg9IjEuNiIgbWFya2VyLWVuZD0idXJsKCNhKSIvPjxwYXRoIGQ9Ik0yNTQgMjIxIEwyNjMgMjIxIiBmaWxsPSJub25lIiBzdHJva2U9IiM4Yjk1YTciIHN0cm9rZS13aWR0aD0iMS42Ii8+PHBhdGggZD0iTTI2MyAxOTEuMCBMMjYzIDI1MS4wIiBmaWxsPSJub25lIiBzdHJva2U9IiM4Yjk1YTciIHN0cm9rZS13aWR0aD0iMS42Ii8+PHBhdGggZD0iTTI2MyAxOTEuMCBMMjcwIDE5MS4wIiBmaWxsPSJub25lIiBzdHJva2U9IiM4Yjk1YTciIHN0cm9rZS13aWR0aD0iMS42IiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+PHJlY3QgeD0iMjcyIiB5PSIxNzYuMCIgd2lkdGg9IjEyNCIgaGVpZ2h0PSIzMCIgcng9IjgiIGZpbGw9IiM0ZDgxNjkiLz48dGV4dCB4PSIzMzQuMCIgeT0iMTk1LjUiIGZvbnQtc2l6ZT0iMTMiIGZvbnQtd2VpZ2h0PSI2MDAiIGZpbGw9IiNmZmYiIHRleHQtYW5jaG9yPSJtaWRkbGUiPlJld2FyZHM8L3RleHQ+PHRleHQgeD0iMzM0LjAiIHk9IjIyMi4wIiBmb250LXNpemU9IjExLjUiIGZvbnQtd2VpZ2h0PSI0MDAiIGZpbGw9IiM4Yjk1YTciIHRleHQtYW5jaG9yPSJtaWRkbGUiPmdhbWUsIEJhY2twYWNrLCB3YWxsZXQ8L3RleHQ+PHBhdGggZD0iTTI2MyAyNTEuMCBMMjcwIDI1MS4wIiBmaWxsPSJub25lIiBzdHJva2U9IiM4Yjk1YTciIHN0cm9rZS13aWR0aD0iMS42IiBtYXJrZXItZW5kPSJ1cmwoI2EpIi8+PHJlY3QgeD0iMjcyIiB5PSIyMzYuMCIgd2lkdGg9IjEyNCIgaGVpZ2h0PSIzMCIgcng9IjgiIGZpbGw9IiM0ZDgxNjkiLz48dGV4dCB4PSIzMzQuMCIgeT0iMjU1LjUiIGZvbnQtc2l6ZT0iMTMiIGZvbnQtd2VpZ2h0PSI2MDAiIGZpbGw9IiNmZmYiIHRleHQtYW5jaG9yPSJtaWRkbGUiPkVtYWlsczwvdGV4dD48dGV4dCB4PSIzMzQuMCIgeT0iMjgyLjAiIGZvbnQtc2l6ZT0iMTEuNSIgZm9udC13ZWlnaHQ9IjQwMCIgZmlsbD0iIzhiOTVhNyIgdGV4dC1hbmNob3I9Im1pZGRsZSI+Q1JNIGVtYWlsPC90ZXh0Pjx0ZXh0IHg9IjYwIiB5PSIyNDIiIGZvbnQtc2l6ZT0iMTIiIGZvbnQtd2VpZ2h0PSI0MDAiIGZpbGw9IiM4Yjk1YTciIHRleHQtYW5jaG9yPSJtaWRkbGUiPmdhbWUgY2xpZW50PC90ZXh0PjxyZWN0IHg9IjEiIHk9IjI1MCIgd2lkdGg9IjExOCIgaGVpZ2h0PSIzMCIgcng9IjgiIGZpbGw9IiM1ZjY4NzgiLz48dGV4dCB4PSI2MC4wIiB5PSIyNjkuNSIgZm9udC1zaXplPSIxMyIgZm9udC13ZWlnaHQ9IjYwMCIgZmlsbD0iI2ZmZiIgdGV4dC1hbmNob3I9Im1pZGRsZSI+U2hvdyBwcm9ncmVzczwvdGV4dD48cGF0aCBkPSJNMTQ2IDI2NSBMMTIxIDI2NSIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjOGI5NWE3IiBzdHJva2Utd2lkdGg9IjEuNiIgbWFya2VyLWVuZD0idXJsKCNhKSIvPjwvc3ZnPgo=" alt="Your backend creates quests and sends events; the platform matches, checks limits and conditions, runs actions and records progress, which a game client signed in as the player reads" /%}

{% admonition type="success" name="The platform keeps the state" %}
You don't store progress, count events or call the reward systems yourself.
{% /admonition %}

You connect with a Publisher Account token or a publisher key, and you onboard your project yourself with one call. [**Authentication**](/api/quests/authentication) lists the credentials each operation accepts.

The API is at `https://quests-platform.xsolla.com`, and every route carries the API version, `/api/v2/...`. Keep publisher keys on your servers, never in a game client.


{% cards columns=2 %}
{% card title="Publisher guide" to="/api/quests/publisher-guide" linkIcon="arrow" %}
Onboard your project, create the chest quest, send events and show quests to players.
{% /card %}
{% /cards %}

## Growing the quest {% #growing-the-quest %}

The chest quest's nodes say *what* it does. Fields on the quest itself extend that logic without touching the nodes: when it runs, how often it pays, what progress players see, and who can see the quest and in what form. Each is explained where it belongs:

| Field | What it adds | Read |
| --- | --- | --- |
| `status`, `start_date`, `end_date` | When the quest runs: drafts, pausing, and the lock once players have progress | [**Quest lifecycle**](/api/quests/quest-guide#quest-lifecycle) |
| `activation_limits` | How often it pays: per player, in total, per day, week or month | [**Activation limits**](/api/quests/activation-limits) |
| `objectives` | The steps players see on their way to completing it | [**Objectives**](/api/quests/public-quests-guide#public-objectives) |
| `is_public`, `public_view` | Who can see the quest, and what they see | [**Public quests guide**](/api/quests/public-quests-guide) |
| `client_sendable` on the trigger | Whether a game client can send the events that start it | [**Client events**](/api/quests/publisher-events-guide#publisher-sending-client) |

To change what the quest *does*, swap or add nodes instead: [**Quest nodes**](/api/quests/quest-nodes) explains how a quest runs and lists every node.

## Find your path {% #start-here %}

Pick the card that matches what you are doing now.

{% cards columns=3 cardMinWidth=150 %}
{% card title="Publisher" to="/api/quests/publisher-guide" linkIcon="arrow" %}
Connect your project and build the chest quest.
{% /card %}
{% card title="Building quests" to="/api/quests/quest-guide" linkIcon="arrow" %}
Fields, connections, conditions, limits and editing.
{% /card %}
{% card title="Every node" to="/api/quests/quest-nodes" linkIcon="arrow" %}
Each trigger, condition and action, with an example.
{% /card %}
{% card title="Examples" to="/api/quests/examples" linkIcon="arrow" %}
Whole quests and step-by-step walkthroughs.
{% /card %}
{% card title="Public quests guide" to="/api/quests/public-quests-guide" linkIcon="arrow" %}
Show quests to players, with or without their progress.
{% /card %}
{% /cards %}


## Before you go live {% #before-go-live %}

These are the rules that matter once real players and real rewards are involved.

### What the platform guarantees {% #guarantees %}

{% cards columns=2 %}
{% card title="Processed asynchronously" %}
A `200` from the events endpoint means the event was **accepted**. Quests run moments later.
A game client signed in as the player sees the outcome on public quests through [List quests with the caller's progress](/api/quests/player-progress/list-me-quests).
There is no progress read for your backend or for private quests.
{% /card %}
{% card title="Once per quest" %}
Each quest processes an `idempotency_key` once, so a retried event never runs a quest's actions twice.
{% /card %}
{% card title="Completed steps are not repeated" %}
A run that resumes after a failure skips the actions that already succeeded.
{% /card %}
{% card title="Projects are isolated" %}
An event reaches only the quests of the project it is sent for.
{% /card %}
{% /cards %}

## Glossary {% #glossary %}

| Term | Meaning |
| --- | --- |
| **Account** | An Xsolla project maps to an account; quests and player progress belong to it. |
| **Workspace** | A list of accounts. An Xsolla merchant maps to a workspace, and each of its projects to an account in it. |
| **Quest** | A graph of nodes with a status, a time window (`start_date` to `end_date`) and optional activation limits. |
| **Node** | One step of a quest: a trigger, a condition or an action. Each has a `type` and a `subtype`, such as [dynamic_event](/api/quests/node-dynamic-event). |
| **Event** | Something a player did: a name, the player's identifiers, a timestamp and optional properties. |
| **Player** | The person an event is about, resolved from its identifiers (`gamer_id`, `xsolla_id`, email). Progress and per-player limits belong to the player. |
| **Run** | One pass of one quest for one event or one scheduled tick. |
| **Activation limit** | A cap on completions, per player (`per_user`) or across all players (`global`), optionally per time window. |
| **Progress** | A player's state on a quest: `not_started`, `in_progress`, `completed` or `expired`, with the count of completions. |
| **Idempotency key** | A UUID per real-world occurrence of an event. Each quest processes a key once. |
| [**Scope**](/api/quests/publisher-events-guide#publisher-sending-scope) | Which later event counts can include an event: `private`, `global`, `within_publisher`, `within_project` or `within_quest`. |
| **Backpack** | The player-facing inventory where item rewards appear. |
| **DDH** | Digital Delivery Hub: delivers currency and items into a publisher's game. |
| **SKU** | An item ID, unique only within its project. |


Version: 2.0

## Servers

```
https://quests-platform.xsolla.com
```

## Security

### Publisher-key

An Xsolla API key of your merchant, for your backend: `Authorization: Basic` with your merchant ID and the API key, Base64-encoded. Where to find both is in [Xsolla API authentication](https://developers.xsolla.com/api/getting-started/#api_authentication); create keys as in [API keys](https://developers.xsolla.com/api/getting-started/#api_keys_overview). Keep it on your servers.

Type: http
Scheme: basic

### Publisher-Account-token

The token of a person signed in to Publisher Account, sent as `Authorization: Bearer`. What it may do follows that person's role in the merchant; see the [Publisher guide](/api/quests/publisher-guide).

Type: http
Scheme: bearer
Bearer Format: JWT

### Player-token

The token of the player signed in to your game, issued by [Xsolla Login](https://developers.xsolla.com/authenticate-users/), sent as `Authorization: Bearer`. It acts for that player only.

Type: http
Scheme: bearer
Bearer Format: JWT

## Download OpenAPI description

[Quest Platform](https://xsolla.redocly.app/_bundle/@l10n/de/api/quests/index.yaml)

## Publisher API

Connect an Xsolla project to quests, check which projects are connected, and create and manage the quests of a project.

### List a merchant's projects

 - [GET /api/v2/merchants/{merchant_id}/projects](https://xsolla.redocly.app/de/api/quests/publisher-api/list-merchant-projects.md): List the merchant's Xsolla projects that are onboarded to Quest Platform, with their status. Your credential needs read access to the whole merchant. If you can access only some of its projects, check each with Get project.

Publisher guide explains onboarding and who can access what.

A publisher key is not accepted here: it is checked against a project, and this path names none.

Authentication

Send one of these credentials; Authentication explains how to get each:

- Publisher Account token: Authorization: Bearer, the token of a person signed in to Publisher Account.

Authentication errors

- 401: the credential is missing, malformed or invalid, or Authorization uses a scheme other than Basic or Bearer.
- 403: the credential is valid, but it is inactive or has no permission for this operation.
- 404: the merchant does not exist, is not onboarded, or this credential has no access to it. The response is the same in all three cases.

### Get project

 - [GET /api/v2/merchants/{merchant_id}/projects/{project_id}](https://xsolla.redocly.app/de/api/quests/publisher-api/get-project.md): Get the Quest Platform project of an Xsolla project. A 200 response means that the project is onboarded and that your credential has access to it.

Publisher guide explains onboarding and who can access what.

Authentication

Send one of these credentials; Authentication explains how to get each:

- Publisher key: Authorization: Basic, with your merchant ID as the username and your Xsolla API key as the password.
- Publisher Account token: Authorization: Bearer, the token of a person signed in to Publisher Account.

Authentication errors

- 401: the credential is missing, malformed or invalid, or Authorization uses a scheme other than Basic or Bearer.
- 403: the credential is valid, but it is inactive or has no permission for this operation.
- 404: the project does not exist, is not onboarded, or this credential has no access to it. The response is the same in all three cases.

### Onboard project

 - [POST /api/v2/merchants/{merchant_id}/projects/{project_id}/onboard](https://xsolla.redocly.app/de/api/quests/publisher-api/onboard-project.md): Connect an Xsolla project to Quest Platform. Call this once per project, before any other call for it. The call is idempotent: calling it again returns the project. After onboarding, the merchant's publisher keys work on the project and quest operations of every onboarded project of the merchant. Each Publisher Account user gets access by calling this operation with their own token.

The call creates whatever does not exist yet: the merchant record, the project, and access for the merchant's publisher keys to every onboarded project of the merchant. merchant_name and project_name are used only for the records this call creates.

With a publisher key (Basic), the key's merchant must match {merchant_id} (otherwise 404), and Xsolla must accept the key for the project (otherwise 401). With a Publisher Account token (Bearer), you must be a member of merchant {merchant_id}, and Xsolla must list the project among the projects you can access (otherwise 404 in both cases).

With a Publisher Account token, the access you get follows your Xsolla membership: a merchant owner gets full access to the merchant, any other member of the whole merchant gets permission to manage its quests, and a member limited to specific projects gets that permission on this project only. Access that you already have is not changed by later calls.

Publisher guide walks through onboarding and the calls that follow it.

Authentication

Send one of these credentials; Authentication explains how to get each:

- Publisher key: Authorization: Basic, with your merchant ID as the username and your Xsolla API key as the password.
- Publisher Account token: Authorization: Bearer, the token of a person signed in to Publisher Account.

Authentication errors

- 401: the credential is missing, malformed or invalid, or Authorization uses a scheme other than Basic or Bearer.
- 403: the credential is a Bearer token other than a Publisher Account token. These credentials cannot onboard a project.
- 404: the merchant or the project does not exist, does not match the credential, or is not accessible to you. The response is the same in all these cases.

### List quests (project scope)

 - [GET /api/v2/merchants/{merchant_id}/projects/{project_id}/quests](https://xsolla.redocly.app/de/api/quests/publisher-api/list-quests-in-project.md): List the project's quests, page by page. Requires read access to the project's quests. Quests with a Web3 reward are left out where Web3 rewards are not available to you or to the merchant.

Quest guide explains the fields of a quest.

Authentication

Send one of these credentials; Authentication explains how to get each:

- Publisher key: Authorization: Basic, with your merchant ID as the username and your Xsolla API key as the password.
- Publisher Account token: Authorization: Bearer, the token of a person signed in to Publisher Account.

Authentication errors

- 401: the credential is missing, malformed or invalid, or Authorization uses a scheme other than Basic or Bearer.
- 403: the credential is valid, but it is inactive or has no permission for this operation.
- 404: the project does not exist, is not onboarded, or this credential has no access to it. The response is the same in all three cases.

### Create a new quest (project scope)

 - [POST /api/v2/merchants/{merchant_id}/projects/{project_id}/quests](https://xsolla.redocly.app/de/api/quests/publisher-api/create-quest-in-project.md): Create a quest in the project. Requires permission to manage the project's quests.

Quest guide explains each field of the quest and how it runs, and Quest nodes lists every node with its parameters.

Authentication

Send one of these credentials; Authentication explains how to get each:

- Publisher key: Authorization: Basic, with your merchant ID as the username and your Xsolla API key as the password.
- Publisher Account token: Authorization: Bearer, the token of a person signed in to Publisher Account.

Authentication errors

- 401: the credential is missing, malformed or invalid, or Authorization uses a scheme other than Basic or Bearer.
- 403: the credential is valid, but it is inactive or has no permission for this operation.
- 404: the project does not exist, is not onboarded, or this credential has no access to it. The response is the same in all three cases.

### Delete a quest (project scope)

 - [DELETE /api/v2/merchants/{merchant_id}/projects/{project_id}/quests/{id}](https://xsolla.redocly.app/de/api/quests/publisher-api/delete-quest-in-project.md): Delete a quest by its ID. Requires permission to manage the project's quests.

Quest guide explains the quest lifecycle.

Authentication

Send one of these credentials; Authentication explains how to get each:

- Publisher key: Authorization: Basic, with your merchant ID as the username and your Xsolla API key as the password.
- Publisher Account token: Authorization: Bearer, the token of a person signed in to Publisher Account.

Authentication errors

- 401: the credential is missing, malformed or invalid, or Authorization uses a scheme other than Basic or Bearer.
- 403: the credential is valid, but it is inactive or has no permission for this operation.
- 404: the project does not exist, is not onboarded, or this credential has no access to it. The response is the same in all three cases.

### Get quest by ID (project scope)

 - [GET /api/v2/merchants/{merchant_id}/projects/{project_id}/quests/{id}](https://xsolla.redocly.app/de/api/quests/publisher-api/get-quest-by-id-in-project.md): Get a quest by its ID. Requires read access to the project's quests.

Quest guide explains the fields of a quest.

Authentication

Send one of these credentials; Authentication explains how to get each:

- Publisher key: Authorization: Basic, with your merchant ID as the username and your Xsolla API key as the password.
- Publisher Account token: Authorization: Bearer, the token of a person signed in to Publisher Account.

Authentication errors

- 401: the credential is missing, malformed or invalid, or Authorization uses a scheme other than Basic or Bearer.
- 403: the credential is valid, but it is inactive or has no permission for this operation.
- 404: the project does not exist, is not onboarded, or this credential has no access to it. The response is the same in all three cases.

### Update a quest (project scope)

 - [PUT /api/v2/merchants/{merchant_id}/projects/{project_id}/quests/{id}](https://xsolla.redocly.app/de/api/quests/publisher-api/update-quest-in-project.md): Update a quest by its ID. Send the complete quest JSON, not only the changed fields. Requires permission to manage the project's quests.

Quest guide explains each field, and which ones you can still change once players have progress on the quest.

Authentication

Send one of these credentials; Authentication explains how to get each:

- Publisher key: Authorization: Basic, with your merchant ID as the username and your Xsolla API key as the password.
- Publisher Account token: Authorization: Bearer, the token of a person signed in to Publisher Account.

Authentication errors

- 401: the credential is missing, malformed or invalid, or Authorization uses a scheme other than Basic or Bearer.
- 403: the credential is valid, but it is inactive or has no permission for this operation.
- 404: the project does not exist, is not onboarded, or this credential has no access to it. The response is the same in all three cases.

### List permitted quest node types (project scope)

 - [GET /api/v2/merchants/{merchant_id}/projects/{project_id}/quests/node-types](https://xsolla.redocly.app/de/api/quests/publisher-api/get-quest-node-types-in-project.md): List the node type and subtype pairs that quests created through these operations can use, sorted by type and then by subtype. Each pair comes with a JSON Schema for its parameters. The list can be empty. A node that matches its schema can still be rejected when you create or update a quest, because the whole quest is validated too. Node types whose rewards are not available to the caller are not listed.

Quest nodes documents each node with an example.

Authentication

Send one of these credentials; Authentication explains how to get each:

- Publisher key: Authorization: Basic, with your merchant ID as the username and your Xsolla API key as the password.
- Publisher Account token: Authorization: Bearer, the token of a person signed in to Publisher Account.

Authentication errors

- 401: the credential is missing, malformed or invalid, or Authorization uses a scheme other than Basic or Bearer.
- 403: the credential is valid, but it is inactive or has no permission for this operation.
- 404: the project does not exist, is not onboarded, or this credential has no access to it. The response is the same in all three cases.

## Publisher events

Report player actions from your backend so that quests can track player progress.

### Send an event

 - [POST /api/v2/merchants/{merchant_id}/projects/{project_id}/events](https://xsolla.redocly.app/de/api/quests/publisher-events/publisher-events.md): Report a player action in your project, so that quests can track the player's progress.

Publisher events guide explains every field, the player identifiers and retries.

The event's publisher is taken from the path. The body accepts only the fields below, and any other field, including publisher, is rejected. idempotency_key must be a UUID, and user_ids[].identifier_type must be one of xsolla_id, gamer_id, guest_id or email.

Authentication

Send one of these credentials; Authentication explains how to get each:

- Publisher key: Authorization: Basic, with your merchant ID as the username and your Xsolla API key as the password.
- Publisher Account token: Authorization: Bearer, the token of a person signed in to Publisher Account.

Player tokens are not accepted. The credential must have access to the project in the path.

Authentication errors

- 401: the credential is missing, or it was rejected for the merchant and the project in the path.

## Public quest list

Read the public quests of a project. No credential is needed.

### List public quests

 - [GET /api/v2/public/merchants/{merchant_id}/projects/{project_id}/quests](https://xsolla.redocly.app/de/api/quests/public-quest-list/list-public-quests.md): List the project's public quests, page by page. Only quests that are public, active and inside their start and end dates are returned, each shown through its public_view. An unknown, inactive or not onboarded project returns 404. A project without public quests returns 200 with an empty data array. Use ids to get only some quests in one request. Quests whose rewards are not available to the caller are not listed.

Public quests guide explains how a quest becomes public and what its public_view shows.

Authentication

None. This operation needs no credential.

### Get a public quest

 - [GET /api/v2/public/merchants/{merchant_id}/projects/{project_id}/quests/{quest_id}](https://xsolla.redocly.app/de/api/quests/public-quest-list/get-public-quest.md): Get one of the project's public quests that is active and inside its start and end dates, shown through its public_view. The response is the same 404 for an unknown, inactive or not onboarded project, and for a quest that is unknown, private, inactive or outside its start and end dates. A quest whose rewards are not available to the caller returns the same 404.

Public quests guide explains how a quest becomes public and what its public_view shows.

Authentication

None. This operation needs no credential.

## Player progress

Read the public quests of a project together with the progress of the player whose token is sent.

### List quests with the caller's progress

 - [GET /api/v2/me/merchants/{merchant_id}/projects/{project_id}/quests](https://xsolla.redocly.app/de/api/quests/player-progress/list-me-quests.md): List the project's public quests that are active and inside their start and end dates. Each quest is shown through its public_view, together with the player's latest progress. Use ids to get only some quests in one request. Quests whose rewards are not available to the caller are not listed. The progress is always the player's own: no parameter, header or body field can select another user, because the user is taken only from the token. Quests are not filtered by progress, so a quest that the player has not started has progress with the not_started status.

Public quests guide explains the public_view and the progress block.

Authentication

Send the player's token; Authentication explains it:

- Player token: Authorization: Bearer, the player's Xsolla ID token or Xsolla Login token. The word Bearer is case-sensitive here.

Authentication errors

- 401: the token is missing, expired, forged or from an unsupported issuer.
- 403: an Xsolla Login token has no merchant (no valid publisher_id claim).

### Get a quest with the caller's progress

 - [GET /api/v2/me/merchants/{merchant_id}/projects/{project_id}/quests/{quest_id}](https://xsolla.redocly.app/de/api/quests/player-progress/get-me-quest.md): Get one of the project's public quests that is active and inside its start and end dates, together with the player's latest progress. A private quest returns the same 404 as an unknown one, even when the player has progress on it. A quest whose rewards are not available to the caller returns the same 404. The progress is always the player's own: no parameter, header or body field can select another user, because the user is taken only from the token. Quests are not filtered by progress, so a quest that the player has not started has progress with the not_started status.

Public quests guide explains the public_view and the progress block.

Authentication

Send the player's token; Authentication explains it:

- Player token: Authorization: Bearer, the player's Xsolla ID token or Xsolla Login token. The word Bearer is case-sensitive here.

Authentication errors

- 401: the token is missing, expired, forged or from an unsupported issuer.
- 403: an Xsolla Login token has no merchant (no valid publisher_id claim).

## Client events

Report the signed-in player's actions from the game client, with the player's token.

### Send an event from a game client

 - [POST /api/v2/me/merchants/{merchant_id}/projects/{project_id}/events](https://xsolla.redocly.app/de/api/quests/client-events/client-events.md): Send an event for the signed-in player from a game or browser client. The player is taken from the token and the game from the path; the body accepts only the fields below and rejects any other field. The event is accepted only if an active quest of the project lets a game client send it.

Publisher events guide explains client events and how a quest allows them.

Authentication

Send the player's token; Authentication explains it:

- Player token: Authorization: Bearer, the signed-in player's Xsolla ID token or Xsolla Login token.

Authentication errors

- 401: the token is missing, expired or invalid.
- 403: the event cannot be sent from a game client here: no active quest of the project lets a game client send it, the project is not onboarded, or an Xsolla Login token has no merchant (no publisher_id claim). All three return the same response.

