Terminal Profile API

Reads and updates the current user's profile (name and email) and surfaces a single aggregate view of all account state via /view/init.

OpenAPI Specification

terminal-shop-openapi.yml Raw ↑
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