Introduction
Welcome to the Scratcher API! Here you can see a list of all the resources we offer and a code example of how to access it.
There is also a guide on how to authenticate with OAuth2.
The PHP examples makes use of the Guzzle HTTP libary to make requests.
Authentication with OAuth2
To make use of our API you must use OAuth2. Scratcher expects all API requests to contain a header like so:
Authorization: Bearer ACCESS_TOKEN
Redirecting For Authorization
<?php
$query = http_build_query([
'client_id' => 'client-id',
'redirect_uri' => 'http://example.com/callback',
'response_type' => 'code',
'scope' => 'read:campaigns read:leads',
]);
header('Location: ' . 'https://app.scratcher.io/oauth/authorize?' . $query);
Remember to replace the parameters with your own.
The first thing you have to do is redirect your user to the specified URL with the parameters below.
If the parameters are valid the user will be shown a page where they can approve or deny access.
Query Parameters
Parameter | Required | Description |
---|---|---|
client_id | true | The client id - this is found when creating an app on Scratcher |
redirect_uri | true | The redirect uri. This MUST match the redirect uri you specified when creating the app |
response_type | true | This must be "code" |
scope | true | The scopes your app needs |
Approving The Request
A user must approve the request before he is redirected. If the user accepts, the user is redirected to your redirect_uri
with the following parameters
Parameter | Description |
---|---|
code | An authorization code needed to get the access token |
If the user denies the request, the user is redirected to your redirect_uri
with the following parameters
Parameter | Description |
---|---|
error | The error code. This defaults to access_denied |
Converting Authorization Codes To Access Tokens
In this example, we make use of the Guzzle HTTP library to make the POST request
<?php
$http = new GuzzleHttp\Client;
$response = $http->post('https://app.scratcher.io/oauth/token', [
'form_params' => [
'grant_type' => 'authorization_code',
'client_id' => 'client-id',
'client_secret' => 'client-secret',
'redirect_uri' => 'http://example.com/callback',
'code' => 'YOUR_CODE_HERE',
],
]);
return json_decode((string) $response->getBody(), true);
The above request returns the following JSON:
{
"token_type": "Bearer",
"access_token" : "...",
"refresh_token" : "...",
"expires_in" : 31536000
}
If the user approves the authorization request, they will be redirected back to your application. You should then issue a POST request to our application to request an access token. The request should include the authorization code that was issued by our application when the user approved the authorization request.
Parameters
Parameter | Required | Description |
---|---|---|
grant_type | true | |
client_id | true | The client id - this is found when creating an app on Scratcher |
client_secret | true | The client secret - this is found when creating an app on Scratcher |
redirect_uri | true | The redirect uri. This MUST match the uri specified on the app |
code | true | The code received from the redirect |
This /oauth/token
route will return a JSON response containing token_type, access_token, refresh_token, and expires_in attributes.
Access tokens expire after 1 year and refresh tokens expire after 1 year and 2 week.
Refreshing Access Tokens
<?php
$http = new GuzzleHttp\Client;
$response = $http->post('https://app.scratcher.io/oauth/token', [
'form_params' => [
'grant_type' => 'refresh_token',
'refresh_token' => 'your-refresh-token',
'client_id' => 'client-id',
'client_secret' => 'client-secret',
'scope' => 'read:campaigns read:leads',
],
]);
return json_decode((string) $response->getBody(), true);
The above request returns the following JSON:
{
"token_type": "Bearer",
"access_token" : "...",
"refresh_token" : "...",
"expires_in" : 31536000
}
You will need to refresh the access token after 1 year.
To refresh the access token, make a request to our server with the refresh_token
.
Parameters
Parameter | Required | Description |
---|---|---|
grant_type | true | |
refresh_token | true | The refresh token you got when first authenticating using OAuth2 |
client_id | true | The client id - this is found when creating an app on Scratcher |
client_secret | true | The client secret - this is found when creating an app on Scratcher |
scope | true | The scopes your app needs |
Authentication without OAuth2
We recommend using OAuth2 to authorize but you can also create an infinite-lived access token under your account on Scratcher. You can then use the token as you would use an OAuth2 token.
Basics
This contains the basic routes such as /me
Account information
Remember to replace the
$accessToken
with your own.
<?php
$http = new GuzzleHttp\Client;
$client->request('GET', 'https://app.scratcher.io/api/v1/me', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer ' . $accessToken,
],
]);
This returns the following response in JSON
{
"data": {
"id": 1,
"name": "John Doe",
"company_name": "Johnny Cars A/S",
"email": "john@example.com",
"phone": 88888888,
"address_street": "Fakestreet 1",
"address_zipcode": "0000",
"address_city": "Fake City",
"cvr": "00000000"
}
}
In this example, we make use of the Guzzle HTTP library to make the GET request to fetch the authenticated user's information.
HTTP Request
GET https://app.scratcher.io/api/v1/me
Campaigns
You can retrieve a specific campaign as well as list all the campaigns on your account.
The campaign object
The campaign object
{
"id": 1337,
"name": "Easter campaign 2019",
"url_slug": "easter-campaign-2019",
"url": "https://game.scratcher.io/easter-campaign-2019",
"demo_url": "https://game.scratcher.io/easter-campaign-2019?dt=362d0b21-865c-4c6e-9799-fdc993f72b92",
"start_date": "2019-04-14 12:00:00",
"end_date": "2019-04-22 12:00:00",
"active": true,
"ended": false,
"created_at": "2019-03-15 11:57:34",
"prizes": [
{
"id": 14,
"name": "10% off",
"description": "Lorem ipsum dolor sit amet",
"prize_type": "normal",
"redeem_type": "discount_code"
}
]
}
Attributes
An array of all prizes on the campaign
prizes[:index].id
The ID of the prize
prizes[:index].name
The name of the prize
prizes[:index].description
The description of the prize
prizes[:index].prize_type
The prize type of the prize (normal, consolation, draw)
prizes[:index].redeem_type
The redeem type of the prize (manual, discount_code, voucher, download)
Retrieve a campaign
Remember to set the headers and access token
<?php
$http = new GuzzleHttp\Client;
$client->request('GET', 'https://app.scratcher.io/api/v1/campaigns/:id');
Response:
{
"data": {
"id": 1,
"name": "My Campaign",
"url_slug": "my-campaign",
"url": "https://game.scratcher.io/my-campaign",
"demo_url": "https://game.scratcher.io/my-campaign?dt=foobar",
"start_date": "2018-01-01 12:00:00",
"end_date": "2018-01-02 12:00:00",
"active": false,
"ended": true,
"created_at": "2017-12-30 23:59:00"
}
}
This will show the information for the specified campaign
HTTP Request
GET https://app.scratcher.io/api/v1/campaigns/:id
List all campaigns
Remember to set the headers and access token
<?php
$http = new GuzzleHttp\Client;
$client->request('GET', 'https://app.scratcher.io/api/v1/campaigns');
Response:
{
"data": [
{
"id": 1,
"name": "My Campaign",
"url_slug": "my-campaign",
"url": "https://game.scratcher.io/my-campaign",
"demo_url": "https://game.scratcher.io/my-campaign?dt=foobar",
"start_date": "2018-01-01 12:00:00",
"end_date": "2018-01-02 12:00:00",
"active": false,
"ended": true,
"created_at": "2017-12-30 23:59:00"
}
]
}
This will list all your campaigns ordered by their creation date. This is paginated with 10 campaigns per page.
HTTP Request
GET https://app.scratcher.io/api/v1/campaigns
Query Parameters
Parameter | Required | Default | Description |
---|---|---|---|
page | false | 1 | The page to fetch data from |
query | false | null | Specify this to filter campaigns by name |
Campaign Private Tokens
Campaign private tokens are used to access private campaigns. The tokens have a length of 64 characters.
Create a private token
Remember to set the headers and access token
<?php
$http = new GuzzleHttp\Client;
$client->request('POST', 'https://app.scratcher.io/api/v1/campaigns/:id/private-tokens');
Response:
{
"data": {
"id": 1,
"token": "81f144fcf56cbd32e4e612fc4590aab9bac8141cb833104549f4e0788882fe3e",
"campaign_url": "https://game.scratcher.io/foobar?token=81f144fcf56cbd32e4e612fc4590aab9bac8141cb833104549f4e0788882fe3e",
"created_at": "2017-12-30 23:59:00"
}
}
This will create a new token for accessing the specified campaign. This token is a one-time use which means you should generate a token for each visitor/user/participant.
HTTP Request
POST https://app.scratcher.io/api/v1/campaigns/:id/private-tokens
Error responses
If the campaign is not private, or if the campaign has ended you will receive a 400 response code.
Key | Description |
---|---|
error | The reason for the error |
Campaign Groups
You can retrieve a specific campaign group as well as list all the campaign groups on your account.
The campaign group object
The campaign group object
{
"id": 1337,
"name": "Advent Calendar 2019",
"campaign_ids": [1, 2, 3],
"created_at": "2019-03-15 11:57:34"
}
Attributes
Retrieve a campaign group
Remember to set the headers and access token
<?php
$http = new GuzzleHttp\Client;
$client->request('GET', 'https://app.scratcher.io/api/v1/campaign-groups/:id');
Response:
{
"data": {
"id": 1,
"name": "My Group",
"created_at": "2017-12-30 23:59:00"
}
}
This will show the information for the specified campaign
HTTP Request
GET https://app.scratcher.io/api/v1/campaign-groups/:id
List all campaign groups
Remember to set the headers and access token
<?php
$http = new GuzzleHttp\Client;
$client->request('GET', 'https://app.scratcher.io/api/v1/campaign-groups');
Response:
{
"data": [
{
"id": 1,
"name": "My Group",
"created_at": "2017-12-30 23:59:00"
}
]
}
This will list all your campaign groups ordered by their creation date. This is paginated with 10 campaigns per page.
HTTP Request
GET https://app.scratcher.io/api/v1/campaign-groups
Query Parameters
Parameter | Required | Default | Description |
---|---|---|---|
page | false | 1 | The page to fetch data from |
Leads
The lead object
The lead object
{
"id": 1,
"first_name": "John",
"last_name": "Doe",
"email": "john@example.com",
"phone_number": "88888888",
"ip_address": "127.0.0.1",
"channel": "facebook_post",
"source": "My Quiz Campaign",
"permissions": [
"Terms and Conditions",
"Newsletter"
],
"permission_text": null,
"prize": {
"id": 36,
"name": "50% Discount Code",
"description": "...",
"discount_code": "FREE50JAN",
"webshop_link": "https://webshop.example",
"download_link": "https://download.example/50-percent.pdf"
},
"draw_prize": {
"id": 252,
"name": "$1.000 coupon",
"description": "Lorem ipsum dolor sit amet",
},
"game": [],
"created_at": "2017-12-30 23:59:00",
"custom_fields": [
{
"field_name": "zipcode",
"value": "8800"
}
],
"discount_codes": [
{
"code": "FOOBAR",
"prize_id": 2,
}
]
}
Attributes
The prize that the lead has won
prize.id
Unique identifier for this object
prize.name
The name of the prize
prize.description
Description of the prize
prize.discount_code
The discount code of the prize (only on single-discount code prizes)
prize.webshop_link
The link to the webshop (only on discount code prizes)
prize.download_link
The download link of the prize (only on downloadable prizes)
The draw prize that the lead has won
draw_prize.id
Unique identifier for this object
draw_prize.name
The name of the prize
draw_prize.description
Description of the prize
Any game-specific data for the lead. This currently is only supported on "Quiz" and "Personality Test" campaigns.
An array of all the custom fields of the lead
custom_fields[:index].field_name
The name of the field
custom_fields[:index].value
The value of the field
An array of all the discount codes the lead has won
discount_codes[:index].code
The discount code
discount_codes[:index].prize_id
The unique identifier for the attached prize
List all leads on a campaign
<?php
$http = new GuzzleHttp\Client;
$client->request('GET', 'https://app.scratcher.io/api/v1/campaigns/:id/leads');
Response:
{
"data": [
{
"id": 1,
"first_name": "John",
"last_name": "Doe",
"email": "john@example.com",
"phone_number": "88888888",
"ip_address": "127.0.0.1",
"channel": "facebook_post",
"source": "My Quiz Campaign",
"permissions": [
"Terms and Conditions",
"Newsletter"
],
"permission_text": null,
"prize": {
"id": 1,
"name": "50% Discount Code",
"description": "...",
"discount_code": "FREE50JAN",
"webshop_link": "https://webshop.example",
"download_link": "https://download.example/50-percent.pdf"
},
"draw_prize": null,
"game": [],
"created_at": "2017-12-30 23:59:00",
"custom_fields": [
{
"field_name": "zipcode",
"value": "8800"
}
],
"discount_codes": [
{
"code": "FOOBAR",
"prize_id": 2,
}
]
}
]
}
This will list all the leads on the specified campaign ordered by their creation date. This is paginated with 20 leads per page.
HTTP Request
GET https://app.scratcher.io/api/v1/campaigns/:id/leads
Query Parameters
Parameter | Required | Default | Description |
---|---|---|---|
page | false | 1 | The page to fetch data from |
sort | false | N/A | The column to sort by |
Sorting
You can sort the leads by specifying the sort
query parameter.
The following columns are sortable: id
, created_at
, updated_at
.
If you prefix the column with a -
it is sorted by descending.
List all leads on a campaign group
<?php
$http = new GuzzleHttp\Client;
$client->request('GET', 'https://app.scratcher.io/api/v1/campaign-groups/:id/leads');
Response:
{
"data": [
{
"id": 1,
"first_name": "John",
"last_name": "Doe",
"email": "john@example.com",
"phone_number": "88888888",
"ip_address": "127.0.0.1",
"channel": "facebook_post",
"source": "My Quiz Campaign",
"permissions": [
"Terms and Conditions",
"Newsletter"
],
"permission_text": null,
"prize": {
"id": 1,
"name": "50% Discount Code",
"description": "...",
"discount_code": "FREE50JAN",
"webshop_link": "https://webshop.example",
"download_link": "https://download.example/50-percent.pdf"
},
"draw_prize": null,
"game": [],
"created_at": "2017-12-30 23:59:00",
"custom_fields": [
{
"field_name": "zipcode",
"value": "8800"
}
],
"discount_codes": [
{
"code": "FOOBAR",
"prize_id": 2,
}
]
}
]
}
This will list all the leads on the specified campaign ordered by their creation date. This is paginated with 20 leads per page.
HTTP Request
GET https://app.scratcher.io/api/v1/campaign-groups/:id/leads
You can also get all leads on the pre-registration list by using the following:
GET https://app.scratcher.io/api/v1/campaign-groups/:id/pre-register/leads
Query Parameters
Parameter | Required | Default | Description |
---|---|---|---|
page | false | 1 | The page to fetch data from |
sort | false | N/A | The column to sort by |
Sorting
You can sort the leads by specifying the sort
query parameter.
The following columns are sortable: id
, created_at
, updated_at
.
If you prefix the column with a -
it is sorted by descending.
Pagination
Example of paginated JSON response
{
"data" [],
"links": {
"first": "https://app.scratcher.io/api/v1/{RESOURCE_URL}?page=1",
"last": "https://app.scratcher.io/api/v1/{RESOURCE_URL}?page=5",
"prev": "https://app.scratcher.io/api/v1/{RESOURCE_URL}?page=1",
"next": "https://app.scratcher.io/api/v1/{RESOURCE_URL}?page=3"
},
"meta": {
"current_page": 2,
"from": 21,
"last_page": 5,
"path": "https://app.scratcher.io/api/v1/{RESOURCE_URL}",
"per_page": 20,
"to": 40,
"total": 100
}
}
Most resources are paginated. Every paginated resource contains 2 extra fields in the response. See example to the right.
Links
This contains the links for the first, last, previous and next page.
Meta
This contains meta-information regarding what page you are on, how many entries per page, the total count, etc.
Limits
Rate Limits
Response:
{
"message": "Too Many Attempts."
}
We have a rate limit of 60 requests per minute before you are throttled. If you make a request while throttled you receive a 429 response.
Headers
Name | Description |
---|---|
X-RateLimit-Limit | The limit per minute |
X-RateLimit-Remaining | The amount of remaining attempts before you are throttled |
X-RateLimit-Reset | The unix timestamp for when you can retry |
Retry-After | The amount of seconds until you can retry |
Scopes
The following scopes are available.
Scope | Description |
---|---|
read:campaigns | Allow listing all campaigns |
read:campaign-groups | Allow listing all campaign groups |
read:leads | Allow listing leads on campaigns |
Errors
The scratcher API uses the following error codes:
Error Code | Meaning |
---|---|
400 | Bad Request -- Your request is invalid. |
401 | Unauthorized -- Your API key is wrong. |
403 | Forbidden -- You do not have the scopes required to access this OR you do not have access to this resource. |
404 | Not Found |
405 | Method Not Allowed -- The method you used was invalid. |
410 | Gone -- The requested resource has been removed from our servers. |
429 | Too Many Requests |
500 | Internal Server Error -- We had a problem with our server. Try again later. |
503 | Service Unavailable -- We're temporarily offline for maintenance. Please try again later. |