{"id":50266578,"url":"https://github.com/second-state/payment-link","last_synced_at":"2026-05-27T14:11:35.791Z","repository":{"id":335759914,"uuid":"1146937513","full_name":"second-state/payment-link","owner":"second-state","description":null,"archived":false,"fork":false,"pushed_at":"2026-03-06T05:50:33.000Z","size":94,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-06T09:58:54.863Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://link.x402labs.dev","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/second-state.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-31T23:20:25.000Z","updated_at":"2026-03-06T05:50:41.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/second-state/payment-link","commit_stats":null,"previous_names":["second-state/payment-link"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/second-state/payment-link","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/second-state%2Fpayment-link","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/second-state%2Fpayment-link/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/second-state%2Fpayment-link/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/second-state%2Fpayment-link/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/second-state","download_url":"https://codeload.github.com/second-state/payment-link/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/second-state%2Fpayment-link/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33569222,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-27T02:00:06.184Z","response_time":53,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-05-27T14:11:34.898Z","updated_at":"2026-05-27T14:11:35.785Z","avatar_url":"https://github.com/second-state.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Payment Link Service\n\nA Python web service for creating x402-protected payment links. This service allows you to generate unique payment URLs that require cryptocurrency payments before granting access. Supports multiple ERC-3009 tokens (USDC, KII, etc.) via a configurable `tokens.yaml`.\n\n## Quick Start with Docker\n\n1. **Configure environment and tokens:**\n\n```bash\n# Pick a network config\ncp .env.example.base-sepolia .env      # testnet\n# cp .env.example.base-mainnet .env    # mainnet\n\n# Pick a token config\ncp tokens.yaml.usdc tokens.yaml              # USDC only\n# cp tokens.yaml.kii tokens.yaml             # KII only\n# cp tokens.yaml.multiple-token tokens.yaml  # USDC + KII\n```\n\n2. **Build the image:**\n\n```bash\ndocker build -t payment-link .\n```\n\n3. **Run the container:**\n\n```bash\ntouch payments.db\ndocker run -d \\\n  -p 8000:8000 \\\n  -v $(pwd)/payments.db:/app/payments.db \\\n  --env-file .env \\\n  --name payment-link \\\n  payment-link\n```\n\nThe `touch` command creates an empty database file, and the `-v` flag mounts it into the container for persistence.\n\n4. **Verify it's running:**\n\n```bash\ncurl http://localhost:8000/\n```\n\n## Token Configuration\n\nAvailable tokens are defined in `tokens.yaml`. Each token specifies its contract address per network; tokens without an address on the active network are automatically excluded.\n\nExample files:\n\n| File | Contents |\n|------|----------|\n| `tokens.yaml.usdc` | USDC (Base, Base Sepolia) |\n| `tokens.yaml.kii` | KII (Base, Base Sepolia) |\n| `tokens.yaml.multiple-token` | USDC + KII |\n\nFormat:\n\n```yaml\ntokens:\n  usdc:\n    symbol: USDC\n    name: USD Coin\n    decimals: 6\n    addresses:\n      base: \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\"\n      base-sepolia: \"0x036CbD53842c5426634e7929541eC2318f3dCF7e\"\n```\n\n## Environment Variables\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `NETWORK` | `base-sepolia` | Blockchain network (`base-sepolia` for testnet, `base` for mainnet) |\n| `APP_BASE_URL` | `http://localhost:8000` | Public base URL for generated payment links |\n| `APP_NAME` | `Payment Link Service` | Service name displayed in payment UI |\n| `APP_LOGO` | `/static/logo.png` | Logo URL for payment UI |\n| `FACILITATOR_URL` | `https://x402f1.secondstate.io` | x402 facilitator service endpoint |\n| `MAX_TIMEOUT_SECONDS` | `60` | Payment timeout in seconds |\n| `CHAIN_ID` | `84532` | Chain ID for the network |\n| `EXPLORER_URL` | `https://sepolia.basescan.org/tx/` | Block explorer URL prefix |\n| `DATABASE_PATH` | `payments.db` | SQLite database file path |\n\n## API Endpoints\n\n### GET /\n\nServes the web UI for creating and paying payment links.\n\nOpen in a browser to access the interactive payment interface.\n\n---\n\n### GET /config\n\nReturns available tokens and chain configuration for the current network.\n\n```json\n{\n  \"network\": \"base-sepolia\",\n  \"chainId\": 84532,\n  \"explorerUrl\": \"https://sepolia.basescan.org/tx/\",\n  \"tokens\": [\n    {\n      \"id\": \"usdc\",\n      \"symbol\": \"USDC\",\n      \"name\": \"USD Coin\",\n      \"decimals\": 6,\n      \"address\": \"0x036CbD53842c5426634e7929541eC2318f3dCF7e\"\n    }\n  ]\n}\n```\n\n---\n\n### GET /create-payment-link\n\nCreates a new payment link with a unique ID.\n\n**Query Parameters:**\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `amount` | float | Yes | — | Payment amount (must be \u003e 0) |\n| `receiver` | string | Yes | — | Blockchain address to receive the payment |\n| `token` | string | No | `usdc` | Token ID (e.g. `usdc`, `kii`) |\n\n**Example Request:**\n```bash\ncurl \"http://localhost:8000/create-payment-link?amount=0.01\u0026receiver=0x1234567890abcdef1234567890abcdef12345678\u0026token=usdc\"\n```\n\n**Response:**\n```json\n{\n  \"payment_id\": \"550e8400-e29b-41d4-a716-446655440000\",\n  \"payment_url\": \"http://localhost:8000/pay/550e8400-e29b-41d4-a716-446655440000\",\n  \"amount\": \"0.01\",\n  \"receiver\": \"0x1234567890abcdef1234567890abcdef12345678\",\n  \"token\": \"usdc\"\n}\n```\n\n---\n\n### GET /pay/{payment_id}\n\nx402-protected payment endpoint. This endpoint handles the payment flow.\n\n**Path Parameters:**\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `payment_id` | string | Unique payment identifier from `/create-payment-link` |\n\n**Behavior:**\n\n1. **If payment is pending (no X-Payment header):** Returns HTTP 402 with payment requirements\n2. **If payment is pending (with valid X-Payment header):** Processes payment and returns success\n3. **If payment is already completed:** Returns the transaction details\n\n**Response (Payment Required - 402):**\n\nFor API clients (non-browser):\n```json\n{\n  \"x402Version\": 1,\n  \"accepts\": [...],\n  \"error\": \"No X-PAYMENT header provided\"\n}\n```\n\nFor browsers: Returns an HTML payment page.\n\n**Response (Payment Successful - 200):**\n```json\n{\n  \"status\": \"paid\",\n  \"tx\": \"0x1234567890abcdef...\"\n}\n```\n\n**Response (Not Found - 404):**\n```json\n{\n  \"error\": \"Payment not found\"\n}\n```\n\n---\n\n### GET /status/{payment_id}\n\nCheck the current status of a payment.\n\n**Path Parameters:**\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `payment_id` | string | Unique payment identifier |\n\n**Example Request:**\n```bash\ncurl \"http://localhost:8000/status/550e8400-e29b-41d4-a716-446655440000\"\n```\n\n**Response (Pending):**\n```json\n{\n  \"payment_id\": \"550e8400-e29b-41d4-a716-446655440000\",\n  \"amount\": 0.01,\n  \"paid\": false,\n  \"tx\": null\n}\n```\n\n**Response (Paid):**\n```json\n{\n  \"payment_id\": \"550e8400-e29b-41d4-a716-446655440000\",\n  \"amount\": 0.01,\n  \"paid\": true,\n  \"tx\": \"0x1234567890abcdef...\"\n}\n```\n\n**Response (Not Found - 404):**\n```json\n{\n  \"error\": \"Payment not found\"\n}\n```\n\n## Usage Example\n\n1. **Create a payment link:**\n\n```bash\ncurl \"http://localhost:8000/create-payment-link?amount=0.01\u0026receiver=0x1234567890abcdef1234567890abcdef12345678\u0026token=usdc\"\n```\n\n2. **Share the `payment_url` with the payer.** When they open it in a browser, they'll see a payment interface.\n\n3. **After payment, the payer can reload the page** to see the confirmation with the transaction hash.\n\n4. **Check payment status programmatically:**\n\n```bash\ncurl \"http://localhost:8000/status/{payment_id}\"\n```\n\n## Development Setup\n\nFor local development without Docker:\n\n1. **Install dependencies:**\n\n```bash\nuv sync\n```\n\n2. **Configure environment:**\n\n```bash\ncp .env.example.base-sepolia .env\ncp tokens.yaml.multiple-token tokens.yaml\n```\n\n3. **Run the server:**\n\n```bash\nuv run python main.py\n```\n\n4. **Run tests:**\n\n```bash\nuv run pytest tests/ -v\n```\n\n## How x402 Works\n\nThe [x402 protocol](https://github.com/coinbase/x402) enables HTTP-native payments:\n\n1. Client requests a protected resource\n2. Server responds with HTTP 402 and payment requirements\n3. Client makes a blockchain payment and includes proof in the `X-Payment` header\n4. Server verifies the payment and grants access\n\nThis service supports any ERC-3009 (TransferWithAuthorization) token on Base / Base Sepolia.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsecond-state%2Fpayment-link","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsecond-state%2Fpayment-link","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsecond-state%2Fpayment-link/lists"}