
LifeScope Data Schema
LifeScope data is broken down into several different interrelated objects:
- Events (actions the user took)
- Content (digital objects such as videos, photos, receipts, text, etc.)
- Contacts (entities a user interacted with)
- People (meta-collection of Contacts)
- Locations (where the user was)
- Connections (a user's specific account with a Provider)
- Providers (services a user used, e.g. Facebook, GitHub, Google Takeout)
Retrieving Related Objects
As part of the GraphQL implementation, objects may have 'Relations' to other objects. What this means is that a related object may be retrieved as part of the call for the original object simply by making the related object one of the 'fields' requested. For example, if you wanted to retrieve the Contacts related to an Event, you would make the following request:
mutation eventSearch(<various variables>) {
id,
contact_ids,
hydratedContacts {
id,
avatar_url,
handle,
name
}
}
Note that the related object also requires you to specify which of its fields you want returned.
Note about LifeScope IDs
All of the objects' IDs are UUID4s.
These UUIDs are stored as Binaries, and directly accessing them via the API will return a garbled jumble that's the direct stringification of those binary characters.
In order to get the human-readable form, a virtual field is provided on the schema; this field is usually titled <field>_id_string
.
The only exception is that the ID of an object is stored as _id
, and the human-readable virtual field is just called id
.
Due to the way virtual fields work, you must request the binary fields as well when making the GraphQL request.
For example, an Event is stored with a UUID4 for its _id
, connection_id
, and provider_id
.
To get human-readable forms of those fields, one would make the following GraphQL request:
mutation eventSearch(<various variables>) {
_id,
id,
connection_id,
connection_id_string,
provider_id,
provider_id_string
}
It is required that you request the binary field when requesting related fields.
As demonstrated in the example in 'Retrieving Related Objects', you would need to request contact_ids
in order to get hydratedContacts
.
Events
Events are the central-most object in LifeScope. They represent an action in a user's history, and are related to virtually every other object in the schema.
Fields
Name | Type | Description |
---|---|---|
_id | Binary | A UUID4 in binary form uniquely identifying this object. |
id | String | A virtual field containing a human-readable form of the Event's _id . |
connection_id | Binary | A UUID4 in binary form uniquely identifying the Connection used to create this Event. |
connection_id_string | String | A virtual field containing a human-readable form of the Event's connection_id . |
contact_interaction_type | String | One of to , from , or with (or undefined) indicating how this Event interacts with the related Contacts. For example, if the Event was a message the user received, this field would be from ; if the Event was editing a document that the user shares with others, this field would likely be with . This field may not always be populated. |
contact_ids | [Binary] | A list of UUID4s in binary form uniquely identifying the Contact(s) associated with this Event. |
contact_id_strings | [String] | A virtual field containing a human-readable form of the Event's contact_ids . |
content_ids | [Binary] | A list of UUID4s in binary form uniquely identifying the Content(s) associated with this Event. |
content_id_strings | [String] | A virtual field containing a human-readable form of the Event's content_ids . |
context | String | A short description of what the Event was, e.g. 'Received', 'Purchased', 'Visited Web Page'. |
created | Date | When the the Event was first created in LifeScope. |
datetime | Date | When the Event actually occurred in real life. |
identifier | String | A unique internal identifier created from mashing up various aspects of the Event. You shouldn't worry about this, as it's only really used to make sure that, for instance, multiple users' interactions with the same piece of Content aren't confused with each other. |
location_id | Binary | A UUID4 in binary form uniquely identifying the Location associated with this Event. |
location_id_string | String | A virtual field containing a human-readable form of the Event's location_id . |
provider_id | Binary | A UUID4 in binary form uniquely identifying the Provider associated with this Event. |
provider_id_string | String | A virtual field containing a human-readable form of the Event's provider_id . |
provider_name | String | The name of the Provider from which this Event was obtained. |
tagMasks | Object | Tags associated or formerly associated with this Event. See the section on tagMasks for further clarification. |
type | String | A one-word categorization of the Event. Examples are 'messaged', 'purchased', 'created'. |
updated | Date | The last time the Event was updated in LifeScope. |
user_id | Binary | A UUID4 in binary form uniquely identifying the user that owns this Event. |
user_id_string | String | A virtual field containing a human-readable form of the Event's user_id . |
Relations
As mentioned in 'Retrieving Related Objects', if you are requesting any of these related objects, you must specify which of the related objects' fields you want retrieved as well.
Name | Related Object |
---|---|
hydratedContacts | Contacts |
hydratedContent | Content |
hydratedLocation | Locations |
Example GraphQL Request with Schema
mutation eventSearch($q: String, $offset: Int, $limit: Int, $filters: String, $sortField: String, $sortOrder: String) {
eventSearch(q: $q, offset: $offset, limit: $limit, filters: $filters, sortField: $sortField, sortOrder: $sortOrder) {
id,
connection_id,
connection_id_string,
contact_interaction_type,
context,
datetime,
provider_id,
provider_id_string,
provider_name,
type,
content_ids,
contact_ids,
location_id,
location_id_string,
tagMasks {
added,
removed,
source
},
hydratedContent {
id,
embed_content,
embed_format,
embed_thumbnail,
mimetype,
price,
tagMasks {
added,
removed,
source
},
text,
title,
type,
url
},
hydratedContacts {
id,
avatar_url,
handle,
name,
tagMasks {
added,
removed,
source
}
}
}
}
Contacts
Contacts represent an entity that a user has interacted with through a digital service, such as a Twitter user or a Gmail account. Contacts on their own have no connection to any other Contact; even if your friend Elena owns both the Twitter account @elena19 and the Gmail account elena.placeholder@gmail.com, both of those are treated as completely separate entities. If you would like to associate multiple Contacts with a single person, you can manually create a Person as documented below.
A Contact can be associated with multiple Events, though that association is strictly one-sided from the perspective of Events. A Contact has no record of which Events it's associated with.
A Contact may only be associated with a single Person at a time.
Fields
Name | Type | Description |
---|---|---|
_id | Binary | A UUID4 in binary form uniquely identifying this object. |
id | String | A virtual field containing a human-readable form of the Contact's _id . |
avatar_url | String | The URL to the Contact's avatar image. |
connection_id | Binary | A UUID4 in binary form uniquely identifying the Connection used to create this Contact. |
connection_id_string | String | A virtual field containing a human-readable form of the Contact's connection_id . |
created | Date | When the the Contact was first created in LifeScope. |
handle | String | The user's unique identifier in the third-party service, e.g. their email address or Twitter handle. |
identifier | String | A unique internal identifier created from mashing up various aspects of the Contact. You shouldn't worry about this, as it's only really used when ingesting data into LifeScope. |
name | String | The user's real name as recorded in the third-party service, e.g. 'Jane Doe'. |
people_id | Binary | A UUID4 in binary form uniquely identifying a Person that this Contact is associated with. |
people_id_string | String | A virtual field containing a human-readable form of the Contact's people_id . |
provider_id | Binary | A UUID4 in binary form uniquely identifying the Provider associated with this Contact. |
provider_id_string | String | A virtual field containing a human-readable form of the Contact's provider_id . |
provider_name | String | The name of the Provider from which this Contact was obtained. |
tagMasks | Object | Tags associated or formerly associated with this Contact. See the section on tagMasks for further clarification. |
updated | Date | The last time the Contact was updated in LifeScope. |
user_id | Binary | A UUID4 in binary form uniquely identifying the user that owns this Contact. |
user_id_string | String | A virtual field containing a human-readable form of the Contact's user_id . |
Relations
None
Example GraphQL Request with Schema
mutation contactSearch($q: String, $offset: Int, $limit: Int, $filters: String, $sortField: String, $sortOrder: String) {
contactSearch(q: $q, offset: $offset, limit: $limit, filters: $filters, sortField: $sortField, sortOrder: $sortOrder) {
id,
avatar_url,
connection_id,
connection_id_string,
provider_id,
provider_id_string,
handle,
name,
provider_id,
provider_id_string,
tagMasks {
added,
removed,
source
}
}
}
Content
Content represents a digital object that a user has interacted with, such as an image, a video, a file, an achievement, or a webpage.
A specific Content can be associated with multiple Events, though that association is strictly one-sided from the perspective of Events. A Content has no record of which Events it's associated with.
Fields
Name | Type | Description |
---|---|---|
_id | Binary | A UUID4 in binary form uniquely identifying this object. |
id | String | A virtual field containing a human-readable form of the Content's _id . |
connection_id | Binary | A UUID4 in binary form uniquely identifying the Connection used to create this Content. |
connection_id_string | String | A virtual field containing a human-readable form of the Content's connection_id . |
created | Date | When the the Content was first created in LifeScope. |
embed_content | String | A URL from which an embeddable version of the Content can be retrieved. Not always present. |
embed_format | String | The format of the embed_content , such as 'email', 'jpeg', or 'mp4'. Not present if there is no embed_content . |
embed_thumbnail | String | A URL from which an embeddable thumbnail of the Content can be retrieved. Not always present, but can be present even if embed_content is null. |
identifier | String | A unique internal identifier created from mashing up various aspects of the Contact. You shouldn't worry about this, as it's only really used when ingesting data into LifeScope. |
mimetype | String | The specific format of the object, e.g. 'image/jpeg'. |
price | Double | The price of the Content, with no specific currency associated. |
provider_id | Binary | A UUID4 in binary form uniquely identifying the Provider associated with this Contact. |
provider_id_string | String | A virtual field containing a human-readable form of the Content's provider_id . |
provider_name | String | The name of the Provider from which this Content was obtained. |
tagMasks | Object | Tags associated or formerly associated with this Content. See the section on tagMasks for further clarification. |
text | String | The text associated with this Content. |
title | String | A title associated with this Content. |
type | String | A classification of the Content, such as 'web-page', 'image', 'video', or 'text'. |
updated | Date | The last time the Content was updated in LifeScope. |
url | String | A URL at which the the Content can be found. |
user_id | Binary | A UUID4 in binary form uniquely identifying the user that owns this Content. |
user_id_string | String | A virtual field containing a human-readable form of the Content's user_id . |
Relations
None
Example GraphQL Request with Schema
mutation contentSearch($q: String, $offset: Int, $limit: Int, $filters: String, $sortField: String, $sortOrder: String) {
contentSearch(q: $q, offset: $offset, limit: $limit, filters: $filters, sortField: $sortField, sortOrder: $sortOrder) {
id,
connection_id,
connection_id_string,
embed_content,
embed_format,
embed_thumbnail,
provider_id,
provider_id_string,
mimetype,
price,
provider_id,
provider_id_string,
tagMasks {
added,
removed,
source
},
text,
title,
type,
url
}
}
Locations
Locations represent where a user was at a given date and time.
There can be many different Locations for the exact same coordinates; a user will likely have many Locations at their home, but each one will have a different datetime
.
We hope to introduce a new object in the future to generalize related Locations into a Place.
Fields
Name | Type | Description |
---|---|---|
_id | Binary | A UUID4 in binary form uniquely identifying this object. |
id | String | A virtual field containing a human-readable form of the Location's _id . |
connection_id | Binary | A UUID4 in binary form uniquely identifying the Connection used to create this Location. |
connection_id_string | String | A virtual field containing a human-readable form of the Location's connection_id . |
created | Date | When the the Location was first created in LifeScope. |
datetime | Date | The exact date at which the user was at that Location. |
estimated | Boolean | Whether this Location was estimated or actually recorded by some service. |
geo_format | String | The format of the coordinates recorded in geolocation . Currently the only valid value is 'lat_lng'. |
geolocation | [Double] | The coordinates of the Location. Currently, they are in [longitude, latitude] order. |
identifier | String | A unique internal identifier created from mashing up various aspects of the Contact. You shouldn't worry about this, as it's only really used when ingesting data into LifeScope. |
provider_id | Binary | A UUID4 in binary form uniquely identifying the Provider associated with this Contact. |
provider_id_string | String | A virtual field containing a human-readable form of the Location's provider_id . |
tracked | Boolean | Whether or not this Location came from LifeScope's location tracking. |
updated | Date | The last time the Location was updated in LifeScope. |
uploaded | Boolean | Whether or not this Location was uploaded in a file. |
user_id | Binary | A UUID4 in binary form uniquely identifying the user that owns this Location. |
user_id_string | String | A virtual field containing a human-readable form of the Location's user_id . |
Relations
None
Example GraphQL Request with Schema
query locationManyById ($ids: [String]) {
locationFindManyById (ids: $ids) {
id,
estimated,
geo_format,
geolocation
}
}
Different Types of Locations
Locations can come from a few different sources:
From the Provider where the Event was retrieved
These Locations were recorded by and retrieved from a Provider. An example would be Locations associated with Tweets and retrieved along with those Tweets.
This type of Location will have estimated
be false, tracked
be false, and uploaded
be false.
Recorded by location tracking in the LifeScope app
If a user enables it, the LifeScope app will record their location whenever they navigate to a page on the LifeScope app.
This type of Location will have estimated
be false, tracked
be true, and uploaded
be false.
These Locations will not be associated with an Event, but can be used to more accurately estimate Events that lack Locations of their own.
Uploaded from a source of GeoJSON data obtained from something like Google Takeout.
Certain Providers, such as Google, have a wealth of location data that a user can download, but which cannot be automatically retrieved from their API. In order to get this information into LifeScope, a user has to manually download this data in the form of a GeoJSON file and then upload it from their settings.
This type of Location will have estimated
be false, tracked
be false, and uploaded
be true.
These Locations will not be associated with an Event, but can be used to more accurately estimate Events that lack Locations of their own.
Estimated by LifeScope from other real Locations.
Since most digital data out there does not have a location, LifeScope will estimate the Location of everything that does not have a real Location associated with it. This process is handled automatically by a worker task, and is re-run periodically. The estimated Location's coordinates are set to the non-estimated Location closest in time to when the Event occurred. The estimated coordinates may change over time if new non-estimated Locations are ingested into LifeScope that are closer in time to the Event in question.
THis type of Location will have estimated
be true, tracked
be false, and uploaded
be false.
These Locations will always be associated with an Event.
People
People are collections of Contacts that all belong to the same person.
As of this writing, they must be manually constructed, and there is no independent verification of whether a Contact actually belongs to a Person.
Fields
Name | Type | Description |
---|---|---|
_id | Binary | A UUID4 in binary form uniquely identifying this object. |
id | String | A virtual field containing a human-readable form of the Contact's _id . |
avatar_url | String | The URL to the Contact's avatar image. |
contact_ids | [Binary] | A list of UUID4s in binary form uniquely identifying the Contacts that are associated with this Person. |
contact_id_strings | [String] | A virtual field containing a human-readable form of the Contact's contact_ids . |
created | Date | When the the Contact was first created in LifeScope. |
first_name | String | The Person's first name. |
middle_name | String | The Person's middle name. |
last_name | String | The Person's last name. |
tagMasks | Object | Tags associated or formerly associated with this Contact. See the section on tagMasks for further clarification. |
updated | Date | The last time the Contact was updated in LifeScope. |
user_id | Binary | A UUID4 in binary form uniquely identifying the user that owns this Contact. |
user_id_string | String | A virtual field containing a human-readable form of the Contact's user_id . |
Relations
As mentioned in 'Retrieving Related Objects', if you are requesting any of these related objects, you must specify which of the related objects' fields you want retrieved as well.
Name | Related Object |
---|---|
hydratedContacts | Contacts |
Example GraphQL Request with Schema
mutation personSearch($q: String, $offset: Int, $limit: Int, $filters: String, $sortField: String, $sortOrder: String) {
personSearch(q: $q, offset: $offset, limit: $limit, filters: $filters, sortField: $sortField, sortOrder: $sortOrder) {
id,
avatar_url,
first_name,
middle_name,
last_name,
contact_ids,
contact_id_strings,
hydratedContacts {
id,
avatar_url,
handle,
name
},
tagMasks {
added,
removed,
source
}
}
}
tagMasks (not an object, but a field of most objects)
One of LifeScope's useful features is the ability to tag objects.
Many objects that are already tagged in the services they were generated from with '#
Taggable objects have a 'tagMasks' field.
This field is an object with three sub-fields: added
, removed
, and source
.
All three of these sub-fields are an array of strings (or null).
source
is comprised of tags that were originally present on the object, and is never modified.
added
is comprised of tags the user has added, and can include tags in source
.
removed
is comprised of tags the user has removed, and can include tags in source
.
When a user removes a tag, it's removed from added
(if present) and added to removed
.
Similarly, when a user adds a tag, it's removed from removed
(if present) and added to added
.
When interpreting this object, the current valid tags are the unique union of source
and added
, minus anything in removed
.
As an example, let's say a Tweet was ingested into LifeScope that already had the tags '#oneTwoThree' and '#whatever'. The user later tagged that Content with 'bestWeekend' and removed the tag 'whatever'. tagMasks would appear as
tagMasks {
added: ['bestWeekend'],
removed: ['whatever'],
source: ['oneTwoThree', 'whatever']
}