B2B API Authentication
Learn how to authenticate with the B2B API using JWT (JSON Web Token) and RSA digital signatures.
Key Pair Generation
Generate RSA Key Pair
Before authentication, you need to generate an RSA key pair:
# Generate a 2048-bit RSA private key
openssl genrsa -out private.pem 2048
# Extract the public key
openssl rsa -in private.pem -pubout -out public.pemRegister Your Public Key
You need to log in with a B2B user to get a JWT token first:
- Email: [email protected]
- Password: Testing@123
- Verify Code: 123456
curl --request POST \
--url http://auth-ss-staging.betprophet.io/api/v1/internal/b2b/keys \
--header 'authorization: Bearer ${JWT_TOKEN}' \
--header 'content-type: application/json' \
--header 'internal-auth: xYA7HZh6GSwEDanHdgayCkbz7s2sGD' \
--data '{
"name": "Test Public Key",
"public_key": "-----BEGIN PUBLIC KEY-----\nMIIBI... truncated ...AQAB\n-----END PUBLIC KEY-----\n"
}'Get List of Public Keys
curl --request GET \
--url http://auth-ss-staging.betprophet.io/api/v1/internal/b2b/keys \
--header 'authorization: Bearer ${JWT_TOKEN}'Delete Public Key
curl --request DELETE \
--url http://auth-ss-staging.betprophet.io/api/v1/internal/b2b/keys/d3ni76svmcpns4tm2bg0 \
--header 'authorization: Bearer ${JWT_TOKEN}' \
--header 'content-type: application/json'Receive your unique Issuer ID (e.g., d3clqdmkthpikm9dc9kg).
Authentication Headers
Each authenticated request must include:
- Content-Type: Must be
application/json(Required) - Authorization: Bearer token with JWT (Required)
Request Signing
Step 1: Prepare Request Body
# Example request data
body = {"message": "sample request"}
# Convert to compact JSON string
body_bytes = json.dumps(body).encode()Step 2: Calculate Body Hash
# Calculate SHA256 hash of request body
import hashlib
hasher = hashlib.sha256()
hasher.update(body_bytes)
body_hash = base64.b64encode(hasher.digest()).decode()Step 3: Create JWT Payload
now = int(time.time()) # in seconds
payload = {
"iss": issuer,
"aud": "prophetx", # should always be `prophetx`
"exp": now + 3600, # in seconds
"iat": now, # in seconds
"jti": f"test-jti-{now}",
"body_hash": body_hash,
}Step 4: Sign JWT Token
import jwt
from cryptography.hazmat.primitives import serialization
path_to_private_key = './keys/private.pem'
with open(path_to_private_key, 'rb') as f:
private_key = serialization.load_pem_private_key(f.read(), password=None)
token = jwt.encode(payload, private_key, algorithm="RS256")Making Authenticated Requests
POST Request Example
import requests
url = "https://api-ss-staging.betprophet.co/b2b/api/v1/pong"
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {token}"
}
response = requests.post(url, data=body_bytes, headers=headers)cURL Example
curl -X POST "https://api-ss-staging.betprophet.co/b2b/api/v1/pong" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \
-d '{"message":"sample request"}'Authentication Flow
JWT Claims Reference
| Claim | Type | Description | Example |
|---|---|---|---|
iss | string | Your partner identifier | "d3clqdmkthpikm9dc9kg" |
aud | string | Target audience (always "prophetx") | "prophetx" |
exp | number | Token expiration (Unix timestamp) | 1640995200 |
iat | number | Token issued at (Unix timestamp) | 1640991600 |
jti | string | Unique token identifier | "req-1640991600" |
body_hash | string | Base64 SHA256 hash of request body | "abc123..." |
Validation Constraints
Token Expiration
- Tokens cannot be issued in the future.
- Tokens cannot be reused.
- The server allows a 5-second clock skew tolerance.
Body Hash Validation
- The request body must exactly match the body used for hash calculation.
- JSON must be in compact format (no extra whitespace).
- UTF-8 encoding is required.
Required Claims
All six JWT claims are mandatory. Missing any claim will result in authentication failure.
Error Responses
Common Error Codes
| Status | Description | Solution | Error Code |
|---|---|---|---|
| 401 | Authorization header missing | Add Authorization: Bearer header | TBD |
| 401 | JWT token expired | Generate a new token with future expiration | TBD |
| 401 | JWT signature verification failed | Check private key and RS256 algorithm | TBD |
| 401 | Request body doesn't match hash | Recalculate body hash with exact request body | TBD |
| 401 | Required claims missing or invalid | Include all 6 required JWT claims | TBD |
| 401 | Issuer not registered | Verify issuer ID and public key registration | TBD |
Error Response Format
{
"error_code": "AUTHENTICATION_FAILED",
"error_type": "token_expired",
"message": "JWT token has expired",
"timestamp": "2023-12-31T12:00:00.000Z",
"request_id": "req_1234567890"
}Code Examples
Python
# Example Python code for authenticationUpdated 8 days ago