Olo

Olo Loyalty API

Olo Loyalty (formerly OloEngage) lets restaurant brands run rewards programs that are tightly bound to the Ordering and POS surfaces - accrual, redemption, tier evaluation, and single-sign-on flow through the Loyalty API and matching loyalty SSO endpoints exposed on the developer portal. Integrates with third-party loyalty engines (Punchh, Paytronix, Thanx) as well as Olo's native loyalty product.

OpenAPI Specification

olo-promotions-openapi.yml Raw ↑
openapi: 3.1.0
info:
  title: Olo Promotions API
  description: >-
    The Olo Promotions Specification defines the HTTP contract that a third-party
    promotions / loyalty provider implements so Olo can validate and redeem coupons
    and loyalty rewards, accrue loyalty points, and manage loyalty accounts during
    the Olo ordering flow. Olo acts as the client and calls the provider-hosted
    endpoints described here. Requests are authenticated with an HMAC-SHA256
    signature computed over the request URL concatenated with the raw request body,
    encoded as URL-safe base64 without padding (or with HTTP Basic for key-based
    auth). This specification is published at https://developer.olo.com/docs and
    modeled directly from Olo's official open-source Promotions SDK
    (github.com/ololabs/promotions-sdk).
  version: '1.0'
  contact:
    name: Olo Developer Support
    url: https://developer.olo.com/
  license:
    name: Olo Promotions SDK License
    url: https://github.com/ololabs/promotions-sdk/blob/main/LICENSE.md
externalDocs:
  description: Olo Promotions Specification
  url: https://developer.olo.com/docs
servers:
  - url: https://{providerHost}
    description: Provider-hosted Promotions endpoint implementing the Olo Promotions Specification
    variables:
      providerHost:
        default: promotions.example.com
        description: The promotions provider's host that implements this specification
tags:
  - name: Accounts
    description: Loyalty account creation and lookup
  - name: Promotions
    description: Validation and redemption of coupons and loyalty rewards
  - name: Accruals
    description: Loyalty point accrual and void
security:
  - OloSignature: []
paths:
  /promotions/accounts:
    post:
      tags:
        - Accounts
      summary: Create Account
      description: Create a new loyalty account in the provider's system for a guest.
      operationId: createAccount
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateAccountRequest'
      responses:
        '200':
          description: The created loyalty account.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Account'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
    get:
      tags:
        - Accounts
      summary: Find Accounts
      description: Find loyalty accounts matching a membership number or other guest identifier.
      operationId: findAccounts
      parameters:
        - name: membershipNumber
          in: query
          required: true
          description: The membership number used to locate the guest's loyalty account(s).
          schema:
            type: string
      responses:
        '200':
          description: The list of matching loyalty accounts.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Account'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /promotions/accounts/{accountId}:
    get:
      tags:
        - Accounts
      summary: Get Account
      description: Retrieve a single loyalty account by its identifier in the provider's system.
      operationId: getAccount
      parameters:
        - name: accountId
          in: path
          required: true
          description: The loyalty account's unique identifier in the provider's system.
          schema:
            type: string
      responses:
        '200':
          description: The requested loyalty account.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Account'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /promotions/validate:
    post:
      tags:
        - Promotions
      summary: Validate Promotions
      description: >-
        Validate the coupons and loyalty rewards applied to a basket. The provider
        calculates discounts and returns the validated promotions with POS reference data.
      operationId: validatePromotions
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PromotionsRequest'
      responses:
        '200':
          description: A transaction containing the validated promotions.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransactionWithPromotionsEnvelope'
        '400':
          $ref: '#/components/responses/BadRequestWithCode'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /promotions/redemptions:
    post:
      tags:
        - Promotions
      summary: Redeem Promotions
      description: >-
        Redeem the coupons and loyalty rewards applied to a placed order, finalizing
        the discounts calculated during validation.
      operationId: redeemPromotions
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PromotionsRequest'
      responses:
        '200':
          description: A transaction containing the redeemed promotions.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransactionWithPromotionsEnvelope'
        '400':
          $ref: '#/components/responses/BadRequestWithCode'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /promotions/redemptions/{redemptionId}:
    delete:
      tags:
        - Promotions
      summary: Void Redemption
      description: Void a previously redeemed set of coupons and rewards for an order.
      operationId: voidRedemption
      parameters:
        - name: redemptionId
          in: path
          required: true
          description: The identifier of the redemption being voided.
          schema:
            type: string
      requestBody:
        required: false
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/VoidRedemptionRequest'
      responses:
        '200':
          description: A transaction confirming the voided redemption.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransactionEnvelope'
        '400':
          $ref: '#/components/responses/BadRequestWithCode'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /promotions/accruals:
    post:
      tags:
        - Accruals
      summary: Accrue Points
      description: Accrue loyalty points for a placed order against a guest's loyalty account.
      operationId: accruePoints
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AccruePointsRequest'
      responses:
        '200':
          description: A transaction confirming the accrual.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransactionEnvelope'
        '400':
          $ref: '#/components/responses/BadRequestWithCode'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /promotions/accruals/{accrualId}:
    delete:
      tags:
        - Accruals
      summary: Void Accrual
      description: Void a previously recorded loyalty point accrual for an order.
      operationId: voidAccrual
      parameters:
        - name: accrualId
          in: path
          required: true
          description: The identifier of the accrual being voided.
          schema:
            type: string
      requestBody:
        required: false
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/VoidAccrualRequest'
      responses:
        '200':
          description: A transaction confirming the voided accrual.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransactionEnvelope'
        '400':
          $ref: '#/components/responses/BadRequestWithCode'
        '401':
          $ref: '#/components/responses/Unauthorized'
components:
  securitySchemes:
    OloSignature:
      type: apiKey
      in: header
      name: Authorization
      description: >-
        HMAC-SHA256 signature over the request URL concatenated with the raw request
        body, using the shared secret as the key, encoded as URL-safe base64 without
        padding. HTTP Basic authorization (base64 of the shared secret) is also supported
        for key-based auth.
  responses:
    Unauthorized:
      description: The request signature was invalid or missing.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    BadRequest:
      description: The request was malformed.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    BadRequestWithCode:
      description: The request could not be processed; a machine-readable error code is included.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorCodeResponse'
  schemas:
    CreateAccountRequest:
      type: object
      description: Request payload to create a new loyalty account.
      properties:
        firstName:
          type: string
          description: First name for the user.
        lastName:
          type: string
          description: Last name for the user.
        phoneNumber:
          type: string
          description: Phone number for the user.
        emailAddress:
          type: string
          description: Email address for the user.
        externalIdentifier:
          type: string
          description: Unique external identifier for the user.
    PromotionsRequest:
      type: object
      description: >-
        Shared payload for the Validate Promotions and Redeem Promotions operations,
        describing the order, its totals, and its basket contents.
      properties:
        orderId:
          type: string
          description: The ID of the order, only populated once the order has been placed.
        accountId:
          type: string
          description: The loyalty account's unique identifier in the provider's system.
        source:
          $ref: '#/components/schemas/Source'
        handoff:
          $ref: '#/components/schemas/Handoff'
        currency:
          type: string
          description: A three-letter ISO 4217 currency code. Defaults to USD when omitted.
        placed:
          type: string
          format: date-time
          description: A UTC RFC 3339 date-time representing when the order was created.
        wanted:
          type: string
          format: date-time
          description: A UTC RFC 3339 date-time representing when the guest wants to receive their food.
        storeNumber:
          type: string
          description: The ID of the store as provided by the restaurant.
        restaurant:
          type: string
          description: A unique ID representing the vendor restaurant in Olo's system.
        brand:
          type: string
          description: A unique ID representing the restaurant brand in Olo's system.
        subtotal:
          type: number
          description: The cost of the food before applying any tax, tip, fees or discounts.
        tax:
          type: number
          description: The amount of tax applied to the order.
        tip:
          type: number
          description: The amount the customer tipped on the order.
        delivery:
          type: number
          description: The delivery fee for the order.
        customFees:
          type: number
          description: The sum of any custom fees applied to the order.
        discount:
          type: number
          description: The sum of any discounts applied to the order.
        total:
          type: number
          description: The final total for the order after any tax, tip, fees and discounts.
        address:
          $ref: '#/components/schemas/Address'
        payments:
          type: array
          items:
            $ref: '#/components/schemas/Payment'
        basket:
          $ref: '#/components/schemas/Basket'
      required:
        - subtotal
        - total
        - basket
    AccruePointsRequest:
      type: object
      description: Request payload to accrue loyalty points for an order.
      properties:
        orderId:
          type: string
          description: The ID of the order, only populated once the order has been placed.
        accountId:
          type: string
          description: The loyalty account's unique identifier in the provider's system.
        source:
          $ref: '#/components/schemas/Source'
        handoff:
          $ref: '#/components/schemas/Handoff'
        currency:
          type: string
          description: A three-letter ISO 4217 currency code. Defaults to USD when omitted.
        placed:
          type: string
          format: date-time
          description: A UTC RFC 3339 date-time representing when the order was created.
        wanted:
          type: string
          format: date-time
          description: A UTC RFC 3339 date-time representing when the guest wants to receive their food.
        storeNumber:
          type: string
          description: The ID of the store as provided by the restaurant.
        restaurant:
          type: string
          description: A unique ID representing the vendor restaurant in Olo's system.
        brand:
          type: string
          description: A unique ID representing the restaurant brand in Olo's system.
        subtotal:
          type: number
          description: The cost of the food before applying any tax, tip, fees or discounts.
        tax:
          type: number
          description: The amount of tax applied to the order.
        tip:
          type: number
          description: The amount the customer tipped on the order.
        delivery:
          type: number
          description: The delivery fee for the order.
        customFees:
          type: number
          description: The sum of any custom fees applied to the order.
        discount:
          type: number
          description: The sum of any discounts applied to the order.
        total:
          type: number
          description: The final total for the order after any tax, tip, fees and discounts.
        address:
          $ref: '#/components/schemas/Address'
        payments:
          type: array
          items:
            $ref: '#/components/schemas/Payment'
        basket:
          $ref: '#/components/schemas/Basket'
      required:
        - accountId
        - subtotal
        - total
    VoidRedemptionRequest:
      type: object
      description: Request payload to void a previously redeemed set of promotions.
      properties:
        orderId:
          type: string
          description: The ID of the order being voided.
        accountId:
          type: string
          description: The loyalty account's unique identifier in the provider's system.
        couponCodes:
          type: array
          description: The coupon codes redeemed with the order that are being voided.
          items:
            type: string
        rewardIds:
          type: array
          description: The IDs of the rewards redeemed with the order that are being voided.
          items:
            type: string
        brand:
          type: string
          description: A unique ID representing the restaurant brand in Olo's system.
        storeNumber:
          type: string
          description: The ID of the store as provided by the restaurant.
        restaurant:
          type: string
          description: A unique ID representing the vendor restaurant in Olo's system.
    VoidAccrualRequest:
      type: object
      description: Request payload to void a previously recorded loyalty point accrual.
      properties:
        orderId:
          type: string
          description: The ID of the order being voided.
        accountId:
          type: string
          description: The loyalty account's unique identifier in the provider's system.
        brand:
          type: string
          description: A unique ID representing the restaurant brand in Olo's system.
        storeNumber:
          type: string
          description: The ID of the store as provided by the restaurant.
        restaurant:
          type: string
          description: A unique ID representing the vendor restaurant in Olo's system.
    Account:
      type: object
      description: A guest's loyalty account.
      properties:
        id:
          type: string
          description: The account's unique identifier in the provider's system.
        status:
          $ref: '#/components/schemas/AccountStatus'
        balance:
          $ref: '#/components/schemas/Balance'
        rewards:
          type: array
          items:
            $ref: '#/components/schemas/AccountReward'
    AccountStatus:
      type: string
      description: Whether the loyalty account is active or inactive.
      enum:
        - Active
        - Inactive
    Balance:
      type: object
      description: A loyalty account's points balance.
      properties:
        quantity:
          type: number
          description: The amount of points in the user's loyalty account.
        target:
          type: number
          description: The points required to unlock the next step in the loyalty account.
        unit:
          type: string
          default: points
          description: The unit used to describe the quantity of a loyalty account balance.
    AccountReward:
      type: object
      description: A reward available in a loyalty account.
      properties:
        id:
          type: string
          description: A unique identifier for the loyalty reward in the provider's system.
        name:
          type: string
          description: The name of the loyalty reward.
        description:
          type: string
          description: A description of the loyalty reward.
        quantity:
          type: integer
          description: The quantity of the reward available in the account.
        currency:
          type: string
          description: A three-letter ISO 4217 currency code. Defaults to USD when omitted.
        expiration:
          type: string
          format: date-time
          description: A UTC RFC 3339 date-time representing when the reward expires.
        reference:
          $ref: '#/components/schemas/PosReference'
        type:
          type: string
          description: Provider-defined category for the reward. Echoed back; not interpreted by Olo.
        imageUrl:
          type: string
          description: An image URL representing the reward. Not interpreted by Olo.
        customFields:
          type: string
          description: Custom provider metadata echoed back in subsequent requests.
    Source:
      type: string
      description: The source of the order.
      enum:
        - Web
        - MobileWeb
        - iOS
        - Android
        - Kiosk
        - Other
    Handoff:
      type: string
      description: The handoff method for the order.
      enum:
        - Pickup
        - Curbside
        - Delivery
        - Dispatch
        - Drivethru
        - Dinein
    Address:
      type: object
      description: The destination address of the order.
      properties:
        street:
          type: string
          description: The street address.
        city:
          type: string
          description: The name of the city.
        code:
          type: string
          description: The zip code.
        country:
          type: string
          description: A three-letter ISO 3166-1 country code.
    Payment:
      type: object
      description: A payment applied to the order.
      properties:
        tender:
          $ref: '#/components/schemas/Tender'
        issuer:
          $ref: '#/components/schemas/Issuer'
        suffix:
          type: string
          description: The credit card suffix. Only populated when tender is Credit.
        amount:
          type: number
          description: The payment amount for this payment method.
    Tender:
      type: string
      description: A payment tender type.
      enum:
        - Cash
        - Check
        - Credit
        - Debit
        - Prepaid
        - Transfer
        - Value
        - Other
    Issuer:
      type: string
      description: The credit card issuer. Only populated when tender is Credit.
      enum:
        - Amex
        - Diners
        - Discover
        - JCB
        - MasterCard
        - PayPal
        - Visa
    Basket:
      type: object
      description: The basket contents for an order.
      properties:
        id:
          type: string
          description: The ID of the basket; the unique order identifier until an order ID is generated.
        rewards:
          type: array
          description: Any loyalty rewards applied to the basket.
          items:
            $ref: '#/components/schemas/BasketReward'
        coupons:
          type: array
          description: Any coupons applied to the basket.
          items:
            $ref: '#/components/schemas/Coupon'
        entries:
          type: array
          description: The Olo representations of the basket items.
          items:
            $ref: '#/components/schemas/OloEntry'
        posEntries:
          type: array
          description: The POS representations of the basket items.
          items:
            $ref: '#/components/schemas/PosEntry'
    DiscountLevel:
      type: string
      description: The level at which a discount is applied.
      enum:
        - Item
        - Basket
    Coupon:
      type: object
      description: A coupon applied to a basket.
      properties:
        id:
          type: string
          description: The coupon's code.
        provider:
          type: string
          description: The name of the coupon's provider.
        level:
          $ref: '#/components/schemas/DiscountLevel'
        product:
          type: string
          description: The Olo product ID the coupon is applied to. Only populated for item-level coupons.
        discount:
          type: number
          description: The discount amount for the coupon. Only populated once the basket is validated.
    BasketReward:
      type: object
      description: A loyalty reward applied to a basket.
      properties:
        id:
          type: string
          description: The ID of the reward in the loyalty provider's system.
        provider:
          type: string
          description: The name of the reward's loyalty provider.
        level:
          $ref: '#/components/schemas/DiscountLevel'
        product:
          type: string
          description: The Olo product ID the reward is applied to. Only populated for item-level rewards.
        discount:
          type: number
          description: The discount amount for the reward. Only populated once the basket is validated.
        type:
          type: string
          description: Provider-defined category for the reward. Echoed back; not interpreted by Olo.
        imageUrl:
          type: string
          description: An image URL representing the reward. Not interpreted by Olo.
        customFields:
          type: string
          description: Custom provider metadata echoed back in subsequent requests.
    OloEntry:
      type: object
      description: An Olo-represented basket item entry.
      properties:
        quantity:
          type: number
          description: The quantity of the item in the basket.
        item:
          $ref: '#/components/schemas/OloItem'
    OloItem:
      type: object
      description: An Olo-represented basket item.
      properties:
        product:
          type: string
          description: The Olo product ID.
        label:
          type: string
          description: The name of the product in Olo's system.
        cost:
          type: number
          description: The per-unit cost of the product in Olo's system.
    PosEntry:
      type: object
      description: A POS-represented basket item entry.
      properties:
        quantity:
          type: number
          description: The quantity of the item in the basket.
        posItem:
          $ref: '#/components/schemas/PosItem'
    PosItem:
      type: object
      description: A POS-represented basket item.
      properties:
        product:
          type: string
          description: The POS product ID.
        categories:
          type: array
          description: The POS category IDs for the product.
          items:
            type: string
        modifiers:
          type: array
          description: The modifiers applied to the product.
          items:
            $ref: '#/components/schemas/Modifier'
        label:
          type: string
          description: The name of the product on the POS.
        cost:
          type: number
          description: The per-unit cost of the product on the POS.
    Modifier:
      type: object
      description: A POS modifier applied to a product, supporting nested modifiers.
      properties:
        id:
          type: string
          description: The POS modifier ID.
        quantity:
          type: number
          description: The quantity of the modifier applied to the product.
        product:
          type: string
          description: The POS product ID the modifier is applied to.
        categories:
          type: array
          description: The POS category IDs for the modifier.
          items:
            type: string
        label:
          type: string
          description: The name of the modifier on the POS.
        cost:
          type: number
          description: The per-unit cost of the modifier on the POS.
        modifiers:
          type: array
          description: The modifiers applied to the modifier.
          items:
            $ref: '#/components/schemas/Modifier'
    TransactionEnvelope:
      type: object
      description: An envelope wrapping a transaction result.
      properties:
        transaction:
          $ref: '#/components/schemas/Transaction'
    TransactionWithPromotionsEnvelope:
      type: object
      description: An envelope wrapping a transaction result that includes validated or redeemed promotions.
      properties:
        transaction:
          $ref: '#/components/schemas/TransactionWithPromotions'
    Transaction:
      type: object
      description: The result of a Promotions operation.
      properties:
        id:
          type: string
          description: A unique identifier for the transaction in the provider's system.
    TransactionWithPromotions:
      allOf:
        - $ref: '#/components/schemas/Transaction'
        - type: object
          properties:
            promotions:
              type: array
              description: The details of the validated or redeemed promotions.
              items:
                $ref: '#/components/schemas/Promotion'
    Promotion:
      type: object
      description: A validated or redeemed promotion.
      properties:
        id:
          type: string
          description: The promotion's identifier; the coupon code for coupons or the reward ID for loyalty rewards.
        type:
          $ref: '#/components/schemas/PromotionType'
        discount:
          type: number
          description: The provider-calculated discount for the validated promotion.
        reference:
          $ref: '#/components/schemas/PosReference'
    PromotionType:
      type: string
      description: The type of a promotion.
      enum:
        - Coupon
        - Reward
    PosReference:
      type: object
      description: Data used to identify a promotion or reward on the POS.
      properties:
        type:
          $ref: '#/components/schemas/PosReferenceType'
        code:
          type: string
          description: The value of the POS reference.
    PosReferenceType:
      type: string
      description: The type of a POS reference.
      enum:
        - Promo
        - Comp
    ErrorResponse:
      type: object
      description: Returned for error responses.
      properties:
        id:
          type: string
          description: A unique identifier for the error in the provider's system.
        details:
          type: string
          description: Additional details used to help troubleshoot the error.
        message:
          type: string
          description: An error message to be shown to the customer.
    ErrorCodeResponse:
      allOf:
        - $ref: '#/components/schemas/ErrorResponse'
        - type: object
          properties:
            code:
              $ref: '#/components/schemas/ErrorCode'
    ErrorCode:
      type: string
      description: A machine-readable code identifying the issue with the request.
      enum:
        - EXPIRED_PROMOTION
        - INVALID_PROMOTION
        - MISSING_ITEM
        - INVALID_TOTAL
        - INVALID_HANDOFF
        - INVALID_ACCOUNT
        - OTHER