{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":[]},"redocly_category":"Guides","product":"Identity Management","type":"markdown"},"seo":{"title":"Offline transaction signing verification","description":"Everything about Mosaic Journeys, SDKs, and APIs","siteUrl":"https://developer.transmitsecurity.com/"},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"offline-transaction-signing-verification","__idx":0},"children":["Offline transaction signing verification"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Organizations that use transaction signing for high-value payments or trades may need to retain independently verifiable evidence of each approval. For example, a financial institution can store the signing artifacts with its transaction record and use them to review a disputed transaction or support an audit."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Offline verification for transaction signing"]}," provides the artifacts required to verify that an approval corresponds to the transaction details presented to the customer. You can retain these artifacts in your own systems and verify them outside Mosaic."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"api-based-approach","__idx":1},"children":["API-based approach"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For Passkeys and Mobile Biometrics in transaction-signing flows, include ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["approval_data"]}," when you start the flow. This object contains the transaction details that the customer reviews and approves. After a successful transaction approval, the final authentication response returns signing artifacts."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For TOTP, the transaction ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["start"]}," response returns ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["approval_data"]}," and the transaction challenge. The final ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["authenticate"]}," response returns ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["authenticator_id"]},", but does not return signing artifacts."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Use the following APIs to complete API-based transaction-signing flows:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Passkeys"]},": ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/openapi/user/backend-webauthn.openapi/other/authenticatewebauthncredential"},"children":["Authenticate WebAuthn API"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Mobile Biometrics"]},": call Create Mobile Biometrics Challenge, then Authenticate with Mobile Biometrics. See the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/openapi/user/backend-mobile-biometrics.openapi"},"children":["Mobile Biometrics API reference"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["TOTP"]},": call Start a Transaction Signing Flow with TOTP, then Authenticate Transaction Signing TOTP. See the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/openapi/user/backend-totp.openapi"},"children":["TOTP API reference"]},"."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"journey-based-approach","__idx":2},"children":["Journey-based approach"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For journeys, add the transaction-signing step for ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/guides/orchestration/journeys/transaction_signing_mobile_biometrics"},"children":["Mobile Biometrics"]},", ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/guides/orchestration/journeys/transaction_signing_mobile_pin"},"children":["Mobile PIN"]},", ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/guides/orchestration/journeys/transaction_signing_webauthn"},"children":["Passkeys"]},", or ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/guides/orchestration/journeys/transaction_signing_totp"},"children":["TOTP"]},", and configure its output variable. After a successful transaction approval, the output variable contains the transaction-signing result."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For Web to Mobile, use the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/guides/orchestration/journeys/transaction_signing_mobile_approve"},"children":["Web to Mobile Transaction Signing"]}," step and implement the required web and mobile Orchestration SDK calls as described in the transaction-signing sections of ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/guides/user/auth_web_to_mobile#transaction-signing"},"children":["Login with Push"]}," or ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/guides/user/auth_web_to_mobile_otp#transaction-signing"},"children":["Login with Push using Web OTP"]},". The web journey output includes signing artifacts from the mobile approval. You can view the output in ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/guides/orchestration/getting-started/journey_analytics"},"children":["Journey Analytics"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The following sections describe the verification data available for each authenticator."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"signing_artifacts-data","__idx":3},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["signing_artifacts"]}," data"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The fields in ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["signing_artifacts"]}," depend on the authenticator used to approve the transaction. Unless stated otherwise, the payloads below are returned both in the final API response and in the result stored in the configured journey output variable. In API responses, ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["authenticator_id"]}," is a top-level field alongside ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["signing_artifacts"]},". In journeys, both are included in the transaction-signing step result."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"passkeys","__idx":4},"children":["Passkeys"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For Passkeys, this is the payload returned by both the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/openapi/user/backend-webauthn.openapi/other/authenticatewebauthncredential"},"children":["Authenticate WebAuthn API"]}," and by ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/guides/orchestration/journeys/transaction_signing_webauthn"},"children":["Transaction Signing with Passkeys"]}," step. It contains the WebAuthn data required to retain and verify the approval."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"signing_artifacts\": {\n    \"approval_data\": \"<APPROVAL_DATA>\",\n    \"public_key\": \"<PUBLIC_KEY>\",\n    \"signature\": \"<SIGNATURE>\",\n    \"credential_id\": \"<CREDENTIAL_ID>\",\n    \"webauthn_session_id\": \"<WEBAUTHN_SESSION_ID>\",\n    \"authenticator_data\": \"<AUTHENTICATOR_DATA>\",\n    \"client_data_json\": \"<CLIENT_DATA_JSON>\",\n    \"raw_challenge\": \"<RAW_CHALLENGE>\"\n  }\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["authenticator_data"]}," contains data asserted by the passkey authenticator, including the relying party ID hash and whether the user was verified. ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client_data_json"]}," contains the browser context, including the request type, origin, and challenge."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To verify the signature, base64-decode ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["authenticator_data"]},", calculate the SHA-256 hash of the base64-decoded ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client_data_json"]},", concatenate those two values, and verify the resulting data against ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["signature"]}," using ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["public_key"]},". To confirm that the approval data is bound to the signature, use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["raw_challenge"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["approval_data"]}," to calculate the expected challenge, then compare it with the challenge in ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client_data_json"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The transaction-signing result includes an ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["authenticator_id"]}," field, which identifies the passkey used for the approval:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["In API-based flows, it is a top-level field alongside ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["signing_artifacts"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["In journeys, it is included in the transaction-signing step result"]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"mobile-biometrics-and-mobile-pin","__idx":5},"children":["Mobile Biometrics and Mobile PIN"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For Mobile Biometrics, this payload is returned by the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/openapi/user/backend-mobile-biometrics.openapi/other/authenticatenativemobilebiometrics"},"children":["Authenticate with Mobile Biometrics API"]}," and by ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/guides/orchestration/journeys/transaction_signing_mobile_biometrics"},"children":["Transaction Signing with Mobile Biometrics"]},". For Mobile PIN, it is returned by ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/guides/orchestration/journeys/transaction_signing_mobile_pin"},"children":["Transaction Signing with Mobile PIN"]},". It contains the approved transaction data, challenge, signature, public key, and signing algorithm."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"signing_artifacts\": {\n    \"approval_data\": \"<APPROVAL_DATA>\",\n    \"signature\": \"<SIGNATURE>\",\n    \"public_key\": \"<PUBLIC_KEY>\",\n    \"algorithm\": {\n      \"name\": \"ecdsa\",\n      \"namedCurve\": \"P-256\",\n      \"hash\": \"sha-256\"\n    }\n  }\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["algorithm"]}," specifies how to verify the signature. Depending on the algorithm, it includes either ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["namedCurve"]}," for ECDSA or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["saltLength"]}," for RSA-PSS, as well as the hash algorithm. For example, an RSA-PSS algorithm is returned as ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["{ \"name\": \"rsa-pss\", \"hash\": \"sha-256\", \"saltLength\": 32 }"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The transaction-signing result includes an ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["authenticator_id"]}," field, which identifies the Mobile Biometrics or Mobile PIN authenticator used for the approval:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["In API-based flows, it is a top-level field alongside ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["signing_artifacts"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["In journeys, it is included in the transaction-signing step result."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"totp","__idx":6},"children":["TOTP"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/guides/orchestration/journeys/transaction_signing_totp"},"children":["Transaction Signing with TOTP"]}," and the Authenticate Transaction Signing TOTP API do not return ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["signing_artifacts"]}," and cannot be independently verified cryptographically offline."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The transaction-signing result includes an ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["authenticator_id"]}," field, which identifies the TOTP authenticator used for the approval:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["In API-based flows, it is a top-level field in the final response"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["In journeys, it is included in the transaction-signing step result"]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"web-to-mobile","__idx":7},"children":["Web to Mobile"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["When you use ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/guides/orchestration/journeys/transaction_signing_mobile_approve"},"children":["Web to Mobile Transaction Signing"]},", the web journey output includes the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["signing_artifacts"]}," generated on the mobile device. Its fields match the authenticator used to approve the transaction. The output also includes ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["authenticator_id"]},", separately from ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["signing_artifacts"]},", which identifies the authenticator used for the approval. If it was provided during authentication, ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["device_id"]}," is returned separately alongside ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["signing_artifacts"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"example-retain-and-verify-an-approval","__idx":8},"children":["Example: retain and verify an approval"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Store the signing data with your own transaction record and the user identifier used by your application. The data required depends on the authenticator:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["For Passkeys, store ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["approval_data"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["authenticator_data"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client_data_json"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["raw_challenge"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["public_key"]},", and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["signature"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["For Mobile Biometrics and Mobile PIN, store the complete ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["signing_artifacts"]}," object."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For example, when reviewing a disputed payment:"]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Retrieve the stored transaction record and signing data."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Verify the signature using the relevant public key and verification data."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Confirm that the approval data matches the transaction record. For Passkeys, also confirm that the challenge in ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client_data_json"]}," corresponds to the stored ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["approval_data"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["raw_challenge"]},"."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A valid signature and matching approval data provide evidence that the transaction was approved with the associated authenticator."]}]},"headings":[{"value":"Offline transaction signing verification","id":"offline-transaction-signing-verification","depth":1},{"value":"API-based approach","id":"api-based-approach","depth":2},{"value":"Journey-based approach","id":"journey-based-approach","depth":2},{"value":"signing_artifacts data","id":"signing_artifacts-data","depth":2},{"value":"Passkeys","id":"passkeys","depth":3},{"value":"Mobile Biometrics and Mobile PIN","id":"mobile-biometrics-and-mobile-pin","depth":3},{"value":"TOTP","id":"totp","depth":3},{"value":"Web to Mobile","id":"web-to-mobile","depth":3},{"value":"Example: retain and verify an approval","id":"example-retain-and-verify-an-approval","depth":2}],"frontmatter":{"seo":{"title":"Offline transaction signing verification"}},"lastModified":"2026-09-01T08:25:01.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/guides/user/transaction_signing_offline_verification","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}