Profile API

Getting Started

Localytics provides a REST API to store and retrieve Profiles information about your users.

A Profile is a collection of key-value pairs represented in JSON format. Here's an example.

{
  "attributes": {
    "$first_name": "Isa",
    "cats": ["Ofelia", "Mittens", "Spot", "Schrödinger"],
    "age": 30,
    "lucky numbers": [1, 48, -100, 13],
    "birthday": "1983-01-01"
  }
}

Remember, Profiles are scoped to your global organization or to individual apps. You can create global, or org-level, Profiles for each of your app users. Each Profile is uniquely identified by a customer ID, and you can store any number of attributes describing the person (such as name, email, age, location, or birthday).

You can also create app-specific Profiles for each user. App-level Profiles store attributes that are only relevant to a particular app (like high score, items purchased, or favorite baseball team).

The Localytics Profiles API exposes Profiles as a single RESTful resource at:

https://profile.localytics.com/v1/profiles/:customer_id
which accepts the HTTP methods GET, PATCH (or POST), and DELETE.

You can read and write app-scoped Profiles at

https://profile.localytics.com/v1/apps/:app_key/profiles/:customer_id

Here's an example URL with sample values.

https://profile.localytics.com/v1/apps/99009zz0099009z0-z00z90-z009-99z0-zz00-000999zz99/profiles/isa

For convenience, you can retrieve all Profiles for a given customer at: GET https://profile.localytics.com/v1/customers/:customer_id

The following Ruby code snippet illustrates how you can quickly start setting and retrieving profile information for your customers.

# Using Ruby 2.1.2
require 'net/http'
require 'json'

# All REST methods are available at this endpoint:
api_root = "https://profile.localytics.com/v1/profiles"

# Let's call our customer "Isa."  In production, of course, you should not use customer's real names or emails
# to identify them, but instead use a secure non-guessable unique identifier like 47c44727-1c22-4dfd-a901-9d0dcf049c89.
customer_id = "Isa"

# Replace these with your real API key and secret:
API_KEY = "MY_API_KEY"
API_SECRET = "MY_API_SECRET"

uri = URI("#{api_root}/#{customer_id}")

Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|

  # Let's see if a profile for Isa exists:
  get_request = Net::HTTP::Get.new(uri)
  get_request.basic_auth(API_KEY, API_SECRET)

  response = http.request(get_request)

  response.code # 404, because we haven't created this profile yet.

  # Now let's create a profile.  Use PATCH whenever you want to set some profile information.
  # It will create a new record if it doesn't already exist.
  patch_request = Net::HTTP::Patch.new(uri)
  patch_request.basic_auth(API_KEY, API_SECRET)
  patch_request.content_type = "application/json"

  # Set up some arbitrary profile data for Isa
  profile_attributes = {
    :name => "Isa",
    :cats => ["Ofelia", "Mittens", "Spot"],
    :age => 30,
    :"lucky numbers" => [1, 48, -100, 13],
    :birthday => "1983-01-01"
  }

  # The data we want to set must be nested under an "attributes" JSON root node
  patch_request.body = JSON.dump({:attributes => profile_attributes})

  response = http.request(patch_request)

  response.code # 202

  # Now Isa should be there
  response = http.request(get_request)
  response.code # 200
  response.body # {"attributes": {"name": "Isa"...}}

  # We can update and delete Isa's profile attributes:
  updated_attributes = {
    :age => 31,
    :cats => nil # Use null to delete individual attributes
  }
  patch_request.body = JSON.dump({:attributes => updated_attributes})

  http.request(patch_request)
  http.request(get_request) # Isa's age has now been updated and his cats are gone

  # We're done with Isa
  delete_request = Net::HTTP::Delete.new(uri)
  delete_request.basic_auth(API_KEY, API_SECRET)
  http.request(delete_request)
end

Authentication

You need to authenticate with an API key and secret in order to access the Localytics APIs.

API keys are available in Settings.

  1. Navigate to Dashboard > Settings > API Keys.
  2. Copy your Profile API key and secret.
  3. The Profile API supports HTTP Basic authentication using your API key as username and API secret as password. For maximum security, unencrypted HTTP is not supported.

Creating and Updating Profiles

Use the HTTP PATCH method to create or update a profile. There are two available PATCH syntaxes: attributes and changes.

If a profile for the given customer already exists, only the attributes specified in the request body will be modified. Other profile attributes in the same record will not be affected.

Requests must specify either:

  • an attributes object containing values to set or delete, or
  • a changes array containing diffs to apply to the profile

You cannot mix the two syntaxes in the same request.

Successful calls of either syntax return 202 Accepted. If some of the provided assignments or changes are not valid, the response will contain an ignored_changes field, comprising an array of objects describing which changes were ignored, and for what reason.

If the request contains no valid assignments or changes, the API will return 400 Bad Request.

When using the attributes syntax, provide key/value pairs. The special value null is used to delete key/value pairs from the profile.

PATCH https://profile.localytics.com/v1/profiles/Bob
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Content-Type: application/json

{
  "attributes": {
    "$first_name": "Bob",
    "cats": ["Ofelia", "Mittens", "Spot", "Schrödinger"],
    "age": 30,
    "lucky numbers": [1, 48, -100, 13],
    "birthday": "1983-01-01",
    "delete me": null
  }
}

When using the changes syntax, provide an array of diff objects, each specifying an update to a profile attribute. Each diff object takes one of the following forms.

Remove a key/value pair
{"op": "delete", "attr": "foo"}
Set a value
{"op": "assign", "attr": "foo", "value": <some-value>}
Increment/decrement an integer
{"op": "increment", "attr": "foo", "value": <some-integer-value>}
Add values to set
{"op": "set-add", "attr": "foo", "value": <some-values>}
Remove values from set
{"op": "set-remove", "attr": "foo", "value": <some-values>}
PATCH https://profile.localytics.com/v1/profiles/Bob
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Content-Type: application/json

{
  "changes": [
    {"op": "assign",     "attr": "$first_name", "value": "Robert"},
    {"op": "increment",  "attr": "age",  "value": -1},
    {"op": "set-remove", "attr": "cats", "value": ["Spot", "Schrödinger"]}
  ]
}

If the two above updates are applied in order, the resulting profile is below.

{
  "attributes": {
    "$first_name": "Robert",
    "cats": ["Ofelia", "Mittens"],
    "age": 29,
    "lucky numbers": [1, 48, -100, 13],
    "birthday": "1983-01-01",
  }
}

Reading profiles

Use GET to return a JSON representation of a customer's profile. Profile attributes are found under the attributes key in the response.

Localytics also automatically collects and stores profile information about your customers. This information is available under the localytics key in the response.

If the profile does not exist, GET returns 404 Not Found.

Retrieve organization-wide profiles

GET /v1/profiles/:customer_id
GET https://profile.localytics.com/v1/profiles/Isa
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

Retrieve app-scoped profiles

GET /v1/apps/:app_id/profiles/:customer_id
GET https://profile.localytics.com/v1/apps/my_app/profiles/Isa
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

Example Response

200 OK

{
  "attributes": {
    "name": "Isa",
    "cats": ["Ofelia", "Mittens", "Spot", "Schrödinger"],
    "age": 30,
    "lucky numbers": [1, 48, -100, 13],
    "birthday": "1983-01-01"
  },
  "localytics": {
    "attributes": {
      "country": "us",
      "city_name": "Boston",
      "last_session_date": "2015-01-15"
    }
  }
}

Retrieve all profiles for a customer

You can also retrieve all profiles for a customer in a single request at:

GET /v1/customers/:customer_id

Profiles for a customer can be found under the profiles key in the response. Each app-scoped profile will contain an app_id field, containing the app key to which the profile is associated.

GET https://profile.localytics.com/v1/customers/Isa
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

{
  "id": "Isa",
  "profiles": [
    {
      "attributes": {
        "name": "Isa",
        "cats": ["Ofelia", "Mittens", "Spot", "Schrödinger"],
        "age": 30,
        "lucky numbers": [1, 48, -100, 13],
        "birthday": "1983-01-01"
      },
      "localytics": {
        "attributes": {
          "country": "us",
          "city_name": "Boston",
          "last_session_date": "2015-01-15"
        }
      }
    },
    {
      "app_id": "my_app",
      "attributes": {
        "high score": 30,
        "favorite teams": ["Red Sox", "Yankees"]
      },
      "localytics": {
        "attributes": {
          "app_version": "3.1",
          "push_enabled": 1,
          "custom_1": "yes"
        }
      }
    }
  ]
}

Query customers by email address

If you've set email with the special $email attribute, you can find customers by their email address at:

GET /v1/customers?email=yourname@example.com

The response will return all profiles for customers in your organization who match the provided email address. Optionally include the app_ids query param with a comma-separated list of app IDs, indicating app-scoped profiles that you would like returned in the response.

GET https://profile.localytics.com/v1/customers?email=isa@localytics.com
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

{
  "customers": [
    {
      "id": "Isa",
      "profiles": [
        {
          "attributes": {
            "$email": "isa@localytics.com",
            "name": "Isa",
            "cats": ["Ofelia", "Mittens", "Spot", "Schrödinger"],
            "age": 30,
            "lucky numbers": [1, 48, -100, 13],
            "birthday": "1983-01-01"
          },
          "localytics": {
            "attributes": {
              "country": "us",
              "city_name": "Boston",
              "last_session_date": "2015-01-15"
            }
          }
        },
        {
          "app_id": "my_app",
          "attributes": {
            "high score": 30,
            "favorite teams": ["Red Sox", "Yankees"]
          },
          "localytics": {
            "attributes": {
              "app_version": "3.1",
              "push_enabled": 1,
              "custom_1": "yes"
            }
          }
        }
      ]
    }
  ]
}

Deleting profiles

Use DELETE to delete an entire profile.

A successful call returns 204 No Content.

Delete org-level profile

DELETE /v1/profiles/:customer_id

DELETE https://profile.localytics.com/v1/profiles/Robert
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

Delete app-level profile

DELETE /v1/apps/:app_id/profiles/:customer_id

DELETE https://profile.localytics.com/v1/apps/my_app/profiles/Robert
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

Data types and limits

Some restrictions apply to the types of data you can send in attribute keys and values. Attribute keys must be strings no longer than 128 characters. Leading and trailing whitespace will be trimmed.

Attribute keys may not begin with the symbols or punctuation shown below.

! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~

The following data types are accepted as attribute values.

  • String: Strings up to 255 characters long. Leading and trailing whitespace will be trimmed. Empty strings are not allowed.
  • Integer: Positive or negative whole numbers only. Decimal places are truncated.
  • Date: ISO 8601-formatted strings will be parsed and stored as dates in format YYYY-MM-DD
  • Set: Sets, represented as JSON arrays, containing strings or integers. Only one data type is allowed in a set; if multiple data types are mixed in a set, all values in the set will be converted to strings. Duplicate values will be collapsed.

Rate limiting requests

The API additionally enforces two types of rate limits:

  • Per API key: No more than 50,000 requests per minute are allowed for a given API key. Please contact Localytics support if you need higher throughput.
  • Per customer ID: No more than 15 requests per minute for a given customer ID + profile database combination. To avoid hitting this limit, make sure to combine all attribute updates for a given customer profile into a single request.

The API will return a 429 response code when a rate limit is exceeded. You should reduce your rate of requests and retry throttled requests after a minute.

Setting Special Profile IDs via the API

You can upload any attributes to a profile, but there are a few "special" attribute names, like $email, that Localytics recognizes and validates for use in email campaigns and other Marketing features. These "special" attributes are called Special Profile IDs.

The Profiles API recognizes the following Special Profile IDs. All Special Profile IDs must be single string values; sets of multiple values are not allowed.

Special Profile ID
Description
$email
A single valid email address, such as "support@localytics.com".
$full_name
Full name, such as "Isa Cohen"
$first_name
First name, such as "Isa"
$last_name
Last name, such as "Cohen"

Because Special Profile IDs don't contain app-specific information, don't scope Special Profile IDs by app. For example, to set a customer's email and name, make the following PATCH request to the Profiles API.

PATCH https://profile.localytics.com/v1/profiles/Bob
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Content-Type: application/json

{
  "attributes": {
    "$first_name": "Isa",
    "$last_name": "Cohen",
    "$full_name": "Isa Cohen",
    "$email": "support@localytics.com"
  }
}

API names for Auto-Profiles

Auto-Profiles have friendlier, public-facing names for the Localytics Dashboard and internal names that are used to interact with the API. Here's a handy reference list that also includes their data types, in case you need it.

Friendly name Internal name Data type
Last app version app_version string
Last OS version os_version string
Total Sessions (ever) total_sessions integer
First session date birthdate date
Last session date last_session_date date
Push enabled push_enabled boolean
Seconds since last session seconds_since_last_session integer
User type user_type string
Last push opened last_push_opened date
Last inapp message displayed date last_inapp_displayed date
Last city city_name string
Last country country string
Last session date last_session_date date
Last time zone device_timezone string
Language language string
Last email received last_email_delivered date
Email unsubscribed date unsubscribed_at date
Last Modified Country last_modified_country date
Last Modified City last_modified_city date
Last Churned And Returned last_churned_and_returned date
Last Push Disable last_push_disable date