Embed Widget
Overview
The embed system lets you display partner dashboard data directly inside your own application. Instead of sending partners to portal.affihub.com, you can show their metrics, links, commissions, and payouts within your app's UI.
How it works
- Your server requests a short-lived JWT token for a specific partner
- Your frontend uses this token to call Affihub's embed API endpoints
- The endpoints return the same data as the partner portal
Generating an embed token
From your server, call the embed token endpoint with your API key:
curl -X POST "https://api.affihub.com/api/v1/embed/token" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"partner_id": "par_abc123"}'Response:
{
"token": "eyJhbGciOiJIUzI1NiIs...",
"expires_in": 3600
}The token is a HS256 JWT valid for 1 hour containing:
{
"partner_id": "par_abc123",
"program_id": "prog_xxx",
"scope": "embed",
"iat": 1712880000,
"exp": 1712883600
}Generate tokens server-side only. Never expose your API key in client-side code.
Using the embed token
Pass the JWT as a Bearer token to the embed endpoints:
const res = await fetch("https://api.affihub.com/embed/data/dashboard", {
headers: {
Authorization: `Bearer ${embedToken}`,
},
});
const dashboard = await res.json();Available endpoints
All endpoints are prefixed with /embed/data/ and accept the JWT Bearer token:
| Method | Endpoint | Description |
|---|---|---|
| GET | /embed/data/dashboard |
Partner dashboard metrics |
| GET | /embed/data/links |
List referral links |
| POST | /embed/data/links |
Create a referral link |
| DELETE | /embed/data/links/:id |
Delete a referral link |
| GET | /embed/data/commissions |
Commission history |
| GET | /embed/data/payouts |
Payout history |
These return the same data as the corresponding /portal/data/* endpoints.
Full integration example
Server (Node.js)
app.get("/api/affiliate-token", async (req, res) => {
// Identify the logged-in user and find their partner ID
const partnerId = await getPartnerIdForUser(req.user.id);
const response = await fetch(
"https://api.affihub.com/api/v1/embed/token",
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.AFFIHUB_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ partner_id: partnerId }),
}
);
const { token } = await response.json();
res.json({ token });
});Client (React)
function AffiliateDashboard() {
const [stats, setStats] = useState(null);
useEffect(() => {
async function load() {
// Get embed token from your server
const { token } = await fetch("/api/affiliate-token").then(r => r.json());
// Fetch dashboard data from Affihub
const data = await fetch(
"https://api.affihub.com/embed/data/dashboard",
{ headers: { Authorization: `Bearer ${token}` } }
).then(r => r.json());
setStats(data);
}
load();
}, []);
if (!stats) return <div>Loading...</div>;
return (
<div>
<h2>Your Affiliate Dashboard</h2>
<p>Clicks: {stats.total_clicks}</p>
<p>Referrals: {stats.total_referrals}</p>
<p>Earnings: ${(stats.total_earned_cents / 100).toFixed(2)}</p>
</div>
);
}Token refresh
Embed tokens expire after 1 hour. Your frontend should handle token expiration:
async function fetchWithToken(url) {
let res = await fetch(url, {
headers: { Authorization: `Bearer ${token}` },
});
if (res.status === 401) {
// Token expired — get a new one
const { token: newToken } = await fetch("/api/affiliate-token")
.then(r => r.json());
token = newToken;
res = await fetch(url, {
headers: { Authorization: `Bearer ${token}` },
});
}
return res.json();
}Security
- Tokens are signed with HMAC-SHA256 using the
EMBED_JWT_SECRET - The
scope: "embed"claim restricts access to embed endpoints only - Tokens are scoped to a single partner — they cannot access other partners' data
- Token expiry is enforced server-side
- Always generate tokens server-side to avoid exposing your API key