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. |
payments[] | 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 lists each tender of a sale in payments, which it sends only when the request includes with_payments=all. Both the transaction list request and the single-transaction request include it. Each tender is kept in Payments[] with the amount it paid. The tender that paid the most is also kept in PaymentMethod for lists and filters. Each tender is read in this order, and the first rule that applies wins:
- Cash: a method whose name contains 現金 (cash) is
Cash, unless the name also contains 券 (voucher). 現金券 and 現金商品券 are vouchers. - Vouchers: a tender with Smaregi's 有価証券 flag (
paymentSecuritiesFlag) keeps its own name, such as 商品券 or QUOカード. - Payment code (支払金種コード): when Smaregi sends a
denominationCode, the code decides. CREDIT, STORE, UNIONPAY and CONTACTLESS areCreditCard. SUICA, ID, QUICPAY, WAON, NANACO and the other e-money codes areIC. PAYPAY, AUPAY, LINEPAY, DPAY, RAKUTENPAY and the other wallet codes areQR. DEBIT, JDEBIT, PREPAID, QUOPAY and any other code keep Smaregi's name for it, for example デビット. A coded tender is named by Smaregi's name for the code, not by the name of the app or terminal. - The store's own name: otherwise the name is matched against lists of e-money, wallet and card brands. Debit, prepaid, vouchers, points and house cards are not read as credit cards.
- creditTotal: a tender that no rule above can read becomes
CreditCardif the card money Smaregi reports increditTotalaccounts for it. Otherwise it keeps the store's name.
The header's cashTotal and creditTotal add only cash or card money that no listed tender accounts for, so the same money is never counted twice. If the sale's only cash tender arrives with neither the amount received nor the change, both are taken from the header (depositCash and change), so the receipt still shows お預り and お釣り. A QR or e-money tender keeps its wallet name in Brand, so the receipt prints "お支払い(QRコード決済・PayPay)" or "お支払い(電子マネー・Suica)". Store screens show only the category. PaymentMethod is Other only when the sale has no tender at all. A tender kept under the store's own name, such as 商品券, still matches the Other payment filter.
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)
-
Matching Smaregi and Square Sales to CustomersHow Smaregi and Square sales are matched to your ReceiptRoller customers. Member and customer information is not synced with the POS; matched sales update the customer's purchase history and visit count.
-
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.