Programmatically integrate with Reflect's data reporting and visualization platform
Although Reflect provides a powerful and intuitive user interface for its data reporting and visualization platform, some use cases require a more programmatic and less UI-driven approach. Reflect thus offers a REST API that enables you to securely manage Reflect projects, views, database connections, data models and more.
The base URL for the Reflect REST API is:
At the moment, there is only one version of the Reflect REST API available
(version 1 or v1). Thus, all API calls have a base URL of:
Successful requests to all endpoints return JSON objects. All errors emitted by the API are also returned as JSON objects that provide fine-grained insight into what went wrong.
We take many measures to ensure that your data is safe as it transits Reflect services.
All traffic through Reflect services is encrypted using TLSv1.2. Any non-encrypted traffic is automatically redirected to the appropriate encrypted channel.
For info on providing authentication for Reflect views in client-side code rather than direct calls to the Reflect REST API, see our Authentication doc.
All HTTP calls to the Reflect REST API require you to provide a Reflect API token as the password component of a basic auth header. You do not need to provide a username in this header. Here’s an example:
$ curl -u ':a1b2c3d-your-secure-api-token-4e5f6g7' \
-H 'Content-Type: application/json' \
'https://api.reflect.io/v1/projects'
You can fetch, create, and delete API tokens in the Reflect app.
By default, API tokens that you create can be used to perform any action available through the REST API. If you’d like to provide a token with read-only API access, you can click READ ONLY? in the tokens interface:

Once you’ve done that, the token can be used for actions such as listing projects, fetching data models, or fetching database connection metadata, but cannot be used to, for example, create a project or delete a view.
The Reflect REST API is highly resource based, with most calls revolving around managing these resources for your account:
Reflect projects are collections of views that visualize your data. You can create as many projects and views as you want.
Both projects and views are referred to using slugs, such as
your-project-1 or your-view-1. All project and view slugs must be unique
for your account (you will receive errors if you try to create a project or
view with a slug that’s already taken).
access_key and a secret_key are
assigned to each project and used for authenticating
views.A project contains any number of views that you’ll use when you want to embed in your application. Each project has a corresponding data model.
| Name | Type | Description |
|---|---|---|
slug |
string | A machine-friendly label for referring to the project |
name |
string | A human-friendly label for referring to the project |
description |
string | A description of the project |
created_at |
timestamp | The date and time at which the project was created |
updated_at |
timestamp | The date and time at which the project was last updated |
{
"name": "Your Project #1",
"slug": "your-project-1",
"description": "The very first project that you created with the API.",
"created_at": "2016-02-04t00:18:07.817442z",
"updated_at": "2016-02-07t01:35:22.223042z"
}
List all of the projects that are currently associated with your Reflect account. This endpoint will return a list of project objects.
$ curl -u ':a1b2c3d-your-secure-api-token-4e5f6g7' \
-H 'Content-Type: application/json' \
'https://api.reflect.io/v1/projects'
[
{
"name": "Your Project #1",
"slug": "your-project-1",
"description": "Your very first project created with the API.",
"created_at": "2016-02-04t00:18:07.817442z",
"updated_at": "2016-02-07t01:35:22.223042z"
}
]
Create a new project for your Reflect account. You must specify two things when
creating a new project: a name for the project (which can include spaces and
special characters) and a slug.
Optionally, you can supply a connections parameters as an array of strings,
each of which represents a connection slug.
$ curl XPOST \
-u ':a1b2c3d-your-secure-api-token-4e5f6g7' \
-H 'Content-Type: application/json' \
--data-binary @./project.json \
'https://api.reflect.io/v1/projects'
The curl example above assumes that you have this JSON stored in a
project.json file:
{
"name": "Your Project #1",
"slug": "your-project-1",
"connections": ["your-connection"]
}
{
"name": "Your Project #1",
"slug": "your-project-1",
"description": "Your very first project created with the API.",
"created_at": "2016-02-04t00:18:07.817442z",
"updated_at": "2016-02-07t01:35:22.223042z"
}
Fetch information about a specific project using the project’s slug.
$ curl -u ':a1b2c3d-your-secure-api-token-4e5f6g7' \
-H 'Content-Type: application/json' \
'https://api.reflect.io/v1/projects/your-project-1'
{
"name": "Your Project #1",
"slug": "your-project-1",
"description": "Your very first project created with the API.",
"created_at": "2016-02-04t00:18:07.817442z",
"updated_at": "2016-02-07t01:35:22.223042z"
}
Update a project.
$ curl -XPUT -u ':a1b2c3d-your-secure-api-token-4e5f6g7' \
--data-binary @./project.json \
-H 'Content-Type: application/json' \
'https://api.reflect.io/v1/projects/your-project-1'
{
"name": "Your Project #1",
"slug": "your-project-1",
"description": "Your very first project created with the API.",
"created_at": "2016-02-04t00:18:07.817442z",
"updated_at": "2016-02-07t01:35:22.223042z"
}
Delete a project (identified by project slug).
$ curl -XDELETE \
-u ':a1b2c3d-your-secure-api-token-4e5f6g7' \
-H 'Content-Type: application/json' \
'https://api.reflect.io/v1/projects/your-project-1'
List statements that have been run for this project in descending order (by the
time at which they were created). Statements are paginated at 10 statements per
page. You can request a different page by passing the page parameter. By
default, the first page is returned.
The runtime attribute is the length of time that it took to run the query in
milliseconds. The status column can be one of success and failed.
$ curl -u ':a1b2c3d-your-secure-api-token-4e5f6g7' \
-H 'Content-Type: application/json' \
'https://api.reflect.io/v1/projects/your-project-1/statements?page=1'
[
{
"statement": "SELECT \"users\".\"email\" AS \"Email\", COUNT(\"users\".\"id\") AS \"Count\" FROM \"users\" AS \"users\" GROUP BY \"Email\"",
"runtime": 9,
"status": "success",
"created_at": "2016-04-06T11:26:02.212968-07:00",
"updated_at": "2016-04-06T11:26:02.212968-07:00"
},
{
"statement": "SELECT \"users\".\"email\" AS \"Email\", COUNT(\"users\".\"id\") AS \"Count\" FROM \"users\" AS \"users\" GROUP BY \"Email\"",
"runtime": 17,
"status": "success",
"created_at": "2016-04-06T11:08:24.749929-07:00",
"updated_at": "2016-04-06T11:08:24.749929-07:00"
}
]
Associate a connection with a project. The server will download the connection’s metadata and update the project’s data model accordingly.
The API endpoint returns the complete data model. If the connection is already
associated with the project, a 412 Precondition
Failed error will be returned.
$ curl -u -XPOST \
':a1b2c3d-your-secure-api-token-4e5f6g7' \
-H 'Content-Type: application/json' \
--data-binary @./connection.json \
'https://api.reflect.io/v1/projects/your-project-1/connections'
{
"slug": "your-connection-1"
}
{
"name": "Example Project",
"slug": "example-project",
"description": "An example project and data model.",
"data_sets": [
{
"name": "example_data_set",
"connection": "your-connection-1",
"tables": [
{
"table": "table1",
"primary_key": "id",
"columns": {
"column1": "text"
}
}
]
}
],
"fields": {
"Field 1": {
"data_set": "example_data_set",
"table": "table1",
"columns": ["column1"]
},
"Field 2": {
"data_set": "example_data_set",
"table": "table1",
"columns": ["column2"]
}
},
"created_at": "2016-02-22T14:31:41.57292-08:00",
"updated_at": "2016-02-22T14:31:41.57292-08:00"
}
Fetch the data model associated with a project (identified by slug).
$ curl -u ':a1b2c3d-your-secure-api-token-4e5f6g7' \
-H 'Content-Type: application/json' \
'https://api.reflect.io/v1/projects/your-project-1/data-model'
{
"slug": "orders",
"name": "Order Project Example",
"description": "An example project and data model for a fictitious ecommerce store.",
"data_sets": [
{
"name": "orders",
"credential": "reflect-connection-1",
"tables": [
{
"table": "orders",
"columns": {
"order_date": "time",
"order_priority": "text"
}
}
]
}
],
"fields": {
"Order Date": {
"data_set": "orders",
"table": "orders",
"columns": ["order_date"]
}
}
}
The Reflect API keeps a record of which database connection credentials live in different Reflect Agents that you’ve deployed. The API endpoints documented here are useful for figuring out which connections Reflect knows about.
Connection metadata is automatically forwarded to the Reflect API by Reflect agents. Database connection info isn’t handled by the Reflect REST API. Only the bare essential metadata is kept for each database connection, in the name of limiting the security surface area of our API. All sensitive database connection information, including usernames, passwords, and IP addresses are encrypted and stored within Reflect Agents.
Although Reflect only ever requires read access to users’ databases, you may nonetheless have security or policy compliance requirements that prevent you from sharing database connection information. In that case, we suggest you run your own Reflect Agent on your own infrastructure. The Reflect Agent stores all database connection information locally and can be run as a multi-agent, high-availability cluster.
Database connection objects consist of just a few pieces of metadata:
| Name | Type | Description |
|---|---|---|
slug |
string | A machine-friendly label for referring to this connection in data models |
name |
string | A label to give to this connection |
driver |
string | The type of database this connection is meant to talk to (currently redshift, postgres, mysql, or mssql) |
created_at |
timestamp | The date and time at which the connection was created |
updated_at |
timestamp | The date and time at which the connection was last updated |
{
"slug": "test-connection-1",
"name": "Your Test Connection",
"driver": "postgres",
"updated_at": "2016-03-01T20:34:10.407359-08:00",
"created_at": "2016-03-01T20:34:10.407359-08:00"
}
List all of the connections that have been forwarded to the Reflect API by agents that you’re managing. This list will also include any connections that you’ve registered with a Reflect-hosted agent.
$ curl -u ':a1b2c3d-your-secure-api-token-4e5f6g7' \
-H 'Content-Type: application/json' \
'https://api.reflect.io/v1/connections'
[
{
"slug": "test-connection-1",
"name": "Test Connection",
"driver": "postgres",
"updated_at": "2016-03-01T20:34:10.407359-08:00",
"created_at": "2016-03-01T20:34:10.407359-08:00"
}
]
Instructs the agent to inspect the database and gather the relevant metadata about tables and relationships between them. It also introspects the data type for each column and classifies it accordingly. How a given column’s data type is classified is dependent upon the database driver.
Relationships are inferred based on foreign key configuration in the database. If no foreign key constraint is configured between tables then a relationship cannot be inferred.
$ curl -u ':a1b2c3d-your-secure-api-token-4e5f6g7' \
-H 'Content-Type: application/json' \
'https://api.reflect.io/v1/connections/test-connection-1/metadata'
{
"name": "your_database",
"connection": "test-connection-1",
"tables": [
{
"table": "your_table",
"columns": {
"column1": "number",
"column2": "text"
}
}
]
}
Instructs the agent to fetch new schema information and updates the available tables and fields. This will be reflected across all projects that use this connection.
$ curl -XPOST -u ':a1b2c3d-your-secure-api-token-4e5f6g7' \
'https://api.reflect.io/v1/connections/test-connection-1/metadata/refresh'
{
"name": "your_database",
"connection": "test-connection-1",
"tables": [
{
"table": "your_table",
"columns": {
"column1": "number",
"column2": "text",
"column3": "text"
}
}
]
}
A project can have multiple pre-defined parameter sets. Parameter sets let you “impersonate” your users in the Reflect app so that you can get a sense for how a given view will look or behave when it’s deployed.
If a project has at least one parameter set, the Reflect app will require that you use a parameter set when editing a view.
| Name | Type | Description |
|---|---|---|
name |
string | A friendly name for the parameter set |
slug |
string | A unique slug for the parameter set. The slug must be unique to all parameter sets in the project. |
parameters |
array | An array of parameters |
created_at |
timestamp | The date and time the key pair was created |
updated_at |
timestamp | The date and time the key pair last updated |
{
"name": "Parameter Set #1",
"slug": "parameter-set-1",
"parameters": [
{
"field": "Your Field #1",
"op": "=",
"value": "abc123"
}
],
"created_at": "2016-04-21T17:57:11.332755Z",
"updated_at": "2016-04-21T17:57:11.332755Z"
}
List all the parameter sets associated with this project. If no parameter sets exist then an empty array will be returned.
If a parameter set exists, the Reflect app will require that you use a parameter set when editing a view.
$ curl -u ':a1b2c3d-your-secure-api-token-4e5f6g7' \
-H 'Content-Type: application/json' \
'https://api.reflect.io/v1/projects/your-project-1/parameter-sets'
[
{
"name": "Parameter Set #1",
"slug": "parameter-set-1",
"parameters": [
{
"field": "Your Field #1",
"op": "=",
"value": "abc123"
}
],
"created_at": "2016-04-21T17:57:11.332755Z",
"updated_at": "2016-04-21T17:57:11.332755Z"
}
]
Creates a new parameter set and associates it with the project. The slug for
the parameter set must be unique. If the slug is not unique, a 412
Precondition Failed error will be returned from the API with details.
$ curl -u ':a1b2c3d-your-secure-api-token-4e5f6g7' \
-H 'Content-Type: application/json' \
--data-binary @./parameter-set.json \
'https://api.reflect.io/v1/projects/your-project-1/parameter-sets'
{
"name": "Parameter Set #1",
"slug": "parameter-set-1",
"parameters": [
{
"field": "Your Field #1",
"op": "=",
"value": "abc123"
}
]
}
{
"name": "Parameter Set #1",
"slug": "parameter-set-1",
"parameters": [
{
"field": "Your Field #1",
"op": "=",
"value": "abc123"
}
],
"created_at": "2016-04-21T17:57:11.332755Z",
"updated_at": "2016-04-21T17:57:11.332755Z"
}
Gets a parameter set associated with the project. If the parameter set does not
exist, a 404 Not Found error will be returned.
$ curl -u ':a1b2c3d-your-secure-api-token-4e5f6g7' \
'https://api.reflect.io/v1/projects/your-project-1/parameter-sets/parameter-set-1'
{
"name": "Parameter Set #1",
"slug": "parameter-set-1",
"parameters": [
{
"field": "Your Field #1",
"op": "=",
"value": "abc123"
}
],
"created_at": "2016-04-21T17:57:11.332755Z",
"updated_at": "2016-04-21T17:57:11.332755Z"
}
Updates an existing parameter set. Only the name and parameters fields are
updatable. Updates to the slug, created_at, and updated_at fields will be
ignored.
If the parameter set does not exist a 404 Not Found error will be returned.
$ curl -XPUT \
-u ':a1b2c3d-your-secure-api-token-4e5f6g7' \
--data-binary @./parameter-set.json \
-H 'Content-Type: application/json' \
'https://api.reflect.io/v1/projects/your-project-1/parameter-sets/parameter-set-1'
{
"name": "Parameter Set #1",
"parameters": [
{
"field": "Your Field #1",
"op": "=",
"value": "abc123"
}
]
}
{
"name": "Parameter Set #1",
"slug": "parameter-set-1",
"parameters": [
{
"field": "Your Field #1",
"op": "=",
"value": "abc123"
}
],
"created_at": "2016-04-21T17:57:11.332755Z",
"updated_at": "2016-04-21T17:57:11.332755Z"
}
Deletes a parameter set specified by name associated with a project specified
by slug. If the parameter set is successfully deleted, the API will return
the parameter set you just deleted.
$ curl -XDELETE \
-u ':a1b2c3d-your-secure-api-token-4e5f6g7' \
'https://api.reflect.io/v1/projects/your-project-1/parameter-sets/parameter-set-1'
{
"name": "Parameter Set #1",
"slug": "parameter-set-1",
"parameters": [
{
"field": "Your Field #1",
"op": "=",
"value": "abc123"
}
],
"created_at": "2016-04-21T17:57:11.332755Z",
"updated_at": "2016-04-21T17:57:11.332755Z"
}
A project has one or more key pairs associated with it. These key pairs are used for generating signed requests so you can use Reflect in multi-tenant environments.
| Name | Type | Description |
|---|---|---|
access_key |
string | A GUID used to identify the project. Can be shared. |
secret_key |
string | A GUID used as a key to the HMAC algorithm. Should not be shared. |
created_at |
timestamp | The date and time at which the key pair was created |
updated_at |
timestamp | The date and time at which the key pair last updated |
{
"access_key": "b5cb8544-07ed-11e6-a66b-cfb440724ccd",
"secret_key": "fc14a940-07ed-11e6-9608-e3ab6109c04d",
"created_at": "2016-04-21T17:57:11.332755Z",
"updated_at": "2016-04-21T17:57:11.332755Z"
}
List all the key pairs that have been generated for this project. The JSON for each project will always include both the secret key and the access key.
$ curl -u ':a1b2c3d-your-secure-api-token-4e5f6g7' \
-H 'Content-Type: application/json' \
'https://api.reflect.io/v1/projects/your-project-1/key-pairs'
[
{
"access_key": "b5cb8544-07ed-11e6-a66b-cfb440724ccd",
"secret_key": "fc14a940-07ed-11e6-9608-e3ab6109c04d",
"created_at": "2016-04-21T17:57:11.332755Z",
"updated_at": "2016-04-21T17:57:11.332755Z"
}
]
Reflect uses agents to communicate with your database. You can run the Reflect Agent yourself and register it with the Reflect APIs or you can use a Reflect-hosted version of the agent.
All communication with databases goes through a Reflect agent. Reflect can host the agent for you, or you can install the agent in your infrastructure.
Agents automatically register themselves with the Reflect API when they first come online.
| Name | Type | Description |
|---|---|---|
id |
int | The ID assigned to the agent by Reflect |
name |
string | A label that you can give to the agent |
url |
string | The URL that the agent lives at |
created_at |
timestamp | The date and time the agent was created |
updated_at |
timestamp | The date and time the agent last updated |
{
"id": 1,
"name": "agent #1",
"url": "http://192.168.50.101:9700",
"created_at": "2016-02-04t00:18:07.817442z",
"updated_at": "2016-02-07t01:35:22.223042z"
}
List all of the agents registered with your Reflect account. This list also includes agents hosted by Reflect.
$ curl -u ':a1b2c3d-your-secure-api-token-4e5f6g7' \
-H 'Content-Type: application/json' \
'https://api.reflect.io/v1/agents'
[
{
"id": 1,
"name": "agent #1",
"url": "http://192.168.50.101:9700",
"created_at": "2016-02-04t00:18:07.817442z",
"updated_at": "2016-02-07t01:35:22.223042z"
}
]
Update the metadata associated with an agent. You can modify the agent’s name
and/or the agent’s url Before the metadata is saved, the API will test to
make sure that the connection can be established.
If a connection cannot be established, an error will be returned.
$ curl -XPUT \
-u ':a1b2c3d-your-secure-api-token-4e5f6g7' \
-H 'Content-Type: application/json' \
-d '{"name": "Your Updated Agent", "url": "http://10.0.10.11:9700"}' \
'https://api.reflect.io/v1/agents/1'
[
{
"id": 1,
"name": "agent #1",
"url": "http://192.168.50.101:9700",
"created_at": "2016-02-04t00:18:07.817442z",
"updated_at": "2016-02-07t01:35:22.223042z"
}
]
The Reflect API can add connections directly to specific agents on your behalf.
The API will keep record of the connections that are on the agent. Anything in
the options object is stored securely on the agent and not stored by the API
in any way.
$ curl -XPUT \
-u ':a1b2c3d-your-secure-api-token-4e5f6g7' \
-H 'Content-Type: application/json' \
--data-binary @./connection.json \
'https://api.reflect.io/v1/agents/1/connections'
{
"name": "Your Connection",
"slug": "your-connection",
"driver": "postgres",
"options": {
"host": "your.host.com",
"port": "5432",
"user": "your_user",
"password": "your_password",
"database": "your_database",
"ssl": "require"
}
}
{
"id": 1,
"name": "agent #1",
"url": "http://192.168.50.101:9700",
"created_at": "2016-02-04t00:18:07.817442z",
"updated_at": "2016-02-07t01:35:22.223042z"
}
See the Reflect Agent documentation for information about supported drivers.
As with adding a new connection, when updating a connection, the relevant connection data is forwarded to the agent and is not stored by the API in any way.
$ curl -XPUT \
-u ':a1b2c3d-your-secure-api-token-4e5f6g7' \
-H 'Content-Type: application/json' \
--data-binary @./connection.json \
'https://api.reflect.io/v1/agents/1/connections/your-connection-1'
{
"name": "Your Connection",
"slug": "your-connection",
"driver": "postgres",
"options": {
"host": "your.host.com",
"port": "5432",
"user": "your_user",
"password": "your_password",
"database": "your_database",
"ssl": "require"
}
}
{
"id": 1,
"name": "agent #1",
"url": "http://192.168.50.101:9700",
"created_at": "2016-02-04t00:18:07.817442z",
"updated_at": "2016-02-07t01:35:22.223042z"
}
Please see the section above for information on supported drivers.
Connect to an agent and test the connection to the database. If the connection
succeeds, the server will indicate that the test passed with a passed: true
value in the response. If the connection failed, it will respond with a
passed: false value and an indicator of why it failed to connect.
$ curl -u ':a1b2c3d-your-secure-api-token-4e5f6g7' \
-H 'Content-Type: application/json' \
'https://api.reflect.io/v1/agents/1/connections/your-connection-1/test'
{
"passed": true,
"details": {
"message": "",
"vendor_error_code": ""
}
}
Data models tell Reflect services how to use the data in your databases to provide reports (which your client-side code then uses to create visualizations). Data models map database columns and expressions to fields, which are referenced at reporting time to generate reports.
Another way to think about it: data models are where the rubber meets the road for reporting and visualization. They map the data in your database to a format that Reflect can understand.
For more in-depth documentation, see Data models.
| Name | Type | Description |
|---|---|---|
slug |
string | A machine-friendly label for referring to the data model |
name |
string | A human-friendly label for referring to the data model |
description |
string | A brief, user-supplied description of the data model |
data_sets |
array | An array of data set configuration objects |
fields |
object | An object containing field configuration object |
Although you can update data models through the API, you cannot create a new data model directly via the API. That’s because there’s always a 1-to-1 relationship between a Reflect project and a data model. When you create a new project a data model is automatically associated with the project and given the same name, slug, and description as the project. Once a project has been created you can modify the data model however you’d like.
{
"slug": "orders",
"name": "Order Project Example",
"description": "An example project and data model for a fictitious ecommerce store.",
"data_sets": [
{
"name": "orders",
"credential": "reflect-connection-1",
"tables": [
{
"table": "orders",
"columns": {
"order_date": "time",
"order_priority": "text",
"order_quantity": "number",
"sales": "number",
"discount": "number",
"profit": "number",
"ship_mode": "text",
"unit_price": "number",
"shipping_cost": "number",
"customer_name": "text",
"city": "text",
"zip_code": "number",
"state": "text",
"region": "text",
"customer_segment": "text",
"product_category": "text",
"product_sub_category": "text",
"product_name": "text",
"product_container": "text",
"product_base_margin": "number"
}
}
]
}
],
"fields": {
"Order Date": {
"data_set": "orders",
"table": "orders",
"columns": ["order_date"]
},
"Customer Name": {
"data_set": "orders",
"table": "orders",
"columns": ["customer_name"]
},
"Customer Segment": {
"data_set": "orders",
"table": "orders",
"columns": ["customer_segment"]
},
"Region": {
"data_set": "orders",
"table": "orders",
"columns": ["region"]
},
"Total Sales": {
"data_set": "orders",
"table": "orders",
"columns": ["sales"],
"expression": "SUM(sales)"
},
"Total Items Sold": {
"data_set": "orders",
"table": "orders",
"columns": ["order_quantity"],
"expression": "SUM(order_quantity)"
}
}
}
Data sets tell Reflect what data lives where in your database and how different
parts relate to each other. Each data set has a unique name attribute that is referenced by other
parts of the data model.
Data sets also get a credential name which tells the Reflect Agent
which connection to use to connect to the database.
| Parameter | Description |
|---|---|
name |
The name of this data set, used to reference it elsewhere in the data model |
credential |
The name of the connection to use when connecting to the database |
tables |
An array of table definitions |
Table definitions are how you tell Reflect what columns live in what tables within your database.
| Parameter | Description |
|---|---|
table |
The name of the physical table in the database |
primary_key |
The primary key used as part of relationships to this table |
columns |
An object of column definitions. The key is the column name and the value is the column type. |
relationships |
An object of relationship definitions. The key is the relationship name and the value is the relationship definition. This attribute is optional. |
The physical columns that belong to the table. All physical columns have a type associated with them. The type can be any one of the following:
| Parameter | Description |
|---|---|
text |
The column is a string or piece of text |
number |
The column is a number |
time |
The column is a date and/or time |
Relationships define how different tables are related to each other. Each relationship has one or more condition objects specifying which keys to join on.
| Parameter | Description |
|---|---|
table |
The foreign table that the current table relates to. |
conditions |
An array of objects specifying the join conditions for the relationship. Each object has the following properties: a local key to join on and a remote foreign_key to join on. |
A field in a data model can be one of the following:
Here are the available parameters for a field configuration object:
| Parameter | Description |
|---|---|
data_set required |
The slug of the data set to which the field belongs |
table required |
The database table associated with the field |
columns required |
An array of table columns used to calculate the field |
expression |
The (optional) SQL expression used to calculate the field (see the JSON snippet above for an example) |
List the entirety of a data model by its slug.
$ curl -u ':a1b2c3d-your-secure-api-token-4e5f6g7' \
-H 'Content-Type: application/json' \
'https://api.reflect.io/v1/projects/example-project/data-model'
{
"name": "Example Project",
"slug": "example-project",
"description": "An example project and data model.",
"data_sets": [
{
"name": "example_data_set",
"credential": "connection-1",
"tables": [
{
"table": "table1",
"primary_key": "id",
"columns": {
"column1": "text"
}
}
]
}
],
"fields": {
"Field 1": {
"data_set": "example_data_set",
"table": "table1",
"columns": ["column1"]
},
"Field 2": {
"data_set": "example_data_set",
"table": "table1",
"columns": ["column2"]
}
},
"created_at": "2016-02-22T14:31:41.57292-08:00",
"updated_at": "2016-02-22T14:31:41.57292-08:00"
}
Update an existing data model. This will overwrite the existing data model.
$ curl XPUT \
-u ':a1b2c3d-your-secure-api-token-4e5f6g7' \
--data-binary @./data_model.json \
-H 'Content-Type: application/json' \
'https://api.reflect.io/v1/projects/example-project/data-model'
The curl example above assumes that you have this JSON stored in a
data_model.json file:
{
"name": "Example Project",
"slug": "example-project",
"description": "This is an example data model",
"data_sets": [
{
"name": "example_data_set",
"credential": "connection-1",
"tables": [
{
"table": "table1",
"primary_key": "id",
"columns": {
"column1": "text"
}
}
]
}
],
"fields": {
"Field 1": {
"data_set": "example_data_set",
"table": "table1",
"columns": ["column1"]
},
"Field 2": {
"data_set": "example_data_set",
"table": "table1",
"columns": ["column2"]
}
},
"created_at": "2016-02-20T12:06:22.57292-02:11",
"updated_at": "2016-02-22T14:31:41.57292-08:01"
}
Each Reflect view can be configured using a view manifest, which is a JSON object that defines the view’s configuration. A view’s manifest contains both general metadata about the view (see the table directly below) as well as configuration for each visualization component in the view. There are currently five types of visualization component available:
Through the API you can both configure general metadata about a view (see the table directly below) as well as provide configuration for each visualization component in the view.
| Name | Type | Description |
|---|---|---|
slug |
string | A machine-friendly label for the view |
name |
string | A human-friendly label for the view |
identifier |
string | A randomly generated identifier for the view used for basic embedding |
configuration |
object | A configuration object for the view that includes a components array and an options object |
created_at |
timestamp | The date and time at which the view was created |
updated_at |
timestamp | The date and time at which the view was last updated |
identifier |
string | The unique identifier for the view |
{
"name": "Report view",
"slug": "report-view",
"configuration": {
"components": [
{
"slug": "timeseries-component-1",
"group": [],
"id": 1,
"metrics": [],
"title": "Timeseries",
"type": "bars",
"layout": {
"x": 0,
"y": 0,
"w": 12,
"h": 2
}
},
{
"slug": "datagrid-component-1",
"group": [],
"id": 2,
"metrics": [],
"title": "Datagrid",
"type": "datagrid",
"layout": {
"x": 0,
"y": 2,
"w": 12,
"h": 3
}
}
],
"options": {
"default_range": {
"count": 2,
"unit": "week"
},
"date_ranges": [
{
"count": 2,
"unit": "week"
},
{
"count": 1,
"unit": "month"
},
{
"count": 2,
"unit": "month"
},
{
"count": 3,
"unit": "month"
}
],
"control_bars": {
"config": {
"title": "Report"
},
"title": {
"enabled": true
},
"filters": {
"enabled": true
}
},
"dimensions": {},
"filter": [],
"formatters": {},
"metrics": {},
"project_slug": "your-project-slug"
},
"version": "1.1.0"
},
"created_at": "2016-03-10T19:27:35.423353Z",
"updated_at": "2016-03-20T23:48:21.99793Z"
}
There are two values you can provide in the configuration field of a view
object:
| Name | Type | Description |
|---|---|---|
components |
array | A list of per-component configuration objects. For more info, see Component configuration. |
options |
object | A view options configuration object that defines general aspects of the view, e.g. |
Each component in a view consists of its own configuration. This configuration describes the displayed data, how that data is presented, as well as the controls the user can manipulate that component with.
Below, you’ll note that most components accept dimensions, metrics, and/or groups. Typically these are strings that represent that field name in your data model. Constructing them as objects, however, offers expanded flexibility.
To alias a field named “Days” into “Days since launch”:
{ "name": "Days", "alias": "Days since launch" }
Setting dimensions/metrics/groups via the View object only specifies which ones are selectable by the user. If you want to explicitly specify which ones are selected on load:
{ "name": "Days", "selected": true }
This is especially useful when configuring datagrids, as well as components with multiple metrics enabled.
Each component type has a slightly different list of options that can be set on it. However, there are some options that can, and sometimes need to be set on each component.
| Parameter | Type | Description |
|---|---|---|
id required |
string | A unique ID for the component |
type required |
string | One of the currently available component types: bars, timeseries, donut, kpi, or datagrid. |
title required |
string | The title of the component |
controls |
Boolean | Whether or not to render controls |
slug |
string | A human-friendly identifier, particularly useful when building Interactions |
layout required |
object | Describes how the component should be sized and positioned on the (12-column) grid. Includes the following keys: width in columns (w), height in rows (h), x-axis offset in columns (x), y-axis offset in rows (y) |
| Option | Description |
|---|---|
metrics required |
An array of metrics. The first one is selected by default. All others are swappable by the user. |
group required |
An array of dimensions. The first one is selected by default. All others are swappable by the user. |
types |
An array of chart types the user may select from. One of area, bar, or line. The first element in the array is selected by default. |
multiple_metrics |
Boolean that describes whether or not to allow the user to simultaneously select multiple metrics. |
sort |
An object with field, and direction keys that describe how to sort the data. |
legend |
A Boolean that describes whether a legend should be displayed. |
| Option | Description |
|---|---|
metrics required |
An array of metrics. The first one is selected by default. All others are swappable by the user. |
dimensions required |
An array of dimensions. The first one is selected by default. All others are swappable by the user. |
group |
An array of dimensions. The first one is selected by default. All others are swappable by the user. |
pie |
Boolean that describes whether the donut should instead be displayed as a pie. |
limit |
How many rows to display per page. |
legend |
Boolean that describes whether a legend should be displayed. |
| Option | Description |
|---|---|
metric required |
A metric to visualize. |
dimension |
A dimension to visualize. |
sparkline_type |
How to visualize the dimension. One of either area or line. |
| Option | Description |
|---|---|
metrics required |
An array of metrics. The first one is selected by default. All others are swappable by the user. |
dimensions required |
An array of dimensions. The first one is selected by default. All others are swappable by the user. |
group |
An array of dimensions. The first one is selected by default. All others are swappable by the user. |
multiple_metrics |
Boolean that describes whether or not to allow the user to simultaneously select multiple metrics. |
sort |
An object with field, and direction keys that describe how to sort the data. |
limit |
How many rows to display per page. |
legend |
Boolean that describes whether a legend should be displayed. |
| Option | Description |
|---|---|
metrics required |
An array of metrics. The first one is selected by default. All others are swappable by the user. |
dimensions |
An array of dimensions. The first one is selected by default. All others are swappable by the user. |
sort |
An object with field, and direction keys that describe how to sort the data. |
limit |
How many rows to display per page. |
search |
Boolean that describes whether or not to enable search. |
View configurations include not only the configuration for each component, but
also some options you can set for the view itself. These options exist in the
options object.
| Option | Description |
|---|---|
control_bars |
Control bars are what power interactions within your view. Their configuration is documented below. |
date_ranges |
Date ranges are useful when including a datepicker control component. Their configuration is documented below. |
default_range |
An object that represents the default date range to use when the view is initially rendered. They share the structure of elements in the date_ranges option. When omitted, no date range is applied. |
dimensions |
An object that maps fields to dimensions. Keys are field names and values are metric names. |
metrics |
An object that maps fields to metrics. Keys are field names and values are metric names. |
filter |
An array of fields that the user may filter by. This is relevant when using the filters control component. |
formatters |
An object that allows you to define which fields are formatted, and how. The keys are field names and the values are one of the supported formatters (listed below). |
project_slug |
The slug of the project that this view belongs to. |
version |
The version of the manifest schema. We recommend you don’t change this manually. |
Control bars are rows that consist of control components. Control components power the interactions within your views.
The control_bars object consists of a config object that allows for
configuration of individual control bars.
Each control bar is then enabled by appending a key with one of title,
datepicker, or filters, and a value of { enabled: true }.
The datepicker control component has some additional configuration described
below.
When using the datepicker component, users can drill down into their views by
date. Users are able to choose a preset date range to filter on.
date_ranges is an array of objects, each representing a range option. Within
each object, count is an integer, and unit is a unit of time, such as
year, month, week, day, or hour. They are all relative to now, so an
object equaling {count: 3, unit: “week”} represents “three weeks ago until
now”.
default_range shares the same structure, but defines the range initially used
when the view is initially rendered.
When datepicker is enabled, components will have an additional time option
that allows you to select which time field should be filtered on through the
datepicker.
An optional filters array can be defined off of the root configuration object.
| Option | Description |
|---|---|
field required |
A filterable field defined in your data model |
op required |
One of: =, !=, >, <, >=, or <= |
value required |
The value to filter with. |
removable |
A Boolean that indicates whether or not this filter is removable by the user. Only applies when the filter control component is in use. When it’s set to false, it’s also invisible to the user. The default is true. |
We support a number of different types of formatters for the values of fields. More info on formatters can be found in our Embedding tutorial.
Lists all of the views associated with a project (identified by slug).
$ curl -u ':a1b2c3d-your-secure-api-token-4e5f6g7' \
-H 'Content-Type: application/json' \
'https://api.reflect.io/v1/projects/your-project-1/views'
[
{
"name": "Your View 1",
"identifier": "a1b2c3-view-identifier-d4e5f6",
"slug": "your-view-1",
"configuration": {
"some": ["configuration-goes-here"]
},
"created_at": "2017-01-10T20:41:48.176742Z",
"updated_at": "2017-01-10T20:41:26.711196Z"
}
]
Creates a new view and associates it with a project (identified by project
slug). The slug for the view must be unique; if it is not unique, a 412
Precondition Failed error will be returned by
the API, along with details.
$ curl -u ':a1b2c3d-your-secure-api-token-4e5f6g7' \
--data-binary @./view.json \
-H 'Content-Type: application/json' \
'https://api.reflect.io/v1/projects/your-project-1/views'
The curl example above assumes that you have this JSON stored in a
view.json file:
{
"name": "Your new view",
"slug": "your-view-1"
}
{
"name": "View Name",
"identifier": "viewIdentifier",
"slug": "your-view-1",
"configuration": {
"some": ["configuration", "goes", "here"]
},
"created_at": "2017-01-10T20:41:48.176742Z",
"updated_at": "2017-01-10T20:41:26.711196Z"
}
Fetches a view, identified by slug, associated with a specific project, also
identified by slug. If the view does not exist, a 404 Not
Found error will be returned.
$ curl -u ':a1b2c3d-your-secure-api-token-4e5f6g7' \
-H 'Content-Type: application/json' \
'https://api.reflect.io/v1/projects/your-project-1/views/your-view-1'
{
"name": "View Name",
"identifier": "viewIdentifier",
"template": "blank",
"slug": "your-view-1",
"configuration": {
"some": ["configuration", "goes", "here"]
},
"created_at": "2017-01-10T20:41:48.176742Z",
"updated_at": "2017-01-10T20:41:26.711196Z"
}
Updates an existing view, identified by slug, associated with a specific project, also identified by slug.
$ curl -XPUT \
-u ':a1b2c3d-your-secure-api-token-4e5f6g7' \
-H 'Content-Type: application/json' \
--data-binary @./view.json \
'https://api.reflect.io/v1/projects/your-project-1/views/your-view-1'
The curl example above assumes that you have this JSON stored in a
view.json file:
{
"configuration": {
"some": ["configuration", "goes", "here"]
}
}
{
"name": "View Name",
"identifier": "viewIdentifier",
"template": "blank",
"slug": "your-view-1",
"configuration": {
"some": ["configuration", "goes", "here"]
},
"created_at": "2017-01-10T20:41:48.176742Z",
"updated_at": "2017-01-10T20:41:26.711196Z"
}
Deletes a view. If the request is successful, a 201
Created will be returned along with the view
that you just deleted in the body.
$ curl -XDELETE \
-u ':a1b2c3d-your-secure-api-token-4e5f6g7' \
-H 'Content-Type: application/json' \
'https://api.reflect.io/v1/projects/your-project-1/views/your-view-1'
We support a number of different types of formatters. These are configured on a per-field bases in the view options.
| Name | Description | Example Input | Example Output |
|---|---|---|---|
percentage |
Multiply the field by 100 and format it as a percentage. | 0.10 | 10% |
numeric_percentage |
Format the field as a percentage but don’t apply the multiplication. | 0.10 | 0.10% |
dollars |
Format the field as US dollars. | 100.125 | $100.13 |
decimal |
Format the field as a number with 2 decimal places. | 100.125 | 100.12 |
numeric |
Format the field as a number with a number with no decimal places. | 100.125 | 100 |
month |
Format a timestamp field as its month in English. | 2015-01-01 12:15:00-07:00 | January 2015 |
date |
Format a timestamp field as a date. | 2015-01-01 12:15:00-07:00 | 01/01/2015 |
date_with_hour |
Format a timestamp field as a date with its hour. | 2015-01-01 12:15:00-07:00 | 01/01/2015 12:00 PM |
date_with_time |
Format a timestamp field as a date with its hour and minute. | 2015-01-01 12:15:00-07:00 | 01/01/2015 12:15 PM |
lowercase |
Format a string field in lowercase. | Darth Vader | darth vader |
uppercase |
Format a string field in uppercase. | Darth Vader | DARTH VADER |
web_content |
Within a string field, find all of the URLs and turn them in to links. | Check out http://www.google.com | Check out http://www.google.com |
image |
Turn the string field in to an image. | http://tiny.cc/7wwqiy |
Reflect’s exporting endpoints allow you to generate a report, then retrieve the output of that report in CSV format.
Fetching a data export from the API is a two-step process. You must:
POST
request to the /export endpoint for the project; and thenGET the
export.These steps are laid out in detail in the sections below.
This step accepts and saves your report settings (outlined below), and on
success will return a 201 Created along with a unique identifier for your
export.
The following JSON fields may be supplied in the POST body:
| Name | Type | Description |
|---|---|---|
dimensions |
array | An array of dimension names to report on. |
metrics |
array | An array of metric names to report on. |
sort |
object | An object with field and direction keys, to specify sort. |
timezone |
string | The desired timezone to report in. |
The following fields will be included in the response:
| Name | Type | Description |
|---|---|---|
created_at |
string | The date and time the export was created. |
updated_at |
string | The date and time the export was updated. |
identifier |
string | The unique identifier for the export, used to retrieve its data. |
settings |
object | The settings, outlined above, for the export request. |
$ curl -XPOST \
-u ':a1b2c3d-your-secure-api-token-4e5f6g7' \
-H 'Content-Type: application/json' \
--data-binary @./export.json \
'https://api.reflect.io/v1/:project-slug/export'
The curl example above assumes that you have this JSON stored in a
export.json file:
{
"dimensions": ["Name"],
"metrics": ["Places lived"]
}
{
"identifier": "1234-abcd-efghi-jklmn",
"settings": {
"dimensions": ["Name"],
"metrics": ["Places lived"]
},
"created_at": "2016-03-10T19:27:35.423353Z",
"updated_at": "2016-03-10T19:27:35.423353Z"
}
Using the identifier given to you in the response of the
previous request, this endpoint will return a CSV
of your data with Content-Type: text/csv.
$ curl -u ':a1b2c3d-your-secure-api-token-4e5f6g7' \
-H 'Content-Type: application/json' \
'https://api.reflect.io/v1/export/:export-identifier'
A 200 OK will be returned on success. This endpoint accepts no other
parameters.
Reflect offers a team members feature, available through the REST API, that enables you to delegate access to your account to other people that you work with. Both the owner of the account and non-owners invited to share the account may issue calls to this endpoint, including adding and removing other team members. The owner of the account, however, cannot be removed or changed.
Team members whom you invite to your account can view and modify everything in your account (except for login information). That includes all views, data models, projects, access and secret keys, and database connections. In other words, there is currently no ownership model in Reflect outside of account ownership.
| Name | Type | Description |
|---|---|---|
id |
integer | The ID of the team member |
email |
string | The email address of your team member |
name |
string | A name for your team member |
company |
string | The company name for your team member. This is automatically inherited from the inviting user’s account. |
is_owner |
Boolean | Whether the team member is the account owner |
is_confirmed |
Boolean | Whether the team member has accepted their invitation to Reflect |
created_at |
timestamp | The date and time at which the team member’s account was created |
{
"id": 1,
"email": "george@a-team.com",
"name": "George Peppard",
"company": "The A Team",
"is_owner": true,
"is_confirmed": true,
"created_at": "2016-03-10T19:27:35.423353Z"
}
Lists all of the team members associated with your account.
$ curl -u ':a1b2c3d-your-secure-api-token-4e5f6g7' \
-H 'Content-Type: application/json' \
'https://api.reflect.io/v1/team-members'
[
{
"id": 1,
"email": "george@a-team.com",
"name": "George Peppard",
"company": "The A Team",
"is_owner": true,
"is_confirmed": true,
"created_at": "2016-03-10T19:27:35.423353Z"
},
{
"id": 2,
"email": "Dirk Benedict",
"name": "dirk@a-team.com",
"company": "The A Team",
"is_owner": false,
"is_confirmed": true,
"created_at": "2016-03-10T19:27:35.423353Z"
}
]
Invite a team member to use Reflect. The user will receive an email to confirm
their account shortly after the invitation is complete. A 201
Created will be returned if the user can be
invited to your account.
If the user cannot be invited to be a team member (e.g. they already have a Reflect account) then an error will be returned.
$ curl -XPOST \
-u ':a1b2c3d-your-secure-api-token-4e5f6g7' \
-H 'Content-Type: application/json' \
--data-binary @./team-member.json \
'https://api.reflect.io/v1/team-members'
The curl example above assumes that you have this JSON stored in a
team-member.json file:
{
"name": "Mr. T",
"email": "mr-t@a-team.com"
}
{
"id": 3,
"email": "mr-t@a-team.com",
"name": "Mr. T",
"company": "The A Team",
"is_owner": false,
"is_confirmed": false,
"created_at": "2016-03-10T19:27:35.423353Z"
}
Removes a team member’s access to your account. The team member’s account will still be functional–they will be able to log in and create their own projects, views, etc., but they’ll lose access to anything you’ve already created.
If the request is successful, a 200 OK will
be returned along with an empty body.
$ curl -XDELETE \
-u ':a1b2c3d-your-secure-api-token-4e5f6g7' \
-H 'Content-Type: application/json' \
'https://api.reflect.io/v1/team-members/3'
All errors emitted by the Reflect API are wrapped in a JSON object that provides:
status (which will always match the HTTP code
returned by the call)code, which is essentially a brief slug for the error. A complete
listing of codes can be found in Error Codes below.message containing narrative-style insight into what went wrong.There are also two sub-classes of error, validation and agent errors, that you may encounter when interacting with our API.
{
"error": {
"status": 400,
"code": "invalid_body",
"message": "Failed to decode body."
}
}
| Code | HTTP code | Meaning |
|---|---|---|
invalid_credentials |
401 | The credentials you provided are invalid and this resource can’t be accessed |
unknown |
500 | An unknown internal server error occurred |
internal_error |
500 | Internal server error (basically equivalent to unknown) |
invalid_body |
400 | The JSON request body that you provided could not be decoded |
invalid_object |
406 | There was an issue with the submitted object |
invalid_reflect_js |
400 | You’re using a version of Reflect.js on the client side that is too old to compare reports |
api_token_not_found |
404 | The API token you requested was not found (this is not an auth error, but rather a resource error) |
not_found |
404 | The resource you requested wasn’t found |
project_not_found |
404 | No project with the provided slug was found |
agent_error |
502 | The Reflect Agent returned an error when attempting to fulfill the request |
agent_ping_failed |
502 | An error occurred while trying to connect to the specified Reflect Agent |
connection_exists |
412 | The specified connection is already associated with the specified project |
invalid_report_settings |
400 | There was an issue with the report that you requested |
For a listing of Agent-related error messages, see the table below.
Validation errors are emitted when you attempt to create or modify a resource but supply a malformed JSON object.
If a validation-related error occurs during your request, a standard error
object will be returned along with a messages object listing field-specific
errors; each validation error included in the messages array will include the
field name as the key and a list of field-specific errors as the value.
{
"error": {
"status": 406,
"code": "invalid_object",
"message": "There were some problems with your submission."
},
"messages": {
"slug": [
"You must specify a slug for this data model."
]
}
}
If an Agent-related error occurs, you will receive a normal error
object from the API along with a messages array that includes
all of the specific error objects received from the Agent.
| Code | HTTP code | Meaning |
|---|---|---|
unknown |
500 | An unknown Agent error occurred |
unknown_error_with_reason |
500 | An unexpected error occurred, but an error message is still provided |
internal_error |
500 | An unspecified error occurred within the Agent |
read_only |
409 | The service is currently running in read-only mode; try the request later |
unreadable_json |
400 | The JSON request body could not be decoded |
invalid_credential |
406 | An invalid connection was supplied for a database connection |
unknown_credential |
404 | The connection with the specified slug was not found |
report_generation_failed |
502 | The specified report could not be successfully generated |
credential_registration_failed |
500 | An error occurred while attempting to register the database connection |
snapshot_failed |
500 | A snapshot (backup) of the database failed |
invalid_driver_type |
406 | The database driver that you specified was not recognized |
error_testing_credential |
406 | The supplied connection could not be used to connect to the database |
failed_testing_credential |
406 | Testing the database connection failed, but no explicit error was thrown; could stem from a permissions issue |
credential_metadata_failed |
500 | Metadata for the specified connection could not be fetched |
corrupt_snapshot |
406 | The snapshot (backup) of the database that you tried to load is corrupted |
invalid_request_type |
400 | The requested operation is not understood by this Agent |
canceled |
410 | The requested operation has been canceled |
authentication_failed |
401 | The specified authentication credentials are not valid |
already_configured |
409 | You’re attempting to configure an Agent that’s already been configured |
not_clustered |
400 | This Agent is not part of a cluster, which is required for this operation to succeed |
{
"error": {
"status": 502,
"code": "agent_error",
"message": "The Reflect Agent returned an error fulfilling this request."
},
"messages": [
{
"status": 502,
"code": "report_generation_failed",
"message": "Report generation failed."
}
]
}