Synthesio API Format

Introduction

Synthesio API is a specification for how a client should request that resources be fetched or modified, and how a server should respond to those requests.

Conventions

The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119 [RFC2119].

Content Negotiation

Client Responsibilities

Clients MUST send all API data in request documents with the header Content-Type: application/json without any media type parameters.

Clients MUST ignore any parameters for the application/json media type received in the Content-Type header of response documents.

Server Responsibilities

Servers MUST send all API data in response documents with the header Content-Type: application/json without any media type parameters.

Servers MUST respond with a 415 Unsupported Media Type status code if a request specifies the header Content-Type: application/json with any media type parameters.

Document Structure

Synthesio API documents are defined in JavaScript Object Notation (JSON) [RFC7159].

Top Level

A JSON object MUST be at the root of every Synthesio API request and response containing data. This object defines a document’s “top level”.

A document MUST contain at least one of the following top-level members:

  • data: the document’s “primary data”

  • errors: an array of error objects

  • meta: a meta object that contains non-standard meta-information.

The members data and errors MAY coexist in the same document. In this case, errors can refer to only a part of the requested operation or be warnings.

A document MAY also contain this top-level member:

  • included: an array of resource objects that are related to the primary data and/or each other (“included resources”).

If a document does not contain a top-level data key, the included member MUST NOT be present either.

The document’s “primary data” is a representation of the resource or collection of resources targeted by a request.

Primary data MUST be either:

A logical collection of resources MUST be represented as an array, even if it only contains one item or is empty.

Resource Identifiers

A “resource identifier” is an unique resource identifier for a given object type. It MUST be a JSON string.

Resource Objects

“Resource objects” appear in a Synthesio API document to represent resources.

A resource object MUST contain at least the following top-level member:

Exceptions

  • The id member is not required when the resource object originates at the client and represents a new resource to be created on the server.

  • The id member is not required when the response data is the result of an action, as it does not represent a resource object.

In addition, a resource object MAY contain any additional attributes as top-level members. Relationships can be either expanded as an object in the attributes or a reference to a resource identifier. If so the attribute name MUST have the _id suffix. API documentation must explicitly define if relationships are given by references or directly expanded.

For one-to-many relationships, the attribute name MUST not change from singular to plural and MUST use the suffix _list. An attribute with this suffix SHOULD be an array of objects.

An attribute with the suffix _list_id SHOULD be an array of strings containing resource identifiers.

Attributes

Attributes may contain any valid JSON value.

Complex data structures involving JSON objects and arrays are allowed as attribute values.

Special suffixes:

  • _id can be used to reference related resources identifiers, if so, it must be considered as foreign key.

  • _list can be used to indicate a one-to-many (or a many-to-many) relationship, if so value MUST be an array of objects.

  • _list_id can be used to reference related resources identifiers, if so, it MUST be an array of strings.

  • _id_list SHOULD NOT be used to avoid confusion.

These _id references MAY or MAY NOT be included as related resources.

Resource Linkage

Resource linkage in a compound document allows a client to link together all of the included resource objects without having to request any other URLs.

Resource linkage MUST be represented as one of the following:

  • null for empty to-one relationships.

  • an empty array ([]) for empty to-many relationships.

  • a single resource identifier for non-empty to-one relationships.

  • an array of resource identifier for non-empty to-many relationships.

For example, the following dashboard is associated with a client, and various reports, but is not associated with any workspace.

// ...
{
  "id": "1",
  "title": "Synthesio Dashboard",
  "client": {
    "id": "1",
    "name": "Synthesio"
  },
  "workspace_id": null,
  "report_list_id": [
    "1",
    "2"
  ]
}
// ...

Compound Documents

To reduce the number of HTTP requests, servers MAY allow responses that include related resources along with the requested primary resources. Such responses are called “compound documents”.

In a compound document, all included resources MUST be represented as an array of resource objects named by the resource type in the top-level included object.

Resource array type MUST be named with the same name without _list and _id suffixes.

Compound documents require “full linkage”, meaning that every included resource MUST be identified by at least one resource identifier in the same document. These resource identifiers could either be primary data or represent resource linkage contained within primary or included resources.

The only exception to the full linkage requirement is when relationship fields that would otherwise contain linkage data are excluded via sparse fieldsets or included resources limitations.

A complete example document with multiple included relationships, for an URI that return objects of the dashboard type:

{
  "data": [{
    "id": "1",
    "title": "Synthesio Dashboard",
    "client": {
      "id": "1",
      "name": "Synthesio"
    },
    "workspace_id": "50",
    "report_list_id": [
      "2",
      "3"
    ]
  }],
  "included": {
    "report": [
      {
        "id": "2",
        "name": "Synthesio main report"
      },
      {
        "id": "3",
        "name": "Synthesio other report"
      }
    ],
    "workspace": [
      {
        "id": "50",
        "name": "Synthesio workspace"
      }
    ]
  }
}

A compound document MUST NOT include more than one resource object for an id for a given type.

Meta Information

Where specified, API responses can have a meta member to include non-standard meta-information. The value of each meta member MUST be an object (a “meta object”).

Any members MAY be specified within meta objects.

For example:

{
  "meta": {
    "copyright": "Copyright 2015 Example Corp.",
  },
  "data": {
    // ...
  }
}

Member Names

All member names used in a Synthesio API document MUST be treated as case sensitive by clients and servers, and they MUST meet all of the following conditions:

  • Member names MUST contain at least one character.

  • Member names MUST contain only the allowed characters listed below.

  • Member names MUST start and end with a “globally allowed character”, as defined below.

To enable an easy mapping of member names to URLs, it is RECOMMENDED that member names use only non-reserved, URL safe characters specified in RFC 3986.

Allowed Characters

The following “globally allowed characters” MAY be used anywhere in a member name:

  • U+0061 to U+007A, “a-z”

  • U+0030 to U+0039, “0-9”

  • U+0080 and above (non-ASCII Unicode characters; not recommended, not URL safe)

Additionally, the following characters are allowed in member names, except as the first or last character:

  • U+002D HYPHEN-MINUS, “-”

  • U+005F LOW LINE, “_”

  • U+0020 SPACE, “ “ (not recommended, not URL safe)

Reserved Characters

The following characters MUST NOT be used in member names:

  • U+002B PLUS SIGN, “+” (used for ordering)

  • U+002C COMMA, “,” (used as a separator between relationship paths)

  • U+002E PERIOD, “.” (used as a separator within relationship paths)

  • U+005B LEFT SQUARE BRACKET, “[” (used in sparse fieldsets)

  • U+005D RIGHT SQUARE BRACKET, “]” (used in sparse fieldsets)

  • U+0021 EXCLAMATION MARK, “!”

  • U+0022 QUOTATION MARK, ‘”’

  • U+0023 NUMBER SIGN, “#”

  • U+0024 DOLLAR SIGN, “$”

  • U+0025 PERCENT SIGN, “%”

  • U+0026 AMPERSAND, “&”

  • U+0027 APOSTROPHE, “’”

  • U+0028 LEFT PARENTHESIS, “(”

  • U+0029 RIGHT PARENTHESIS, “)”

  • U+002A ASTERISK, “*”

  • U+002F SOLIDUS, “/”

  • U+003A COLON, “:”

  • U+003B SEMICOLON, “;”

  • U+003C LESS-THAN SIGN, “<”

  • U+003D EQUALS SIGN, “=”

  • U+003E GREATER-THAN SIGN, “>”

  • U+003F QUESTION MARK, “?”

  • U+0040 COMMERCIAL AT, “@”

  • U+005C REVERSE SOLIDUS, “”

  • U+005E CIRCUMFLEX ACCENT, “^”

  • U+0060 GRAVE ACCENT, “`”

  • U+007B LEFT CURLY BRACKET, “{”

  • U+007C VERTICAL LINE, “|”

  • U+007D RIGHT CURLY BRACKET, “}”

  • U+007E TILDE, “~”

  • U+007F DELETE

  • U+0000 to U+001F (C0 Controls)

Fetching Data

Fetching resources

Standard resources data, including relationships, can be fetched by sending a GET request to an endpoint.

Responses can be further refined with the optional features described in responses section.

POST fallback for long URLs

GET endpoints MUST accept request as a POST, specifying in the payload at top level a _method attribute with value GET and a _parameters attribute with the url encoded query string. This allow to avoid potential problems when reaching URL length limits with optional parameters.

When sending a POST request without the method attribute, the server will understand the request as a POST.

For example these two requests MUST give the same result:

GET /dashboards/1 HTTP/1.1
POST /dashboards/1 HTTP/1.1
Content-Type: application/json

{
  "_method": "GET",
  "_parameters": "size=10&some_parameter=value"
}

Fetching action’s results

Data produced as the result of an action MUST be fetched by sending a POST request. Action routes MUST use the _ prefix in their last URL component name.

Example:

POST /mention/v2/reports/15/_search HTTP/1.1
Content-Type: application/json

Responses

200 OK

A server MUST respond to a successful request to fetch an individual resource or resource collection with a 200 OK response.

A server MUST respond to a successful request to fetch a resource collection with an array of resource objects or an empty array ([]) as the response document’s primary data.

For example, a GET request to a collection of articles could return:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "data": [{
    "id": "1",
    "title": "Synthesio API paints my bikeshed!"
  },
  {
    "id": "2",
    "title": "Rails is Omakase"
  }]
}

A similar response representing an empty collection would be:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "data": []
}

A server MUST respond to a successful request to fetch an individual resource with a resource object or null provided as the response document’s primary data.

null is only an appropriate response when the requested URL is one that might correspond to a single resource, but doesn’t currently.

For example, a GET request to an individual article could return:

Request: /articles/1

HTTP/1.1 200 OK
Content-Type: application/json

{
  "data": {
    "id": "1",
    "title": "Synthesio API paints my bikeshed!",
    "author_id": "1"
  }
}

If the above article’s author is missing, then a GET request to that related resource would return:

Request: /articles/1/author

HTTP/1.1 200 OK
Content-Type: application/json

{
  "data": null
}
404 Not Found

A server MUST respond with 404 Not Found when processing a request to fetch a single resource that does not exist, except when the request warrants a 200 OK response with null as the primary data (as described above).

Other Responses

A server MAY respond with other HTTP status codes.

A server MAY include error details with error responses.

A server MUST prepare responses, and a client MUST interpret responses, in accordance with HTTP semantics.

Sparse Fieldsets

A client MAY request that an endpoint return only specific fields in the response on a per-type basis by including a fields[TYPE] parameter.

The value of the fields parameter MUST be a comma-separated (U+002C COMMA, “,”) list that refers to the name(s) of the fields to be returned.

If a client requests a restricted set of fields for a given resource type, an endpoint MUST NOT include additional fields in resource objects of that type in its response.

POST /reports/1/_search?fields[mention]=title,content&fields[author]=full_name HTTP/1.1
Accept: application/json

Errors

Processing Errors

A server MAY choose to stop processing as soon as a problem is encountered, or it MAY continue processing and encounter multiple problems. For instance, a server might process multiple attributes and then return multiple validation problems in a single response.

When a server encounters multiple problems for a single request, the most generally applicable HTTP error code SHOULD be used in the response. For instance, 400 Bad Request might be appropriate for multiple 4xx errors or 500 Internal Server Error might be appropriate for multiple 5xx errors.

Error Objects

Error objects provide additional information about problems encountered while performing an operation. Error objects MUST be returned as an array keyed by errors in the top level of a Synthesio API document.

An error object MAY have the following members:

  • id: a unique identifier for this particular occurrence of the problem.

  • status: the HTTP status code applicable to this problem, expressed as a string value.

  • code: an application-specific error code, expressed as a string value.

  • title: a short, human-readable summary of the problem that SHOULD NOT change from occurrence to occurrence of the problem, except for purposes of localization.

  • detail: a human-readable explanation specific to this occurrence of the problem. Like title, this field’s value can be localized.

  • meta: a meta object containing non-standard meta-information about the error.