Overview

Developers · Hashry Pay

Hashry Pay developer guide

Take card payments inside your own checkout page. Hashry's card form runs in a frame on your page. Card numbers never touch your page or your server. Your keys never touch the browser.

This guide is for the developer who builds the integration. The merchant sends you this link from the Hashry admin.

How to use this guide

  1. Read How it works on this page.
  2. Do the admin setup with the merchant.
  3. Follow your stack's page from start to end. It has every file, and ends with a paid test order.
  4. Then test and go live.

The packages are an early release (0.x). Their API can change before 1.0.

1. How it works

Your server holds the secret key and talks to Hashry. Your page only shows Hashry's card form. A payment goes like this:

  1. The shopper is ready to pay. Your page asks your server to start the payment.
  2. Your server creates the payment with its secret key (POST /v1/channel/payment-intents). It sets the amount from its own order. The page never sends an amount.
  3. Your server passes the four checkout values to the page, and nothing else: embed_url, transaction_uid, status_url and status_token.
  4. The page shows the card form. The shopper enters the card. If the bank wants a 3-D Secure check, it runs inside the card form.
  5. If the bank declines the card, the card form asks for another one, up to 3 cards. Your server does nothing.
  6. The card form says completed. That is a cue, not proof. The page asks your server.
  7. Your server confirms with Hashry (POST /v1/channel/payment-intents/{uid}/refresh), or gets a webhook. Only then does it mark the order paid.

Words used in this guide

WordWhat it means
PaymentOne payment per order, with its amount, currency and status. The API calls it a payment intent. Its ID is uid in the API, payment_intent_uid in webhooks.
Card formHashry's form, in a frame on your page. The shopper types the card there, so card numbers never reach your page.
Full payment pageThe same form on a Hashry page of its own. The card form offers it if the bank check has trouble in a frame. The shopper comes back through your return_url.
Checkout valuesThe four values your server passes to the page: embed_url, transaction_uid, status_url and status_token.
Status tokenLets the page read one payment's status, for display. It can't confirm or change anything.
AttemptOne go at paying, inside a payment. When every card in a card form is declined, your server starts a new attempt on the same payment.
ConfirmYour server asks Hashry for the latest outcome, with Hashry's refresh call. Only then does it mark the order paid.
WebhookA signed POST from Hashry to your server when a payment changes.
Idempotency keyA name you choose for each create call, such as order-1042-pay-1. Sending the same key again is safe: you get the same payment back.
Embed originThe https address of the page that shows the card form.
Return originThe https address of your return_url and cancel_url.
Sandbox and liveSandbox is for testing, with test cards and no real money. The key you use picks the mode.

What may go in the browser

ValueLooks likeWhere it may go
Client secrethsk_live_…, hsk_test_…Server only.
Webhook signing secrethwhsec_live_…, hwhsec_test_…Server only.
Access tokenFrom POST /auth/tokenServer only.
Client IDShown with the keyServer. Keep it with the secret.
embed_urlhttps://pay.hashrytech.com/…The page, once. It works like a password for this one payment: never log or store it.
transaction_uidAn IDThe page.
status_url and status_tokenhst_…The page. The token reads this payment's status, amount and currency, and nothing else.
Don't:

Never call the Hashry API from the browser. If you send your client secret from a browser:

  • Hashry refuses the call with 403 secret_key_used_in_browser.
  • It shows the call in the admin's Integration health panel, and emails the account owners.
  • If the merchant turned on Revoke keys used from a web browser, the key stops working at once.
Note:

Hashry spots browser calls by the Sec-Fetch-Site header. Server HTTP clients don't send it. If your server forwards a shopper's browser headers to Hashry, drop the Sec-Fetch-* headers.

2. Set up in the Hashry admin

The merchant does this once, or gives you access. In the Hashry admin, open the store, then its Payment Integration sales channel. Live and Test Sandbox are separate tabs, each with its own keys and settings. Start on Test Sandbox.

  1. Issue a test key. In Test API keys, choose Issue test key. Copy the client ID and the client secret (hsk_test_…). The secret is shown once. Share it through a password manager, not a chat message.
  2. Allow your page's address. In Test return addresses, add your page's origin to Allowed return origins. Then add the same origin to Allowed embed origins, under Embedded card form. For development, that is https://localhost:3000 (Next.js) or https://localhost:5173 (the others). Use the scheme, the host, and the port if it is not 443. No path, no wildcard.
  3. Turn on key safety. On the Details tab, in Key safety, turn on Revoke keys used from a web browser.
Note:

Use https, even on your own machine. Allowed return origins accept http://localhost, but allowed embed origins do not, and the card form shows only in https pages. Each stack page sets up a local certificate for you.

If the card says the embedded card form is off, ask Hashry to turn it on for the account. You set up the webhook URL later, when you test: see Test and go live.

Sandbox and live

Sandbox and live use the same API host. The key picks the mode. A test key sees only test payments. Your code does not change when you go live: only the settings do.

SandboxLive
Client secrethsk_test_…hsk_live_…
Webhook secrethwhsec_test_…hwhsec_live_…
HASHRY_ENVIRONMENTsandboxlive
Card form hostdevpay.hashrytech.compay.hashrytech.com
MoneyTest cards only. Not in payouts or reports.Real cards

Your server settings

Every stack page reads these settings. Each one shows a settings file ready to fill in.

SettingWhat it isSecret?
HASHRY_CLIENT_IDThe client ID of your key.Keep it with the secret.
HASHRY_CLIENT_SECRETThe client secret: hsk_test_… or hsk_live_….Yes.
HASHRY_ENVIRONMENTsandbox or live. It must match the key.No.
HASHRY_WEBHOOK_SECRETThe webhook signing secret. You get it when you set up webhooks.Yes.
PUBLIC_BASE_URLThe https address shoppers open. Not needed in SvelteKit.No.
Don't:

Never put a secret in browser code, in a mobile app, or in a setting with a public prefix such as NEXT_PUBLIC_, VITE_ or PUBLIC_. Anyone who loads the page can read those. If a key leaks, the merchant revokes it in the admin and issues a new one.

3. Pick your stack

Each page takes you from a new app to a paid test order, with every file in order. Follow one page from start to end.

Your stackWhat you build
Next.jsOne app: route handlers and a React page.
Express + ReactAn Express server and a React page built with Vite.
SvelteKitOne app: +server.ts routes and a Svelte page.
PythonA FastAPI server and a React page. Notes for Django and Flask.

Another stack? Use the parts on their own:

Help and support

  • Something not working? Start with Troubleshooting.
  • Questions: email support@hashrytech.com.
  • Security problems: email support@hashrytech.com with "Security" in the subject. Say which package and version, what you found, and how to repeat it. Don't post the details anywhere public.
  • Licence: Apache-2.0. Each package ships LICENSE and NOTICE. The licence gives no right to use the Hashry name or logo.
  • The API schema is public: GET https://api.hashrytech.com/openapi/partner (OpenAPI 3.1).

Supported versions

PackageFromRuns on
@hashrytech/paynpmCurrent Chrome, Edge, Firefox and Safari, including Safari on iPhone
@hashrytech/pay-reactnpmReact 18 (18.2 or newer) and React 19
@hashrytech/pay-sveltenpmSvelte 5
@hashrytech/pay-build-guardnpmNode 22 or newer; Vite 5 or newer, or webpack 5
@hashrytech/pay-nodenpmNode 22.12 or newer. Server only.
hashry-payPyPIPython 3.11 or newer

"Current" browsers means about the last two years of releases.

Next: build it for your stack

Back to top

© 2026 Hashry Solutions Limited. All rights reserved.