# Introduction

## Welcome

Welcome to the r4nkt documentation...a work-in-progress.

Our goal is to explain how r4nkt works and how you can make the most of it. As we build it up and polish it, we hope to hear from our users so that we can focus on areas that will be the most helpful.

## What is r4nkt?

R4nkt gives you all of the power and flexibility you need to gamify your application or to round out your game with features that may be missing. Gamifying your application helps you easily realize some of the many [benefits](https://r4nkt.com/blog/why-gamify-my-app) of gamification. It helps you gain insight into how your end-users use your software via activities. Introducing achievements, leaderboards, and rewards can help engage and motivate your end-users as well as make your application a little more fun.

At its core, r4nkt is driven by player activities. Players are end-users. They are the individuals using your software or playing your games. Whenever a player does something within your software that you have determined to be interesting, then you report it to r4nkt via the r4nkt API. R4nkt then takes that information and acts on it. This includes evaluating whether or not any achievements have been earned, awarding badges, updating leaderboard rankings, and notifying you when anything interesting happens.

## Who is r4nkt for?

R4nkt was designed for software developers of all stripes that would like to introduce game-design elements and game principles to their applications.

As noted above, there are many [benefits](https://r4nkt.com/blog/why-gamify-my-app) to gamification. R4nkt is for anyone interested in enjoying these benefits.

R4nkt can be used with traditional applications or actual games. It can be used with any platform, including Android, iOS, Windows, macOS, and Linux.

## Process

Of course, for all this to happen, one must do the following:

1. sign up
2. create a game
3. define your game's resources
4. prepare your application to use the [API](https://r4nkt.com/docs/1.0/api/overview)
5. prepare your application to respond to [webhooks](/webhooks/overview)
6. report your players' activities

## Concepts

For information about the different bits and pieces that make up r4nkt, please take a look at [the next section](/concepts/overview).

## Support

If you have any questions or comments related to the documentation or if you have any difficulties with the service, please feel free to email us at <support@r4nkt.com> or contact us on [Discord](https://discord.gg/3gMfd3eyHY).

Our customers are our top priority and we'd love to help...!


# Getting Started

## How to create a simple achievement

{% embed url="<https://youtu.be/Uo4gf-SeC0I>" %}

This video walks you through the basic steps necessary to create a simple achievement:

* Provision your game
* Create an API token
* Find your game ID
* Create a standard leaderboard
* Create an action
* Create a criterion
* Create a criteria group
* Create an achievement
* Report player activity
* View leaderboard rankings


# Overview

## Games

When you use r4nkt, you will have the opportunity to create one or more [games](/concepts/games). Once you have a r4nkt game, then you can begin to define and use its gamification elements. This section will introduce you to the various concepts within each r4nkt game.

Click [here](/concepts/games) for more information on the r4nkt game.

## Resources

Each r4nkt game consists of the the following resources:

* [Achievements](/concepts/achievements)
* [Actions](/concepts/actions)
* [Badges](/concepts/badges)
* [Criteria](/concepts/criteria)
* [Criteria Conditions](/concepts/criteria-conditions)
* [Criteria Groups](/concepts/criteria-groups)
* [Leaderboards](/concepts/leaderboards)
* [Players](/concepts/players)
* [Rewards](/concepts/rewards)
* [Scores](/concepts/scores)

## Common Properties

Many of these resources have the following properties:

| Name         |  Type  | Default |
| ------------ | :----: | :-----: |
| custom\_id   | string |    -    |
| name         | string |    -    |
| description  | string | *empty* |
| custom\_data |  json  | *empty* |

Whenever a resource has these properties, the `custom_id` and `name` are required. They must be unique for the given resource type for the game to which they belong.

Here is some more information about each property:

* `custom_id`: This is your *key* to the resource and is used for identification via the API. Currently, it can be set to any combination of alphanumeric characters, underscore, hyphen, period, and tilde and cannot exceed 255 characters.
* `name`: This is your way of giving your resource a friendly name. It's expected that this property might be used when displaying the given resource to your players. It can be set to any string value but may not exceed 255 characters.
* `description`: While not required, this property allows you to give a friendly description of the given resource. As with `name`, it's expected that this property might be used when displaying the resource to your players. Currently, it can be set to any string value, but may not exceed 255 characters.
* `custom_data`: This is a property that allows you to associate custom data with the given resource. You may want to associate image URLs with achievements, for example. Currently, it can be set to any valid JSON string that does not exceed 1024 characters.

{% hint style="warning" %}
If you plan to use [custom data references](/concepts/custom-data-reference) with your [criteria conditions](/concepts/criteria-conditions), you must remember to only use the following characters for your `custom_data` keys: `a-z`, `A-Z`, and underscore.
{% endhint %}

{% hint style="warning" %}
There are currently no limits on nesting depth for `custom_data`, but there is a limit of 10 when using [custom data references](/concepts/custom-data-reference).
{% endhint %}

{% hint style="warning" %}
There are currently no limits on how many characters long custom data keys can be, but this will likely change in the near future.
{% endhint %}

## Sessions

{% hint style="warning" %}
Sessions have been temporarily disabled to allow for a reworking based on feedback.
{% endhint %}

Sessions provide a way for you to identify certain activity. A typical r4nkt application or game will report a player's activity without any session context. However, there are times where you may want to report activity for a specific period of time, or a session. Achievements that are earned within the context of a session will have their points added to any corresponding [session-based leaderboard](/concepts/leaderboards#type) that you have defined for your game.


# Achievements

## Description

Achievements in r4nkt are like goals that you can create and define. They provide ways to measure a player's activities, to incentivize certain behavior, or to provide goals. Your players, through the actions they take, can meet these goals and earn an achievement.  When this is done, they will be awarded a [badge](/concepts/badges) to represent the earned achievement.

You must assign criteria to your achievements. These criteria must be met in order to earn the achievement and receive a related badge. You may assign points to achievements, which are then awarded to your players once they are earned. Finally, you may attach [rewards](/concepts/rewards) to your achievements and then distribute them once they are earned.

{% hint style="warning" %}
Keep in mind that new or modified achievements are not evaluated to see whether or not players have met the criteria. Rather, achievements are only evaluated when related [player activities](/concepts/activities) have been reported.
{% endhint %}

## Properties

Achievements have the following properties:

| Name                        |    Type    | Default |
| --------------------------- | :--------: | :-----: |
| custom\_id                  |   string   |    -    |
| name                        |   string   |    -    |
| description                 |   string   | *empty* |
| custom\_data                |    json    | *empty* |
| is\_secret                  |   boolean  |  false  |
| custom\_criteria\_group\_id |   string   | *empty* |
| points                      |   integer  |    1    |
| rewards                     | collection | *empty* |

{% hint style="info" %}
Click [here](/concepts/overview#common-properties) for information about common properties.
{% endhint %}

### Is secret

An achievement's `is_secret` property determines whether or not it is returned to the calling application for normal requests. It is boolean and must therefore be equal to one of the following values:

* true
* false

{% hint style="info" %}
By default, "secret" achievements will not be returned by "list" or "get" calls to the API.
{% endhint %}

An achievement with an `is_secret` value of `true` is intended to be kept hidden from the player. It is recommended to make an achievement "secret" if it contains a spoiler you don't want to reveal too early, eg. "Discover that you were a ghost all along!".

Finally, an achievement that is "known" (`is_secret` is `false`) is one where the player can know about the achievement prior to having earned it.

### Criteria group

An achievement can have a single [criteria group](/concepts/criteria-groups), which is identified by the criteria group's `custom_id` and asigned to its `custom_criteria_group_id` property. This is where you begin to define the different criteria that must be met in order for the player to earn the achievement and be awarded a [badge](/concepts/badges).

### Points

An achievement can be given points. Whenever a player earns an achievement, any associated points are automatically added to the points for any other achievements they have earned and your game's standard and session-based [leaderboards](/concepts/leaderboards#type) will be updated automatically.

### Rewards

An achievement can have multiple [rewards](/concepts/rewards). They are associated with achievements so that, when a player earns an achievement, any associated rewards can be distributed.


# Actions

## Description

Actions in r4nkt are essentially things that a player can do within your application or game. Actions can be things like closing a sale, submitting an article, or slaying a red dragon. Whatever they might be will depend on your app and what you find interesting and want to measure or promote. Whenever your player performs a given action, r4nkt should be notified via the API. Once r4nkt is notified, the action is recorded for the specified player and r4nkt determines whether any achievements have been earned.

## Properties

Actions have the following properties:

| Name         |    Type    | Default |
| ------------ | :--------: | :-----: |
| custom\_id   |   string   |    -    |
| name         |   string   |    -    |
| description  |   string   | *empty* |
| custom\_data |    json    | *empty* |
| reactions    | collection | *empty* |

{% hint style="info" %}
Click [here](/concepts/overview#common-properties) for information about common properties.
{% endhint %}

### Reactions

An action may have reactions. This is one of the many features designed to make your life easier.

Sometimes, your player will do something that could translate into one or more individual actions. You can keep track of and report each of these individually, or you can assign reactions to your actions where it makes sense and then let r4nkt do the rest of the work for you.

Let's say that you have an application where your players can submit content in a variety of ways. Perhaps they can submit product articles as well as reviews. You might want to keep track of the number of articles submitted, the number of reviews submitted, and the overall number of content submissions. To do this, you would create three actions: `submit.article`, `submit.review`, and `submit.content`. Then, you would add `submit.content` as a reaction to both `submit.article` and `submit.review`. Then, whenever you report that a player has submitted an article, that will be recorded *and* r4nkt will automatically record an additional activity: `submit.content`. Likewise, when you report that a player has submitted a review, r4nkt will record that *and* it will automatically record its reaction: `submit.content`.

In doing this, you can define achievements that use `submit.content`, `submit.article`, and `submit.review` in whatever way you want, since they're all recorded. Once you know that the reactions are set up correctly, then your application only needs to worry about recording the "top-level" action.

Some notes about reactions:

* Actions can have zero or more reactions.
* Actions cannot have duplicate reactions.
* Chains can be defined. That is, action A can trigger action B, which can trigger action C.
* Chains may not be cyclical. That is, action A can trigger action B, but action B cannot trigger action A.
* Depending on your subscription, there may be limits to the number of reactions a single action can have as well as the depth or length of an action-reaction chain.


# Activities

## Description

Activities in r4nkt are key. Your app will report your player activities, which is how r4nkt knows what [actions](/concepts/actions) your [players](/concepts/players) have performed. You do this via [API](/api/activities).

Whenever your player performs a given action, you report this to r4nkt. The player activity is recorded and r4nkt goes into action. Among other things, it triggers any defined reactions, it determines whether any achievements have been earned, it updates leaderboards, if necessary, and it notifies you if anything interesting has taken place.

## Properties

Actions have the following properties:

| Name                |   Type  | Default |
| ------------------- | :-----: | :-----: |
| uuid                |  string |    -    |
| custom\_action\_id  |  string |    -    |
| custom\_player\_id  |  string |    -    |
| custom\_session\_id |  string | *empty* |
| amount              | integer |    1    |
| date\_time\_utc     |  string |  *now*  |
| custom\_data        |   json  | *empty* |

### UUID

This is a universally unique identifier for the individual activity. You may provide your own UUID when reporting a new activity, otherwise r4nkt will automatically generate one.

### Custom Action ID

This is the custom ID for the action that the player has performed. This **must** match an existing action within your game.

### Custom Player ID

This is the player's custom ID.

{% hint style="info" %}
If this custom ID is new to r4nkt, then a new player will be automatically created with this custom ID.
{% endhint %}

### Custom Session ID

@todo 🤓

### Amount

This is the number of times the player has performed the specified action.

Sometimes it makes sense that the player has performed something more than once at a given moment. Consider, for example, that you have an action for archiving documents. If the player archives a single document, then you could not send this field and r4nkt will default it to 1. Alternatively, you can send the field and the explicit value of 1. But, if your app supports a bulk archive function, then you would send this field with the amount of files that are bulk archived.

### Date/Time

If this field is not sent, then r4nkt assumes that the player has just performed this action. If you choose to send this data, however, it **must** be a date/time in the past.

The date/time is always interpreted as belonging to the UTC time zone. You must remember to convert the date/time from any non-UTC time zone before reporting the player activity.

The date/time must have the following format: `2021-03-14 12:34:56`

### Custom Data

You can pass [custom data](/concepts/overview#common-properties) whenever player activity is reported. Taking advantage of this feature opens up a great deal of possibilities when it comes to defining interesting and unique-to-your-app achievement criteria. Please read about [custom data references](/concepts/custom-data-reference) for more information.


# Badges

## Description

Badges in r4nkt are given to a player when an achievement has been earned.  That is to say, when an achievement's criteria have been met, then a badge is awarded.

## Properties

Badges have the following properties:

| Name                    |   Type  | Default |
| ----------------------- | :-----: | :-----: |
| custom\_achievement\_id |  string |    -    |
| custom\_player\_id      |  string |    -    |
| points                  | integer |    -    |
| custom\_session\_id     |  string |    -    |

### Achievement

A badge is given to a player to show that they have met the criteria for a given [achievement](/concepts/achievements). It is represented by the badge's `custom_achievement_id` property, which corresponds to the achievement's `custom_id`.

### Player

The [player](/concepts/players) that has earned the badge is represented by the badge's `custom_player_id` property, which is the player's `custom_id`.

### Custom Session ID

If a badge was earned within the context of a session, then that custom session ID will be provided.&#x20;


# Criteria

## Description

In r4nkt, you create criteria in order to judge or decide whether or not a player has earned an achievement. They are relatively simple resources that specify an action, a rule, and possibly some conditions.

Criteria are created and attached to criteria groups, which are in turn attached to achievements. Once this is done, then an achievement's criteria, which consist of at least one criterion within at least one criteria group, can be evaluated. Then, whenever a player's activities are reported to r4nkt, any related achievements' criteria groups are evaluated. If they resolve to true, then the player has earned the achievement and will be awarded a corresponding badge.

## Properties

A criterion has the following properties:

| Name               |  Type  | Default |
| ------------------ | :----: | :-----: |
| custom\_id         | string |    -    |
| name               | string |    -    |
| description        | string | *empty* |
| type               | string |   sum   |
| custom\_action\_id | string |    -    |
| conditions         |  json  | *empty* |
| rule               | string |  gte:1  |
| streak             | string |    -    |

{% hint style="info" %}
Click [here](/concepts/overview#common-properties) for information about common properties.
{% endhint %}

### Type

The criterion's `type` property is intended to determine how a player's activities are considered during evaluation. A criterion will consider a set of relevant activities and its type will determine what value to use when applying its `rule` property.

Currently, there are three values from which to choose:

* `amount`: When evaluated, if any single relevant activity's `amount` value allows the criterion's rule to pass, then the criterion is met.
* `average`: When evaluated, this type of criterion takes the average of all relevant activity amounts, which is then used by the `rule`.
* `sum`: This type of criterion, when evaluated, calculates the sum of all relevant activity amounts. This sum is then used when applying the `rule`.

So, let's say that your player has recorded the following activities:

```javascript
[
    {"custom_action_id": "close.sale", "amount": 2},
    {"custom_action_id": "close.sale", "amount": 5},
    {"custom_action_id": "close.sale", "amount": 1},
    {"custom_action_id": "close.sale", "amount": 4}
]
```

If you have a criterion of type `amount`, then the rule will look at each of the individual `amount` values. If any of them allow the rule to pass, then the criterion will have been met.

Here are some possible rules and the result for this scenario:

* `gt:5`: false, because none of the amounts are greater than 5
* `lt:3`: true
* `eq:12`: false, because none of the amounts are equal to 12

If you have a criterion of type `average`, then the rule will look at an average of the various `amount` values, which happens to be 3 in this case. If the rule passes when using 3, then the criterion will have been met.

Here are some possible rules and the result for this scenario:

* `gt:5`: false, because the average is 3, which is not greater than 5
* `lt:3`: false, because the average is 3, which is not less than 3
* `eq:12`: false, because the average is 3, which is not equal to 12

If you have a criterion of type `sum`, then the rule will look at a sum of the various `amount` values, which happens to be 12 in this case. If the rule passes when using 12, then the criterion will have been met.

Here are some possible rules and the result for this scenario:

* `gt:5`: true
* `lt:3`: false, because the sum is 12, which is not less than 3
* `eq:12`: true

### Action

A criterion's action is represented by its `custom_action_id`, which corresponds to the related action's `custom_id` property. When a criterion is evaluated, its rule is applied against all player activities for the same action to determine whether or not the criterion has been met.

### Conditions

[Criteria conditions](/concepts/criteria-conditions) are common to both criteria and [criteria groups](/concepts/criteria-groups). If present, they are applied before looking to see if a criterion has been met. Conditions provide a way to filter player activities when determining whether or not a criterion has been met. Once filtered, the [criterion's rule](/concepts/criteria#rule) is used against whatever activities remain.

### Rule

The criterion's `rule` property is used during evaluation. It consists of an operator and a threshold. They have the following form: `operator:threshold`.

When a criterion is evaluated, it determines a value. This value is determined based on the criterion's type. Once determined, it is used when the criterion's rule is applied. When applied, the rule compares the value to the specified `threshold`. The comparison is determined by `operator`.

#### Operator

The criterion rule's operator can have any one of the following values:

* `eq`: If a criterion rule's `operator` is set to `eq`, then the criterion will resolve to true if the given value is *equal to* `threshold`.
* `gt`: If a criterion rule's `operator` is set to `gt`, then the criterion will resolve to true if the given value is *greater than* `threshold`.
* `gte`: If a criterion rule's `operator` is set to `gte`, then the criterion will resolve to true if the given value is *greater than or equal to* `threshold`.
* `lt`: If a criterion rule's `operator` is set to `lt`, then the criterion will resolve to true if the given value is *less than* `threshold`.
* `lte`: If a criterion rule's `operator` is set to `lte`, then the criterion will resolve to true if the given value is *less than or equal to* `threshold`.

{% hint style="warning" %}
Be careful when using `eq`, since there are times where a player will record activities where the amount might increment the total count for a given action such that the threshold is passed, meaning the criterion might not be met when it's otherwise expected.  More often than not, `gte` should be used.
{% endhint %}

#### Threshold

A criterion rule's `threshold` is a number that is compared to the value determined by its type. The comparison is made using the specified operator.

### Streak

The criterion's `streak` property is used during evaluation. It consists of an interval and an amount. They have the following form: `interval:amount`.

#### Interval

The criterion streak's interval can have any one of the following values:

* `days`: The criterion will have been met if, after all of the conditions have been applied, the rule resolves to true over the course of several consecutive days, which is determined by the streak `amount`.
* `hours`: The criterion will have been met if, after all of the conditions have been applied, the rule resolves to true over the course of several consecutive hours, which is determined by the streak `amount`.

#### Amount

A criterion streak's `amount` is an integer indicated the minimum length of the streak.

{% hint style="warning" %}
Currently, streaks of any kind may be between 1 and 100, inclusive.
{% endhint %}

#### Examples

Here are some simple examples:

* `days:5`: The rule must resolve to true for five consecutive days.
* `hours:12`: The rule must resolve to true for twelve consecutive hours.


# Criteria Conditions

## Description

Conditions are common to both [criteria](/concepts/criteria) and [criteria groups](/concepts/criteria-groups). They can be used to filter a player's activities before applying any criteria rules.

{% hint style="warning" %}
Criteria condition administration is currently only supported via API. We hope to have our admin UI updated to support criteria condition administration in the near future.
{% endhint %}

## Examples

In order to help illustrate the difference between using criteria conditions and not using them, let's consider a simple example.

Let's say that you have an achievement, "The Closer". This achievement has a single criterion, "Closed 10 Sales", which is tied to your "Close a Sale" action and has rule, `gte:sum,10`.

Without any criteria conditions applied, each time you report player activity for action, "Close a Sale", r4nkt will look to see if the player has closed ten or more sales. If so, then the achievement's lone criterion will be met and the player will earn a badge for "The Closer".

Now, you can create another achievement called "Last Minute Super Closer" that has the same criterion, "Closed 10 Sales". You can give the achievement's criteria group the following condition: `dayOfMonth:last`. Now, whenever you report player activity for action, "Close a Sale", r4nkt will find all of the "Close a Sale" activities that a player has reported on the last day of any month. The sum of each activity's `amount` is taken and, if it meets or exceeds 10, then the achievement's lone criterion will be met and the player will earn a badge for "Last Minute Super Closer".

So, the difference is that without criteria conditions, *all* related player activities are considered. With criteria conditions, only those activities that match the conditions you specified will be taken into account.

## Possibilities

Using the same example criterion tied to the "Close a Sale" action, here is a very simple summary of the various combinations of rules and conditions and what they mean:

|    Condition   |       Rule      | Activities Considered | Criterion Met When                              |
| :------------: | :-------------: | :-------------------: | ----------------------------------------------- |
|    `<none>`    |   `gte:sum,10`  |          all          | The sum of each activity's amount is 10 or more |
|    `<none>`    | `gte:amount,10` |          all          | Any single activity's amount is 10 or more      |
| `dayOfMonth:1` |   `gte:sum,10`  |    1st of any month   | The sum of each activity's amount is 10 or more |
| `dayOfMonth:1` | `gte:amount,10` |    1st of any month   | Any single activity's amount is 10 or more      |

As you can see, there are many possibilities. Combining and nesting criteria groups and applying one or more criteria conditions where it makes sense, together with the flexible criteria rules, gives you a great deal of power and flexibility to get more and more of the specific kinds of achievements you want for your users.

## Available Criteria Conditions

### Activity Data

This condition has the following form: `activityData:field,operator,operand`

When applied, this condition will filter out any activities according to the arguments that you provide. It filters on activities' `custom_data` field, specified by `field`, by comparing it to whatever has been specified in \`operand\`.

This condition is quite powerful and flexible for two reasons. First, it can "peek into" the `custom_data` that you provide when you report player activity. Second, it can compare it to "fixed" values or custom data for the current activity or the current activity's player.

This condition has the following arguments:

| Name     |       Type      | Default |
| -------- | :-------------: | :-----: |
| field    |      string     |    -    |
| operator |      string     |    -    |
| operand  | integer\|string |    -    |

Both `field` and `operator` must be strings, while `operand` may be either an integer or a string.

#### Field

The field argument refers to custom data in activities. You use the field to refer to any value that may have been stored when reporting player activity. By using "dot" notation, you can refer to nested data elements within the `custom_data` field.

#### Operator

The operator simply dictates how the specified activity field will be "compared" to the operand value.

It can be any one of the following values:

* `eq`: equal to
* `gt`: greater than
* `gte`: greater than or equal to
* `lt`: less than
* `lte`: less than or equal to

#### Operand

The operand is the value that each activity's custom data field, as specified, is compared to in order to determine which activities are considered when applying the affected criteria.

The operand may be a "static" value like `1234` or `red`. In such cases, only alphanumeric characters are permitted.

The operand may also be a [custom data reference](/concepts/custom-data-reference), in which case it must be enclosed in curly braces, meaning it would like something like this: `{player.some.path}`.

#### Examples

To better illustrate how this criteria condition might look, please consider some simple examples.

First, you might store custom data like this when reporting certain player activity:

```javascript
{
  "category": "ABC123",
  "attributes": {
    "color": "red",
    "quantity": 4
  }
}
```

To refer to these fields you would use the following definitions:

* `activityData:category,eq,{activity.category}`: When applied, this would filter out all activities that do not have the same category as the current activity.
* `activityData:attributes.color,eq,{player.favorites.color}`: When applied, this would filter out all activities that do not match the current player's favorite color.
* `activityData:attributes.quantity,gte,10`: When applied, this would filter out all activities having a quantity of less than 10.

### Between Hours

This condition has the following form: `betweenHours:from,duration`

When applied, this condition will filter out any activities that are not between the hours specified.

This condition has the following arguments:

| Name     |   Type  | Default |
| -------- | :-----: | :-----: |
| from     | integer |    -    |
| duration | integer |    -    |

Both `from` and `duration` must be integers.

The argument, `from`, may be any integer from `0` to `23`. It represents the starting time hour.

The argument, `duration`, may be any integer from `0` to `24`. It determines the stopping time hour by taking `from` and adding `duration` to it. So, `betweenHours:9,8` will look for activities that take place between 9:00 and 17:00.

{% hint style="warning" %}
Currently, the minimum value of `duration` is `0`, but this may be increased to `1` in the future.
{% endhint %}

### Day of Month

This condition has the following form: `dayOfMonth:day`

When applied, this condition will filter out any activities that are not on the specified day of the month.

This condition has the following arguments:

| Name |       Type      | Default |
| ---- | :-------------: | :-----: |
| day  | integer\|string |    -    |

The argument, `day`, may be any integer from `1` to `31` , the string, `last`, or a custom data reference string.

>

When `last` is used, it will filter on the last day of the month. For example, `dayOfMonth:last` will filter out any activities that are not on the last day of the month. For January, this will be the 31st. For February, this will be the 28th or 29th, depending on the year.

{% hint style="warning" %}
If specifying values for `day` that do not make sense, then results may be unexpected. As such, it is inadvisable to use values greater than 28 unless you combine `dayOfMonth:31`, for example, with other conditions that guarantee the results won't be unexpected, like `month:12`.
{% endhint %}

### Day of Week

This condition has the following form: `dayOfWeek:day`

When applied, this condition will filter out any activities that did not occur during the specified day of the week.

This condition has the following arguments:

| Name |   Type  | Default |
| ---- | :-----: | :-----: |
| day  | integer |    -    |

The argument, `day`, may be any integer from `1` to `7`.

### Day of Year

This condition has the following form: `dayOfYear:day`

When applied, this condition will filter out any activities that did not occur during the specified day of the year.

This condition has the following arguments:

| Name |       Type      | Default |
| ---- | :-------------: | :-----: |
| day  | integer\|string |    -    |

The argument, `day`, may be any integer from `1` to `366` or the string, `last`.

When `last` is used, it will filter on the last day of the year. For example, `dayOfYear:last` will filter out any activities that are not on the last day of the year. This will always be December 31st, but you will not need to worry about whether or not it is a leap year. This will be taken into account for you automatically.

### Days of Week

This condition has the following form: `daysOfWeek:day[,day]`

When applied, this condition will filter out any activities that did not occur during the specified days of the week.

This condition has the following arguments:

| Name |   Type  | Default |
| ---- | :-----: | :-----: |
| day  | integer |    -    |

The argument, `day`, may be any integer from `1` to `7`.

Any combination of days may be provided, separated by a commas (`,`). Duplicates will be ignored.

Some examples:

* weekdays: `daysOfWeek:2,3,4,5,6`
* weekends: `daysOfWeek:1,7`

{% hint style="warning" %}
No more than six days are permitted.
{% endhint %}

### Month

This condition has the following form: `month:month`

When applied, this condition will filter out any activities that did not occur during the specified month.

This condition has the following arguments:

| Name  |       Type      | Default |
| ----- | :-------------: | :-----: |
| month | integer\|string |    -    |

The argument, `month`, may be any integer from `1` to `12` or a custom data reference string.

### Months

This condition has the following form: `months:month[,month]`

When applied, this condition will filter out any activities that did not occur during the specified months.

This condition has the following arguments:

| Name  |       Type      | Default |
| ----- | :-------------: | :-----: |
| month | integer\|string |    -    |

The argument, `month`, may be any integer from `1` to `12` or a custom data reference string.

Any combination of months may be provided, separated by a commas (`,`). Duplicates will be ignored.

Some examples:

* typical summer months (in the northern hemisphere 🤓): `months:6,7,8`
* typical summer months (in the southern hemisphere 🙃): `months:12,1,2`

{% hint style="warning" %}
No more than eleven months are permitted.
{% endhint %}

### Player Data

This condition is similar to `activityData`. It has the following form: `playerData:field,operator,operand`

When applied, this condition will allow related activities to be evaluated if it passes. If it does not pass, then it will halt any further evaluation. It compares a given `custom_data` field for the player, specified by `field`, to whatever has been specified in `operand`.

As with `activityData`, this condition is quite powerful and flexible. First, it can "peek into" the related player's `custom_data`. Second, it can compare it to "fixed" values, custom data for the current activity, or custom data for the current activity's player.

This condition has the following arguments:

| Name     |       Type      | Default |
| -------- | :-------------: | :-----: |
| field    |      string     |    -    |
| operator |      string     |    -    |
| operand  | integer\|string |    -    |

Both `field` and `operator` must be strings, while `operand` may be either an integer or a string.

#### Field

The field argument refers to a player's custom data. You use the field to refer to any value that may have been stored with the current player. By using "dot" notation, you can refer to nested data elements within the `custom_data` field.

#### Operator

The operator simply dictates how the specified custom player data field will be "compared" to the operand value.

It can be any one of the following values:

* `eq`: equal to
* `gt`: greater than
* `gte`: greater than or equal to
* `lt`: less than
* `lte`: less than or equal to

#### Operand

The operand is the value that each player's custom data field, as specified, is compared to in order to determine whether or not further evaluation should be permitted.

The operand may be a "static" value like `1234` or `red`. In such cases, only alphanumeric characters are permitted.

The operand may also be a [custom data reference](/concepts/custom-data-reference), in which case it must be enclosed in curly braces, meaning it would like something like this: `{player.some.path}`.

#### Examples

To better illustrate how this criteria condition might look, please consider some simple examples.

First, you might store custom data like this on a player:

```javascript
{
  "category": "ABC123",
  "attributes": {
    "preferred_currency": "usd",
    "balance": 100
  }
}
```

To refer to these fields you would use the following definitions:

* `playerData:category,eq,{activity.category}`: When applied, this would pass if the current player category matches the activity category.
* `playerData:attributes.preferred_currency,eq,{activity.currency}`: When applied, this would pass if the current player's preferred currency matches the current activity currency.
* `playerData:attributes.balance,gte,10`: When applied, this would pass if the current player's balance is greater than or equal to 10.

{% hint style="warning" %}
Please note that if the specified player field is not found, this means the condition **failed**.
{% endhint %}

### Same Date

This condition has the following form: `sameDate`.

When applied, this condition will filter out any activities that did not occur on the same date as the triggering activity.

### Same Day of Month

This condition has the following form: `sameDayOfMonth`.

When applied, this condition will filter out any activities that did not occur on the same day of the month as the triggering activity.

### Same Day of Week

This condition has the following form: `sameDayOfWeek`.

When applied, this condition will filter out any activities that did not occur on the same day of the week as the triggering activity.

### Same Day of Year

This condition has the following form: `sameDayOfYear`.

When applied, this condition will filter out any activities that did not occur on the same day of the year as the triggering activity.

### Same Month

This condition has the following form: `sameMonth`.

When applied, this condition will filter out any activities that did not occur during the same month as the triggering activity.

### Same Week

This condition has the following form: `sameWeek`.

When applied, this condition will filter out any activities that did not occur during the same week as the triggering activity.

### Same Year

This condition has the following form: `sameYear`.

When applied, this condition will filter out any activities that did not occur during the same year as the triggering activity.

## Defining Criteria Conditions

Criteria conditions by themselves are relatively simple and straightforward, but in order to give you the ability to define complex criteria the structure is not quite as simple or straightforward. It is, however, easy enough to understand.

You can apply criteria conditions to your criteria as well as your criteria groups. The structure is the same in either case.

Criteria conditions are json and have the following format:

```javascript
{
  "operator": "and",
  "groups": [
    {
      "operator": "or",
      "conditions": [
        "betweenHours:8,4",
        "betweenHours:13,4"
      ]
    },
    {
      "conditions": [
        "dayOfWeek:6"
      ]
    }
  ]
}
```

So, at the "top", your criteria conditions definition can have the following properties:

| Name     |    Type    | Default |
| -------- | :--------: | :-----: |
| operator |   string   |   and   |
| groups   | collection |   *-*   |

Currently, `operator` can have one of the following values: `and` or `or`. It is used to determine how the grouped conditions are combined when applying the various conditions.

The `groups` property is a collection of "condition groups". Currently, you must have between 1 and 3 condition groups.

Each "condition group", then, has the following properties:

| Name       |    Type    | Default |
| ---------- | :--------: | :-----: |
| operator   |   string   |   and   |
| conditions | collection |    -    |

Here, `operator` is very similar to before. It can be either `and` or `or`, and it's used to determine how the actual conditions within the group are applied.

The `conditions` collection is where you list the various conditions that you would like to have applied. Currently, you must have between 1 and 3 conditions.


# Criteria Groups

## Description

A criteria group is a group of criteria and/or nested criteria groups. A criteria group is attached to an [achievement](/concepts/achievements) and used to determine whether or not the achievement has been earned by a player.

## Properties

A criteria group has the following properties:

| Name             |    Type    | Default |
| ---------------- | :--------: | :-----: |
| custom\_id       |   string   |    -    |
| name             |   string   |    -    |
| description      |   string   | *empty* |
| operator         |   string   |   and   |
| criteria         | collection | *empty* |
| criteria\_groups | collection | *empty* |
| conditions       |    json    | *empty* |

{% hint style="info" %}
Click [here](/concepts/overview#common-properties) for information about common properties.
{% endhint %}

### Operator

The criteria group's `operator` property determines which boolean logic is employed when it is evaluated. It can have any one of the following values:

* `and`: The criteria group's criteria and nested criteria groups will be `and`ed together when evaluated. This means that all criteria and nested criteria groups for a criteria group with `operator` equal to `and` must be `true` for it to evaluate to `true` itself.
* `or`: The criteria group's criteria and nested criteria groups will be `or`ed together when evaluated. This means at least one of a criteria group's criteria or nested criteria groups must be `true` for it to evaluate to `true` itself.
* `xor`: The criteria group's criteria and nested criteria groups will be `xor`ed together when evaluated. This means only one of a criteria group's criteria or nested criteria groups can be `true` for it to evaluate to `true` itself.

{% hint style="warning" %}
If a criteria group has neither criteria nor nested criteria groups, then it will **always** evaluate to `false`, regardless of its operator value.
{% endhint %}

### Criteria

A criteria group can have multiple [criteria](/concepts/criteria). They can be attached to a criteria group in order to be evaluated against a player's activities.

### Criteria Groups

A criteria group may itself have nested criteria groups. This allows for a single achievement to have simple or complex criteria.

Some notes about nested criteria groups:

* Criteria groups can have zero or more nested criteria groups.
* Criteria groups cannot have duplicate nested criteria groups.
* Chains can be defined. That is, criteria group A can nest criteria group B, which can nest criteria group C.
* Chains may not be cyclical. That is, criteria group A can nest criteria group B, but criteria group B cannot nest criteria group A.
* Depending on your subscription, there may be limits to the number of nested criteria groups a single criteria group can have as well as the depth or length of an criteria group-nested-criteria group chain.

### Conditions

[Criteria conditions](/concepts/criteria-conditions) are common to both [criteria](/concepts/criteria) and criteria groups. If present, they are applied before looking to see if a criterion has been met. Conditions provide a way to filter player activities when determining whether or not a criterion has been met. Once filtered, the [criterion's rule](/concepts/criteria#rule) is used against whatever activities remain.


# Custom Data Reference

Custom data references give you much more flexibility and power when it comes to defining your achievements. Using them will allow you to create achievements that:

* are more dynamic
* better reflect the domain knowledge of your game

Custom data references can be used in a handful of [criteria conditions](/concepts/criteria-conditions) and can be used to reference custom data on the following entities:

* action: This refers to the action that is part of the current player activity.
* activity: This refers to the current player activity.
* player: This refers to the player that is part of the current player activity.

This is how it works:

* You report your player activity.
* R4nkt receives the reported player activity and begins to process it. This is what is considered the **current player activity**.
* When applying criteria conditions, any custom data references that are encountered will be replaced with whatever value is found for the **current player activity**, whether that be the player, the action, or the activity itself.

The custom references themselves work in a fairly straightforward manner. They "reach into" the relevant resource's `custom_data` value, with each "dot" (`.`) referring to nested values.

## Example

A simple example would be to define an achievement to be awarded whenever certain actions are performed on your player's birthday. Since you have many players, how do you do this?

You would use custom data references, of course:

* `month:{player.birthdate.month}`
* `dayOfMonth:{player.birthdate.day}`

A full definition would like like so:

```javascript
{
  "groups": [
    {
      "conditions": [
        "month:{player.birthdate.month}",
        "dayOfMonth:{player.birthdate.day}"
      ]
    }
  ]
}
```

And your player's `custom_data` might look like so:

```javascript
{
  "birthdate": {
    "day": 29,
    "month": 5,
    "year": 1970
  }
}
```


# Games

## Description

Games in r4nkt are what you need for your application or game that you wish to gamify. Each r4nkt game you have access to will allow you to configure a set of resources that will allow you to add gamification features to your game or application.

## Properties

Games have the following properties:

| Name            |  Type  | Default |
| --------------- | :----: | :-----: |
| game\_id        | string |    -    |
| name            | string |    -    |
| description     | string | *empty* |
| webhook\_url    | string | *empty* |
| webhook\_secret | string | *empty* |

### Game ID

Your game ID is automatically generated and unique to your game within the r4nkt system. It is used to talk to the r4nkt API.

### Webhook URL

A webhook URL is the URL that will be called to pass information along to you for different events that occur within r4nkt. You can read more about webhooks [here](/webhooks/overview).

### Webhook secret

A webhook secret is used to validate any webhook calls you receive from r4nkt. You can read more about webhooks [here](/webhooks/overview).


# Leaderboards

## Description

Leaderboards are where you record and/or retrieve your player rankings and scores. There are different types of leaderboards that offer different features, but they all track your players' scores.

## Time spans

One thing to note about leaderboards is that they track scores for several different time spans. This allows you to use the same leaderboard to track rankings for various time spans. The currently supported time spans are as follows:

* `all-time`
* `daily`
* `monthly`
* `weekly`
* `yearly`

Whenever a score is recorded, it is recorded for each of the aforementioned timespans. So, when a score is recorded, the all-time time span for the leaderboard is updated, as are the daily, weekly, monthly, and yearly time spans for the leaderboard for the specific day, week, month, and year that correspond to the recording's date/time.

This powerful feature allows you to easily retrieve and display rankings for any given day, week, month, or year for which scores have been recorded as well as the all-time rankings.

{% hint style="info" %}
If no scores have been recorded for a given time-span, then an empty set of leaderboard rankings will be returned.
{% endhint %}

## Properties

Leaderboards have the following properties:

| Name                |  Type  |      Default     |
| ------------------- | :----: | :--------------: |
| custom\_id          | string |         -        |
| name                | string |         -        |
| description         | string |      *empty*     |
| custom\_data        |  json  |      *empty*     |
| type                | string |     standard     |
| custom\_session\_id | string |      *empty*     |
| ordering            | string | larger-is-better |
| score\_preference   | string |   prefer-higher  |

{% hint style="info" %}
Click [here](/concepts/overview#common-properties) for information about common properties.
{% endhint %}

### Type

There are currently three types of leaderboards supported in r4nkt. A leaderboard's type can be found in its `type` property and can have one of the following values:

* `standard`: This type of leaderboard is one based on players' achievement points. Whenever an achievement is earned, then the points for all of their earned achievements are added together and recorded. This is done automatically and for each time span. No other customization is required.
* `session`: This type of leaderboard is nearly identical to the `standard` type.  The difference is that it only reflects achievement points that have been earned within the context of a session.
* `custom`: A custom leaderboard is one where the players' scores must be uploaded directly. When a player's score is submitted for a custom leaderboard, then it will be compared to the player's old score on that leaderboard, if it exists. If none exist, then the new one will be recorded. If the new one is better than the old one, then the new one will be added and the old one will be forgotten. This is done for each time span. Again, no other customization is required.

{% hint style="info" %}
For any given game, no more than one `standard` leaderboard is allowed.
{% endhint %}

{% hint style="info" %}
You cannot submit scores to`standard` or `session` leaderboards.
{% endhint %}

{% hint style="info" %}
When comparing scores the leaderboard's `ordering` property is used to determine which score is better **and** how to rank. Read more [here](/concepts/leaderboards#ordering).
{% endhint %}

{% hint style="warning" %}
Please note that, once created, a leaderboard's `type` property cannot be changed.
{% endhint %}

### Custom Session ID

For session-based leaderboards (`type` is set to `session`), a custom session ID is required.  This ID is used when reporting activity if the activity took place within some sort of custom session.  Whenever activity is reported when a custom session ID is provided, then those activities will be processed within such a context first.

{% hint style="warning" %}
Please note that, once created, a leaderboard's `custom_session_id` property cannot be changed.
{% endhint %}

### Ordering

A leaderboard's `ordering` property determines how the scores are interpreted as well as how rankings are determined.  It can have one of the following values:

* `larger-is-better`: These leaderboards consider larger scores as better than lower ones.
* `smaller-is-better`: These leaderboards consider smaller scores as better than larger ones.

### Score Preference

A leaderboard's `score_preference` property determines how new scores are compared to old scores when updating a given leaderboard. This applies to all leaderboard types and is applying the same regardless of the leaderboard's `ordering` property.

A leaderboard's `score_preference` can be set to one of the following values:

* `prefer-higher`: When comparing a new score to an old one, the new one will be added if it's greater than the old one.
* `prefer-lower`: When comparing a new score to an old one, the new one will be added if it's less than the old one.
* `prefer-first`: The first score will be added. All subsequent scores will be ignored.
* `prefer-last`: Each score that is submitted will added. Any previous scores will be removed.

## Rankings

Of course, a leaderboard is somewhat boring without the ability to see how the players are ranked.

### Leaderboard Rankings

Leaderboard rankings can be requested for any leaderboard.  Pagination is supported and rankings can be requested for any given time span, which defaults to `all-time`.

### Player Rankings

An individual player's ranking for a specified leaderboard is also available.  It can be requested for any given time span, but it defaults to `all-time`.&#x20;


# Players

## Description

Players in r4nkt are your end-users. They are the individuals that use your software or play your game.

## Properties

Players have the following properties:

| Name         |  Type  | Default |
| ------------ | :----: | :-----: |
| custom\_id   | string |    -    |
| time\_zone   | string |   UTC   |
| custom\_data |  json  | *empty* |

{% hint style="info" %}
Click [here](/concepts/overview#common-properties) for information about common properties.
{% endhint %}

### Time Zone

This property represents your player's time zone. Any date/time-related calculations for your player will take this value into account.

If you have criteria that must be met between specified hours or on a specified day, then this is how you make sure that your individual players' actions are interpreted accurately for each individual player. When it's 5 PM for your players in New York, New York, US, it's not 5 PM in Sydney, Australia. In fact, it's not even the same day.

Setting this property correctly for each of your individual players solves this problem. Then, each of your players' actions are interpreted according to the criteria you have specified but in the context of their own time zone.

We use time zones from the [tz database](https://en.wikipedia.org/wiki/Tz_database).

Here is a list of some common or recognizable time zone values:

* `Europe/Copenhagen`
* `Europe/London`
* `America/New_York`
* `America/Los_Angeles`
* `Asia/Tokyo`
* `Australia/Sydney`

You can [look here](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) for a complete listing of possible values.

{% hint style="info" %}
This property defaults to `UTC`.
{% endhint %}


# Rewards

## Description

Rewards, once created, can be assigned to achievements. Upon earning an achievement, you can then distribute these rewards to the player. They can be anything you like. You might want to award a certain number of points to a custom leaderboard. You might want to fire off an order to Amazon for a gift card. You might send an email to someone in HR to hand-deliver a weekend getaway package. The possibilities are endless.

## Properties

Rewards have the following properties:

| Name         |  Type  | Default |
| ------------ | :----: | :-----: |
| custom\_id   | string |    -    |
| name         | string |    -    |
| description  | string | *empty* |
| custom\_data |  json  | *empty* |

{% hint style="info" %}
Click [here](/concepts/overview#common-properties) for information about common properties.
{% endhint %}

{% hint style="info" %}
Rewards can be anything you like, but it's **your** responsibility to to distribute the reward to the player.
{% endhint %}


# Scores

## Description

Scores are used to rank players against one another. Scores are generated automatically for standard leaderboards whenever achievements with points are earned. Scores are to be submitted manually for custom leaderboards. When a leaderboard ranking is requested, a score is a simple number. A score is unique to a player, leaderboard, and time span.

Once a score is submitted for a custom leaderboard, r4nkt will make sure that it is represented for each time span. If a player already has a score for a leaderboard and time-span combination, then r4nkt will determine whether or not the new score is better. If so, then it will be updated. If not, then it will be ignored. You will be informed of the time spans for which the submitted score was an improvement.

## Properties

When submitting a score for a custom leaderboard, it can have following properties:

| Name                    |   Type  | Default |
| ----------------------- | :-----: | :-----: |
| custom\_leaderboard\_id |  string |    -    |
| custom\_player\_id      |  string |    -    |
| score                   | integer | *empty* |
| date\_time\_utc         |  string | *empty* |

### Leaderboard

A score is submitted for a specific custom leaderboard, which is identified by its `custom_id` property.

{% hint style="warning" %}
Scores submitted to `standard` leaderboards will be rejected.
{% endhint %}

### Player

A score is submitted for a specific player, which is identified by the player's `custom_id` property.

{% hint style="info" %}
When submitting scores, if the `custom_player_id` is not recognized, then a new player will be created.
{% endhint %}

### Score

The score is an integer. Currently, it must be a value between 0 and 9,223,372,036,854,775,807, inclusive.

### Date/time

The `date_time_utc` value is the date/time (UTC) for when the score should be recorded. It defaults to the current date/time. If provided, however, it must be a date/time in the past. Scores may not be submitted for the future.


# Criteria Conditions

## Anniversary

It's quite common to want to filter on a given anniversary.

If you want to specify the anniversary for some "static" date like [Festivus](https://en.wikipedia.org/wiki/Festivus): `dayOfMonth:23` and `month:12`

{% hint style="info" %}
Remember to `and` these together in your definitions.
{% endhint %}

Here is how this might appear when specified in JSON:

```javascript
{
    "conditions": [
        "operator": "and",
        "groups": [
            "operator": "and",
            "conditions": [
                "month:12",
                "dayOfMonth:23"
            ]
        ]
    ]
}
```

## Summer Months

This is a relatively easy recipe, but it's included anyway.

If you want to specify the typical summer months in the northern hemisphere: `months:6,7,8`

If you want to specify the typical summer months in the southern hemisphere: `months:12,1,2`

{% hint style="info" %}
&#x20;In addition to the seasons being different between earth's hemispheres, not everyone agrees on which months constitute a given season. 🤓
{% endhint %}


# Achievements

These "recipes" give you examples of various achievements with different levels of complexity. All of them could be altered to apply to similar situations. Hopefully these will give you a better idea of what you can do with r4nkt.

## First Time Closer

For this example, we will imagine that we have an achievement that is to be awarded to your player the first time they close a sale.

### Ingredients

#### Actions

Only one action is required with the following properties:

* custom\_id: close.sale
* name: Close a Sale

#### Criteria

Only one criterion is required with the following properties:

* custom\_id: closed.a.sale
* name: Closed a Sale
* custom\_action\_id: close.sale
* type: sum
* rule: gte:1

#### Criteria Groups

Only one criteria group is required with the following properties:

* custom\_id: closed.a.sale
* name: Closed a Sale
* criteria (custom criteria IDs):
  * closed.a.sale

#### Achievements

Your achievement should have the following properties:

* custom\_criteria\_group\_id: closed.a.sale

## Night Owl

For this example, we will imagine that we have an achievement that is to be awarded to your player when they post an article between midnight and 4 AM.

### Ingredients

#### Actions

Only one action is required with the following properties:

* custom\_id: post.article
* name: Post Article

#### Criteria

Only one criterion is required with the following properties:

* custom\_id: posted.article
* name: Posted Article
* custom\_action\_id: post.article
* type: sum
* rule: gte:1

#### Criteria Groups

Only one criteria group is required with the following properties:

* custom\_id: posted.article.in.middle.of.night
* name: Posted Article in the Middle of the Night
* criteria (custom criteria IDs):
  * posted.article
* criteria\_conditions:
  * groups:
    * conditions:
      * betweenHours:0,4

#### Achievements

Your achievement should have the following properties:

* custom\_criteria\_group\_id: posted.article.in.middle.of.night

## Happy Birthday Tony Stark

For this example, we will imagine that we have an achievement that is to be awarded to your player when they schedule a meeting on [Tony Stark's](https://en.wikipedia.org/wiki/Tony_Stark_\(Marvel_Cinematic_Universe\)) birthday, May 29.

### Ingredients

#### Actions

Only one action is required with the following properties:

* custom\_id: schedule.meeting
* name: Schedule Meeting

#### Criteria

Only one criterion is required with the following properties:

* custom\_id: scheduled.meeting
* name: Scheduled Meeting
* custom\_action\_id: schedule.meeting
* type: sum
* rule: gte:1

#### Criteria Groups

Only one criteria group is required with the following properties:

* custom\_id: scheduled.meeting.on.tony.starks.birthday
* name: Scheduled Meeting on Tony Stark's Birthday
* criteria (custom criteria IDs):
  * scheduled.meeting
* criteria\_conditions:
  * groups:
    * conditions:
      * month:5
      * dayOfMonth:29

#### Achievements

Your achievement should have the following properties:

* custom\_criteria\_group\_id: scheduled.meeting.on.tony.starks.birthday

## Trash Collector

Here we will imagine that we have an achievement that is to be awarded to your player when they delete 100+ files in a single day.

### Ingredients

#### Actions

Only one action is required with the following properties:

* custom\_id: delete.file
* name: Delete File

#### Criteria

Only one criterion is required with the following properties:

* custom\_id: deleted.100.files.in.single.day
* name: Deleted 100 Files in Single Day
* custom\_action\_id: delete.file
* type: sum
* rule: gte:100
* criteria\_conditions:
  * groups:
    * conditions:
      * sameDay

#### Criteria Groups

Only one criteria group is required with the following properties:

* custom\_id: deleted.100.files.in.single.day
* name: Deleted 100 Files in Single Day
* criteria (custom criteria IDs):
  * deleted.100.files.in.single.day

#### Achievements

Your achievement should have the following properties:

* custom\_criteria\_group\_id: deleted.100.files.in.single.day

## One Week Wonder

Here we will imagine that we have an achievement that is to be awarded to your player when they log in to your game each day of a given week.

{% hint style="warning" %}
Note that this will define when a player has performed the action for each day of a single week...that is, Sunday through Saturday. This is not the same as performing an action for seven straight days, nor is it the same as performing an action on each day of the week, but not necessarily the same week.
{% endhint %}

### Ingredients

#### Actions

Only one action is required with the following properties:

* custom\_id: log.in
* name: Log In

#### Criteria

Seven criteria are required for this recipe, one for each day of the week.  They should like like the following, but with adjustments made to `custom_id`, `name`, and `rule` for each respective day of the week:

* custom\_id: logged.in.on.sunday
* name: Logged In on Sunday
* custom\_action\_id: log.in
* type: sum
* rule: gte:1
* criteria\_conditions:
  * groups:
    * conditions:
      * dayOfWeek:1

#### Criteria Groups

Only one criteria group is required with the following properties:

* custom\_id: logged.in.each.day.of.week.for.one.week
* name: Logged in each Day of Week for One Week
* criteria (custom criteria IDs):
  * logged.in.on.sunday
  * logged.in.on.monday
  * logged.in.on.tuesday
  * logged.in.on.wednesday
  * logged.in.on.thursday
  * logged.in.on.friday
  * logged.in.on.saturday
* criteria\_conditions:
  * groups:
    * conditions:
      * sameWeek

#### Achievements

Your achievement should have the following properties:

* custom\_criteria\_group\_id: logged.in.each.day.of.week.for.one.week

## 6-Digits Club

Here we will imagine that we have an achievement that is to be awarded to your player when they close a sale for $100,000 or more.

{% hint style="warning" %}
This recipe requires that whenever you report that your player has closed a sale that the price is attached via the activity's `custom_data` field.
{% endhint %}

### Ingredients

#### Actions

* custom\_id: close.sale
* name: Close a Sale

#### Criteria

Only one criterion is required with the following properties:

* custom\_id: closed.a.sale
* name: Closed a Sale
* custom\_action\_id: close.sale
* type: sum
* rule: gte:1

#### Criteria Groups

Only one criteria group is required with the following properties:

* custom\_id: closed.a.sale.for.100000.or.more
* name: Closed a Sale for 100000+
* criteria (custom criteria IDs):
  * closed.a.sale
* criteria\_conditions:
  * groups:
    * conditions:
      * activityData:price,gte,1000

#### Achievements

Your achievement should have the following properties:

* custom\_criteria\_group\_id: closed.a.sale.for.100000.or.more

## Repeat Business

Here we will imagine that we have an achievement that is to be awarded to your player when they sell a car to a customer for the second time.

{% hint style="warning" %}
This recipe requires that whenever you report that your player has sold a car that the customer ID is attached via the activity's `custom_data` field.
{% endhint %}

### Ingredients

#### Actions

Only one action is required with the following properties:

* custom\_id: sell.car
* name: Sell a Car

#### Criteria

Only one criterion is required with the following properties:

* custom\_id: sold.at.least.two.cars
* name: Sold at least Two Cars
* custom\_action\_id: sell.car
* type: sum
* rule: gte:2

#### Criteria Groups

Only one criteria group is required with the following properties:

* custom\_id: sold.a.second.car.to.same.customer
* name: Sold a second Car to the Same Customer
* criteria (custom criteria IDs):
  * sold.at.least.two.cars
* criteria\_conditions:
  * groups:
    * conditions:
      * activityData:customer.id,eq,{activity.customer.id}

#### Achievements

Your achievement should have the following properties:

* custom\_criteria\_group\_id: sold.a.second.car.to.same.customer

## Twenty-Something

Here we will imagine that we have an achievement that is to be awarded to your player when they enroll someone in their 20s.

{% hint style="warning" %}
This recipe requires that whenever you report that your player has enrolled someone that the age of the enrollee is attached via the activity's `custom_data` field.
{% endhint %}

### Ingredients

#### Actions

Only one action is required with the following properties:

* custom\_id: enroll.person
* name: Enroll Person

#### Criteria

Only one criterion is required with the following properties:

* custom\_id: enrolled.person
* name: Enrolled Person
* custom\_action\_id: enroll.person
* type: sum
* rule: gte:1

#### Criteria Groups

Only one criteria group is required with the following properties:

* custom\_id: enrolled.twenty.something
* name: Enrolled Twenty-Something
* criteria (custom criteria IDs):
  * enrolled.person
* criteria\_conditions:
  * groups:
    * conditions:
      * activityData:customer.age,gte,20
      * activityData:customer.age,lt,30

#### Achievements

Your achievement should have the following properties:

* custom\_criteria\_group\_id: enrolled.twenty.something

## Birthday Boss Beater

Here we will imagine that we have an achievement that is to be awarded to your player when they defeat the boss at the end of the game on their birthday.

{% hint style="warning" %}
This recipe requires that whenever you store your player's birthday in the player resource's `custom_data` field.
{% endhint %}

### Ingredients

#### Actions

Only one action is required with the following properties:

* custom\_id: defeat.boss
* name: Defeat Boss

#### Criteria

Only one criterion is required with the following properties:

* custom\_id: defeated.boss
* name: Defeated Boss
* custom\_action\_id: defeat.boss
* type: sum
* rule: gte:1

#### Criteria Groups

Only one criteria group is required with the following properties:

* custom\_id: defeated.boss.on.birthday
* name: Defeated Boss on Birthday
* criteria (custom criteria IDs):
  * defeated.boss
* criteria\_conditions:
  * groups:
    * conditions:
      * month:{player.birthday.month}
      * dayOfMonth:{player.birthday.day}

#### Achievements

Your achievement should have the following properties:

* custom\_criteria\_group\_id: defeated.boss.on.birthday


# Overview

In order to use r4nkt, you will need to use our Application Programming Interface, or API. The API allows you to configure your application. This use of the API is optional. The alternative is to use our [Laravel Nova](https://nova.laravel.com/)-based administration panel. The API also allows you to do things like record player activity and get leaderboard data. This is required in order to properly and fully use r4nkt.

Everything you see in the administration panel can be controlled with the API.

There are only a couple of things you will need in order to start using the API:

1. Learn about our API [authentication](/api/authentication)
2. Generate an API token

You may now go about using the API. Optionally, we provide a [PHP SDK package](/php-sdk/overview) to help get you started.

## API Endpoints

The base for all r4nkt API endpoints is `https://api.r4nkt.com/v1`. The rest of the endpoint is based on the type of resource you're interested in and the method that you would like the API to perform.

Here are the API methods, or verbs, that the r4nkt API uses and a brief description of what they mean:

* `POST`: this indicates that you would like to create a resource.
* `GET`: this indicates that you would like to retrieve information for a specific resource (a specific badge or a specific leaderboard, etc) or a resource type (badges, leaderboards, etc). Requests that use `GET` are considered *idempotent*, which means that no data is modified.
* `PUT`: this indicates that a specific resource is to be updated or modified.
* `DELETE`: this indicates that a specific resource is to be deleted.

To be clear, requests that use the `GET` method will *not* modify your resources while requests that use the other methods will modify them.

## Headers

In addition to the `Authorization` header for [authentication](/api/authentication), you should also include the following headers in all requests:

* `Accept: application/json`
* `Content-Type: application/json`

## Response Data

All r4nkt API endpoint responses are JSON-formatted. Here's a sample response from the `/criteria` endpoint, that lists all criteria:

```javascript
{
  "data": [
    {
      "custom_id": "onetedtpvjwcdgplqnjr",
      "name": "afpjycybpmuimrcuuwdj",
      "description": "Repellendus quibusdam consequatur provident.",
      "type": "simple",
      "rule": "gte:sum,1",
      "created_at": "2020-01-18 23:38:07",
      "updated_at": "2020-01-18 23:38:07",
      "custom_action_id": "wodgmtysxugytbmqzbll"
    },
    {
      "custom_id": "gexbxdctpkpebgmwvkql",
      "name": "ysgrjcpuqmdudrvrjbxe",
      "description": "Id voluptatum nihil tempore.",
      "type": "simple",
      "rule": "gte:sum,1",
      "created_at": "2020-01-18 23:38:07",
      "updated_at": "2020-01-18 23:38:07",
      "custom_action_id": "wodgmtysxugytbmqzbll"
    }
  ]
}
```

Each endpoint returns different data, reflecting the resource type and operation that is being formed. More information on each endpoint can be found in the documentation specific to each endpoint.

## Rate limiting

Our API requests are rate limited. This is done in large part to prevent abuse and ensure service stability. A rate limit sets the maximum number of API calls that can be made in a given period of time.

Currently, we have only one kind of rate limit:

* number of requests per day

The exact limit is determined by the subscription tier to which the call is tied.  That is, when an API request is made, a game ID is passed along.  This game ID indicates a specific game which, in turn, belongs to a specific subscription tier.  This tier determines the actual limit.

## Pagination

Almost every resource index endpoint supports pagination. Our API [expects](https://jsonapi.org/examples/#pagination) you to use the [json:api spec](https://jsonapi.org) for pagination. The default page number is always 1 and the default page size is currently set to 30. The maximum allowable page size is currently set to 100.


# Authentication

## Get your API token

Once you are logged in to your dashboard navigate to API access and create an API token.

You can name your token, so you know where this one is going to be used, in case you ever need to revoke it.

## r4nkt API access

Once you create a token, it will be shown only once to you. Make sure to store it safely. After it is shown it can only be revoked, in which case you will need to generate a new token for use.

Once you have your token, you can authenticate against the API.

## Authenticate against the API

The token you've received can be used in the `Authorization` header.

Here's a curl example of how you can authenticate against the API. In this example, it will list all of your game's actions.

```bash
$ R4NKT_TOKEN="your API token"
$ curl https://api.r4nkt.com/v1/games/<your game id>/actions \
    -H "Authorization: Bearer $R4NKT_TOKEN" \
    -H "Accept: application/json" \
    -H "Content-Type: application/json"
```

The token is used to authenticate. The `/v1/games/<game_id>/actions` endpoint is hit to retrieve your game's actions. The resulting response payload might look like this:

```javascript
{
   "data":[
      {
         "custom_id":"solve.puzzle",
         "name":"solve.puzzle",
         "description":"Solve any puzzle",
         "custom_data":null,
         "created_at":"2021-10-06T12:05:20.000000Z",
         "updated_at":"2021-10-06T12:05:20.000000Z"
      },
      {
         "custom_id":"open.chest",
         "name":"open.chest",
         "description":"Open any chest",
         "custom_data":null,
         "created_at":"2021-10-06T12:05:20.000000Z",
         "updated_at":"2021-10-06T12:05:20.000000Z"
      }
   ],
   "links":{
      ...
   },
   "meta":{
      ...
   }
}
```


# Achievements

## Create an achievement

<mark style="color:green;">`POST`</mark> `/v1/games/:game_id/achievements`

#### Request Body

| Name                        | Type   | Description |
| --------------------------- | ------ | ----------- |
| custom\_id                  | string |             |
| name                        | string |             |
| description                 | string |             |
| is\_secret                  | string |             |
| points                      | string |             |
| custom\_criteria\_group\_id | string |             |
| custom\_data                | string |             |

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

```
```

{% endtab %}
{% endtabs %}

## Retrieve an achievement

<mark style="color:blue;">`GET`</mark> `/v1/games/:game_id/achievements/:id`

#### Path Parameters

| Name | Type   | Description |
| ---- | ------ | ----------- |
|      | string |             |

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

```
```

{% endtab %}
{% endtabs %}

## Update an achievement

<mark style="color:orange;">`PUT`</mark> `/v1/games/:game_id/achievements/:id`

#### Path Parameters

| Name | Type   | Description |
| ---- | ------ | ----------- |
|      | string |             |

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

```
```

{% endtab %}
{% endtabs %}

## Delete an achievement

<mark style="color:red;">`DELETE`</mark> `/v1/games/:game_id/achievements/:id`

#### Path Parameters

| Name | Type   | Description |
| ---- | ------ | ----------- |
|      | string |             |

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

```
```

{% endtab %}
{% endtabs %}

## List all achievements

<mark style="color:blue;">`GET`</mark> `/v1/games/:game_id/achievements`

#### Path Parameters

| Name | Type   | Description |
| ---- | ------ | ----------- |
|      | string |             |

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

```
```

{% endtab %}
{% endtabs %}


# Actions

## Create an action

<mark style="color:green;">`POST`</mark> `/v1/games/:game_id/actions`

#### Request Body

| Name         | Type   | Description |
| ------------ | ------ | ----------- |
| custom\_id   | string |             |
| name         | string |             |
| description  | string |             |
| custom\_data | string |             |
| reactions    | array  |             |

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

```
```

{% endtab %}
{% endtabs %}

## Retrieve an action

<mark style="color:blue;">`GET`</mark> `/v1/games/:game_id/actions/:id`

#### Path Parameters

| Name | Type   | Description |
| ---- | ------ | ----------- |
|      | string |             |

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

```
```

{% endtab %}
{% endtabs %}

## Update an action

<mark style="color:orange;">`PUT`</mark> `/v1/games/:game_id/actions/:id`

#### Path Parameters

| Name | Type   | Description |
| ---- | ------ | ----------- |
|      | string |             |

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

```
```

{% endtab %}
{% endtabs %}

## Delete an action

<mark style="color:red;">`DELETE`</mark> `/v1/games/:game_id/actions/:id`

#### Path Parameters

| Name | Type   | Description |
| ---- | ------ | ----------- |
|      | string |             |

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

```
```

{% endtab %}
{% endtabs %}

## List all actions

<mark style="color:blue;">`GET`</mark> `/v1/games/:game_id/actions`

#### Path Parameters

| Name | Type   | Description |
| ---- | ------ | ----------- |
|      | string |             |

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

```
```

{% endtab %}
{% endtabs %}


# Activities

## Create an activity

<mark style="color:green;">`POST`</mark> `/v1/games/:game_id/activities`

#### Request Body

| Name                | Type    | Description                                           |
| ------------------- | ------- | ----------------------------------------------------- |
| custom\_action\_id  | string  |                                                       |
| custom\_player\_id  | string  |                                                       |
| custom\_session\_id | string  |                                                       |
| amount              | integer | Defaults to 1                                         |
| date\_time\_utc     | string  | Sample format: \`2021-01-13T23:13:46.921279Z\`        |
| uuid                | string  | Must be a valid RFC 4122 (version 1, 3, 4, or 5) UUID |

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

```
```

{% endtab %}
{% endtabs %}

## UUID

This parameter can be used to determine whether or not you have already reported a given player activity. This scenario might occur for a number of reasons, e.g. poor network, errors that occur in your project when sending, etc.

## Amount

The amount that you specify indicates the number of times the action has been performed by the player.

{% hint style="info" %}
Default: `1`
{% endhint %}

## Date/Time UTC

This is the date/time that the action is to be recorded.  For some circumstances, this shouldn't be necessary, but for others it will.  It is good to use if precision is important or if there's a need to "go back in time" and report activities that weren't previously reported.

{% hint style="info" %}
Default: the current date/time when the request is received.
{% endhint %}

{% hint style="info" %}
The value passed cannot be in the future.
{% endhint %}


# Criteria

## Create a criterion

<mark style="color:green;">`POST`</mark> `/v1/games/:game_id/criteria/`

#### Request Body

| Name               | Type   | Description |
| ------------------ | ------ | ----------- |
| custom\_id         | string |             |
| name               | string |             |
| description        | string |             |
| type               | string |             |
| custom\_action\_id | string |             |
| conditions         | string |             |
| rule               | string |             |

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

```
```

{% endtab %}
{% endtabs %}

## Retrieve a criterion

<mark style="color:blue;">`GET`</mark> `/v1/games/:game_id/criteria/:id`

#### Path Parameters

| Name | Type   | Description                                                |
| ---- | ------ | ---------------------------------------------------------- |
| id   | string | The custom ID of the criterion you would like to retrieve. |

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

```
```

{% endtab %}
{% endtabs %}

## Update a criterion

<mark style="color:orange;">`PUT`</mark> `/v1/games/:game_id/criteria/:id`

#### Path Parameters

| Name | Type   | Description                                              |
| ---- | ------ | -------------------------------------------------------- |
| id   | string | The custom ID of the criterion you would like to update. |

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

```
```

{% endtab %}
{% endtabs %}

## Delete a criterion

<mark style="color:red;">`DELETE`</mark> `/v1/games/:game_id/criteria/:id`

#### Path Parameters

| Name | Type   | Description                                              |
| ---- | ------ | -------------------------------------------------------- |
|      | string | The custom ID of the criterion you would like to delete. |

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

```
```

{% endtab %}
{% endtabs %}

## List all criteria

<mark style="color:blue;">`GET`</mark> `/v1/games/:game_id/criteria`

#### Path Parameters

| Name | Type   | Description |
| ---- | ------ | ----------- |
|      | string |             |

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

```
```

{% endtab %}
{% endtabs %}


# Criteria Groups

## Create a criteria group

<mark style="color:green;">`POST`</mark> `/v1/games/:game_id/criteria-groups`

#### Path Parameters

| Name | Type   | Description |
| ---- | ------ | ----------- |
|      | string |             |

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

```
```

{% endtab %}
{% endtabs %}

## Retrieve a criteria group

<mark style="color:blue;">`GET`</mark> `/v1/games/:game_id/criteria-groups/:id`

#### Path Parameters

| Name | Type   | Description |
| ---- | ------ | ----------- |
|      | string |             |

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

```
```

{% endtab %}
{% endtabs %}

## Update a criteria group

<mark style="color:orange;">`PUT`</mark> `/v1/games/:game_id/criteria-groups/:id`

#### Path Parameters

| Name | Type   | Description |
| ---- | ------ | ----------- |
|      | string |             |

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

```
```

{% endtab %}
{% endtabs %}

## Delete a criteria group

<mark style="color:red;">`DELETE`</mark> `/v1/games/:game_id/criteria-groups/:id`

#### Path Parameters

| Name | Type   | Description |
| ---- | ------ | ----------- |
|      | string |             |

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

```
```

{% endtab %}
{% endtabs %}

## List all criteria groups

<mark style="color:blue;">`GET`</mark> `/v1/games/:game_id/criteria-groups`

#### Path Parameters

| Name | Type   | Description |
| ---- | ------ | ----------- |
|      | string |             |

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

```
```

{% endtab %}
{% endtabs %}


# Leaderboards

## Create a leaderboard

<mark style="color:green;">`POST`</mark> `/v1/games/:game_id/leaderboards`

#### Path Parameters

| Name | Type   | Description |
| ---- | ------ | ----------- |
|      | string |             |

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

```
```

{% endtab %}
{% endtabs %}

## Retrieve a leaderboard

<mark style="color:blue;">`GET`</mark> `/v1/games/:game_id/leaderboards/:id`

#### Path Parameters

| Name | Type   | Description |
| ---- | ------ | ----------- |
|      | string |             |

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

```
```

{% endtab %}
{% endtabs %}

## Update a leaderboard

<mark style="color:orange;">`PUT`</mark> `/v1/games/:game_id/leaderboards/:id`

#### Path Parameters

| Name | Type   | Description |
| ---- | ------ | ----------- |
|      | string |             |

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

```
```

{% endtab %}
{% endtabs %}

## Delete a leaderboard

<mark style="color:red;">`DELETE`</mark> `/v1/games/:game_id/leaderboards/:id`

#### Path Parameters

| Name | Type   | Description |
| ---- | ------ | ----------- |
|      | string |             |

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

```
```

{% endtab %}
{% endtabs %}

## List all leaderboards

<mark style="color:blue;">`GET`</mark> `/v1/games/:game_id/leaderboards`

#### Path Parameters

| Name | Type   | Description |
| ---- | ------ | ----------- |
|      | string |             |

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

```
```

{% endtab %}
{% endtabs %}

## List a leaderboard's rankings

<mark style="color:blue;">`GET`</mark> `/v1/games/:game_id/leaderboards/:id/rankings`

#### Path Parameters

| Name | Type   | Description |
| ---- | ------ | ----------- |
|      | string |             |

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

```
```

{% endtab %}
{% endtabs %}

## List a specific player's leaderboard ranking

<mark style="color:blue;">`GET`</mark> `/v1/games/:game_id/leaderboards/:id/players/:player_id/rankings`

#### Path Parameters

| Name | Type   | Description |
| ---- | ------ | ----------- |
|      | string |             |

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

```
```

{% endtab %}
{% endtabs %}


# Players

## Create a player

<mark style="color:green;">`POST`</mark> `/v1/games/:game_id/players`

#### Path Parameters

| Name | Type   | Description |
| ---- | ------ | ----------- |
|      | string |             |

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

```
```

{% endtab %}
{% endtabs %}

## Retrieve a player

<mark style="color:blue;">`GET`</mark> `/v1/games/:game_id/players/:id`

#### Path Parameters

| Name | Type   | Description |
| ---- | ------ | ----------- |
|      | string |             |

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

```
```

{% endtab %}
{% endtabs %}

## Update a player

<mark style="color:orange;">`PUT`</mark> `/v1/games/:game_id/players/:id`

#### Path Parameters

| Name | Type   | Description |
| ---- | ------ | ----------- |
|      | string |             |

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

```
```

{% endtab %}
{% endtabs %}

## Delete a player

<mark style="color:red;">`DELETE`</mark> `/v1/games/:game_id/players/:id`

#### Path Parameters

| Name | Type   | Description |
| ---- | ------ | ----------- |
|      | string |             |

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

```
```

{% endtab %}
{% endtabs %}

## List all players

<mark style="color:blue;">`GET`</mark> `/v1/games/:game_id/players`

#### Path Parameters

| Name | Type   | Description |
| ---- | ------ | ----------- |
|      | string |             |

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

```
```

{% endtab %}
{% endtabs %}


# Player Badges

## List a specific player's badges

<mark style="color:blue;">`GET`</mark> `/v1/games/:game_id/players/:player_id/badges`

#### Path Parameters

| Name                                         | Type   | Description |
| -------------------------------------------- | ------ | ----------- |
| game\_id<mark style="color:red;">\*</mark>   | string |             |
| player\_id<mark style="color:red;">\*</mark> | string |             |

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

```
```

{% endtab %}
{% endtabs %}


# Rewards

## Create a reward

<mark style="color:green;">`POST`</mark> `/v1/games/:game_id/rewards`

#### Path Parameters

| Name                                       | Type   | Description |
| ------------------------------------------ | ------ | ----------- |
| game\_id<mark style="color:red;">\*</mark> | string |             |

#### Request Body

| Name                                         | Type   | Description |
| -------------------------------------------- | ------ | ----------- |
| custom\_id<mark style="color:red;">\*</mark> | string |             |
| name<mark style="color:red;">\*</mark>       | string |             |
| description                                  | string |             |
| custom\_data                                 | json   |             |

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

```
```

{% endtab %}
{% endtabs %}

## Retrieve a reward

<mark style="color:blue;">`GET`</mark> `/v1/games/:game_id/rewards/:id`

#### Path Parameters

| Name                                       | Type   | Description |
| ------------------------------------------ | ------ | ----------- |
| game\_id<mark style="color:red;">\*</mark> | string |             |
| id                                         | string |             |

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

```
```

{% endtab %}
{% endtabs %}

## Update a reward

<mark style="color:orange;">`PUT`</mark> `/v1/games/:game_id/rewards/:id`

#### Path Parameters

| Name                                       | Type   | Description |
| ------------------------------------------ | ------ | ----------- |
| game\_id<mark style="color:red;">\*</mark> | string |             |
| id<mark style="color:red;">\*</mark>       | string |             |

#### Request Body

| Name         | Type   | Description |
| ------------ | ------ | ----------- |
| custom\_id   | string |             |
| name         | string |             |
| description  | string |             |
| custom\_data | json   |             |

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

```
```

{% endtab %}
{% endtabs %}

## Delete a reward

<mark style="color:red;">`DELETE`</mark> `/v1/games/:game_id/rewards/:id`

#### Path Parameters

| Name                                       | Type   | Description |
| ------------------------------------------ | ------ | ----------- |
| game\_id<mark style="color:red;">\*</mark> | string |             |
| id                                         | string |             |

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

```
```

{% endtab %}
{% endtabs %}

## List all rewards

<mark style="color:blue;">`GET`</mark> `/v1/games/:game_id/rewards`

#### Path Parameters

| Name     | Type   | Description |
| -------- | ------ | ----------- |
| game\_id | string |             |

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

```
```

{% endtab %}
{% endtabs %}


# Scores

## Create a score

<mark style="color:green;">`POST`</mark> `/v1/games/:game_id/scores`

#### Path Parameters

| Name | Type   | Description |
| ---- | ------ | ----------- |
|      | string |             |

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

```
```

{% endtab %}
{% endtabs %}


# Overview

Webhooks provide a way for r4nkt to talk to your application. They are critical in that they are the only means of communicating real-time information to your application.

If you do not use webhooks, then you will need to poll the API and keep track of certain information in your application in order to be able to synchronize whatever you find interesting.

Setting up webhooks, however, is relatively easy and it allows you to only worry about the events if and when they occur.

You can find out how to [get started](/webhooks/getting-started). Then, you can learn more about the [events](/webhooks/events) that occur that result in a webhook being sent to your system. Finally, if you use [Laravel](https://laravel.com/), you might be interested in using our [Laravel package](/laravel-package/overview).


# Getting Started

## How they work

There are certain events that will occur that you may find interesting. Whenever one of these takes place, we will pass that information along to you. Probably the most interesting event is whenever a player has been awarded a badge. When this happens, you will be notified via webhook of the event along with relevant information, eg. the player and the achievement that was earned and any related rewards.

At this point, you can do whatever you want or need to do with the information. Typically, you will then notify the player that they have been awarded a badge. You may also want to handle any associated rewards.

The webhook itself works by firing a `POST` request to the game's webhook URL property. The request's payload will have all of the event's relevant data. For details about the payloads, please look at the documentation for each event.

## Configuration

Your game's webhook settings can be configured and tested in the game dashboard's webhook settings panel. It consists of two settings:

* Webhook URL: This is the URL that will be called to pass information along to you for different events. A new game has no webhook URL. You must set this manually.
* Webhook secret: This secret is used to validate any webhook calls you receive. A random secret is generated for all new games, but you can always change it to something more preferable.

{% hint style="warning" %}
A game requires neither a webhook URL nor a webhook secret, but **no webhook calls will be made unless they are both provided**.
{% endhint %}

Once your game has a valid webhook URL and webhook secret, then the webhook will be called for each event we fire.

{% hint style="info" %}
Be sure to take advantage of the "test webhook" functionality that you can find in the game dashboard's webhook settings panel.
{% endhint %}

## Authentication

The webhooks that we send will be signed by the webhook secret, which you should have provided during game creation or modification.

{% hint style="info" %}
While you don't have to validate incoming webhook requests, we highly recommend that you do so.
{% endhint %}

## Retries

If we send a webhook and receive a `2xx` status code, then we will consider the webhook successful. If, however, any other status code is returned or if no response is made within 3 seconds, then we will consider the webhook failed.

Failed webhooks will be retried a maximum of 3 times. Prior to each retry, we will wait a small-but-increasing period of time: 10 seconds before the first retry, 100 seconds before the second, and 1000 seconds before the third and final.

If all retries have failed, then that particular event will not be sent again.

## Authentication and Signing

Each time we make a webhook call, we pass a header called `X-R4nkt-Signature`, which will contain a signature that your webhook handler can use to validate the incoming request. The signature is generated using the [HMAC-256](https://en.wikipedia.org/wiki/HMAC) method, like so:

```php
$signature = hash_hmac('sha256', $payload, $secret);
```

`$payload` is the JSON-formatted body of the `POST` request for the specific event.

`$secret` is your game's webhook secret setting.

`hash_hmac()` function is a [PHP function](https://www.php.net/manual/en/function.hash-hmac.php) that is used to "\[g]enerate a keyed hash value using the HMAC method".

The `$signature` value that is generated must match the value passed in the `X-R4nkt-Signature` header. If it does not, then the webhook is *not* valid.

The sample code above that is used to determine the signature is in PHP, but this can be done in many languages. Here are [some examples](https://www.jokecamp.com/blog/examples-of-creating-base64-hashes-using-hmac-sha256-in-different-languages/).

{% hint style="info" %}
Please note that the signature is **not** encoded, Base64 or otherwise.
{% endhint %}


# Events

## Introduction

Each time a given event occurs, r4nkt will notify you via a webhook. This page will list and describe the various events that can be fired.

{% hint style="warning" %}
No webhook will be called if the game's webhook URL and webhook secret properties haven't been properly set up.
{% endhint %}

## Common Payload

Each webhook will contain some common data in its payload:

* `type`: This value is used to indicate the webhook *type*.
* `date_time_utc`: This indicates the date/time for the event represented by the webhook. It will be an ISO 8601 UTC date/time representation, eg `2019-02-01T03:45:27.612584Z`.

Here is what the common elements of a sample payload might look like:

```javascript
{
    "type":"badge-earned",
    "date_time_utc":"2019-02-01T03:45:27.612584Z",
    ...
}
```

## Badge Earned

When a player earns a new badge, r4nkt will send a "badge earned" webhook. In addition to the common payload data, this webhook also includes the following:

* `custom_player_id`: The custom ID for the player that earned the badge.
* `custom_achievement_id`: The custom ID for the related achievement.
* `points`: The number of points that were allocated to the player for having earned the badge.

Here is a sample payload:

```javascript
{
    "type":"badge-earned",
    "date_time_utc":"2019-02-01T03:45:27.612584Z",
    "custom_player_id":"",
    "custom_achievement_id":"",
    "points":100
}
```

## Webhook Test

This webhook is sent from the game dashboard's webhhook settings panel and is manually initiated by any user with access. It is used to help get webhook integration up and running. In addition to the common payload data, this webhook also includes the following:

* `inspiring_quote`: This serves two purposes. First, it provides additional data so that developers have a little better idea about what to expect. Second, it can serve to inspire. 😊

Here is a sample payload:

```javascript
{
    "type":"webhook-test",
    "date_time_utc":"2019-02-01T03:45:27.612584Z",
    "inspiring_quote":"He who is contented is rich. - Laozi"
}
```

## Testing

In order to test and debug, you might like to use a service like [RequestBin.com](https://requestbin.com/) or [webhook.site](https://webhook.site/), which can show you the payload of the webhook data in real-time.


# Overview

## Introduction

If you use PHP, then you can use [our PHP package](https://github.com/r4nkt/r4nkt-php-sdk) to help get up and running fairly quickly with a lot of r4nkt-related functionality. Here are some of the things it will currently do for you:

* It will help you easily manage r4nkt resources, e.g., creating achievements, listing actions, getting leaderboards.
* It allows you easily report player activity.


# Getting Started

Installation is quite easy.   You can simply grab the latest stable version via composer:

```bash
composer require r4nkt/r4nkt-php-sdk
```

The next step is to create an instance of the SDK's `R4nkt` object. Its constructor takes the following parameters:

* `string $apiToken` (required) Your API token. If you don't have an API key yet, read up on the API authentication first first.
* `string $gameId` (required) Your game ID.
* &#x20;`GuzzleHttp\Client $client` (optional) You can pass in your own client to use or allow the SDK to create and use its own.

Here is an example of how one can instantiate the `R4nkt` object:

```php
$apiToken = 'lR8OsPu9q3VWm70zAA2irbUCWL';
$gameId = 'ABCD1234';

$r4nkt = new R4nkt\PhpSdk\R4nkt($apiToken, $gameId);
```

Once initiated, you can then begin to manage game resources.


# Overview

## Introduction

If you use Laravel, then you can use [our Laravel package](https://github.com/r4nkt/laravel-r4nkt-sdk) to help get you up and running quickly. Here are some of the things it will do for you:

* It will help you easily manage r4nkt resources, e.g., creating achievements, listing actions, getting leaderboards.
* It allows you easily report player activity.

Coming soon:

* It allows you to easily report player activity.
* It helps get webhook handling functionality in place.
* It allows you to easily define jobs or events that should be dispatched when specific webhook events hit your app.

{% hint style="info" %}
This package will *not* handle what should be done *after* the webhook request has been validated and the right job or event is called.
{% endhint %}


# Installation

First, grab the latest stable version via composer:

```bash
$ composer require r4nkt/laravel-r4nkt-sdk
```

The service provider will automatically register itself.

To publish the configuration file, you must use the following command:

```bash
php artisan vendor:publish --provider="R4nkt\\LaravelR4nkt\\LaravelR4nktServiceProvider" --tag="laravel-r4nkt-sdk-config"
```

Here are the contents of the published configuration file, `config/r4nkt.php`:

```php
return [

    /*
    |--------------------------------------------------------------------------
    | Base URL
    |--------------------------------------------------------------------------
    |
    | This determines the base URL for the API that the SDK will use. Generally
    | speaking, you shouldn't ever need to set or change.
    |
    */

    'base_url' => env('R4NKT_BASE_URL', 'https://api.r4nkt.com/v1'),

    /*
    |--------------------------------------------------------------------------
    | API Token
    |--------------------------------------------------------------------------
    |
    | R4nkt requires that you use an API token when communicating with its API.
    | Make one at the r4nkt API settings page: https://r4nkt.com/settings#/api
    |
    */

    'api_token' => env('R4NKT_API_TOKEN'),

    /*
    |--------------------------------------------------------------------------
    | Game ID
    |--------------------------------------------------------------------------
    |
    | R4nkt also requires that you specify the game ID for each API call. Find
    | this at the game configuration settings: https://r4nkt.com/settings/games
    |
    */

    'game_id' => env('R4NKT_GAME_ID'),

    /*
    |--------------------------------------------------------------------------
    | Webhook Signing Secret
    |--------------------------------------------------------------------------
    |
    | R4nkt will sign webhooks using a secret. You can find the secret used for
    | individual games at the game configuration settings:
    |  - https://r4nkt.com/settings/games
    |
    */

    'signing_secret' => env('R4NKT_SIGNING_SECRET'),

    /*
    |--------------------------------------------------------------------------
    | Custom Player ID Resolver
    |--------------------------------------------------------------------------
    |
    | This class is responsible for determining the player's custom ID.
    |
    | This class should implement
    | `R4nkt\Laravel\Support\CustomPlayerIdResolver\CustomPlayerIdResolver`
    |
    */

    'custom_player_id_resolver' => \R4nkt\Laravel\Support\CustomPlayerIdResolver\PrimaryKeyCustomPlayerIdResolver::class,

    /*
    |--------------------------------------------------------------------------
    | Custom Player ID Decoder
    |--------------------------------------------------------------------------
    |
    | This class is responsible for decoding the player's custom ID.
    |
    | This class should implement
    | `R4nkt\Laravel\Support\CustomPlayerIdDecoder\CustomPlayerIdDecoder`
    |
    */

    'custom_player_id_decoder' => \R4nkt\Laravel\Support\CustomPlayerIdDecoder\PrimaryKeyCustomPlayerIdDecoder::class,

    /*
    |--------------------------------------------------------------------------
    | Date/Time UTC Resolver
    |--------------------------------------------------------------------------
    |
    | This class is responsible for resolving the date/time UTC value to a
    | properly formatted string.
    |
    | This class should implement
    | `R4nkt\Laravel\Support\DateTimeUtcResolver\DateTimeUtcResolver`
    |
    */

    'date_time_utc_resolver' => \R4nkt\Laravel\Support\DateTimeUtcResolver\DefaultDateTimeUtcResolver::class,

    /*
    |--------------------------------------------------------------------------
    | Webhook Jobs
    |--------------------------------------------------------------------------
    |
    | Here you can define the job that should be run when a certain webhook
    | hits your application.
    |
    | You can find a list of R4nkt webhook types here:
    |  - https://r4nkt.com/docs/webhooks/events
    |
    */

    'jobs' => [
        // 'badge-earned' => \App\Jobs\R4nktWebhooks\HandleBadgeEarned::class,
        // ...
    ],

];
```

You should set the `signing_secret` value for the specific game you are interested in receiving webhooks from.

Finally, you should set up routing. The route that is set up here should match the webhook URL for the specific game you are interested in receiving webhooks from. To do so, you must pass this route using the following command in your app's routes file:

```php
Route::R4nktWebhooks('configured-webhook-route');
```

This command registers a `POST` route to a package controller.

Because r4nkt has no way of getting a CSRF token, you must add that route to the `$except` array of the `VerifyCsrfToken` middleware like so:

```php
protected $except = [
    'configured-webhook-route',
];
```

{% hint style="info" %}
Both the webhook secret and URL values can be found on the games management page.
{% endhint %}

##


# Webhooks

{% hint style="warning" %}
This page has not yet been updated for the new Laravel package.
{% endhint %}

Currently, r4nkt sends out webhooks for only one event type, but more [event types](/webhooks/events) may come in the future.

R4nkt signs all requests that hit your game's specified webhook url. This package will automatically verify each webhook request's signature. If any signature is not valid, the request was likely not sent by r4nkt and will be rejected and a `R4nkt\R4nktWebhooks\WebhookFailed` exception will be thrown.

Unless something is wrong, this package will respond with a status code of `200` to all webhook requests. This will prevent r4nkt from resending the same event.

When using this package, you have two ways to handle incoming webhook requests:

* you can opt to [queue a job](/laravel-package/webhooks#using-jobs-to-handle-webhook-requests)
* you can [set up event listeners](/laravel-package/webhooks#using-event-listeners-to-handle-webhook-requests)

## Using Jobs to Handle Webhook Requests

If you want to do something when a specific event type comes in you can define a job that does the work. Here's an example of such a job:

```php
namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use R4nkt\LaravelWebhooks\R4nktWebhookCall;

class HandleBadgeEarnedCheck implements ShouldQueue
{
    use InteractsWithQueue, Queueable, SerializesModels;

    /** @var  \R4nkt\LaravelWebhooks\R4nktWebhookCall */
    public $webhookCall;

    public function __construct(R4nktWebhookCall $webhookCall)
    {
        $this->webhookCall = $webhookCall;
    }

    public function handle()
    {
        // do your work here

        // you can access the payload of the webhook call with $this->webhookCall->payload
    }
}
```

{% hint style="info" %}
You are advised to make this job queueable. This will minimize the webhook request response time, allow you to handle more r4nkt webhook requests, and help avoid timeouts.
{% endhint %}

Once your job is created, it must be registered in the jobs array in the `r4nkt.php` config file. The key should be the name of the r4nkt event type and the value should be the job's fully qualified class name.

```php
// config/r4nkt.php

'jobs' => [
    'badgeEarned' => \App\Jobs\R4nktWebhooks\HandleBadgeEarnedCheck::class,
],
```

## Using Event Listeners to Handle Webhook Requests

Upon receiving a valid webhook request, this package will fire a `r4nkt-webhooks::*` event. So, you can define event listeners to listen for any events this package might fire.

The event payload will be the instance of `R4nktWebhookCall` that was created for the incoming request.

Here is an example of how you can listen for an event by registering a listener in the `EventServiceProvider`:

```php
/**
 * The event listener mappings for the application.
 *
 * @var    array
 */
protected $listen = [
    'r4nkt-webhooks::badgeEarned' => [
        App\Listeners\MailOperators::class,
    ],
];
```

Here's an example of such a listener:

```php
namespace App\Listeners;

use Illuminate\Contracts\Queue\ShouldQueue;
use R4nkt\LaravelWebhooks\R4nktWebhookCall;

class BadgeEarned implements ShouldQueue
{
    public function handle(R4nktWebhookCall $webhookCall)
    {
        // do your work here

        // you can access the payload of the webhook call with `$webhookCall->payload`
    }
}
```

{% hint style="info" %}
You are advised to make this event listener queueable. This will minimize the webhook request response time, allow you to handle more r4nkt webhook requests, and help avoid timeouts.
{% endhint %}

The above example is only one way to handle events in Laravel. To learn the other options, read the Laravel documentation on handling [events](https://laravel.com/docs/events).

## Using the Webhook Call Object

As already noted, your events or jobs will receive an instance of `R4nkt\LaravelWebhooks\R4nktWebhookCall`.

You can access the raw payload by calling:

```php
$r4nktWebhookCall->payload; // returns an array
```

Or you can opt to get more specific information:

```php
$r4nktWebhookCall->type(); // returns the webhook type, e.g. `badgeEarned`
$r4nktWebhookCall->dateTime(); // returns the date/time (string, Ymdhis) when r4nkt generated this webhook call
```


