Upload Endpoint (PUT)

Table of contents

  1. Endpoint
  2. URL Parameters
  3. Request Headers
    1. Required
    2. Payment (Required for actual upload)
    3. Optional
  4. TTL (Time-To-Live)
  5. Examples
    1. Basic Upload
    2. Upload with Custom TTL
    3. Upload Binary File
  6. Response
    1. Success (200 OK)
    2. Response Fields
    3. Response Headers
  7. Payment Required (402)
  8. Accessing Uploaded Content
    1. S3 Path
    2. IPFS CID
    3. Gateway URL
  9. Content Expiration
  10. Overwriting
  11. Errors

Endpoint

PUT /:bucket/:key

Upload content with x402 payment.


URL Parameters

Parameter Description
bucket Storage bucket name
key Object key (filename/path)

Example: PUT /mybucket/images/photo.jpg


Request Headers

Required

Header Description
Content-Type MIME type of content
Content-Length Size in bytes

Payment (Required for actual upload)

Header Description
X-PAYMENT Base64-encoded signed payment

Or alternatively:

Payment-Authorization: x402 <base64-payload>

Optional

Header Default Description
X-Fula-TTL 3600 Storage duration in seconds

You can also use X-TTL-Seconds.


TTL (Time-To-Live)

Limit Value Duration
Minimum 60 1 minute
Default 3600 1 hour
Maximum 2592000 30 days

Values outside this range are clamped.


Examples

Basic Upload

# Step 1: Get payment requirements
curl -X PUT "https://x402.api.cloud.fx.land/mybucket/hello.txt" \
  -H "Content-Type: text/plain" \
  -H "Content-Length: 12" \
  -d "Hello World!"
# Returns 402

# Step 2: Upload with payment
curl -X PUT "https://x402.api.cloud.fx.land/mybucket/hello.txt" \
  -H "Content-Type: text/plain" \
  -H "Content-Length: 12" \
  -H "X-PAYMENT: <payment>" \
  -d "Hello World!"

Upload with Custom TTL

24 hours (86400 seconds):

curl -X PUT "https://x402.api.cloud.fx.land/mybucket/file.txt" \
  -H "Content-Type: text/plain" \
  -H "Content-Length: 1024" \
  -H "X-Fula-TTL: 86400" \
  -H "X-PAYMENT: <payment>" \
  -d "Content..."

Upload Binary File

curl -X PUT "https://x402.api.cloud.fx.land/mybucket/image.png" \
  -H "Content-Type: image/png" \
  -H "Content-Length: $(wc -c < image.png)" \
  -H "X-Fula-TTL: 3600" \
  -H "X-PAYMENT: <payment>" \
  --data-binary @image.png

Response

Success (200 OK)

{
  "success": true,
  "cid": "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG",
  "bucket": "mybucket",
  "key": "hello.txt",
  "size_bytes": 12,
  "expires_at": "2024-01-15T11:30:00.000Z",
  "tx_hash": "0xabc123...",
  "gateway_url": "https://ipfs.cloud.fx.land/ipfs/QmYwAP..."
}

Response Fields

Field Description
success Boolean success indicator
cid IPFS Content Identifier
bucket Storage bucket
key Object key
size_bytes Stored content size
expires_at Expiration timestamp (ISO 8601)
tx_hash Settlement transaction hash
gateway_url IPFS gateway URL

Response Headers

X-PAYMENT-RESPONSE: <base64-encoded settlement>

Decoded:

{
  "success": true,
  "transaction": "0xabc123...",
  "network": "eip155:324705682"
}

Payment Required (402)

When no payment header:

{
  "x402Version": 1,
  "accepts": [{
    "scheme": "exact",
    "network": "eip155:324705682",
    "maxAmountRequired": "10000",
    "payTo": "0x...",
    "asset": "eip155:324705682/erc20:0x...",
    "description": "Storage: 0.01 MB for 1 hour",
    "maxTimeoutSeconds": 300
  }],
  "error": "Payment Required"
}

Accessing Uploaded Content

After upload, access via:

S3 Path

https://s3.cloud.fx.land/:bucket/:key

IPFS CID

Use the cid from the response with any IPFS gateway.

Gateway URL

The gateway_url provides direct access.


Content Expiration

  • Content expires after TTL
  • Expired content is automatically deleted
  • CID remains valid but content unavailable
  • Re-upload with new payment to extend

Overwriting

Uploading to an existing key:

  • Requires new payment
  • Previous content immediately unavailable
  • CID changes if content differs

Errors

Status Meaning
402 Payment required/invalid
400 Invalid request format
413 Payload too large
500 Server error

See Error Handling for details.