Smaregi Transaction Data and Receipt Roller Transaction Data Mapping
Receipt Roller connects to multiple POS vendors, including Smaregi. So that transactions imported from any vendor can be handled internally through a common transaction data model (PosTransactionDto), vendor-specific fields are normalized. This article gives a technical explanation of how transaction data from the Smaregi Platform API corresponds to Receipt Roller's internal model.
This article is reference material for developers and operations staff who want to understand the internal specification of the POS integration. For the day-to-day setup steps, see Smaregi POS integration setup. For the canonical field-level model specification, see PosTransactionDto specification (field reference).
Hierarchical structure correspondence
The Smaregi Platform API has four layers: contract, store, terminal, and transaction. On the Receipt Roller side, these correspond one-to-one, by design, to four layers: business account, store, POS terminal, and transaction.
- Contract (contractId) ↔ Receipt Roller's business account. When you install the "Receipt Roller Link" app on Smaregi, that contract is tied to a single Receipt Roller business account (
SmaregiContract.OrganizationId). - Smaregi store (storeId) ↔ Receipt Roller store. Tied to the Receipt Roller-side POS terminal via
PosTerminal.SmaregiStoreId. - Smaregi terminal (terminalId) ↔ Receipt Roller's POS terminal. Held in
PosTerminal.SmaregiTerminalId; one Receipt Roller POS terminal corresponds to one Smaregi terminal (register). - Transaction (transactionHeadId) ↔ Receipt Roller's transaction. The same ID is saved as both
PosTransaction.TransactionIdandExternalTransactionId.
Transaction header field mapping
The correspondence between the response from Smaregi's /pos/transactions (SmaregiTransaction) and Receipt Roller's PosTransactionDto.
| Smaregi | Receipt Roller | Notes |
|---|---|---|
transactionHeadId | TransactionId / ExternalTransactionId | The same value is saved into two fields. Becomes the idempotent upsert key. |
transactionDateTime | TransactionDateTime | The JST string is converted to UTC before saving. |
| (currency) | Currency | Kept fixed as JPY. |
storeId | (not stored directly) | Already saved as PosTerminal.SmaregiStoreId at connection time. On the transaction side, replaced with PosTerminal.StoreId (the Receipt Roller store ID). |
terminalId | (not stored directly) | Already saved as PosTerminal.SmaregiTerminalId at connection time. On the transaction side, replaced with PosTerminal.TerminalId (the Receipt Roller terminal ID). |
customerId / customerCode | ExternalIds.ProviderCustomerId (and passed to CRM resolution) | Passed to the CRM resolution logic as a customer match key (described below), and also kept on the transaction as a cross-vendor ID. |
staffId | StaffId | Carried over as-is. |
staffName | StaffName | If blank, backfilled by fetching from /pos/staffs/{staffId}. |
total | TotalAmount | Since Smaregi also returns numbers as strings, parsed with decimal.TryParse. |
subtotal | SubtotalAmount | If 0, computed from total - tax. |
tax | TaxAmount | Same string-parsing as above. |
discount | DiscountAmount | Same as above. |
status / cancelDivision | Status | See the status conversion table below. |
receiptNumber / terminalTransactionId | ReceiptNumber | The receipt number issued by the terminal. |
paymentMethods[] | Payments[] / PaymentMethod | Each tender is fully preserved in Payments[] (supports split payments). PaymentMethod holds the primary method (described below). |
Status code conversion
Smaregi's status values are returned as numeric strings. Receipt Roller normalizes these into string labels internally.
| Smaregi value | Meaning | Receipt Roller Status |
|---|---|---|
"1" | Completed | Completed |
"2" | Canceled | Voided |
"3" | Refunded | Refunded |
| Unknown value / blank | — | Pending (fallback) |
Depending on the specification, there are cases where status and cancelDivision are used together in a field name. Both values are checked for the determination, so as long as either one is present, classification is done correctly.
Payment method normalization
Smaregi's paymentMethods is returned as an array, with each element containing a payment method name and an amount (multiple elements for split payments). Receipt Roller keeps every tender in Payments[], and additionally keeps a single "primary payment method" in PaymentMethod for backward compatibility. The primary method is chosen as the element with the largest amount from the array, and its Japanese label is normalized into an internal code.
| Smaregi label | Receipt Roller internal code |
|---|---|
| Contains "cash" (現金) | Cash |
| Contains "credit" (クレジット) | CreditCard |
| Contains "QR" | QR |
| Contains "e-money" (電子マネー) or "IC" | IC |
| Array is blank / not applicable | Other |
Smaregi's transaction list API sometimes does not include the payment method, in which case it is backfilled from a separate endpoint. For the latest implementation status, refer to the source code (SmaregiTransactionMapper).
Line item mapping
Separately from the transaction header, line item data is fetched from /pos/transactions/{id}/details, converted into an array of PosTransactionLineItemDto, and serialized into LineItemsJson.
Smaregi SmaregiTransactionDetail | Receipt Roller PosTransactionLineItemDto | Notes |
|---|---|---|
productName | ProductName | Carried over as-is. |
quantity | Quantity | String rounded to an integer. Values of 0 or less are corrected to 1. |
price | UnitPrice | String parsed. |
subtotal | Subtotal | String parsed. |
taxRate | TaxRate | String parsed. |
tax | TaxAmount | Tax amount at the line-item level. Kept as an amount, not just a rate. |
productId | CatalogObjectId / ProductId | The catalog ID for cross-system linking. |
categoryName | Category | Carried over as-is. |
ItemCount (the total number of purchased items across the whole transaction) is calculated as the sum of Quantity across line items.
Line-item-level discount amounts are planned to be mapped once the corresponding field name in Smaregi's transactionDetails has been confirmed. Until then, DiscountAmount is left as null, and the raw payload (RawJson) is retained to prevent data loss.
Retaining the raw data (RawJson)
At import time, the source raw payload of the transaction header plus line items is saved into RawJson. This is a safety measure for internal server use, so that even fields that haven't been modeled yet can be recovered later (it is not returned by the API).
Resolving customer information (CRM integration)
The customerId / customerCode obtained from Smaregi are passed to the CRM resolution service (IPosCustomerMatchService) as a customer match key, and are also kept on the transaction as the cross-vendor ID ExternalIds.ProviderCustomerId. If a match is found, the transaction is automatically linked to the corresponding Receipt Roller CRM customer profile, and used for calculating per-customer purchase history and churn-risk scores.
The main types of match keys are as follows (see the implementation's PosCustomerMatchDto).
- Membership number (membership code) — Smaregi's
customerCode, etc. - External customer ID — Smaregi's
customerId - Email address / phone number — only when obtainable from Smaregi
Transactions where no match is found can still be linked later by the customer themselves via an in-store terminal QR scan.
Backfilling staff information
There are cases where the transaction header contains only staffId. In that case, /pos/staffs/{staffId} is called separately to fetch displayName, which is saved into StaffName. Even if fetching the staff name fails, the transaction import itself is not treated as a failure — it is saved with a blank name (to prevent loss of transaction data).
Distinguishing the acquisition path (Source)
Even for the same transaction, the Source field records which path it was imported through.
Webhook— a path pushed in real time from SmaregiSync— a manual sync path triggered when a store operator presses the "Sync with Smaregi" buttonAPI— acquisition via other Platform API calls (e.g. instant fetch at QR scan time)
Even if the same transactionHeadId arrives via multiple paths, the transaction is never duplicated, since it is upserted keyed on that same ID. The Source value reflects the most recently imported path.
Timezone handling
The Smaregi Platform API returns date-times in ISO 8601 format in JST (+09:00). The Receipt Roller side always saves everything in UTC, converting to JST for display. When sending a date-time filter to the Platform API as well, UTC is converted to JST and URL-encoded before sending (so that the + sign in +09:00 is not misinterpreted as a space).
Idempotency
The transaction upsert is keyed on transactionHeadId. Even if the same transaction arrives via both a webhook and a manual sync, it ends up consolidated into a single record. UpdatedAt is updated to the most recent import time, but TransactionDateTime (the time the transaction occurred) remains unchanged.
Overview of the import pipeline
- A transaction occurs on the Smaregi side → a webhook is sent from Smaregi Platform to Receipt Roller
- Receipt Roller's webhook receiving endpoint performs custom header authentication
transactionHeadIds(there can be multiple) are extracted from the payload- For each ID, the transaction header + line items + staff are fetched from the Platform API
- Converted into
PosTransactionDtobySmaregiTransactionMapper - The customer match key is passed to
IPosCustomerMatchService, and CRM resolution is performed - Saved via
PosTransactionService.UpsertAsync(duplicates are overwritten) PosTerminal.LastTransactionAtis updated (used for displaying the latest transaction via QR scan)- If the customer has been identified, handed off to the automated delivery service (electronic receipt delivery)
Related articles
- PosTransactionDto specification (field reference) — detailed specification of each field
- Square transaction data mapping — the Square version
- Smaregi POS integration setup — connection steps
- POS integration overview
- Square POS integration setup
- Two-way membership data sync with Smaregi / Square
- Per-customer purchase history (POS integration)
-
Two-Way Member Information Sync with Smaregi/SquareLearn how ReceiptRoller's member information syncs bidirectionally with connected POS systems like Smaregi and Square. Covers which fields sync, sync timing, conflict priority rules, new customer matching, supported POS systems, and troubleshooting.
-
How Digital Receipts WorkAn explanation of how ReceiptRoller's digital receipts work, and how to set up POS integration with Square and Smaregi.
-
Smaregi x ReceiptRoller — Digital Receipts, Customer Management, and Sales Analysis in One AppLearn how ReceiptRoller Link connects with Smaregi checkouts to unify automatic digital receipt issuance, member management, sales analysis with AI advice, Apple/Google Wallet membership cards, SNS integration, and flyer distribution. Install "ReceiptRoller Link" from the Smaregi App Marketplace to get started today with no complicated API setup required.
-
Smaregi Product Data and Receipt Roller Product Data MappingExplains how Smaregi's product master is converted into Receipt Roller's product master (ProductDto), field by field. Covers the correspondence for product code, product name, category, price, and cost, along with quirks specific to Smaregi.
-
Smaregi Staff Data and Receipt Roller Staff Data MappingExplains how Smaregi staff master data is converted into Receipt Roller's staff data (StaffDto), field by field. Covers the name-splitting logic for staffName, the staffCode to EmployeeNumber mapping, and how displayFlag controls skipping of hidden staff.