Profile API

Getting Started

Localytics provides a REST API to store and retrieve Profiles information about your users. If you are looking to bulk export and/or import Profiles, please visit Profile Exports or Profile Imports.

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==

End-User Privacy

Localytics provides APIs to help customers build applications that respect an end user's privacy guidance. Two separate privacy APIs are available to manage future data collection (opt-in/out) and to completely delete an end user's data (GDPR customer Right-to-be-Forgotten).

These two APIs address separate privacy concerns and rely on different underlying mechanisms within the SDK. Customers may choose to use either of these APIs but should not attempt to use both APIs within the same application.

Data Collection Opt In/Out

The setOptedOut API controls future data collection on a device. When enabled, no behavioral data will be collected on the device and Places monitoring will be disabled by default. This setting affects all data collection on the device regardless of whether the user has signed into the app.

Refer to the setOptedOut API in the appropriate SDK developer documentation for usage details and sample applications.

Customer Right-to-be-Forgotten

Implementing the GDPR Right-To-Be-Forgotten is supported by the setPrivacyOptedOut API or setting of the application profile privacy_delete attribute. Once a user has requested to be forgotten within an app they will no longer be targeted for personalized messages and all their historical app profile attributes and app data will be deleted from Localytics.

No changes to the application profile attributes will be accepted for forgotten users.

Refer to the setPrivacyOptedOut API in the appropriate SDK developer documentation for usage details and sample applications.

These two APIs available in Localytics SDKs address separate privacy concerns and rely on different underlying mechanisms within the SDK. Customers may choose to use either of these APIs, but should not use both APIs within the same application.

Application Profile privacy_delete Attribute

Some privacy regulations require our customers to delete an end user's data upon request, and many customers do require a server-side method to inform Localytics of users that have requested to have their data deleted. Setting an end user's application profile attribute privacy_delete to 1 initiates a request to be forgotten on behalf of that user. Localytics will then run a back-end process to begin dropping any additional data uploaded from the known individual’s device, and will proceed with deleting all personal data and identifiers to complete the intended Right-to-be-Forgotten request.
Once this attribute is set to 1, Localytics will also delete the identified end user’s application data from Localytics production systems, and the user can no longer be uniquely targeted for messages.

A forgotten user may choose to be remembered again by setting privacy_delete to 0. Data collection will be reinitiated and only data collected after the attribute was reset will be available for message targeting. The privacy_delete attribute is set using the Profile API. Only the values 1 (forget customer) and 0 (start remembering) are accepted for privacy_delete.

The privacy_delete attribute will remain in a forgotten user's profile and can be used for building an audience. Audience export reports may be used to reconcile or verify end-user privacy_delete status. Note that forgotten users will be silently deleted from the audience if the audience is used for message targeting.

While it is possible to use the set privacy_delete directly using the Profile API, it is recommended that the SDK setPrivacyOptedOut API always be used to control this setting from applications. The setPrivacyOptedOut API provides complimentary methods that simplify building GDPR-compliant applications.

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.
  • 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