API Reference
Base URL: https://api.machinemarket.ai
All endpoints accept and return JSON. No authentication headers are required — payment is authentication.
iNote
Error responses always include an
error string and optionally a code string for programmatic handling.POST
/v1/spawnProvision a new VPS instance. Requires a verified USDC payment on Base.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
tier | string | yes | "Nano" | "Small" | "Medium" | "Large" |
template | string | yes | "base" | "node" | "python" | "agent" |
duration | string | yes | "1h" | "24h" | "7d" | "30d" |
region | string | no | Hetzner region ID. Defaults to "fsn1". See GET /v1/regions. |
tx_hash | string | yes | Transaction hash of the USDC payment on Base (0x-prefixed, 64 hex chars). |
wallet_address | string | yes | Sender wallet address (0x-prefixed, 40 hex chars). |
ssh_pubkey | string | no | Your SSH public key. If omitted, a keypair is generated and the private key is returned. |
Response (201)
| Field | Type | Required | Description |
|---|---|---|---|
instance.id | string | yes | UUID of the created instance. |
instance.tier | string | yes | The tier name. |
instance.template | string | yes | The template ID. |
instance.region | string | yes | Hetzner region ID. |
instance.status | string | yes | "provisioning" or "running". |
instance.ip_address | string | null | yes | IP address (null while provisioning). |
instance.created_at | string | yes | ISO 8601 timestamp. |
instance.expires_at | string | yes | ISO 8601 expiry timestamp. |
instance.cost_usdc | number | yes | Total cost in USDC. |
credentials.ssh_user | string | yes | Always "root". |
credentials.ssh_host | string | null | yes | Same as ip_address. |
credentials.ssh_port | number | yes | Always 22. |
credentials.ssh_private_key | string | no | PEM private key (only if ssh_pubkey was omitted). |
Error codes
| Field | Type | Required | Description |
|---|---|---|---|
400 | — | no | Invalid request body or parameters. |
402 | PAYMENT_INVALID | no | Payment verification failed (wrong amount, sender, or failed tx). |
409 | TX_DUPLICATE | no | Transaction hash already used. |
429 | WALLET_LIMIT | no | Max 10 concurrent instances per wallet. |
502 | PROVISION_FAILED | no | Hetzner provisioning failed. |
curl
curl -X POST https://api.machinemarket.ai/v1/spawn \
-H "Content-Type: application/json" \
-d '{
"tier": "Small",
"template": "node",
"duration": "24h",
"tx_hash": "0xabc...def",
"wallet_address": "0x1234...5678"
}'SDK
typescript
const result = await mm.spawn({
tier: "Small",
template: "node",
duration: "24h",
tx_hash: "0xabc...def",
wallet_address: "0x1234...5678",
});GET
/v1/instances/:idGet instance details. If the instance is still provisioning, the API polls Hetzner for updated status.
Response (200)
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | Instance UUID. |
tier | string | yes | Tier name. |
template | string | yes | Template ID. |
region | string | yes | Region ID. |
status | string | yes | "provisioning" | "running" | "expired" | "destroyed". |
ip_address | string | null | yes | IP address. |
created_at | string | yes | ISO 8601. |
expires_at | string | yes | ISO 8601. |
destroyed_at | string | null | yes | ISO 8601 or null. |
cost_usdc | number | yes | Total cost. |
curl
curl https://api.machinemarket.ai/v1/instances/YOUR_INSTANCE_IDSDK
typescript
const instance = await mm.getInstance("YOUR_INSTANCE_ID");
console.log(instance.status, instance.ip_address);DELETE
/v1/instances/:idImmediately destroy an instance. The server is deleted from Hetzner.
Response (200)
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | Instance UUID. |
status | string | yes | Always "destroyed". |
Error codes
| Field | Type | Required | Description |
|---|---|---|---|
404 | — | no | Instance not found. |
409 | — | no | Instance already terminated. |
502 | — | no | Failed to delete server from provider. |
curl
curl -X DELETE https://api.machinemarket.ai/v1/instances/YOUR_INSTANCE_IDSDK
typescript
const result = await mm.destroyInstance("YOUR_INSTANCE_ID");
console.log(result.status); // "destroyed"POST
/v1/instances/:id/extendExtend an active instance with a new USDC payment. The new duration is added to the current expiry.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
duration | string | yes | "1h" | "24h" | "7d" | "30d". |
tx_hash | string | yes | Transaction hash of the extension payment. |
wallet_address | string | yes | Sender wallet address. |
Response (200)
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | Instance UUID. |
expires_at | string | yes | New ISO 8601 expiry. |
extension_cost_usdc | number | yes | Cost of this extension. |
total_cost_usdc | number | yes | Cumulative cost. |
Error codes
| Field | Type | Required | Description |
|---|---|---|---|
400 | — | no | Invalid parameters. |
402 | PAYMENT_INVALID | no | Payment verification failed. |
404 | — | no | Instance not found. |
409 | TX_DUPLICATE | no | Transaction hash already used. |
409 | — | no | Can only extend active instances. |
curl
curl -X POST https://api.machinemarket.ai/v1/instances/YOUR_ID/extend \
-H "Content-Type: application/json" \
-d '{
"duration": "24h",
"tx_hash": "0xdef...789",
"wallet_address": "0x1234...5678"
}'SDK
typescript
const result = await mm.extendInstance("YOUR_ID", {
duration: "24h",
tx_hash: "0xdef...789",
wallet_address: "0x1234...5678",
});
console.log("New expiry:", result.expires_at);GET
/v1/pricingGet all available pricing tiers and durations.
Response (200)
| Field | Type | Required | Description |
|---|---|---|---|
tiers | PricingTier[] | yes | Array of tier objects with name, vcpu, ram, storage, hourly/daily/monthly rates. |
durations | Duration[] | yes | Array of duration objects with label, value, hours. |
currency | string | yes | Always "USDC". |
chain | string | yes | Always "Base". |
curl
curl https://api.machinemarket.ai/v1/pricingSDK
typescript
const pricing = await mm.getPricing();
pricing.tiers.forEach(t =>
console.log(`${t.name}: $${t.hourly}/hr`)
);GET
/v1/regionsGet available deployment regions.
Response (200)
| Field | Type | Required | Description |
|---|---|---|---|
regions | RegionInfo[] | yes | Array of region objects with id, name, country, available. |
default | string | yes | Default region ID ("fsn1"). |
curl
curl https://api.machinemarket.ai/v1/regionsSDK
typescript
const regions = await mm.getRegions();
const available = regions.regions.filter(r => r.available);
console.log(available);~Tip
See the SDK Reference for TypeScript type definitions and error handling patterns.