Changelog

All the latest updates, improvements, and fixes to Decal

Webhook Visibility, Location Management & Friendlier Errors

Webhook Delivery Inspector

A new Webhooks view under Settings → Connections lets merchants see exactly what happened to every outgoing webhook. Filter by status and event type, drill into any individual delivery to view the request body, response body, headers, response code, and duration as code blocks, and read the error details for failed attempts (DNS lookup failed, HTTP error, request timed out, etc.) right at the top of the page.

Every webhook attempt is now persisted with full forensics, so a failure that happened overnight is still inspectable the next morning — no more guessing whether the endpoint was reachable.

Manual Locations

Locations no longer require a Square integration. A unified location form covers name, description, street address, phone, email, timezone, and recurring business hours, and works whether the location was created manually or imported from Square.

For merchants who do use Square, sync precedence is now snapshot-based: Square only overwrites a field if the merchant hasn't changed it since the last sync. Edit business hours, fix a typo in your address, or update a phone number directly in Decal without worrying that the next Square sync will clobber it.

Custom Sign-Up Bonus Messages

Merchants running Stored Value programs can now write their own first-top-up bonus message. The dashboard Sign-Up Bonus settings tab adds a formatting toolbar (bold, italic, center alignment), a 140-character counter, and a one-click Remove button to return to the default. The phone mock preview updates live as you type so you can see exactly what first-time top-up customers will see at checkout.

Friendlier API Errors

Errors returned from the API now carry through the actual reason instead of a generic "An unexpected error occurred" fallback. Auth flows in particular — invalid OTP, expired challenge, fingerprint mismatch, hourly refresh limit — now surface real messages to integrators and apps. The HTTP status code and error code contract is unchanged; only the user-facing message is more useful.

Minor Improvements

  • Square order-not-found shows the right page. Checkout sessions for missing Square orders now display the order-not-found message instead of a generic server error.
  • Payment page production crash fixed. Resolved a minor error that could surface on the payment page in production for some wallets.
  • "Required information" heading hidden when not needed. The checkout page no longer shows the Required information heading if you haven't configured any required customer input fields on the checkout session.
  • Branded merchant sites are more resilient. Custom domain sites now tolerate transient database hiccups instead of bubbling to an error page, with a friendlier in-page recovery state when something does fail.
Read more →

Decal Treasury, Finances Overview & the Add-ons Hub

Decal Treasury

The Finances overview is now live. At a glance it shows your idle Balance available to allocate, funds currently in Decal Treasury with a per-tier yield breakdown, and funds available to transfer back to Balance. When funds are sitting idle, the Balance card surfaces a quick action to allocate them to your Treasury account directly — no separate flow required. Tap the yield badge to expand the full tier-by-tier breakdown.

Transferring funds from Treasury to Balance is done from the Payouts page. Timing depends on your tier:

  • Basic-tier funds transfer to Balance instantly.
  • Pro-tier funds enter a ~24-hour unlock window. A live Cash Unlocking callout will display on the Payouts page with a countdown timer and a batch-claim button once the window closes.

The Balance card shows only the portion of your funds that can be allocated to Treasury today, with a secondary line for your "additional balances" — support for those is coming soon for Treasury yield.

Yield is generated through managed treasury strategies and is not guaranteed. Decal is a payments platform, not a bank.

Products & Add-ons

A new Products & Add-ons page gives merchants a single place to discover and enable optional features. Each add-on card shows whether the feature is generally available, in early access, or coming soon. One click enables or disables it.

The dashboard sidebar and pages update automatically: enabling an add-on unlocks its section in the nav; disabling one hides it cleanly without affecting your data.

Website Pages

The website area now includes a Pages view that lists every page your customer website responds to. Alongside the built-in pages (/, /login), any add-on you enable surfaces its pages here — for example, Stored Value adds /balance and /topup. Each row shows the path, title, live status, and a View live link to the page on your primary domain.

Minor Improvements

  • Branding saves no longer auto-publish your custom site. Saving your logo, theme color, or display name no longer accidentally brings a draft site online. Publishing remains an explicit action under Website → Settings.
  • Friendlier domain conflict errors. If a domain is already in use by another organization, the dialog now says so with a clear message instead of a generic failure.
  • Canonical URLs across custom website pages. All public merchant site pages now set correct canonical URLs and page titles for consistent SEO.
Read more →

Invite Your Team, Checkout API Upgrades & Payouts GA

Team Invites

Merchants can now invite teammates end-to-end from Team settings. Enter a name, email, and role (Admin or Owner), and the invite is sent by email automatically — with a copyable invite link for sharing outside of email.

  • Resend email is available from the pending invites menu, so a lost email isn't a dead end
  • Leave Organization is now a first-class action from your own member profile, with a safety guard that prevents the last owner from leaving without first transferring ownership
  • Remove Member and Change Role actions are live in member detail page as well
  • Invitee display name is set automatically from the name fields the inviter provides

Checkout API Upgrades

Following the Checkout Sessions and Orders API launch last week, a batch of upgrades aimed at integration reliability.

Top-level externalId on POST /v0/checkout/sessions and POST /v0/orders. Pass your own order identifier (cart ID, POS ticket, order number) directly on the order and retry safely — a second create call with the same externalId returns 409 Conflict with a DUPLICATE_EXTERNAL_ID error code. Built-in idempotency key that makes flaky network calls safe to retry.

Required fields at checkout. Create a session with requiredFields set to phone, shippingAddress, and/or location, and Decal's hosted checkout page will collect the missing information from the customer during the payment collection. Any fields you pre-fill at session creation allow the skipping those fields entirely.

{ORDER_ID} URL template. successUrl and callbackUrl now support {ORDER_ID} alongside the existing {SESSION_ID}. Substitution uses the formatted typed IDs (cs_<mode>_<cuid>, ord_<mode>_<cuid>), so the URLs your handlers receive are ready to plug straight back into the API.

Metadata limits. Orders and order items now have metadata shape constraints — max 50 keys, keys up to 40 characters, string values up to 500 characters, flat primitive arrays only. Keeps row sizes, response payloads, and webhook deliveries tidy. Well-formed existing metadata is unaffected.

Live Session Expiry Countdown

Checkout sessions now show a live countdown timer when less than 10 minutes remain, and transition gracefully to the expired or cancelled page mid-checkout — no page reload required. Whichever fires first (the timer hitting zero or the order polling detecting expiry) wins, so the customer always lands on the right page.

Saved Customer Payment Methods

Card and wallet details are now persisted after each successful payment. This enables returning-customer detection by card fingerprint — groundwork for faster repeat checkout flows.

Payouts for All Merchants

The Payouts page is now available to every organization — previously it was gated behind a feature flag.

Submitting a stablecoin payout updates the available balance and payout activity in-place. The active payout shows a spinner until it confirms (usually within sub-second), and failures surface inline with a clickable error badge. No more full-page reloads on submit.

Manual Wallet Connect

Wallets that don't publish a deep link scheme (e.g. Jupiter) can now be connected via a guided manual flow. A Don't see your wallet? entry appears at the bottom of the wallet list and opens a sheet with step-by-step instructions and a copy button — no auto-redirect or auto-copy.

Wallet sort order also updated so Mobile Wallet Adapter appears after named wallets but before Brave.

Minor Improvements

  • QR codes canonicalized to pay.usedecal.com — scan-to-pay QR codes and wallet deep links now route through the pay app redirect, so customers always see and share pay.usedecal.com/loc/{id} URLs regardless of your merchant handle or site configuration. Printed QRs keep working across handle and location status changes.
  • Dashboard time range sync — changing the chart period now updates all four metric cards to the same window, and the selection is preserved in the URL so it survives refresh and can be shared. Adds Year to date as a fourth option.
  • Payment destination fixpaymentDestination set on a checkout session now correctly routes funds to the specified wallet instead of the merchant's default orchestration wallet.
  • Checkout polling on tab return — returning to the browser tab after a wallet deep-link now immediately triggers an order status check, regardless of whether the wallet sheet is still open.
  • Dashboard sign-in fix — resolved a schema validation error that could reject valid emails on the sign-in screen, plus a layout fix to the error alert on dashboard, passport, and admin login screens.
Read more →

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 →