Changelog

All the latest updates, improvements, and fixes to Decal

Checkout Sessions API, Manually Adding Wallets & More

Developer API: Checkout Sessions & Orders

The Checkout Sessions API and Orders API are now available to merchants in closed-beta.

Checkout Sessions let you create a hosted payment page with a single API call. Pass your order details, get back a URL, and redirect your customer. Decal handles the checkout UI, payment collection, and order tracking.

curl -X POST https://api.usedecal.com/v0/checkout/sessions \
  -H "Authorization: Bearer sk_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [{ "name": "Cold Brew", "quantity": 1, "unitPrice": 550 }],
    "successUrl": "https://yoursite.com/confirmed?session={SESSION_ID}"
  }'

The response includes a url to redirect your customer to and the full order object so you have the order ID handy for confirmation.

Orders can also be managed independently — create, retrieve, update, or cancel orders directly without going through a checkout session. Useful for POS integrations or anywhere you're managing order state server-side.

Both APIs:

  • Support taxes and discounts (fixed and percentage)
  • Accept a customer object that will find-or-create a customer record, with externalId support for mapping to your own customer IDs
  • Use test/live mode automatically based on your API key (sk_test_ vs sk_live_)

Webhooks

Checkout sessions now fire a checkout.session.completed webhook to your callbackUrl after a successful payment — before the customer is redirected to your successUrl. This means your server knows about the payment before the customer lands on your confirmation page, eliminating the need to poll for payment status.

Both successUrl and callbackUrl support a {SESSION_ID} placeholder template that gets replaced with the actual session ID at creation time, so you don't need to store the mapping yourself:

{
  "callbackUrl": "https://yoursite.com/webhooks/decal?session={SESSION_ID}"
}

Manual Settlement Wallets

You can now add a settlement wallet by pasting a Solana address directly, without connecting a browser extension. This enables wallet types that can't go through the standard signature flow:

  • Multisig wallets (Squads) — add a program-owned address directly
  • Cold storage (Ledger, Keystone, etc) — no need to plug in
  • Any externally managed address

Manually added wallets are tagged with a Manual badge in your wallet list, and adding one requires a confirmation checkbox since funds sent to a wrong address can't be recovered.

Manually add a Settlement Wallet

Payment Destination Override

When creating an order or checkout session via the API, you can now specify exactly which settlement wallet receives the funds — overriding the default wallet resolution for that transaction:

{
  "items": [{ "name": "Catering Package", "quantity": 1, "unitPrice": 25000 }],
  "paymentDestination": "sw_live_abc1234567890"
}

Accepts either a typed wallet ID (sw_live_...) or a raw Solana address from your verified wallets.

Stored Value Improvements

A few quality of life improvements for Stored Value programs:

  • No settlement wallet required to activate — the activation checklist is now two steps (balance name + launch). The settlement wallet step was a leftover requirement that didn't actually affect how stored value payments route, so it's gone.
  • Default bonus values — new programs now come pre-filled with bonus configurations ($5 bonus on $25+ first load, $5 bonus on $50+ recurring loads) so you're not starting from a blank slate.
  • Better bonus display — when a top-up added to a checkout qualifies for a bonus, the bonus details appear inline before the customer pays. The balance page now shows the correct bonus type automatically (signup vs topup) without being anchored to a preset amount.
  • Smarter low-balance messaging — first-time customers no longer see a misleading "Low balance" warning. Instead they see a first-topup incentive. Returning customers with a low balance continue to see the existing reload nudge.

Embedded Authentication

Customer authentication now uses inline embedded flows instead of pop-up windows. New users enter their OTP code directly in the app, and returning users authenticate via an embedded iframe. Popups are only used as a fallback for passkey (WebAuthn) auth, with automatic popup blocker detection and Safari-specific recovery instructions.

Minor

  • Stablecoin payment setup streamlined — enabling a stablecoin payment method is now a single click. The prior flow opened a wallet selection dialog linked to the payment method; that's gone. Payment routing now resolves via orchestration wallets at payment time.
  • Better card payment errors — user-actionable Coinflow errors (invalid zip, declined card) are now shown directly to customers instead of a generic failure message.
Read more →

Finances Dashboard & Stored Value Bonuses

Finances Dashboard

The merchant dashboard now has a dedicated Finances section, consolidating everything related to your money in one place. The new section includes:

  • Payouts — Initiate stablecoin transfers from your Decal-managed wallet to your settlement wallet, with real-time balance visibility.
  • Pay-ins — Coming soon.
  • Accounts — Manage your settlement wallets. Bank accounts coming soon.

Settlement wallet management and payouts have moved out of Settings into this new section. Existing bookmarks and links redirect automatically.

Stored Value Bonuses

Merchants can now configure sign-up bonuses and top-up bonuses for their Stored Value program. Both support fixed-amount or percentage-based bonus credits with tiered spend thresholds — for example, "Load $50, get $5 free" or "Load $100, get 15% bonus."

Sign-up bonuses are claimable once per customer. For top-ups, only one bonus tier applies per transaction. Configure both from the Top-Ups tab in your Stored Value program settings.

Non-members and unauthenticated customers now see a signup bonus teaser when viewing a merchant's balance page or the balance top-up addon at checkout. The teaser shows the lowest-threshold bonus tier (e.g. "New member bonus — top up $25 or more to get +$5 free"), giving customers an incentive to join before they reach the amount selection step.

Custom Onboarding Messaging

Stored Value programs now support customizable onboarding content that customers see when signing up. In the dashboard under General > Customer Messaging, merchants can set:

  • A headline shown on the balance page and sign-up sheet (defaults to "Join the {program name} program").
  • A subheadline for a short marketing statement.
  • Up to 6 benefit bullet points highlighting why customers should join.

This gives merchants full control over the first impression their Stored Value program makes.

The Stored Value settings page now also includes a branded phone mock preview, showing a live preview of the customer-facing onboarding screen in merchant brand colors as they edit.

Minor Improvements

  • Organization avatars now display as rounded squares instead of circles, making them visually distinct from user and team member avatars throughout the dashboard.
  • Checkout pages load faster thanks to cached merchant location data, reducing unnecessary database round-trips on repeat visits.
Read more →

Checkout Top-Ups & Stored Value Configuration

Checkout Top-Ups for New Customers

Customers who aren't signed in or enrolled in a merchant's Stored Value program can now tap the balance top-up addon at checkout to sign up and add a top-up in a single inline flow — no navigation away from the order required.

When a customer opens the Stored Value payment sheet with zero or insufficient balance, they now see a contextual top-up amount grid instead of a disabled button. After signing in or completing onboarding, they're correctly registered as a merchant customer and can proceed immediately.

Stored Value Top-Up Configuration

Merchants can now configure custom top-up preset amounts and a low-balance reload reminder for their Stored Value programs. Settings are available in the dashboard under the new Top-Ups tab. The checkout page and balance page respect these settings; programs without custom configuration continue to use platform defaults.

Merchant Branding Fixes

Several branding color issues have been resolved:

  • Merchants using "single" color mode now correctly see their configured scheme regardless of the visitor's OS dark mode preference — previously, the platform's default dark palette bled through for unconfigured color variables.
  • The branding system now derives and emits all CSS variables used by UI components, eliminating color mismatches caused by variables falling back to dark-mode defaults.
  • The branding editor's phone mock preview now reflects custom colors in real time.
  • Advanced color overrides (primary button text, secondary button text, card background, card text, muted text, input background) are now editable under an "Advanced Colors" toggle.

Minor Improvements

  • Guest customers and unenrolled customers are now protected from inadvertently purchasing balance top-ups at checkout. If a guest attempts to pay an order containing a top-up line item, the item is automatically removed and the customer is shown an updated order.
  • Added checkout auth token for the crypto wallet deep-link wallet flow, preserving top-up items when customers open external wallet apps like Phantom or Solflare.
Read more →

Order Management & Square Integration Settings

Order Management

The merchant dashboard now includes full order management pages. The order listing page supports pagination and filtering by status, payment status, and search by order ID or customer name. Each order detail page shows line items, a financial breakdown, customer info, and timestamps.

Merchants can void open, unpaid orders directly from the dashboard — cancellation propagates to external POS systems like Square automatically. A stale order detection system alerts merchants when Square locations have lingering open orders, with a bulk void option to clean them up.

Square Integration Settings

The Square integration page now includes a settings panel with toggles for:

  • Location sync — A weekly cron job syncs Square locations, creating new ones, updating metadata, preserving merchant-customized names, and deactivating removed locations. A "Sync now" button is available for on-demand syncing.
  • Customer sync — A daily two-way sync between Decal and Square. Inbound creates or updates Decal customers from Square; outbound pushes new Decal customers to Square. Conflicts resolve via most-recent-update-wins with email-based matching for initial linking.
  • Stale order auto-cancellation — Automatically cancels stale Square orders when enabled. Orders are upserted into Decal first for visibility, then cancelled on Square.

Card Billing Address Configuration

Merchants can now be configured to require either full billing address (address, city, state, zip, country) or minimal card details only for card payments. The checkout form conditionally renders address fields based on the merchant's configuration. Existing merchants default to full address.

Minor Improvements

  • Fixed a critical mode consistency bug where toggling between test and live mode kept the original customer record, allowing a live customer to join a test Stored Value program. Mode toggle now re-resolves the customer in the target mode, with defense-in-depth validation at the database level.
  • Square payments now include the Decal transaction ID as a reference for merchant cross-referencing, with deterministic idempotency keys for retry safety.
  • Fixed card checkout failing with "Order not found" on Square locations due to typed IDs being passed directly to the Square API.
  • Card payment error messages no longer leak internal configuration details — unknown errors now return a generic fallback message.
  • Fixed tax double-counting when adding a balance top-up to Square orders with additive taxes.
  • Cancelled orders no longer incorrectly trigger the "order details changed" dialog.
  • Empty orders now show a clear "Order Empty" status instead of a broken $0.00 receipt.
  • All open payment sheets close automatically when an order is completed or cancelled via polling.
Read more →

API Keys, Stale Order Protection & Stored Value Management

API Keys

Merchants now have a secure API key system for programmatic access. All keys scoped to your organization.

From the new API Keys settings page, you can create secret keys with an optional name, view existing keys with masked hints and a reveal toggle, see who created each key, and revoke active keys. Keys use the sk_ prefix and include your platform mode (test/live) for safety.

Stale Order Protection

Customers are now protected from paying stale order amounts. The checkout page polls for order changes every second and shows a full-screen dialog when a merchant modifies an order in Square while checkout is open. The dialog highlights exactly what changed — items added or removed and the new total. A server-side fingerprint check also blocks payment if the order data has changed since the customer last reviewed it.

Payment Method Management

Payment method detail pages are now generic and data-driven. Feature flags, setup actions, and settlement wallet management are driven by a single PaymentMethodDefinition config, eliminating method-specific branching. New payment methods work automatically once added to the definitions.

Each detail page now shows the current settlement wallet with a quick action to change it, or fall back to the organization default.

Stored Value Management

Stored Value management has been consolidated into a dedicated dashboard section. The setup wizard, activation checklist, and program editing now live under the Stored Value pages instead of being split across payment method settings.

Minor Improvements

  • OTP verification form now disables on success with a polished animation and redirect message.
Read more →

Card Payments, Integration Health & Para Authentication

Card Payments

Several card payment improvements shipped this week:

  • Fixed initialization hang — Card payment sessions no longer stall when opening the payment dialog.
  • 4-digit expiration year — Eliminates ambiguous 2-digit year handling that allowed invalid dates to pass validation.
  • Better error messages — User-actionable errors like invalid zip or declined card are now shown directly instead of a generic failure message.
  • Auto-resolved email — Authenticated customers no longer need to re-enter their email in the card form.
  • Hidden zero fees — The "$0.00 processing fee" text no longer appears when there is no fee.
  • Test mode fix — Stablecoin confirm and cancel operations no longer fail in test mode.

Integration Health Monitoring

Integration pages now surface connection health directly in the dashboard. Health badges show auth refresh failures, upcoming expirations, and expired auth tokens at a glance. Detail pages include alert banners with an actionable "Resync Now" button.

Behind the scenes, a daily cron job automatically refreshes expiring OAuth tokens with a 7-day lookahead window. Failed refreshes trigger admin alert emails. The system supports any OAuth integration type automatically.

Improved Customer Authentication

Sign-in now streamlines customer authentication into a single OTP prompt. Customers authenticate once and get both a customer session in a single flow. This fixes the previous scenarios that would require a customer to authenticate twice, reducing friction at login.

Balance Top-Ups

The balance top-up flow has been unified so the guest token experience reuses the same components as the authenticated flow. Card payments are now supported for balance top-ups in addition to stablecoins. Payment method selection is displayed inline and selecting a method immediately opens the payment sheet.

Minor Improvements

  • Session mode is now the single source of truth for all checkout and top-up actions, matching industry standard approaches. Mode is no longer derived from location integrations or passed from the client.
  • Checkout URLs simplified from loc_live_{id} to raw CUIDs, with backwards-compatible redirects for old URL formats, resulting in shorter URLs.
  • Dashboard revenue chart fixed for merchants in non-UTC timezones.
  • Square integration switched to production APIs for both test and live modes, with data isolation handled within the Decal dashboard.
  • Square resync now correctly updates OAuth tokens when the integration has an expired auth token.
  • Test mode banner is now a shared component across apps with improved scroll-hide behavior.
  • Failed top-up transactions can now be retried without creating duplicate records — the existing transaction resets from FAILED to INITIATED.
Read more →