v1.0.0
OpenAPI 3.1.0

Phaze Enterprise API

Please note: This is an early v1 release of the Phaze Enterprise API. We may need to introduce breaking changes to this version in the future. For example, we plan to change how Phaze Relays are managed within an organization, which may affect parts of this API. Before introducing that change, we will email all customers who have created an API key to make sure they're aware of the expected change.

Overview

The Phaze Enterprise API is a REST interface for managing your enterprise from your own tools and automation. With an API key created in the Phaze admin dashboard, you can invite and manage members, organize them into organizations and groups, control who can reach which machines, and run the locations and relays that carry connections inside your network. This API is available to enterprises on a Phaze Enterprise plan.

Authentication

Every request must carry an enterprise API key as a Bearer token in the Authorization header (Authorization: Bearer <key>). Keys are created by enterprise admins in the Phaze web app and are scoped to a single enterprise. Every resource in this API is resolved within that enterprise, so an organization or user that belongs to another enterprise is reported as 404 not_found. Unknown, revoked, or expired keys receive 401 unauthorized.

Rate limits

Limits are enforced per enterprise, so all keys of one enterprise share the same budget. Exceeding a limit returns 429 too_many_requests and starts a lockout during which every request in that scope is rejected.

Scope Limit Lockout after exceeding
Default, all endpoints 200 requests per minute 5 minutes
Email sending: POST /invites and POST /invites/resend when send_email is true 10 requests per 10 minutes 10 minutes

Rate limit headers

Every response includes the current rate limit state for its scope.

Header Description
X-RateLimit-Limit Maximum number of requests allowed in the current window
X-RateLimit-Remaining Requests left in the current window, 0 while rejected
Retry-After Seconds to wait before retrying. Only present on 429 responses

Pagination

List endpoints accept the following query parameters. Out-of-range values are clamped rather than rejected. The response count is the total number of matching items, so offset + limit < count means more pages remain.

Parameter Default Description
limit 50 Number of items per page, from 1 to 200
offset 0 Number of items to skip, 0 or greater

Requests

  • The base URL is https://public-api.phaze.app/enterprise/v1. All paths in this reference are relative to it.
  • Request bodies must be JSON and sent with Content-Type: application/json. Other media types receive 415.
  • Requests time out after 10 seconds.
  • PATCH endpoints are partial updates. Send only the fields to change; omitted fields keep their current value. A body with no updatable fields is rejected with 400.
  • Bulk endpoints take an array of items with a per-endpoint maximum. Duplicates are rejected with 422. Where an endpoint can partially succeed, valid items are applied and the rest are returned under rejected with a reason.

Responses

Every JSON response carries a status field with the HTTP status text. Single resources are returned under data. Lists return an array under data plus a count of the total items matching the query across all pages. 204 No Content responses have no body.

// single resource
{ "status": "OK", "data": { ... } }
// paginated resources
{ "status": "OK", "data": [ ... ], "count": 0 }

Errors

The API uses standard HTTP status codes. Unsuccessful responses carry an errors array where each item has a machine-readable code and a human-readable message. Validation failures return 422 with one item per invalid field, where field names the request body field.

// error
{ "status": "Not Found", "errors": [ { "code": "not_found", "message": "..." } ] }
// validation error
{ "status": "Unprocessable Entity", "errors": [ { "code": "validation_failed", "field": "role", "message": "..." } ] }
Status Code When
400 bad_request Malformed JSON, invalid path or query parameter, or an empty update
401 unauthorized Missing, unknown, or expired API key
403 forbidden The operation is disabled for this enterprise
403 limit_reached A resource limit was hit, the message names the limit
404 not_found The resource does not exist in this enterprise
405 method_not_allowed Unsupported method for the path
409 conflict A resource with the same name already exists
409 org_not_empty The organization cannot be deleted while it has machines or relays
409 location_has_relays The location cannot be deleted while it has relays
415 unsupported_media_type Request body is not application/json
422 validation_failed One or more request body fields are invalid
429 too_many_requests Rate limit exceeded, see Retry-After
500 internal_server_error Unexpected server error

Timestamps

Timestamps in request and response bodies are RFC 3339 strings in UTC, for example 2026-09-04T18:21:07Z.

Resource limits

Creating a resource beyond these limits fails with 403 limit_reached.

Resource Limit
Organizations per enterprise 20
Members per enterprise, pending invites included 5000
Members per organization 2000
Machine keys per organization 100
Groups per organization 200
Members per group 500
Locations per organization 100
Relays per organization 200

SCIM

When directory sync (SCIM) is enabled for the enterprise, the identity provider owns the member lifecycle. Creating, resending, or deleting invites and deleting members return 403 forbidden. Role changes and organization assignments remain available.

Server:https://public-api.phaze.app/enterprise/v1

Production

Client Libraries

Invite

Pending invitations for new members. An invite becomes a member when the recipient signs up through its signup link.

List pending invites

Lists invites that have not been accepted, including expired ones. Expired invites can be resent. signup_url is never included here.

Query Parameters
  • limit
    Type: integer
    min:  
    1
    max:  
    200

    Integer numbers.

  • offset
    Type: integer

    Integer numbers.

  • q
    Type: string

    Search by email

Responses
  • application/json
  • application/json
  • application/json
Request Example for get/invites
curl https://public-api.phaze.app/enterprise/v1/invites \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN'
{
  "status": "string",
  "data": [
    {
      "id": "string",
      "email": "hello@example.com",
      "signup_url": "https://example.com",
      "is_expired": true,
      "sender": {
        "id": "string",
        "name": "string",
        "email": "hello@example.com"
      },
      "expires_at": "2026-09-11T14:59:55.350Z",
      "created_at": "2026-09-11T14:59:55.350Z",
      "updated_at": "2026-09-11T14:59:55.350Z"
    }
  ],
  "count": 1
}

Invite users to the enterprise

Creates invites for the given emails. Emails that already belong to this enterprise or already have a pending invite are silently skipped. Invites expire after 7 days. Counts toward the email rate limit when send_email is true. Unavailable while SCIM is enabled.

Body
required
application/json
  • emails
    Type: array string[] 1…100 unique!
    required

    Email addresses to invite. Domains must be verified for the enterprise.

  • send_email
    Type: boolean
    required

    Set to true to send invite emails. Otherwise deliver the returned signup_url yourself

Responses
  • application/json
  • application/json
  • application/json
Request Example for post/invites
curl https://public-api.phaze.app/enterprise/v1/invites \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN' \
  --data '{
  "emails": [
    ""
  ],
  "send_email": false
}'
{
  "status": "string",
  "data": {
    "invited": [
      {
        "id": "string",
        "email": "hello@example.com",
        "signup_url": "https://example.com",
        "is_expired": true,
        "sender": {
          "id": "string",
          "name": "string",
          "email": "hello@example.com"
        },
        "expires_at": "2026-09-11T14:59:55.350Z",
        "created_at": "2026-09-11T14:59:55.350Z",
        "updated_at": "2026-09-11T14:59:55.350Z"
      }
    ],
    "rejected": [
      {
        "email": "hello@example.com",
        "reason": "string"
      }
    ]
  }
}

Revoke invites

Deletes the invites and invalidates their signup links. Unknown invite IDs are ignored. Unavailable while SCIM is enabled.

Body
required
application/json
  • invite_ids
    Type: array string[] 1…100 unique!
    required
Responses
  • 204

    No Content

  • application/json
  • application/json
Request Example for delete/invites
curl https://public-api.phaze.app/enterprise/v1/invites \
  --request DELETE \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN' \
  --data '{
  "invite_ids": [
    ""
  ]
}'
No Body

Resend invites

Issues a fresh signup link and expiry for each invite, invalidating the previous link. Unknown invite IDs are ignored. Counts toward the email rate limit when send_email is true. Unavailable while SCIM is enabled.

Body
required
application/json
  • invite_ids
    Type: array string[] 1…100 unique!
    required
  • send_email
    Type: boolean
    required

    Set to true to send invite emails. Otherwise deliver the returned signup_url yourself

Responses
  • application/json
  • application/json
  • application/json
Request Example for post/invites/resend
curl https://public-api.phaze.app/enterprise/v1/invites/resend \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN' \
  --data '{
  "invite_ids": [
    ""
  ],
  "send_email": false
}'
{
  "status": "string",
  "data": [
    {
      "id": "string",
      "email": "hello@example.com",
      "signup_url": "https://example.com",
      "is_expired": true,
      "sender": {
        "id": "string",
        "name": "string",
        "email": "hello@example.com"
      },
      "expires_at": "2026-09-11T14:59:55.350Z",
      "created_at": "2026-09-11T14:59:55.350Z",
      "updated_at": "2026-09-11T14:59:55.350Z"
    }
  ]
}

EnterpriseMember (Collapsed)

User accounts managed by the enterprise. Members are created by accepting an invite or through SCIM, then assigned to organizations.

Organization (Collapsed)

Top-level containers within the enterprise. Machines, machine keys, groups, locations, and relays all belong to an organization.

OrgMember (Collapsed)

Membership of enterprise members in an organization, with a per-organization role.

MachineKey (Collapsed)

Enrollment keys the Phaze host application uses to register machines into an organization.

Machine (Collapsed)

Group (Collapsed)

Named sets of organization members. Assigning a machine to a group gives every member of the group access.

GroupMember (Collapsed)

Membership of organization members in a group.

Location (Collapsed)

Private network sites within an organization. Machines and relays in the same location can exchange traffic through that location's relays.

Relay (Collapsed)

Relay servers that carry connections within a location when peers cannot connect directly. Configured with a relay key and addresses reachable from inside and outside the private network.

Connection (Collapsed)

Remote desktop sessions from members to an organization's machines, active and historical.

Connection Operations

Models