NAV Navbar
cURL Ruby JavaScript

Introduction

Welcome to the Leevia API!

You can use Leevia API to access various functionality of Leevia platform for online contest.

In this documentation you will find information and examples on how to authenticate and use Leevia APIs. We provide examples for cURL, Ruby, and JavaScript, but you can use the language you prefer to make API calls, as long as you language allows you to make standard HTTP requests.

You can view code examples in the dark area to the right, and you can switch the programming language of the examples with the tabs in the top right.

Version

This is the documentation for API version 1.0

Last updated 2018-12-10

Authentication

Every request to an API endpoint must be authenticated. Authentication is performed by a JWT token which must be supplied as an HTTP header of the request. The token http header is in the format: Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhY2NvdW50X2lkIjyxLCJleHAiOjE1Mzg3NDI5NjgsImlzc7I6IkxlZXZpYSBhcGkifQ.dE4M1UKC4yFBq3SvlruJieqi_vBQB6qy1DjYyDGjptA

To obtain this JWT token you first need to sign in to the API with your api_key and api_secret pair. You will find these keys in the API page of your contest.

Therefore authentication is performed in two steps:

  1. Obtain the JWT token using api_key and api_secret
  2. Call the desired endpoint providing the JWT token obtained

Obtain the JWT token

To Obtain the JWT token

require 'net/http'
require 'openssl'

uri = URI("https://app.leevia.com/api/v1/campaigns/#{CAMPAIGN_ID}/authenticate")
request = Net::HTTP::Get.new(uri)
request['Accept'] = 'application/vnd.leevia.api.v1+json'
request['Content-Type'] = 'application/json'
request['App-Key'] = KEY
timestamp = Time.now.to_i
request['Timestamp'] = timestamp
request['Signature'] = OpenSSL::HMAC.hexdigest('sha256', SECRET, "#{KEY}.#{timestamp}")

result = Net::HTTP.start(uri.hostname, uri.port) do |http|
  http.request(request)
end
result['Authorization']
timestamp=$(date +%s)
message="KEY.$timestamp"
signature=$(echo -n $message | openssl dgst -sha256 -hmac SECRET -binary | xxd -p -c 256)

curl -I --request GET \
  --url https://app.leevia.com/api/v1/campaigns/CAMPAIGN_ID/authenticate \
  --header 'Accept: application/vnd.leevia.api.v1+json' \
  --header 'App-Key: KEY' \
  --header 'Content-Type: application/json' \
  --header "Signature: $signature" \
  --header "Timestamp: $timestamp"| grep Authorization | sed -e s/Authorization:[[:space:]]//
timestamp = + new Date();
message = KEY + "." + timestamp;
signature = CryptoJS.HmacSHA256(message, SECRET).toString(CryptoJS.enc.Hex);

var request = new XMLHttpRequest();
request.open("GET", "https://app.leevia.com/api/v1/campaigns/CAMPAIGN_ID/authenticate", false);
request.setRequestHeader('Accept', 'application/vnd.leevia.api.v1+json');
request.setRequestHeader('Content-Type', 'application/json');
request.setRequestHeader('App-Key', KEY);
request.setRequestHeader('Timestamp', timestamp);
request.setRequestHeader('Signature', signature);
request.send(null);

console.log(request.getResponseHeader("authorization"));

Make sure to replace KEY with your API key.
Make sure to replace SECRET with your API Secret.
Make sure to replace CAMPAIGN_ID with the id of your campaign/contest.

In this section we describe how to obtain the JWT token that can be used to authenticate API calls.

A valid request must provide 3 headers: App-Key, Timestamp, Signature. Signature is a SHA256 HMAC hexdigest of the string App-Key.Timestamp

Headers

Header Description Example
App-Key this is your api_key TSOePKXvYHQ4fUu8Lv-DePB2a-o
Timestamp a timestamp in a format like %Y-%m-%d %H:%M:%S %Z or integers 2018-10-08 12:29:16 +0200 or 1538994556
Signature SHA256 HMAC digest of the string App-Key.Timestamp, How to generate digest in different languages 99a7f67ea1f8b2beb488de470dd0e541fb1c0a70f7741dca0dffea8bdafb2d24

Signature

To verify if you are creating correct signature you can use the following input to test your algorithm:

timestamp = 1234
key = "my_app_key"
secret = "my_super_secret_key"

which means that "message" will be my_app_key.1234. And your signature must be equal to 90f5df1c0df13ba3701bc21566e4a529720939b7f12b9a60be1d611727a09d0c

Response

Example response's HTTP Headers

HTTP/1.1 204 No Content
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhY2NvdW50X2lkIjoxLCJleHAiOjE1MzkwOTY5NTIsImlzcyI6IkxlZXZpYSBhcGkifQ.IkuNktOM5gFZIdnvGzdz4q4szocJ7AZGiZn7v7iPrvI
x-expires: 1539096952

When the request succeeds you get an empty response with status code 204 (No Content). You will find the JWT Token in the Authorization response header.

There will be also present an header x-expires that contains a timestamp in which the token will expires and hence it would not be possible to use this token anymore.

Tokens expire after one day they have been issued.

Headers

Any request made to the Leevia API must include two specific headers: Accept and Content-Type. These are used to determine the version of the API and the format of the request's body.

Header Value
Accept application/vnd.leevia.api.v1+json
Content-Type application/json

Instant Win

Instant Win is a family of contest types. An instant win could be Rush and Win, Insta Win, Coupon or Giveaway, which differ for the way prizes are assigned.

You can find more information about Instant Win family here.

Register Participant

To register a new Participant

require 'net/http'
require 'openssl'
require 'json'

uri = URI("https://app.leevia.com/api/v1/campaigns/instant_wins/#{CAMPAIGN_ID}/participants")
request = Net::HTTP::Post.new(uri)
request['Accept'] = 'application/vnd.leevia.api.v1+json'
request['Content-Type'] = 'application/json'
request['Authorization'] = 'Bearer JWT_TOKEN'

participant = {
  first_name: "John",
  last_name: "Doe",
  email: "john.doe@leevia.com",
  acceptances: {rules: true, newsletter: false},
  custom_data: {
    date_of_birth: {hashed_date:{dd:"18", mm:"05", yyyy:"1971"}},
    a_custom_field: "some text"
  }
}

request.body = participant.to_json

result = Net::HTTP.start(uri.hostname, uri.port) do |http|
  http.request(request)
end
result.body
curl --request POST \
  --url https://app.leevia.com/api/v1/campaigns/instant_wins/CAMPAIGN_ID/participants \
  --header 'Accept: application/vnd.leevia.api.v1+json' \
  --header 'Authorization: Bearer JWT_TOKEN' \
  --header 'Content-Type: application/json' \
  --form first_name=John \
  --form last_name=Doe \
  --form email=john.doe@leevia.com \
  --form 'acceptances={ "rules": "true",
   "newsletter" : "false"}' \
   --form 'custom_data={"date_of_birth":{"hashed_date":{"dd":"18","mm":"05","yyyy":"1971"}}, "a_custom_field": "some text"}'
var request = new XMLHttpRequest();
request.open("POST", "https://app.leevia.com/api/v1/campaigns/instant_wins/CAMPAIGN_ID/participants", false);
request.setRequestHeader('Accept', 'application/vnd.leevia.api.v1+json');
request.setRequestHeader('Content-Type', 'application/json');
request.setRequestHeader('Authorization', 'Bearer JWT_TOKEN');

var participant = {
  "first_name": "John",
  "last_name": "Doe",
  "email": "john.doe@leevia.com",
  "acceptances": {"rules": true, "newsletter": false},
  "custom_data": {
    "date_of_birth": {"hashed_date":{"dd":"18", "mm":"05", "yyyy":"1971"}},
    "a_custom_field": "some text"
  }
};

request.send(JSON.stringify(participant));

console.log(request.responseText);

Make sure to replace CAMPAIGN_ID with the id of your campaign/contest.
Make sure to replace JWT_TOKEN with your JWT token.

A participant is a person who participate to an Instant Win contest. A participant must provide First Name, Last Name, Email and other fields depending on the contest setup.

HTTP Request

POST https://app.leevia.com/api/v1/campaigns/instant_wins/CAMPAIGN_ID/participants

CAMPAIGN_ID is the id of your contest.

Fields

Field Type Description Example
first_name String First Name of the participant Alice
last_name String Last Name of the participant Wonderland
email String Email of the participant alice.wonderland@leevia.com
acceptances Object An hash containing rules and newsletter with boolean value (rules must be true) {"rules": true, "newsletter": false}
custom_data Object An hash containing any other field required by the contest {"pet": "bunny"}

acceptances can contain additional custom fields. For more information on the type and format of various fields see the specific section: Privacy Acceptances

custom_data must contain all the mandatory additional field that were specified during contest creation. For more information on the type and format of various fields see the specific section: Additional User Data

Response

Example of a successful response

{
  "id": 11,
  "email": "john.doe@leevia.com",
  "created_at": "2018-10-02T12:25:50.380+02:00",
  "campaign_id": 80,
  "is_winner": false,
  "coupon_code": null,
  "prize_id": 1
}

Example of an error response

{
  "email": "john.doe-leevia.com",
  "campaign_id": 80,
  "is_winner": false,
  "coupon_code": null,
  "prize_id": 1,
  "errors": {
      "email": [
        "is invalid"
      ],
      "rules": [
        "Accept the terms to participate"
      ]
  }
}

The response will be a JSON object.
In case of a successful response the JSON will contain information about the participant created.
When the request fails the JSON response will list all the errors with their explanation.

Additional User Data

When creating or editing a contest it is possible to specify multiple additional user data that a user needs to provide to participate to the contest.
In this section we explain how to communicate these data through Leevia API.

An additional user data can be marked as mandatory or not. When it is mandatory you must provide it when creating a participant through API otherwise the request will not be accepted.

Additional user data must be sent in the field custom_data when registering a participant

Pre-configured fields

Example of a JSON containing multiple pre-configured additional user data

{
  "first_name":"John",
  "last_name":"Doe",
  "email":"john.doe@leevia.com",
  "acceptances": {
    "rules":true,
    "newsletter":false
  },
  "custom_data": {
    "gender": "M",
    "date_of_birth": { "hashed_date": {"dd":"18","mm":"05","yyyy":"1971"} },
    "phone": 123456789,
    "city": "Milano",
    "province": "MI",
    "zip_code": "20156",
    "occupation": "Student"
  }
}

Additional user data are inside the field custom_data

Leevia provides some pre-configured fields that you can enable. These are:

Field Type Description Example Value
gender String a gender type M/F "gender": "M" or "gender": "F"
date_of_birth Object a date "date_of_birth": {"hashed_date":{"dd":"28", "mm":"05", "yyyy":"1989"}}
phone Number a phone number "phone": 3458921863525
city String a city name "city": "Milano"
province String a province name or identifier "province": "MI"
zip_code String a postal address idetifier "zip_code": "20152"
occupation String a profession "occupation": "Software Developer"

Custom fields

Example of a JSON containing multiple custom additional user data

{
  "first_name":"John",
  "last_name":"Doe",
  "email":"john.doe@leevia.com",
  "acceptances": {
    "rules":true,
    "newsletter":false
  },
  "custom_data": {
    "custom_text": "Lorem ipsum dolor sit amet",
    "custom_text_area": "Lorem ipsum dolor sit amet, consectetur adipiscing elit ...",
    "custom_numeric": 123,
    "custom_generic_date": "2018-10-01",
    "custom_date_of_birth": {"hashed_date":{"dd":"19", "mm":"05", "yyyy":"1988"}},
    "custom_time": "20:15",
    "custom_dropdown": "answer",
    "custom_multiple_choice": "choice1",
    "custom_search": "searching"
  },
  "custom_file_field": "the_file"
}

In addition to the Pre-configured fields it is also possible to add completely custom fields. When creating a custom fields you need to choose type and label.

type will be used to specify the value type.

label will be used to identify your custom field, thus if you have a custom field with label "My Custom Field" you will need to pass to the API something like "my_custom_field": "my value". You can see the identifier of your custom field in the "API" page of your contest.

When creating custom fields from the backoffice you can choose different types of input, these types are converted in JSON format like in the following table:

Input Type Field Type Example Value
Text String "my_custom_field": "Lorem ipsum dolor sit amet"
Text Area String "my_custom_field": "Lorem Ipsum faucibus purus in massa tempor"
Numeric Number "my_custom_field": 123
Generic Date String "my_custom_field": "2018-10-01"
Date of Birth Object "my_custom_field": {"hashed_date":{"dd":"28", "mm":"05", "yyyy":"1989"}}
Time String "my_custom_field": "10:56"
Dropdown String "my_custom_field": "Lorem"
Multiple Choice String "my_custom_field": "Ipsum"
Search String "my_custom_field": "dolor"
File Binary "my_custom_field": BINARY_FILE

Example of a file uploading using Ruby and rest-client gem

require 'rest-client'

response = RestClient.post( "https://app.leevia.com/api/v1/campaigns/instant_wins/#{CAMPAIGN_ID}/participants" ,
  {
    first_name: "John",
    last_name: "Doe",
    email: "john.doe@leevia.com",
    acceptances: {rules: true, newsletter: false},
    custom_data: {
      phone: 1234
    },
    file_field: File.new('FILE_PATH')
  },
  {
    "Accept": 'application/vnd.leevia.api.v1+json',
    "Authorization": 'Bearer JWT_TOKEN'
  }
)

puts response.code
puts response.body

Make sure to replace CAMPAIGN_ID with the id of your campaign/contest.
Make sure to replace JWT_TOKEN with your JWT token.
Make sure to replace FILE_PATH with your file.

Privacy Acceptances

Example of a JSON containing a custom privacy acceptance

{
  "first_name":"John",
  "last_name":"Doe",
  "email":"john.doe@leevia.com",
  "acceptances": {
    "rules":true,
    "newsletter":false,
    "a_custom_acceptance":true,
  },
  "custom_data": {
    "gender": "M"
  }
}

Additional acceptances are inside the field acceptances

When creating or editing a contest it is possible to specify multiple acceptances that a user needs to accept to participate to the contest.
In this section we explain how to communicate these data through Leevia API.

By default Leevia provides two fields: rules and newsletter.

Field Type Description Example Value
rules Boolean Privacy policy for the contest. must be true true
newsletter Boolean Acceptances to receive newsletter communications true/false

When more additional custom privacy acceptances are added, you can see their identifier in the "API" page of your contest. You need to pass this identifier in the api call along with a true/false value.

Errors

The Leevia API may return the following error codes:

Error Code Meaning
400 Bad Request -- Your request is invalid.
401 Unauthorized -- You are not authorized. Ensure validity of token, keys or campaign_id
403 Forbidden -- You are not authorized. Ensure validity of token, keys or campaign_id
404 Not Found -- The requested resource could not be found.
422 Unprocessable Entity -- The request contains invalid parameters and the resource can not be read/write.
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.