All requests to do tips must be signed with partner token. Partner token is a string that must be obtained via the following API.
API online documentations: OpenAPI specification, Swagger, Scalar, API docs.
GET /api/v1/partner/<partner-key>/token?user=<user-id>
URL parameter:
<partner-key> is a secret key generated by FeelApp admin via
admin interface. Please contact us to obtain the key.user-id - optional parameter, string, up to 1000 chars long.
If this parameter is specified, requests signed with this key can
be only executed for the given user.
If this parameter is omited, the token can be used to manipulate
any user.Headers:
<partner-key> (This method is recommended over URL parameter) is a secret key generated by FeelApp admin via
admin interface. Please contact us to obtain the key.If the token is exposed to users (e.g. is used with Feel App JavaScript library), then it’s strongly recommended to provide user id parameter, otherwiser this token can be used to send signals to ANY user.
{
partner_token: 'partner-token'
}
The token is valid for 24 hours. Please note that each subsequent request can return a different partner token. Multiple tokens obtained this way can be valid at the same time as long as they are not expired.
For security reason, to avoid partner key exposure we recommend to perform such requests from server side only, not from the client side.
Represents external users (users registered on partners’ websites)
GET /api/v1/user/<user-id>/status?partner_token=<partner-token>
URL parameter
partner_token - partner token previously returned by
/api/v1/partner/<partner-key>/token requestuser-id - performer user id on the partner website, string, up to
1000 chars long.Headers:
partner_token - (This method is recommended over URL parameter) partner token previously returned by
/api/v1/partner/token request{
user_id: ‘user-id’,
authenticated: true | false,
online: true | false
devices:
user_id - performer user id, same as provided in requestauthenticated - true if user is known to FeelApponline - true if user is known and has the performer app runningdevices is a list of devices which are connected to the app
(e.g. ['PEARL', 'ONYX'])rooms is a list of rooms user currently joined. Each room contains
following fields:
GET /api/v1/user/<user-id>/auth?partner_token=<partner-token>
URL parameter
partner_token - partner token previously returned by
/api/v1/partner/<partner-key>/token requestuser-id - performer user id on the partner website, string, up to
1000 chars long.Headers:
partner_token - (This method is recommended over URL parameter) partner token previously returned by
/api/v1/partner/token request{ auth_token: ‘auth-token’ }
This request returns auth token which should be displayed as the QR code and scanned with FeelConnect.
401 NOT AUTHORIZED - partner token is invalid or is not authorized
for the user.GET /api/v1/user/<user-id>/conncode
URL parameter
user-id - performer user id on the partner website, string, up to
1000 chars long.
Headers:partner_token: [token], where [token] is the partner token previously returned by
/api/v1/partner/token request{ connection_code: ‘connection-code’ } This request returns connection code which should be typed in in FeelConnect. Note The token is valid for 1 minute.
401 NOT AUTHORIZED - partner token is invalid or is not authorized
for the user.Partners can be notified about user status change via http callback (web hook call). In order to do that the partner must implement a webhook endpoint web page which will be called by Feel platform each time user status is changed.
This webhook endpoint web page should be published somewhere on the internet and Feel platform should be notified about endpoint URL. This URL will be stored in the Feel platform database. Every time the status of any user has changed, Feel platform will send an HTTP request to the webhook endpoint.
Partners can use following script to submit URL of your webhook endpoint page to Feel platform: https://github.com/dulta/feelapp-api/blob/master/examples/webhook.php
Please download the script, change $PARTNER_KEY variable, upload it to your local web server and open in your browser.
You can also contact us so we change this URL in our database manually.
Each user status change will initiate a POST request to your webhook endpoint page. User status will be provided in POST variables:
user_id - performer user idauthenticated - true if user is has scanned a QR code with Feel app, false otherwiseonline - true if user is known and has the Feel app running, false otherwisedevices is a list of devices which are connected to the app
(e.g. ['PEARL', 'ONYX'])rooms is a list of rooms user currently joined. Each room contains
following fields:
room_id - unique room idread - flag indicating if user can read from this roomwrite - flag indicating if user can write to this roomid - message ID. This field defines message order - a message with lower ID have been
generated earlier than a message with higher ID.Partners can opt for receiving the user status web-hooks post messages with an authorization header in order to enforce end-to-end integrity. The signature headers included in the message by the Feel API are:
Authorization : string with the header parameters used for signing the messages. It mus start with ‘Signature ‘
keyId: identification of the secret key used to sign (i.e partner_key)algorithm: algorithm used to sign the message (i.e.hmac-sha256)headers: headers used to compose the singing string (i.e. date digest)signature : hash of the signature string using the partner_key as keyTo verify the message integrity, the following steps are necessary according IETF HTTP Signatures draft RFC. We will use the following header as an example to illustrate the steps.
'Content-Type': 'application/x-www-form-urlencoded'
'Host': '127.0.0.1:40975'
'Authorization': 'Signature keyId="partner_key",algorithm="hmac-sha256",headers="date digest",signature="F+VUsyOcbpcOCGj9WbrBwG6vp1jseEb/feMv4gpUQuk="'
'Content-Length': '136', (), (), ('Date', u'Wed, 06 Mar 2019 16:34:53 GMT'), ('),
'Accept-Encoding': u'identity'
headers in that order:
>> digest = sha256(message_payload)
>> digest
'Digest': 'SHA-256=pDxRTfF3W7ErElFzkhJ7M3t92luH6X4CLwYDY4o67q4='
>> # construct the string concatenating headers...
>> sts
'date: Wed, 06 Mar 2019 16:34:53 GMT\ndigest: SHA-256=pDxRTfF3W7ErElFzkhJ7M3t92luH6X4CLwYDY4o67q4='
signature string: >> sig = b64decode("F+VUsyOcbpcOCGj9WbrBwG6vp1jseEb/feMv4gpUQuk=")
>> sig
'\x17\xe5T\xb3#\x9cn\x97\x0e\x08h\xfdY\xba\xc1\xc0n\xaf\xa7X\xecxF\xff}\xe3/\xe2\nTB\xe9'
algorithm (hmac-sha256) and the secret partner_key. >> sig == hmac.new(str(partner_key), sts, digestmod=hashlib.sha256).digest()
True
Python example:
# receive incoming request...
# load partner_key ...
import base64
import hashlib
import hmac
# check that there is a authorization header
assert "Authorization" in incoming_request.headers
assert incoming_request.headers["Authorization"].startswith("Signature ")
import pdb; pdb.set_trace()
# check required signature parameters
_, sig_struct = incoming_request.headers["Authorization"].split(" ", 1)
sig_struct = {i.split("=", 1)[0]: i.split("=", 1)[1].strip('"') for i in sig_struct.split(",")}
for field in "keyId", "algorithm", "signature":
assert field in sig_struct
# check hash algorithm
assert sig_struct["algorithm"] == "hmac-sha256"
# get string to sign
headers = sig_struct.get("headers", "date").split(" ")
sts = []
for header in headers:
value = incoming_request.headers[header]
sts.append("{k}: {v}".format(k=header.lower(), v=value))
sts = "\n".join(sts).encode()
# verify signature
sig = base64.b64decode(sig_struct["signature"])
assert sig == hmac.new(str(partner_key), sts, digestmod=hashlib.sha256).digest()
POST /api/v1/user/<user-id>/tip?partner_token=<partner-token>
URL parameters:
user-id - performer user id on the partner websitepartner_token - partner token previously returned by
/api/v1/partner/<partner-key>/token requestHeaders:
partner_token - (This method is recommended over URL parameter) partner token previously returned by
/api/v1/partner/token requestPOST parameters:
sender - username of the person who sent the tip, string (e.g. John Doe)amount - tip amount, string (e.g. 10 coins)duration - tip (vibration) duration in seconds, floating point number (e.g. 2.5)strength - tip (vibration) strength in percents, integer (e.g. 50)strength_increment - (optional) percentage incremental increase in strength for every pair of overlaping tips.timestamp - (required if strength_increment is defined) timestamp in the format 2019-11-18T15:02:44.218ZcustomText - custom text, string. If specified, the mobile app will only show this text,
sender and amount will be ignored and not displayed in the app.pattern - tip pattern, string. Optional parameter. Contains JSON describing tip pattern.
Format: {“time”: signal, …} where - time is floating point number, seconds, mind the quite chars; - signal is 0..4 integer defining vibration strength.light_show - Light show index, string. Optional parameter. It can be any number from 0 to 12. If the parameter is missing, the device will play the Light Show set on the Setting screen for a particular device in the FC3 app.
Map of indexes and Light show names: {“0”: “Starlight”, “1”: “Comet”, “2”: “Blink”, “3”: “Glow”, “4”: “Spin”, “5”: “Spectrum”, “6”: “Unicorn”, “7”: “Flare”, “8”: “Sparkle”, “9”: “Strobe”, “10”: “Supernova”, “11”: “Galaxy”, “12”: “Rainbow”}light_show_primary_color - The primary color for the selected light show, string. Optional parameter. It will be applied only if the light_show equals to 0, 2, 3, or 4. List of possible color names: [‘red’, ‘orange’, ‘yellow’, ‘green’, ‘cyan’, ‘blue’, ‘violet’, ‘magenta’, ‘pink’]light_show_secondary_color - The secondary color for the selected light show, string. Optional parameter. It will be applied only if the light_show equals 0. The list of possible color names is the same as for primary colors: [‘red’, ‘orange’, ‘yellow’, ‘green’, ‘cyan’, ‘blue’, ‘violet’, ‘magenta’, ‘pink’]It possible to make the vibration ot the tip to be incrementally increasead by a percentage of is strength value by defining strength_increment and timestamp in the POST paramaters. The increment takes place when the actual tip timeframe overlaps with the previous tip time frame until the accumualted strength adds up to 100.
Example:
duration: 5, strength : 50, incremental_strength: 20 , timestamp: ‘2019-11-18T15:02:44.218Z’} ==> actual strength= 50duration: 5, strength : 50, incremental_strength: 20 , timestamp: ‘2019-11-18T15:02:46.301Z’} ==> actual strength = 60 (50 + 10)duration: 5, strength : 50, incremental_strength: 20 , timestamp: ‘2019-11-18T15:02:51.120Z’} ==> actual strength = 72 (60 + 12)404 NOT FOUND - user is offline or is not known to the FeelApp system.
You should use /api/v1/user/<user-id>/status to see the reason
why the tip cannot be sent.401 NOT AUTHORIZED - partner token is invalid or is not authorized
for the user.400 'message': 'timestamp parameter required when 'strength_increment is used'GET /api/v1/user/<user-id>/realtime?partner_token=<partner-token>
URL parameters:
user-id - performer user id on the partner websitepartner_token - partner token previously returned by
/api/v1/partner/<partner-key>/token requestHeaders:
partner_token - (This method is recommended over URL parameter) partner token previously returned by
/api/v1/partner/token request{ realtime_resource_id: ‘realtime-resource-id’ }
This request returns the realtime resource id which should be used with FellMe JavaScript SDK.
404 NOT FOUND - user is not known to the FeelApp system.401 NOT AUTHORIZED - partner token is invalid or is not authorized
for the user.POST /api/v1/room/<room-id>/users?partner_token=<partner-token>
User cannot be added to more than one room at the same time. If the user has already joined another room, this call will return error.
URL parameters:
partner_token - partner token previously returned by
/api/v1/partner/<partner-key>/token requestroom-id - room id to add user to. If room does not exist, it will
be created.Headers:
partner_token - (This method is recommended over URL parameter) partner token previously returned by
/api/v1/partner/token requestPOST parameters:
user - user id on the partner websiteread - 0 or 1, indicating if user can read data from the roomwrite - 0 or 1, indicating if user can write data to the roomReturns {} in case of success
404 NOT FOUND - user is not known to the FeelApp system.401 NOT AUTHORIZED - partner token is invalid or is not authorized
for the user.409 CONFLICT - user is already in other room. Please remove user from
that room first.DELETE /api/v1/room/<room-id>/users/<user-id>?partner_token=<partner-token>
URL parameters:
partner_token - partner token previously returned by
/api/v1/partner/<partner-key>/token requestuser-id - user id on the partner websiteHeaders:
partner_token - (This method is recommended over URL parameter) partner token previously returned by
/api/v1/partner/token requestReturns {} in case of success
404 NOT FOUND - user is not known to the FeelApp system or not in the room.401 NOT AUTHORIZED - partner token is invalid or is not authorized
for the user.POST /api/v1/user/<user-id>/webpage?partner_token=<partner-token>
URL parameters:
partner_token - partner token previously returned by
/api/v1/partner/<partner-key>/token requestuser-id - user id on the partner websiteHeaders:
partner_token - (This method is recommended over URL parameter) partner token previously returned by
/api/v1/partner/token requestPOST parameters:
title - string, title of a new webpagecategory - string, category of a new webpageurl - string, url of a new webpageReturns {} in case of success
401 NOT AUTHORIZED - partner token is invalid or is not authorized
for the user.404 NOT FOUND - user is not known to the FeelApp system409 CONFLICT - page with this URL already existsDELETE /api/v1/user/<user-id>/webpage?partner_token=<partner-token>
URL parameters:
partner_token - partner token previously returned by
/api/v1/partner/<partner-key>/token requestuser-id - user id on the partner websiteHeaders:
partner_token - (This method is recommended over URL parameter) partner token previously returned by
/api/v1/partner/token requestPOST parameters:
url - url of the webpage to deleteReturns {} in case of success
404 NOT FOUND - user is not known to the FeelApp system or doesn’t have
a webpage with this URL401 NOT AUTHORIZED - partner token is invalid or is not authorized
for the user.GET /api/v1/rooms_with_users?partner_token=<partner-token>
URL parameters:
partner_token - partner token previously returned by
/api/v1/partner/<partner-key>/token requestHeaders:
partner_token - (This method is recommended over URL parameter) partner token previously returned by
/api/v1/partner/token request