Backend API Reference
Base URL: /api/v1
Technical Specifications & Models
Architectural Diagrams
- URL: https://s.icepanel.io/zy65Yso2WMsBJH/uB20
- Password: Pinpoint123!
Table of Contents
- Individual Access Management
- Models
- Platform Users
- Organizations
- Stores
- Users
- Org Memberships
- Store Memberships
- Invites
- Products
- Product Categories
- Suppliers
- Customers
- Inventory
- Inventory Ledger
- Serial Numbers
- Transactions
- Returns
- Discounts
- Promotions
- Compliance Checks
- Notifications
- Stock Transfers
- Tax Configurations
- Terminals
- Shifts
- Activity Log
- Specifications
- API Endpoints
Models
PlatformUser
File: internal/repository/platform_users.go
| Field | Type | JSON |
|---|---|---|
| UserID | uuid.UUID | user_id |
string | email | |
| PasswordHash | string | - (hidden) |
| FirstName | string | first_name |
| LastName | string | last_name |
| Role | string | role |
| Active | bool | active |
| LastLogin | *time.Time | last_login |
| CreatedAt | time.Time | created_at |
| UpdatedAt | time.Time | updated_at |
Organization
An Organization is a grouping of Stores (see Store) controlled by one Owner.
SSO UPSELL - Potential future feature
File: internal/repository/organizations.go
Attributes:
| Field | Type | JSON | Description |
|---|---|---|---|
| OrgID | uuid.UUID | org_id | Unique identifier |
| Name | string | name | Friendly name |
| EIN | string | ein | Employer Identification Number |
| Slug | string | slug | URL-friendly identifier (e.g., peakpos.co/pinpoint-payments) |
| Active | bool | active | Whether organization is active |
| CreatedAt | time.Time | created_at | Database creation timestamp |
| UpdatedAt | time.Time | updated_at | Database update timestamp |
| HQLocation | string | hq_location | Headquarters location (derives timezone) |
| TimeOffset | int | time_offset | Time zone offset |
Dependents:
- Suppliers
- Stores (see Store)
- Product Categories (user-definable)
- Products (see Products) - modifiable by Stores and Organization
- Users (see User) - via Master User (all groups) and OrgMembership object
Store
A Store is a Place/Point of Sale.
File: internal/repository/stores.go
Attributes:
| Field | Type | JSON | Description |
|---|---|---|---|
| StoreID | uuid.UUID | store_id | Unique identifier |
| OrgID | uuid.UUID | org_id | Parent organization |
| Name | string | name | Store name |
| AddressLine1 | *string | address_line1 | Street address |
| AddressLine2 | *string | address_line2 | Suite/unit number |
| City | *string | city | City |
| State | *string | state | State |
| ZipCode | *string | zip_code | ZIP/Postal code |
| Phone | *string | phone | Contact phone |
| Currency | string | currency | Currency code |
| Timezone | string | timezone | Store timezone |
| OpeningTime | *string | opening_time | Opening time (7-day schedule) |
| ClosingTime | *string | closing_time | Closing time (7-day schedule) |
| RCN | *string | rcn | Registration/compliance number |
| Active | bool | active | Whether store is active |
| OnboardingCompleted | bool | onboarding_completed | Onboarding status |
| CreatedAt | time.Time | created_at | Database creation timestamp |
| UpdatedAt | time.Time | updated_at | Database update timestamp |
Dependents:
User
Any person who accesses this platform.
File: internal/repository/users.go
Attributes:
| Field | Type | JSON | Description |
|---|---|---|---|
| UserID | uuid.UUID | user_id | Unique identifier |
string | email | User email | |
| PasswordHash | string | - (hidden) | Hashed password |
| FirstName | string | first_name | First name |
| LastName | string | last_name | Last name |
| PIN | *string | - (hidden) | PIN for quick login |
| Active | bool | active | Whether user is active |
| LastLogin | *time.Time | last_login | Last login timestamp |
| CreatedAt | time.Time | created_at | Database creation timestamp |
| UpdatedAt | time.Time | updated_at | Database update timestamp |
| Roles | []Role | roles | User roles |
| RoleID | uuid.UUID | role_id | Primary role identifier |
| GroupIDs | []uuid.UUID | group_ids | List of group memberships |
| TaxInfo | object | tax_info | Tax information (NO SSN!) |
| AccountingID | *string | accounting_id | E.g., QuickBooks EmployeeUUID |
| PayrollID | *string | payroll_id | E.g., QuickBooks EmployeeUUID |
Dependent to:
- Organizations
- Stores
- Shifts
Tech Support User:
A special type of user created via any interaction with a user who belongs to an organization. This includes generic employees. Tech support users receive privileges equivalent to the user who requested tech support.
- Time-limited role that expires in one hour
OrgMembership
File: internal/repository/org_memberships.go
| Field | Type | JSON |
|---|---|---|
| MembershipID | uuid.UUID | membership_id |
| OrgID | uuid.UUID | org_id |
| UserID | uuid.UUID | user_id |
| Role | string | role |
| CreatedAt | time.Time | created_at |
OrgMembershipWithUser extends the above with:
| Field | Type | JSON |
|---|---|---|
string | email | |
| FirstName | string | first_name |
| LastName | string | last_name |
| Active | bool | active |
StoreMembership
File: internal/repository/store_memberships.go
| Field | Type | JSON |
|---|---|---|
| MembershipID | uuid.UUID | membership_id |
| StoreID | uuid.UUID | store_id |
| UserID | uuid.UUID | user_id |
| Role | string | role |
| Clearances | int | clearances |
| CreatedAt | time.Time | created_at |
StoreMembershipWithUser extends the above with:
| Field | Type | JSON |
|---|---|---|
string | email | |
| FirstName | string | first_name |
| LastName | string | last_name |
| Active | bool | active |
Invite
File: internal/repository/invites.go
| Field | Type | JSON |
|---|---|---|
| InviteID | uuid.UUID | invite_id |
| OrgID | uuid.UUID | org_id |
| StoreID | *uuid.UUID | store_id |
string | email | |
| FirstName | *string | first_name |
| LastName | *string | last_name |
| OrgRole | *string | org_role |
| StoreRole | *string | store_role |
| Token | string | token |
| Status | string | status |
| ExpiresAt | time.Time | expires_at |
| AcceptedAt | *time.Time | accepted_at |
| CreatedBy | *uuid.UUID | created_by |
| CreatedAt | time.Time | created_at |
Product
A product sold in an organization.
File: internal/repository/products.go
Attributes:
| Field | Type | JSON | Description |
|---|---|---|---|
| ProductID | uuid.UUID | product_id | Unique identifier |
| StoreID | uuid.UUID | store_id | Store(s) where product is sold |
| Barcode | string | barcode | Barcode/SKU |
| Name | string | name | Product name |
| Description | *string | description | Product description |
| SupplierID | *uuid.UUID | supplier_id | Supplier reference |
| Price | decimal.Decimal | price | Selling price |
| Cost | decimal.Decimal | cost | Cost price |
| RequiresSerial | bool | requires_serial | Whether product requires serial number tracking |
| Over18 | bool | over_18 | Requires 18+ age verification |
| Over21 | bool | over_21 | Requires 21+ age verification |
| TaxRate | decimal.Decimal | tax_rate | Tax rate for product |
| Stock | int | stock | Total stock (tied with sum(inventory, product, all stores)) |
| ProductType | string | product_type | Type/category of product |
| Active | bool | active | Whether product is active |
| CreatedAt | time.Time | created_at | Database creation timestamp |
| UpdatedAt | time.Time | updated_at | Database update timestamp |
Dependents:
- Inventory
- SerialNumber
- ProductCategory
- Supplier
ProductCategory
Categories for products.
File: internal/repository/product_categories.go
Attributes:
| Field | Type | JSON | Description |
|---|---|---|---|
| CategoryID | uuid.UUID | category_id | Unique identifier |
| OrgID | uuid.UUID | org_id | Parent organization |
| IsChild | bool | is_child | Whether this is a child category |
| ParentID | *uuid.UUID | parent_id | Parent category ID (for nested categories) |
| Name | string | name | Category name |
| Slug | string | slug | URL-friendly identifier |
| Depth | int16 | depth | Nesting depth level |
| SortOrder | int | sort_order | Display order |
| Active | bool | active | Whether category is active |
| CreatedAt | time.Time | created_at | Database creation timestamp |
| UpdatedAt | time.Time | updated_at | Database update timestamp |
Supplier
A company that makes or distributes a product to the store.
File: internal/repository/suppliers.go
Attributes:
| Field | Type | JSON | Description |
|---|---|---|---|
| SupplierID | uuid.UUID | supplier_id | Unique identifier |
| OrgID | uuid.UUID | org_id | Parent organization |
| Name | string | name | Supplier name |
| ContactEmail | *string | contact_email | Contact email address |
| ContactPhone | *string | contact_phone | Contact phone number |
| Active | bool | active | Whether supplier is active |
| CreatedAt | time.Time | created_at | Database creation timestamp |
| UpdatedAt | time.Time | updated_at | Database update timestamp |
ProductSupplier (junction):
| Field | Type | JSON | Description |
|---|---|---|---|
| ProductID | uuid.UUID | product_id | Product reference |
| SupplierID | uuid.UUID | supplier_id | Supplier reference |
| SupplierSKU | *string | supplier_sku | Supplier's SKU for this product |
| Cost | *decimal.Decimal | cost | Cost from this supplier |
| IsPreferred | bool | is_preferred | Whether this is the preferred supplier |
Customer
File: internal/repository/customers.go
Attributes:
| Field | Type | JSON | Description |
|---|---|---|---|
| CustomerID | uuid.UUID | customer_id | Unique identifier |
| OrgID | uuid.UUID | org_id | Parent organization |
| DOB | *time.Time | dob | Date of birth |
| FirstName | *string | first_name | First name |
| LastName | *string | last_name | Last name |
*string | email | Email address | |
| Phone | *string | phone | Phone number |
| Points | int | points | Loyalty points |
| CreatedAt | time.Time | created_at | Database creation timestamp |
| UpdatedAt | time.Time | updated_at | Database update timestamp |
InventoryEntry
Also known as StoreInventoryItem.
File: internal/repository/inventory.go
Attributes:
| Field | Type | JSON | Description |
|---|---|---|---|
| InventoryID | uuid.UUID | inventory_id | Unique identifier (StoreInventoryItemID) |
| StoreID | uuid.UUID | store_id | Store reference |
| OrgID | uuid.UUID | org_id | Organization reference |
| ProductID | uuid.UUID | product_id | Product reference |
| Quantity | int | quantity | Current quantity |
| Price | decimal.Decimal | price | Price at this store |
| ChangeType | string | change_type | Type of inventory change |
| ReferenceID | *uuid.UUID | reference_id | Reference to related entity |
| UserID | *uuid.UUID | user_id | User who made the change |
| SourceStoreID | *uuid.UUID | source_store_id | Source store for transfers |
| DestStoreID | *uuid.UUID | destination_store_id | Destination store for transfers |
| Notes | *string | notes | Additional notes |
| CreatedAt | time.Time | created_at | Database creation timestamp |
Dependents:
- Inventory Ledger Update
Depends on:
- Store
- Product
InventoryLevel / LedgerEntry
Also known as InventoryLedgerUpdate.
File: internal/repository/inventory_ledger.go
InventoryLevel:
| Field | Type | JSON | Description |
|---|---|---|---|
| StoreID | uuid.UUID | store_id | Store reference |
| ProductID | uuid.UUID | product_id | Product reference |
| QuantityOnHand | int | quantity_on_hand | Current quantity on hand |
| ReorderPoint | *int | reorder_point | Threshold for reorder alert |
| ReorderQty | *int | reorder_qty | Suggested reorder quantity |
| LastCountedAt | *time.Time | last_counted_at | Last physical count timestamp |
| UpdatedAt | time.Time | updated_at | Database update timestamp |
LedgerEntry (InventoryLedgerUpdate):
| Field | Type | JSON | Description |
|---|---|---|---|
| LedgerID | uuid.UUID | ledger_id | Unique identifier (ReferenceID) |
| StoreID | uuid.UUID | store_id | Store reference |
| OrgID | uuid.UUID | org_id | Organization reference |
| ProductID | uuid.UUID | product_id | Product reference |
| StoreInventoryItemID | uuid.UUID | store_inventory_item_id | From inventory item |
| QuantityChange | int | quantity_change | Quantity delta |
| ChangeType | string | change_type | Type of change |
| ReferenceType | *string | reference_type | Type of referenced entity |
| ReferenceID | *uuid.UUID | reference_id | ID of this update |
| UserID | *uuid.UUID | user_id | User that made change |
| Notes | *string | notes | Additional notes |
| CreatedAt | time.Time | created_at | Database creation timestamp |
Depends on:
- StoreInventoryItem
SerialNumber
File: internal/repository/serial_numbers.go
Attributes:
| Field | Type | JSON | Description |
|---|---|---|---|
| SerialID | uuid.UUID | serial_id | Unique identifier |
| OrgID | uuid.UUID | org_id | Organization reference |
| StoreID | uuid.UUID | store_id | Store reference |
| ProductID | uuid.UUID | product_id | Product reference |
| SerialNumber | string | serial_number | The serial number string |
| Status | string | status | Current status (available, sold, returned) |
| ReceivedAt | time.Time | received_at | When serial was received |
| SoldAt | *time.Time | sold_at | When serial was sold |
| TransactionID | *uuid.UUID | transaction_id | Associated transaction |
| UserID | *uuid.UUID | user_id | User who sold to / received from |
| Notes | *string | notes | Additional notes |
| RequiredForms | *string | required_forms | Any required forms (point to S3) |
Transaction
File: internal/repository/transactions.go
Attributes:
| Field | Type | JSON | Description |
|---|---|---|---|
| TransactionID | uuid.UUID | transaction_id | Unique identifier |
| TransactionRef | int | transaction_ref | Non-unique int for Dejavoo |
| StoreID | uuid.UUID | store_id | Store reference |
| OrgID | uuid.UUID | org_id | Organization reference |
| ProductIDs | []uuid.UUID | product_ids | List of product IDs |
| UserID | uuid.UUID | user_id | Cashier/employee |
| CustomerID | *uuid.UUID | customer_id | Customer (optional) |
| TerminalID | *uuid.UUID | terminal_id | Terminal used |
| Datetime | time.Time | datetime | Transaction timestamp |
| Subtotal | decimal.Decimal | subtotal | Subtotal before tax/discount |
| TaxApplied | decimal.Decimal | tax_applied | Total taxes |
| DiscountTotal | decimal.Decimal | discount_total | Total discounts |
| TotalSpent | decimal.Decimal | total_spent | Final total |
| AmountPaidWithCash | decimal.Decimal | amount_paid_cash | Cash amount |
| AmountPaidWithCard | decimal.Decimal | amount_paid_card | Card amount |
| PaymentMethod | string | payment_method | Payment method (Cash, card, etc) (Enum) |
| Status | string | status | Transaction status |
| CreatedAt | time.Time | created_at | Database creation timestamp |
| UpdatedAt | time.Time | updated_at | Database update timestamp |
Depends on:
- Store
- Organization
- Customer (Optional)
- InventoryLedgerUpdate(s) [list of updates]
- Return (Optional)
- Discount(s) (Optional)
Dependencies:
- DejavooCardAuthorization (Optional)
TransactionItem:
| Field | Type | JSON | Description |
|---|---|---|---|
| ItemID | uuid.UUID | item_id | Unique identifier |
| TransactionID | uuid.UUID | transaction_id | Parent transaction |
| ProductID | uuid.UUID | product_id | Product reference |
| Quantity | int | quantity | Quantity purchased |
| UnitPrice | decimal.Decimal | unit_price | Price per unit |
| DiscountApplied | decimal.Decimal | discount_applied | Discount on this item |
| TaxApplied | decimal.Decimal | tax_applied | Tax on this item |
| LineTotal | decimal.Decimal | line_total | Total for this line |
TransactionPayment:
| Field | Type | JSON | Description |
|---|---|---|---|
| PaymentID | uuid.UUID | payment_id | Unique identifier |
| TransactionID | uuid.UUID | transaction_id | Parent transaction |
| PaymentMethod | string | payment_method | Method (cash, card, etc) |
| Amount | decimal.Decimal | amount | Amount paid |
| ReferenceNum | *string | reference_num | External reference number |
| ProcessedAt | time.Time | processed_at | When payment was processed |
TransactionDetail extends Transaction with:
| Field | Type | JSON | Description |
|---|---|---|---|
| UserName | string | user_name | Employee name |
| CustomerName | *string | customer_name | Customer name |
| Items | []TransactionItem | items | Transaction items |
| Payments | []TransactionPayment | payments | Payment records |
Receipts
Receipts are generated from Transactions for customer-facing documentation.
Note: Implementation details TBD - likely generated from Transaction data.
DejavooCardAuthorization
Status: TBD
Card authorization records for Dejavoo payment processing.
Attributes:
| Field | Type | JSON | Description |
|---|---|---|---|
| AuthorizationID | uuid.UUID | authorization_id | Unique identifier |
| TransactionID | uuid.UUID | transaction_id | Parent transaction |
| ... | ... | ... | TBD |
Dependencies: N/A
Depends on:
- Transaction
Batch
Status: TBD
Batch processing for card authorizations.
Attributes:
| Field | Type | JSON | Description |
|---|---|---|---|
| BatchID | uuid.UUID | batch_id | Unique identifier |
| StoreID | uuid.UUID | store_id | Store reference |
| BatchNumber | string | batch_number | Batch number |
| AuthorizationIDs | []uuid.UUID | authorization_ids | List of authorization IDs |
| BatchStatus | string | batch_status | Status (enum) |
Dependencies: N/A
Depends on:
- DejavooCardAuthorization
Return
File: internal/repository/returns.go
| Field | Type | JSON |
|---|---|---|
| ReturnID | uuid.UUID | return_id |
| StoreID | uuid.UUID | store_id |
| UserID | uuid.UUID | user_id |
| CustomerID | *uuid.UUID | customer_id |
| ProductID | uuid.UUID | product_id |
| TransactionID | *uuid.UUID | transaction_id |
| Quantity | int | quantity |
| RefundAmount | decimal.Decimal | refund_amount |
| DateReturned | time.Time | date_returned |
| Reason | string | reason |
| ReasonNotes | *string | reason_notes |
| Restocked | bool | restocked |
| CreatedAt | time.Time | created_at |
ReturnWithDetails extends the above with:
| Field | Type | JSON |
|---|---|---|
| UserName | string | user_name |
| ProductName | string | product_name |
| CustomerName | *string | customer_name |
Discount
File: internal/repository/discounts.go
Attributes:
| Field | Type | JSON | Description |
|---|---|---|---|
| DiscountID | uuid.UUID | discount_id | Unique identifier |
| OrgID | uuid.UUID | org_id | Organization reference |
| StoreID | uuid.UUID | store_id | Store reference |
| ProductID | *uuid.UUID | product_id | Product reference (optional) |
| Qty | int | qty | Quantity threshold |
| Name | string | name | Discount name |
| Description | *string | description | Discount description |
| Type | string | type | Discount type (enum) |
| Discount | decimal.Decimal | discount | Discount amount (float) |
| StartDate | time.Time | start_date | Start date |
| EndDate | time.Time | end_date | End date |
| ProductType | *string | product_type | Product type filter |
| DiscountType | string | discount_type | Type (percent/fixed) |
| Amount | decimal.Decimal | amount | Amount value |
| MinPurchase | *decimal.Decimal | min_purchase | Minimum purchase required |
| MaxDiscount | *decimal.Decimal | max_discount | Maximum discount cap |
| Active | bool | active | Whether discount is active |
| CreatedAt | time.Time | created_at | Database creation timestamp |
| UpdatedAt | time.Time | updated_at | Database update timestamp |
Dependencies:
- Transaction
Depends On:
- Organization
- Store
- Product
Promotion
File: internal/repository/promotions.go
| Field | Type | JSON |
|---|---|---|
| PromotionID | uuid.UUID | promotion_id |
| OrgID | uuid.UUID | org_id |
| Name | string | name |
| Description | *string | description |
| PromotionType | string | promotion_type |
| BuyQuantity | int | buy_quantity |
| GetQuantity | int | get_quantity |
| DiscountValue | *decimal.Decimal | discount_value |
| AppliesToAllStores | bool | applies_to_all_stores |
| StartDate | time.Time | start_date |
| EndDate | time.Time | end_date |
| Active | bool | active |
| MaxUsesPerTransaction | *int | max_uses_per_transaction |
| CreatedAt | time.Time | created_at |
| UpdatedAt | time.Time | updated_at |
| ProductIDs | []uuid.UUID | product_ids |
| StoreIDs | []uuid.UUID | store_ids |
ComplianceCheck
File: internal/repository/compliance.go
| Field | Type | JSON |
|---|---|---|
| CheckID | uuid.UUID | check_id |
| OrgID | uuid.UUID | org_id |
| StoreID | uuid.UUID | store_id |
| TransactionID | *uuid.UUID | transaction_id |
| ProductID | uuid.UUID | product_id |
| UserID | uuid.UUID | user_id |
| CheckType | string | check_type |
| IDType | *string | id_type |
| IDDob | *time.Time | id_dob |
| IDExpiry | *time.Time | id_expiry |
| VerifiedAge | *int | verified_age |
| RequiredAge | int | required_age |
| Result | string | result |
| OverrideReason | *string | override_reason |
| OverrideBy | *uuid.UUID | override_by |
| CreatedAt | time.Time | created_at |
ComplianceSummary:
| Field | Type | JSON |
|---|---|---|
| TotalChecks | int | total_checks |
| Passes | int | passes |
| Fails | int | fails |
| Overrides | int | overrides |
Notification
File: internal/repository/notifications.go
| Field | Type | JSON |
|---|---|---|
| NotificationID | uuid.UUID | notification_id |
| OrgID | uuid.UUID | org_id |
| StoreID | *uuid.UUID | store_id |
| Type | string | type |
| Title | string | title |
| Message | string | message |
| Metadata | json.RawMessage | metadata |
| Read | bool | read |
| CreatedAt | time.Time | created_at |
StockTransfer
File: internal/repository/stock_transfers.go
| Field | Type | JSON |
|---|---|---|
| TransferID | uuid.UUID | transfer_id |
| OrgID | uuid.UUID | org_id |
| FromStoreID | uuid.UUID | from_store_id |
| ToStoreID | uuid.UUID | to_store_id |
| Status | string | status |
| InitiatedBy | uuid.UUID | initiated_by |
| ReceivedBy | *uuid.UUID | received_by |
| Notes | *string | notes |
| CreatedAt | time.Time | created_at |
| CompletedAt | *time.Time | completed_at |
| Items | []StockTransferItem | items |
StockTransferItem:
| Field | Type | JSON |
|---|---|---|
| ID | uuid.UUID | id |
| TransferID | uuid.UUID | transfer_id |
| ProductID | uuid.UUID | product_id |
| Quantity | int | quantity |
| ReceivedQty | *int | received_qty |
TaxConfig
File: internal/repository/tax_configurations.go
| Field | Type | JSON |
|---|---|---|
| TaxConfigID | uuid.UUID | tax_config_id |
| StoreID | uuid.UUID | store_id |
| Label | *string | label |
| JurisdictionType | string | jurisdiction_type |
| JurisdictionCode | *string | jurisdiction_code |
| JurisdictionName | *string | jurisdiction_name |
| RateType | string | rate_type |
| RateBps | *int | rate_bps |
| RateAmountMinor | *int64 | rate_amount_minor |
| TaxBasis | string | tax_basis |
| AppliesToCategory | *uuid.UUID | applies_to_category |
| Priority | int | priority |
| EffectiveFrom | string | effective_from |
| EffectiveTo | *string | effective_to |
| Active | bool | active |
| CreatedAt | time.Time | created_at |
| UpdatedAt | time.Time | updated_at |
Tax calculation rejects malformed jurisdiction_type or rate_type values instead of silently zero-rating them.
Tax Reports
Notes: tax report endpoints require explicit from and to query parameters; the API no longer invents a rolling default range.
| Method | Path | Notes |
|---|---|---|
| GET | /stores/:store_id/tax-reports | Requires from and to |
| GET | /stores/:store_id/tax-reports/summary | Requires from and to |
Terminal
File: internal/repository/terminals.go
| Field | Type | JSON |
|---|---|---|
| TerminalID | uuid.UUID | terminal_id |
| StoreID | uuid.UUID | store_id |
| TerminalName | string | terminal_name |
| TerminalSecret | string | terminal_secret |
| IsActive | bool | is_active |
| LastSeen | *time.Time | last_seen |
| CreatedAt | time.Time | created_at |
Shifts
File: internal/repository/shifts.go
ShiftPreference:
| Field | Type | JSON |
|---|---|---|
| PreferenceID | uuid.UUID | preference_id |
| StoreID | uuid.UUID | store_id |
| UserID | uuid.UUID | user_id |
| DayOfWeek | int | day_of_week |
| StartTime | string | start_time |
| EndTime | string | end_time |
| Priority | int | priority |
| CreatedAt | time.Time | created_at |
| UpdatedAt | time.Time | updated_at |
ShiftAssigned:
| Field | Type | JSON |
|---|---|---|
| AssignedID | uuid.UUID | assigned_id |
| StoreID | uuid.UUID | store_id |
| UserID | uuid.UUID | user_id |
| AssignedBy | uuid.UUID | assigned_by |
| ShiftDate | time.Time | shift_date |
| StartTime | string | start_time |
| EndTime | string | end_time |
| Notes | *string | notes |
| CreatedAt | time.Time | created_at |
| UpdatedAt | time.Time | updated_at |
ShiftActual:
| Field | Type | JSON |
|---|---|---|
| ActualID | uuid.UUID | actual_id |
| StoreID | uuid.UUID | store_id |
| UserID | uuid.UUID | user_id |
| AssignedID | *uuid.UUID | assigned_id |
| ShiftDate | time.Time | shift_date |
| ClockIn | *time.Time | clock_in |
| ClockOut | *time.Time | clock_out |
| BreakMinutes | int | break_minutes |
| NoShow | bool | no_show |
| CreatedAt | time.Time | created_at |
| UpdatedAt | time.Time | updated_at |
ShiftRequest:
| Field | Type | JSON |
|---|---|---|
| RequestID | uuid.UUID | request_id |
| StoreID | uuid.UUID | store_id |
| UserID | uuid.UUID | user_id |
| RequestedDate | time.Time | requested_date |
| StartTime | string | start_time |
| EndTime | string | end_time |
| Status | string | status |
| ReviewedBy | *uuid.UUID | reviewed_by |
| ReviewedAt | *time.Time | reviewed_at |
| Notes | *string | notes |
| CreatedAt | time.Time | created_at |
ActivityLog
File: internal/repository/activity_log.go
| Field | Type | JSON |
|---|---|---|
| LogID | uuid.UUID | log_id |
| ActorType | string | actor_type |
| ActorID | uuid.UUID | actor_id |
| OrgID | *uuid.UUID | org_id |
| StoreID | *uuid.UUID | store_id |
| Action | string | action |
| EntityType | *string | entity_type |
| EntityID | *uuid.UUID | entity_id |
| Details | map[string]interface{} | details |
| IPAddress | *string | ip_address |
| CreatedAt | time.Time | created_at |
Standard API Response Envelope
All responses use:
{
"success": true,
"data": { ... },
"error": { "code": "...", "message": "..." },
"meta": { "page": 1, "limit": 20, "total": 100, "total_pages": 5 }
}
Specifications
IAM
Individual Access Management specification for the platform.
Group
Definition: Non-user defined groups are an arbitrary grouping of services (API endpoints, microservices, etc.)
Permissions (AWS-style)
- Permissions are assignable to a Group
- Permissions should be the maximal grouping of API endpoints and/or microservices relevant to that Group
Roles
- Roles are a user-defined selection of Groups that give access to a particular service
- Roles are defined at an Organization level
Users
Users have the following IAM-related attributes:
- REQUIRES a Role
- Have a list of Role IDs
- Have UUIDs that correspond to Groups
- On a separate list, modifiers (diversions) from a Role are stored with UUIDs
API Endpoints
Public Routes (No Auth)
| Method | Path | Handler | Description |
|---|---|---|---|
| GET | /health | inline | Health check |
| POST | /api/v1/auth/login | authHandler.Login | User login |
| POST | /api/v1/platform/auth/login | platformAuthHandler.Login | Platform admin login |
| POST | /api/v1/invites/validate | inviteHandler.Validate | Validate invite token |
| POST | /api/v1/invites/accept | inviteHandler.Accept | Accept invite and create account |
| POST | /api/v1/stores/:store_id/auth/pin-login | pinAuthHandler.Login | PIN-based login for store staff |
Authenticated Routes
Middleware: Auth(jwtSecret)
| Method | Path | Handler | Description |
|---|---|---|---|
| GET | /api/v1/auth/me | authHandler.Me | Get current user info |
| POST | /api/v1/auth/change-password | authHandler.ChangePassword | Change password |
| GET | /api/v1/platform/auth/me | platformAuthHandler.Me | Get current platform user info |
Platform Routes
Middleware: Auth + PlatformOnly
Superadmin Only
Middleware: + PlatformRole("superadmin")
| Method | Path | Handler | Description |
|---|---|---|---|
| GET | /api/v1/platform/orgs | platformOrgHandler.List | List organizations |
| POST | /api/v1/platform/orgs | platformOrgHandler.Create | Create organization |
| GET | /api/v1/platform/orgs/:id | platformOrgHandler.Get | Get organization |
| PUT | /api/v1/platform/orgs/:id | platformOrgHandler.Update | Update organization |
| DELETE | /api/v1/platform/orgs/:id | platformOrgHandler.Delete | Delete organization |
| GET | /api/v1/platform/orgs/:id/stores | platformOrgHandler.ListStores | List org stores |
| GET | /api/v1/platform/users | platformUserHandler.List | List platform users |
| POST | /api/v1/platform/users | platformUserHandler.Create | Create platform user |
| GET | /api/v1/platform/users/:id | platformUserHandler.Get | Get platform user |
| PUT | /api/v1/platform/users/:id | platformUserHandler.Update | Update platform user |
| DELETE | /api/v1/platform/users/:id | platformUserHandler.Delete | Delete platform user |
Superadmin + Support
Middleware: + PlatformRole("superadmin", "support")
| Method | Path | Handler | Description |
|---|---|---|---|
| POST | /api/v1/platform/impersonate | impersonateHandler.Impersonate | Impersonate org/store user |
Organization-Scoped Routes
Base path: /api/v1/orgs/:org_id
Middleware: Auth + OrgContext
All Org Members
| Method | Path | Handler | Description |
|---|---|---|---|
| GET | /orgs/:org_id/members | orgMemberHandler.List | List org members |
| GET | /orgs/:org_id/customers | orgCustomerHandler.List | List customers |
| GET | /orgs/:org_id/customers/:customer_id | orgCustomerHandler.Get | Get customer |
| POST | /orgs/:org_id/customers | orgCustomerHandler.Create | Create customer |
| PUT | /orgs/:org_id/customers/:customer_id | orgCustomerHandler.Update | Update customer |
| POST | /orgs/:org_id/customers/:customer_id/points | orgCustomerHandler.AdjustPoints | Adjust loyalty points |
| GET | /orgs/:org_id/categories | categoryHandler.List | List categories |
| GET | /orgs/:org_id/categories/tree | categoryHandler.ListTree | List category tree |
| GET | /orgs/:org_id/categories/:category_id | categoryHandler.Get | Get category |
| GET | /orgs/:org_id/suppliers | supplierHandler.List | List suppliers |
| GET | /orgs/:org_id/suppliers/:supplier_id | supplierHandler.Get | Get supplier |
| GET | /orgs/:org_id/suppliers/:supplier_id/products | supplierHandler.ListProductSuppliers | List supplier products |
| GET | /orgs/:org_id/serial-numbers | serialNumberHandler.List | List serial numbers |
| GET | /orgs/:org_id/serial-numbers/:serial_id | serialNumberHandler.Get | Get serial number |
| GET | /orgs/:org_id/serial-numbers/lookup/:serial | serialNumberHandler.GetBySerial | Lookup by serial string |
| GET | /orgs/:org_id/notifications | notificationHandler.List | List notifications |
| GET | /orgs/:org_id/notifications/unread-count | notificationHandler.CountUnread | Count unread |
| GET | /orgs/:org_id/notifications/:notification_id | notificationHandler.Get | Get notification |
| POST | /orgs/:org_id/notifications/:notification_id/read | notificationHandler.MarkRead | Mark read |
| POST | /orgs/:org_id/notifications/read-all | notificationHandler.MarkAllRead | Mark all read |
| GET | /orgs/:org_id/promotions | promotionHandler.List | List promotions |
| GET | /orgs/:org_id/promotions/active | promotionHandler.ListActive | List active promotions |
| GET | /orgs/:org_id/promotions/:promotion_id | promotionHandler.Get | Get promotion |
| GET | /orgs/:org_id/stock-transfers | stockTransferHandler.List | List stock transfers |
| GET | /orgs/:org_id/stock-transfers/:transfer_id | stockTransferHandler.Get | Get stock transfer |
Org Admin (org_owner, org_admin)
Middleware: + RequireOrgRole("org_owner", "org_admin")
| Method | Path | Handler | Description |
|---|---|---|---|
| POST | /orgs/:org_id/members | orgMemberHandler.Add | Add org member |
| PUT | /orgs/:org_id/members/:user_id | orgMemberHandler.UpdateRole | Update member role |
| DELETE | /orgs/:org_id/members/:user_id | orgMemberHandler.Remove | Remove member |
| DELETE | /orgs/:org_id/customers/:customer_id | orgCustomerHandler.Delete | Delete customer |
| GET | /orgs/:org_id/invites | inviteHandler.ListByOrg | List org invites |
| POST | /orgs/:org_id/invites | inviteHandler.Create | Create invite |
| POST | /orgs/:org_id/invites/:invite_id/revoke | inviteHandler.Revoke | Revoke invite |
| DELETE | /orgs/:org_id/invites/:invite_id | inviteHandler.Delete | Delete invite |
| GET | /orgs/:org_id/activity-log | activityLogHandler.ListOrgActivityLogs | List org activity |
| POST | /orgs/:org_id/categories | categoryHandler.Create | Create category |
| PUT | /orgs/:org_id/categories/:category_id | categoryHandler.Update | Update category |
| DELETE | /orgs/:org_id/categories/:category_id | categoryHandler.Delete | Delete category |
| POST | /orgs/:org_id/suppliers | supplierHandler.Create | Create supplier |
| PUT | /orgs/:org_id/suppliers/:supplier_id | supplierHandler.Update | Update supplier |
| DELETE | /orgs/:org_id/suppliers/:supplier_id | supplierHandler.Delete | Delete supplier |
| POST | /orgs/:org_id/suppliers/:supplier_id/products | supplierHandler.AddProductSupplier | Link supplier to product |
| DELETE | /orgs/:org_id/suppliers/:supplier_id/products/:product_id | supplierHandler.RemoveProductSupplier | Unlink supplier |
| POST | /orgs/:org_id/serial-numbers | serialNumberHandler.Create | Create serial number |
| POST | /orgs/:org_id/serial-numbers/:serial_id/sell | serialNumberHandler.Sell | Mark serial sold |
| POST | /orgs/:org_id/serial-numbers/:serial_id/return | serialNumberHandler.Return | Mark serial returned |
| POST | /orgs/:org_id/notifications | notificationHandler.Create | Create notification |
| POST | /orgs/:org_id/promotions | promotionHandler.Create | Create promotion |
| PUT | /orgs/:org_id/promotions/:promotion_id | promotionHandler.Update | Update promotion |
| DELETE | /orgs/:org_id/promotions/:promotion_id | promotionHandler.Delete | Delete promotion |
| POST | /orgs/:org_id/promotions/:promotion_id/toggle | promotionHandler.ToggleActive | Toggle active |
| POST | /orgs/:org_id/stock-transfers | stockTransferHandler.Create | Create transfer |
| POST | /orgs/:org_id/stock-transfers/:transfer_id/ship | stockTransferHandler.Ship | Ship transfer |
| POST | /orgs/:org_id/stock-transfers/:transfer_id/receive | stockTransferHandler.Receive | Receive transfer |
| POST | /orgs/:org_id/stock-transfers/:transfer_id/cancel | stockTransferHandler.Cancel | Cancel transfer |
Store-Scoped Routes
Base path: /api/v1/stores/:store_id
Middleware: Auth + StoreContext
All Store Members
| Method | Path | Handler | Description |
|---|---|---|---|
| GET | /stores/:store_id/members | storeMemberHandler.List | List store members |
| GET | /stores/:store_id/products | productHandler.List | List products |
| GET | /stores/:store_id/products/:id | productHandler.Get | Get product |
| GET | /stores/:store_id/products/barcode/:barcode | productHandler.GetByBarcode | Get product by barcode |
| GET | /stores/:store_id/products/types | productHandler.GetTypes | Get product types |
| GET | /stores/:store_id/inventory | inventoryHandler.List | List inventory |
| GET | /stores/:store_id/inventory/:id | inventoryHandler.GetStock | Get stock level |
| GET | /stores/:store_id/inventory/:id/history | inventoryHandler.GetHistory | Get inventory history |
| GET | /stores/:store_id/transactions | transactionHandler.List | List transactions |
| GET | /stores/:store_id/transactions/:id | transactionHandler.Get | Get transaction |
| GET | /stores/:store_id/transactions/summary | transactionHandler.GetSummary | Get summary stats |
| GET | /stores/:store_id/transactions/daily-sales | transactionHandler.GetDailySales | Get daily sales |
| GET | /stores/:store_id/discounts | discountHandler.List | List discounts |
| GET | /stores/:store_id/discounts/:id | discountHandler.Get | Get discount |
| GET | /stores/:store_id/discounts/active | discountHandler.GetActive | Get active discounts |
| GET | /stores/:store_id/returns | returnHandler.List | List returns |
| GET | /stores/:store_id/returns/:id | returnHandler.Get | Get return |
| GET | /stores/:store_id/shifts/preferences/me | shiftHandler.GetMyPreferences | Get my shift preferences |
| POST | /stores/:store_id/shifts/preferences | shiftHandler.CreatePreference | Create preference |
| PUT | /stores/:store_id/shifts/preferences/:id | shiftHandler.UpdatePreference | Update preference |
| DELETE | /stores/:store_id/shifts/preferences/:id | shiftHandler.DeletePreference | Delete preference |
| GET | /stores/:store_id/shifts/assigned | shiftHandler.ListAssigned | List assigned shifts |
| GET | /stores/:store_id/shifts/assigned/me | shiftHandler.GetMyAssigned | Get my assigned shifts |
| GET | /stores/:store_id/shifts/status | shiftHandler.GetStatus | Get shift status |
| POST | /stores/:store_id/shifts/clock-in | shiftHandler.ClockIn | Clock in |
| POST | /stores/:store_id/shifts/clock-out | shiftHandler.ClockOut | Clock out |
| GET | /stores/:store_id/shifts/requests | shiftHandler.ListRequests | List shift requests |
| POST | /stores/:store_id/shifts/requests | shiftHandler.CreateRequest | Create shift request |
| GET | /stores/:store_id/settings | settingsHandler.GetStoreSettings | Get store settings |
| POST | /stores/:store_id/terminals/:id/heartbeat | settingsHandler.TerminalHeartbeat | Terminal heartbeat |
| GET | /stores/:store_id/compliance/checks | complianceHandler.GetChecks | Get compliance checks |
| GET | /stores/:store_id/compliance/checks/:check_id | complianceHandler.Get | Get check detail |
| GET | /stores/:store_id/compliance/summary | complianceHandler.GetSummary | Get compliance summary |
| POST | /stores/:store_id/compliance/verify-age | complianceHandler.VerifyAge | Verify age |
| GET | /stores/:store_id/tax-configs | taxConfigHandler.List | List tax configs |
| GET | /stores/:store_id/tax-configs/active | taxConfigHandler.ListActive | List active configs |
| GET | /stores/:store_id/tax-configs/:config_id | taxConfigHandler.Get | Get tax config |
| GET | /stores/:store_id/onboarding/status | onboardingHandler.GetStatus | Get onboarding status |
| POST | /stores/:store_id/mkonnekt/skandata | mkonnektHandler.GetSkanData | Get mKonnekt SKAN data |
Store Manager+ (store_admin, manager)
Middleware: + RequireStoreRole("store_admin", "manager")
| Method | Path | Handler | Description |
|---|---|---|---|
| POST | /stores/:store_id/products | productHandler.Create | Create product |
| PUT | /stores/:store_id/products/:id | productHandler.Update | Update product |
| POST | /stores/:store_id/inventory/receive | inventoryHandler.Receive | Receive inventory |
| POST | /stores/:store_id/inventory/adjust | inventoryHandler.Adjust | Adjust inventory |
| POST | /stores/:store_id/inventory/transfer | inventoryHandler.Transfer | Transfer inventory |
| POST | /stores/:store_id/transactions/:id/void | transactionHandler.Void | Void transaction |
| POST | /stores/:store_id/returns | returnHandler.Create | Create return |
| POST | /stores/:store_id/shifts/assigned | shiftHandler.CreateAssigned | Assign shift |
| PUT | /stores/:store_id/shifts/assigned/:id | shiftHandler.UpdateAssigned | Update assignment |
| DELETE | /stores/:store_id/shifts/assigned/:id | shiftHandler.DeleteAssigned | Delete assignment |
| POST | /stores/:store_id/shifts/requests/:id/review | shiftHandler.ReviewRequest | Review shift request |
| POST | /stores/:store_id/compliance/override | complianceHandler.Override | Override compliance check |
| GET | /stores/:store_id/reports/dashboard | reportHandler.Dashboard | Dashboard stats |
| GET | /stores/:store_id/reports/sales | reportHandler.Sales | Sales report |
| GET | /stores/:store_id/reports/inventory | reportHandler.Inventory | Inventory report |
| GET | /stores/:store_id/reports/members | reportHandler.Members | Members report |
| POST | /stores/:store_id/query | queryHandler.Query | NL query (symbolic logic) |
| GET | /stores/:store_id/query/schema | queryHandler.Schema | Get query schema |
Store Admin Only
Middleware: + RequireStoreRole("store_admin")
| Method | Path | Handler | Description |
|---|---|---|---|
| POST | /stores/:store_id/members | storeMemberHandler.Add | Add store member |
| PUT | /stores/:store_id/members/:user_id | storeMemberHandler.UpdateRole | Update member role |
| DELETE | /stores/:store_id/members/:user_id | storeMemberHandler.Remove | Remove member |
| DELETE | /stores/:store_id/products/:id | productHandler.Delete | Delete product |
| POST | /stores/:store_id/discounts | discountHandler.Create | Create discount |
| PUT | /stores/:store_id/discounts/:id | discountHandler.Update | Update discount |
| DELETE | /stores/:store_id/discounts/:id | discountHandler.Delete | Delete discount |
| POST | /stores/:store_id/discounts/:id/toggle | discountHandler.ToggleActive | Toggle discount |
| GET | /stores/:store_id/terminals | settingsHandler.ListTerminals | List terminals |
| GET | /stores/:store_id/terminals/:id | settingsHandler.GetTerminal | Get terminal |
| POST | /stores/:store_id/terminals | settingsHandler.CreateTerminal | Create terminal |
| PUT | /stores/:store_id/terminals/:id | settingsHandler.UpdateTerminal | Update terminal |
| DELETE | /stores/:store_id/terminals/:id | settingsHandler.DeleteTerminal | Delete terminal |
| POST | /stores/:store_id/terminals/:id/regenerate-secret | settingsHandler.RegenerateTerminalSecret | Regenerate secret |
| PUT | /stores/:store_id/settings | settingsHandler.UpdateStoreSettings | Update settings |
| PUT | /stores/:store_id/settings/timezone | settingsHandler.UpdateTimezone | Update timezone |
| PUT | /stores/:store_id/settings/operating-hours | settingsHandler.UpdateOperatingHours | Update hours |
| POST | /stores/:store_id/settings/complete-onboarding | settingsHandler.CompleteOnboarding | Complete onboarding |
| GET | /stores/:store_id/activity-log | activityLogHandler.ListActivityLogs | List activity logs |
| GET | /stores/:store_id/activity-log/actions | activityLogHandler.GetActions | Get distinct actions |
| GET | /stores/:store_id/activity-log/entity-types | activityLogHandler.GetEntityTypes | Get entity types |
| GET | /stores/:store_id/activity-log/user/:user_id | activityLogHandler.GetUserActivitySummary | User activity summary |
| GET | /stores/:store_id/activity-log/:id | activityLogHandler.GetActivityLog | Get single log entry |
| GET | /stores/:store_id/invites | inviteHandler.ListByStore | List store invites |
| POST | /stores/:store_id/invites | inviteHandler.Create | Create invite |
| POST | /stores/:store_id/invites/:invite_id/revoke | inviteHandler.Revoke | Revoke invite |
| DELETE | /stores/:store_id/invites/:invite_id | inviteHandler.Delete | Delete invite |
| GET | /stores/:store_id/compliance/list | complianceHandler.List | List all compliance |
| POST | /stores/:store_id/tax-configs | taxConfigHandler.Create | Create tax config |
| PUT | /stores/:store_id/tax-configs/:config_id | taxConfigHandler.Update | Update tax config |
| DELETE | /stores/:store_id/tax-configs/:config_id | taxConfigHandler.Delete | Delete tax config |
| PUT | /stores/:store_id/onboarding/phase | onboardingHandler.UpdatePhase | Update onboarding phase |
Request Body Schemas
Auth
POST /auth/login
{ "email": "string (required)", "password": "string (required)" }
POST /auth/change-password
{
"current_password": "string (required)",
"new_password": "string (required, min=8)"
}
POST /platform/auth/login
{ "email": "string (required)", "password": "string (required)" }
POST /stores/:store_id/auth/pin-login
{ "pin": "string (required)" }
Invites
POST /invites/validate
{ "token": "string (required)" }
POST /invites/accept
{
"token": "string (required)",
"password": "string (required, min=8)",
"first_name": "string (required)",
"last_name": "string (required)"
}
POST /:scope/invites
{
"email": "string (required)",
"first_name": "string",
"last_name": "string",
"org_role": "string",
"store_role": "string",
"store_id": "uuid"
}
Platform
POST /platform/orgs
{ "name": "string (required)", "slug": "string (required)" }
PUT /platform/orgs/:id
{ "name": "string (required)", "slug": "string (required)", "active": "bool" }
POST /platform/users
{
"email": "string (required)",
"password": "string (required, min=8)",
"first_name": "string (required)",
"last_name": "string (required)",
"role": "string (required)"
}
POST /platform/impersonate
{ "org_id": "uuid (required)", "store_id": "uuid (required)" }
Members
POST /orgs/:org_id/members
{
"user_id": "uuid (required)",
"role": "org_owner|org_admin|org_member (required)"
}
POST /stores/:store_id/members
{
"user_id": "uuid (required)",
"role": "store_admin|manager|cashier|stocker (required)",
"clearances": "int"
}
Products
POST/PUT /stores/:store_id/products
{
"barcode": "string (required)",
"name": "string (required)",
"description": "string",
"price": "decimal (required)",
"cost": "decimal (required)",
"over_18": "bool",
"over_21": "bool",
"tax_rate": "decimal",
"stock": "int",
"product_type": "string (required)",
"active": "bool"
}
Inventory
POST /stores/:store_id/inventory/receive
{
"product_id": "uuid (required)",
"quantity": "int (required, >0)",
"notes": "string"
}
POST /stores/:store_id/inventory/adjust
{
"product_id": "uuid (required)",
"quantity": "int (required)",
"reason": "string (required)",
"notes": "string"
}
POST /stores/:store_id/inventory/transfer
{
"product_id": "uuid (required)",
"destination_store_id": "uuid (required)",
"quantity": "int (required, >0)",
"notes": "string"
}
Discounts
POST/PUT /stores/:store_id/discounts
{
"name": "string (required)",
"description": "string",
"start_date": "datetime (required)",
"end_date": "datetime (required)",
"product_id": "uuid",
"product_type": "string",
"discount_type": "percent|fixed (required)",
"amount": "decimal (required)",
"min_purchase": "decimal",
"max_discount": "decimal",
"active": "bool"
}
Returns
POST /stores/:store_id/returns
{
"customer_id": "uuid",
"product_id": "uuid (required)",
"transaction_id": "uuid",
"quantity": "int (required, >0)",
"refund_amount": "decimal (required)",
"reason": "string (required)",
"reason_notes": "string",
"restocked": "bool"
}
Customers
POST/PUT /orgs/:org_id/customers
{
"first_name": "string",
"last_name": "string",
"email": "string",
"phone": "string"
}
POST /orgs/:org_id/customers/:customer_id/points
{ "points": "int (required)" }
Categories
POST /orgs/:org_id/categories
{
"name": "string (required)",
"slug": "string (required)",
"parent_id": "uuid",
"sort_order": "int"
}
Suppliers
POST /orgs/:org_id/suppliers
{
"name": "string (required)",
"contact_email": "string",
"contact_phone": "string"
}
POST /orgs/:org_id/suppliers/:supplier_id/products
{
"supplier_id": "uuid (required)",
"supplier_sku": "string",
"cost": "decimal",
"is_preferred": "bool"
}
Serial Numbers
POST /orgs/:org_id/serial-numbers
{
"store_id": "uuid (required)",
"product_id": "uuid (required)",
"serial_number": "string (required)",
"notes": "string"
}
Promotions
POST /orgs/:org_id/promotions
{
"name": "string (required)",
"description": "string",
"promotion_type": "string (required)",
"buy_quantity": "int (required)",
"get_quantity": "int (required)",
"discount_value": "decimal",
"applies_to_all_stores": "bool",
"start_date": "datetime (required)",
"end_date": "datetime (required)",
"max_uses_per_transaction": "int",
"product_ids": "[uuid]",
"store_ids": "[uuid]"
}
Stock Transfers
POST /orgs/:org_id/stock-transfers
{
"from_store_id": "uuid (required)",
"to_store_id": "uuid (required)",
"notes": "string",
"items": [{ "product_id": "uuid (required)", "quantity": "int (required, >0)" }]
}
POST /orgs/:org_id/stock-transfers/:transfer_id/receive
{
"items": [{ "item_id": "uuid (required)", "received_qty": "int (required, >=0)" }]
}
Compliance
POST /stores/:store_id/compliance/verify-age
{
"product_id": "uuid (required)",
"check_type": "string (required)",
"id_type": "string",
"id_dob": "string",
"id_expiry": "string",
"verified_age": "int",
"required_age": "int (required)"
}
POST /stores/:store_id/compliance/override
{ "check_id": "uuid (required)", "reason": "string (required)" }
Notifications
POST /orgs/:org_id/notifications
{
"store_id": "uuid",
"type": "string (required)",
"title": "string (required)",
"message": "string (required)",
"metadata": "json"
}
Tax Configurations
POST /stores/:store_id/tax-configs
{
"name": "string (required)",
"rate": "decimal (required)",
"applies_to_category": "uuid",
"active": "bool"
}
Shifts
POST /stores/:store_id/shifts/preferences
{
"day_of_week": "int (0-6)",
"start_time": "string (required)",
"end_time": "string (required)",
"priority": "int"
}
POST /stores/:store_id/shifts/assigned
{
"user_id": "uuid (required)",
"shift_date": "string (required)",
"start_time": "string (required)",
"end_time": "string (required)",
"notes": "string"
}
POST /stores/:store_id/shifts/requests
{
"requested_date": "string (required)",
"start_time": "string (required)",
"end_time": "string (required)",
"notes": "string"
}
Settings
PUT /stores/:store_id/settings
{
"name": "string (required)",
"address_line1": "string",
"address_line2": "string",
"city": "string",
"state": "string",
"zip_code": "string",
"phone": "string",
"currency": "string (required)"
}
POST /stores/:store_id/terminals
{ "terminal_name": "string (required)", "is_active": "bool" }
Onboarding
PUT /stores/:store_id/onboarding/phase
{ "phase": "string (required)", "complete": "bool" }
Query
POST /stores/:store_id/query
{
"question": "string (required)",
"history": [{ "role": "string", "content": "string" }]
}
Status Service
The status service is an internal health-check aggregator. It has no authentication and is not exposed to any portal. It is used by uptime monitoring and ops dashboards.
Cloud Run service: pinpointpos-status
Port: 8080
Spring application name: myriad-status
GET /
Root health check. Returns the same response as GET /health.
GET /health
Detailed health check. Polls the Cloud Run Admin API for every other service and returns a combined status.
Authentication: None (internal only; restrict via Cloud Run ingress or Cloud Armor).
Response (200):
{
"success": true,
"data": {
"status": "healthy",
"services": {
"merchant-api": "healthy",
"management-api": "healthy",
"terminal-api": "healthy",
"terminal-onboarding": "healthy",
"tx-bundler": "healthy"
}
}
}
status values: healthy (all services healthy) or degraded (one or
more services unhealthy or unreachable).
Per-service status values: healthy or unhealthy.
When GOOGLE_CLOUD_PROJECT is not set, health checks are skipped:
{
"success": true,
"data": {
"status": "healthy",
"checks": "skipped",
"reason": "GOOGLE_CLOUD_PROJECT is not configured"
}
}
Internal: CloudRunHealthService
Monitors all other Cloud Run services by calling the Cloud Run Admin API
(GET /v2/projects/{project}/locations/{region}/services/{service}).
Monitored services:
pinpointpos-merchant-apipinpointpos-management-apipinpointpos-terminal-apipinpointpos-terminal-onboardingpinpointpos-tx-bundler
A service is considered healthy when its latestReadyRevision is non-empty or
its terminalCondition.state is CONDITION_SUCCEEDED. All other states
(including API errors and timeouts) are reported as unhealthy.
Connection timeout: 3 seconds. Request timeout: 5 seconds.
Endpoint Count Summary
| Scope | Count |
|---|---|
| Public (no auth) | 6 |
| Authenticated (user) | 3 |
| Platform (admin) | 13 |
| Organization-scoped | 55 |
| Store-scoped | 93 |
| Total | 170 |