Create a Site via API

Provision a disposable Joomla trial site programmatically and poll for its status using two simple REST endpoints.

Overview

Creating a site is asynchronous. The first endpoint (POST /api/v1/trial-sites) accepts your configuration and returns a siteId and pollToken immediately. Provisioning continues in the background. The second endpoint (GET /api/v1/trial-sites/{siteId}) lets you poll for status until the site is ready or failed.

Each trial site has a fixed 4-hour lifetime and is permanently deleted on expiry with no backup. The exact deletion time is in result.expiresAt.

Authentication

All requests require an API key sent as a Bearer token. Get your key at Settings → Application API Key (signed-in dashboard). One active key per account; the full key is shown once at creation.

http
Authorization: Bearer ij_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json

Treat the key like a password — it authorises site creation against your account quota. Rotate it from Settings if it is ever exposed.

  • Missing, malformed, or revoked key → 401 Unauthorized.
  • One active key per account.

Base URL

All requests go to the production base URL https://jinstant.com. Every example in this guide uses it.

Endpoint 1 — Create a trial site

POST/api/v1/trial-sites202 Accepted

Reserves a provisioning job and returns immediately. Every request body field is optional — send an empty JSON object ({}) or no body at all to use all defaults.

Request body

NameTypeRequiredDefaultDescription
joomlaVersion"5" | "6"No"6""5" provisions the latest Joomla 5 release (currently 5.4); "6" provisions the latest Joomla 6 release (currently 6.1). See the versions matrix below for allowed PHP combinations.
phpVersion"8.1" | "8.2" | "8.3" | "8.4"No"8.3"Must be compatible with the selected Joomla version. Unsupported combinations return 400.

Examples

bash
curl -X POST "https://jinstant.com/api/v1/trial-sites" \
  -H "Authorization: Bearer $JINSTANT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "joomlaVersion": "6",
    "phpVersion": "8.3"
  }'

Response — 202 Accepted

json
{
  "siteId": "4db53b6f-b1a6-4e46-a793-9a15a9dbf9ef",
  "pollToken": "uG0Q6Zq4xv9M3v3q8c2m4mS0nLQh4x2M",
  "status": "queued",
  "progressStage": "queued",
  "progressMessage": "Your site is in line. We are setting up Joomla 6 / PHP 8.3."
}
NameTypeDescription
siteIdstring (UUID)Identifies the provisioning job. Use in endpoint 2's path.
pollTokenstringSecret required to poll status. Pair it with siteId — store both.
statusstring"queued" on creation.
progressStagestringMachine-readable stage. See the status lifecycle below.
progressMessagestringHuman-readable progress text, safe to display in a UI.

Endpoint 2 — Check status / get result

GET/api/v1/trial-sites/{siteId}?token={pollToken}200 OK

Requires the same Authorization: Bearer key and the token query parameter. The job must belong to the authenticated user. Responses are always Cache-Control: no-store.

Parameters

NameTypeInRequiredDescription
siteIdstringpathYesThe siteId from endpoint 1.
tokenstringqueryYesThe pollToken from endpoint 1. Missing token → 400.

Example request

bash
curl "https://jinstant.com/api/v1/trial-sites/$SITE_ID?token=$POLL_TOKEN" \
  -H "Authorization: Bearer $JINSTANT_API_KEY"

Status lifecycle

The status field moves through these values while you poll:

statusTerminal?Meaning
queuedNoJob accepted, waiting for a provisioning slot.
provisioningNoActively building the Joomla environment.
readyYesSite is running. Credentials available on first read.
failedYesProvisioning failed. Check the "error" field.

progressStage provides finer-grained machine-readable stages:queuedleasing_warm_instance creating_filesstarting_containers waiting_for_joomlaconfiguring_routing ready / failed.

Response examples

In progress

json
{
  "status": "provisioning",
  "progressStage": "waiting_for_joomla",
  "progressMessage": "Almost there. Finishing setup for Joomla 6 / PHP 8.3.",
  "error": null,
  "result": null
}

Ready

json
{
  "status": "ready",
  "progressStage": "ready",
  "progressMessage": "Joomla 6 / PHP 8.3 is ready.",
  "error": null,
  "result": {
    "slug": "ab3k9m2q8n",
    "siteUrl": "https://ab3k9m2q8n.jinstant.com",
    "expiresAt": "2026-06-20T21:05:00.000Z",
    "credentials": {
      "username": "admin",
      "password": "s3cr3t-one-time-pw",
      "administratorUrl": "https://ab3k9m2q8n.jinstant.com/administrator/",
      "magicLoginUrl": "https://ab3k9m2q8n.jinstant.com/administrator/instant-login-xxxx.php"
    }
  }
}

One-time credentials

The credentials block — password, administratorUrl, and magicLoginUrl — is returned only on the first poll that observes status: "ready". The server marks them consumed on that read. Subsequent polls still return result (slug, siteUrl, expiresAt) but with credentials: null.

Capture and store the credentials from the first ready response.

Failed

json
{
  "status": "failed",
  "progressStage": "failed",
  "progressMessage": "Provisioning failed",
  "error": "Provisioning failed",
  "result": null
}

Response fields

NameTypeDescription
statusstringqueued | provisioning | ready | failed
progressStagestring | nullFine-grained stage name.
progressMessagestring | nullHuman-readable status text.
errorstring | nullPopulated when status is "failed".
resultobject | nullnull until ready; the site details once ready (see below).
result.slugstringThe site's subdomain label.
result.siteUrlstringPublic URL of the running Joomla site.
result.expiresAtstring (ISO 8601)When the site auto-deletes (created + 4 hours).
result.credentialsobject | nullAdmin login details — returned once. null on subsequent polls.
result.credentials.usernamestringAdmin username.
result.credentials.passwordstringPlaintext admin password.
result.credentials.administratorUrlstringDirect URL to the Joomla /administrator/ panel.
result.credentials.magicLoginUrlstringOne-click auto-login URL — no password required.

Polling strategy

  • Poll endpoint 2 every ~2 seconds.
  • Stop when status === "ready" (capture credentials immediately) or status === "failed" (read error).
  • Recommended timeout budget: 2–5 minutes. Most sites provision in under a minute when a warm-pool instance is available.

Complete example (Node.js)

This script creates a site, polls until it is ready, and logs the result. Credentials are captured on the first ready response.

javascript
const BASE = "https://jinstant.com";
const KEY  = process.env.JINSTANT_API_KEY;

async function createTrialSite() {
  // 1) Create the job
  const create = await fetch(`${BASE}/api/v1/trial-sites`, {
    method: "POST",
    headers: { Authorization: `Bearer ${KEY}`, "Content-Type": "application/json" },
    body: JSON.stringify({ joomlaVersion: "6", phpVersion: "8.3" }),
  });
  if (create.status !== 202) throw new Error(`Create failed: ${create.status}`);
  const { siteId, pollToken } = await create.json();

  // 2) Poll until ready or failed (≈5 min budget)
  const deadline = Date.now() + 5 * 60 * 1000;
  while (Date.now() < deadline) {
    const res = await fetch(
      `${BASE}/api/v1/trial-sites/${siteId}?token=${encodeURIComponent(pollToken)}`,
      { headers: { Authorization: `Bearer ${KEY}` } }
    );
    const body = await res.json();

    if (body.status === "ready") {
      // 3) Capture credentials NOW — they are returned only once.
      console.log("Site URL:", body.result.siteUrl);
      console.log("Login:",    body.result.credentials);
      return body.result;
    }
    if (body.status === "failed") throw new Error(body.error ?? "Provisioning failed");

    await new Promise((r) => setTimeout(r, 2000));
  }
  throw new Error("Timed out waiting for the site to become ready.");
}

Site lifetime

Trial sites created via the API have a fixed 4-hour lifetime. They are automatically and permanently deleted on expiry, with no backups, consistent with the Terms of Use. The exact deletion time is in result.expiresAt.

Versions reference

Joomla / PHP matrix

joomlaVersion (API)ProvisionsAllowed phpVersion
"5"Joomla 5.4"8.1", "8.2", "8.3"
"6" (default)Joomla 6.1"8.3" (default), "8.4"

You choose the major line ("5" or "6") and always get the latest release we support on it. Unsupported combinations (e.g. joomlaVersion: "6" with phpVersion: "8.1") return 400 Bad Request.

Errors

All error responses use JSON: { "error": "message" }.

HTTPMeaningTypical cause
400Bad RequestMalformed JSON; unsupported joomlaVersion / phpVersion; unsupported combination; (endpoint 2) missing token.
401UnauthorizedMissing, malformed, invalid, or revoked API key.
404Not FoundNo job matches that siteId + token for the authenticated user.
409ConflictAccount already at its concurrent-site limit (default 3). Delete a site to free a slot.
429Too Many RequestsMore than 3 create attempts per 60-minute window from one IP.
500Internal Server ErrorUnexpected provisioning or server failure.

Note

A malformed JSON body is rejected with 400 before authentication is checked. All other validation happens after the key is verified — so a bad key returns 401 even when the body is also invalid.

Rate limits & quotas

  • Create rate limit: 3 POST attempts per 60-minute window, per IP. Exceeding this returns 429.
  • Concurrent-site quota:3 active sites per account (a site is "active" when its status is queued, provisioning, ready, failed, or deleting). Exceeding this returns 409. Delete a site from your dashboard to free a slot.

Next steps