OpenAPI and clients
The OpenAPI file, generating clients, and examples in curl, JavaScript, PHP and Python.
The OpenAPI file
GET https://YOUR-MYFORGE/api/v1/openapi.json
It is public (no token) and describes every endpoint with its scope (x-scope), request body, and response codes. In the dashboard it is also shown under API, then API reference. The pages in the API reference group of these docs are generated from it.
Generate a client with any OpenAPI 3.1 tool, for example openapi-generator or openapi-typescript. Set the base URL to https://YOUR-MYFORGE/api/v1 and the security scheme to a bearer token. Add the Idempotency-Key header to every change.
For AI agents: /llms.txt and /llms-full.txt. See AI with the REST API.
curl
export MYFORGE=https://YOUR-MYFORGE/api/v1
export TOKEN=mf_YOUR_TOKEN
curl -s -H "Authorization: Bearer $TOKEN" $MYFORGE/sites
curl -s -X POST $MYFORGE/sites/SITE_ID/deploy \
-H "Authorization: Bearer $TOKEN" \
-H "Idempotency-Key: deploy-shop-20261009-1"
JavaScript (Node 18+ or browser)
Never put a token in browser code that other people can open. Use this on a server or in CI.
const base = 'https://YOUR-MYFORGE/api/v1';
const headers = { Authorization: `Bearer ${process.env.MYFORGE_TOKEN}`, Accept: 'application/json' };
const sites = await (await fetch(`${base}/sites`, { headers })).json();
console.log(sites.data.map((s) => s.domain));
const res = await fetch(`${base}/sites/${sites.data[0].id}/deploy`, {
method: 'POST',
headers: { ...headers, 'Idempotency-Key': crypto.randomUUID() },
});
if (res.status !== 202) throw new Error(`Deploy refused: ${res.status} ${(await res.json()).message}`);
const deployment = (await res.json()).data;
PHP
$http = Http::withToken(env('MYFORGE_TOKEN'))
->acceptJson()
->baseUrl('https://YOUR-MYFORGE/api/v1');
$sites = $http->get('/sites')->throw()->json('data');
$response = $http
->withHeaders(['Idempotency-Key' => (string) Str::uuid()])
->post("/sites/{$sites[0]['id']}/deploy");
if ($response->status() !== 202) {
throw new RuntimeException($response->json('message'));
}
Python
import os, uuid, requests
base = "https://YOUR-MYFORGE/api/v1"
headers = {"Authorization": f"Bearer {os.environ['MYFORGE_TOKEN']}", "Accept": "application/json"}
sites = requests.get(f"{base}/sites", headers=headers, timeout=30).json()["data"]
r = requests.post(
f"{base}/sites/{sites[0]['id']}/deploy",
headers={**headers, "Idempotency-Key": str(uuid.uuid4())},
timeout=30,
)
r.raise_for_status()
deployment = r.json()["data"]
Waiting for the deployment (Python)
import time
while True:
d = requests.get(f"{base}/sites/{site_id}/deployments/{deployment['id']}", headers=headers, timeout=30).json()["data"]
if d["status"] in ("succeeded", "failed"):
break
time.sleep(10)
print(d["status"], d.get("code_findings"))
Tips
- If you retry after a timeout, reuse the same
Idempotency-Key. For a new action, make a new key. - Follow
links.nextin lists. - Handle
429by waiting, and409by reading the state, not by retrying blindly. - Set timeouts on every call.