{ "type": "<entity>", "data": { ... } }Import Files
Imports are not entirely supported on V3. This page is a work in progress.
If you've just started using Stream, you might want to import data from your old infrastructure. Instead of using the APIs and creating your own import scripts, you can make use of our import feature.
Import files use the JSON Lines format (one JSON object per line). Each line is an envelope that wraps a single record:
Valid values for type are: user, feed, feed_group, feed_view, activity, comment, reaction, bookmark, follow, collection, poll, and poll_vote. The full JSON Schemas are published at GetStream/protocol.
The Process
The steps for importing data into your app are as follows:
Install the Stream CLI
curl -fsSL https://getstream.io/cli.sh | bashSet up your app
getstream login
getstream initUpload the file and track the import task
getstream import feeds myfile.jsonl --watch
getstream import status <task-id>
getstream import listSee the getstream import reference for all flags.
Users
Users are shared with chat and video. So if you already use those products you typically don't need to import users. The structure for importing users is shown below:
{ "type": "user", "data": { "id": "myuserid", "role": "user", "custom": {} } }Feeds
This is how you can import feeds.
{
"type": "feed",
"data": {
"group_id": "user",
"id": "myuserid",
"fid": "user:myuserid",
"created_by_id": "myuserid",
"name": "My Feed",
"description": "A sample feed",
"visibility": "public",
"custom": {}
}
}fid is the fully-qualified feed id and is typically "{group_id}:{id}".
Follows
For follows specify the import in the following structure:
{
"type": "follow",
"data": {
"source_fid": "timeline:123",
"target_fid": "user:222",
"source_created_by_id": "myuserid",
"target_created_by_id": "user222",
"push_preference": "none",
"custom": {}
}
}source_created_by_id and target_created_by_id are the user IDs who created the source and target feeds, respectively. They're required for import (the live Follow API call doesn't need them, since it derives the creator from each feed automatically).
Activities
Activities are the core records posted to one or more feeds:
{
"type": "activity",
"data": {
"id": "activity-123",
"type": "post",
"user_id": "user-222",
"fids": ["user:myuserid"],
"text": "hello world",
"visibility": "public",
"custom": {}
}
}Comments
For comments specify the import in the following structure:
{
"type": "comment",
"data": {
"id": "comment-1",
"object_type": "activity",
"object_id": "activity-123",
"user_id": "user-222",
"text": "buy a gaming chair",
"mentioned_user_ids": ["user-222"],
"parent_id": null,
"attachments": [],
"custom": {}
}
}Reactions
For reactions specify the import in the following structure:
{
"type": "reaction",
"data": {
"user_id": "user-222",
"activity_id": "activity-123",
"type": "like",
"custom": {}
}
}activity_id is required. Set comment_id as well when reacting to a comment on the activity.
Polls
Polls are a shared entity — the same poll and poll_vote records are used by both Feeds and Chat. To attach a poll to an activity, import the poll first, then reference it from the activity via poll_id:
{
"type": "poll",
"data": {
"id": "poll-123",
"name": "Which feature should we build next?",
"created_by_id": "user-222",
"voting_visibility": "public",
"enforce_unique_vote": true,
"max_votes_allowed": 1,
"options": [
{ "id": "option-1", "text": "Stories" },
{ "id": "option-2", "text": "Live video" },
{ "id": "option-3", "text": "Polls" }
],
"custom": {}
}
}The poll fields are:
| name | type | description | required |
|---|---|---|---|
| id | string | unique poll ID (max 255 chars) | ✓ |
| name | string | the poll question / title | ✓ |
| created_by_id | string | user ID of the poll creator | ✓ |
| description | string | poll description | |
| voting_visibility | string | public or anonymous (defaults to public) | |
| enforce_unique_vote | boolean | only allow a single vote per user | |
| max_votes_allowed | integer | maximum votes per user, between 1 and 10 | |
| allow_user_suggested_options | boolean | allow users to suggest new options | |
| allow_answers | boolean | allow free-form text answers | |
| is_closed | boolean | whether the poll is closed for voting | |
| options | array | poll options, each with an id (required), text, and custom | |
| created_at | string | creation time (defaults to import time) | |
| updated_at | string | last update time (defaults to created_at) | |
| custom | object | custom fields (up to 5 KiB) |
To attach the poll to an activity, set poll_id:
{
"type": "activity",
"data": {
"id": "activity-123",
"type": "poll",
"user_id": "user-222",
"fids": ["user:myuserid"],
"poll_id": "poll-123",
"custom": {}
}
}Poll Votes
A poll_vote is either a vote (pointing at an option via option_id) or an answer (free-form text via answer_text). The two are mutually exclusive — set is_answer to true with answer_text for an answer, otherwise provide option_id for a vote. Import votes after their poll.
{
"type": "poll_vote",
"data": {
"id": "vote-1",
"poll_id": "poll-123",
"option_id": "option-1",
"user_id": "user-222",
"custom": {}
}
}The poll_vote fields are:
| name | type | description | required |
|---|---|---|---|
| id | string | unique poll vote ID (max 255 chars) | ✓ |
| poll_id | string | ID of the poll this vote belongs to | ✓ |
| user_id | string | user ID who cast the vote | ✓ |
| option_id | string | ID of the chosen option (required for a vote, omit for an answer) | |
| is_answer | boolean | set to true when this is a free-form answer | |
| answer_text | string | the free-form answer text (required when is_answer is true) | |
| created_at | string | creation time (defaults to import time) | |
| updated_at | string | last update time (defaults to created_at) |
Putting it all together
A single import file mixes entity types — one record per line:
{"type":"user","data":{"id":"myuserid","role":"user","custom":{}}}
{"type":"feed","data":{"group_id":"user","id":"myuserid","fid":"user:myuserid","created_by_id":"myuserid","custom":{}}}
{"type":"activity","data":{"id":"activity-123","type":"post","user_id":"myuserid","fids":["user:myuserid"],"text":"hello world"}}
{"type":"comment","data":{"id":"comment-1","object_type":"activity","object_id":"activity-123","user_id":"myuserid","text":"nice!"}}
{"type":"reaction","data":{"user_id":"myuserid","activity_id":"activity-123","type":"like"}}
{"type":"poll","data":{"id":"poll-123","name":"Which feature next?","created_by_id":"myuserid","options":[{"id":"option-1","text":"Stories"},{"id":"option-2","text":"Polls"}]}}
{"type":"activity","data":{"id":"activity-456","type":"poll","user_id":"myuserid","fids":["user:myuserid"],"poll_id":"poll-123"}}
{"type":"poll_vote","data":{"id":"vote-1","poll_id":"poll-123","option_id":"option-1","user_id":"myuserid"}}