HarvestGPU Documentation
HarvestGPU is a BYOK (Bring Your Own Key) GPU routing platform. Connect your own GPU provider API keys, submit jobs through a single API, and we route them to the cheapest available GPU across all your accounts.
Getting Started
HarvestGPU works with your existing GPU provider accounts. Here is how to get set up:
1. Create a HarvestGPU account
Sign up at /register or via the API. This gives you a HarvestGPU API key for authenticating requests.
2. Connect your GPU provider keys
Go to Dashboard Settings and add your API keys for one or more providers. You can also use the API:
curl -X POST http://localhost:5000/api/v1/providers/keys \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"provider": "runpod", "api_key": "YOUR_RUNPOD_KEY", "label": "My RunPod"}'
3. Submit jobs
Jobs are routed across your connected providers to find the cheapest option. A built-in mock provider is always available for testing, even without any provider keys.
Supported providers and where to get API keys
| Provider | Slug | API Key Page |
|---|---|---|
| RunPod | runpod | runpod.io/console/user/settings |
| Lambda Labs | lambda | cloud.lambdalabs.com/api-keys |
| Vast.ai | vastai | cloud.vast.ai/account |
| TensorDock | tensordock | marketplace.tensordock.com/api |
Your keys are stored securely and only used to call provider APIs on your behalf. Billing for GPU usage goes directly through your provider accounts.
Quick Start
Get running in under a minute.
1. Get your API key
curl -X POST http://localhost:5000/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{"email": "you@example.com", "password": "your-password"}'
Save the api_key from the response. It looks like hg_live_abc123...
2. Submit a GPU job
curl -X POST http://localhost:5000/api/v1/jobs \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"gpu": "H100",
"image": "pytorch/pytorch:latest",
"command": "python train.py",
"priority": "cost"
}'
3. Check job status
curl http://localhost:5000/api/v1/jobs/JOB_ID \
-H "Authorization: Bearer YOUR_API_KEY"
Authentication
All authenticated endpoints accept two auth methods:
- API Key (recommended): Pass your API key as a Bearer token:
Authorization: Bearer hg_live_... - API Key Header:
X-API-Key: hg_live_... - JWT Token: Obtained from the login endpoint. Same Bearer header format.
Python SDK
Installation
pip install harvestgpu
Usage
from harvestgpu import HarvestGPU
gpu = HarvestGPU(api_key="hg_live_...")
# Submit a job - routes to cheapest provider
job = gpu.run(
gpu="H100",
image="pytorch/pytorch:latest",
command="python train.py",
budget_max=2.50,
)
print(job.status) # "running"
print(job.provider) # "mock" (or real provider)
print(job.cost_per_hour) # 2.86
# List your jobs
jobs = gpu.jobs()
for j in jobs:
print(f"{j.id}: {j.gpu_type} on {j.provider} - {j.status}")
# Get current GPU pricing
pricing = gpu.pricing()
for p in pricing:
print(f"{p.gpu_model}: ${p.price}/hr via {p.provider}")
# Stop a job
job.stop()
# Get logs
logs = job.logs()
print(logs)
CLI Tool
# Authenticate
harvestgpu auth login --key hg_live_...
harvestgpu auth whoami
# Run a GPU job
harvestgpu run --gpu H100 --image pytorch/pytorch:latest --command "python train.py"
# Manage jobs
harvestgpu jobs list
harvestgpu jobs status JOB_ID
harvestgpu jobs logs JOB_ID
harvestgpu jobs stop JOB_ID
# Check pricing
harvestgpu pricing
harvestgpu pricing --gpu H100
API Reference
Base URL: http://localhost:5000/api/v1
All responses follow this envelope:
{
"status": "ok", // or "error"
"data": { ... }, // present on success
"error": "message" // present on error
}
Auth Endpoints
/api/v1/auth/register
Create a new account and get an API key.
Request Body
{
"email": "you@example.com",
"password": "min8chars",
"company": "optional"
}
Response
{
"status": "ok",
"data": {
"user_id": "abc123",
"email": "you@example.com",
"api_key": "hg_live_xyz...",
"token": "jwt.token.here"
}
}
/api/v1/auth/login
Login and get a JWT token.
Request Body
{"email": "you@example.com", "password": "your-password"}
/api/v1/auth/me
Get current user info, usage, and active jobs. Requires auth.
Job Endpoints
/api/v1/jobs
Submit a new GPU job. We route to the best provider based on your priority.
Request Body
{
"gpu": "H100", // required
"image": "pytorch/pytorch:latest", // Docker image
"command": "python train.py", // Command to run
"budget_max_per_hour": 2.50, // optional price cap
"max_duration_hours": 4, // optional max runtime
"priority": "cost" // "cost" | "speed" | "availability"
}
/api/v1/jobs
List your jobs with optional filters.
Query Parameters
status- Filter: running, completed, failed, stopped, queuedgpu- Filter by GPU typeprovider- Filter by provider sluglimit- Results per page (default 50, max 100)offset- Pagination offset
/api/v1/jobs/:job_id
Get details for a specific job.
/api/v1/jobs/:job_id/stop
Stop a running job. Charges for compute used so far.
/api/v1/jobs/:job_id/logs
Get logs for a job. Live-streams for running jobs.
Provider Endpoints
/api/v1/providers
List all providers and their availability. No auth required.
/api/v1/providers/:slug/gpus
List available GPUs from a specific provider.
/api/v1/pricing
Real-time pricing matrix across all providers. No auth required.
Provider Key Endpoints
/api/v1/providers/keys
Add or update a provider API key. Requires auth.
Request Body
{
"provider": "runpod", // runpod | lambda | vastai | tensordock
"api_key": "your-provider-key",
"label": "My RunPod Account" // optional
}
/api/v1/providers/keys
List connected providers. Returns provider name, last 4 chars of key, label, and active status. Does not return full keys. Requires auth.
/api/v1/providers/keys/:provider
Remove a provider key. Requires auth.
/api/v1/providers/keys/:provider/test
Test if a stored key is valid by calling the provider's API. Requires auth.
Response
{
"status": "ok",
"data": {
"provider": "runpod",
"valid": true,
"message": "Key is valid"
}
}
Usage Endpoints
/api/v1/billing/usage
Current period usage with daily breakdown. Requires auth.
/api/v1/billing/history
Past usage records. Requires auth.
Webhook Endpoints
/api/v1/webhooks
List your configured webhooks. Requires auth.
/api/v1/webhooks
Create a new webhook.
Request Body
{"url": "https://your-app.com/webhook", "events": "job.completed,job.failed"}
/api/v1/webhooks/:id
Delete a webhook. Requires auth.
Webhook Events
When configured, we send HTTP POST requests to your webhook URL with these events:
job.completed- Job finished successfullyjob.failed- Job encountered an errorjob.stopped- Job was manually stopped
Payload Format
{
"event": "job.completed",
"job_id": "abc123",
"gpu_type": "H100",
"provider": "runpod",
"total_cost": 3.45,
"status": "completed",
"timestamp": "2026-04-14T12:00:00Z"
}
Rate Limits
| Plan | Requests/minute | Jobs/hour |
|---|---|---|
| Free | 60 | 10 |
| Pay As You Go | 1,000 | 100 |
| Enterprise | 10,000 | Unlimited |
Error Handling
All errors return this format:
{
"status": "error",
"error": "Human-readable error message"
}
| HTTP Code | Meaning |
|---|---|
| 400 | Bad request (missing or invalid parameters) |
| 401 | Authentication required or invalid |
| 404 | Resource not found |
| 503 | No providers available for the request |