Preview. The API is shared with design partners and may change before launch. Register interest for sandbox access.
OAuth 2.0 and mTLS
Bank-grade integrations authenticate with the OAuth 2.0 client credentials grant. There are no shared secrets: your client proves its identity with a private key that never leaves your infrastructure, ideally in an HSM or a cloud KMS.
Endpoints
Section titled “Endpoints”| Purpose | URL |
|---|---|
| Token endpoint | https://partner-api.getphew.com/oauth2/token |
| Token endpoint (mTLS) | https://partner-api-mtls.getphew.com/oauth2/token |
| Checkout API and Partner API (mTLS) | https://api-mtls.getphew.com/v1, https://partner-api-mtls.getphew.com/v1 |
| Authorization server metadata (RFC 8414) | https://partner-api.getphew.com/.well-known/oauth-authorization-server |
| Phew signing keys (JWKS) | https://partner-api.getphew.com/.well-known/jwks.json |
Registering a client
Section titled “Registering a client”- Choose a client authentication method:
private_key_jwtortls_client_auth. - Send us your public keys, either as a JWKS URL that we fetch (recommended, so you can rotate on your own schedule)
or as uploaded public keys. Accepted algorithms:
PS256,ES256andEdDSA. RSA keys must be at least 2048 bits. - For mTLS, send the subject DN of your client certificate and the issuing CA chain. We accept certificates from your own private CA or a public CA.
- Tell us the scopes each client needs and your egress IP ranges.
- We return a
client_idper environment.
Getting a token
Section titled “Getting a token”Create a client assertion JWT signed with your private key:
// Header{ "alg": "PS256", "kid": "psp-2026-10", "typ": "JWT" }
// Claims{ "iss": "cli_01JD8A3B5C7D9E1F3G5H7J9K1M", "sub": "cli_01JD8A3B5C7D9E1F3G5H7J9K1M", "aud": "https://partner-api.getphew.com/oauth2/token", "jti": "5b4f3c1e-8d2a-4e6b-9f0a-1c2d3e4f5a6b", "iat": 1761220329, "exp": 1761220389}The assertion must expire within 60 seconds of iat, and each jti is accepted only once. Exchange it for an access
token:
curl https://partner-api.getphew.com/oauth2/token \ -d grant_type=client_credentials \ -d client_id=cli_01JD8A3B5C7D9E1F3G5H7J9K1M \ -d client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer \ -d client_assertion=eyJhbGciOiJQUzI1NiIsImtpZCI6InBzcC0yMDI2LTEwIn0... \ -d scope="offers:write policies:write"Connect to the mTLS host with your client certificate. The certificate authenticates the client, and the issued token is bound to it.
curl https://partner-api-mtls.getphew.com/oauth2/token \ --cert client.pem --key client-key.pem \ -d grant_type=client_credentials \ -d client_id=cli_01JD8A3B5C7D9E1F3G5H7J9K1M \ -d scope="offers:write policies:write"API calls with a certificate-bound token must also be made over mTLS with the same certificate: use
api-mtls.getphew.com for the Checkout API and partner-api-mtls.getphew.com for the Partner API.
The response:
{ "access_token": "eyJhbGciOiJFUzI1NiIsImtpZCI6InBoZXctMjAyNi0xMCJ9...", "token_type": "Bearer", "expires_in": 600, "scope": "offers:write policies:write"}Access tokens
Section titled “Access tokens”Access tokens are JWTs signed by Phew with ES256. Treat them as opaque; their format may change. Properties you can rely on:
- They expire after 10 minutes. Cache the token and request a new one about a minute before expiry. Refresh tokens are not issued.
- They carry only the scopes requested, which must be a subset of the scopes the client is registered for.
- With mTLS, they are bound to your certificate (RFC 8705
cnf.x5t#S256). Phew rejects the token if it’s presented without the matching certificate.
Certificate and key rotation
Section titled “Certificate and key rotation”- JWKS URL: publish the new key alongside the old one, start signing with it, then remove the old key. We refresh
your JWKS every 15 minutes and immediately when we see an unknown
kid. - Uploaded keys and certificates: send the new key or certificate; both are valid until you confirm the switch.
- Phew notifies your security contact at least 30 days before any certificate you depend on expires.
Errors
Section titled “Errors”Token endpoint errors follow RFC 6749:
error |
Meaning |
|---|---|
invalid_client |
Assertion or certificate failed verification, unknown client_id, or reused jti |
invalid_scope |
A requested scope isn’t granted to this client |
unauthorized_client |
The client isn’t allowed to use this grant or authentication method |
invalid_request |
Missing or malformed parameter |