Categories
Research (1)
Brink POS PoC integration note
Goal
Define the minimum viable approach for a Brink POS API pull PoC that:
- pulls Brink SOAP data for one tenant-location
- stores raw responses safely
- lands a small source-shaped Brink staging subset
- fills the first useful curated tables
- keeps enough metadata for debugging and reruns
This document is intentionally PoC-oriented. It is not the final production design.
PoC decisions
- Use Brink as a read-only
API pullsource. - Start with these Brink calls only:
Sales2.GetOrdersKitchen.GetOrderBumpTimesKitchen.GetOrderItemBumpTimesSettings2.GetLastModifiedTime- selected settings lookups for items, modifier groups, destinations, taxes, tenders, employees, and kitchen queues
- Store raw SOAP responses in S3.
- Reuse existing
kdsaidbmetadata for the PoC: TenantWarehouseMappingIngestionBatchIngestionCheckpoint- Do not require new control-plane metadata tables for the PoC.
- Use structured logs for per-call detail instead of a dedicated pull-attempt table.
Brink constraints
- Brink is SOAP over HTTPS with WSDLs.
- Auth is header-based:
AccessToken,LocationToken. - TLS 1.2 or 1.3 is required.
ResultCode = 0means success.GetOrdersis heavy and Brink recommends conservative polling.- Brink mixes business date, UTC timestamps, and location-local
DateTimeOffsetwatermarks.
Recommended implementation approach
- Try generated SOAP clients first for
Sales2,Settings2, andKitchen. - If generated code is awkward, switch quickly to a thin hand-written SOAP client for the small PoC call set.
- Keep all Brink transport details behind one adapter boundary.
PoC staging scope
The Brink PoC staging scope is limited to what can support the current curated contracts in backend/Kds.Ai.Warehouse/Models/Curated/CuratedCanonicalModels.cs.
Important simplification rule for the PoC:
- keep
stagingsource-shaped, but keep it simple Sales2.GetOrdersdoes not need to be fully exploded into many staging tables on day one- prefer one primary order-centered staging landing plus only the child tables that clearly help
staging -> curatedtransformations, replay, or debugging - move canonical reshaping and business semantics into
curated
In scope staging tables
staging.brink_orders- optional normalized child tables from
Sales2.GetOrderswhen they materially simplify curated publication: staging.brink_order_entriesstaging.brink_order_entry_modifiersstaging.brink_order_taxesstaging.brink_order_entry_taxesstaging.brink_order_paymentsstaging.brink_order_payment_detailsstaging.brink_itemsstaging.brink_modifier_groupsstaging.brink_modifier_group_itemsstaging.brink_destinationsstaging.brink_tablesstaging.brink_kitchen_queuesstaging.brink_taxesstaging.brink_tendersstaging.brink_employeesstaging.brink_order_bump_timesstaging.brink_order_item_bump_times
Optional PoC support tables
staging.brink_current_business_datesstaging.brink_api_call_logstaging.brink_raw_payload_manifest
For the PoC, these optional tables can be skipped if the same information is available through IngestionBatch, IngestionCheckpoint, structured logs, and S3 raw object paths.
Out of scope for the PoC
- full settings sync
- labor sync
- future-date orders and deposit flows
- inventory
- loyalty
- hourly sales
- production-grade replay/backfill control plane
Staging source matrix
| Staging table | Brink source | API/service call | Brink contract reference | Endpoint and docs reference |
|---|---|---|---|---|
staging.brink_orders | order headers | Sales2.GetOrders | Order | Endpoint: https://{{server}}.brinkpos.net/Sales2.svc; docs: https://brinkapiportal.parpos.com/sales2#GetOrders |
staging.brink_order_entries | order lines | Sales2.GetOrders | OrderEntry, OrderItem, OrderGiftCard | Endpoint: https://{{server}}.brinkpos.net/Sales2.svc; docs: https://brinkapiportal.parpos.com/sales2#GetOrders |
staging.brink_order_entry_modifiers | entry modifiers | Sales2.GetOrders | OrderItemModifier | Endpoint: https://{{server}}.brinkpos.net/Sales2.svc; docs: https://brinkapiportal.parpos.com/sales2#GetOrders |
staging.brink_order_taxes | order-level taxes | Sales2.GetOrders | OrderTax | Endpoint: https://{{server}}.brinkpos.net/Sales2.svc; docs: https://brinkapiportal.parpos.com/sales2#GetOrders |
staging.brink_order_entry_taxes | entry-level taxes | Sales2.GetOrders | OrderEntryTax | Endpoint: https://{{server}}.brinkpos.net/Sales2.svc; docs: https://brinkapiportal.parpos.com/sales2#GetOrders |
staging.brink_order_payments | payment headers | Sales2.GetOrders | OrderPayment | Endpoint: https://{{server}}.brinkpos.net/Sales2.svc; docs: https://brinkapiportal.parpos.com/sales2#GetOrders |
staging.brink_order_payment_details | payment detail events | Sales2.GetOrders | OrderPaymentDetail | Endpoint: https://{{server}}.brinkpos.net/Sales2.svc; docs: https://brinkapiportal.parpos.com/sales2#GetOrders |
staging.brink_items | item master | Settings2.GetSettings or Settings.GetItems | MenuItem or Item | Endpoints: https://{{server}}.brinkpos.net/Settings2.svc, https://{{server}}.brinkpos.net/Settings.svc; docs: https://brinkapiportal.parpos.com/settings2#GetSettings, https://brinkapiportal.parpos.com/settings#GetItems |
staging.brink_modifier_groups | modifier group headers | Settings2.GetModifierGroups or Settings.GetModifierGroups | ModifierGroup | Endpoints: https://{{server}}.brinkpos.net/Settings2.svc, https://{{server}}.brinkpos.net/Settings.svc; docs: https://brinkapiportal.parpos.com/settings2#GetModifierGroups, https://brinkapiportal.parpos.com/settings#GetModifierGroups |
staging.brink_modifier_group_items | modifier group membership | Settings2.GetModifierGroups or Settings.GetModifierGroups | ModifierGroup child membership | Endpoints: https://{{server}}.brinkpos.net/Settings2.svc, https://{{server}}.brinkpos.net/Settings.svc; docs: https://brinkapiportal.parpos.com/settings2#GetModifierGroups, https://brinkapiportal.parpos.com/settings#GetModifierGroups |
staging.brink_destinations | destination lookup | Settings2.GetDestinations or Settings.GetDestinations | Destination | Endpoints: https://{{server}}.brinkpos.net/Settings2.svc, https://{{server}}.brinkpos.net/Settings.svc; docs: https://brinkapiportal.parpos.com/settings2#GetDestinations, https://brinkapiportal.parpos.com/settings#GetDestinations |
staging.brink_tables | table lookup | Settings2.GetTables | Table | Endpoint: https://{{server}}.brinkpos.net/Settings2.svc; docs: https://brinkapiportal.parpos.com/settings2#GetTables |
staging.brink_kitchen_queues | kitchen queue lookup | Settings2.GetKitchenQueues | KitchenQueue | Endpoint: https://{{server}}.brinkpos.net/Settings2.svc; docs: https://brinkapiportal.parpos.com/settings2#GetKitchenQueues |
staging.brink_taxes | tax lookup | Settings2.GetTaxes or Settings.GetTaxes | Tax | Endpoints: https://{{server}}.brinkpos.net/Settings2.svc, https://{{server}}.brinkpos.net/Settings.svc; docs: https://brinkapiportal.parpos.com/settings2#GetTaxes, https://brinkapiportal.parpos.com/settings#GetTaxes |
staging.brink_tenders | tender lookup | Settings.GetTenders | Tender | Endpoint: https://{{server}}.brinkpos.net/Settings.svc; docs: https://brinkapiportal.parpos.com/settings#GetTenders |
staging.brink_employees | employee lookup | Settings2.GetEmployees or Settings2.GetSettings(Employee) | Employee | Endpoint: https://{{server}}.brinkpos.net/Settings2.svc; docs: https://brinkapiportal.parpos.com/settings2#GetEmployees, https://brinkapiportal.parpos.com/settings2#GetSettings |
staging.brink_order_bump_times | kitchen order bump events | Kitchen.GetOrderBumpTimes | OrderBumpTime | Endpoint: https://{{server}}.brinkpos.net/Kitchen.svc; docs: https://brinkapiportal.parpos.com/kitchen#GetOrderBumpTimes |
staging.brink_order_item_bump_times | kitchen item bump events | Kitchen.GetOrderItemBumpTimes | OrderItemBumpTime | Endpoint: https://{{server}}.brinkpos.net/Kitchen.svc; docs: https://brinkapiportal.parpos.com/kitchen#GetOrderItemBumpTimes |
Curated fill matrix
| Curated table | Input staging tables | Brink contract reference | Endpoint and docs reference | PoC fill strategy |
|---|---|---|---|---|
curated.kitchen_item_status_events | staging.brink_order_item_bump_times, staging.brink_kitchen_queues, staging.brink_orders, staging.brink_order_entries | OrderItemBumpTime, Order, OrderEntry, KitchenQueue | Kitchen.GetOrderItemBumpTimes: https://brinkapiportal.parpos.com/kitchen#GetOrderItemBumpTimes; Sales2.GetOrders: https://brinkapiportal.parpos.com/sales2#GetOrders | Supported. Derive one row per item bump using synthetic status semantics where needed. |
curated.kitchen_order_items | staging.brink_order_entries, staging.brink_order_item_bump_times, staging.brink_orders, staging.brink_items | OrderEntry, OrderItemBumpTime, Order, MenuItem or Item | Sales2.GetOrders, Kitchen.GetOrderItemBumpTimes, item docs | Supported. Map food/item lines into the current kitchen item contract. |
curated.kitchen_orders | staging.brink_orders, staging.brink_order_bump_times, staging.brink_destinations, staging.brink_kitchen_queues | Order, OrderBumpTime, Destination, KitchenQueue | Sales2.GetOrders, Kitchen.GetOrderBumpTimes, destination docs | Supported. Map Brink orders into current kitchen order rows with canonical defaults where needed. |
curated.pos_transaction_items | staging.brink_order_entries, staging.brink_order_entry_modifiers, staging.brink_order_entry_taxes, staging.brink_orders, staging.brink_items | OrderEntry, OrderItemModifier, OrderEntryTax, Order | Sales2.GetOrders, item docs | Supported. Use canonical projection into the current Aloha-shaped contract. |
curated.pos_transactions | staging.brink_orders, staging.brink_destinations, staging.brink_employees | Order, Destination, Employee | Sales2.GetOrders, destination docs, employee docs | Supported. Use order header data as the source of the transaction row. |
curated.pos_transaction_tenders | staging.brink_order_payments, staging.brink_order_payment_details, staging.brink_tenders, staging.brink_orders, staging.brink_employees | OrderPayment, OrderPaymentDetail, Tender | Sales2.GetOrders, Settings.GetTenders | Supported. Transform Brink payments into the current tender-style transaction contract. |
curated.pos_tables | staging.brink_tables | Table | Settings2.GetTables: https://brinkapiportal.parpos.com/settings2#GetTables | Supported as a direct lookup mapping. |
curated.pos_tenders | staging.brink_tenders | Tender | Settings.GetTenders: https://brinkapiportal.parpos.com/settings#GetTenders | Supported as a direct lookup mapping with many nullable fields. |
curated.pos_catalog_items | staging.brink_items, staging.brink_taxes | MenuItem or Item, Tax | item docs, tax docs | Supported. Map only fields with safe Brink equivalents. |
curated.pos_modifiers | staging.brink_modifier_groups, staging.brink_modifier_group_items, staging.brink_items | ModifierGroup, child membership | modifier docs, item docs | Supported. Canonical projection only, not one-to-one parity. |
curated.pos_orders | staging.brink_orders, staging.brink_order_payments, staging.brink_destinations | Order, OrderPayment, Destination | Sales2.GetOrders, destination docs | Optional in the PoC. Add only if we agree on a simple canonical mapping. |
curated.pos_order_items | staging.brink_order_entries, staging.brink_orders, staging.brink_items, staging.brink_order_entry_modifiers | OrderEntry, Order, Item | Sales2.GetOrders, item docs | Optional in the PoC. Add only if we agree on a simple canonical mapping. |
curated.pos_menu_items | staging.brink_items, staging.brink_destinations, staging.brink_kitchen_queues | MenuItem or Item, Destination, KitchenQueue | item docs, destination docs, queue docs | Optional in the PoC. Only if the current contract can be filled without excessive source-specific hacks. |
curated.customers | staging.brink_orders | customer-related fields on Order | Sales2.GetOrders: https://brinkapiportal.parpos.com/sales2#GetOrders | Out of scope unless Brink order payloads give stable customer data for the current contract. |
curated.pos_table_definitions | none | none | none | Out of scope for the PoC. |
curated.loyalty_customers | none | none | none | Out of scope for the PoC. |
curated.pos_hourly_sales | none | none | none | Out of scope for the PoC. |
curated.inventory_items | none | none | none | Out of scope for the PoC. |
PoC metadata minimum
Use the existing control-plane metadata only:
TenantWarehouseMappingIngestionBatchIngestionCheckpoint
For the PoC, this is enough if we also do these three things:
- Save raw SOAP responses to S3.
- Record the main raw response path on the batch when practical.
- Emit structured logs for every Brink call.
Minimum batch usage
- Use one
IngestionBatchper Brink sync stream. - Recommended first stream names:
- orders
- order-bumps
- item-bumps
- settings
Minimum checkpoint usage
Use the existing IngestionCheckpoint table with these keys:
location:{location_key}:orders:modified-timelocation:{location_key}:order-bumps:bump-timelocation:{location_key}:item-bumps:bump-timelocation:{location_key}:settings:last-modified
Rules:
- advance checkpoints only after successful end-to-end completion of the stream
- failed runs must not advance checkpoints
- preserve watermark offsets exactly for Brink
DateTimeOffsetvalues
Minimum structured logging
For every Brink call, log at least:
tenant_idbatch_idsource_typeservice_nameoperation_nameendpoint_urlrequest_window_startrequest_window_endresult_codestatusraw_response_s3_path
PoC minimum bar
The Brink PoC is good enough if:
- One tenant can be linked to one Brink location and endpoint stack.
- The adapter can pull orders, kitchen bumps, and one settings freshness check.
- Raw SOAP responses are saved to S3.
- One batch is recorded per sync stream.
- Checkpoints advance only after stream success.
- Failures do not advance checkpoints.
- Logs are rich enough to diagnose which Brink call failed and for what time window.
- The first agreed curated tables can be populated from the staging subset.
References
docs/ETL.mddocs/features/ETL/epics/06-source-adapter-brink-pos-api/backend/Kds.Ai.Warehouse/Sql/Bootstrap/Tenant/Staging/backend/Kds.Ai.Warehouse/Models/Curated/CuratedCanonicalModels.cshttps://brinkapiportal.parpos.com/https://brinkapiportal.parpos.com/bestpracticeandfaqshttps://brinkapiportal.parpos.com/sales2https://brinkapiportal.parpos.com/settings2https://brinkapiportal.parpos.com/settingshttps://brinkapiportal.parpos.com/kitchen