Zenifra API

The Zenifra API lets you automate everything you do in the console: create and remove projects, publish new versions, configure variables, domain, instances, and auto-scaling, follow builds, logs, and metrics, and operate databases, managed services, scheduled Jobs, and preview environments.

This page covers what applies to every route: authentication, permissions, response format, asynchronous operations, rate limits, and status codes. Each reference page describes the fields, permissions, and errors specific to its endpoints.

Base URL

All routes use the /v1 prefix:

https://api.zenifra.com/v1

Send JSON bodies with Content-Type: application/json.

Authentication

Create the key in Organization → API Keys in the console. It belongs to the organization, grants only the scopes you choose, and can have an expiration date and an allowed IP list. The secret starts with znf_ and is shown only once, when the key is created. See Organization API Keys.

Send the key in one of these headers:

-H "x-api-key: znf_..."
# or
-H "Authorization: Bearer znf_..."

The organization is identified by the key itself, so the x-organization-id header is not needed for these calls.

User session token

Integrations that act on behalf of a person use Authorization: Bearer <token> and must send the active organization in x-organization-id. Without this header, the API responds 400 or 403, depending on the route.

Some routes only accept a user token, such as creating and revoking Git connections (owner session required), preview environment settings, and member management. The pages for those routes state this restriction.

Legacy project keys

Older keys bound to a single project are still accepted only to update the published image (Update image) and to operate preview environments with the opt-in enabled. For any other route, use an organization API key.

Headers

HeaderWhen to useDescription
x-api-key or Authorization: Bearer znf_...AutomationOrganization API key
Authorization: Bearer <token>User sessionLogin token
x-organization-idRequired with a user tokenActive organization. Ignored when the credential is an organization API key
Content-Type: application/jsonRequests with a bodyPayload format
Idempotency-KeyRoutes that accept itAvoids duplicate operations when a request is retried; see below

Permissions

An owner session has full access. assistant and member users and API keys need the action scope on the right resource, either by specific ID or with * for every resource of that type:

TaskMinimum scope
Create an HTTP project or scheduled Jobproject.create on organization:*
Create a database (PostgreSQL, MariaDB, or Analytics)database.create on organization:*
Create Key-Value, Cache, or Queue (Valkey)managed_service.create on organization:*
View a projectproject.read on project:<project-id>
Metrics and storage usageproject.metrics.read on project:<project-id>
Logs and buildsproject.logs.read on project:<project-id>
Publish a new imageproject.image.update on project:<project-id>
Remove a projectproject.delete on project:<project-id>

The complete scope catalog is in Organization API Keys. An API key used from an IP outside its allowed list receives 403 with the code API_KEY_IP_NOT_ALLOWED; an expired or revoked key receives 401.

Response format

Responses use a JSON envelope with status:

{
  "status": "success",
  "data": { }
}

Errors return status: "failed" with a readable message and, when available, a stable code to handle in your code:

{
  "status": "failed",
  "code": "PROJECT_MUST_BE_RUNNING",
  "message": "project must be running to update autoscaling"
}

Use the code (when present) and the HTTP status to decide what to do; do not depend on the exact message text.

On most routes the body is validated before authentication. Because of that, an invalid payload returns 400 even when the credential is also missing.

Asynchronous operations and idempotency

Long-running operations, such as builds, previews, and managed service credential rotation, respond 202 Accepted with an operation identifier. Template deployments respond 201 with the deployment state. Check the state on the route indicated by the resource page until the operation finishes.

Routes that accept the Idempotency-Key header use it to return the same operation when the request is repeated, without creating a second resource. Generate a unique value per operation (for example, a UUID) and reuse it only when retrying exactly the same request.

Rate limits

Each route has its own limit, counted per source IP address, method, and route. Reads usually allow more calls per minute than writes, and sensitive operations, such as plan or exposure changes, have lower limits. Each resource page lists the relevant limits.

When the limit is exceeded, the API responds 429 Too Many Requests with a message that says how many seconds to wait. Implement retries with increasing backoff.

HTTP status codes

CodeMeaning
200Request succeeded
201Resource created
202Operation accepted and processed in the background
400Invalid data, missing required header, or operation not supported for the project type
401Missing, invalid, expired, or revoked credential; on some older routes, plan without the feature
402Plan without metrics, or organization with a pending payment
403Insufficient permission, resource outside the credential scope, IP not allowed, or plan without the feature (e.g. HEALTHCHECK_NOT_AVAILABLE_FOR_PLAN)
404Resource not found (project, organization, build, preview, run)
409Conflict with the current state, such as an operation in progress, a stopped project, or no capacity available on the plan
429Rate limit exceeded or change in a cooldown period
500Internal error
502A dependent step of the operation failed
503Feature temporarily unavailable; try again later

Endpoints by area

Projects

TaskPageMain endpoints
Create, list, and remove projects; read plansProjectsPOST /project, GET /project, DELETE /project/:id, GET /project/plans
Read project, name, description, and exposureProject InformationGET /project/:id, PATCH /project/:id/name, PATCH /project/:id/exposure
Stop or resumeLifecyclePATCH /project/:id/stop, PATCH /project/:id/resume
Change plan and renewalPlanPATCH /project/:id/plan
Scale instancesInstancesGET /project/:id/instances, PATCH /project/:id/instances
Configure auto-scalingAuto-scalingPATCH /project/:id/autoscaling
Configure health checksHealth checkGET /project/:id/healthcheck, PATCH /project/:id/healthcheck
Email warningsAlertsGET /project/:id/alerts, PATCH /project/:id/alerts
Environment variablesEnvironment VariablesGET /project/:id/envs, PATCH /project/:id/envs
StorageStoragePATCH /project/:id/storage/size, GET /project/:id/storage/usage
Subdomain and custom domainsDomainPATCH /project/:id/domain, PATCH /project/:id/custom-domains
Restrict access by IPNetwork accessPATCH /project/:id/network-access
Project costsProject billingGET /project/:id/billing/hourly-usage, GET /project/:id/billing/ledger
Scheduled JobsScheduled JobsPATCH /project/:id/schedule, GET /project/:id/job-runs

Deploy

TaskPageMain endpoints
Publish an imageUpdate Deploy ImagePATCH /project/:id/image
Publication historyDeploymentsGET /project/:id/historic/deployments
Connect repositories and configure the sourceGit connections and sources/git/providers, /git/connections, /project/:id/source
Trigger and follow buildsGit repository buildsPOST /project/:id/deploy, GET /project/:id/builds, GET /project/:id/builds/:buildId/logs
Preview environmentsPreview EnvironmentsPUT /project/:id/preview-environments/:previewKey
TemplatesTemplatesGET /templates, POST /templates/:id/deployments

The /project/:id/github/* routes remain available for older GitHub projects. For new integrations, use the /project/:id/deploy and /project/:id/builds routes, which work with any Git provider.

Data and services

TaskPageMain endpoints
Database status, connection, password, and versionDatabasesGET /project/:id/database/status, GET /project/:id/database/connection
Key-Value, Cache, and Queue (Valkey)Managed servicesGET /managed-services/:id/connection, PATCH /managed-services/:id/credentials

Observability

TaskPageMain endpoints
Metrics and logsMetrics and LogsGET /project/:id/metrics, GET /project/:id/logs
HTTP trafficNetwork MetricsGET /project/:id/metrics/network/*

Examples

cURL

curl "https://api.zenifra.com/v1/project/507f1f77bcf86cd799439011" \
  -H "x-api-key: $ZENIFRA_API_KEY"

Python

import os
import requests

BASE_URL = "https://api.zenifra.com/v1"
headers = {"x-api-key": os.environ["ZENIFRA_API_KEY"]}

response = requests.get(
    f"{BASE_URL}/project/507f1f77bcf86cd799439011/metrics",
    headers=headers,
    timeout=30,
)
response.raise_for_status()
print(response.json()["data"])

Node.js

const BASE_URL = 'https://api.zenifra.com/v1'

async function getMetrics(projectId) {
  const response = await fetch(`${BASE_URL}/project/${projectId}/metrics`, {
    headers: { 'x-api-key': process.env.ZENIFRA_API_KEY },
  })

  if (!response.ok) {
    throw new Error(`Zenifra API ${response.status}: ${await response.text()}`)
  }

  return (await response.json()).data
}

getMetrics('507f1f77bcf86cd799439011').then(console.log)

Store the API key in an environment variable or secret manager; never put it in source code or frontend applications.

FAQ

Where do I find the API key and the project ID?

The API key is created in Organization → API Keys; the secret is shown only once, so store it securely when you create it. If you lose the secret, revoke the key and create another one. The project ID is shown in the console, in the project page URL, and in the GET /v1/project response.

Does one API key work for every project?

It works for the resources and actions you choose when creating it. Use the specific project ID to limit the key to one project, or * for all current and future projects in the organization. Prefer keys with the fewest scopes, separated by environment or integration.

Is x-organization-id always required?

No. With an organization API key, the organization comes from the key itself. With a user token, the header is required.

Is there a rate limit?

Yes. Limits vary by route and are counted per source IP. When you receive 429, wait for the time shown in the response before retrying. For high-volume automation, contact support.

Can I use the CLI or MCP instead of the API?

Yes. The CLI and the MCP server use the same API and the same permissions, and are the fastest path for scripts and assistants.

Last updated on

On this page