| Internet-Draft | Tempo Charge | March 2026 |
| Moxey, et al. | Expires 4 September 2026 | [Page] |
This document defines the "charge" intent for the "tempo" payment method in the Payment HTTP Authentication Scheme [I-D.httpauth-payment]. It specifies how clients and servers exchange one-time TIP-20 token transfers on the Tempo blockchain.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 4 September 2026.¶
Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
The charge intent represents a one-time payment of a specified amount.
The server may submit the signed transaction any time before the expires
timestamp.¶
This specification defines the request schema, credential formats, and settlement procedures for charge transactions on Tempo.¶
The following diagram illustrates the Tempo charge flow:¶
Client Server Tempo Network
| | |
| (1) GET /api/resource | |
|--------------------------> | |
| | |
| (2) 402 Payment Required | |
| intent="charge" | |
|<-------------------------- | |
| | |
| (3) Sign transfer tx | |
| | |
| (4) Authorization: Payment | |
|--------------------------> | |
| | (5) Broadcast tx |
| |--------------------------> |
| | (6) Transfer complete |
| |<-------------------------- |
| (7) 200 OK + Receipt | |
|<-------------------------- | |
| | |
¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.¶
Tempo's enshrined token standard, implemented as precompiles rather
than smart contracts. TIP-20 tokens use 6 decimal places and provide
transfer, transferWithMemo, transferFrom, and approve operations.¶
An EIP-2718 transaction with type prefix 0x76, supporting batched
calls, multiple signature types (secp256k1, P256, WebAuthn), 2D nonces,
and validity windows.¶
Tempo's nonce system where each account has multiple independent nonce
lanes (nonce_key), enabling parallel transaction submission.¶
An account that pays transaction fees on behalf of another account.
Tempo Transactions support fee payment via a separate signature
domain (0x78), allowing the server to pay for fees while the client
only signs the payment authorization.¶
The request parameter in the WWW-Authenticate challenge contains a
base64url-encoded JSON object.¶
| Field | Type | Required | Description |
|---|---|---|---|
methodDetails.chainId
|
number | OPTIONAL | Tempo chain ID (default: 42431) |
methodDetails.feePayer
|
boolean | OPTIONAL | If true, server pays transaction fees (default: false) |
Example:¶
{
"amount": "1000000",
"currency": "0x20c0000000000000000000000000000000000000",
"recipient": "0x742d35Cc6634C0532925a3b844Bc9e7595f8fE00",
"expires": "2025-01-06T12:00:00Z",
"methodDetails": {
"chainId": 42431,
"feePayer": true
}
}
¶
The client fulfills this by signing a Tempo Transaction with
transfer(recipient, amount) or transferWithMemo(recipient, amount, memo)
on the specified currency (token address),
with validBefore set to expires. The client SHOULD use a dedicated
nonceKey (2D nonce lane) for payment transactions to avoid blocking
other account activity if the transaction is not immediately settled.¶
If methodDetails.feePayer is true, the client signs with
fee_payer_signature set to 0x00 and fee_token empty, allowing the
server to sponsor fees. If feePayer is false or omitted, the client
MUST set fee_token and pay fees themselves.¶
The credential in the Authorization header contains a base64url-encoded
JSON object per Section 5.2 of [I-D.httpauth-payment].¶
| Field | Type | Required | Description |
|---|---|---|---|
challenge
|
object | REQUIRED | Echo of the challenge from the server |
payload
|
object | REQUIRED | Tempo-specific payload object |
source
|
string | OPTIONAL | Payer identifier as a DID (e.g., did:pkh:eip155:42431:0x...) |
The source field, if present, SHOULD use the did:pkh method with the
Tempo chain ID (42431 for Moderato testnet) and the payer's
Ethereum address.¶
When type is "transaction", signature contains the complete signed
Tempo Transaction (type 0x76) serialized as RLP and hex-encoded with
0x prefix. The transaction MUST contain a transfer(recipient, amount)
or transferWithMemo(recipient, amount, memo) call on the TIP-20 token.¶
| Field | Type | Required | Description |
|---|---|---|---|
signature
|
string | REQUIRED | Hex-encoded RLP-serialized signed transaction |
type
|
string | REQUIRED |
"transaction"
|
Example:¶
{
"challenge": {
"id": "kM9xPqWvT2nJrHsY4aDfEb",
"realm": "api.example.com",
"method": "tempo",
"intent": "charge",
"request": "eyJ...",
"expires": "2025-02-05T12:05:00Z"
},
"payload": {
"signature": "0x76f901...signed transaction bytes...",
"type": "transaction"
},
"source": "did:pkh:eip155:42431:0x1234567890abcdef1234567890abcdef12345678"
}
¶
When type is "hash", the client has already broadcast the transaction
to the Tempo network. The hash field contains the transaction hash for
the server to verify onchain.¶
| Field | Type | Required | Description |
|---|---|---|---|
hash
|
string | REQUIRED | Transaction hash with 0x prefix |
type
|
string | REQUIRED |
"hash"
|
Example:¶
{
"challenge": {
"id": "kM9xPqWvT2nJrHsY4aDfEb",
"realm": "api.example.com",
"method": "tempo",
"intent": "charge",
"request": "eyJ...",
"expires": "2025-02-05T12:05:00Z"
},
"payload": {
"hash": "0x1a2b3c4d5e6f7890abcdef1234567890abcdef1234567890abcdef1234567890",
"type": "hash"
},
"source": "did:pkh:eip155:42431:0x1234567890abcdef1234567890abcdef12345678"
}
¶
When a request includes feePayer: true, the server commits to paying
transaction fees on behalf of the client.¶
When feePayer: true:¶
Client signs with placeholder: The client signs the Tempo Transaction
with fee_payer_signature set to a placeholder value (0x00) and
fee_token left empty. The client uses signature domain 0x76.¶
Server receives credential: The server extracts the client-signed transaction from the credential payload.¶
Server adds fee payment signature: The server selects a fee_token (any
USD-denominated TIP-20 stablecoin) and signs the transaction using
signature domain 0x78. This signature commits to the transaction
including the fee_token and client's address.¶
Server broadcasts: The final transaction contains both signatures:¶
When feePayer: false or omitted, the client MUST set fee_token to a
valid USD TIP-20 token address and pay fees themselves. The server
broadcasts the transaction as-is without adding a fee payer signature.¶
When acting as fee payer, servers:¶
For intent="charge" fulfilled via transaction, the client signs a
transaction containing a transfer or transferWithMemo call. If feePayer: true, the server
adds its fee payer signature before broadcasting:¶
Client Server Tempo Network
| | |
| (1) Authorization: | |
| Payment <credential> | |
|------------------------------->| |
| | |
| | (2) If feePayer: true, |
| | add fee payment signature |
| | |
| | (3) eth_sendRawTxSync |
| |------------------------------->|
| | |
| | (4) Transfer executed |
| | (~500ms finality) |
| |<-------------------------------|
| | |
| (5) 200 OK | |
| Payment-Receipt: <txHash> | |
|<-------------------------------| |
| | |
¶
Client submits credential containing signed transfer or transferWithMemo transaction¶
If feePayer: true, server adds fee sponsorship (signs with 0x78 domain)¶
Server broadcasts transaction to Tempo¶
Transaction included in block with immediate finality (~500ms)¶
Server returns receipt with the transaction digest¶
For credentials with type="hash", the client has already broadcast
the transaction. The server verifies the transaction onchain:¶
Client Server Tempo Network
| | |
| (1) Broadcast tx | |
|------------------------------------------------------> |
| | |
| (2) Transaction confirmed | |
|<------------------------------------------------------ |
| | |
| (3) Authorization: | |
| Payment <credential> | |
| (with txHash) | |
|--------------------------> | |
| | |
| | (4) eth_getTransactionReceipt
| |--------------------------> |
| | |
| | (5) Receipt returned |
| |<-------------------------- |
| | |
| | (6) Verify receipt |
| | |
| (7) 200 OK | |
| Payment-Receipt: | |
| <txHash> | |
|<-------------------------- | |
| | |
¶
Limitations:¶
Upon successful settlement, servers MUST return a Payment-Receipt header
per Section 5.3 of [I-D.httpauth-payment]. Servers MUST NOT include a
Payment-Receipt header on error responses; failures are communicated via
HTTP status codes and Problem Details.¶
The receipt payload for Tempo charge:¶
| Field | Type | Description |
|---|---|---|
method
|
string |
"tempo"
|
reference
|
string | Transaction hash of the settlement transaction |
status
|
string |
"success"
|
timestamp
|
string | [RFC3339] settlement time |
Tempo Transactions include chain ID, nonce, and optional validBefore/
validAfter timestamps that prevent replay attacks:¶
Clients MUST parse and verify the request payload before signing:¶
Servers acting as fee payers accept financial risk in exchange for providing a seamless payment experience.¶
Denial of Service: Malicious clients could submit valid-looking credentials that fail onchain, causing the server to pay fees without receiving payment. Servers SHOULD implement rate limiting and MAY require client authentication before accepting payment credentials.¶
Fee Token Exhaustion: Servers MUST monitor their fee token balance and reject new payment requests when balance is insufficient.¶
This document registers the following payment method in the "HTTP Payment Methods" registry established by [I-D.httpauth-payment]:¶
| Method Identifier | Description | Reference |
|---|---|---|
tempo
|
Tempo blockchain TIP-20 token transfer | This document |
Contact: Tempo Labs (contact@tempo.xyz)¶
This document registers the following payment intent in the "HTTP Payment Intents" registry established by [I-D.httpauth-payment]:¶
| Intent | Applicable Methods | Description | Reference |
|---|---|---|---|
charge
|
tempo
|
One-time TIP-20 transfer | This document |
Challenge:¶
HTTP/1.1 402 Payment Required WWW-Authenticate: Payment id="kM9xPqWvT2nJrHsY4aDfEb", realm="api.example.com", method="tempo", intent="charge", request="eyJhbW91bnQiOiIxMDAwMDAwIiwiY3VycmVuY3kiOiIweDIwYzAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDEiLCJyZWNpcGllbnQiOiIweDc0MmQzNUNjNjYzNEMwNTMyOTI1YTNiODQ0QmM5ZTc1OTVmOGZFMDAiLCJleHBpcmVzIjoiMjAyNS0wMS0wNlQxMjowMDowMFoiLCJtZXRob2REZXRhaWxzIjp7ImNoYWluSWQiOjQyNDMxfX0"¶
The request decodes to:¶
{
"amount": "1000000",
"currency": "0x20c0000000000000000000000000000000000000",
"recipient": "0x742d35Cc6634C0532925a3b844Bc9e7595f8fE00",
"expires": "2025-01-06T12:00:00Z",
"methodDetails": {
"chainId": 42431
}
}
¶
This requests a transfer of 1.00 pathUSD (1000000 base units).¶
Credential:¶
GET /api/resource HTTP/1.1 Host: api.example.com Authorization: Payment eyJjaGFsbGVuZ2UiOnsiaWQiOiJrTTl4UHFXdlQybkpySHNZNGFEZkViIn0sInBheWxvYWQiOnsic2lnbmF0dXJlIjoiMHg3NmY5MDEuLi4iLCJ0eXBlIjoidHJhbnNhY3Rpb24ifSwic291cmNlIjoiZGlkOnBraDplaXAxNTU6NDI0MzE6MHgxMjM0NTY3ODkwYWJjZGVmMTIzNDU2Nzg5MGFiY2RlZjEyMzQ1Njc4In0¶
The authors thank the Tempo community for their feedback on this specification.¶