Credentials
Client-submitted payment proofs
A Credential is your response to a Challenge, proving that you paid or authorized the payment. Send credentials in the Authorization header.
Structure
Authorization: Payment eyJjaGFsbGVuZ2UiOnsiaWQiOiJxQjN3RXJUeVU3aU9wQXNEOWZHaEprIiwi...The credential is a base64url-encoded JSON object:
{
"challenge": {
"expires": "2025-01-15T12:05:00Z",
"id": "qB3wErTyU7iOpAsD9fGhJk",
"intent": "charge",
"method": "tempo",
"opaque": "eyJyb3V0ZSI6Ii92MS9zZWFyY2gifQ",
"realm": "mpp.dev",
"request": "eyJhbW91bnQiOiIxMDAwIi4uLn0",
},
"payload": {
"signature": "0xabc123...",
"type": "transaction"
},
"source": "did:pkh:eip155:4217:0x1234567890abcdef..."
}The echoed Challenge keeps the original HTTP wire values. In a Credential, challenge.request and challenge.opaque remain the same base64url-encoded JCS JSON strings from the WWW-Authenticate header.
Fields
| Field | Description |
|---|---|
challenge | The Challenge being responded to |
source | Identity of the payer (address, DID, account ID) |
payload | Method-specific payment proof |
Single-use credentials
Each credential is valid for exactly one request. When processing a credential:
- Verify the
challenge.idmatches an outstanding challenge - Verify the challenge has not expired
- Verify the payment or proof using method-specific procedures
- Reject any replayed credentials
Tempo charge payload types
Tempo charge currently uses three Credential payload shapes:
payload.type | When the client uses it | What the server verifies |
|---|---|---|
transaction | Non-zero charge in pull mode | Signed Tempo transaction before broadcast |
hash | Non-zero charge in push mode | On-chain receipt for the submitted transaction |
proof | Zero-amount identity flow | Signed proof message over the Challenge ID with no on-chain transfer |
Example
Tempo charge payment
{
"challenge": {
"id": "zL4xCvBnM6kJhGfD8sAaWe",
"intent": "charge",
"method": "tempo",
"opaque": "eyJyb3V0ZSI6Ii92MS9zZWFyY2gifQ",
"realm": "mpp.dev",
"request": "eyJhbW91bnQiOiI1MDAwIiwiY3VycmVuY3kiOiJ1c2QiLCJyZWNpcGllbnQiOiIweDc0MmQzNUNjNjYzNEMwNTMyOTI1YTNiODQ0QmM5ZTc1OTVmOGZFMDAifQ"
},
"payload": {
"signature": "0x1b2c3d4e5f6a7b8c9d0e...",
"type": "transaction"
},
"source": "did:pkh:eip155:4217:0x1234567890abcdef1234567890abcdef12345678"
}The server verifies the signature authorizes a transfer matching the challenge parameters, then submits the payment on-chain.
For zero-amount Tempo Challenges, the payload becomes {"type":"proof","signature":"0x..."}. The server verifies the proof against the source identity instead of broadcasting a transfer.