Native API
TrackVision offers both a native REST and GraphQL API to manage the data in the database. The API has predictable resource-oriented URLs, relies on standard HTTP status codes, and uses JSON for input and output. The native API is dynamic - when you make configuration changes to the data model in your installation, the changes are reflected immediately in the API. This means that the exact input/output of the API may vary depending on the amount of configuration and customisation you have performed.
REST vs. GraphQL
There is no difference in the functionality available between the native REST and GraphQL endpoints. The functionality available in both is mapped to the same set of core services, meaning that you don't lose any performance or capabilities by choosing one or the other - which one you choose is up to you.
Your API endpoints
The REST API endpoint of your TrackVision installation is simply the domain of your application that you log into: for example https://mybrand.trackvision.ai
The GraphQL API endpoint of your TrackVision installation is the domain that you log into suffixed with /graphql; for example https://mybrand.trackvision.ai/graphql
Authentication
By default, all data in the system is off-limits for unauthenticated users. To gain access to protected data, you must include an access token or session cookie with every request.
Useful references:
Relational Data
By default, TrackVision only retrieves the reference value of a relational field in your data. To also retrieve nested
data of a relational field the fields parameter in REST can be used, or regular nested
queries in GraphQL. This allows you to retrieve product data and the associated owning organisation details in one request, for example.
Creating / Updating / Deleting
Similarly to fetching, relational content can be modified deeply as well.
Many-to-One
Many-to-One relationships are fairly straightforward to manage relationally. You can simply submit the changes you want as an object under the relational key in your collection. For example, if you wanted to create a new featured brand for a product, you could submit:
{
"brand": {
"brand_name": "My shiny brand!"
}
}
This will create a new record in the related collection, and save its primary key in the brand field for
this item. To update an existing item, simply provide the primary key with the updates, and TrackVision will treat it as an
update instead of a creation:
{
"brand": {
"id": 15,
"brand_name": "This is an updated name for my brand!"
}
}
Seeing that the Many-to-One relationship stores the foreign key on the field itself, removing the item can be done by nullifying the field:
{
"brand": null
}
One-to-Many (/ Many-to-Many)
One-to-Many, and therefore Many-to-Many and Many-to-Any, relationships can be updated in one of two ways:
Basic
The API will return one-to-many fields as an array of nested keys or items (based on the fields parameter). You can
use this same structure to select what the related items are:
{
"children": [2, 7, 149]
}
You can also provide an object instead of a primary key in order to create new items nested on the fly, or an object with a primary key included to update an existing item:
{
"children": [
2, // assign existing item 2 to be a child of the current item
{
"name": "A new nested item"
},
{
"id": 149,
"name": "Assign and update existing item 149"
}
]
}
To remove items from this relationship, simply omit them from the array:
{
"children": [2, 149]
}
This method of updating a one-to-many is very useful for smaller relational datasets.
"Detailed"
Alternatively, you can provide an object detailing the changes as follows:
{
"children": {
"create": [{ "name": "A new nested item" }],
"update": [{ "id": 149, "name": "A new nested item" }],
"delete": [7]
}
}
This is useful if you need to have more tightly control on staged changes, or when you're working with a big relational dataset.
Many-to-Any (Union Types)
Many-to-Any fields work very similar to a "regular" many-to-many, with the exception that the related field can pull in the fields from any of the related collections, for example:
{
"sections": [
{
"collection": "headings",
"item": {
/* headings fields */
}
},
{
"collection": "paragraphs",
"item": {
/* paragraphs fields */
}
}
]
}
System data in GraphQL
Due to restrictions in GraphQL itself, it's impossible to properly scope/namespace system functionality from regular
data access. In order to prevent any naming conflicts between user-created and system data, we've scoped the access of
the two into separate endpoints for user and system data respectively: /graphql and /graphql/system. Both endpoints
share the same underlying schema, so nested relations will work as expected regardless if they "cross over" between
user and system data. The only difference in the two endpoints are the root query and mutation fields available.
Error Codes
Below are the global error codes used within TrackVision, and what they mean.
| Error Code | HTTP Status | Description |
|---|---|---|
FAILED_VALIDATION | 400 | Validation for this particular item failed |
FORBIDDEN | 403 | You are not allowed to do the current action |
INVALID_TOKEN | 403 | Provided token is invalid |
TOKEN_EXPIRED | 401 | Provided token is valid but has expired |
INVALID_CREDENTIALS | 401 | Username / password or access token is wrong |
INVALID_IP | 401 | Your IP address isn't allow-listed to be used with this user |
INVALID_OTP | 401 | Wrong OTP was provided |
INVALID_PAYLOAD | 400 | Provided payload is invalid |
INVALID_QUERY | 400 | The requested query parameters can not be used |
UNSUPPORTED_MEDIA_TYPE | 415 | Provided payload format or Content-Type header is unsupported |
REQUESTS_EXCEEDED | 429 | Hit the rate limit |
ROUTE_NOT_FOUND | 404 | Endpoint does not exist |
SERVICE_UNAVAILABLE | 503 | Could not use external service |
UNPROCESSABLE_CONTENT | 422 | You tried doing something illegal |
To prevent leaking which items exist, all actions for non-existing items will return a FORBIDDEN error.