Skip to content

Commit f31bcbf

Browse files
committed
Restore authorize and subscription intents with Tempo implementations
Restores the core intent specs and Tempo method implementations that were removed in #88. Stripe implementations will follow in a separate PR.
1 parent e471905 commit f31bcbf

File tree

4 files changed

+1688
-0
lines changed

4 files changed

+1688
-0
lines changed
Lines changed: 342 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,342 @@
1+
---
2+
title: Authorize Intent for HTTP Payment Authentication
3+
abbrev: Payment Intent Authorize
4+
docname: draft-payment-intent-authorize-00
5+
version: 00
6+
category: info
7+
ipr: trust200902
8+
submissiontype: IETF
9+
consensus: true
10+
11+
author:
12+
- name: Jake Moxey
13+
ins: J. Moxey
14+
email: jake@tempo.xyz
15+
org: Tempo Labs
16+
- name: Brendan Ryan
17+
ins: B. Ryan
18+
email: brendan@tempo.xyz
19+
org: Tempo Labs
20+
- name: Tom Meagher
21+
ins: T. Meagher
22+
email: thomas@tempo.xyz
23+
org: Tempo Labs
24+
25+
normative:
26+
RFC2119:
27+
RFC8174:
28+
I-D.httpauth-payment:
29+
title: "The 'Payment' HTTP Authentication Scheme"
30+
target: https://datatracker.ietf.org/doc/draft-httpauth-payment/
31+
author:
32+
- name: Jake Moxey
33+
date: 2026-01
34+
---
35+
36+
--- abstract
37+
38+
This document defines the "authorize" payment intent for use with the
39+
Payment HTTP Authentication Scheme {{I-D.httpauth-payment}}. The "authorize"
40+
intent represents a pre-authorization where the payer grants the server
41+
permission to charge up to a specified amount within a time window,
42+
without immediate payment.
43+
44+
--- middle
45+
46+
# Introduction
47+
48+
The "authorize" intent enables pre-authorized payments where the payer
49+
grants the server permission to charge up to a specified amount at a
50+
later time. This is useful for:
51+
52+
- **Metered billing**: Pay-per-use APIs where total cost is unknown upfront
53+
- **Delayed fulfillment**: Services where delivery occurs after authorization
54+
- **Spending caps**: User-controlled limits on automated spending
55+
56+
Unlike the "charge" intent which requires immediate payment, "authorize"
57+
creates a payment capability that the server can exercise later.
58+
59+
## Relationship to Payment Methods
60+
61+
Payment methods implement "authorize" using their native authorization
62+
mechanisms:
63+
64+
| Method | Implementation |
65+
|--------|----------------|
66+
| Tempo | Access Keys with spending limits |
67+
| Stripe | SetupIntent + saved PaymentMethod |
68+
| EVM | ERC-20 `approve()` or EIP-3009 authorization |
69+
70+
# Requirements Language
71+
72+
{::boilerplate bcp14-tagged}
73+
74+
# Terminology
75+
76+
Authorization
77+
: A grant of permission for a server to initiate payments up to a
78+
specified limit within a specified time window, without requiring
79+
immediate payment.
80+
81+
Spending Limit
82+
: The maximum amount that can be charged against an authorization
83+
before it is exhausted.
84+
85+
Revocation
86+
: The act of canceling an authorization before its natural expiry,
87+
preventing further charges.
88+
89+
# Intent Semantics
90+
91+
## Definition
92+
93+
The "authorize" intent represents a request for the payer to grant
94+
permission for the server to initiate payments up to a specified limit,
95+
within a specified time window.
96+
97+
## Properties
98+
99+
| Property | Value |
100+
|----------|-------|
101+
| **Intent Identifier** | `authorize` |
102+
| **Payment Timing** | Deferred (server-initiated later) |
103+
| **Idempotency** | Reusable within limits |
104+
| **Reversibility** | Revocable before use |
105+
106+
## Flow
107+
108+
~~~
109+
Client Server Payment Network
110+
│ │ │
111+
│ (1) GET /resource │ │
112+
├───────────────────────────────>│ │
113+
│ │ │
114+
│ (2) 402 Payment Required │ │
115+
│ intent="authorize" │ │
116+
│<───────────────────────────────┤ │
117+
│ │ │
118+
│ (3) Sign authorization │ │
119+
│ │ │
120+
│ (4) Authorization: Payment │ │
121+
├───────────────────────────────>│ │
122+
│ │ │
123+
│ │ (5) Register authorization │
124+
│ ├─────────────────────────────>│
125+
│ │ │
126+
│ (6) 200 OK (authorized) │ │
127+
│<───────────────────────────────┤ │
128+
│ │ │
129+
│ ... later ... │ │
130+
│ │ │
131+
│ (7) GET /resource │ │
132+
├───────────────────────────────>│ │
133+
│ │ (8) Charge via auth │
134+
│ ├─────────────────────────────>│
135+
│ │ │
136+
│ (9) 200 OK + Receipt │ │
137+
│<───────────────────────────────┤ │
138+
│ │ │
139+
~~~
140+
141+
## Non-Atomicity
142+
143+
Unlike "charge", the "authorize" intent is non-atomic:
144+
145+
- Authorization registration is separate from payment collection
146+
- Multiple charges may occur against a single authorization
147+
- Total charges MUST NOT exceed the authorized limit
148+
149+
# Request Schema
150+
151+
The `request` parameter for an "authorize" intent is a JSON object with
152+
shared fields defined by this specification and optional method-specific
153+
extensions in the `methodDetails` field.
154+
155+
## Shared Fields
156+
157+
All payment methods implementing the "authorize" intent MUST support these
158+
shared fields, enabling clients to parse and display authorization requests
159+
consistently across methods.
160+
161+
### Required Fields
162+
163+
| Field | Type | Description |
164+
|-------|------|-------------|
165+
| `amount` | string | Maximum authorization amount in base units |
166+
| `currency` | string | Currency or asset identifier (see {{currency-formats}}) |
167+
| `expires` | string | Authorization expiry timestamp in ISO 8601 format |
168+
169+
### Optional Fields
170+
171+
| Field | Type | Description |
172+
|-------|------|-------------|
173+
| `recipient` | string | Payment recipient in method-native format |
174+
| `description` | string | Human-readable authorization description |
175+
| `externalId` | string | Merchant's reference (order ID, etc.) |
176+
| `methodDetails` | object | Method-specific extension data |
177+
178+
## Currency Formats {#currency-formats}
179+
180+
The `currency` field supports multiple formats to accommodate different
181+
payment networks:
182+
183+
| Format | Example | Description |
184+
|--------|---------|-------------|
185+
| ISO 4217 | `"usd"`, `"eur"` | Fiat currencies (lowercase) |
186+
| Token address | `"0x20c0..."` | ERC-20, TIP-20, or similar token contracts |
187+
| Well-known symbol | `"sat"`, `"btc"`, `"eth"` | Native blockchain assets |
188+
189+
Clients can detect the format:
190+
191+
- Starts with `0x`: Token contract address
192+
- Three lowercase letters: ISO 4217 currency code
193+
- Otherwise: Well-known symbol or method-specific identifier
194+
195+
## Method Extensions
196+
197+
Payment methods MAY define additional fields in the `methodDetails` object.
198+
These fields are method-specific and MUST be documented in the payment
199+
method specification.
200+
201+
## Examples
202+
203+
### Traditional Payment Processor (Stripe)
204+
205+
~~~ json
206+
{
207+
"amount": "100000",
208+
"currency": "usd",
209+
"expires": "2025-01-22T12:00:00Z",
210+
"description": "Pre-authorization for metered API usage",
211+
"methodDetails": {
212+
"captureMethod": "manual"
213+
}
214+
}
215+
~~~
216+
217+
### Blockchain Payment (Tempo)
218+
219+
~~~ json
220+
{
221+
"amount": "50000000",
222+
"currency": "0x20c0000000000000000000000000000000000001",
223+
"expires": "2025-02-05T12:00:00Z",
224+
"methodDetails": {
225+
"chainId": 42431
226+
}
227+
}
228+
~~~
229+
230+
# Credential Requirements
231+
232+
## Payload
233+
234+
The credential `payload` for an "authorize" intent contains the
235+
authorization grant. The format is method-specific:
236+
237+
| Authorization Type | Description | Example Methods |
238+
|-------------------|-------------|-----------------|
239+
| Signed Key Auth | Delegated signing key | Tempo Access Keys |
240+
| Token Approval | On-chain approval | EVM ERC-20 approve |
241+
| Saved Payment Method | Stored card/account | Stripe SetupIntent |
242+
243+
## Reusability
244+
245+
Unlike "charge" credentials, "authorize" credentials may enable multiple
246+
subsequent charges. The authorization persists until:
247+
248+
- The expiry timestamp is reached
249+
- The spending limit is exhausted
250+
- The payer explicitly revokes it
251+
252+
# Authorization Lifecycle
253+
254+
## Registration
255+
256+
When the server receives an "authorize" credential:
257+
258+
1. Verify the authorization signature/proof
259+
2. Store the authorization for future use
260+
3. Return success (200) to indicate authorization accepted
261+
4. Optionally return `Payment-Authorization` for session reuse
262+
263+
## Charging
264+
265+
When charging against an authorization:
266+
267+
1. Verify the authorization is still valid (not expired, not revoked)
268+
2. Verify sufficient limit remains
269+
3. Execute the charge via method-specific mechanism
270+
4. Decrement the remaining limit
271+
5. Return `Payment-Receipt` with charge details
272+
273+
## Revocation
274+
275+
Payers SHOULD be able to revoke authorizations before expiry. Revocation
276+
mechanisms are method-specific:
277+
278+
| Method | Revocation Mechanism |
279+
|--------|---------------------|
280+
| Tempo | Remove Access Key from account |
281+
| EVM | Set approval to zero |
282+
| Stripe | Detach PaymentMethod from Customer |
283+
284+
## Expiry
285+
286+
Servers MUST NOT charge against expired authorizations. Servers SHOULD
287+
provide a mechanism for payers to query authorization status.
288+
289+
# Security Considerations
290+
291+
## Limit Verification
292+
293+
Clients MUST verify the requested limit is acceptable before signing.
294+
Authorizations grant future spending capability without further user
295+
interaction.
296+
297+
## Expiry Windows
298+
299+
Clients SHOULD prefer short authorization windows. Long-lived
300+
authorizations increase risk if credentials are compromised.
301+
302+
Recommended maximum windows:
303+
304+
| Use Case | Recommended Max |
305+
|----------|-----------------|
306+
| Single session | 1 hour |
307+
| Daily usage | 24 hours |
308+
| Monthly billing | 30 days |
309+
310+
## Revocation Capability
311+
312+
Payment methods implementing "authorize" SHOULD provide revocation
313+
mechanisms. Payers MUST be able to revoke authorizations if they suspect
314+
compromise.
315+
316+
## Authorization Scope
317+
318+
Authorizations SHOULD be scoped as narrowly as possible:
319+
320+
- Specific recipient address (not "any address")
321+
- Specific asset/currency
322+
- Reasonable limits and expiry
323+
324+
## Server Accountability
325+
326+
Servers holding authorizations are responsible for:
327+
328+
- Secure storage of authorization data
329+
- Not exceeding authorized limits
330+
- Providing transaction records to payers
331+
- Honoring revocation requests
332+
333+
# IANA Considerations
334+
335+
## Payment Intent Registration
336+
337+
This document registers the "authorize" intent in the "HTTP Payment
338+
Intents" registry established by {{I-D.httpauth-payment}}:
339+
340+
| Intent | Description | Reference |
341+
|--------|-------------|-----------|
342+
| `authorize` | Pre-authorization for future charges | This document |

0 commit comments

Comments
 (0)