API Documentation for SPY Systems
SPY System API V2 Documentation: Style and Product Data Management
This document describes how developers can authenticate and communicate with the SPY System API V2, which is specifically designed for managing style and product-related data.
OpenAPI Specification (OAS)
We leverage OpenAPI to document our API endpoints, ensuring compatibility with various development tools:
- OpenAPI Generator: Generate client libraries for your preferred programming languages (e.g., PHP, C#, Ruby, Python, and many more).
- Postman: Perform quick tests against endpoints without integrating them directly into your codebase.
API Structure
The API adheres to the JSON:API specification for consistency and predictability.
For each resource (e.g., Style, Brand, Type), we provide one or more endpoints for common operations such as listing, fetching, and, where applicable, updating and deleting.
The basic URI structure follows this pattern:
/ [use-case] / [resource-name] / [resource-id] / [sub-resource-name] / [sub-resource-id]
Examples for Style Endpoints (/pdm/styles
):
- List Styles:
GET /pdm/styles
- Create Style:
POST /pdm/styles
(with required data in the request body) - Fetch Single Style:
GET /pdm/styles/{styleId}
- Update Style:
PATCH /pdm/styles/{styleId}
Authentication
All API V2 endpoints require an authentication token.
- Obtain Token: Call
POST /auth/login
and provide yourclientId
andclientSecret
in the request body to receive a short-lived authorization token. - Add to Header: Include this token in the
X-Spy-Authorization
header key for all subsequent authenticated requests.
Important: Authorization tokens can expire at any time. Your application should be prepared to handle token expiration and re-authenticate as needed.
Resource Object Structure
A resource object in the API V2 follows the standard JSON:API format:
{
"type": "resource-type",
"id": "1",
"attributes": {
"attribute1": "value",
"attribute2": false
},
"relationships": {
"relationship-to-one": {
"data": {
"type": "sub-type",
"id": 1
}
},
"relationship-to-many": {
"data": [
{
"type": "sub-type2",
"id": "2"
},
{
"type": "sub-type2",
"id": "3"
}
]
}
}
}
Listing Resources
To retrieve a list of resources, send a GET
request to the collection endpoint, e.g., GET /pdm/styles
.
Example Response for Listing Styles:
{
"links": {
"first": "https://demo.spysystem.dk/api/v2/pdm/styles?page[token]=abc&page[offset]=0",
"last": "https://demo.spysystem.dk/api/v2/pdm/styles?page[token]=abc&page[offset]=10",
"prev": null,
"next": "https://demo.spysystem.dk/api/v2/pdm/styles?page[token]=abc&page[offset]=1"
},
"data": [
{
"type": "style",
"id": "1",
"attributes": {
"styleNo": "S1000",
"styleName": "First style"
},
"relationships": {
"brand": {
"data": {
"type": "brand",
"id": "1"
}
},
"styleColors": {
"data": [
{
"type": "styleColor",
"id": "1"
},
{
"type": "styleColor",
"id": "2"
}
]
}
}
},
{
"type": "style",
"id": "2",
"attributes": {
"styleNo": "S1001",
"styleName": "Second style"
},
"relationships": {
"brand": {
"data": {
"type": "brand",
"id": "1"
}
},
"styleColors": {
"data": [
{
"type": "styleColor",
"id": "3"
},
{
"type": "styleColor",
"id": "4"
}
]
}
}
}
]
}
Fetching a Single Resource
To retrieve a specific resource, append its ID to the resource endpoint, e.g., GET /pdm/styles/1
.
Example Response for Fetching a Single Style:
{
"data": {
"type": "style",
"id": "1",
"attributes": {
"styleNo": "S1000",
"styleName": "First style"
},
"relationships": {
"brand": {
"data": {
"type": "brand",
"id": "1"
}
}
},
"styleColors": {
"data": [
{
"type": "styleColor",
"id": "1"
},
{
"type": "styleColor",
"id": "2"
}
]
}
}
}
To minimize API calls, you can include related resources directly in your primary request by using the include
query parameter. For example, to include styleColors
when fetching styles: GET /pdm/styles?include=styleColors
.
Example Response with Included styleColors
:
{
"data": {
"type": "style",
"id": "1",
"attributes": {
"styleNo": "S1000",
"styleName": "First style"
},
"relationships": {
"brand": {
"data": {
"type": "brand",
"id": "1"
}
},
"styleColors": {
"data": [
{
"type": "styleColor",
"id": "1"
},
{
"type": "styleColor",
"id": "2"
}
]
}
}
},
"included": {
"styleColor": {
"1": {
"type": "styleColor",
"id": "1",
"attributes": {
"active": true,
"noosType": "none"
},
"relationships": {
"color": {
"data": {
"type": "color",
"id": "1"
}
}
}
},
"2": {
"type": "styleColor",
"id": "2",
"attributes": {
"active": true,
"noosType": "noos"
},
"relationships": {
"color": {
"data": {
"type": "color",
"id": "2"
}
}
}
}
}
}
}
Important Considerations:
- Including too many resources can be resource-intensive and may lead to performance issues or rate limits.
- Refer to the specific endpoint documentation to determine which resources are available for inclusion.
Fetching a Subset of Attributes/Relationships (Sparse Fieldsets)
To optimize data transfer, you can request only specific attributes or relationships for a resource using the fields_[resource_type]
query parameter.
Example: Fetching styleNo
and brand
for a Style:
GET /pdm/styles?fields_style=styleNo,brand
{
"data": {
"type": "style",
"id": "1",
"attributes": {
"styleNo": "S1000"
},
"relationships": {
"brand": {
"data": {
"type": "brand",
"id": "1"
}
}
}
}
}
This also applies to included resources.
Example: Fetching specific fields for included resources:
GET /pdm/styles?include=styleColors&fields_style=styleNo,styleColors&fields_styleColor=active
{
"data": {
"type": "style",
"id": "1",
"attributes": {
"styleNo": "S1000"
},
"relationships": {
"styleColors": {
"data": [
{
"type": "styleColor",
"id": "1"
},
{
"type": "styleColor",
"id": "2"
}
]
}
}
},
"included": {
"styleColor": {
"1": {
"type": "styleColor",
"id": "1",
"attributes": {
"active": true
}
},
"2": {
"type": "styleColor",
"id": "2",
"attributes": {
"active": true
}
}
}
}
}
Filtering Resources
Most GET
endpoints support filtering resources by adding ?filter[field]=value
to the request URL.
Examples:
- Filter active colors:
GET /pdm/colors?filter[active]=true
- Filter styles by brand ID:
GET /pdm/styles?filter[brandId]=1
Pagination
List endpoints typically return a maximum of 50 resources by default. You can adjust this limit using ?page[limit]
, with values between 1 and 250 (e.g., ?page[limit]=100
).
To retrieve additional items, use the pagination links provided in the links
object of the response, or leverage the meta.pageToken
with page[offset]
.
Example: Initial request for 1 style:
GET /pdm/styles?page[limit]=1
{
"meta": {
"pageToken": "abc"
},
"links": {
"first": "https://demo.spysystem.dk/api/v2/pdm/styles?page[limit]=1&page[token]=abc&page[offset]=0",
"last": "https://demo.spysystem.dk/api/v2/pdm/styles?page[limit]=1&page[token]=abc&page[offset]=1",
"prev": null,
"next": "https://demo.spysystem.dk/api/v2/pdm/styles?page[limit]=1&page[token]=abc&page[offset]=1"
},
"data": [
{
"type": "style",
"id": "1",
"attributes": {
"styleNo": "S1000",
"styleName": "First style"
},
"relationships": {
"brand": {
"data": {
"type": "brand",
"id": "1"
}
},
"styleColors": {
"data": [
{
"type": "styleColor",
"id": "1"
},
{
"type": "styleColor",
"id": "2"
}
]
}
}
}
]
}
Example: Requesting the next page:
GET /pdm/styles?page[limit]=1&page[token]=abc&page[offset]=1
{
"meta": {
"pageToken": "abc"
},
"links": {
"first": "https://demo.spysystem.dk/api/v2/pdm/styles?page[limit]=1&page[token]=abc&page[offset]=0",
"last": null,
"prev": "https://demo.spysystem.dk/api/v2/pdm/styles?page[limit]=1&page[token]=abc&page[offset]=0",
"next": "https://demo.spysystem.dk/api/v2/pdm/styles?page[limit]=1&page[token]=abc&page[offset]=1"
},
"data": [
{
"type": "style",
"id": "2",
"attributes": {
"styleNo": "S1001",
"styleName": "Second style"
},
"relationships": {
"brand": {
"data": {
"type": "brand",
"id": "1"
}
},
"styleColors": {
"data": [
{
"type": "styleColor",
"id": "3"
},
{
"type": "styleColor",
"id": "4"
}
]
}
}
}
]
}
Note: When paginating, you are restricted from changing any URL parameters other than page[token]
and page[offset]
.