Contact Log in

Standard Model Spec

Thankful’s Standard Model Spec is a framework that enables Thankful to deeply integrate your business, handling returns, missing packages, order tracking and more using custom backends.

The Standard Model delivers value immediately with small engineering asks, then improves over time with additional effort. With this framework you can spec out and plan your engineering requirements alongside the type of experience you’d like to deliver to your customers.

Each action Thankful performs has a set of endpoints that you MUST implement. Each endpoint has fields that you MUST or MAY implement. Optional fields are noted in the documentation with additional comments surrounding blocks of fields: if provided, optional fields unlock better experiences for your customers.

URLs are set and cannot be adjusted. Thankful will send a request to the URL exactly as described. All request URLs are namespaced under /thankful/api/.

URL parameters will always be URL-encoded according to RFC3986.

Table of Contents

Versioning

This API is versioned on an endpoint-by-endpoint basis, enabling you to upgrade endpoints gradually. For instance, you could use both v1.0 of Get Order and v2.0 of Return Order. It’s up to you to self-report your API version in the X-API-Version response header, for example:

X-API-Version: v1.0

Your server MUST send a version header with every response.

The current version is v1.0. The Standard Model follows semver, so non-breaking changes such as adding fields and endpoints will increment the MINOR number, e.g. v1.1, v1.2. Any breaking changes such as renaming fields or removing fields will be done very rarely, but those will increment the MAJOR number, e.g. v2.0, v3.0.

Authorization

Thankful uses Basic authentication over HTTPS in combination with other security measures.

You can generate and expire API keys on the API Settings page.

That is enough to protect most applications.

Some companies require additional verification, so Thankful supports the following approaches. None are necessary for your security, but they optionally layer protections on top of the Basic auth HTTPS core:

Actions

To enable any action, all of the associated endpoints MUST be implemented.

Endpoints

Get Orders

Endpoint: GET /thankful/api/orders

Query parameters:

One of the above query parameters will always be included.

Example:

GET <your_api_url>/thankful/api/orders?email=bob%40example.com

Request:
	Header:
		Authentication: Basic <your_auth_token>
		X-Request-ID: 9bsv0s23l8og00uph220
		X-Timestamp: 2019-12-31T00:00:00Z
		X-HMAC-SHA512: <signature>
		Content-Type: application/json
		Accept: application/json

	Body:
		<empty>

Response:
	Status: 200 OK
	Header:
		X-API-Version: v1.0
		Content-Type: application/json
	Body:
		[]Order

Create Order

Endpoint: POST /thankful/api/orders

Example:

POST <your_api_url>/thankful/api/orders

Request:
	Header:
		Authentication: Basic <your_auth_token>
		X-Request-ID: 9bsv0s23l8og00uph220
		X-Timestamp: 2019-12-31T00:00:00Z
		X-HMAC-SHA512: <signature>
		Content-Type: application/json
		Accept: application/json

	Body:
		Order

Response:
	Status: 200 OK
	Header:
		X-API-Version: v1.0
		Content-Type: application/json
	Body:
		Order

Update Order

Endpoint: PATCH /thankful/api/orders/:id

Example:

GET <your_api_url>/thankful/api/orders/123

Request:
	Header:
		Authentication: Basic <your_auth_token>
		X-Request-ID: 9bsv0s23l8og00uph220
		X-Timestamp: 2019-12-31T00:00:00Z
		X-HMAC-SHA512: <signature>
		Content-Type: application/json
		Accept: application/json

	Body:
		Order

Response:
	Status: 200 OK
	Header:
		X-API-Version: v1.0
		Content-Type: application/json
	Body:
		<empty>

Create Return

Endpoint: POST /thankful/api/orders/:id/returns

Example:

POST <your_api_url>/thankful/api/orders/123/returns

Request:
	Header:
		Authentication: Basic <your_auth_token>
		X-Request-ID: 9bsv0s23l8og00uph220
		X-Timestamp: 2019-12-31T00:00:00Z
		X-HMAC-SHA512: <signature>
		Content-Type: application/json
		Accept: application/json

	Body:
		Return

Response:
	Status: 200 OK
	Header:
		X-API-Version: v1.0
		Content-Type: application/json
	Body:
		Return

Get Customers

Endpoint: GET /thankful/api/customers

Query parameters:

One of the above query parameters will always be included.

Example:

GET <your_api_url>/thankful/api/customers?email=bob%40example.com

Request:
	Header:
		Authentication: Basic <your_auth_token>
		X-Request-ID: 9bsv0s23l8og00uph220
		X-Timestamp: 2019-12-31T00:00:00Z
		X-HMAC-SHA512: <signature>
		Content-Type: application/json
		Accept: application/json

	Body:
		<empty>

Response:
	Status: 200 OK
	Header:
		X-API-Version: v1.0
		Content-Type: application/json
	Body:
		[]Customer

Get Customer

Endpoint: GET /thankful/api/customers/:id

Example:

GET <your_api_url>/thankful/api/customers/123

Request:
	Header:
		Authentication: Basic <your_auth_token>
		X-Request-ID: 9bsv0s23l8og00uph220
		X-Timestamp: 2019-12-31T00:00:00Z
		X-HMAC-SHA512: <signature>
		Content-Type: application/json
		Accept: application/json

	Body:
		<empty>

Response:
	Status: 200 OK
	Header:
		X-API-Version: v1.0
		Content-Type: application/json
	Body:
		Customer

Update Customer

Endpoint: PATCH /thankful/api/customers/:id

Example:

PATCH <your_api_url>/thankful/api/customers/123

Request:
	Header:
		Authentication: Basic <your_auth_token>
		X-Request-ID: 9bsv0s23l8og00uph220
		X-Timestamp: 2019-12-31T00:00:00Z
		X-HMAC-SHA512: <signature>
		Content-Type: application/json
		Accept: application/json

	Body:
		Customer

Response:
	Status: 200 OK
	Header:
		X-API-Version: v1.0
		Content-Type: application/json
	Body:
		<empty>

Send Password Reset

Endpoint: POST /thankful/api/customers/:id/password_reset

Example:

POST <your_api_url>/thankful/api/customers/123/password_reset

Request:
	Header:
		Authentication: Basic <your_auth_token>
		X-Request-ID: 9bsv0s23l8og00uph220
		X-Timestamp: 2019-12-31T00:00:00Z
		X-HMAC-SHA512: <signature>
		Content-Type: application/json
		Accept: application/json

	Body:
		<empty>

Response:
	Status: 200 OK
	Header:
		X-API-Version: v1.0
		Content-Type: application/json
	Body:
		<empty>

Create Discount

Endpoint: POST /thankful/api/orders/:id/discounts

Example:

POST <your_api_url>/thankful/api/orders/123/discounts

Request:
	Header:
		Authentication: Basic <your_auth_token>
		X-Request-ID: 9bsv0s23l8og00uph220
		X-Timestamp: 2019-12-31T00:00:00Z
		X-HMAC-SHA512: <signature>
		Content-Type: application/json
		Accept: application/json

	Body:
		Discount

Response:
	Status: 200 OK
	Header:
		X-API-Version: v1.0
		Content-Type: application/json
	Body:
		Discount

Update Subscription

Endpoint: PATCH /thankful/api/subscriptions/:id

Example:

PATCH <your_api_url>/thankful/api/subscriptions/123

Request:
	Header:
		Authentication: Basic <your_auth_token>
		X-Request-ID: 9bsv0s23l8og00uph220
		X-Timestamp: 2019-12-31T00:00:00Z
		X-HMAC-SHA512: <signature>
		Content-Type: application/json
		Accept: application/json

	Body:
		Subscription

Response:
	Status: 200 OK
	Header:
		X-API-Version: v1.0
		Content-Type: application/json
	Body:
		<empty>

Data Structures

Data structures are split into several sections to minimize the build-out based on what’s needed for the business. A certain set of fields for each data type are required for core functionality. Required fields MUST all be implemented for any endpoint which requires them. The endpoints needed for your business will depend on your tickets, and Thankful can make helpful recommendations on great places to start. See Actions for more detail on required endpoints and data-structures on an action-by-action basis.

You can opt-into more advanced features by providing additional fields, such as allowing Thankful to process returns for individual items by providing line_items, returns, and refunds information when looking up orders.

Your business can add more fields over time and Thankful will automatically adapt its workflows to use them, instantly offering customers more incredible experiences.

Each field has a name and a data type. There are core data types (int, string, float, bool), specific formats like RFC3339_timestamp which is a string in the form of “2019-12-31T00:00:00Z”, and other data structures like Address or Fulfillment. Each data structure is documented in the same way. An asterisk (*) indicates that the field might be null or not included.

All prices use whole cents (integers). Floating point numbers or strings are never used for prices.

Address

A street address.

{
	street_1  string
	street_2  string
	city      string
	state     string
	country   string
	zip       string
}

Carrier

Carrier must be one of the following:

We have hundreds of carrier integrations. If you use a different carrier, let Thankful know, and we’ll provide you the identifier.

Customer

{
	id         string
	full_name  string
	phones     []string
	emails     []string
	vip        bool
	blacklist  bool
	orders     []Order

	// For subscription companies
	subscriptions []Subscription

	// For one-off data to enable functionality beyond this framework.
	// You'll need to work with Thankful's deployment team to utilize any
	// data provided as properties. Only string key/value pairs are
	// supported.
        properties {
		key   string
		value string
	}
}

Discount

{
	id string

	// If you give pre-generated discount codes to users
	code string

	// If discounts will be applied without pre-generated codes
	amount int
	amount_type string

	created_at RFC3339_timestamp

	// For one-off data to enable functionality beyond this framework.
	// You'll need to work with Thankful's deployment team to utilize any
	// data provided as properties. Only string key/value pairs are
	// supported.
        properties {
		key   string
		value string
	}
}

Either code OR (amount AND amount_type) must be defined.

Fulfillment

A fulfillment represents a single package or shipment.

{
	id                string
	line_item_ids     []string
	shipping_address  Address
	shipping_speed    ShippingSpeed
	carrier           Carrier
	status            FulfillmentStatus
	tracking_number   string
	tracking_url      string
	created_at        RFC3339_timestamp

	// For one-off data to enable functionality beyond this framework.
	// You'll need to work with Thankful's deployment team to utilize any
	// data provided as properties. Only string key/value pairs are
	// supported.
        properties {
		key   string
		value string
	}
}

FulfillmentStatus

FulfillmentStatus is a string enum which must have one of the following values:

LineItem

Line item in an order represents an individual product that was purchased.

{
	product_id       string
	name             string
	price            int
	quantity         int
	photo_url        string
	return_eligible  bool

	// For one-off data to enable functionality beyond this framework.
	// You'll need to work with Thankful's deployment team to utilize any
	// data provided as properties. Only string key/value pairs are
	// supported.
        properties {
		key   string
		value string
	}
}

Order

{
	// Required for core functionality. If an order does not require
	// delivery (such as for digital products), leave shipping_address
	// null
	id                      string
	order_number            string
	status                  OrderStatus
	shipping_address        *Address
	fulfillments            []Fulfillment
	customer_id             string
	total_price             int
	created_at              RFC3339_timestamp

	// To control whether we allow cancellations beyond time-based SLAs
        cancel_eligible bool

	// For marketplaces with 2-sided buyer+seller transactions
	seller_shipping_address *Address
	seller_fulfillments     []Fulfillment

	// For full returns/exchange experience
	line_items  []LineItem
	returns     []Return
	refunds     []Refund

	// For sending replacement items, packages
	line_items          []LineItem
	reference_order_id  string

	// For one-off data to enable functionality beyond this framework.
	// You'll need to work with Thankful's deployment team to utilize any
	// data provided as properties. Only string key/value pairs are
	// supported.
        properties {
		key   string
		value string
	}
}

OrderStatus

OrderStatus is a string enum which must be one of the following depending on your type of business. It is important you only use the statuses for your business type and do not mix-and-match the ones below.

Traditional ecommerce where a store sells directly to a buyer use these statuses:

2-sided marketplaces where the seller ships directly to a buyer (i.e. there’s no review step) will use these statuses:

2-sided marketplaces that connect a buyer and a seller with a middle verification step, such as to check for authenticity, will use these statuses:

Refund

{
	id           string
	amount       int
	return_id    *string
	discount_id  *string
	created_at   RFC3339_timestamp

	// For one-off data to enable functionality beyond this framework.
	// You'll need to work with Thankful's deployment team to utilize any
	// data provided as properties. Only string key/value pairs are
	// supported.
        properties {
		key   string
		value string
	}
}

Exactly one return_id OR discount_id must be included. Refunds with null return_id AND discount_id are invalid. Refunds that include both return_id AND discount_id are invalid.

Return

{
	id                      string
	total                   int
	adjusted                int
	refund_id               string
	returned_line_item_ids  []string
	started_at              RFC3339_timestamp
	received_at             *RFC3339_timestamp

	// For one-off data to enable functionality beyond this framework.
	// You'll need to work with Thankful's deployment team to utilize any
	// data provided as properties. Only string key/value pairs are
	// supported.
        properties {
		key   string
		value string
	}
}

ShippingSpeed

ShippingSpeed is a string enum which must have one of the following values:

Subscription

{
	id        string
	status    SubscriptionStatus
	per_year  int
	tier      string

	last_order_id            string
	next_order_scheduled_at  RFC3339_timestamp

	paused_until   *RFC3339_timestamp
	expires_at     *RFC3339_timestamp
	created_at     RFC3339_timestamp

	// For one-off data to enable functionality beyond this framework.
	// You'll need to work with Thankful's deployment team to utilize any
	// data provided as properties. Only string key/value pairs are
	// supported.
        properties {
		key   string
		value string
	}
}

SubscriptionStatus

SubscriptionStatus is a string enum that must be one of the following: