Square - POS

Below is the sample script for Square POS. For more information on Square Order APIs, please refer to their API Documentation.

import requests
from datetime import datetime, timedelta
import argparse

####### CONSTANTS (need to be filled out before using) #######
SQUARE_API_URL = "https://connect.squareup.com"
SQUARE_ACCESS_TOKEN = ""
LOCATION_IDS = []

VERKADA_API_URL = "https://api.verkada.com"
VERKADA_API_TOKEN = ""

CAMERA_ID = ""
CUSTOM_EVENT_UID = ""
ORGANIZATION_ID = ""

####### TO CUSTOMIZE (change as you see fit) #######
# To see possible fields: https://developer.squareup.com/reference/square/objects/Order
def parse_order(order: dict) -> dict:
    return {
        "item": order["line_items"][0]["name"],
        "order_number": order["id"][:5],
        "price": float(order["total_money"]["amount"]) / 100,
        "size": order["line_items"][0]["variation_name"],
    }

####### HELPERS (do not change) #######
def iso8601_to_unixms(isodate: str) -> int:
    if isodate[-1] == "Z":
        isodate = isodate[:-1]
    dt = datetime.fromisoformat(isodate)
    return int(dt.timestamp() * 1000)

def iso8601_x_minutes_ago(current_time: str, last_x_minutes: int):
    dt = datetime.fromisoformat(current_time) - timedelta(minutes=last_x_minutes)
    return dt.isoformat()

####### MAIN #######
def main(exe_date, last_x_minutes: int):

    # Get orders from Square API
    response = requests.post(
        f"{SQUARE_API_URL}/v2/orders/search",
        json={
            "location_ids": LOCATION_IDS,
            "query": {
                "filter": {
                    "date_time_filter": {
                        "closed_at": {
                            "start_at": iso8601_x_minutes_ago(exe_date, last_x_minutes),
                            "end_at": exe_date
                        }
                    },
                    "state_filter": {"states": ["COMPLETED"]}
                },
                "sort": {"sort_field": "CLOSED_AT"}
            }
        },
        headers={"Authorization": f"Bearer {SQUARE_ACCESS_TOKEN}"}
    )

    if response.status_code != 200:
        print(
            "Request to {} returned a {}: {}".format(SQUARE_API_URL, response.status_code, response.text)
        )
        return

    orders = response.json().get("orders", [])

    # Parse orders and send them to Verkada
    for order in orders:
        event = parse_order(order)
        time_ms = iso8601_to_unixms(order['closed_at'])

        create_event_response = requests.post(
            f"{VERKADA_API_URL}/cameras/v1/video_tagging/event",
            params={
                "org_id": ORGANIZATION_ID
            },
            json={
                "camera_id": CAMERA_ID,
                "time_ms": time_ms,
                "event_type_uid": CUSTOM_EVENT_UID,
                "attributes": event
            },
            headers={"x-api-key": VERKADA_API_TOKEN}
        )

        assert create_event_response.status_code == 200, create_event_response.text
    

if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        description="Fetch data from point-of-sale services and save as custom events"
    )
    parser.add_argument(
        '-x', '--execution_date', type=str, required=False, default=datetime.now().isoformat(), help="date of execution"
    )
    parser.add_argument(
        '-l', '--last_x_minutes', type=int, required=False, default=15, help="Retrieve sales from the last X minutes"
    )

    cmdline = parser.parse_args()
    exe_date = cmdline.execution_date
    last_x_minutes = cmdline.last_x_minutes

    main(exe_date, last_x_minutes)