Wirex baas auth
Skill wirexapp/wirex-baas-agent-skills/skills/wirex-baas-auth
Wirex BaaS authentication — how to authenticate API requests. Server-to-Server OAuth2 token exchange (POST /api/v1/token), user-scoped token issuance (POST /api/v1/user/authorize), Privy-based authentication. Covers required headers (Authorization, X-Chain-Id, X-User-Address/Email/Id), token caching strategy (48h validity, 5min refresh buffer), and security best practices.From its SKILL.md
npx -y skills add wirexapp/wirex-baas-agent-skills --skill wirex-baas-authAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its file declares
Copied from the file, not written here
The file declares its own license as Apache-2.0. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
8.1 KB, as published. Nobody here has run it
Wirex BaaS Authentication
Overview
Wirex BaaS uses a layered authentication model with three distinct methods, each serving different integration patterns:
- Server-to-Server (S2S) OAuth2 -- Machine-to-machine authentication using client credentials. This is the foundation; all other auth methods build on top of it.
- User Token Issuance -- Partner-issued tokens scoped to a specific user, obtained by presenting an S2S token with user identity headers.
- Privy Authentication -- Third-party identity provider integration for retail user flows, using Privy access and identity tokens.
All tokens are HMAC-SHA256 signed JWTs with a 48-hour validity period. The platform recommends caching tokens and refreshing them 5 minutes before expiry.
Method 1: Server-to-Server (S2S) Authentication
S2S authentication is the primary method for backend integrations. It uses the OAuth2 client credentials grant to obtain an access token.
Endpoint
POST /api/v1/token
This is a user-agnostic endpoint -- no user identity headers are required.
Request
Headers:
| Header | Value |
|---|---|
Content-Type | application/json |
Body:
| Field | Type | Required | Description |
|---|---|---|---|
client_id | string | Yes | Your partner application UUID |
client_secret | string | Yes | Your partner secret |
grant_type | string | Yes | Must be client_credentials |
Response
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_at": 1700172800
}
| Field | Type | Description |
|---|---|---|
access_token | string | HMAC-SHA256 signed JWT token |
token_type | string | Always Bearer |
expires_at | integer | Unix timestamp (seconds) when the token expires |
Token Details
| Property | Value |
|---|---|
| Algorithm | HMAC-SHA256 (HS256) |
| Validity | 48 hours from issuance |
| Scope | partner:full |
| Format | JWT (JSON Web Token) |
Method 2: User Token Issuance
User tokens are scoped to a specific user and grant access to user-specific endpoints (balances, transfers, cards, KYC). They are obtained by presenting a valid S2S token along with user identity headers.
Endpoint
POST /api/v1/user/authorize
Request
Headers:
| Header | Required | Description |
|---|---|---|
Authorization | Yes | Bearer <s2s_access_token> |
X-Chain-Id | Yes | Target chain ID (e.g., 84532 for Sandbox Base Sepolia) |
X-User-Address | Yes | The user's EOA address (not the Smart Wallet address) |
Content-Type | Yes | application/json |
Body: Empty or {}
Response
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_at": 1700172800
}
The user token has the same format and validity as the S2S token but includes user-scoped claims.
Method 3: Privy Authentication
Privy authentication is designed for retail user flows where users authenticate directly through a Privy-powered frontend.
Prerequisites
- Set up a Privy application at privy.io
- Provide your Privy App ID to Wirex during onboarding
- Wirex configures your Privy App ID in your company credentials
Token Exchange Headers
| Header | Required | Description |
|---|---|---|
Authorization | Yes | Bearer <privy_access_token> (from Privy SDK login) |
Identity | Yes | Bearer <privy_identity_token> (from Privy SDK login) |
X-Chain-Id | Yes | Target chain ID |
Privy tokens are validated against Privy's JWKS endpoint. The aud claim in the access token must match your configured Privy App ID.
User Registration via Privy
POST /api/v1/user/retail
Body:
{
"country": "US"
}
User Identity Headers
For endpoints that operate on a specific user, exactly one of the following headers must be provided:
| Header | Format | Description |
|---|---|---|
X-User-Address | Hex string (EVM) or Stellar public key | The user's EOA address (not the Smart Wallet address) |
X-User-Email | Email string | The user's registered email address |
X-User-Id | String | The platform-assigned user identifier |
Rules:
- Exactly one identity header is required for user-specific calls. Multiple identity headers in the same request will be rejected with
ErrorInvalidField. - When choosing which header to use:
X-User-Idis most reliable,X-User-Addressfor on-chain context,X-User-Emailas fallback.
User-Agnostic Endpoints
| Endpoint | Method | Description |
|---|---|---|
/api/v1/token | POST | S2S token exchange |
/api/v1/user | POST | Create user (v1) |
/api/v2/user | POST | Create user (v2) |
/api/v1/config | GET | Platform configuration |
/api/v1/validation/rules | GET | Validation rules |
Token Caching
Tokens are valid for 48 hours but should be cached and refreshed proactively with a 5-minute buffer before expiry.
Token lifetime: |<-------------- 48 hours ------------->|
| |
Issue time |--- Use cached token ---|--- Refresh ---|
t=0 t=47h55m t=48h
^
5-min buffer
Error Handling
Error Response Format
{
"error_reason": "ErrorPermissionDenied",
"error_description": "Invalid client credentials",
"error_category": {
"category": "CategoryUnauthorized",
"http_status_code": 401
},
"error_details": [
{"key": "field", "details": "client_secret"}
]
}
Note:
error_categoryis an object withcategoryandhttp_status_codefields.error_detailsis an optional array providing field-level error context.
Common Authentication Errors
| Error Reason | HTTP | Category | Description |
|---|---|---|---|
ErrorPermissionDenied | 401 | CategoryUnauthorized | Invalid credentials or token signature |
ErrorExpired | 401 | CategoryUnauthorized | Access token has expired |
ErrorMissingField | 400 | CategoryValidationFailure | Required field or header missing |
ErrorInvalidField | 400 | CategoryValidationFailure | Invalid value or multiple user identifiers provided |
ErrorNotSupported | 401 | CategoryUnauthorized | Client credentials not supported for this company type |
ErrorConfigurationInvalid | 500 | CategoryInternalFailure | Privy App ID not registered (Privy flow) |
Security Best Practices
- Never expose
client_secretin client-side code. All token exchange must happen server-side. - Use a secrets manager (AWS Secrets Manager, HashiCorp Vault, GCP Secret Manager) to store credentials.
- Cache tokens with a 5-minute buffer before expiry to avoid request failures.
- Always use HTTPS. TLS 1.2 or higher is required.
- Implement request timeouts. 30-second timeout recommended.
- Never log full tokens. Truncate to first 10 characters if logging is needed.
Complete Authentication Flow
POST /api/v1/tokenwithclient_id+client_secret→ receive S2S token (48h validity)POST /api/v1/user/authorizewithBearer {s2s_token}+X-User-Address+X-Chain-Id→ receive user token (48h validity)- Call user-scoped endpoints (wallets, cards, transfers) with
Bearer {user_token}
References
- Authentication Endpoint Reference -- Complete endpoint specifications, JWT claims, JavaScript code examples, token caching, and full request/response details