Skip to content

Developer

PHP

Mint Reqio HS256 identity tokens on a PHP server using firebase/php-jwt. Compatible with Laravel, Symfony, and plain PHP.

The snippet below is exactly what the dashboard generates under Project > Settings > Identity when you choose PHP. Copy it from the dashboard to get your real project ID and audience URL pre-filled.

Install

composer require firebase/php-jwt

Mint a token

<?php
// composer require firebase/php-jwt
use Firebase\JWT\JWT;

$now = time();
$payload = [
    "sub"    => $user->id,
    "email"  => $user->email,
    "traits" => ["plan" => $user->plan, "amount" => $user->planAmount, "interval" => $user->billingInterval], // amount in cents; interval "month" | "year"
    "aud"    => "https://reqio.app/p/YOUR_PROJECT_ID",
    "iat"    => $now,
    "exp"    => $now + 300,
];
$token = JWT::encode($payload, $_ENV["REQIO_SECRET"], "HS256");

Replace YOUR_PROJECT_ID with your project ID, or copy the full snippet from the dashboard where the audience URL is pre-filled.

Environment variable

Set REQIO_SECRET to the signing secret from Project > Settings > Identity > Reveal secret. Store it in your environment (.env file, server config, or secrets manager) and never echo it into responses.

Laravel example

<?php

namespace App\Http\Controllers;

use Firebase\JWT\JWT;
use Illuminate\Http\Request;

class PageController extends Controller
{
    public function index(Request $request)
    {
        $user = $request->user();
        $now  = time();

        $token = JWT::encode(
            [
                "sub"    => (string) $user->id,
                "email"  => $user->email,
                "traits" => ["plan" => $user->plan, "amount" => $user->plan_amount, "interval" => $user->billing_interval],
                "aud"    => config("services.reqio.audience"),
                "iat"    => $now,
                "exp"    => $now + 300,
            ],
            config("services.reqio.secret"),
            "HS256"
        );

        return view("page", compact("token"));
    }
}
{{-- resources/views/page.blade.php --}}
<script
  src="https://reqio.app/widget.js"
  data-project-id="{{ config('services.reqio.project_id') }}"
  data-identity-token="{{ $token }}"
  async
></script>

Store the audience URL in services.reqio.audience in config/services.php so you do not hardcode it.

Plain PHP example

<?php

require 'vendor/autoload.php';

use Firebase\JWT\JWT;

$now = time();
$token = JWT::encode(
    [
        "sub"   => (string) $_SESSION["user_id"],
        "email" => $_SESSION["user_email"] ?? null,
        "aud"   => getenv("REQIO_AUDIENCE"),
        "iat"   => $now,
        "exp"   => $now + 300,
    ],
    getenv("REQIO_SECRET"),
    "HS256"
);
?>

<script
  src="https://reqio.app/widget.js"
  data-project-id="<?= htmlspecialchars(getenv("REQIO_PROJECT_ID")) ?>"
  data-identity-token="<?= htmlspecialchars($token) ?>"
  async
></script>

Always escape output with htmlspecialchars when interpolating into HTML attributes.

Pass the token to the widget

For server-rendered templates, pass the token via data-identity-token:

<script
  src="https://reqio.app/widget.js"
  data-project-id="YOUR_PROJECT_ID"
  data-identity-token="<?= htmlspecialchars($token) ?>"
  async
></script>

For SPAs where the user authenticates after the initial page load, call window.Reqio.identify() from JavaScript after login:

window.Reqio.identify(token);

Traits reference

| Field | Type | Description | |---|---|---| | plan | string | Plan name on your billing system, e.g. "pro". | | amount | int | Recurring charge as billed, in cents. For annual plans send the full annual total; Reqio divides by 12 to derive the monthly value. | | interval | "month" or "year" | Billing cadence for amount. |

Security

Store REQIO_SECRET in your environment and never echo it into responses. The JWT is short-lived and audience-bound to one project, limiting the blast radius of a leaked token. The signing secret must never leave your server.