Skip to main content

Redirect URL Templating

Bookla can dynamically personalize the success, failure, and cancel redirect URLs that your payment provider sends a customer back to after checkout. Instead of a single static URL, you can define a template URL with placeholders (e.g. {{.ID}}, {{.Amount}}), and Bookla will fill them in with the details of the actual transaction before handing the URL to the payment provider.

To make sure nobody can tamper with those values on the way back to your site, every templated URL is also cryptographically signed with a secret only you know. You can then ask Bookla to verify the signature before trusting anything you read from the query string.

This guide explains:

  • What you can put into a redirect URL template
  • How to enable the feature for a provider
  • How the signed URL that reaches your customer looks
  • How to verify that signature on your side

When to use it

Use redirect URL templating when your post-payment page needs to know something specific about the transaction, for example:

  • Showing a confirmation like "Booking #123 paid" without an extra API call
  • Passing the booking or reference ID to your own analytics / CRM
  • Redirecting to a different page depending on the item type or plugin
  • Reconciling the redirect to an order in your own system

Because the templated parameters are signed, you can safely use them to drive UI or lookups, as long as you validate the signature first.

Supported providers

Redirect URL templating is available for the following providers:

  • Stripe
  • Klix
  • Decta
  • Montonio
  • MercadoPago

Each provider exposes two settings you can toggle:

  • enable_url_templating — enables placeholder substitution and signing
  • signing_secret — the shared secret used to compute and verify the HMAC signature

Both are set per company, alongside the existing success_redirect_url, failure_redirect_url and cancel_redirect_url fields for that provider.

info

If enable_url_templating is false (the default), Bookla passes the configured redirect URLs to the provider as‑is — no substitution, no signing. Existing integrations keep working unchanged.

Enabling templating

  1. Open your payment provider settings in the Bookla dashboard (e.g. Stripe, Klix, …).

  2. In each redirect URL field you want to template, replace static values with placeholders (see the reference below). For example:

    https://yourshop.com/booking/success?booking={{.ItemID}}&ref={{.ReferenceID}}&amount={{.Amount}}&currency={{.Currency}}
  3. Set Enable URL templating to true.

  4. Set a Signing secret — a long, random string that only your backend will know. Treat it like an API key: never ship it to the browser, and rotate it if you suspect it has leaked.

  5. Save the settings.

From this point on, every time Bookla hands a redirect URL to the provider, it will first substitute the placeholders and then append two extra query parameters — ts and sig — that you can use to verify the URL.

caution

If enable_url_templating is true but signing_secret is missing or empty, Bookla will refuse to create a payment URL for that transaction. Always configure both fields together.

Placeholder reference

Placeholders use Go text/template syntax: a dot followed by the field name, wrapped in double curly braces. The leading dot is required — {{ID}} without the dot is invalid.

PlaceholderDescriptionExample value
{{.ID}}Unique ID of the payment transaction in Booklad2c1b0c4-7a3e-4d7e-9a7b-3c2d1e0f0a1b
{{.ItemID}}ID of the item being paid for (e.g. booking ID)e2f3a4b5-6789-4abc-def0-0123456789ab
{{.ItemIDs}}Comma‑separated list of item IDs if the transaction covers multiple itemsid1,id2,id3
{{.ItemType}}Type of item the transaction pays forbooking, ticket, subscription
{{.PluginNamespace}}Namespace of the plugin that initiated the payment, if anycom.example.plugin
{{.Amount}}Transaction amount in the smallest currency unit (cents, etc.)5000 (= 50.00)
{{.Currency}}ISO 4217 currency codeEUR, USD, GBP
{{.ReferenceID}}Your own reference for the transaction, if one was provided when bookingORDER-456

Notes:

  • Amount is always an integer in the smallest currency unit of the transaction currency (cents for EUR/USD, etc.). It is not divided by 100 for you.
  • ItemIDs is a single string, not repeated query parameters. If you need each ID as its own parameter, split the string on , on your side after verification.
  • Only these fields are available. Any other placeholder (e.g. {{.CustomerEmail}}) will cause template processing to fail.

A complete example

Template configured in the dashboard:

https://shop.example.com/payments/done?txID={{.ID}}&item={{.ItemID}}&type={{.ItemType}}&amt={{.Amount}}&curr={{.Currency}}&ref={{.ReferenceID}}

URL that Bookla will ultimately hand to the payment provider:

https://shop.example.com/payments/done?
txID=d2c1b0c4-7a3e-4d7e-9a7b-3c2d1e0f0a1b
&item=e2f3a4b5-6789-4abc-def0-0123456789ab
&type=booking
&amt=5000
&curr=EUR
&ref=ORDER-456
&ts=1713600000
&sig=9f3c…64‑hex‑chars…a1

(Line breaks added for readability — the real URL is a single line.)

Template syntax rules

A few things to keep in mind when authoring templates:

  • Use dotted field names. {{.ID}} is valid, {{ID}} is not. Bookla will return an error that explicitly reminds you of this if you get it wrong.
  • Values are automatically URL‑encoded. Bookla applies path‑style escaping (%20 for spaces, etc.) to every placeholder value before substitution, so you don't need to — and you must not — wrap fields in {{urlquery ...}}. Doing so would double‑encode the value.
  • Static query parameters are preserved. Anything you put in the template that is not a placeholder (e.g. ?source=checkout) is passed through untouched and is not included in the signature.
  • Mix placeholders freely in path and query. Both work: /payments/{{.ID}}/done and ?id={{.ID}} are valid.
  • URL length is capped at 2000 characters after substitution and signing. If your template plus data exceeds this, Bookla will fail payment URL generation rather than produce an unusable link.

The signed URL

Once the placeholders are filled in, Bookla appends two query parameters to the URL before it leaves the platform:

ParameterMeaning
tsUnix timestamp (seconds) at which the URL was signed
sigHex‑encoded HMAC‑SHA256 of the templated parameters and the timestamp

Only the parameters that Bookla actually templated contribute to the signature. Static query parameters and non-templated path segments are ignored. This means you can add extra tracking parameters to a redirect on your side without breaking verification — as long as you don't touch the templated ones, ts or sig.

A signature is valid for 5 minutes from its ts. A small amount of clock skew (up to 1 minute) into the future is tolerated, but older signatures or timestamps more than a minute ahead of the server clock will be rejected.

Verifying the signature on your side

When your success / failure / cancel page loads, you should:

  1. Collect all query parameters you received.
  2. Call Bookla's verify‑signature endpoint, forwarding those parameters.
  3. Only trust the values in the URL if Bookla returns valid: true.

Endpoint

GET /companies/{company_id}/payments/verify-signature
  • company_id — the UUID of the company whose redirect URL was signed.
  • All the query parameters you received on the redirect (including ts and sig) must be forwarded as‑is.

Response

{
"valid": true
}

or, when verification fails:

{
"valid": false,
"reason": "signature_expired"
}

Reason codes

The reason field uses a stable set of values you can branch on:

ReasonWhat it means
missing_parametersts or sig is missing from the URL.
invalid_timestampts is not a valid integer.
signature_expiredts is older than the 5‑minute validity window.
timestamp_in_futurets is more than 1 minute ahead of Bookla's server clock.
invalid_signature_formatsig is not valid hexadecimal.
invalid_signature_lengthsig is not 64 hex characters (32 bytes of HMAC‑SHA256).
signature_mismatchThe signature does not match — the URL was tampered with, or the secret is wrong.
company_settings_not_foundNo payment settings exist for the given company.
provider_settings_not_foundThe company has no configured preferred provider settings.
signing_secret_not_configuredTemplating was not set up for this provider, so there is nothing to verify.
failed_to_extract_signing_secretBookla couldn't read the signing secret from the provider settings.
internal_errorAn unexpected error happened while verifying. Safe to retry.

Example flow

User is redirected to:
https://shop.example.com/payments/done?txID=d2c1…&amt=5000&curr=EUR&ts=1713600000&sig=9f3c…a1

Your backend receives the request and calls:
GET https://us.bookla.com/api/v1/companies/{company_id}/payments/verify-signature
?txID=d2c1…&amt=5000&curr=EUR&ts=1713600000&sig=9f3c…a1

Bookla responds:
{ "valid": true }

Your backend now trusts txID, amt, currency and renders the confirmation.
tip

You do not need to implement HMAC yourself — always prefer the verify‑signature endpoint. It is the single source of truth for which parameters are signed, how the signing string is built, and when a signature has expired.

Security notes

  • Keep the signing secret secret. It only lives in Bookla's settings and on your own backend. Never expose it to the browser or to the payment provider.
  • Always verify before trusting. The templated parameters are convenience — a confirmation page that reads amount straight from the URL without calling the verify endpoint can be spoofed.
  • Rotate if leaked. Rotating the signing_secret immediately invalidates any unverified links that are still floating around in customers' tabs or email inboxes. Users mid‑checkout will need to start a new payment.
  • Don't rely on it for authorization. A valid signature proves the URL was issued by Bookla for a specific transaction — it doesn't replace your own session / auth when performing actions like refunding or modifying a booking.

Troubleshooting

  • failed to process URL template error when creating a payment. Usually means a placeholder has the wrong shape. Double‑check you used {{.FieldName}} with a leading dot and an exact field from the reference.
  • Signature always returns signature_expired. Your server clock and Bookla's may be drifting. The allowed window is 5 minutes old and up to 1 minute in the future; make sure your host runs NTP.
  • Signature always returns signature_mismatch. Confirm the signing_secret configured in Bookla exactly matches what you expect, and that you're forwarding all query parameters (including any you weren't expecting) to the verify endpoint — not just the ones you recognize.
  • URL generation fails with a length error. Your template plus transaction values exceeds 2000 characters. Drop unnecessary placeholders or shorten static parts of the URL.
  • Redirect works but ts/sig are missing. enable_url_templating is probably off, or the template URL contains no placeholders at all — Bookla only signs URLs that were actually templated.