Official Python SDK for instanode.dev — zero-friction developer infrastructure for AI agents
Project description
instanode
Official Python SDK for instanode.dev — zero-friction developer infrastructure. Provision real databases, caches, queues, and heartbeat monitors with a single function call. No account required. No Docker. No setup.
pip install instanode
Quickstart
Heartbeat monitor (cron job health check)
import instanode
client = instanode.Client()
# Provision a monitor — no account needed
mon = client.provision_monitor(name="nightly-backup")
print(mon.url) # https://instanode.dev/ping/<token>
# Wrap any callable — sends /start, then success or /fail automatically
def run_backup():
... # your job logic here
client.heartbeat_wrap(mon.token, run_backup)
Postgres database
import instanode
client = instanode.Client()
db = client.provision_database(name="my-app-db")
# Use the connection string with psycopg2, SQLAlchemy, Django, asyncpg, etc.
print(db.connection_url)
# postgres://user:pass@host:5432/dbname
# Anonymous resources expire in 24 h. Check the note field:
if db.note:
print(db.note) # "Claim your resources at https://instanode.dev/start?t=..."
Full provision (DB + cache + MongoDB + monitor)
import instanode
client = instanode.Client()
db = client.provision_database(name="app-db")
cache = client.provision_cache(name="app-cache")
mongo = client.provision_mongodb(name="app-nosql")
mon = client.provision_monitor(name="app-health")
print(db.connection_url) # postgres://...
print(cache.connection_url) # redis://...
print(mongo.connection_url) # mongodb://...
print(mon.url) # https://instanode.dev/ping/<token>
Authentication
Without an API key, the SDK operates in anonymous mode: resources are real but expire after 24 hours and have lower rate limits (100 pings/day, 10 MB Postgres, etc.).
To make resources permanent, call client.claim() or visit the upgrade URL that
appears in result.note.
# Set via environment variable (recommended)
export INSTANODE_API_KEY=sk_...
# Or pass to the constructor
client = instanode.Client(api_key="sk_...")
Method Reference
| Method | Endpoint | Auth required |
|---|---|---|
provision_monitor(name) |
POST /ping/new |
No |
heartbeat(token) |
POST /ping/{token} |
No |
heartbeat_start(token) |
POST /ping/{token}/start |
No |
heartbeat_fail(token) |
POST /ping/{token}/fail |
No |
heartbeat_wrap(token, fn) |
start + success/fail | No |
provision_database(name) |
POST /db/new |
No |
provision_cache(name) |
POST /cache/new |
No |
provision_mongodb(name) |
POST /nosql/new |
No |
provision_queue(name) |
POST /queue/new |
No |
claim(jwt, email, team_name) |
POST /claim |
No |
list_resources() |
GET /api/v1/resources |
Yes |
get_resource(token) |
GET /api/v1/resources/{token} |
Yes |
delete_resource(token) |
DELETE /api/v1/resources/{token} |
Yes |
rotate_credentials(token) |
POST /api/v1/resources/{token}/rotate-credentials |
Yes |
Tier Limits
| Tier | Postgres | Redis | MongoDB | Pings/day |
|---|---|---|---|---|
| anonymous | 10 MB / 2 conn / 24 h | 5 MB / 24 h | 5 MB / 2 conn / 24 h | 100 |
| hobby (claimed) | 500 MB / 5 conn | 25 MB | 100 MB / 5 conn | 1 000 |
| pro ($12/mo) | 5 120 MB / 20 conn | 256 MB | 2 048 MB / 20 conn | 50 000 |
| team ($49/mo) | unlimited | unlimited | unlimited | unlimited |
Error handling
import instanode
client = instanode.Client()
try:
db = client.provision_database()
except instanode.InstanodeError as exc:
print(exc.status_code) # 503
print(exc.code) # "provisioning_failed"
print(exc.message) # "provisioner unavailable"
if exc.is_rate_limited(): # 429
print("slow down")
elif exc.is_service_unavailable(): # 503
print("try again later")
elif exc.is_not_found(): # 404
print("wrong token")
elif exc.is_conflict(): # 409 — JWT already claimed
print("already claimed")
Context manager (auto-cleanup)
The client supports use as a context manager. No persistent connections are held, so this is mainly for idiomatic resource scoping:
import instanode
with instanode.Client() as client:
db = client.provision_database()
# use db.connection_url ...
# client goes out of scope here
Async support
import asyncio
import instanode.aio
async def main():
async with instanode.aio.AsyncClient() as client:
# Provision concurrently
db, cache = await asyncio.gather(
client.provision_database(name="app-db"),
client.provision_cache(name="app-cache"),
)
print(db.connection_url)
print(cache.connection_url)
# heartbeat_wrap works with async functions too
async def run_job():
await asyncio.sleep(0.1)
mon = await client.provision_monitor(name="async-job")
await client.heartbeat_wrap(mon.token, run_job)
asyncio.run(main())
Claiming anonymous resources
When instanode.dev surfaces the upgrade URL in result.note, extract the JWT from
the ?t= query parameter and call claim():
import instanode
from urllib.parse import urlparse, parse_qs
client = instanode.Client()
db = client.provision_database()
if db.note and "instanode.dev/start" in (db.note or ""):
# parse the JWT from the URL in the note
# e.g. note = "Claim at https://instanode.dev/start?t=eyJ..."
upgrade_url = db.note.split()[-1]
jwt = parse_qs(urlparse(upgrade_url).query)["t"][0]
result = client.claim(
jwt=jwt,
email="dev@example.com",
team_name="My Team", # optional
)
print(f"Claimed {result.claimed} resources → team {result.team_id}")
Zero dependencies
The SDK uses only the Python standard library (urllib.request). No requests,
no httpx, no aiohttp. Works in any environment including AWS Lambda, Google
Cloud Functions, and minimal Docker images.
Links
- Homepage: https://instanode.dev
- Documentation: https://instanode.dev/docs
- GitHub: https://github.com/InstaNode-dev/sdk-python
- PyPI: https://pypi.org/project/instanode
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file instanode-0.2.0.tar.gz.
File metadata
- Download URL: instanode-0.2.0.tar.gz
- Upload date:
- Size: 21.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
67d22ba4bd8650c0192a15db521c11474b5bd2f61a0788cc96ea72926709e766
|
|
| MD5 |
1688193c3624f2f2d5bdf882de912cde
|
|
| BLAKE2b-256 |
686a175f297fb585a5cf680ab2b8dddf17b927c4daf6c4e1b26d040cddb1aca5
|
File details
Details for the file instanode-0.2.0-py3-none-any.whl.
File metadata
- Download URL: instanode-0.2.0-py3-none-any.whl
- Upload date:
- Size: 14.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
382f69cd4a091d0569b5d4352ab69128086a1d8e880b8404cb84dd9e9ab8580e
|
|
| MD5 |
90d2507e2c9a2323a48a07a8a8b41ad1
|
|
| BLAKE2b-256 |
2ae65e37e6b990b626e797628a9b816370252dbee56b053f55b8e4d234abc6cd
|