Smaregi Transaction Data and Receipt Roller Transaction Data Mapping

Smaregi POS Integration Data Mapping Technical Details Transaction Data API

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.TransactionId and ExternalTransactionId.

Transaction header field mapping

The correspondence between the response from Smaregi's /pos/transactions (SmaregiTransaction) and Receipt Roller's PosTransactionDto.

Smaregi Receipt Roller Notes
transactionHeadIdTransactionId / ExternalTransactionIdThe same value is saved into two fields. Becomes the idempotent upsert key.
transactionDateTimeTransactionDateTimeThe JST string is converted to UTC before saving.
(currency)CurrencyKept 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 / customerCodeExternalIds.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.
staffIdStaffIdCarried over as-is.
staffNameStaffNameIf blank, backfilled by fetching from /pos/staffs/{staffId}.
totalTotalAmountSince Smaregi also returns numbers as strings, parsed with decimal.TryParse.
subtotalSubtotalAmountIf 0, computed from total - tax.
taxTaxAmountSame string-parsing as above.
discountDiscountAmountSame as above.
status / cancelDivisionStatusSee the status conversion table below.
receiptNumber / terminalTransactionIdReceiptNumberThe receipt number issued by the terminal.
paymentMethods[]Payments[] / PaymentMethodEach 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 valueMeaningReceipt Roller Status
"1"CompletedCompleted
"2"CanceledVoided
"3"RefundedRefunded
Unknown value / blankPending (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 labelReceipt Roller internal code
Contains "cash" (現金)Cash
Contains "credit" (クレジット)CreditCard
Contains "QR"QR
Contains "e-money" (電子マネー) or "IC"IC
Array is blank / not applicableOther

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 SmaregiTransactionDetailReceipt Roller PosTransactionLineItemDtoNotes
productNameProductNameCarried over as-is.
quantityQuantityString rounded to an integer. Values of 0 or less are corrected to 1.
priceUnitPriceString parsed.
subtotalSubtotalString parsed.
taxRateTaxRateString parsed.
taxTaxAmountTax amount at the line-item level. Kept as an amount, not just a rate.
productIdCatalogObjectId / ProductIdThe catalog ID for cross-system linking.
categoryNameCategoryCarried 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 Smaregi
  • Sync — a manual sync path triggered when a store operator presses the "Sync with Smaregi" button
  • API — 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

  1. A transaction occurs on the Smaregi side → a webhook is sent from Smaregi Platform to Receipt Roller
  2. Receipt Roller's webhook receiving endpoint performs custom header authentication
  3. transactionHeadIds (there can be multiple) are extracted from the payload
  4. For each ID, the transaction header + line items + staff are fetched from the Platform API
  5. Converted into PosTransactionDto by SmaregiTransactionMapper
  6. The customer match key is passed to IPosCustomerMatchService, and CRM resolution is performed
  7. Saved via PosTransactionService.UpsertAsync (duplicates are overwritten)
  8. PosTerminal.LastTransactionAt is updated (used for displaying the latest transaction via QR scan)
  9. If the customer has been identified, handed off to the automated delivery service (electronic receipt delivery)

Related articles

Published: 2026-05-28 Updated: 2026-07-02
Related articles