HTTP API
Build automation against explicit contracts.
Midnight's control plane is rooted at /api/v1alpha. Use the OpenAPI document served by the installation you call, authenticate with one declared credential class, and treat asynchronous operations as the source of progress truth.
On this page
SOURCE OF TRUTH
Generate from the installation, not this website.
curl --fail-with-body https://your-midnight.example/api/v1alpha/openapi.yaml --output midnight-openapi.yamlThe marketing site describes the product, while the served contract reflects the exact build installed on your host. Midnight is Railway-inspired, but it is not Railway API-compatible or a drop-in replacement.
AUTHORITY
Use one credential class for its intended routes.
- Human session · midn_user_
- Dashboard, CLI, and tenant APIs admitted by the user's current workspace and project grants.
- Project automation · midn_sa_
- Narrow CI deploy/source intake and same-project deployment or operation reads. It cannot manage installation settings.
- Runtime agent
- A secret bound to one agent ID and only its registration, heartbeat, desired-state, and status routes.
- Installation recovery
- Explicit break-glass compatibility for installation-wide operator routes; never a substitute for tenant access.
Send accepted bearer credentials as Authorization: Bearer <token>. A token never widens itself or falls back to a different authority class.
FIRST MUTATION
Create a project with a stable retry identity.
export MIDNIGHT_URL=https://your-midnight.example
export MIDNIGHT_TOKEN=midn_user_...
export REQUEST_KEY=project-payments-v1
curl --fail-with-body -X POST "$MIDNIGHT_URL/api/v1alpha/projects" -H "Authorization: Bearer $MIDNIGHT_TOKEN" -H 'Content-Type: application/json' -H "Idempotency-Key: $REQUEST_KEY" --data '{
"workspace_id": "wrk_example",
"slug": "payments",
"display_name": "Payments"
}'RETRIES AND CONCURRENCY
Make ambiguous outcomes safe.
- Idempotency-Key
- A stable opaque identity for one logical mutation. Retry only the same concrete route and exact body with that key.
- ETag
- The strong version returned by a resource read.
- If-Match
- Required by compare-and-swap mutations. A stale value returns 412 rather than overwriting newer state.
- 202 Accepted
- Durable asynchronous intake. Follow the returned operation; do not report the action as complete yet.
# A prior GET returned: ETag: "3"
VARIABLE_REQUEST_KEY=variable-rotation-v4
curl --fail-with-body -X PATCH "$MIDNIGHT_URL/api/v1alpha/services/$SERVICE_ID/environments/$ENVIRONMENT_ID/variables/$VARIABLE_ID" -H "Authorization: Bearer $MIDNIGHT_TOKEN" -H 'Content-Type: application/json' -H 'If-Match: "3"' -H "Idempotency-Key: $VARIABLE_REQUEST_KEY" --data '{"expected_version":3,"value":"<new-value>"}'ASYNC WORK
Poll or resume the operation stream.
curl --fail-with-body "$MIDNIGHT_URL/api/v1alpha/operations/$OPERATION_ID" -H "Authorization: Bearer $MIDNIGHT_TOKEN"
curl -N "$MIDNIGHT_URL/api/v1alpha/operations/$OPERATION_ID/events?after=0&stream=sse" -H "Authorization: Bearer $MIDNIGHT_TOKEN"- 1
Persist the operation ID
It is the stable handle for status, events, logs, cancellation, and support evidence.
- 2
Advance the cursor
Store the last event sequence and reconnect with
afterso a dropped stream can resume without pretending the gap did not occur. - 3
Wait for terminal state
Only
SUCCEEDEDproves the operation completed. Then verify the deployment, health, and route resources relevant to the action.
HIGH-VALUE ROUTES
Start with the core resource path.
| Method | Path | Purpose |
|---|---|---|
| POST | /api/v1alpha/auth/sessions | Create a human session |
| GET | /api/v1alpha/auth/me | Read the verified human principal |
| GET · POST | /api/v1alpha/projects | List or create projects |
| GET · POST | /api/v1alpha/environments | List or create environments |
| GET · POST | /api/v1alpha/services | List or create services |
| GET · PUT | /api/v1alpha/services/{service_id}/environments/{environment_id}/config | Read or replace service configuration |
| GET · POST | /api/v1alpha/services/{service_id}/environments/{environment_id}/variables | List metadata or create a write-only variable |
| POST | /api/v1alpha/services/{id}/deployments | Queue a digest-pinned image deployment |
| POST | /api/v1alpha/services/{id}/up | Upload source and queue a build |
| GET | /api/v1alpha/operations/{id} | Read authoritative operation state |
| GET | /api/v1alpha/operations/{id}/events | Read or stream operation events |
| GET | /api/v1alpha/operations/{id}/logs | Read backed operation logs |
PROBLEM DETAILS
Branch on code, preserve request_id.
Errors use application/problem+json with a stable machine-readable code, HTTP status, human detail, and request_id. Branch on the code rather than parsing message text.
{
"type": "https://midnight.dev/docs/errors#PRECONDITION_FAILED",
"title": "Precondition failed",
"status": 412,
"detail": "If-Match does not match the current resource version.",
"code": "PRECONDITION_FAILED",
"request_id": "req_example"
}