Terminal Tokens & Apps API
Manages personal access tokens used as Bearer credentials and registers OAuth apps (client ID/secret and redirect URI) for third-party integrations.
Manages personal access tokens used as Bearer credentials and registers OAuth apps (client ID/secret and redirect URI) for third-party integrations.
openapi: 3.0.1
info:
title: Terminal Shop API
description: >-
Public REST API for Terminal, a developer-focused coffee company. The API
powers product browsing, carts, orders, subscriptions, addresses, cards,
profiles, personal access tokens, and OAuth apps - the same surface behind
the `ssh terminal.shop` storefront and the official SDKs. All monetary
amounts are integers in US cents. Authentication is a Bearer personal
access token (`trm_live_*` in production, `trm_test_*` in the dev sandbox)
or an OAuth 2.0 access token.
termsOfService: https://www.terminal.shop/terms
contact:
name: Terminal Support
url: https://www.terminal.shop
version: '1.0'
servers:
- url: https://api.terminal.shop
description: Production
- url: https://api.dev.terminal.shop
description: Dev sandbox (no real charges)
security:
- bearerAuth: []
tags:
- name: Product
- name: Cart
- name: Order
- name: Subscription
- name: Address
- name: Card
- name: Profile
- name: Token
- name: App
- name: Email
- name: View
paths:
/product:
get:
operationId: listProducts
tags: [Product]
summary: List all products
description: List all products for sale in the Terminal shop.
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
type: array
items:
$ref: '#/components/schemas/Product'
/product/{id}:
get:
operationId: getProduct
tags: [Product]
summary: Get product
description: Get a product by ID from the Terminal shop.
parameters:
- $ref: '#/components/parameters/PathID'
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
$ref: '#/components/schemas/Product'
/cart:
get:
operationId: getCart
tags: [Cart]
summary: Get cart
description: Get the current user's cart.
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
$ref: '#/components/schemas/Cart'
delete:
operationId: clearCart
tags: [Cart]
summary: Clear cart
description: Clear the current user's cart.
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
type: string
description: Empty string on success.
/cart/item:
put:
operationId: setCartItem
tags: [Cart]
summary: Add or update cart item
description: Add an item to the current user's cart, or update its quantity.
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [productVariantID, quantity]
properties:
productVariantID:
type: string
description: ID of the product variant to add.
quantity:
type: integer
format: int64
description: Quantity of the item. Set to 0 to remove it.
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
$ref: '#/components/schemas/Cart'
/cart/address:
put:
operationId: setCartAddress
tags: [Cart]
summary: Set cart shipping address
description: Set the shipping address for the current user's cart.
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [addressID]
properties:
addressID:
type: string
description: ID of the saved shipping address.
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
type: string
/cart/card:
put:
operationId: setCartCard
tags: [Cart]
summary: Set cart payment card
description: Set the payment card for the current user's cart.
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [cardID]
properties:
cardID:
type: string
description: ID of the saved payment card.
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
type: string
/cart/convert:
post:
operationId: convertCart
tags: [Cart]
summary: Convert cart to order
description: Convert the current user's cart to an order and place it.
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
$ref: '#/components/schemas/Order'
/order:
get:
operationId: listOrders
tags: [Order]
summary: List orders
description: List the orders associated with the current user.
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
type: array
items:
$ref: '#/components/schemas/Order'
post:
operationId: createOrder
tags: [Order]
summary: Create order
description: >-
Create an order without a cart. The order is placed immediately using
the supplied address, card, and variant quantities.
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [addressID, cardID, variants]
properties:
addressID:
type: string
description: ID of the shipping address.
cardID:
type: string
description: ID of the payment card.
variants:
type: object
description: Map of product variant ID to quantity.
additionalProperties:
type: integer
format: int64
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
type: string
description: ID of the created order.
/order/{id}:
get:
operationId: getOrder
tags: [Order]
summary: Get order
description: Get the order with the given ID.
parameters:
- $ref: '#/components/parameters/PathID'
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
$ref: '#/components/schemas/Order'
/subscription:
get:
operationId: listSubscriptions
tags: [Subscription]
summary: List subscriptions
description: List the subscriptions associated with the current user.
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
type: array
items:
$ref: '#/components/schemas/Subscription'
post:
operationId: createSubscription
tags: [Subscription]
summary: Create subscription
description: Create a subscription for the current user.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SubscriptionInput'
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
type: string
/subscription/{id}:
get:
operationId: getSubscription
tags: [Subscription]
summary: Get subscription
description: Get the subscription with the given ID.
parameters:
- $ref: '#/components/parameters/PathID'
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
$ref: '#/components/schemas/Subscription'
put:
operationId: updateSubscription
tags: [Subscription]
summary: Update subscription
description: Update the subscription with the given ID.
parameters:
- $ref: '#/components/parameters/PathID'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
addressID:
type: string
cardID:
type: string
schedule:
$ref: '#/components/schemas/SubscriptionSchedule'
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
$ref: '#/components/schemas/Subscription'
delete:
operationId: deleteSubscription
tags: [Subscription]
summary: Cancel subscription
description: Cancel the subscription with the given ID.
parameters:
- $ref: '#/components/parameters/PathID'
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
type: string
/address:
get:
operationId: listAddresses
tags: [Address]
summary: List addresses
description: Get the shipping addresses associated with the current user.
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
type: array
items:
$ref: '#/components/schemas/Address'
post:
operationId: createAddress
tags: [Address]
summary: Create address
description: Create and add a shipping address to the current user.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AddressInput'
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
type: string
description: ID of the created address.
/address/{id}:
get:
operationId: getAddress
tags: [Address]
summary: Get address
description: Get the shipping address with the given ID.
parameters:
- $ref: '#/components/parameters/PathID'
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
$ref: '#/components/schemas/Address'
delete:
operationId: deleteAddress
tags: [Address]
summary: Delete address
description: Delete a shipping address from the current user.
parameters:
- $ref: '#/components/parameters/PathID'
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
type: string
/card:
get:
operationId: listCards
tags: [Card]
summary: List cards
description: List the credit cards associated with the current user.
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
type: array
items:
$ref: '#/components/schemas/Card'
post:
operationId: createCard
tags: [Card]
summary: Create card
description: >-
Attach a credit card (via a Stripe token) to the current user.
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [token]
properties:
token:
type: string
description: Stripe card token.
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
type: string
description: ID of the created card.
/card/collect:
post:
operationId: collectCard
tags: [Card]
summary: Collect card
description: >-
Create a temporary URL for collecting credit card information on a
Stripe-hosted page.
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
type: object
required: [url]
properties:
url:
type: string
format: uri
description: Hosted card-collection URL.
/card/{id}:
get:
operationId: getCard
tags: [Card]
summary: Get card
description: Get the credit card with the given ID.
parameters:
- $ref: '#/components/parameters/PathID'
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
$ref: '#/components/schemas/Card'
delete:
operationId: deleteCard
tags: [Card]
summary: Delete card
description: Delete a credit card associated with the current user.
parameters:
- $ref: '#/components/parameters/PathID'
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
type: string
/profile:
get:
operationId: getProfile
tags: [Profile]
summary: Get profile
description: Get the current user's profile.
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
$ref: '#/components/schemas/Profile'
put:
operationId: updateProfile
tags: [Profile]
summary: Update profile
description: Update the current user's name and email.
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [name, email]
properties:
name:
type: string
email:
type: string
format: email
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
$ref: '#/components/schemas/Profile'
/token:
get:
operationId: listTokens
tags: [Token]
summary: List tokens
description: List the personal access tokens associated with the current user.
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
type: array
items:
$ref: '#/components/schemas/Token'
post:
operationId: createToken
tags: [Token]
summary: Create token
description: >-
Create a personal access token. The secret is returned only once at
creation time.
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
type: object
required: [id, token]
properties:
id:
type: string
token:
type: string
description: The token secret (shown once).
/token/{id}:
get:
operationId: getToken
tags: [Token]
summary: Get token
description: Get the personal access token with the given ID.
parameters:
- $ref: '#/components/parameters/PathID'
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
$ref: '#/components/schemas/Token'
delete:
operationId: deleteToken
tags: [Token]
summary: Delete token
description: Delete the personal access token with the given ID.
parameters:
- $ref: '#/components/parameters/PathID'
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
type: string
/app:
get:
operationId: listApps
tags: [App]
summary: List apps
description: List the OAuth apps associated with the current user.
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
type: array
items:
$ref: '#/components/schemas/App'
post:
operationId: createApp
tags: [App]
summary: Create app
description: Create an OAuth app. The client secret is returned only at creation.
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [name, redirectURI]
properties:
name:
type: string
redirectURI:
type: string
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
type: object
required: [id, secret]
properties:
id:
type: string
secret:
type: string
/app/{id}:
get:
operationId: getApp
tags: [App]
summary: Get app
description: Get the OAuth app with the given ID.
parameters:
- $ref: '#/components/parameters/PathID'
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
$ref: '#/components/schemas/App'
delete:
operationId: deleteApp
tags: [App]
summary: Delete app
description: Delete the OAuth app with the given ID.
parameters:
- $ref: '#/components/parameters/PathID'
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
type: string
/email:
post:
operationId: createEmail
tags: [Email]
summary: Subscribe email
description: Subscribe to email updates from Terminal.
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [email]
properties:
email:
type: string
format: email
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
type: string
/view/init:
get:
operationId: initView
tags: [View]
summary: Get app data
description: >-
Get all data needed to render the Terminal storefront app in a single
request - region plus the current user's products, profile, addresses,
cards, cart, orders, subscriptions, tokens, and apps.
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required: [data]
properties:
data:
$ref: '#/components/schemas/InitView'
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
description: >-
Personal access token (`trm_live_*` in production, `trm_test_*` in the
dev sandbox) or OAuth 2.0 access token, passed as
`Authorization: Bearer <token>`.
parameters:
PathID:
name: id
in: path
required: true
schema:
type: string
schemas:
Product:
type: object
required: [id, name, description, variants]
properties:
id:
type: string
name:
type: string
description:
type: string
variants:
type: array
items:
$ref: '#/components/schemas/ProductVariant'
order:
type: integer
format: int64
description: Sort order of the product.
subscription:
type: string
enum: [allowed, required]
description: Whether subscriptions are allowed or required for this product.
tags:
$ref: '#/components/schemas/ProductTags'
ProductVariant:
type: object
required: [id, name, price]
properties:
id:
type: string
name:
type: string
price:
type: integer
format: int64
description: Price of the variant in US cents.
tags:
type: object
additionalProperties: true
ProductTags:
type: object
properties:
app:
type: string
color:
type: string
featured:
type: boolean
market_eu:
type: boolean
market_global:
type: boolean
market_na:
type: boolean
Cart:
type: object
required: [items, subtotal, amount]
properties:
items:
type: array
items:
$ref: '#/components/schemas/CartItem'
subtotal:
type: integer
format: int64
description: Subtotal of the items in the cart, in cents.
amount:
$ref: '#/components/schemas/CartAmount'
addressID:
type: string
cardID:
type: string
shipping:
$ref: '#/components/schemas/CartShipping'
CartItem:
type: object
required: [id, productVariantID, quantity, subtotal]
properties:
id:
type: string
productVariantID:
type: string
quantity:
type: integer
format: int64
subtotal:
type: integer
format: int64
CartAmount:
type: object
required: [subtotal]
properties:
subtotal:
type: integer
format: int64
shipping:
type: integer
format: int64
total:
type: integer
format: int64
CartShipping:
type: object
properties:
service:
type: string
timeframe:
type: string
Order:
type: object
required: [id, amount, created, items, shipping, tracking]
properties:
id:
type: string
amount:
$ref: '#/components/schemas/OrderAmount'
created:
type: string
items:
type: array
items:
$ref: '#/components/schemas/OrderItem'
shipping:
$ref: '#/components/schemas/OrderShipping'
tracking:
$ref: '#/components/schemas/OrderTracking'
index:
type: integer
format: int64
OrderAmount:
type: object
required: [shipping, subtotal]
properties:
shipping:
type: integer
format: int64
subtotal:
type: integer
format: int64
OrderItem:
type: object
required: [id, amount, quantity]
properties:
id:
type: string
amount:
type: integer
format: int64
quantity:
type: integer
format: int64
description:
type: string
productVariantID:
type: string
OrderShipping:
type: object
required: [city, country, name, street1, zip]
properties:
city:
type: string
country:
type: string
name:
type: string
street1:
type: string
street2:
type: string
zip:
type: string
province:
type: string
phone:
type: string
OrderTracking:
type: object
properties:
number:
type: string
service:
type: string
status:
type: string
enum: [PRE_TRANSIT, TRANSIT, DELIVERED, RETURNED, FAILURE, UNKNOWN]
statusDetails:
type: string
statusUpdatedAt:
type: string
url:
type: string
Subscription:
type: object
required: [id, productVariantID, quantity, addressID, cardID, created, price]
properties:
id:
type: string
productVariantID:
type: string
quantity:
type: integer
format: int64
addressID:
type: string
cardID:
type: string
created:
type: string
price:
type: integer
format: int64
description: Price of the subscription line in cents.
next:
type: string
description: Next scheduled order date.
schedule:
$ref: '#/components/schemas/SubscriptionSchedule'
SubscriptionInput:
type: object
required: [productVariantID, quantity, addressID, cardID]
properties:
productVariantID:
type: string
quantity:
type: integer
format: int64
addressID:
type: string
cardID:
type: string
schedule:
$ref: '#/components/schemas/SubscriptionSchedule'
SubscriptionSchedule:
oneOf:
- type: object
required: [type]
properties:
type:
type: string
enum: [fixed]
interval:
type: integer
format: int64
- type: object
required: [type, interval]
properties:
type:
type: string
enum: [weekly]
interval:
type: integer
format: int64
description: Number of weeks between orders.
Address:
type: object
required: [id, city, country, created, name, street1, zip]
properties:
id:
type: string
city:
type: string
country:
type: string
created:
type: string
name:
type: string
street1:
type: string
street2:
type: string
zip:
type: string
province:
type: string
phone:
type: string
AddressInput:
type: object
required: [city, country, name, street1, zip]
properties:
city:
type: string
country:
type: string
name:
type: string
street1:
type: string
street2:
type: string
zip:
type: string
province:
type: string
phone:
type: string
Card:
type: object
required: [id, brand, created, expiration, last4]
properties:
id:
type: string
brand:
type: string
created:
type: string
last4:
type: string
expiration:
$ref: '#/components/schemas/CardExpiration'
CardExpiration:
type: object
required: [month, year]
properties:
month:
type: integer
format: int64
year:
type: integer
format: int64
Profile:
type: object
required: [user]
properties:
user:
type: object
required: [id, email, fingerprint, name, stripeCustomerID]
properties:
id:
type: string
email:
type: string
nullable: true
fingerprint:
type: str
# --- truncated at 32 KB (33 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/terminal-shop/refs/heads/main/openapi/terminal-shop-openapi.yml