Article sections

    API Overview

    We use a RESTful API, in which all endpoints are prefixed with the API version and a unique hash identifying your shop.

    http://api.reveal.omniconvert.com/v1/s/shpdmo/...

    The v1​ part indicated you’re using the version 1 of the API, while the shpdmo​ represents the unique alphanumeric hash identifying your shop. However, the login endpoint does not contain this unique, as it is performed outside a shop context.

    API Authentication

    Our API is secured using JWT token, so before anything else, will first need to authenticate:

    POST http://api.reveal.omniconvert.com/v1/login
    Body: {
      "username": "your_username",
      "key": "your_api_key"
    }
    Headers: Content-type: application/json

    As a response, you will receive something similar to:

    {
        "code": 200,
        "expire": "2019-06-03T08:05:34Z",     
        "token": "K0FIc0FJZy1hb...K0FDSS10eXBlK0FDSTorQUNJQUlnQjlBQWcg"
    }

    The token expires after 1 hour and it must be used in all subsequent API requests.

    Customer RFM

    Availability – When to download

    The files are available only after the Onboarding process is finished, and are refreshed daily, when the daily sequence runs. If you want to know exactly when the daily sequence is done, check the Webhooks section below.

    Endpoints

    To fetch the complete list of customers with their associated RFM information you can call:

    • GET http://api.reveal.omniconvert.com/v1/s/shpdmo/rfm/download/customers.csv
    • GET http://api.reveal.omniconvert.com/v1/s/shpdmo/rfm/download/customers.json

    To fetch only the list of customers with recently switched RFM Groups or changed RFM Scores, also with their associated RFM information you can call:

    • GET http://api.reveal.omniconvert.com/v1/s/shpdmo/rfm/download/customers_diff.csv
    • GET http://api.reveal.omniconvert.com/v1/s/shpdmo/rfm/download/customers_diff.json

    What “recently” means can be configure from Settings > Export Settings > RFM Customer Difference Window

    Headers: Authorization:"Bearer token here"

    The shpdmo part of the URL must be substituted with your shop unique ID, which you can find in the URL of your Reveal Dashboard.

    Customer data structure – export

    Attribute Type Limits Description
    customer_eid string 255 The identifier you have defined for the customer
    email string 255 The email of the customer
    first_name string 255 First name
    last_name string 255 Last name
    rfm_score string 3 3-digit score
    rfm_group_id int Ther RFM Group id
    rfm_group_name string 255 The name of the RFM Group
    {
        "customers_rfm": [
            {
                "custom_attributes": null,
                "customer_eid": "1894",
                "customer_email": "[email protected]",
                "customer_first_name": "Horace",
                "customer_last_name": "Kshlerin",
                "profit": null,
                "revenue": null,
                "rfm_group_id": null,
                "rfm_group_name": null,
                "rfm_score": ""
            },
            {
                "custom_attributes": null,
                "customer_eid": "1916",
                "customer_email": "[email protected]",
                "customer_first_name": "Coy",
                "customer_last_name": "Cummerata",
                "profit": 27.8219,
                "revenue": 140.08,
                "rfm_group_id": 8,
                "rfm_group_name": "Breakup",
                "rfm_score": "112"
            },
    }

    Customers with rfm_group_id ​and rfm_group_name containing ​null values must also be taken into account. They placed an order, but then canceled it, so they are not eligible for RFM segmentation. The RFM score and segmentation must be updated (removed) for them.

    NPS Invitations

    Availability – When to download

    The files are available only after the daily sequence. The files are regenerated daily, after the daily sequence runs and contains only the new NPSInvitations that should be sent.
    If no new NPSInvitation was generated since the last daily sequence, the file will contain only the CSV header or a JSON with an empty nps_invitations_rfm object  . If you want to know exactly when the daily sequence is done, check the Webhooks section below.

    Endpoints

    To fetch the list of daily generated NPS Invitations (the list can also be empty if no NPS Invitation could be generated for that day, say no new orders or no one passed the capping rules):

    • GET
      http://api.reveal.omniconvert.com/v1/s/shpdmo/nps/download/daily_invitations.csv
    • GET
      http://api.reveal.omniconvert.com/v1/s/shpdmo/nps/download/daily_invitations.json
     Headers: Authorization: "Bearer token here"

    The shpdmo part of the URL must be substituted with your shop unique ID, which you can find in the URL of your Reveal Dashboard.

    NPS Invitation data structure – export

    Column Type Description
    nps_unique string The identifier of the NPS Invitation; just in case you want to mark it as sent through API
    customer_eid string The identifier you have defined for the customer
    customer_email string The customer email
    customer_first_name string
    customer_last_name string
    status string The status of the invitation:
    to_send,
    not_sent,
    sent,
    consumed,
    expired.
    send_until string DateTime in format YYYY-MM-dd HH:mm:ss
    nps_open_link string The link that should be added in email as a “tracking” pixel, in order to measure the email open rate
    nps_link string The link of the NPS
    nps_link_0 string The link of the NPS with prefilled overall score = 0; to use in email in grid
    nps_link_1 string The link of the NPS with prefilled overall score = 1; to use in email in grid
    nps_link_10 string The link of the NPS with prefilled overall score = 10; to use in email in grid
    nps_list_id int If is part of an NPS Invitations List
    rfm_score string The RFM score of the customer for the moment when he placed the order (that order included)
    rfm_group_id int The RFM Group Id of the customer for the moment when he placed the order (that order included)
    rfm_group_name string The RFM Group name of the customer for the moment when he placed the order (that order included)

    If no daily NPS Invitations were generated, the csv will contain solely the header row, while the json will contain an empty array within the “nps_invitations_rfm” field ({"nps_invitations_rfm":[]}).

    NPS Invitation API methods

    Create & Delete

    These methods are not immplemented, since they have no real use. The NPS Invitation is created automatically and cannot be deleted.

    Mark as sent

    Method: POST /nps-invitations/{nps_invitation_unique}/mark-sent
    Body: empty
    Response: 200 with nps_invitation object, or error status with error message

    This will also update the NPS Invitation List to “mark as sent” if this was the last unsent NPS
    Invitation in the list, so the data will be consistent.

    Show

    Method: GET /nps-invitations/{nps_invitation_unique}
    Body: empty
    Response: 200 with nps_invitation object, or error status with error message

    List

    Method: GET /nps-invitations?filters&page
    Body: empty
    Response: 200 with page object, or error status with error message

    You can filter the nps_invitations by:

    Attribute Type Description
    status string One of:
    to_send,
    not_sent,
    sent,
    consumed,
    expired.

    One thing to notice, if you don’t use the “mark as sent” feature, a NPS Invitation can transition from to_send in not_sent then in consumed.
    customer_eid string The unique identifier you have defined for the customer
    customer_email string Customer email
    order_eid string The unique identifier you have defined for the order
    nps_list int The id of the NPS Invitation List the invitations were included in.
    rfm_score string
    rfm_group int
    Invitation data structure – API
    Attribute Type Description
    id int The id of the invitation
    unique string The unique generated for this invitation
    link string The link of the NPS; you can add to it &q=X for prefilling the overall score with X, where X is between 0-10
    customer_eid string The unique identifier you have defined for the customer
    customer_email string Customer email
    customer_first_name string
    customer_last_name string
    order_eid string The unique identifier you have defined for the order, you may need it for your internal tracking
    nps_list int
    rfm_score string
    rfm_group_id int
    send_until datetime
    sent_at
    consumed_at
    status string The status of the invitation:
    to_send,
    not_sent,
    sent,
    consumed,
    expired.

    You should email the invitation only when the status is “to_send”, otherwise you risk sending it twice, too late or even after it was consumed. Also you should use the “mark as sent” feature for the invitations you sent, otherwise you will risk seeing again in the “to_send” status and send them twice or more.

    Export

    Method: GET /nps/export/invitations.{format}?filter
    Body: empty
    Response: 200 status, or error status
    CSV or JSON file with structure described at the beginning of chapter.
    The returned list is composed of all to_send NPS Invitations (unless otherwise specified in filter).
    Note the list_id field, which tells you if that invitation is part of an NPS Invitation List, which probably you downloaded before and maybe already sent it. We recommend to use one of the 2 variants, individual invites or lists to avoid double sends or skipping some emails.
    The export data structure is the one in NPS Invitation data structure – export section above

    Bulk Mark as sent

    Method: POST /bulk/nps-invitations/mark-sent
    Body:

    {
        "nps_invitations": [
            nps_invitation_unique,
            nps_invitation_unique,
         ]
    }

    Response: 204 status, or error status with error message

    The data structure supports multiple nps_invitations uniques, defined in the array under “nps_invitations” key. For a better tracking it is your responsibility to perform this call for all the NPSInvitations for which the email was sent. You can also use the NPSInvitationList “mark as sent” feature.

    NPS Invitation List data structure

    Attribute Type Description
    id int The id of the invitation list
    status string The NPS Invitation List status, one of:
    to_send,
    not_sent,
    sent.

    Even if the status is to_send or not_sent, there might be some NPS Invitations in it that are sent, because they were “marked as sent” individually, and also some other NPS Invitations that are in fact sent but with status not updated. So it’s a good idea to use the “mark as sent” feature. If the status is sent, it means all the invitations are also “marked as sent”, but it is in your job to actually send them, we just want to help you track the progress.
    send_until datetime
    sent_at datetime
    nps_invitations array Array with nps_invitation objects, but only with unique and status field.

    NPS Invitation List API methods

    Create & Delete

    These methods have no use. The NPS Invitation List is created automatically and cannot be deleted.

    Mark as sent

    Method: POST
    /nps-invitations-lists/{nps_invitations_list_id}/mark-sent

    Body: empty
    Response: 200 with nps_invitations_list object, or error status with error message

    This will update all the NPS Invitations in the list to “mark as sent” so the data will be consistent. If the status is already “consumed”, it will return a 409.

    Show

    Method: GET /nps-invitations-lists/{nps_invitations_list_id}
    Body: empty
    Response: 200 with nps_invitations_list object, or error status with error message

    List

    Method: GET /nps-invitations-lists?filters&page
    Body: empty
    Response: 200 with page object, or error status with error message

    You can use this instead of daily feed, he will get here all the lists even if they were generated from GUI. Then use the nps_invitations API method list to get the actual invitations.

    You can filter the nps_invitations_lists by:

    Attribute Type Description
    status string One of:
    to_send,
    not_sent,
    sent,

    Remember to use the “mark as sent” feature for an accurate response

    Bulk Mark as sent

    Method: POST /bulk/nps-invitations-lists/mark-sent
    Body:

     {
        "nps_invitations_lists": [
            nps_invitations_list_id,
            nps_invitations_list_id,
        ]
    } 

    Response: 204 status, or error status with error message

    Webhooks

    Implementing webhooks allows you to use the most fresh information from Reveal.

    If you need to know when the daily sequence is finished, so you can start download the RFM customers or the NPS Invitations, you can subscribe to a webhook and Reveal will call your endpoint to notify that the information was updated.

    Endpoints

    POST http://api.reveal.omniconvert.com/v1/s/shpdmo/webhooks 
    Headers: Authorization:"Bearer token here"
    Body: {
    	"url": "http://yourdomain.com/any/path/you/want",
    	"events": [
    		"job.notification_sequence_daily.done",
    		"job.notification_sequence_daily.exited"
    	],
    	"secret": “a secret string max length 64",
    	"description": "I want to know when daily sequence is finished"
    }

    Security

    During the creation process of the webhook, Reveal will call the endpoint on the URL provided.

    If Reveal does not receive a 200 OK and also the expected response content, the webhook creation will fail. This way, Reveal is assured that the webhooks will deliver you the needed information.

    Below, details are provided on how you can check the call is actually from Reveal and also how to compose the response.

    Reveal sends these headers in the webhook call:

    X-Reveal-Signature: t=timestamp,v1=hmac_string
    X-Reveal-Shop-Unique: shpdmo
    X-Reveal-Event-Name: job.notification_sequence_daily.done
    X-Reveal-Test: true

    X-Reveal-Shop-Unique – states the shop fow which the webhook was called; useful when handling multiple shops
    X-Reveal-Event-Name – contains the event which caused the webhook to trigger; useful in case you registered for multiple events on the same webhook;
    If the event is job.notification_sequence_daily.done, the daily sequence finished with success, so you can download the RFM customers and the NPSInvitations
    If the event is job.notification_sequence_daily.exited, the daily sequence encountered errors, and you should not download the files, because they were not updated, and thus, are not fresh
    X-Reveal-Test – signals if the call is just a test call, such as the one that is triggered when you create the webhook on Reveal
    If the value is true, you still have to return 200 OK and the expected content, but you shouldn’t do anything on your side, because no actual event happened
    X-Reveal-Signature – the security header;
    The Unix timestamp of the request is included within the t parameter; you can check this not to be too old, to prevent replay attacks; we recommend to check the timestamp to be somewhere now() +/- 30 seconds (keep in mind Reveal servers and your server may not have the exact same time, so adjust this interval as you need).
    The next parameter is the version of the Webhook API, which can only be v1 for now.
    The value of the above parameter is the actual security hash, hmac_string.

    Computing the hmac

    Concatenate the timestamp from header with the dot character and with the request body
    signedPayload = "timestamp.requestBody"

    Compute the SHA256 hmac with the secret you used in the Webhook create request
    expectedHmac = hash_hmac('sha256', signedPayload, secret);

    Compare the hmac_string from header with the expected hmac
    hash_equals(hmac_string, expectedHmac)

    If the hashes are not equal, don’t trust the request! It’s not originating from Reveal.

    If the hashes are equal you know the request is a valid Reveal Webhook request, so you need to compute the result Reveal is expecting to.

    Building the response

    First, you have to JSON-decode the requestBody; you will find an object with 2 keys 

    {
        "_hook_id": "hook_id_string",
        "_payload": payloadObject
    } 

    Get the current Unix timestamp and create a new JSON object like this:

    obj = {
        "_hook_id": "hook_id_string",
        "timestamp": currentTimestamp,
    }

    Concatenate the current timestamp with the dot character and with the obj
    signedPayload = "currentTimestamp.obj"

    Compute the SHA256 hmac with the secret you used in the Webhook create request
    hmac = hash_hmac('sha256', signedPayload, secret);

    Concatenate the current timestamp with the pipe character and with the obtained hmac
    response = "now|hmac"

    Return a 200 OK response with the above response as the content

    If you need any assistance in implementing the Data Export, we’re more than happy to help. 🙂