Authentication
All API requests require authentication via a Bearer token in the header:
Authorization: Bearer YOUR_API_KEYGenerating API Keys
- Go to Dashboard → API Keys
- Click Create New Key
- Give it a descriptive name
- Copy the key immediately (it won't be shown again) — it starts with
sk_
Important: API keys have the same permissions as your account. Keep them secret and rotate regularly.
Base URL
https://hostwares.com/apiAll endpoints are relative to this base URL. Responses are JSON.
Sites API
| Method | Endpoint | Description |
|---|---|---|
GET | /sites | List all your sites |
POST | /sites | Create a site (returns an invoice to pay) |
GET | /sites/:id | Get site details |
PATCH | /sites/:id | Update domain or trigger an action |
DELETE | /sites/:id | Delete a site permanently |
Create a site
Hosting is invoice-based, not credit-based — creating a site does not deploy it immediately. The site is created in PENDING status and an unpaid invoice is returned; deployment starts automatically once that invoice is paid (PayPal).
POST /api/sites
{
"name": "my-nextjs-app",
"deployType": "github",
"githubUrl": "github.com/user/my-app",
"branch": "main",
"port": 3000,
"buildCommand": "npm run build",
"startCommand": "npm start",
"packId": "optional — defaults to the cheapest active pack",
"billingTerm": 1
}Response
{
"invoiceToken": "inv_abc123",
"invoiceId": "cm1234abcd",
"siteId": "cm5678efgh"
}Pay the invoice at https://hostwares.com/invoice/{invoiceToken} — the AI assistant can also generate and pay-link this invoice for you in chat.
Databases API
| Method | Endpoint | Description |
|---|---|---|
GET | /databases | List all databases |
POST | /databases | Create a database (returns an invoice to pay) |
GET | /databases/:id | Get database details |
PATCH | /databases/:id | Trigger an action |
DELETE | /databases/:id | Delete a database permanently |
Create a database
POST /api/databases
{
"name": "production-db",
"type": "postgresql",
"packId": "optional — defaults to the cheapest active pack",
"billingTerm": 1
}Same invoice-first flow as Sites — provisioning starts once the returned invoice is paid.
Credits API
| Method | Endpoint | Description |
|---|---|---|
GET | /credits | Balance + last 20 transactions |
GET | /credits/packages | Available packages (no auth required) |
POST | /credits/purchase | Create a credit-pack invoice |
Check balance
GET /api/credits
Response:
{
"balance": 450,
"transactions": [
{ "id": "tx_1", "type": "purchase", "amount": 500, "createdAt": "2026-07-01T08:00:00Z" }
]
}Purchase credits
POST /api/credits/purchase
{ "packageId": "pro" }
Response:
{ "invoiceToken": "inv_xyz", ... }Site & Database Actions
Use PATCH with an action field to control container state. To delete a resource, use the DELETE method instead — it isn't a PATCH action.
PATCH /api/sites/:id
{ "action": "restart" }Site actions
| Action | Description |
|---|---|
start | Start a stopped container |
stop | Stop a running container |
restart | Restart the container |
deploy | Trigger a new deployment |
Database actions: start, stop, restart.
Error Handling
Errors return JSON with an error field. The HTTP status code tells you the category:
{ "error": "Not found" }| Status | Meaning |
|---|---|
| 400 | Invalid request body or parameters |
| 401 | Missing or invalid API key / session |
| 403 | Authenticated, but you don't own this resource |
| 404 | Resource not found |
| 429 | Rate limited — see below |
| 500 | Server error (retry later) |
Rate Limits
60 requests per minute per API key, tracked independently from your dashboard session. Exceeding it returns 429 with {"error": "rate_limited"} — back off and retry after a few seconds.
The AI chat endpoints (/api/chat, /api/chat/stream) have separate, plan-based limits — see the AI Assistant docs.
Code Examples
Node.js (fetch)
const response = await fetch('https://hostwares.com/api/sites', {
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
}
});
const sites = await response.json();Python (requests)
import requests
headers = {"Authorization": "Bearer YOUR_API_KEY"}
response = requests.get("https://hostwares.com/api/sites", headers=headers)
sites = response.json()cURL
curl -X GET https://hostwares.com/api/sites \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json"Trigger a redeploy via API
curl -X PATCH https://hostwares.com/api/sites/SITE_ID \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"action": "deploy"}'This is what the GitHub Actions / GitLab CI examples on the Integrations page use to redeploy an existing site on every push.
AI Chat
POST /api/chat
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
{
"message": "deploy my-app from github.com/user/repo",
"conversationId": "optional-for-context"
}
Response:
{
"message": "✓ Deploying my-app...",
"conversationId": "conv_abc123",
"balance": 448,
"creditsUsed": 10
}The AI can execute 95 DevOps tools across web and CLI. Credits are deducted once per full interaction — see How Credits Work.
CLI Device Authentication
# Step 1: Get device code
POST /api/auth/device
→ { "device_code": "...", "user_code": "ABC123", "verification_url": "https://hostwares.com/cli/authorize?code=ABC123" }
# Step 2: User opens URL in browser and clicks Authorize
# Step 3: CLI polls until approved
GET /api/auth/device-poll?code=DEVICE_CODE
→ { "status": "pending" } (keep polling)
→ { "status": "approved", "token": "permanent-api-key" } (done)Security
- All API keys are scoped to the user who created them
- Tokens never expire unless manually revoked from Dashboard → API Keys
- Server credentials are encrypted at rest (AES-256-CBC)
- Payment verification required before first deploy (anti-abuse)
- AI assistant cannot access other users' resources
- Destructive actions (delete, stop) require confirmation in the AI
- Rate limited: 60 requests/minute per key
- HTTPS only — all API traffic encrypted in transit