> For the complete documentation index, see [llms.txt](https://docs.fonbnk.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.fonbnk.com/widget-integration/signing-the-url.md).

# Signing the URL

The Pay Widget is configured by URL query parameters. Two of them identify you:

1. <mark style="color:yellow;">**source**</mark> — the "Source" value from your merchant dashboard.
2. <mark style="color:yellow;">**signature**</mark> — a JWT signed with a URL signature secret from your merchant dashboard.

### Generating the signature

Sign a JWT with the **HS256** algorithm, using your URL signature secret as the key. Put a unique value in the payload so each token is distinct, and set an expiry with `expiresIn`. During testing you can generate one at <https://jwt.io/>.

You can also carry widget configuration parameters in the token payload instead of the query string, which keeps them out of the visible URL.

```typescript
import * as jsonwebtoken from 'jsonwebtoken';
import { v4 as uuid } from 'uuid';

const signature = jsonwebtoken.sign(
    {
      uid: uuid(),
    },
    YOUR_SIGNATURE_SECRET,
    {
      algorithm: 'HS256',
      expiresIn: '1h',
    },
 );
```

### Always set an expiry

{% hint style="warning" %}
**An expiry will become required.** A token with no `exp` claim is still accepted today. We will start refusing those, and we will tell you the date before we do. Add `expiresIn` now and nothing will need changing later.
{% endhint %}

A signed URL travels in the address bar, so it reaches browser history, `Referer` headers, and any log or support ticket that records the link. Anyone holding it can open the widget as you, with your fee settings, your rates and your limits, for as long as the token stays valid. A token with no `exp` never becomes invalid on its own. Revoking the secret in the dashboard is the only thing that stops it, and that stops every other link signed with the same secret too.

We honour the `exp` you set, so keep it as short as your flow allows:

| Your flow                                       | Suggested lifetime                                              |
| ----------------------------------------------- | --------------------------------------------------------------- |
| Sign per checkout on your server, then redirect | minutes to an hour                                              |
| Send a customer a payment link they open later  | match how long the link should work, in days rather than months |
| Embed one signed link in a page                 | do not. Sign per visit instead (see below)                      |

{% hint style="info" %}
**Do not hard-code one signed link into a page or an email template.** It stops working when the token expires, while the page still serves it to customers. Sign a fresh token per visit on your server, or link to a page of your own that redirects to a freshly signed widget URL.
{% endhint %}

A link you generate on the **Pay widget** page of the merchant dashboard is signed for you and carries a 90-day expiry. The dashboard shows you the date it stops working.

### Use HS256

Sign with **HS256**. HS384 and HS512 are also accepted today, and we plan to accept HS256 only. If you sign with either of the others, move to HS256 now.

{% hint style="warning" %}
The secret is a signing key. It belongs on your server — never in client-side code, and never in the URL itself. You can create and rotate secrets from the dashboard.
{% endhint %}

With `source` and `signature` in hand, move on to [URL params](/widget-integration/url-params.md) to configure the widget.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.fonbnk.com/widget-integration/signing-the-url.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
