# signTransformUrl

```ts
function signTransformUrl(
   unsignedUrl, 
   signingKey, 
opts): Promise<string>;
```

Defined in: packages/asset-client/src/transform.ts:663

Sign a transform URL with the tenant's HMAC signing key. Appends
`?kid=<8 hex>&exp=<unix seconds>&sig=<64 hex>`.

Must agree byte-for-byte with the server's `verifyTransformSignature`.
Uses WebCrypto, so works in browsers, Node ≥ 16, Bun, and Workers.

The canonical DSL is the one already produced by `serializeTransform`
(sort keys + lowercase strings), so signing a URL built by `getTransformUrl`
is automatic — the same canonical form is in the URL path.

## ⚠️ `exp` IS ROUNDED DOWN TO THE MINUTE, AND THAT IS LOAD-BEARING

The edge cache key for `/t/` is the FULL URL. A per-request `exp` would make
every render of the same image a distinct cache entry — turning a path that
reaches the origin roughly never into one that reaches it on every view.
Rounding down to the minute means every renderer signing the same URL in the
same minute produces the same bytes, so the entry is shared. Down, never up,
so the URL never outlives the lifetime the caller asked for.

A build-time signer that wants ONE stable URL per deploy should pass a fixed
`nowSeconds` (the build timestamp) rather than a longer lifetime.

## Parameters

| Parameter | Type |
| ------ | ------ |
| `unsignedUrl` | `string` |
| `signingKey` | `string` |
| `opts` | [`SignTransformOptions`](/api/nitida/asset-client/type-aliases/signtransformoptions/) |

## Returns

`Promise`\<`string`\>