Strutta API

Background

The Strutta API allows you to tap into the core of Strutta’s promotions platform and take advantage of advanced complexity and customization.

In our years of experience creating thousands of turnkey and custom promotions, we’ve seen the Social Promotions market mature. Our customers have begun to want more than just Sweepstakes or Contests; they now want to be able to pick and choose which aspects of each type they want to utilize, and to be able to add new elements.

So, when we began constructing this API, we decided it was important to do away with the traditional “Contest” and “Sweepstakes” definitions we’d lived by in the past. As engineers and consumers of the Promotions API we felt that generalizing these definitions would encourage us to create a more flexible API. We also understood that changing the definition of what our technology is capable of opens up a huge swath of use cases we had not yet considered.

By giving API clients the ability to add core elements like Games, Entries, Moderation, Random Draws, and Points Rounds to any aspect of their software we’re making it possible to apply the power of social promotions to any section of the marketing funnel.

Technical

Strutta API is designed to be as RESTful as possible. We use HTTP verbs and standard HTTP response codes, and object hierarchy is (with a few exceptions) described exactly by the URI.

This API is designed so that it can easily and securely be implemented on both the client and the server. JSON is returned in all API responses, including errors, which have a standardized structure. We do our best to provide specific, in-depth error messages to save you headaches.

Throughout the many parameter lists in this documentation, only parameters marked as optional are not required.

Version

This documentation is for API version 2.0

Authentication

The Strutta API has two types of consumers - Users and Participants - each with their own API token(s) and permission sets.

Users

Users are those who have created an account on our developer portal. On account creation, each User is issued a Private and a Public token.

Private tokens give permission to perform every action this API provides. They also allow a User to act on behalf of Participants. Never use your private token in client-side code. Any client-side action should use either a Participant token or the User’s public token.

Public tokens are read-only tokens for accessing the elements of Games that do not require any sort of authentication. They are designed for client-side exposure.

User tokens do not expire automatically. A User may add, remove, and regenerate both Private and Public tokens on our developer portal.

Participants

Participants are those that play the Games created by Users. It is important to note that a Participant is created within the scope of a single Game, and is only permitted to interact with that Game.

When a Participant is created, they are automatically issued a token with api_basic and registered permissions.

api_basic provides the Participant with general READ permissions.

registered scopes ownership of the Participant object to the Participant themselves, allowing the creator to update their metadata and to create/update their own Entries and Points.

Extended permissions (administrate, moderate, judge) can be granted to a Participant by a User or a Participant with the administrate permission. See Participant Permissions to learn more.

By default, Participant tokens expire after 24 hours. See Renew Participant Token to learn more.

Using your token

Example Requests

curl http://api.strutta.com/v2/games \
     -H "Authorization: Token token=mystruttatoken"

GET http://api.strutta.dev:4000/v2/games/?token=mystruttatoken

The API expects a token to be included either as a URI parameter or in a request header.

URI Parameter:

http://api.strutta.com/v2/path/?token=mystruttatoken

Header:

Authorization: Token token=mystruttatoken

Paging

Objects that Offer Paging

We offer the option to page through your records of Games, Entries, Participants, and Tags.

Parameters & Usage

Ruby Paging Example

# Configure API
strutta = Strutta::API.new 'mystruttatoken'
my_game = strutta.games(333)

#page by 10 at a time
limit = 10

# First request - only pass 'limit'
entries = my_game.entries.all(limit: limit)

# Get next 3 pages
page = 1
3.times do
  paging_params = {
    limit: limit,
    offset: limit * page
  }
  new_entries = my_game.entries.all(paging_params)
  page += 1
  # Process entries...
end

example response

{
"results": [
  {
    "id": 1,
    "participant_id": 10,
    "game_id": 100,
    "metadata": {
      "country": "canada",
      "state": "",
      "province": "British Columbia"
    }
  },
  {
    "id": 3,
    "participant_id": 12,
    "game_id": 100,
    "metadata": {
      "country": "canada",
      "state": "",
      "province": "Manitoba"
    }
 ],
 "count": 5
}
{
"results": [
  {
    "id": 1,
    "participant_id": 10,
    "game_id": 100,
    "metadata": {
      "country": "canada",
      "state": "",
      "province": "British Columbia"
    }
  },
  {
    "id": 3,
    "participant_id": 12,
    "game_id": 100,
    "metadata": {
      "country": "canada",
      "state": "",
      "province": "Manitoba"
    }
 ],
 "count": 5
}

The foundations of our paging system are limit and offset parameters, with an optional supplementary sort parameter.

Paging Request Parameters

All List requests are controlled by three parameters. They can be used together or individually.

Parameter Description Default
limit The maximum number of objects to return Dependent on Object requested
offset Number of objects to skip past nil
sort Sorting by created_at asc or desc

Paging Response Parameters

The most recently created objects of any given type have the highest id attributes. By default, list responses are made up of a results array sorted by id in a descending (high-to-low).

Name Description
results Array of objects requested
count Total number of pageable objects

Games

Games are the top-level element of the Strutta API. They are simple container objects that essentially namespace Rounds, Flow, Entries, and Points.

Attributes

Name Type Description
title string The Game’s title
metadata JSON Arbitrary key-value data
sub_account string Arbitrary string for grouping Games
entries_count integer Total Entries in Game
participants_count integer Total Participants in Game
created UNIX timestamp When the Game was created
last_updated UNIX timestamp When the Game was last updated

Create a Game

Example Request

strutta = Strutta::API.new 'mystruttatoken'

my_game = {
  title: "My First Game",
  sub_account: "test-1234",
  metadata: {
    summary: "Here's a little more about my game...",
    organizer: "NaaS.io.ly - Ninjas as a service"
  }
}
strutta.games.create(my_game)
{
  "title": "My First Game",
  "sub_account": "test-1234",
  "metadata": {
    "summary": "Here's a little more about my game...",
    "organizer": "NaaS.io.ly - Ninjas as a service"
  }
}

Example Response - 201

{
  "id": 111,
  "title": "My First Game",
  "sub_account": "test-1234",
  "metadata": {
    "summary": "Here's a little more about my game...",
    "organizer": "NaaS.io.ly - Ninjas as a service"
  },
  "entries_count": 342,
  "participants_count": 234,
  "created": 1413889551,
  "last_updated": 1413889551
}
{
  "id": 111,
  "title": "My First Game",
  "sub_account": "test-1234",
  "metadata": {
    "summary": "Here's a little more about my game...",
    "organizer": "NaaS.io.ly - Ninjas as a service"
  },
  "entries_count": 342,
  "participants_count": 234,
  "created": 1413889551,
  "last_updated": 1413889551
}

A Game can be an unnamed container object or a well-defined object with a large amount of associated metadata; it all depends on your use case.

HTTP Request

POST /v2/games

Parameters

Name Type Description
title string The Game’s title (optional)
metadata JSON Arbitrary key-value data (optional)
sub_account string Arbitrary string for grouping Games (optional)

Minimum Permission

Consumer Permission
User private_token
Participant N/A

Get All Games

Example Request

strutta = Strutta::API.new 'mystruttatoken'
strutta.games.all(sub_account: 'test-1234')
  {
    "sub_account": "test-1234"
  }

Example Response - 200

{
  "results": [
    {
      "id": 111,
      "title": "My First Game",
      "sub_account": "test-1234",
      "metadata": {
        "summary": "Here's a little more about my game...",
        "organizer": "NaaS.io.ly - Ninjas as a service"
      },
      "entries_count": 342,
      "participants_count": 234,
      "created": 1413889551,
      "last_updated": 1413889551
    },
    {
      "id": 222,
      "title": "My Second Game",
      "sub_account": "test-1234",
      "metadata": {
        "summary": "This is another Game",
        "organizer": "NaaS.io.ly - Ninjas as a service"
      },
      "entries_count": 223,
      "participants_count": 101,
      "created": 141398753,
      "last_updated": 141399432
    }
  ],
  "paging": {
    "min_id": 111,
    "max_id": 222,
    "next_max_id": 110,
  }
}
{
  "results": [
    {
      "id": 111,
      "title": "My First Game",
      "sub_account": "test-1234",
      "metadata": {
        "summary": "Here's a little more about my game...",
        "organizer": "NaaS.io.ly - Ninjas as a service"
      },
      "entries_count": 342,
      "participants_count": 234,
      "created": 1413889551,
      "last_updated": 1413889551
    },
    {
      "id": 222,
      "title": "My Second Game",
      "sub_account": "test-1234",
      "metadata": {
        "summary": "This is another Game",
        "organizer": "NaaS.io.ly - Ninjas as a service"
      },
      "entries_count": 223,
      "participants_count": 101,
      "created": 141398753,
      "last_updated": 141399432
    }
  ],
  "paging": {
    "min_id": 111,
    "max_id": 222,
    "next_max_id": 110
  }
}

Please see Paging for request and response parameters.

HTTP Request

GET /v2/games

Count Limits/Default

The count parameter defaults to 10 and is limited to 20 for this endpoint.

Minimum Permission

Consumer Permission
User private_token
Participant N/A

Get a Specific Game

Example Request

strutta = Strutta::API.new 'mystruttatoken'
strutta.games(111).get

Example Response - 200

{
  "id": 111,
  "title": "My First Game",
  "sub_account": "test-1234",
  "metadata": {
    "summary": "Here's a little more about my game...",
    "organizer": "NaaS.io.ly - Ninjas as a service"
  },
  "entries_count": 342,
  "participants_count": 234,
  "created": 1413889551,
  "last_updated": 1413889551
}
{
  "id": 111,
  "title": "My First Game",
  "sub_account": "test-1234",
  "metadata": {
    "summary": "Here's a little more about my game...",
    "organizer": "NaaS.io.ly - Ninjas as a service"
  },
  "entries_count": 342,
  "participants_count": 234,
  "created": 1413889551,
  "last_updated": 1413889551
}

HTTP Request

GET /v2/games/:id

URI Parameters

Parameter Description
:id The ID of the Game to retrieve

Minimum Permission

Consumer Permission
User public_token
Participant api_basic

Update Game

Example Request

strutta = Strutta::API.new 'mystruttatoken'

update = {
  title: 'Updated title',
  metadata: {
    region: 'West Coast',
    timezone: 'America/Vancouver'
  }
}
strutta.games(333).update(update)
{
  "title": "Updated title",
  "metadata": {
    "region": "West Coast",
    "timezone": "America/Vancouver"
  }
}

Example Response - 200

{
  "id": 333,
  "title": "Updated title",
  "sub_account": "test-1234",
  "metadata": {
    "region": "West Coast",
    "timezone": "America/Vancouver"
  },
  "entries_count": 342,
  "participants_count": 234,
  "created": 1413889551,
  "last_updated": 1413897453
}
{
  "id": 333,
  "title": "Updated title",
  "sub_account": "test-1234",
  "metadata": {
    "region": "West Coast",
    "timezone": "America/Vancouver"
  },
  "entries_count": 342,
  "participants_count": 234,
  "created": 1413889551,
  "last_updated": 1413897453
}

HTTP Request

PATCH /v2/games/:id

URI Parameters

Parameter Description
:id The ID of the Game to update

Parameters

Name Type Description
title string The Game’s title (optional)
metadata JSON Arbitrary key-value data (optional)
sub_account string Arbitrary string for grouping Games (optional)

Minimum Permission

Consumer Permission
User private_token
Participant administrate

Delete Game

Example Request

strutta = Strutta::API.new 'mystruttatoken'
strutta.games(333).delete

Example Response - 204

  No Content

HTTP Request

DELETE /v2/games/:id

URI Parameters

Parameter Description
:id The ID of the Game to delete

Minimum Permission

Consumer Permission
User private_token
Participant administrate

Rounds

Background

In order to help us generalize Contests and Sweepstakes into Games, we decided to deconstruct them into their simplest elements, Rounds.

For example, a Contest Game is typically made up of Rounds that Flow like this:

Submission -> Voting -> Judging -> Prize Fullfillment (webhook)

A Sweepstakes Game is slightly more simple:

Submission -> Random Draw -> Prize Fullfillment (webhook)

When viewed this way, you see just how similar Contests and Sweepstakes are, and how easy it would be to create a hybrid of the two. What if a User wanted to run a photo contest where instead of a Judging the ultimate winner was chosen by Random Draw? Simple:

Submission -> Voting -> Random Draw -> Prize Fullfillment (webhook)

What if a different User wanted to moderate their Sweepstakes entries before entering them in the Random Draw? Again, simple:

Submission -> Moderation -> Random Draw -> Prize Fullfillment (webhook)

As you can see, these use cases become easy to model when you think of each Game as a Flow of Rounds.

Flow is described in-depth in the next section. First, we must define our Rounds.

Action and Timed Rounds

Programatically, there are two groups of Rounds: Action and Timed.

Action Rounds

Action Rounds advance Entries to subsequent rounds when an action takes place.

Moderation is a good example: when an administrator approves or denies an Entry it is moved to the Round’s pass_round or fail_round immediately.

There are two Rounds of this type: submission and on_demand.

Timed Rounds

There are four Rounds of this type: random_draw, points, judging, and webhook. Timed rounds, by default, will automatically advance their entries at their end_date.

Judging is a good example: Once the Round has ended, based on submitted judgements during the round a number of entries will advance to the Round’s pass_round. Those that “lose” are advanced to the Round’s fail_round.

Manually Advancing a Round

Timed rounds are affected by the manually_advance boolean parameter. If manually_advance is set to false or nil (default), the Round’s Entries will all advance at the Round’s end_date according to the Round’s Rules.

However, if manually_advance is set to true, the Round’s Entries will all advance (as per its Rules) only when triggered by the advance endpoint.

HTTP Request

POST /v2/games/:id/rounds/:id/advance

Global Attributes

Each Round type has the following shared global attributes.

Global Attributes

Name Type Description
type string String identifier of the Round type
title string The Round’s title
start_date UNIX timestamp The Round’s start date
end_date UNIX timestamp The Round’s end date
manually_advance boolean Whether a timed round automatically advanced at its end_date or requires a manual trigger

Round Types and their Rules

Submission

String identifier: submission

If a Game had a front door, it would be a Submission Round. Rounds of this type define the rules for how often and how frequently a Participant can play a Game.

Submission Rules

Name Type Description Options
interval string Time period during which num_entries and num_referrals are allowed minute hour day week month game
num_entries int Total number of Entries a Participant is allowed during interval
num_referrals int Total number of extra Entries a Participant is allowed during interval (optional)

Moderation

String identifier: moderation

Moderation Rounds are used to quickly eliminate any inappropriate or off-topic content. They can be used between two Rounds of any type.

The manually_advance parameter is particularly important for Moderation Rounds.

manually_advance Effect at Moderation Round’s end_date
false or nil (default) Any Entries currently in the Moderation Round will advance to its fail_round
true Any Entries currently in the Moderation Round will remain in the Moderation Round

Moderation is performed by Participants with the moderate permission. Visit Moderation to learn more.

Moderation Rules

Name Type Description

This Round Type has no rules

Points

String identifier: points

There are many manifestations of Points across the internet. Examples include: “Votes”, “Likes”, “Re-Tweets”, “Subscribes”, and many more.

At the end of the day, each of the above is just a way of keeping score. To further our generalized Game analogy, we opted to use Points as our descriptor.

Points Rounds define the number of Points (postive or negative) a Participant can assign per Entry during a pre-defined interval. When the interval is completed, Entries are sorted by Points, and a pre-defined number “win”.

Points Rules

Name Type Description Options
interval int Time period during which min_allowed <= x <= max_allowed Points are allowed minute hour day week month game
winners int Total number of winners chosen
max_allowed int Maximum number of Points a Participant is allowed during interval. Must be greater than 0.
min_allowed int Minimum number of Points a Participant is allowed during interval Can be negative. Must be less than max_allowed. Default: 0.

Judging

String identifier: judging

Judging Rounds allow Participants with the judge permission to rank a pre-defined number of Entries based on whatever criteria the User/Administrator decides. These ranks are translated into a Judging score in the background. When the Judging Round reaches its end date, the Entries are sorted by these scores, and a pre-defined number “win”.

Because of the complexity of validation and implementation of ranking, Judging rounds can only have a maximum ranking_size of 20. This results in winners also being limited to 20. If you require a larger pool of ranked Entries and winners, consider using a Points Round.

Visit Judging to learn more.

Judging Rules

Name Type Description
winners int Total number of winners chosen by judges (1 - 20)
ranking_size int The number of Entries to be ranked by each Judge (1 - 20)

Random Draw

String identifier: random_draw

Random Draw Rounds are the bread and butter of Sweepstakes Games, but can really be used Games of any kind. Rounds of this type can define either an absolute number of winners or a percentage of total Entries that will “win” the Round.

Random Draw Rules

Name Type Description
winners int Total number of random winners chosen
percentage boolean Whether to interpret winners as a percentage. Default: false

On Demand

String identifier: on_demand

The On-Demand Winners endpoint behaves as a mini-game within your Game. A pre-defined number of entries are randomly drawn from all entries that have an active (non-nil) state. These winners are then passed through the provided On-Demand Round and returned.

Visit On Demand Winners for more information.

On Demand Rules

Name Type Description

This Round Type has no rules

Instant Win

String identifier instant_win

Instant Win Rounds will immediately advance an Entry to its pass_round or fail_round based on odds provided in its rules.

Instant Win Rules

Name Type Description
max_winners int Max number of winners that can go to pass_round
max_entries int Max number of times a participant can enter. If entry number > max_entries number, entry is pushed to fail_round
odds int Chance of winning, 1 in (odds).

Webhook

String identifier: webhook

“Webhook” rounds have undergone a number of transformations as we have come to understand our users' needs. At this point in time they essentially act as “holding” rounds.

By default, at a “Webhook” Round’s end_date, all entries will advance to the Round’s pass_round. However, if you turn on the manually_advance parameter to true, they will remain in the round even after the end_date.

Create a Round

Example Request

strutta = Strutta::API.new 'mystruttatoken'

submission_round = {
  type: "submission",
  title: "Submission Round",
  start_date: 1413905219,
  end_date: 1414799999,
  rules: {
    num_entries: 10,
    num_referrals: 1,
    interval: "day"
  }
}
strutta.games(333).rounds.create(submission_round)
{
  "type": "submission",
  "title": "Submission Round",
  "start_date": 1413905219,
  "end_date": 1414799999,
  "rules": {
    "num_entries": 10,
    "num_referrals": 1,
    "interval": "day"
  }
}

Example Response - 201

{
  "id": 4343,
  "title": "Submission Round",
  "start_date": 1413905219,
  "end_date": 1414799999,
  "type": "submission",
  "rules": {
    "num_entries": 10,
    "num_referrals": 1,
    "interval": "day"
  }
}
{
  "id": 4343,
  "title": "Submission Round",
  "start_date": 1413905219,
  "end_date": 1414799999,
  "type": "submission",
  "rules": {
    "num_entries": 10,
    "num_referrals": 1,
    "interval": "day"
  }
}

There are many types of Rounds, each with a different set of rules. With each POST, pass in both the Round type and the rules associated with that type.

HTTP Request

POST /v2/games/:id/rounds

URI Parameters

Parameter Description
:id The ID of the parent Game

Parameters

Parameter Type Description
type string The string identifier of the type of Round to create
title string The Round’s title
start_date UNIX timestamp The Round’s start date
end_date UNIX timestamp The Round’s end date
rules Type-specific rules. See Round Types and their Rules.
manually_advance boolean Whether a timed round automatically advanced at its end_date or requires a manual trigger

Minimum Permission

Consumer Permission
User private_token
Participant administrate

Get All Rounds

Example Request

strutta = Strutta::API.new 'mystruttatoken'
strutta.games(333).rounds.all

Example Response

[
  {
    "id": 4343,
    "title": "Submission Round",
    "start_date": 1413905219,
    "end_date": 1414799999,
    "type": "submission",
    "rules": {
      "num_entries": 10,
      "interval": "day"
    }
  },
  {
    "id": 4344,
    "title": "Random Draw Round",
    "start_date": 1413908765,
    "end_date": 1414876466,
    "type": "random_draw",
    "rules": {
      "winners": 100,
      "percentage": false
    }
  }
]
[
  {
    "id": 4343,
    "title": "Submission Round",
    "start_date": 1413905219,
    "end_date": 1414799999,
    "type": "submission",
    "rules": {
      "num_entries": 10,
      "interval": "day"
    }
  },
  {
    "id": 4344,
    "title": "Random Draw Round",
    "start_date": 1413908765,
    "end_date": 1414876466,
    "type": "random_draw",
    "rules": {
      "winners": 100,
      "percentage": false
    }
  }
]

HTTP Request

GET /v2/games/:id/rounds

URI Parameters

Parameter Description
:id The ID of the parent Game

Minimum Permission

Consumer Permission
User public_token
Participant api_basic

Get a Specific Round

Example Request

strutta = Strutta::API.new 'mystruttatoken'
strutta.games(333).rounds(4344).get

Example Response

{
  "id": 4344,
  "title": "Random Draw Round",
  "start_date": 1413908765,
  "end_date": 1414876466,
  "type": "random_draw",
  "rules": {
    "winners": 100,
    "percentage": false
  }
}
{
  "id": 4344,
  "title": "Random Draw Round",
  "start_date": 1413908765,
  "end_date": 1414876466,
  "type": "random_draw",
  "rules": {
    "winners": 100,
    "percentage": false
  }
}

HTTP Request

GET /v2/games/:id/rounds/:round_id

URI Parameters

Parameter Description
:id The ID of the Parent Game
:round_id The ID of the Round to retrieve

Minimum Permission

Consumer Permission
User public_token
Participant api_basic

Update Round

Example Request

strutta = Strutta::API.new 'mystruttatoken'

update = {
  title: 'Updated Round title',
  end_date: 1414876466,
  rules: {
    num_entries: 51
  }
}
strutta.games(333).rounds(4343).update(update)
{
  "title": "Updated Round title",
  "end_date": 1414876466,
  "rules": {
    "num_entries": 51
  }
}

Example Response

{
  "id": 4343,
  "title": "Updated Round title",
  "start_date": 1413905219,
  "end_date": 1414876466,
  "type": "submission",
  "rules": {
    "num_entries": 51,
    "interval": "day"
  }
}
{
  "id": 4343,
  "title": "Updated Round title",
  "start_date": 1413905219,
  "end_date": 1414876466,
  "type": "submission",
  "rules": {
    "num_entries": 51,
    "interval": "day"
  }
}

Once created, a Round may not change its type. Attempting to add or alter attributes not associated with the Round’s current type will result in an error.

HTTP Request

PATCH /v2/games/:id/rounds/:round_id

URI Parameters

Parameter Description
:id The ID of the parent Game
:round_id The ID of the Round to update

Parameters

See Create a Round for parameters.

Minimum Permission

Consumer Permission
User private_token
Participant administrate

Delete Round

Example Request

strutta = Strutta::API.new 'mystruttatoken'
strutta.games(333).rounds(4343).delete

Example Response - 204

  No Content

HTTP Request

DELETE /v2/games/:id/rounds/:round_id

URI Parameters

Parameter Description
:id The ID of the Parent Game
:round_id The ID of the Round to delete

Minimum Permission

Consumer Permission
User private_token
Participant administrate

Flow

Once you’ve defined your Rounds, it’s time to define how an Entry moves through them in the context of your Game. This definition is the called the Flow.

How it works

When a Entry’s time in a Round ends (triggered either by an action or a timestamp), the rules defined for that Round decide whether the Entry will pass or fail. The Flow is used to define what Round the Entry will be moved into at this point.

Each element of the Flow definition contains a reference to an id as well as a pass_round and a fail_round ID. An Entry that passes the Round referenced by id will advance into the pass_round, an Entry that fails will advance into the fail_round. If no pass_round or fail_round ID is defined, the Entry will no be longer active in the Game.

It is important to note that at some point, each Entry’s time in a Game must end. Either they don’t pass a Round with no defined fail_round, or they advance until they are in a Round with no defined pass_round or fail_round, known as a Terminal Round.

The Round that an Entry is currently a part of is referred to as the Entry’s state. Visit Entries to learn more.

Definition

Definition 1 - Simple Flow

[
  {  
      "id": 333,
      "pass_round": 555,
      "start": true
  },  
  {  
      "id": 555,
      "pass_round": 777
  },
  {  
      "id": 777,
      "pass_round": 888
  },
  {  
      "id": 888 (Terminal Round)
  }
]

Definition 2 - Split Flow

[
  {  
      "id": 1111,
      "pass_round": 2222,
      "start": true
  },  
  {  
      "id": 2222,
      "pass_round": 3333,
      "fail_round": 5555  
  },
  {  
      "id": 3333,
      "pass_round": 4444
  },
  {  
      "id": 4444 (Terminal Round)
  },
  {  
      "id": 5555,
      "pass_round": 6666
  },
  {  
      "id": 6666 (Terminal Round)
  }
}  

Definition 3 - Wildcard Flow

[
  {  
      "id": 111,
      "pass_round": 222,
      "start": true
  },  
  {  
      "id": 222,
      "pass_round": 444,
      "fail_round": 333
  },
  {  
      "id": 333,
      "pass_round": 444
  },
  {  
      "id": 444,
      "pass_round": 555
  },
  {  
      "id": 555 (Terminal Round)
  }
}  

Definition 4 - Category Flow

[
  {  
      "id": 111,
      "pass_round": 112,
      "start": true
  },
  {  
      "id": 222,
      "pass_round": 223,
      "start": true
  },  
  {  
      "id": 112,
      "pass_round": 333
  },
  {  
      "id": 222,
      "pass_round": 333
  },
  {  
      "id": 333,
      "pass_round": 444
  },
  {  
      "id": 444 (Terminal Round)
  }
}  

Example 1: Simple Flow

Recall the first Flow defined in the Round description:

Submission -> Points (Voting) -> Judging -> Webhook (Prize Fullfillment) Round types were adjusted to represent our more generalized Game definition

This is an example of a simple, linear Flow. Any Entries that don’t pass each Round are rendered inactive.

Let’s assume we’ve already created our Rounds and collected their IDs:

Example 2: Split Flow

Let’s take this one step further. What if a User wanted a contest Game with the typical Submission/Voting/Judging model, but wanted the Participants who didn’t make the Judging Round to end on more positive note by entering them into a Random Draw.

All of a sudden we have split Flow: those who pass the Voting Round are up for the grand prize via the Judging Round, those who fail have a chance at the consolation prize via a Random Draw Round. Here’s where the fail_round parameter comes into play.

Again, let’s assume we’ve already created our Rounds and collected their IDs:

Example 3: Wildcard Playoff Flow

A Flow that is split can also rejoin the original path at a later point.

For example, wild-card playoff spots allow a team into the playoffs via an alternate route, usually in the form of a mini-tournament between teams vying for the wildcard spot.

If we built the above model using this API, here’s how the Rounds might be defined:

Example 4: Categories Flow

Many Games require Entries to divided into categories, voted on, then re-grouped for a finalist Judging Round. This can be achieved by creating multiple start Submission rounds at the beginning of the Flow.

Let’s assume we’ve created the following rounds:

Let’s also assume that Submission 1 & 2 and Voting 1 & 2 have the exact same start and end dates.

A note on readability

For technical simplicity’s sake, both the pass_round and fail_round parameters are optional. Sometimes this can make examples a little tough to read. If it helps:

{ n "id": 111 }

Is equivalent to:

{ n "id": 111, "pass_round": null, "fail_round": null }

Flow Element Attributes

Name Type Description Default
id int The ID of the Round
pass_round int The ID of the pass Round null
fail_round int The ID of the fail Round null
start boolean Whether this is the initial Round in the Flow false

Create a Flow

Example Request

strutta = Strutta::API.new 'mystruttatoken'

flow = [
  {  
      id: 777,
      pass_round: 888
  },
  {  
      id: 555,
      pass_round: 777
  },
  {  
      id: 888
  },
  {  
      id: 333,
      pass_round: 555,
      start: true
  }
]
strutta.games(333).flow.create(definition: flow)
{
  "definition":
  [
    {  
        "id": 777,
        "pass_round": 888
    },  
    {  
        "id": 555,
        "pass_round": 777
    },

    {  
        "id": 888
    },
    {  
        "id": 333,
        "pass_round": 555,
        "start": true
    }
  ]
}

Example Response - 201. Note that order of Flow Elements reflects the Flow itself

[
  {
    "id": "333",
    "pass_round": "555",
    "start": "true"
  },
  {
    "id": "555",
    "pass_round": "777"
  },
  {
    "id": "777",
    "pass_round": "888"
  },
  {
    "id": "888"
  }
]
[
  {
    "id": "333",
    "pass_round": "555",
    "start": "true"
  },
  {
    "id": "555",
    "pass_round": "777"
  },
  {
    "id": "777",
    "pass_round": "888"
  },
  {
    "id": "888"
  }
]

Constructing a Flow requires that you have already created your Rounds. There are a few other validation requirements to be aware of:

Start Round

Each Flow must have at least one Round that has been designated as the start Round. This Round must be of type Submission.

Circular Paths

A Flow is broken down into a series of paths, beginning at the start Round and ending at a Terminal Round or some other inactive state. While each Round may be accessed via different routes, no Round may be accessed more than once on any given path.

HTTP Request

POST /v2/games/:id/flow

URI Parameters

Parameter Description
:id The ID of the parent Game

Flow Parameters

Name Type Description
definition JSON A JSON array of Flow Elements

Flow Element Parameters

Name Type Description Default
id int The ID of the Round
pass_round int The ID of the pass Round null
fail_round int The ID of the fail Round null
start boolean Whether this is the initial Round in the Flow false

Minimum Permission

Consumer Permission
User private_token
Participant administrate

Get Flow

Example Request

strutta = Strutta::API.new 'mystruttatoken'
strutta.games(333).flow.get

Example Response - 200

[
  {
    "id":"333",
    "pass_round":"555",
    "start":"true"
  },
  {
    "id":"555",
    "pass_round":"777"
  },
  {
    "id":"777",
    "pass_round":"888"
  },
  {
    "id":"888"
  }
]
[
  {
    "id":"333",
    "pass_round":"555",
    "start":"true"
  },
  {
    "id":"555",
    "pass_round":"777"
  },
  {
    "id":"777",
    "pass_round":"888"
  },
  {
    "id":"888"
  }
]

HTTP Request

GET /v2/games/:id/flow

URI Parameters

Parameter Description
:id The ID of the parent Game

Minimum Permission

Consumer Permission
User public_token
Participant api_basic

Update Flow

Delete Flow

Example Request

strutta = Strutta::API.new 'mystruttatoken'
strutta.games(333).flow.delete

Example Response - 204

  No Content

HTTP Request

DELETE /v2/games/:id/flow

URI Parameters

Parameter Description
:id The ID of the Parent Game

Minimum Permission

Consumer Permission
User private_token
Participant administrate

Participants

Participants are those who interact with a User’s games. They create Entries and Points, and they can also be Administrators, Judges, and Moderators.

See Participant Permissions to learn more.

Attributes

Name Type Description
email string The Participants’s email
metadata JSON Arbitrary key-value data
referral_code string The Participant’s Referral code (see Referrals)
token string The Participant’s API token
token_expired boolean Whether the Participant’s token has expired

Create a Participant

Example Request - POST /games/333/participants

strutta = Strutta::API.new 'mystruttatoken'

participant = {
  email: 'charles@dickens.com',
  metadata: {
    industry: 'Print Media',
    birthdate: '07/02/1812'
  }
}
strutta.games(333).participants.create(participant)
{
  "email": "charles@dickens.com",
  "metadata": {
    "industry": "Print Media",
    "birthdate": "07/02/1812"
  }
}

Example Response - 201

{
  "id": 6767,
  "metadata": {
    "industry": "Print Media",
    "birthdate": "07/02/1812"
  },
  "email": "charles@dickens.com",
  "referral_code": "rmimgndo",
  "token": "18d20376152626a013c4acd35ee8859a",
  "token_expired": false
}
{
  "id": 6767,
  "metadata": {
    "industry": "Print Media",
    "birthdate": "07/02/1812"
  },
  "email": "charles@dickens.com",
  "referral_code": "rmimgndo",
  "token": "18d20376152626a013c4acd35ee8859a",
  "token_expired": false
}

When a Participant is created, they are automatically issued an API token with the api_basic and registered permissions.

The initial token is only valid for 24 hours. Any subsequent actions by the Participant will require renewing the Participant’s token.

Be sure to auth requests using the Participant’s token instead of the User Public token whenever possible. Every API call is logged in our database, and that data will be much more rich if a Participant ID is associated with each possible record.

HTTP Request

POST /v2/games/:id/participants

URI Parameters

Parameter Description
:id The ID of the parent Game

Parameters

Parameter Type Description
email string The Participants’s email
metadata JSON Arbitrary key-value data (optional)

Minimum Permission

Consumer Permission
User private_token
Participant administrate

Get All Participants

Example Request - GET /games/333/participants

strutta = Strutta::API.new 'mystruttatoken'
strutta.games(333).participants.all

Example Response - 200

{
  "results": [
    {
      "id": 6767,
      "metadata": {
        "industry": "Print Media",
        "birthdate": "07/02/1812"
      },
      "email": "charles@dickens.com"
    },
    {
      "id": 8720,
      "metadata": {
        "industry": "Politics",
        "birthdate": "30/04/1797"
      },
      "email": "george@washington.com"
    },
  ],
  "paging": {
    "min_id": 6767,
    "max_id": 8720,
    "next_max_id": 6766
  }
}
[
  {
    "id": 6767,
    "metadata": {
      "industry": "Print Media",
      "birthdate": "07/02/1812"
    },
    "email": "charles@dickens.com"
  },
  {
    "id": 6768,
    "metadata": {
      "industry": "Politics",
      "birthdate": "30/04/1797"
    },
    "email": "george@washington.com"
  },
]

Please see Paging for request and response parameters.

HTTP Request

GET /v2/games/:id/participants

Count Limits/Default

The count parameter defaults to 20 and is limited to 50 for this endpoint.

URI Parameters

Parameter Description
:id The ID of the parent Game

Minimum Permission

Consumer Permission
User public_token
Participant api_basic

Get a Specific Participant

Example Request - GET /games/333/participants/6767

strutta = Strutta::API.new 'mystruttatoken'
strutta.games(333).participants(6767).get

Example Response - 200

{
  "id": 6767,
  "metadata": {
    "industry": "Print Media",
    "birthdate": "07/02/1812"
  },
  "email": "charles@dickens.com",
  "token": "18d20376152626a013c4acd35ee8859a",
  "token_expired": true
}
{
  "id": 6767,
  "metadata": {
    "industry": "Print Media",
    "birthdate": "07/02/1812"
  },
  "email": "charles@dickens.com",
  "token": "18d20376152626a013c4acd35ee8859a",
  "token_expired": true
}

HTTP Request

GET /v2/games/:id/participants/:participant_id

URI Parameters

Parameter Description
:id The ID of the parent Game
:participant_id The ID of the Participant to retrieve

Minimum Permission

Consumer Permission Notes
User public_token
User private_token To access Participant token data
Participant api_basic
Participant administrate To access Participant token data

Get Participant by Email

Example Request - GET /games/333/participants/search

strutta = Strutta::API.new 'mystruttatoken'
strutta.games(333).participants.search(email: 'charles@dickens.com')
{
  "email": "charles@dickens.com"
}

Example Response - 200

{
  "id": 6767,
  "metadata": {
    "industry": "Print Media",
    "birthdate": "07/02/1812"
  },
  "email": "charles@dickens.com",
  "token": "18d20376152626a013c4acd35ee8859a",
  "token_expired": false
}
{
  "id": 6767,
  "metadata": {
    "industry": "Print Media",
    "birthdate": "07/02/1812"
  },
  "email": "charles@dickens.com",
  "token": "18d20376152626a013c4acd35ee8859a",
  "token_expired": false
}

HTTP Request

GET /v2/games/:id/participants/search

URI Parameters

Parameter Description
:id The ID of the parent Game

Parameters

Name Type Description
email string The email of the desired Participant

Minimum Permission

Consumer Permission Notes
User public_token
User private_token To access Participant token data
Participant api_basic
Participant administrate To access Participant token data

Update Participant

Example Request - PATCH /games/333/participants/6767

strutta = Strutta::API.new 'mystruttatoken'

update = {
  metadata: {
    birthday: '02/07/1812'
    industry: 'Print Media',
    died: '09/06/1870'
  }
}
strutta.games(333).participants(6767).update(update)
{
  "metadata": {
    "birthday": "02/07/1812",
    "industry": "Print Media",
    "died": "09/06/1870"
  }
}

Example Response - 200

{
  "id": 6767,
  "metadata": {
    "birthday": "02/07/1812",
    "industry": "Print Media",
    "died": "09/06/1870"
  },
  "email": "charles@dickens.com",
  "token": "18d20376152626a013c4acd35ee8859a",
  "token_expired": false
}
{
  "id": 6767,
  "metadata": {
    "birthday": "02/07/1812",
    "industry": "Print Media",
    "died": "09/06/1870"
  },
  "email": "charles@dickens.com",
  "token": "18d20376152626a013c4acd35ee8859a",
  "token_expired": false
}

You can edit a Participant’s metadata at any time. Since email addresses are used to identify Participants, a Participant’s email address cannot be changed.

HTTP Request

PATCH /v2/games/:id/participants/:participant_id

URI Parameters

Parameter Description
:id The ID of the parent Game
:participant_id The ID of the Participant to update

Parameters

Parameter Type Description
metadata JSON Arbitrary key-value data

Minimum Permission

Consumer Permission Notes
User private_token
Participant administrate
Participant registered If a Participant is editing their own metadata

Renew Participant Token

Example Request - PATCH /games/333/participants/6767/token

strutta = Strutta::API.new 'mystruttatoken'
strutta.games(333).participants(6767).token_renew(duration: 60 * 60)
{
  "duration": 3600
}

Example Response - 200

{
  "token": "3e9dsgskj32f8fj3fae0vfnsi217dnds",
  "token_expired": false
}
{
  "token": "3e9dsgskj32f8fj3fae0vfnsi217dnds",
  "token_expired": false
}

Participant API tokens are valid as long as you’d like them to be. Ideally their duration matches or exceeds the session length of the API client. This way, a new Participant token only needs to be requested with each login to the client.

HTTP Request

PATCH /v2/games/:id/participants/:participant_id/token

URI Parameters

Parameter Description
:id The ID of the parent Game
:participant_id The ID of the Participant to renew

Parameters

Name Type Description Default
duration int The amount of seconds the token is valid for 1 day

Minimum Permission

Consumer Permission
User private_token
Participant administrate

Delete Participant

Example Request - DELETE /games/333/participants/6767

strutta = Strutta::API.new 'mystruttatoken'
strutta.games(333).participants(6767).delete

Example Response - 204

  No Content

HTTP Request

DELETE /v2/games/:id/participant/:participant_id

URI Parameters

Parameter Description
:id The ID of the Parent Game
:participant_id The ID of the Participant to delete

Minimum Permission

Consumer Permission
User private_token
Participant administrate

Participant Permissions

When a Participant is created, they are automatically issued a token with api_basic and registered permissions.

api_basic provides the Participant with general READ permissions.

registered scopes ownership of the Participant object to the Participant who created it, allowing the creator to update their metadata and to create/update their own Entries and Points. Think “my body’s nobody’s body but mine.”

There are three other permissions that can be granted to a user:

Administrate

The administrate permission gives a Participant the ability to perform every action a User Private key allows, with the exception of creating new Games and viewing a list of the User’s Games. Do not include Administrator tokens anywhere in client-side code.

Moderate

The moderate permission gives a Participant the ability to moderate Entries that are in a Moderation Round.

Judge

The judge permission gives a Participant the ability to judge Entries that are in a Judging Round.

Get Participant Permissions

Example Request - GET /games/333/participants/4444/permissions

strutta = Strutta::API.new 'mystruttatoken'
strutta.games(333).participants(4444).permissions.get

Example Response - 200

{
  "permissions": [
    "api_basic",
    "registered",
    "administrate",
    "moderate"
  ]
}
{
  "permissions": [
    "api_basic",
    "registered",
    "administrate",
    "moderate"
  ]
}

HTTP Request

GET /v2/games/:id/participants/permissions

URI Parameters

Parameter Description
:id The ID of the parent Game

Minimum Permission

Consumer Permission
User private_token
Participant administrate

Update Participant Permissions

Example Request - PATCH /games/333/participants/4444/permissions

strutta = Strutta::API.new 'mystruttatoken'

permissions = {
  add: %w( judge ),
  remove: %w( administrate moderate )
}

strutta.games(333).participants(4444).permissions.update(permissions)
{
    "add": [ "judge" ],
    "remove": [ "administrate", "moderate" ]
}

Example Response - 200

{
  "permissions": [
    "api_basic",
    "registered",
    "judge"
  ]
}
{
  "permissions": [
    "api_basic",
    "registered",
    "judge"
  ]
}

Updates are handled using two arrays, add and remove.

HTTP Request

PATCH /v2/games/:id/participants/:participants_id/permissions

URI Parameters

Parameter Description
:id The ID of the parent Game
:participant_id The ID of the Participant to update

Parameters

Parameter Type Description
add Array of strings A list of permissions to add
remove Array of strings A list of permissions to remove

Minimum Permission

Consumer Permission
User private_token
Participant administrate

Entries

Entries are stateful, which means that they belong to different Rounds as the Game progresses. For example, an Entry is part of a Moderation Round until Moderation is completed, when is is moved to the Moderation Round’s pass_round or fail_round.

A Round’s ownership of an Entry is visible in the Entry’s state attribute, which directly maps to the current Round’s ID.

When an Entry is created, the Participant who created the Entry is given the owner permission for the Entry. Entries have Public READ permissions, but only the Entry owner, Administrators and Users can Update and Delete the Entry.

Attributes

Name Type Description
id int The Entry ID
participant_id int The ID of the Participant who owns the Entry
metadata JSON Arbitrary key-value data
created_at string Date and time of creation in ISO 8601 format
media JSON Two valid keys, link and type for defining media associated with the Entry
state int The ID of the Round the Entry is currently a part of
points int Total Points in Round (displays if state is a Points Round)
rank int Current Rank in Round (displays if state is a Points Round)

Create an Entry

Example Request - POST /games/:id/entries

strutta = Strutta::API.new 'mystruttatoken'

entry = {
  participant_id: 6767,
  metadata: {
    title: 'My House',
    description: 'This is a picture of my house'
  },
  media: [{
    link: 'http://placehold.it/350x150',
    type: 'image'
  }]
}
strutta.games(333).entries.create(entry)
{
  "participant_id": 6767,
  "metadata": {
    "title": "My House",
    "description": "This is a picture of my house"
  },
  "media": {
    "link": "http://placehold.it/350x150",
    "type": "image"
  }
}

Example Response - 201

{
  "id": 9898,
  "participant_id": 6767,
  "state": 222,
  "created_at": "2016-01-01T00:00:00.001Z",
  "metadata": {
    "title": "My House",
    "description": "This is a picture of my house"
  },
  "media": {
    "link": "http://placehold.it/350x150",
    "type": "image"
  }
}
{
  "id": 9898,
  "participant_id": 6767,
  "state": 222,
  "created_at": "2016-01-01T00:00:00.001Z",
  "metadata": {
    "title": "My House",
    "description": "This is a picture of my house"
  },
  "media": {
    "link": "http://placehold.it/350x150",
    "type": "image"
  }
}

Entries must be created by Participants - or on behalf of existing Participants - when the Game has 1 or more active Submission rounds.

HTTP Request

POST /v2/games/:id/entries

URI Parameters

Parameter Description
:id The ID of the parent Game

Parameters

Parameter Type Description
participant_id int The ID of the Participant the Entry belongs to
metadata JSON Arbitrary key-value data (optional)
referral string The ID of a referring Participant (optional; see Referrals)

Minimum Permission

Consumer Permission Notes
User private_token
Participant api_basic
Participant administrate If creating an Entry on behalf of another Participant

Create a Participant and Entry

POST v2/games/:id/enter

This is the consolidated endpoint for creating an entry without first needing to create a participant.

Parameters

Parameter Description
token the API key, required
email An email used to identify the participant. Required, unless an identifier is passed
identifier An alphanumeric string used to identify the participant. Required, unless an email is passed
metatdata Optional json to include with the entry

The API will only accept an email or identifier, not both. In the case that the participant has reached the submission limit, the API will return the status of 422 unprocessable entity as well as the last valid entry from the participant.

Get All Entries

Example Request - GET /games/:id/entries

strutta = Strutta::API.new 'mystruttatoken'
strutta.games(333).entries.all(state: 4444, participant: true)
{
  "state": 4444,
  "participant": true
}

Example Response - 200

{
  "results": [
    {
      "id": 9898,
      "participant_id": 6767,
      "state": 222,
      "created_at": "2016-01-01T00:00:00.001Z",
      "metadata": {
        "title": "My House",
        "description": "This is a picture of my house"
      },
      "media": {
        "link": "http://placehold.it/350x150",
        "type": "image"
      },
      "participant": {
        "id": 6767,
        "metadata": {
          "industry": "Print Media",
          "birthdate": "07/02/1812"
        },
        "email": "charles@dickens.com"
      }
    },
    {
      "id": 9899,
      "participant_id": 6767,
      "state": 4444,
      "created_at": "2016-01-01T00:00:01.001Z",
      "metadata": {
        "title": "My House",
        "description": "This is a picture of my house"
      },
      "media": {
        "link": "http://placehold.it/350x150",
        "type": "image"
      },
      "participant": {
        "id": 6767,
        "metadata": {
          "industry": "Print Media",
          "birthdate": "07/02/1812"
        },
        "email": "charles@dickens.com"
      }
    }
  ],
  "paging": {
    "min_id": 9898,
    "max_id": 9899,
    "next_max_id": 9897
  }
}
{
  "results": [
    {
      "id": 9898,
      "participant_id": 6767,
      "state": 222,
      "created_at": "2016-01-01T00:00:00.001Z",
      "metadata": {
        "title": "My House",
        "description": "This is a picture of my house"
      },
      "media": {
        "link": "http://placehold.it/350x150",
        "type": "image"
      },
      "participant": {
        "id": 6767,
        "metadata": {
          "industry": "Print Media",
          "birthdate": "07/02/1812"
        },
        "email": "charles@dickens.com"
      }
    },
    {
      "id": 9899,
      "participant_id": 6767,
      "state": 4444,
      "created_at": "2016-01-01T00:00:01.001Z",
      "metadata": {
        "title": "My House",
        "description": "This is a picture of my house"
      },
      "media": {
        "link": "http://placehold.it/350x150",
        "type": "image"
      },
      "participant": {
        "id": 6767,
        "metadata": {
          "industry": "Print Media",
          "birthdate": "07/02/1812"
        },
        "email": "charles@dickens.com"
      }
    }
  ],
  "paging": {
    "min_id": 9898,
    "max_id": 9899,
    "next_max_id": 9897
  }
}

Please see Paging for request and response parameters.

HTTP Request

GET /v2/games/:id/entries

Count Limits/Default

The count parameter defaults to 20 and is limited to 50 for this endpoint.

Points

points and rank are included automatically if the Entry’s current state is a Points Round.

If past_state represents a Points Round, all Entries will return their rank and points for the Points Round represented by past_state, not their current state.

URI Parameters

Parameter Description
:id The ID of the parent Game

Parameters

Name Type Description
since_id int Return Entries created after since_id
max_id int Return Entries created before and including max_id
count int 1-50 (optional - defaults to 50)
participant_id int Get Entries created by a Participant
participant boolean Whether to get the Participant with the Entry (optional – defaults to false)
state int Get Entries currently in this state
past_state int Get Entries that have had this state

Minimum Permission

Consumer Permission
User public_token
Participant api_basic

Entry Leaderboard

Example Request - GET /games/:id/entries/leaderboard

strutta = Strutta::API.new 'mystruttatoken'

leaderboard_params = {
  round_id: 4444,
  top_rank: 1,
  limit: 3
}
strutta.games(333).entries.leaderboard(leaderboard_params)
{
  "round_id": 4444,
  "top_rank": 1,
  "limit": 3
}

Example Response - 200

{
  "results": [
    {
      "id": 9898,
      "participant_id": 6767,
      "state": 4444,
      "created_at": "2016-01-01T00:00:00.001Z",
      "metadata": {
        "title": "My first Entry"
      },
      "points": 231,
      "rank": 1
    },
    {
      "id": 9899,
      "participant_id": 6767,
      "state": 4444,
      "created_at": "2016-01-01T00:00:01.001Z",
      "metadata": {
        "title": "My second Entry"
      },
      "points": 187,
      "rank": 2
    },
    {
      "id": 9976,
      "participant_id": 6779,
      "state": 4444,
      "metadata": {
        "title": "My third Entry"
      },
      "points": 76,
      "rank": 3
    }
  ],
  "paging": {
    "top_rank": 1,
    "bottom_rank": 3,
    "next_top_rank": 4
  }
}
{
  "results": [
    {
      "id": 9898,
      "participant_id": 6767,
      "state": 4444,
      "created_at": "2016-01-01T00:00:01.001Z",
      "metadata": {
        "title": "My first Entry"
      },
      "points": 231,
      "rank": 1
    },
    {
      "id": 9899,
      "participant_id": 6767,
      "state": 4444,
      "created_at": "2016-01-01T00:00:00.001Z",
      "metadata": {
        "title": "My second Entry"
      },
      "points": 187,
      "rank": 2
    },
    {
      "id": 9976,
      "participant_id": 6779,
      "state": 4444,
      "metadata": {
        "title": "My third Entry"
      },
      "points": 76,
      "rank": 3
    }
  ],
  "paging": {
    "top_rank": 1,
    "bottom_rank": 3,
    "next_top_rank": 4
  }
}

A Leaderboard is a set of Entries sorted by points.

You can request a Leaderboard of 1-20 Entries. For paging, this endpoint uses a combination of the top_rank and limit parameters. For Example:

Desired Leaderboard top_rank limit
Top 10 Entries (1-10) 1 10
Next 10 Entries (11-20) 11 10

A note on ties

Entries with equal points will each be given the highest rank possible, as shown below.

Entry ID Points Rank
111 100 1
222 100 1
333 100 1
444 50 4
555 50 4
666 10 6

HTTP Request

GET /v2/games/:id/entries/leaderboard

URI Parameters

Parameter Description
:id The ID of the parent Game

Parameters

Name Type Description
round_id int The ID of the Points Round
top_rank int The highest rank desired. Ie. for the top 10, choose 1 (optional - defaults to 1)
limit int 1-20 (optional - defaults to 20)

Minimum Permission

Consumer Permission
User public_token
Participant api_basic

Get a Specific Entry

Example Request - GET /games/:id/entries/:entry_id

strutta = Strutta::API.new 'mystruttatoken'
strutta.games(333).entries(9898).get

Example Response

{
  "id": 9898,
  "participant_id": 6767,
  "state": 4444,
  "created_at": "2016-01-01T00:00:00.001Z",
  "metadata": {
    "title": "My Entry"
  },
  "points": 33212,
  "rank": 12
}
{
  "id": 9898,
  "participant_id": 6767,
  "state": 4444,
  "created_at": "2016-01-01T00:00:00.001Z",
  "metadata": {
    "title": "My Entry"
  },
  "points": 33212,
  "rank": 12
}

Points

points and rank are included automatically if the Entry’s current state is a Points Round.

If points_state represents a Points Round, the response will include the Entry’s rank and points for the Points Round represented by points_state, not its current state.

HTTP Request

GET /v2/games/:id/entries/:entry_id

URI Parameters

Parameter Description
:id The ID of the parent Game
:entry_id The ID of the Entry to retrieve

Parameters

Name Type Description
points_state int Return rank and points for the Entry while in the Points Round with this id

Get Entry Transitions

Example Request - GET /games/:id/entries/:entry_id/transitions

strutta = Strutta::API.new 'mystruttatoken'
strutta.games(333).entries(9898).transitions

Example Response

{
  "transitions": [
    { "from": 555, "to": 666 },
    { "from": 666, "to": 777 }
  ]
}
{
  "transitions": [
    { "from": 555, "to": 666 },
    { "from": 666, "to": 999 }
  ]
}

Whenever an Entry advances from one Round to another, its transitions are recorded. Use this endpoint to see the path a specific Entry has taken through a Game.

HTTP Request

GET /v2/games/:id/entries/:entry_id/transitions

URI Parameters

Parameter Description
:id The ID of the parent Game
:entry_id The ID of the Entry to retrieve

Response Parameters

Parameter Description
transitions An Array of transition elements

Transition Element Parameters

Parameter Description
from The state before the transition
to The state after the transition

On Demand Winners

Example Request - POST /games/:id/entries/on-demand-winners

strutta = Strutta::API.new 'mystruttatoken'
strutta.games(333).entries.on_demand_winners

Example Response

{
  "results": [
    {
      "id": 9898,
      "participant_id": 6767,
      "state": 4444,
      "created_at": "2016-01-01T00:00:00.001Z",
      "metadata": {
        "title": "My first Entry"
      }
    },
    {
      "id": 9899,
      "participant_id": 6767,
      "state": 4444,
      "created_at": "2016-01-01T00:00:01.001Z",
      "metadata": {
        "title": "My second Entry"
      }
    }
  ],
  "paging": {
    "min_id": 9898,
    "max_id": 9899,
    "next_max_id": 9897
  }
}
{
  "results": [
    {
      "id": 9898,
      "participant_id": 6767,
      "state": 4444,
      "created_at": "2016-01-01T00:00:00.001Z",
      "metadata": {
        "title": "My first Entry"
      }
    },
    {
      "id": 9899,
      "participant_id": 6767,
      "created_at": "2016-01-01T00:00:01.001Z",
      "state": 4444,
      "metadata": {
        "title": "My second Entry"
      }
    }
  ],
  "paging": {
    "min_id": 9898,
    "max_id": 9899,
    "next_max_id": 9897
  }
}

The On-Demand Winners endpoint behaves as a mini-game within your Game. A pre-defined number of entries are randomly drawn from all entries that have an active (non-nil) state. These winners are then passed through the provided On-Demand Round and returned.

Since any all Entry state changes are recorded, it is easy to get a list of winners using the past_state parameter in GET Entries.

HTTP Request

POST v2/games/:id/entries/on-demand-winners

URI Parameters

Parameter Description
:winner_count The number of Entries to randomly select as winners
:round_id The ID On-Demand Round - required only if you have more than one active On-Demand Round

Response Parameters

Parameter Description
results An Array of winning Entries
paging The paging hash

Update Entry

Example Request - PATCH /games/:id/entries/:entry_id

strutta = Strutta::API.new 'mystruttatoken'

update = {
  metadata: {
    title: "New Entry Title"
  },
  state: 123
}
strutta.games(333).entries(9898).update(update)
{
  "metadata": {
    "title": "New Entry Title"
  },
  "state": 123
}

Example Response

{
  "id": 9898,
  "participant_id": 6767,
  "state": 123,
  "created_at": "2016-01-01T00:00:00.001Z",
  "metadata": {
    "title": "New Entry Title"
  }
}
{
  "id": 9898,
  "participant_id": 6767,
  "state": 123,
  "metadata": {
    "title": "New Entry Title"
  }
}

HTTP Request

PATCH /v2/games/:id/entries/:entry_id

URI Parameters

Parameter Description
:id The ID of the parent Game
:entry_id The ID of the Entry to update

Parameters

Name Type Description
metadata JSON Arbitrary key-value data
state int The desired state for the Entry
participant_id int The new owner of the Entry

Minimum Permission

Consumer Permission Notes
User private_token
Participant Entry owner
Participant administrate If updating participant_id or state of Entry, or updating on behalf of another participant

Delete Entry

Example Request - DELETE /games/:id/entries/:entry_id

strutta = Strutta::API.new 'mystruttatoken'
strutta.games(333).entries(9898).delete

Example Response - 204

  No Content

HTTP Request

DELETE /v2/games/:id/entries/:entry_id

URI Parameters

Parameter Description
:id The ID of the Parent Game
:entry_id The ID of the Entry to delete

Minimum Permission

Consumer Permission Notes
User private_token
Participant Entry owner
Participant administrate If deleting an Entry on behalf of another Participant

Tags

Entries can be tagged with simple strings values, which can then be filtered against to group entries. To supply multiple tags, simply comma-delimit them.

Tags can be supplied alongside an optional tag_type, which defaults to tags.

Get an Entry’s Tags

Example Request - GET /games/:id/entries/:entry_id/?tags=true

# Gem functionality not available, please use JSON endpoint

Example Response - 201

# Gem functionality not available, please use JSON endpoint
{
  "id": 9898,
  "participant_id": 6767,
  "state": 222,
  "created_at": "2016-01-01T00:00:00.001Z",
  "metadata": {
    "title": "My House",
    "description": "This is a picture of my house"
  },
  "media": [],
  "tags": [
    {
      "genre": [
        "jazz",
        "funk"
      ]
    },
    {
      "tags": [
        "fan favourite"
      ]
    },
    {
      "private": [
        "great"
      ]
    }
  ]
}

HTTP Request

GET /v2/games/:id/entries/:entry_id/?tags=true

URI Parameters

Parameter Description
:id The ID of the parent Game
:entry_id The ID of the parent Game
tags pass true to include tags with the Entry

Notes

We are currently experimenting with also allowing a tags=true parameter for the entries index route, to cut down on API requests.

This endpoint looks like this:

GET /v2/games/:id/entries/?tags=true

This will return paged results just like /entries, but with the nested tags attribute for each entry. This will be available for the time being, but we reserve the right to remove the tags flag from this endpoint in the future, for performance reasons.

Add tags to an Entry

Example Request - POST /games/:id/entries/:entry_id/tags

# Gem functionality not available, please use JSON endpoint
{
  "tag_type": "genre",
  "tag_name": "jazz,funk"
}

Example Response - 201

# Gem functionality not available, please use JSON endpoint
{
  "id": 9898,
  "participant_id": 6767,
  "state": 222,
  "created_at": "2016-01-01T00:00:00.001Z",
  "metadata": {
    "title": "My House",
    "description": "This is a picture of my house"
  },
  "media": [],
  "tags": [
    {
      "genre": [
        "jazz",
        "funk"
      ]
    },
  ]
}

HTTP Request

POST /v2/games/:id/entries/:entry_id/tags

URI Parameters

Parameter Description
:id The ID of the parent Game
:entry_id The ID of the parent Game

Parameters

Parameter Type Description
tag_type string The type of tag, defaults to tags
tag_name string The name of the tag, can be multiple by comma-delimiting. e.g. tag_name=rock,pop,jazz

Delete Tags from Entry

Example Request - DELETE /games/:id/entries/:entry_id/tags

# Gem functionality not available, please use JSON endpoint
{
  "tag_type": "genre",
  "tag_name": "rock"
}

Example Response - 200

# Gem functionality not available, please use JSON endpoint
{
  "id": 9898,
  "participant_id": 6767,
  "state": 222,
  "created_at": "2016-01-01T00:00:00.001Z",
  "metadata": {
    "title": "My House",
    "description": "This is a picture of my house"
  },
  "media": [{
    "link": "http://placehold.it/350x150",
    "type": "image"
  }],
  "tags": []
}

HTTP Request

DELETE /v2/games/:id/entries/:entry_id/tags

URI Parameters

Parameter Description
:id The ID of the parent Game
:entry_id The ID of the parent Game

Parameters

Parameter Type Description
tag_type string The type of tag that is to be deleted. Defaults to tags. optional
tag_name string The name of the tag to be deleted.

Get all Tags from a game

Example Request - GET /games/:id/entries/tags

# Gem functionality not available, please use JSON endpoint

Example Response - 200

# Gem functionality not available, please use JSON endpoint
{
  "tags": [
    {
      "genre": ["rock", "jazz"]
    },
    {
      "tags": [ "horse", "staple", "battery"]
    },
    {
      "colour": ["blue"]
    }
  ]
}

HTTP Request

GET /v2/games/:id/entries/tags?tag_type=genre

URI Parameters

Parameter Description
:id The ID of the parent Game
tag_type The type of tags to return, defaults to returning all tags. optional

Parameters

none.

Notes

This endpoint is computed by looking at the currently tagged entries, and will return empty if no entries are tagged.

Get Entries by Tag

Example Request - GET /games/:id/entries/?tag_type=genre&tag_name=jazz

# Gem functionality not available, please use JSON endpoint

Example Response - 200

# Gem functionality not available, please use JSON endpoint
{
  "results": [
    {
      "id": 9898,
      "participant_id": 6767,
      "state": 4444,
      "created_at": "2016-01-01T00:00:01.001Z",
      "metadata": {
        "title": "My first Entry"
      },
      "tags": [
        {
          "genre": ["jazz", "rock"]
        },
        {
          "private": ["great"]
        }
      ]
    },
    {
      "id": 9899,
      "participant_id": 6767,
      "state": 4444,
      "created_at": "2016-01-01T00:00:00.001Z",
      "metadata": {
        "title": "My second Entry"
      },
      "tags": [
        {
          "genre": ["jazz", "blues"]
        },
        {
          "private": ["terrible"]
        }
      ]
    },
    {
      "id": 9976,
      "participant_id": 6779,
      "state": 4444,
      "metadata": {
        "title": "My third Entry"
      },
      "tags": [
        {
          "genre": ["jazz", "pop"]
        },
        {
          "private": ["great"]
        }
      ]
    }
  ],
  "paging": {
    "max_id": 1,
    "min_id": 3,
    "next_max_id": 4
  }
}

HTTP Request

GET /v2/games/:id/entries/?tag_type=genre&tag_name=jazz,rock

URI Parameters

Parameter Description
:id The ID of the parent Game
:game_id The ID of the parent Game
tag_type The type of tag, defaults to tags
tag_name The tag to filter against. Can be multiple, comma-delimited tags

Paging

Paging is identical to all other paging in the API.

Notes

When you supply multiple tags, the API will return any entries that match any tag.

Example request for multiple tag_name

GET /v2/games/:id/entries/?tag_type=genre&tag_name=jazz,rock,blues

response

{
  "results": [
    {
      "id": 123,
      "participant_id": 6779,
      "state": 4444,
      "metadata": {
        "title": "My third Entry"
      },
      "tags": [
        {
          "genre": ["rock", "pop"]
        }
      ]
    },
    {
      "id": 124,
      "participant_id": 6779,
      "state": 4444,
      "metadata": {
        "title": "My third Entry"
      },
      "tags": [
        {
          "genre": ["jazz", "blues"],
          "private": ["offensive"]
        }
      ]
    },
    {
      "id": 125,
      "participant_id": 6779,
      "state": 4444,
      "metadata": {
        "title": "My third Entry"
      },
      "tags": [
        {
          "genre": ["blues", "funk"]
        }
      ]
    }
  ],
  "paging": {
    // paging params
  }
}

Points

There are many manifestations of Points across the internet. Examples include: “Votes”, “Likes”, “Re-Tweets”, “Subscribes”, “Diggs”, and many more.

At the end of the day, each of the above is just a way of keeping score. To further our generalized Game analogy, we opted to use Points as our descriptor.

Attributes

Name Type Description
id int The Point ID
weight int Weight associated with the Point. Can be negative. (Optional - Defaults to 1)

Award Points to an Entry

Example Request - POST /games/:id/points

strutta = Strutta::API.new 'mystruttatoken'
point_params = {
  round_id: 4444,
  entry_id: 55555,
  participant: 1212,
  weight: 5
}
strutta.games(333).points.create(point_params)
{
  "round_id": 4444,
  "entry_id": 55555,
  "participant_id": 1212,
  "weight": 5
}

Example Response - 201

{
  "id": 76767,
  "weight": 5
}
{
  "id": 76767,
  "weight": 5
}

A Participant awards Points to an Entry during a Round. Therefore, the IDs of all of these parent objects must be part of the POST.

Validation

Recall that when the Points Round is defined, a min_allowed and a max_allowed value is set, as well as a validation interval.

Total Point value is the sum of the weight of all Point records created during interal. Since weight can be negative, a Participant can theoretically add and subtract values from their total value as many times as they’d like during interval, they just have to honour min_allowed <= total <= max_allowed.

HTTP Request

POST /v2/games/:id/points

URI Parameters

Parameter Description
:id The ID of the parent Game

Request Parameters

Parameter Type Description
round_id ID of the Points round
entry_id ID of the Entry Points are being awarded to
participant ID of the Participant awarding Points
weight Weight associated with the Point. Can be negative. (Optional - Defaults to 1)

Minimum Permission

Consumer Permission Notes
User private_token
Participant registered If a Participant is adding Points for themselves
Participant administrate If a Participant is adding Points on behalf of another

Moderation

The Moderation endpoint simplifies the logic of moving an Entry through a Moderation Round.

Get Entries in Moderation

It is possible for a Game to have concurrent Moderation Rounds. This endpoint conveniently gathers all Entries in Moderation and orders them by their state.

Example Request - GET /games/:id/moderation

strutta = Strutta::API.new 'mystruttatoken'
strutta.games(333).moderation.get

Example Response - 200

{
  "results": [
    {
      "id": 9898,
      "participant_id": 6767,
      "state": 1234,
      "metadata": {
        "image": "http://placehold.it/350x150",
        "title": "Image Entry",
        "description": "This is a picture of my house"
      }
    },
    {
      "id": 9899,
      "participant_id": 6767,
      "state": 1234,
      "metadata": {
        "image": "http://placehold.it/350x150",
        "title": "Image Entry #2",
        "description": "This is another picture of my house"
      }
    },
    {
      "id": 3322,
      "participant_id": 4433,
      "state": 3324,
      "metadata": {
        "title": "Entry in state 3324"
      }
    },
    {
      "id": 9899,
      "participant_id": 6767,
      "state": 3324,
      "metadata": {
        "title": "Another Entry in state 3324"
      }
    }
  ]
}
{
  "results": [
    {
      "id": 9898,
      "participant_id": 6767,
      "state": 1234,
      "metadata": {
        "image": "http://placehold.it/350x150",
        "title": "Image Entry",
        "description": "This is a picture of my house"
      }
    },
    {
      "id": 9899,
      "participant_id": 6767,
      "state": 1234,
      "metadata": {
        "image": "http://placehold.it/350x150",
        "title": "Image Entry #2",
        "description": "This is another picture of my house"
      }
    },
    {
      "id": 3322,
      "participant_id": 4433,
      "state": 3324,
      "metadata": {
        "title": "Entry in state 3324"
      }
    },
    {
      "id": 9899,
      "participant_id": 6767,
      "state": 3324,
      "metadata": {
        "title": "Another Entry in state 3324"
      }
    }
  ]
}

HTTP Request

GET /v2/games/:id/moderation

URI Parameters

Parameter Description
:id The ID of the parent Game

Request Parameters

Parameter Description
round_id Use to filter Entries to a single Moderation Round (optional)

Minimum Permission

Consumer Permission
User private_token
Participant moderate

Moderate Entries

Example Request - POST /games/:id/moderation

strutta = Strutta::API.new 'mystruttatoken'

moderation = [
  {
    id: 1234,
    pass: true
  },
  {
    id: 3543,
    pass: false
  },
  {
    id: 5435,
    pass: false
  },
  {
    id: 2364,
    pass: true
  },
  {
    id: 8535,
    pass: true
  }
]

strutta.games(333).moderation.create(moderation: moderation)
{
  "moderation": [
    {
      "id": 1234,
      "pass": "true"
    },
    {
      "id": 3543,
      "pass": "false"
    },
    {
      "id": 5435,
      "pass": "false"
    },
    {
      "id": 2364,
      "pass": "true"
    },
    {
      "id": 8535,
      "pass": "true"
    }
  ]
}

Example Response - 200

{
  "results": [
    {
      "id": 1234,
      "state": 555
    },
    {
      "id": 3543,
      "state": 666
    },
    {
      "id": 5435,
      "state": 666
    },
    {
      "id": 2364,
      "state": "not_in_moderation"
    },
    {
      "id": 8535,
      "state": "error_advancing_entry"
    }
  ]
}
{
  "results": [
    {
      "id": 1234,
      "state": 555
    },
    {
      "id": 3543,
      "state": 666
    },
    {
      "id": 5435,
      "state": 666
    },
    {
      "id": 2364,
      "state": "not_in_moderation"
    },
    {
      "id": 8535,
      "state": "error_advancing_entry"
    }
  ]
}

This endpoint allows you to Moderate entries in batches - even if they aren’t in the same Moderation Round.

Because this is a batch action, HTTP errors won’t be thrown if a single update is not successful. Rather, errors are recorded in the state value of the return object.

Error Meaning
not_in_moderation Either the Entry does not exist or it is not currently in Moderation
error_advancing_entry An error occurred when updating the Entry’s state. Try again.

HTTP Request

POST /v2/games/:id/moderation

URI Parameters

Parameter Description
:id The ID of the parent Game

Parameters

Parameter Type
moderation array of Moderation hashes, limit 20

Moderation Hash Parameters

Parameter Type Description
id int The Entry ID
pass bool Whether the Entry passed moderation

Minimum Permission

Consumer Permission
User private_token
Participant moderate

Judging

Get Judging results for a Round

strutta = Strutta::API.new 'mystruttatoken'
strutta.games(333).judging.get(round_id: 4444)

Example Response - 200

{
  "round_id": 4444,
  "judging": [
    {
      "judge_id": 55555,
      "judgments": [
        {
          "id": 1234,
          "entry_id": 878787,
          "score": 3,
          "metadata": {
            "comments": "This entry was very well designed."
          },
          "created": 1413889551
        },
        {
          "id": 1235,
          "entry_id": 878788,
          "score": 2,
          "metadata": {
            "comments": "This entry was decent."
          },
          "created": 1413889599
        },
        {
          "id": 1236,
          "entry_id": 878789,
          "score": 1,
          "metadata": {
            "comments": "This entry was third in my books."
          },
          "created": 1413889655
        }
      ]
    },
    {
      "judge_id": 55556,
      "judgments": [
        {
          "id": 1237,
          "entry_id": 878788,
          "score": 3,
          "metadata": {
            "comments": "This entry was excellent."
          },
          "created": 1413889551
        },
        {
          "id": 1238,
          "entry_id": 878789,
          "score": 2,
          "metadata": {
            "comments": "This entry was relatively good."
          },
          "created": 1413889599
        },
        {
          "id": 1239,
          "entry_id": 878787,
          "score": 1,
          "metadata": {
            "comments": "This entry half-hearted."
          },
          "created": 1413889655
        }
      ]
    }
  ]
}
{
  "round_id": 4444,
  "judging": [
    {
      "judge_id": 55555,
      "judgments": [
        {
          "id": 1234,
          "entry_id": 878787,
          "score": 3,
          "metadata": {
            "comments": "This entry was very well designed."
          },
          "created": 1413889551
        },
        {
          "id": 1235,
          "entry_id": 878788,
          "score": 2,
          "metadata": {
            "comments": "This entry was decent."
          },
          "created": 1413889599
        },
        {
          "id": 1236,
          "entry_id": 878789,
          "score": 1,
          "metadata": {
            "comments": "This entry was third in my books."
          },
          "created": 1413889655
        }
      ]
    },
    {
      "judge_id": 55556,
      "judgments": [
        {
          "id": 1237,
          "entry_id": 878788,
          "score": 3,
          "metadata": {
            "comments": "This entry was excellent."
          },
          "created": 1413889551
        },
        {
          "id": 1238,
          "entry_id": 878789,
          "score": 2,
          "metadata": {
            "comments": "This entry was relatively good."
          },
          "created": 1413889599
        },
        {
          "id": 1239,
          "entry_id": 878787,
          "score": 1,
          "metadata": {
            "comments": "This entry half-hearted."
          },
          "created": 1413889655
        }
      ]
    }
  ]
}

This endpoint provides detailed information about the Judging for a specific Judging Round.

HTTP Request

GET /v2/games/:id/judging

URI Parameters

Parameter Description
:id The ID of the parent Game

Request Parameters

Parameter Description
judge_id Restrict this response to just the Judgments made by the Participant with ID: judge_id (optional)

Response Parameters

Parameter Type Description
round_id int The Judging Round ID requested
judging array An array of Participant Judgments grouped by judge_id

Participant Judgment Parameters

Parameter Type Description
judge_id int The ID of the Participant with the judge permission who created judgments
judgments array An array of Individual Judgments created by this Judge

Individual Judgment Parameters

Parameter Type Description
id int The Judgment ID
entry_id int The ID of the Entry being judged
score int The score given to the Entry by the Judge
metadata JSON Any metadata added by the Judge
created UNIX timestamp When the Judgment was created

Minimum Permission

Consumer Permission
User private_token
Participant judge

Judge Entries

Example Request

strutta = Strutta::API.new 'mystruttatoken'

judging = [
  {
    entry_id: 1234,
    rank: 1,
    metadata: {
      comments: 'First place'
    }
  },
  {
    entry_id: 1235,
    rank: 2,
    metadata: {
      comments: 'Second place'
    }
  },
  {
    entry_id: 1236,
    rank: 3,
    metadata: {
      comments: 'Third place'
    }
  }
]

strutta.games(333).judging.create(round_id: 4444, judge_id: 55555, judging: judging)
{
  "round_id": 4444,
  "judge_id": 55555,
  "judging": [
    {
      "entry_id": 1234,
      "rank": 1,
      "metadata": {
        "comments": "First place"
      }
    },
    {
      "entry_id": 1235,
      "rank": 2,
      "metadata": {
        "comments": "Second place"
      }
    },
    {
      "entry_id": 1236,
      "rank": 3,
      "metadata": {
        "comments": "Third place"
      }
    }
  ]
}

Example Response - 201

{
  "message": "Judging was successful"
}
{
  "message": "Judging was successful"
}

This endpoint provides detailed information about the Judging for a specific Judging Round.

HTTP Request

POST /v2/games/:id/judging

URI Parameters

Parameter Description
:id The ID of the parent Game

Request Parameters

Parameter Description
round_id The ID of the Judging Round
judge_id The Participant ID of the Judge

Minimum Permission

Consumer Permission
User private_token
Participant judge

Errors

Errors generally take this form:

{
  "error": "Error Type",
  "message": "Detailed description of why the error occurred."
}
{
  "error": "Error Type",
  "message": "Detailed description of why the error occurred."
}

The Strutta API uses the following error codes:

Code Meaning
400 Bad Request – Error wih your request - generally syntactical
401 Unauthorized – Your API token is not valid
422 Not Acceptable – Error wih your request - generally semantic
429 Too Many Requests – Rate limiting
500 Internal Server Error – We had a problem with our server. Try again later.
503 Service Unavailable – We’re temporarially offline for maintenance. Please try again later.