
Gen Paylink Govilo
- 3k installs
- 1 repo stars
- Updated February 13, 2026
- hau823823/gen-paylink-govilo
gen-paylink-govilo is an agent skill that uploads files to Govilo and creates USDC-priced crypto unlock links via the Bot API.
About
Gen Paylink Govilo is an agent skill that turns ZIP files, folders, or individual files into paid crypto unlock links through the Govilo Bot API. Before running, the agent must ask the user for product title, USDC price, and optional description rather than guessing values. The uv-based create-link CLI validates GOVILO_API_KEY and SELLER_ADDRESS from a dedicated .env.govilo file, auto-packages non-ZIP inputs, presigns an upload, PUTs the archive to R2, and creates the unlock item. JSON stdout reports ok status with unlock_url on success and exit code 1 on failure. Limits are twenty megabytes and twenty files per ZIP. The workflow covers config validation, packaging, POST presign, PUT upload, and POST items. Seller address defaults from SELLER_ADDRESS or --address on Base chain. Setup references guide registration at govilo.xyz and warns never to point --env-file at a project .env containing unrelated secrets.
- create-link CLI packages ZIP, folder, or file inputs into Govilo paid unlock URLs.
- Bot API flow: presign upload, PUT to R2, then POST items for unlock_url.
- Requires GOVILO_API_KEY and Base-chain SELLER_ADDRESS in a dedicated .env.govilo.
- Agent must ask user for title, USDC price, and description before executing.
- Hard limits: 20 MB ZIP size and 20 files per archive.
Gen Paylink Govilo by the numbers
- 3,019 all-time installs (skills.sh)
- Ranked #151 of 2,715 Automation & Workflows skills by installs in the Skillselion catalog
- Security screen: CRITICAL risk (skills.sh audit)
- Data as of Aug 5, 2026 (Skillselion catalog sync)
gen-paylink-govilo capabilities & compatibility
- Capabilities
- input packaging for zip, folder, or repeatable f · govilo bot api presign, r2 upload, and item crea · usdc pricing with base chain seller address · json ok or failure output with dedicated env fil · setup and registration walkthrough via reference
- Use cases
- orchestration · email
- Runs
- Runs locally
- Pricing
- Bring your own API key
npx skills add https://github.com/hau823823/gen-paylink-govilo --skill gen-paylink-goviloAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 3k |
|---|---|
| repo stars | ★ 1 |
| Security audit | 1 / 3 scanners passed |
| Last updated | February 13, 2026 |
| Repository | hau823823/gen-paylink-govilo ↗ |
How do I automate uploading a ZIP or folder to Govilo and generate a paid unlock link with crypto checkout?
Package files into Govilo paid unlock links via Bot API presign upload, R2 PUT, and item creation with USDC pricing on Base.
Who is it for?
Developers selling digital files who want one-command Govilo unlock link creation from folders or ZIPs.
Skip if: Skip when GOVILO_API_KEY or seller wallet is unavailable and the user has not registered at govilo.xyz.
When should I use this skill?
User wants a Govilo unlock link, paid file download, or Bot API presign upload workflow.
What you get
JSON result with unlock_url after presigned R2 upload and Govilo item creation on Base chain.
- Govilo unlock link
- uploaded file on Govilo R2
By the numbers
- [object Object]
- [object Object]
- [object Object]
Files
Govilo To Go
Turn any file into a paid unlock link — one command to package, upload, and collect crypto payments. The last mile of automation: from creation to monetization.
Before Running
Always ask the user for these values before executing the CLI — never guess or use placeholders:
1. title — What is the product name? 2. price — How much to charge (in USDC)? 3. description — Short description of the product (optional, but always ask)
CLI Command
Requires uv. See references/setup-guide.md for install instructions.
Run from this skill's base directory. Use a dedicated env file containing only GOVILO_API_KEY (and optionally SELLER_ADDRESS). Never point --env-file at a project .env that contains unrelated secrets.
cd <skill_base_directory>
uv run --env-file <path_to>/.env.govilo create-link \
--input <path> \
--title "Product Name" \
--price "5.00" \
--address "0x..." \
--description "optional"If no .env.govilo exists, create one before running:
GOVILO_API_KEY=sk_live_xxx
SELLER_ADDRESS=0x...--input accepts ZIP file, folder, or individual files (repeatable). Non-ZIP inputs are auto-packaged.
All output is JSON {"ok": true/false, ...} with exit code 1 on failure.
Parameters
| Param | Required | Source | Description |
|---|---|---|---|
--input | Yes | CLI (repeatable) | ZIP, folder, or file paths |
--title | Yes | CLI | Product title |
--price | Yes | CLI | Price in USDC |
--address | No | CLI > SELLER_ADDRESS env | Seller EVM wallet |
--description | No | CLI | Product description |
Workflow
1. Validate config (API Key + seller address) 2. Package inputs → ZIP (if not already ZIP) 3. POST /api/v1/bot/uploads/presign → get upload_url + session_id 4. PUT upload_url → upload ZIP to R2 5. POST /api/v1/bot/items → get unlock_url
File Limits
- Max ZIP size: 20 MB
- Max files in ZIP: 20
Setup
Two values are required:
| Variable | Required | Description |
|---|---|---|
GOVILO_API_KEY | Yes | Bot API key from [govilo.xyz][] |
SELLER_ADDRESS | Yes* | EVM wallet address on Base chain |
[govilo.xyz]: https://govilo.xyz/
*SELLER_ADDRESS can also be passed via --address CLI parameter.
See references/setup-guide.md for step-by-step registration and wallet setup instructions.
API Reference
See references/bot-api-quick-ref.md for Bot API endpoints and error codes.
[project]
name = "govilo-to-go"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = ["requests"]
[project.scripts]
create-link = "scripts.workflow_create:main"
[project.optional-dependencies]
dev = ["pytest"]
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
packages = ["scripts"]
[tool.pytest.ini_options]
testpaths = ["tests"]
Bot API Quick Reference
Base URL: https://api.unlock.govilo.xyz
Endpoints
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /api/v1/bot/uploads/presign | Bearer sk_live_xxx | Get presigned upload URL |
| POST | /api/v1/bot/items | Bearer sk_live_xxx | Confirm upload and create item |
Presign Request
POST /api/v1/bot/uploads/presign
{"seller_address": "0x..."}Response: upload_url, session_id, object_path, expires_at
Upload
PUT <upload_url>
Content-Type: application/zip
Body: <raw ZIP bytes>Create Item Request
POST /api/v1/bot/items
{"session_id": "...", "title": "...", "price": "5.00", "description": "..."}Response: id, unlock_url, file_count, total_size, upload_status
Error Codes
| Code | HTTP | Message |
|---|---|---|
| 809108001 | 401 | invalid api key |
| 809108002 | 401 | api key has been revoked |
| 809108003 | 401 | api key has expired |
| 809108005 | 429 | daily api key usage limit exceeded |
| 809108006 | 429 | api key rate limit exceeded |
| 809104001 | 404 | upload session not found |
| 809104002 | 410 | upload session expired |
| 809104003 | 404 | file not found |
Setup Guide
Prerequisites
This skill requires uv — a fast Python package manager and runner.
Install uv
macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
Windows
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
Or via Homebrew
brew install uv
uv run automatically resolves Python >=3.11 and the requests dependency from pyproject.toml — no manual pip install needed.
Required Values
Two values are required before using this tool:
GOVILO_API_KEY— Bot API authentication tokenSELLER_ADDRESS— Your wallet address on Base chain
1. API Key
Get Your API Key
1. Go to https://govilo.xyz/ 2. Sign up for an account (Gmail auth login) 3. Open the left sidebar menu → click Settings 4. Scroll to the API Key section → click Manage API Key 5. Create a new key and copy it (format: sk_live_xxx)
Configure
Create a dedicated env file (e.g. .env.govilo) containing only Govilo credentials:
.env.govilo
GOVILO_API_KEY=sk_live_xxx
Important: Do not use a shared project .env that may contain unrelated secrets.Always use a dedicated file like .env.govilo to avoid accidental leakage.Verify
cd skills/gen-paylink-govilo uv run --env-file .env.govilo create-link --help
If the key is missing or invalid, the tool outputs:
{"ok": false, "error": "API Key not configured. ..."}
2. Seller Address
Requirements
- Chain: Base (Base Mainnet only, Chain ID: 8453)
- Format: EVM address —
0x+ 40 hex characters - Example:
0x1234567890abcdef1234567890abcdef12345678
Get Your Address
MetaMask:
1. Install MetaMask browser extension (https://metamask.io/) 2. Create or import a wallet 3. Switch network to Base (add if not listed: Chain ID 8453, RPC https://mainnet.base.org) 4. Click the account name at the top to copy your address
Coinbase Wallet:
1. Install Coinbase Wallet (https://www.coinbase.com/wallet) 2. Create or import a wallet 3. Switch network to Base 4. Tap Receive → copy your address
Configure
Option A — Environment variable (recommended for repeated use):
Add to your .env.govilo file:
SELLER_ADDRESS=0xYourWalletAddress
Option B — CLI parameter (per-command override):
create-link --address "0xYourWalletAddress" ...
CLI --address takes priority over SELLER_ADDRESS env var.
Tip: You can also set a Default Payout Address on the Govilo website
(Settings → Default Payout Address → paste your 0x... address → Save).This address is pre-filled when creating new links on the web UI, but the CLI
still requiresSELLER_ADDRESSenv var or--addressparameter.
from pathlib import Path
import requests
class ApiError(Exception):
def __init__(self, message: str, code: int | None = None):
super().__init__(message)
self.code = code
class GoviloClient:
def __init__(self, api_key: str, base_url: str):
self._base_url = base_url.rstrip("/")
self._headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
}
def _check_response(self, resp: requests.Response) -> dict:
body = resp.json()
if body.get("code", 0) != 0:
raise ApiError(body.get("msg", "unknown error"), body.get("code"))
return body["data"]
def presign(self, seller_address: str) -> dict:
resp = requests.post(
f"{self._base_url}/api/v1/bot/uploads/presign",
headers=self._headers,
json={"seller_address": seller_address},
)
return self._check_response(resp)
def upload(self, upload_url: str, zip_path: Path) -> None:
with open(zip_path, "rb") as f:
resp = requests.put(
upload_url,
headers={"Content-Type": "application/zip"},
data=f,
)
if resp.status_code != 200:
raise ApiError(f"Upload failed: HTTP {resp.status_code}")
def create_item(
self,
session_id: str,
title: str,
price: str,
description: str = "",
) -> dict:
resp = requests.post(
f"{self._base_url}/api/v1/bot/items",
headers=self._headers,
json={
"session_id": session_id,
"title": title,
"price": price,
"description": description,
},
)
return self._check_response(resp)
from dataclasses import dataclass
import os
BASE_URL = "https://api.unlock.govilo.xyz"
class ConfigError(Exception):
pass
@dataclass(frozen=True)
class Config:
api_key: str
seller_address: str
base_url: str = BASE_URL
def load_config(
cli_api_key: str | None = None,
cli_address: str | None = None,
) -> Config:
api_key = cli_api_key or os.environ.get("GOVILO_API_KEY")
if not api_key:
raise ConfigError(
"API Key not configured. See references/setup-guide.md for registration steps. "
"Register at https://govilo.xyz/ then set GOVILO_API_KEY=sk_live_xxx"
)
seller_address = cli_address or os.environ.get("SELLER_ADDRESS")
if not seller_address:
raise ConfigError(
"Seller address required (Base chain). Use --address 0x... or set SELLER_ADDRESS env var. "
"See references/setup-guide.md for wallet setup"
)
return Config(api_key=api_key, seller_address=seller_address)
import tempfile
import zipfile
from pathlib import Path
MAX_ZIP_SIZE = 20 * 1024 * 1024 # 20 MB
MAX_FILE_COUNT = 20
class PackageError(Exception):
pass
def _validate_zip(zp: Path) -> None:
if zp.stat().st_size > MAX_ZIP_SIZE:
raise PackageError(f"ZIP file exceeds 20 MB limit")
with zipfile.ZipFile(zp) as zf:
if len(zf.namelist()) > MAX_FILE_COUNT:
raise PackageError(f"ZIP contains more than {MAX_FILE_COUNT} files")
def _zip_paths(paths: list[Path], dest: Path) -> None:
with zipfile.ZipFile(dest, "w", zipfile.ZIP_DEFLATED) as zf:
for p in paths:
zf.write(p, p.name)
def package(inputs: list[str]) -> Path:
paths = [Path(p) for p in inputs]
for p in paths:
if not p.exists():
raise PackageError(f"Path not found: {p}")
# Single .zip file — passthrough
if len(paths) == 1 and paths[0].suffix == ".zip":
_validate_zip(paths[0])
return paths[0]
# Single directory — zip its contents
if len(paths) == 1 and paths[0].is_dir():
files = [f for f in paths[0].rglob("*") if f.is_file()]
if len(files) > MAX_FILE_COUNT:
raise PackageError(f"Directory contains more than {MAX_FILE_COUNT} files")
dest = Path(tempfile.mktemp(suffix=".zip"))
with zipfile.ZipFile(dest, "w", zipfile.ZIP_DEFLATED) as zf:
for f in files:
zf.write(f, f.relative_to(paths[0]))
_validate_zip(dest)
return dest
# Multiple files — zip them together
if len(paths) > MAX_FILE_COUNT:
raise PackageError(f"Input exceeds {MAX_FILE_COUNT} files limit")
dest = Path(tempfile.mktemp(suffix=".zip"))
_zip_paths(paths, dest)
_validate_zip(dest)
return dest
import argparse
import json
import sys
from pathlib import Path
from scripts.api_client import GoviloClient, ApiError
from scripts.config import load_config, ConfigError
from scripts.packager import package, PackageError
def _output(data: dict) -> None:
print(json.dumps(data, ensure_ascii=False))
def _fail(error: str, code: int | None = None) -> None:
out = {"ok": False, "error": error}
if code is not None:
out["code"] = code
_output(out)
sys.exit(1)
def main() -> None:
parser = argparse.ArgumentParser(description="Upload files and create Govilo unlock link")
parser.add_argument("--input", required=True, action="append", dest="inputs", help="ZIP, folder, or file path (repeatable)")
parser.add_argument("--title", required=True, help="Product title")
parser.add_argument("--price", required=True, help="Price in USDC (e.g. 5.00)")
parser.add_argument("--address", default=None, help="Seller EVM wallet address (overrides SELLER_ADDRESS env)")
parser.add_argument("--description", default="", help="Product description")
args = parser.parse_args()
try:
cfg = load_config(cli_api_key=None, cli_address=args.address)
except ConfigError as e:
_fail(str(e))
try:
zip_path = package(args.inputs)
except PackageError as e:
_fail(str(e))
is_temp = zip_path not in [Path(p) for p in args.inputs]
try:
client = GoviloClient(api_key=cfg.api_key, base_url=cfg.base_url)
try:
presign_data = client.presign(cfg.seller_address)
client.upload(presign_data["upload_url"], zip_path)
item_data = client.create_item(
session_id=presign_data["session_id"],
title=args.title,
price=args.price,
description=args.description,
)
except ApiError as e:
_fail(str(e), code=e.code)
_output({
"ok": True,
"unlock_url": item_data["unlock_url"],
"item_id": item_data["id"],
"file_count": item_data["file_count"],
"total_size": item_data["total_size"],
})
finally:
if is_temp:
zip_path.unlink(missing_ok=True)
Related skills
Forks & variants (1)
Gen Paylink Govilo has 1 known copy in the catalog totaling 3k installs. They canonicalize to this original listing.
- hau823823 - 3k installs
FAQ
What environment variables are required?
GOVILO_API_KEY is required and SELLER_ADDRESS or --address must be a Base-chain EVM wallet.
What are the file size limits?
Maximum ZIP size is 20 MB with up to 20 files inside the archive.
Must the agent ask before running?
Yes. Title, USDC price, and optional description must come from the user, never placeholders.
Is Gen Paylink Govilo safe to install?
skills.sh reports 1 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.