# PhoneAgent — Full Reference

{
  "openapi": "3.1.0",
  "info": {
    "title": "PhoneAgent",
    "version": "0.1.0",
    "summary": "Temporary exclusive phone numbers for AI agents.",
    "description": "Pay via x402 (USDC on Base L2). Charged only when an SMS actually arrives; silent rentals settle 0 and incur no on-chain transaction. No signup, no API keys — discover and pay purely over HTTP 402.",
    "license": {
      "name": "Proprietary"
    },
    "contact": {
      "name": "PhoneAgent"
    }
  },
  "servers": [
    {
      "url": "https://api.phoneagent.xyz"
    }
  ],
  "x-x402": {
    "scheme": "exact",
    "network": "base",
    "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    "payTo": "0xF6705e3dA2d2f98aFd3944E4a6B0D6Ca931e576A"
  },
  "paths": {
    "/countries": {
      "get": {
        "operationId": "listCountries",
        "summary": "List available countries and per-service pricing.",
        "description": "Returns the live storefront. Each country entry lists which services are offered, at which SKU ($1 activate or $2 activate_premium), and the current inventory pool — higher pool = better deliverability. Paid discovery: 0.01 USDC per call on Base, settled inline. The dust price exists to register this resource in CDP Bazaar's discovery index — agents barely notice the cost.",
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "X-Payment-Response": {
                "description": "Base64-encoded `{tx, network}` of the on-chain settlement that paid for this call.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CountryList"
                },
                "examples": {
                  "snapshot": {
                    "value": [
                      {
                        "code": "US",
                        "name": "United States",
                        "services": [
                          {
                            "code": "go",
                            "name": "Google / Gmail",
                            "mode": "activate",
                            "price_usdc": 1,
                            "pool": 265876
                          },
                          {
                            "code": "ig",
                            "name": "Instagram",
                            "mode": "activate",
                            "price_usdc": 1,
                            "pool": 214368
                          },
                          {
                            "code": "tg",
                            "name": "Telegram",
                            "mode": "activate_premium",
                            "price_usdc": 2,
                            "pool": 40123
                          }
                        ]
                      }
                    ]
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required (or payment invalid). Body is the same x402 PaymentRequirements shape as /rent, priced at 0.01 USDC.",
            "headers": {
              "X-Payment-Required": {
                "description": "Base64-encoded PaymentRequirements (same as body).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentRequired"
                }
              }
            }
          },
          "502": {
            "description": "Settlement failed at the facilitator."
          }
        }
      }
    },
    "/rent": {
      "post": {
        "operationId": "rentNumber",
        "summary": "Rent one exclusive phone number.",
        "description": "Returns 402 Payment Required with x402 `exact` PaymentRequirements. After the client signs an EIP-3009 transferWithAuthorization for the quoted price ($1 activate / $2 activate_premium) and re-POSTs with X-Payment, we verify the signature with the facilitator, reserve a number upstream, and return the rental. We only call /settle (capture funds) when an SMS actually arrives; otherwise we never call settle and the authorization expires unused — the client is never charged.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RentRequest"
              },
              "examples": {
                "basic": {
                  "value": {
                    "country": "US",
                    "service": "go",
                    "duration_minutes": 10
                  }
                },
                "withWebhook": {
                  "value": {
                    "country": "ID",
                    "service": "other",
                    "duration_minutes": 15,
                    "webhook_url": "https://agent.example.com/sms-hook"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Number rented (after successful payment verification).",
            "headers": {
              "X-Payment-Response": {
                "description": "Base64-encoded receipt. With scheme `exact` the server holds the signed authorization and only calls settle if an SMS arrives; no settlement tx exists yet when this response is returned.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Rental"
                },
                "example": {
                  "rental_id": "r_01HW8Z2KQ7",
                  "phone_number": "14155551234",
                  "token": "tok_7fG3",
                  "expires_at": "2026-04-24T18:35:00Z",
                  "mode": "activate"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request or service×country not offered."
          },
          "402": {
            "description": "Payment required (or payment invalid).",
            "headers": {
              "X-Payment-Required": {
                "description": "Base64-encoded PaymentRequirements (same as body).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentRequired"
                }
              }
            }
          },
          "503": {
            "description": "No inventory available for this combination."
          }
        }
      }
    },
    "/sms/{rental_id}": {
      "get": {
        "operationId": "getSms",
        "summary": "Fetch received SMS (short or long poll).",
        "description": "Pass `wait=1..25` to long-poll — the connection is held up to that many seconds, returning as soon as an SMS lands. `wait=0` or omitted returns current list immediately. `token` is returned at rent time.",
        "parameters": [
          {
            "name": "rental_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "wait",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 25
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Array of SMS messages (possibly empty).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SmsList"
                },
                "example": [
                  {
                    "from": "VERIFY",
                    "text": "Your code is 478392",
                    "receivedAt": 1714000100000
                  }
                ]
              }
            }
          },
          "404": {
            "description": "Rental not found or token invalid."
          }
        }
      }
    },
    "/rentals/{rental_id}": {
      "get": {
        "operationId": "getRentalStatus",
        "summary": "Get rental status.",
        "parameters": [
          {
            "name": "rental_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Rental status.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RentalStatus"
                },
                "example": {
                  "rental_id": "r_01HW8Z2KQ7",
                  "status": "settled",
                  "mode": "activate",
                  "service": "go",
                  "country": "US",
                  "phone_number": "14155551234",
                  "created_at": "2026-04-24T18:20:00Z",
                  "expires_at": "2026-04-24T18:40:00Z",
                  "sms_received": true,
                  "settle_tx_hash": "0xebd4ec367a…"
                }
              }
            }
          },
          "404": {
            "description": "Rental not found."
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ServiceCode": {
        "type": "string",
        "enum": [
          "tg",
          "wa",
          "go",
          "fb",
          "ig",
          "tw",
          "ds",
          "mm",
          "wx",
          "pm",
          "other"
        ],
        "description": "One of the supported services: `tg` — Telegram, `wa` — WhatsApp, `go` — Google / Gmail, `fb` — Facebook, `ig` — Instagram, `tw` — Twitter / X, `ds` — Discord, `mm` — Microsoft, `wx` — Apple / iCloud, `pm` — PayPal, `other` — Any other service."
      },
      "Mode": {
        "type": "string",
        "enum": [
          "activate",
          "activate_premium"
        ]
      },
      "RentRequest": {
        "type": "object",
        "required": [
          "country",
          "service",
          "duration_minutes"
        ],
        "properties": {
          "country": {
            "type": "string",
            "description": "ISO 3166-1 alpha-2 country code. Must be a code offered right now — see /countries.",
            "enum": [
              "UA",
              "KZ",
              "CN",
              "PH",
              "MM",
              "ID",
              "MY",
              "KE",
              "TZ",
              "VN",
              "US",
              "IL",
              "HK",
              "PL",
              "GB",
              "MG",
              "NG",
              "EG",
              "IN",
              "IE",
              "KH",
              "LA",
              "RS",
              "ZA",
              "RO",
              "CO",
              "EE",
              "CA",
              "MA",
              "GH",
              "AR",
              "UZ",
              "DE",
              "LT",
              "HR",
              "SE",
              "NL",
              "LV",
              "AT",
              "BY",
              "TH",
              "SA",
              "MX",
              "TW",
              "ES",
              "BD",
              "CZ",
              "LK",
              "PE",
              "PK",
              "NZ",
              "BR",
              "KR",
              "MN",
              "NP",
              "CY",
              "FR",
              "HU",
              "BG",
              "FI",
              "IT",
              "PY",
              "AE",
              "NO",
              "PT",
              "GE",
              "MD",
              "KW",
              "AM",
              "AU",
              "CH",
              "DK",
              "SG"
            ]
          },
          "service": {
            "$ref": "#/components/schemas/ServiceCode"
          },
          "duration_minutes": {
            "type": "integer",
            "minimum": 1,
            "maximum": 20,
            "description": "Minutes to wait for SMS. v1 serves single-SMS activations up to 20 minutes (smsfast's upstream activation window)."
          },
          "webhook_url": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "Rental": {
        "type": "object",
        "properties": {
          "rental_id": {
            "type": "string"
          },
          "phone_number": {
            "type": "string",
            "description": "E.164 number without the leading `+` (e.g. `442026022220` for +44 20 2602 2220)."
          },
          "token": {
            "type": "string",
            "description": "Bearer token for GET /sms/{rental_id}."
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "mode": {
            "$ref": "#/components/schemas/Mode"
          }
        }
      },
      "CountryList": {
        "type": "array",
        "items": {
          "$ref": "#/components/schemas/CountryEntry"
        }
      },
      "CountryEntry": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "description": "ISO 3166-1 alpha-2."
          },
          "name": {
            "type": "string"
          },
          "services": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "code": {
                  "$ref": "#/components/schemas/ServiceCode"
                },
                "name": {
                  "type": "string"
                },
                "mode": {
                  "$ref": "#/components/schemas/Mode"
                },
                "price_usdc": {
                  "type": "number"
                },
                "pool": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "Sms": {
        "type": "object",
        "properties": {
          "from": {
            "type": "string"
          },
          "text": {
            "type": "string"
          },
          "receivedAt": {
            "type": "integer"
          }
        }
      },
      "SmsList": {
        "type": "array",
        "items": {
          "$ref": "#/components/schemas/Sms"
        }
      },
      "RentalStatus": {
        "type": "object",
        "properties": {
          "rental_id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "created",
              "paid",
              "active",
              "settled",
              "expired",
              "released"
            ]
          },
          "mode": {
            "$ref": "#/components/schemas/Mode"
          },
          "service": {
            "$ref": "#/components/schemas/ServiceCode"
          },
          "country": {
            "type": "string"
          },
          "phone_number": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "sms_received": {
            "type": "boolean"
          },
          "settle_tx_hash": {
            "type": [
              "string",
              "null"
            ],
            "description": "USDC transfer tx hash on Base (set when SMS arrived and we called /settle). Null on silent rentals — the EIP-3009 authorization expires unused with no on-chain footprint."
          }
        }
      },
      "PaymentRequired": {
        "type": "object",
        "properties": {
          "x402Version": {
            "type": "integer"
          },
          "accepts": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "scheme": {
                  "type": "string",
                  "example": "exact"
                },
                "network": {
                  "type": "string",
                  "example": "base"
                },
                "maxAmountRequired": {
                  "type": "string",
                  "example": "1000000",
                  "description": "Exact amount in USDC base units (6 decimals). $1 for activate, $2 for activate_premium."
                },
                "resource": {
                  "type": "string"
                },
                "description": {
                  "type": "string"
                },
                "mimeType": {
                  "type": "string"
                },
                "payTo": {
                  "type": "string"
                },
                "maxTimeoutSeconds": {
                  "type": "integer",
                  "description": "EIP-3009 validBefore window (seconds). Covers the rental duration + 5 min buffer."
                },
                "asset": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  }
}
