---
updatedAt: 2026-09-25T08:07:22.000Z
agentTools:
  projectIndex: https://docs.skyfire.xyz/llms.txt
---

# Verify and Extract Data from Tokens

Skyfire tokens are standard signed JWTs. When a request reaches your service, it may include a token in the `kyapay-token` header.

> Older integrations may use the `skyfire-pay-id` header but this is deprecated and being replaced.

Before acting on the request, your service should verify the token and validate its contents.

Without these checks, your service may accept forged or expired tokens.

***

# High Level Validation Flow

At a high level, the flow looks like:

1. Extract the token from the request header (`kyapay-token` or `skyfire-pay-id`).
2. Verify the signature using Skyfire’s public keys (JWKS).
   1. Production: <Anchor target="_blank" href="https://app.skyfire.xyz/.well-known/jwks.json"><https://app.skyfire.xyz/.well-known/jwks.json></Anchor>
   2. Sandbox (for testing): <Anchor target="_blank" href="https://app-sandbox.skyfire.xyz/.well-known/jwks.json"><https://app-sandbox.skyfire.xyz/.well-known/jwks.json></Anchor>
3. Decode the token
4. Validate the claims. This can help you ensure the token is:
   1. The intended token type (`typ`)
   2. From the correct environment (`env`, `iss`)
   3. Still valid (`iat`, `exp`)

Only after all of these checks pass should your service authorize access and/or collect payment.

***

# Token Format

Skyfire tokens are signed **JSON Web Tokens (JWTs)**. Each token contains:

* A **header** describing how the token was signed
* A **payload** containing identity and/or payment claims
* A **signature** used to verify authenticity

All Skyfire tokens are signed using:

* Algorithm: `ES256`

***

# Signature Verification (JWKS)

To verify the token, your service must use the Skyfire public keys published via JWKS (JSON Web Key Set).

> **Recommendation:** Cache the JWKS response for up to 60 minutes to avoid unnecessary network calls.

<Tabs>
  <Tab title="Production">
    <Cards columns="1">
      <Card title="JWKS File" href="https://app.skyfire.xyz/.well-known/jwks.json" icon="fa-key">
        Public keys for JWT verification.

        [https://app.skyfire.xyz/.well-known/jwks.json](https://app.skyfire.xyz/.well-known/jwks.json)
      </Card>
    </Cards>
  </Tab>

  <Tab title="Sandbox">
    <Cards columns="1">
      <Card title="JWKS File" href="https://app-sandbox.skyfire.xyz/.well-known/jwks.json" icon="fa-key">
        Public keys for JWT verification.

        [https://app-sandbox.skyfire.xyz/.well-known/jwks.json](https://app-sandbox.skyfire.xyz/.well-known/jwks.json)
      </Card>
    </Cards>
  </Tab>
</Tabs>

Use any standard JWKS / JOSE library to verify and decode tokens: <Anchor target="_blank" href="https://www.jwt.io/libraries">JWT / JOSE Libraries</Anchor>

See a TypeScript example using the `jose` library:

```typescript
// Fetch the JWKS from /.well-known/jwks.json
const jwks = await getJWKS()

// Create a verifier from the JWKS
const verifier = jose.createLocalJWKSet(jwks)

// Verify signature and extract payload
const { payload, protectedHeader } = await jose.jwtVerify(
  token.token,
  verifier,
  {
    issuer: 'https://app.skyfire.xyz',
  }
)
```

***

# Claims to Verify

Once the token passes signature verification, decode it to access its **header** and **payload** claims.

## Header Claims

For token headers, we recommend validating:

| Claim | Validation                                                                     |
| :---- | :----------------------------------------------------------------------------- |
| `typ` | Matches your accepted token types. One of `kya+jwt`, `pay+jwt`, `kya-pay+jwt`. |

For general information about the header of Skyfire tokens, see this [page](https://docs.skyfire.xyz/docs/common-token-claims#header) .

***

## Payload Claims

There are common claims that exist across all Skyfire tokens, regardless of token type. Across these claims, we recommend validating:

| Claim | Validation                                                                          |
| :---- | :---------------------------------------------------------------------------------- |
| `env` | Is `production` for production integrations. Is `sandbox` for sandbox integrations. |
| `iat` | Is a 10-digit epoch-seconds value in the past.                                      |
| `jti` | Is a UUID.                                                                          |
| `exp` | Is a 10-digit epoch-seconds value now or in the future                              |

For more general information about these claims, see this [page](https://docs.skyfire.xyz/docs/common-token-claims#payload).

The claims below are only applicable in specific cases. You will not typically validate these. For more information, contact <support@tryskyfire.com>.

| Claim | Validation                                                                                                                                               |
| :---- | :------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `aud` | *Not always applicable* - Is your Skyfire Seller Agent ID (if you have onboarded your Seller Service to Skyfire for, for example, Payments Processing)   |
| `sdm` | *Not always applicable* - Is your website/service's root domain.                                                                                         |
| `ssi` | *Not always applicable* - Is your Skyfire Seller Service ID (if you have onboarded your Seller Service to Skyfire for, for example, Payments Processing) |
| `sub` | *Not always applicable* - Matches the expected Buyer Agent ID (if you are only allowing specific buyer agents / buyer agent platforms)                   |

<br />

***

## `kya` Tokens (`typ = kya+jwt`)

In addition to the common validations, consider validating identity-specific claims:

* `hid` contains the human principal’s identity claims (JSON object)
* `apd` (optional) contains agent platform's identity claims (JSON object)
* `aid` contains agent identity claims (JSON object)

For more general information about `kya` claims, see this [page](https://docs.skyfire.xyz/docs/kya-token).

***

## `pay` Tokens (`typ = pay+jwt`)

In addition to the common validations, consider validating payment-specific claims:

| Claim | Validation                                                                                                                                                        |
| :---- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `val` | Is greater than 0.                                                                                                                                                |
| `amt` | Is greater than 0.                                                                                                                                                |
| `cur` | Is `USD`                                                                                                                                                          |
| `stp` | Matches your expected settlement type. One of `coin`, `card`, `bank`.                                                                                             |
| `sti` | Includes `sti.verified: true`. Additional validations encouraged.                                                                                                 |
| `spr` | Matches your configured seller service price (if you have onboarded to Skyfire for Payments Processing)                                                           |
| `sps` | Matches your configured pricing scheme (if you have onboarded to Skyfire for Payments Processing). One of: `pay_per_use`, `subscription`, `pay_per_mb`, `custom`. |

***

## `kya-pay` Tokens (`typ = kya-pay+jwt`)

Perform **both** `kya` and `pay` validations.

***

# Reference Implementations

The following examples demonstrate how to verify Skyfire tokens and perform common claim validations.

They are intended as **reference implementations**. You should adapt validation logic to your service’s requirements and risk tolerance.

<Tabs>
  <Tab title="Typescript">
    <Cards>
      <Card title="Verify a Token Created to an External Seller" href="https://github.com/skyfire-xyz/kyapay/blob/main/code-examples/verifyToken/typescript/src/verifyKyaTokenToExternalSeller.ts" icon="fa-code" target="_blank">
        See a KYA token validation implementation to an external seller.
      </Card>

      <Card title="Verify a Token Created to an Onboarded Seller Service" href="https://github.com/skyfire-xyz/kyapay/blob/main/code-examples/verifyToken/typescript/src/verifyKyaPayTokenToOnboardedService.ts" icon="fa-code" target="_blank">
        See a KYA-PAY token validation implementation to a Skyfire-onboarded seller service.
      </Card>
    </Cards>
  </Tab>

  <Tab title="Python">
    <Cards>
      <Card title="Verify a Token Created to an External Seller" href="https://github.com/skyfire-xyz/kyapay/blob/main/code-examples/verifyToken/python/verifyKyaTokenToExternalSeller.py" icon="fa-code" target="_blank">
        See a KYA token validation implementation to an external seller.
      </Card>

      <Card title="Verify a Token Created to an Onboarded Seller Service" href="https://github.com/skyfire-xyz/kyapay/blob/main/code-examples/verifyToken/python/verifyKyaPayTokenToOnboardedService.py" icon="fa-code" target="_blank">
        See a KYA-PAY token validation implementation to a Skyfire-onboarded seller service.
      </Card>
    </Cards>
  </Tab>
</Tabs>