> For the complete documentation index, see [llms.txt](https://hinkal-team.gitbook.io/hinkal/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://hinkal-team.gitbook.io/hinkal/hinkal-waas/description/request-authentication.md).

# Request Authentication

This page describes authentication for the **WaaS API**. The [API](/hinkal/hinkal-api/description/overview.md) uses a different, EVM-wallet-signature scheme — see [API Authentication](/hinkal/hinkal-api/description/authentication.md). Both are purely cryptographic — there are no passwords.

Every request to the WaaS API (except the health check and `/waas/public-balance`) is authenticated using **X-Stamp** — an Ed25519-based request signing scheme. There are no passwords or API tokens. Authentication is purely cryptographic.

## Keypair setup

When integrating with WaaS, developers generate an Ed25519 keypair client-side. The public key is registered with Hinkal and stored in the database as the unique identifier for that user. The corresponding private key never leaves the client.

## How X-Stamp works

For every request, the client produces a stamp by signing the full request payload with their Ed25519 private key, bound to the specific route:

* For `POST` requests: the request body is signed
* For `GET` requests: the query parameters are signed

The signed message is serialized as `JSON.stringify([binding, Object.entries(params)])` before signing, where `binding` is `"<METHOD> <routePath>"` (e.g. `"POST /waas/create-wallet"`) — the server's route pattern, not the literal request URL. This stops a stamp captured for one endpoint from being replayed against another. The one parameterized WaaS route, `GET /waas/scheduled-transaction/{scheduleId}`, binds to the literal `"GET /waas/scheduled-transaction/:scheduleId"`, not the concrete `scheduleId`. See [Signing Requests](/hinkal/hinkal-waas/signing-requests.md) for full, runnable examples.

The resulting stamp — a Base64URL-encoded JSON object containing the public key and hex-encoded signature — is sent as the `X-Stamp` header:

```json
{
  "publicKey": "<hex-encoded ed25519 public key>",
  "signature": "<hex-encoded ed25519 signature>"
}
```

## Validation

The API server verifies the X-Stamp signature on every request. For sensitive operations such as transaction signing, the enclave independently re-validates the stamp — so even if the API layer were compromised, an invalid or forged stamp would be rejected before any key material is touched.

## Nonce

Every request must include a `nonce` field as part of the signed payload. The nonce must be unique — once a nonce has been used, any subsequent request with the same nonce is permanently rejected. This prevents replay attacks where a valid signed request could be resubmitted by an attacker.
