Set Primary Endpoint

PUT /v1/applications/{uuid}/primary-endpoint

An application can be served by several endpoints, and one of them is its primary. This call makes one of the app's endpoints the primary, which changes the app's canonical URL: the primary's hostname is the host the app's cron jobs call and, for a WordPress app, the site address. WordPress then redirects visitors on the app's other endpoints to the primary. Every endpoint keeps serving the production deploy with its own settings; only the primary changes.

The app's first endpoint becomes its primary automatically. If you delete the primary endpoint, the app's oldest remaining served endpoint takes over. GET /v1/applications/{uuid} lists the app's endpoints and names the primary in primary_endpoint_uuid. See Domains, endpoints & HTTPS for the dashboard side.

Requires the caller's account to have Endpoints write permission (as other application changes). Setting the current primary again succeeds and changes nothing.

Request body

endpoint_uuid string (uuid)
Required. One of this app's endpoints. It must be served: an endpoint paused over your plan's limits, on a custom domain paused over your plan's limits, or suspended by the ngris team can't be the primary.

Response (200 OK)

Returns the updated application, the same object as GET /v1/applications/{uuid}: primary_endpoint_uuid names the new primary and its entry in endpoints has primary: true.

Errors

400
The body is not JSON (invalid request body), endpoint_uuid is missing (endpoint_uuid is required), or it is not a uuid ({"error":"endpoint_uuid must be a uuid","param":"endpoint_uuid"}).
403
Your role lacks Endpoints write, or the plan has no application hosting.
404
application not found or endpoint not found: no such app or endpoint in the active account (another account's reads the same).
409
this endpoint does not serve this application: the endpoint is another app's, or a tunnel endpoint.
endpoint_not_served: the endpoint isn't served, so it can't be the primary. reason says why: quota_paused (paused over your plan's endpoint limit), domain_quota_paused (its custom domain is paused over your plan's limit) or admin_suspended (the ngris team suspended it; contact support).
quota_paused: the app itself is paused over your plan's limits and is read-only until the account has room again.

Deprecated: until the sunset the application object also carries the legacy integer id and *_id fields. Don't use them; read uuid and the *_uuid fields.

Request
curl -X PUT \ "https://api.ngris.com/v1/applications/019be838-d261-7d9b-9499-71995a3a91c6/primary-endpoint" \ -H "X-API-KEY: <your_api_key>" \ -H "Content-Type: application/json" \ -d '{ "endpoint_uuid": "019bb1e4-e785-77d2-9966-c3cff31d0a0e" }'
Response — 200 OK
{ "uuid": "019be838-d261-7d9b-9499-71995a3a91c6", "name": "my-site", "type": "static", "primary_endpoint_uuid": "019bb1e4-e785-77d2-9966-c3cff31d0a0e", "endpoints": [ { "uuid": "019bb1e2-6f10-7c41-a1d3-2b8e4c9f0a17", "hostname": "example.com", "url": "https://example.com", "primary": false, "serving_mode": "agentless", "status": "active", "tls_status": "issued", "tls_source": "domain", "tls_expires_at": "2027-01-05T10:00:00Z", "quota_paused": false, "auth_mode": "none", "auth_protected": false, "created_at": "2026-10-01T09:00:00Z" }, { "uuid": "019bb1e4-e785-77d2-9966-c3cff31d0a0e", "hostname": "www.example.com", "url": "https://www.example.com", "primary": true, "serving_mode": "agentless", "status": "active", "tls_status": "issued", "tls_source": "domain", "tls_expires_at": "2027-01-05T10:00:00Z", "quota_paused": false, "auth_mode": "none", "auth_protected": false, "created_at": "2026-10-16T14:30:00Z" } ] }
Response — 409 (endpoint not served)
{ "error": "This endpoint is paused over your plan's limit, so it can't be the primary endpoint.", "code": "endpoint_not_served", "reason": "quota_paused" }
On this page
Set Primary Endpoint