Animated countdown GIF from the current UTC time to endDate. Always uncached. Supports 5 templates (default, minimal, neon, retro, corporate) and full customization: colors, fonts, dimensions, padding, cell padding, labels, dividers. Animates for `seconds` frames at `fps`.
/api/countdown/gifPAYMENT-SIGNATURE.The gif API is a pay-per-call countdown endpoint built for AI agents and autonomous software. Animated countdown GIF from the current UTC time to endDate.
There is no signup and no API key. An agent (or any HTTP client) hits the endpoint, receives an x402 "402 Payment Required" challenge, signs a sub-cent USDC payment on Base or Solana, and retries — the data comes back on the paid request. That makes it a drop-in gif data source for an agent tool-use loop, an MCP host, or a backend that needs countdown data on demand without onboarding to yet another vendor portal.
| Name | Type | Description |
|---|---|---|
endDaterequired | string | date-time |
template | string | one of: default | minimal | neon | retro | corporate |
seconds | integer | min 1 · max 60 |
fps | integer | min 1 · max 10 |
width | integer | min 200 · max 1600 |
height | integer | min 80 · max 800 |
padding | integer | min 0 · max 200 |
cellPadding | integer | min 0 · max 200 |
digitFontSize | integer | min 20 · max 300 |
labelFontSize | integer | min 6 · max 80 |
labelPaddingY | integer | min 0 · max 60 |
digitPaddingY | integer | min -60 · max 60 |
letterSpacing | number | min 0 · max 20 |
bg | string | max 40 chars |
fg | string | max 40 chars |
labelColor | string | max 40 chars |
dividerColor | string | max 40 chars |
digitFont | string | one of: mono | sans |
labelFont | string | one of: mono | sans |
digitWeight | string | one of: regular | bold |
showLabels | ||
showDays | ||
dividerChar | string | min 1 chars · max 3 chars |
expiredText | string | min 1 chars · max 30 chars |
labelDays | string | min 1 chars · max 12 chars |
labelHours | string | min 1 chars · max 12 chars |
labelMinutes | string | min 1 chars · max 12 chars |
labelSeconds | string | min 1 chars · max 12 chars |
# 1. Probe with no auth → 402 envelope with PaymentRequirements curl -sS 'https://2s.io/api/countdown/gif?endDate=example&template=default&seconds=1&fps=1&width=200&height=80&padding=0&cellPadding=0&digitFontSize=20&labelFontSize=6&labelPaddingY=0&digitPaddingY=-60&letterSpacing=0&bg=example&fg=example&labelColor=example÷rColor=example&digitFont=mono&labelFont=mono&digitWeight=regular&showLabels=false&showDays=false÷rChar=example&expiredText=example&labelDays=example&labelHours=example&labelMinutes=example&labelSeconds=example' # 2. Sign + retry with PAYMENT-SIGNATURE: curl -sS 'https://2s.io/api/countdown/gif?endDate=example&template=default&seconds=1&fps=1&width=200&height=80&padding=0&cellPadding=0&digitFontSize=20&labelFontSize=6&labelPaddingY=0&digitPaddingY=-60&letterSpacing=0&bg=example&fg=example&labelColor=example÷rColor=example&digitFont=mono&labelFont=mono&digitWeight=regular&showLabels=false&showDays=false÷rChar=example&expiredText=example&labelDays=example&labelHours=example&labelMinutes=example&labelSeconds=example' \ -H 'PAYMENT-SIGNATURE: <base64-json-payload>' # Or use the canonical runner (handles probe → sign → retry): # EVM_PRIVATE_KEY=0x... node --env-file=.env.local \ # --experimental-strip-types scripts/x402-pay.ts \ # 'https://2s.io/api/countdown/gif?endDate=example&template=default&seconds=1&fps=1&width=200&height=80&padding=0&cellPadding=0&digitFontSize=20&labelFontSize=6&labelPaddingY=0&digitPaddingY=-60&letterSpacing=0&bg=example&fg=example&labelColor=example÷rColor=example&digitFont=mono&labelFont=mono&digitWeight=regular&showLabels=false&showDays=false÷rChar=example&expiredText=example&labelDays=example&labelHours=example&labelMinutes=example&labelSeconds=example'
import { TwoS } from '@2sio/sdk'
const client = new TwoS({
privateKey: process.env.EVM_PRIVATE_KEY as `0x${string}`,
})
const result = await client.countdown.gif({
"endDate": "example",
"template": "default",
"seconds": 1,
"fps": 1,
"width": 200,
"height": 80,
"padding": 0,
"cellPadding": 0,
"digitFontSize": 20,
"labelFontSize": 6,
"labelPaddingY": 0,
"digitPaddingY": -60,
"letterSpacing": 0,
"bg": "example",
"fg": "example",
"labelColor": "example",
"dividerColor": "example",
"digitFont": "mono",
"labelFont": "mono",
"digitWeight": "regular",
"showLabels": false,
"showDays": false,
"dividerChar": "example",
"expiredText": "example",
"labelDays": "example",
"labelHours": "example",
"labelMinutes": "example",
"labelSeconds": "example"
})
console.log('endpoint:', result.endpoint)
console.log('cost:', result.costUsd, 'USDC')
console.log('tx:', result.settlement?.txHash)
console.log('data:', result.data)import os
from twosio import TwoS
client = TwoS(private_key=os.environ["EVM_PRIVATE_KEY"])
result = client.countdown.gif(endDate="example", template="default", seconds=1, fps=1, width=200, height=80, padding=0, cellPadding=0, digitFontSize=20, labelFontSize=6, labelPaddingY=0, digitPaddingY=-60, letterSpacing=0, bg="example", fg="example", labelColor="example", dividerColor="example", digitFont="mono", labelFont="mono", digitWeight="regular", showLabels=False, showDays=False, dividerChar="example", expiredText="example", labelDays="example", labelHours="example", labelMinutes="example", labelSeconds="example")
print("endpoint:", result.endpoint)
print("cost:", result.cost_usd, "USDC")
print("tx:", (result.settlement or {}).get("tx_hash"))
print("data:", result.data)// 1. Add @2sio/mcp to your MCP host config (Claude Desktop example below).
// EVM_PRIVATE_KEY funds x402 payments per call.
// claude_desktop_config.json
{
"mcpServers": {
"2sio": {
"command": "npx",
"args": ["-y", "@2sio/mcp"],
"env": { "EVM_PRIVATE_KEY": "0x..." }
}
}
}
// 2. Once the server is running, agents call this tool via standard MCP:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "countdown.gif",
"arguments": {
"endDate": "example",
"template": "default",
"seconds": 1,
"fps": 1,
"width": 200,
"height": 80,
"padding": 0,
"cellPadding": 0,
"digitFontSize": 20,
"labelFontSize": 6,
"labelPaddingY": 0,
"digitPaddingY": -60,
"letterSpacing": 0,
"bg": "example",
"fg": "example",
"labelColor": "example",
"dividerColor": "example",
"digitFont": "mono",
"labelFont": "mono",
"digitWeight": "regular",
"showLabels": false,
"showDays": false,
"dividerChar": "example",
"expiredText": "example",
"labelDays": "example",
"labelHours": "example",
"labelMinutes": "example",
"labelSeconds": "example"
}
}
}