Integrate Real-Time Order State Changes with AWS Kinesis in Shift4 Venue

Article author
Cory LeFevre
  • Updated

Description: Learn how to integrate Shift4 Venue with your AWS-hosted Kinesis stream to receive real-time order state changes. This guide covers infrastructure setup, permissions configuration, payload structure, and data processing best practices.


Kinesis Feed Overview

Shift4 Venue's ordering system publishes order state change events to a Kinesis stream hosted in Shift4 Venue's AWS account. A Shift4 Venue-managed Lambda then publishes those messages to a Kinesis stream in your AWS account, which you must configure. From there, you can connect your own Lambda functions to this stream to implement custom business logic.

This design provides full control over business logic and scaling capabilities, such as Kinesis shard counts, within your AWS environment.

Controlling Access

To enable Shift4 Venue's Lambda to publish to your Kinesis stream, set up the following:

  1. Create a "Kinesis Writer" IAM role in your AWS account.
  2. Trust policy: This role must trust the ARN of the Shift4 Venue Lambda role.

Example pseudocode:

credentials = Aws::AssumeRoleCredentials.new(role_arn: "THE-ARN-OF-THE-WRITER-ROLE-YOU-CREATED")
kinesis_client = Aws::Kinesis::Client.new(credentials)

kinesis_client.put_record(stream_name: "your-stream-name", data: <JSON PAYLOAD HERE>)

Shift4 Venue's Lambda will assume the role you provide, enabling it to publish to your stream.

Implementation Order

  1. You create:
    • A Kinesis stream in your AWS account
    • A "Kinesis Writer" IAM role (leave the trust policy empty for now)
    • Provide Shift4 Venue with:
      • The ARN of the writer role
      • The AWS region of the stream
  2. Shift4 Venue will:
    • Provision a Lambda that publishes to your Kinesis stream
    • Share the ARN of the Lambda role
  3. You update:
    • The trust policy of your writer role to allow the Shift4 Venue Lambda to assume it

Shift4 Venue Integration

Shift4 Venue’s ordering system, "Stadium," emits order state change events. These are published to your Kinesis stream through the integration Lambda. Your own AWS-hosted Lambdas can consume and process these events.

Requirements

Shift4 Venue:

  • A Kinesis stream per environment (e.g., mars-dev, levis-prd)
  • A dedicated publishing Lambda

Client:

  • A Kinesis stream
  • A consumer Lambda with required business logic
  • IAM roles with appropriate read/write permissions

Identity Management / Permissions

Set up the following AWS resources:

  • A Kinesis stream
  • A consumer Lambda with logic to process messages
  • An IAM role/user for the Lambda with permission to read from the stream
  • A Writer Role with sts:AssumeRole permissions for the Shift4 Venue Lambda ARN

Sample Payload


  {
  "_id": "01k59tjjnmmssyj9n16eq91ykp",
  "_v": 1,
  "o": "arena",
  "u": "c9ad749f-d76c-4756-b063-f60e8e12e36d",
  "s": "stadium",
  "e": "order.state.change",
  "p": {
    "bundle_id": null,
    "client_created_at": "2025-09-16T17:49:53Z",
    "confirmation_number": "698100",
    "created_at": "2025-09-16T17:49:54Z",
    "device_uuid": "82c61f28-6d06-4a34-82da-bd0d2ffc7409",
    "discount": "0",
    "device_subtype": "concessions-pos",
    "employee_id": "4976992c-000c-4fdb-9d4d-9da705130d70",
    "employee_name": "Gary ",
    "menu_external_ref_id": null,
    "menu_name": "Suite 317 - POS",
    "product_type": "Food",
    "revenue_center_external_ref_id": "suite_317",
    "revenue_center_name": "Suite 317",
    "revenue_center_uuid": "d3ab13ee-61b6-4286-95fe-2b58cd6f66cc",
    "sales_event_id": null,
    "service_type": "POS",
    "source_device_uuid": "82c61f28-6d06-4a34-82da-bd0d2ffc7409",
    "state": "completed",
    "tax": 50,
    "tip": 0,
    "total": 3050,
    "transaction_history": [
      {
        "state": "authorized",
        "time": "2025-09-16T17:49:54Z"
      },
      {
        "state": "settled",
        "time": "2025-09-16T17:49:54Z"
      }
    ],
    "updated_at": "2025-09-16T17:53:47Z",
    "user_external_ref_id": "c9ad749f-d76c-4756-b063-f60e8e12e36d",
    "uuid": "3667877f-e822-45ea-ba0f-ce26cd2fc3e6",
    "venue_uuid": "1c7a17e6-141a-4591-a59b-10c8f58d5584",
    "state_history": [
      {
        "state": "processing",
        "time": "2025-09-16T17:49:54Z"
      },
      {
        "state": "completed",
        "time": "2025-09-16T17:53:47Z"
      }
    ],
    "line_items": [
      {
        "created_at": "2025-09-16T17:49:54Z",
        "modified_line_item_uuid": null,
        "name": "12 inch Sub",
        "price": 500,
        "promotion_discount": 0,
        "promotions": [],
        "quantity": 1,
        "refunded_at": null,
        "removed_at": null,
        "reporting_category_uuid": "91fe17a2-012c-43a8-a9ec-6d48f593d241",
        "sku": "5dollafootlong",
        "tax_amount_in_cents": 50,
        "tax_inclusive": false,
        "updated_at": "2025-09-16T17:49:54Z",
        "uuid": "573ee7c1-7614-4156-b080-ec4c1ae10772"
      },
      {
        "created_at": "2025-09-16T17:49:54Z",
        "modified_line_item_uuid": null,
        "name": "Red Red Wine",
        "price": 2500,
        "promotion_discount": 0,
        "promotions": [],
        "quantity": 1,
        "refunded_at": null,
        "removed_at": null,
        "reporting_category_uuid": null,
        "sku": "bottleredwine",
        "tax_amount_in_cents": 0,
        "tax_inclusive": false,
        "updated_at": "2025-09-16T17:49:54Z",
        "uuid": "6535976f-4ea9-48c4-a3c3-1cce02d36d77"
      }
    ],
    "payment_transactions": [
      {
        "authorization_amount": "30.5",
        "card_type": "cash",
        "created_at": "2025-09-16T17:49:54Z",
        "last_four": null,
        "payment_type": "cash",
        "settlement_amount": "30.5",
        "updated_at": "2025-09-16T17:49:54Z"
      }
    ]
  }
}

Data Types


  {
    "_id": "standard ULID string",
    "_v": "short integer",
    "o": "256 character string",
    "u": "36 character UUID",
    "s": "short string, currently always 'stadium'",
    "e": "256 character string",
    "p": {
        "uuid": "36 character UUID string",
        "state": "256 character string",
        "created_at": "256 character date string",
        "total": "16-bit integer total in cents",
        "tax": "16-bit integer tax in cents",
        "discount": "256 character string discount amount",
        "tip": "16-bit integer tax in cents",
        "device_uuid": "36 character UUID string",
        "revenue_center_name": "256 character string",
        "revenue_center_external_ref_id": "256 character string",
        "menu_name": "256 character string",
        "menu_external_ref_id": "256 character string",
        "service_type": "short string",
        "employee_name": "256 character string",
        "employee_id": "256 character string",

        "transaction_hip.bundle_id": "256 character string",
        "user_external_ref_id": "256 character string",
        "product_type": "256 character string",
        "updated_at": "256 character date string",
        "line_items.tax_inclusive": "boolean (true/false)",
        "line_items.updated_at": "256 character date string",
        "line_items.tax_amount_in_cents": "16-bit integer tax in cents",
        "line_items.promotion_discount": "16-bit integer total in cents",
        "line_items.quantity": "16-bit integer",
        "line_items.reporting_category_uuid": "36 character UUID",
        "source_device_uuid": "36 character UUID",
        "sales_event_id": "36 character UUID",
        "device_subtype": "256 character string",
        "client_created_at": "256 character date string",

        "payment_transactions": [
            {
                "authorization_amount": "32-bit integer amount in cents",
                "card_type": "256 character string",
                "created_at": "256 character date string",
                "last_four": "4 character string",
                "payment_type": "256 character string",
                "settlement_amount": "32-bit integer amount in cents",
                "updated_at": "256 character date string"
            }
        ],

        "story": [
            {
                "state": "256 character string",
                "time": "256 character date string"
            }
        ],

        "state_history": [
            {
                "state": "256 character string",
                "time": "256 character date string"
            }
        ],

        "line_items": [
            {
                "uuid": "36 character UUID string",
                "name": "256 character string",
                "price": "16-bit integer price in cents",
                "sku": "256 character string",
                "created_at": "256 character date string",
                "refunded_at": "256 character date string",
                "removed_at": "256 character date string",
                "modified_line_item_uuid": "36 character UUID string"
            }
        ]
    }
}

Payload Deduplication Tip

Each payload includes a state_history array with timestamps. To detect duplicate messages:

  • Sort the array by date.
  • Generate a hash from the sorted array.
  • Compare hashes to identify duplicates.

Kinesis Feed Field Reference

General Fields

  • _id: Unique ULID identifier
  • _v: Version (always 1)
  • o: Organization identifier
  • u: User UUID
  • s: Source (always "stadium")
  • e: Event type (always "order.state.change")

Order Object (p)

  • uuid: Order ID
  • venue_uuid: Venue ID
  • state: Current state
  • client_created_at: Order start timestamp
  • created_at: Creation timestamp
  • device_subtype: Device type
  • total, tax, tip: Amounts in cents
  • discount: Discount in cents
  • device_uuid: Device ID
  • revenue_center_name: Location name
  • revenue_center_uuid: Location ID
  • menu_name, menu_external_ref_id: Menu identifiers
  • service_type: POS, Delivery, etc.
  • employee_name, employee_id: Employee identifiers (if applicable)

Payment Transactions

  • authorization_amount, settlement_amount: Dollar amounts
  • payment_type: Source type
  • last_four: Card last four digits (if available)
  • transaction_history: Payment states and timestamps

Order State History

  • state: Order state
  • time: Timestamp

Line Items

  • uuid, name, sku, created_at_date, updated_at: Item metadata
  • price, tax_amount_in_cents: In cents
  • refunded_at_date, removed_at_date: Refund/void timestamps
  • modified_line_item_uuid: Reference for modified items
  • tax_inclusive: Boolean indicator
  • item_uuid: Menu item ID

Promotions

  • discount_amount_in_cents: Per-item discount
  • uuid: Promotion ID

Was this article helpful?

0 out of 0 found this helpful

Have more questions? Submit a request

Comments

0 comments

Please sign in to leave a comment.