API Documentation
Getting started with the API
To get the link to create API keys, reach out to your Kotis contact. Note that API keys should be saved securely and shared with the minimum number of people possible to reduce unauthorized access.
Creating an API key
"Live" checkbox - Checking this box will create a live API key. If you want to generate a test key that won't impact anything in production, leave this box unchecked. Test keys can be marked as live later when you're ready to use them. Please note that once a key is switched to Live mode, it cannot be reverted to a test key.
"Notes" - This is an optional field best used to track the purpose of each key, helping you maintain your list of keys and remove inactive ones.
Check inventory
#GET https://kwf.kotisdesign.com/api/v1/skus/quantity
#set 'Authorization' header to api key
#success response
{
"data": [
{
"id": "33315",
"type": "skus",
"attributes": {
"physical_quantity": 0,
"available_quantity": 0,
"sku": "107529-1-L"
}
},
{
"id": "33316",
"type": "skus",
"attributes": {
"physical_quantity": 0,
"available_quantity": 0,
"sku": "107529-1-M"
}
},
{
"id": "33317",
"type": "skus",
"attributes": {
"physical_quantity": 0,
"available_quantity": 0,
"sku": "107529-1-S"
}
}
],
"jsonapi": {
"version": "1.0"
}
}
Create an order
#POST https://kwf.kotisdesign.com/api/v1/orders/create
#set 'Authorization' header to api key
#set 'Content-Type' header to 'application/json'
#example JSON
{
"email": "test@example.com",
"shipping_method": "Economy",
"order_id": "",
"skus": [
{"quantity": "3",
"sku": "107529-1-S"},
{"quantity": "1",
"sku": "107529-4-OSFA"}
],
"address": {
"name": "Test Person",
"attention": "",
"address1": "123 First Street",
"address2": "",
"city": "Seattle",
"state": "WA",
"zip": "98102",
"country": "",
"phone": "",
"address_type": ""
}
}
#success response
{
"status": "success",
"order_num": "5134691"
}
#failure response
{
"errors": [
{
"title": "Invalid Order",
"detail": "Sku 1 does not exist, Sku 2 does not exist"
}
]
}
Check order status (including tracking)
#GET https://kwf.kotisdesign.com/api/v1/orders/status?order_numbers=12345,23719201
#set 'Authorization' header to api key
#success response
{
"data": [
{
"id": "12345",
"type": "orders",
"attributes": { "status": "shipped" },
"relationships": {
"shipments": {
"data": [
{
"type": "shipments",
"id": "543416"
},
{
"type": "shipments",
"id": "544568"
}
]
}
}
},
{
"id": "23719201",
"type": "orders",
"relationships": {
"shipments": {
"data": [
{
"type": "shipments",
"id": "767586"
}
]
}
}
}
],
"included": [
{
"id": "543416",
"type": "shipments",
"attributes": {
"tracking_numbers": "1Z8424330419842539",
"shipment_date": "2018-10-02T14:50:24-07:00",
"delivery_status": "delivered"
}
},
{
"id": "544568",
"type": "shipments",
"attributes": {
"tracking_numbers": "1Z8424330402599594",
"shipment_date": "2018-10-05T15:18:28-07:00",
"delivery_status": "out_for_delivery"
}
},
{
"id": "767586",
"type": "shipments",
"attributes": {
"tracking_numbers": "9405537897842130146579",
"shipment_date": "2019-11-12T07:48:06-08:00",
"status": "in_transit"
}
}
],
"jsonapi": {
"version": "1.0"
}
}
#response with invalid orders
{
"data": [],
"jsonapi": {
"version": "1.0"
}
}
#invalid key
{
"errors": [
{
"title": "Invalid Api Key",
"detail": ""
}
]
}
#possible shipment 'delivery_status' values are:
# "unknown", "pre_transit", "in_transit", "out_for_delivery", "delivered",
# "available_for_pickup", "return_to_sender", "failure", "cancelled" or "error"
#possible order status values are:
# "pending", "partially_shipped", "shipped", "delivered", "cancelled"
Get orders by source
This endpoint uses a GET request to return order numbers and status by their source.
Sources include:
- all: retuns all orders regardless of source
- portal: returns orders created via your portals
- api: returns orders created via the API
- csv: returns orders created via CSV upload
- inventory-management: returns orders created via inventory management
# GET https://kwf.kotisdesign.com/api/v1/orders/by_source
# set 'Authorization' header to your API key for access
#
# Required params:
# source: 'string value'
# start_date: 'string date in ISO 8601 format, e.g. 2025-08-01'
# end_date: 'string date in ISO 8601 format, e.g. 2025-08-31'
#
# source value must be one of "all", "portal", "api", "csv", "inventory-management"
#
# Optional params:
# portal_name: 'string value'
#
# portal_name may be any of your portal names (URLs). It is only used when the 'source' value is 'portal'.
#
Example request
# GET https://kwf.kotisdesign.com/api/v1/orders/by_source
# set 'Authorization' header to your API key for access
headers = { 'Authorization': YOUR_API_KEY }
body = {
source: 'portal',
start_date: '2025-08-01',
end_date: '2025-08-31',
portal: 'testportalurl'
}
HTTP.get("https://kwf.kotisdesign.com/api/v1/orders/by_source, headers: headers, body: body)
Example response (successful)
# STATUS: 200 OK
{
"data": [
{
"order_number": "123456",
"order_date": "2025-08-02T12:30Z",
"status": "shipped",
"source": "portal",
"portal_name": "testportalurl"
},
// more orders
]
}
Errors will be returned if:
- "source" is missing or invalid
- "start_date" or "end_date" is missing or not a valid ISO 8601 date
- "end_date" is before "start_date"
- "start_date" and "end_date" are more than 60 days apart
Example response (error)
# STATUS: 400 BAD REQUEST
{
"errors": [
{
"title": "Invalid source",
"detail": "Invalid source. Valid sources: all, portal, api, csv, inventory-management",
"status": "400",
},
// more errors, if present
]
}
Create redemption codes
#POST https://stores.kotisdesign.com/api/v1/redemption_codes/create
#set 'Authorization' header to api key
{
"portal_slug": "YOUR_PORTAL_SLUG",
"number_to_create": "100"
}
Required fields
Field |
Description |
portal_slug |
The slug (URL name) of the portal to generate codes for. |
number_to_create |
Number of redemption codes to generate. Accepts either a JSON number or numeric string. |
Optional fields
Field |
Description |
points |
Amount of points to apply to each generated code. Required for portals that use points, forbidden for portals that do not use points, and must be greater than 0. |
Email address to associate with the generated code and send the code to. Only allowed when number_to_create is 1. |
|
first_name |
First name to associate with the generated code. Only allowed when number_to_create is 1 and requires email. |
last_name |
Last name to associate with the generated code. Only allowed when number_to_create is 1 and requires email. |
Notes:
- Requires a live API key.
- Daily generation limit: 5,000 codes.
- Yearly generation limit: 100,000 codes.
- If the portal uses points, the points field is required.
- Sending points to a portal that does not use points will return a validation error.
- Sending a points value of 0 will return a validation error.
- email, first_name, and last_name can only be used when number_to_create is 1.
- first_name and last_name require email. Sending either field without an email address will return a validation error.
- If email is provided, the generated code will be emailed to that address immediately.
- If a portal is near its daily or yearly limit and the requested number of codes exceeds the remaining allowance, a validation message will be returned indicating the maximum number of codes that can be created. If you anticipate hitting these limits, please reach out to your Kotis contact so we can discuss options.
Example: Create and email a redemption code
{
"portal_slug": "YOUR_PORTAL_SLUG",
"number_to_create": 1,
"email": "recipient@example.com",
"first_name": "Jane",
"last_name": "Doe"
}
Example: Create points-based redemption codes
{
"portal_slug": "YOUR_PORTAL_SLUG",
"number_to_create": 100,
"points": 100
}
Example: Create and email a points-based redemption code
{
"portal_slug": "YOUR_PORTAL_SLUG",
"number_to_create": 1,
"points": 100,
"email": "recipient@example.com",
"first_name": "Jane",
"last_name": "Doe"
}
Get redemption code status
This endpoint uses a GET request to return information about a specific redemption code.
# GET https://stores.kotisdesign.com/api/v1/redemption_codes/status
# set 'Authorization' header to api key
#
# Required params:
# portal_slug: "string value",
# code: "string value"
#
Example request
# GET https://stores.kotisdesign.com/api/v1/redemption_codes/status
# set "Authorization" header to your API key for access
headers = { 'Authorization': YOUR_API_KEY }
body = {
portal_slug: "YOUR_PORTAL_SLUG",
code: "CODE_TO_LOOKUP"
}
HTTP.get("https://stores.kotisdesign.com/api/v1/redemption_codes/status, headers: headers, body: body)
Example response (successful)
# STATUS: 200 OK
{
"data": {
"code": "CODE_TO_LOOKUP",
"status": "unclaimed",
"opened": true,
"opened_date": "2020-12-02T14:55:41.750-08:00",
"claimed_date": null,
"order_number": null
},
"status": "ok"
}
Possible "status" values:
- "claimed": code has been claimed
- "unclaimed": code remains unclaimed
- "hidden": code has been removed
Errors will be returned if:
- A code is not found
- Request is malformed
Example response (error)
# STATUS: 400 BAD REQUEST or 404 NOT FOUND
{
"errors": [
{
"title": "Code not found",
"detail": ""
}
],
// more errors, if present
}