Skip to main content
A self-contained script that walks through the entire lifecycle: find the cheapest GPU offer, procure it, wait for it to be ready, and print SSH access details.
#!/usr/bin/env python3
"""Find the cheapest GPU offer, procure it, and print SSH access details."""

import time
import requests

BASE_URL = "https://supply-api.compute-index.com"
TOKEN = "YOUR_TOKEN"
SSH_PUBLIC_KEY = "ssh-ed25519 AAAA... your-key"

headers = {"Authorization": f"Bearer {TOKEN}"}


# Step 1: Get offers
yaml_spec = """
compute:
  gpu_type: H100
  gpu_count: 1
  max_price_per_gpu_hour: 5
  contract_type: ondemand
"""

print("Fetching offers...")
resp = requests.post(
    f"{BASE_URL}/get_offers",
    data=yaml_spec,
    headers={**headers, "Content-Type": "application/yaml"},
    timeout=30,
)
resp.raise_for_status()
offers = resp.json()["offers"]

if not offers:
    print("No offers found")
    exit(1)

# Step 2: Pick the cheapest
cheapest = min(offers, key=lambda o: o["gpu_price_per_hour"])
offer_id = cheapest["offer_id"]
print(f"Cheapest: {cheapest['vendor']} — ${cheapest['gpu_price_per_hour']:.4f}/GPU/hr")


# Step 3: Procure
print(f"Procuring {offer_id}...")
resp = requests.post(
    f"{BASE_URL}/procure_offer",
    json={"offer_id": offer_id, "ssh_public_key": SSH_PUBLIC_KEY},
    headers=headers,
    timeout=300,
)
resp.raise_for_status()
print(f"Status: {resp.json()['status']}")


# Step 4: Poll until ready
print("Waiting for instance...")
for _ in range(120):  # up to 30 minutes
    status = requests.get(
        f"{BASE_URL}/offers/{offer_id}/status", headers=headers
    ).json()
    procurement = status["procurement_status"]

    if procurement == "ready":
        instance = status["instances"][0]
        ip = instance.get("external_ip")
        ssh_cmd = instance.get("ssh_command")
        print(f"\nInstance ready!")
        print(f"  IP:  {ip}")
        print(f"  SSH: ssh -i ~/.ssh/your_private_key {ssh_cmd.split('ssh ')[-1] if ssh_cmd else f'root@{ip}'}")
        break

    if procurement == "failed":
        print(f"Failed: {status.get('failure_reason')}")
        exit(1)

    print(f"  {procurement}...")
    time.sleep(15)


# Step 5: Clean up (uncomment when done)
# resources = requests.get(
#     f"{BASE_URL}/resources?offer_id={offer_id}", headers=headers
# ).json()["resources"]
# for r in resources:
#     requests.delete(
#         f"{BASE_URL}/resources/{r['resource_id']}?force=true", headers=headers
#     )
#     print(f"Deleted {r['resource_id']}")

What this does

  1. Get offers — queries all vendors for H100 x1 under $5/GPU/hr
  2. Pick cheapest — selects the lowest-priced offer
  3. Procure — provisions the instance with your SSH key
  4. Poll — waits up to 30 minutes for the instance to be ready
  5. Clean up — code to delete the resource (commented out by default)

Customizing

Change the YAML spec to match your needs. See the YAML Spec guide for all available options:
yaml_spec = """
region: EU
vendor: nebius
compute:
  gpu_type: A100
  gpu_count: 8
  max_price_per_gpu_hour: 2.50
  contract_type: ondemand
cloud_init: |
  #cloud-config
  packages:
    - htop
    - nvidia-container-toolkit
"""