OpenRelay Internal API

Machine-to-machine endpoints used by platform infrastructure. Not part of the public API.

OpenAPI Specification

openrelay-internal-api-openapi.yml Raw ↑
openapi: 3.1.0
info:
  description: 'The OpenRelay control-plane REST API. Deploy GPU VMs and inference clusters, manage organizations and billing, and automate your infrastructure. All requests are authenticated with an API key (`vl_…`) unless noted otherwise.

    '
  title: OpenRelay Account Internal API
  version: 0.1.0
servers:
- description: Production
  url: https://api.openrelay.inc
- description: Beta
  url: https://api.beta.openrelay.inc
- description: Local development
  url: http://localhost:8083
tags:
- description: Machine-to-machine endpoints used by platform infrastructure. Not part of the public API.
  name: Internal
  x-internal: true
paths:
  /health:
    get:
      operationId: getHealth
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Health'
          description: Service is up
      summary: Liveness probe (no auth)
      tags:
      - Internal
      x-internal: true
  /v1/nodes/enroll:
    post:
      operationId: enrollNode
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/EnrollNodeRequest'
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EnrollNodeBundle'
          description: Enrolled
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Invalid/expired token
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Revoked
        '409':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Node busy (reassign blocked) or hostname conflict
        '429':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Quota exhausted
      security: []
      summary: Self-enroll a node using a provisioning token (no API key)
      tags:
      - Internal
      x-internal: true
components:
  schemas:
    GpuInventory:
      description: 'Versioned, driverless GPU detection (lspci) collected by enroll.sh. Works on VFIO hosts with no NVIDIA driver and on non-NVIDIA accelerators. source=none means the node could not detect (no lspci) — the control plane must NOT treat that as "no GPUs".

        '
      properties:
        devices:
          items:
            properties:
              bdfs:
                description: full BDFs of the group's devices
                items:
                  type: string
                type: array
              count:
                type: integer
              pciClass:
                description: PCI class code, e.g. 0300/0302/1200
                type: string
              pciDeviceId:
                description: vendor:device, e.g. 10de:2204
                type: string
              pciName:
                description: lspci device name string
                type: string
            required:
            - pciDeviceId
            - count
            type: object
          type: array
        driverVersion:
          type: string
        iommuGroups:
          description: 'Per-IOMMU-group VFIO units: each entry is one IOMMU group containing an NVIDIA/AMD GPU. A group''s GPUs are indivisible (must be passed together). Empty when IOMMU is off (gVisor/CPU nodes) — those GPUs are fed via the Nomad device fingerprint instead. Kept out of the hardware fingerprint (BDFs renumber across reboots).

            '
          items:
            properties:
              gpus:
                description: GPU-class (0300/0302) NVIDIA/AMD devices in this group — the sellable + passthrough set
                items:
                  properties:
                    bdf:
                      description: full BDF, e.g. 0000:04:00.0
                      type: string
                    deviceId:
                      description: vendor:device, e.g. 10de:2204
                      type: string
                  required:
                  - bdf
                  - deviceId
                  type: object
                type: array
              group:
                description: IOMMU group number (provenance)
                type: integer
            required:
            - group
            - gpus
            type: object
          type: array
        nvswitchCount:
          description: NVSwitch bridges (PCI class 0680, vendor 10de) on the node
          type: integer
        source:
          description: none | lspci | lspci+nvidia-smi
          type: string
        version:
          type: integer
      required:
      - version
      - source
      - devices
      - nvswitchCount
      type: object
    Health:
      properties:
        service:
          type: string
        status:
          type: string
      required:
      - status
      - service
      type: object
    Error:
      properties:
        code:
          type: string
        error:
          type: string
      required:
      - error
      type: object
    EnrollNodeRequest:
      properties:
        cpuCores:
          type: integer
        cpuModel:
          type: string
        gpuInventory:
          $ref: '#/components/schemas/GpuInventory'
        gpus:
          description: LEGACY nvidia-smi detection (name + pci.bus_id BDF — NOT a vendor:device id despite the example). Kept for old scripts; gpuInventory supersedes it.
          items:
            properties:
              name:
                type: string
              pciId:
                description: nvidia-smi pci.bus_id (a BDF like 00000000:04:00.0)
                type: string
            required:
            - pciId
            type: object
          type: array
        hardwareFingerprint:
          type: string
        hostname:
          type: string
        identityPubkey:
          description: 'Node ed25519 identity public key (base64 raw, 32 bytes). Identity v2 collision-safe anchor: the box generates this once, keeps the private key at /etc/vectorlay/identity.key, and signs every enroll with it. Optional — absent = legacy (v1) enroll.'
          type: string
        machineId:
          description: Stable per-box identity (SMBIOS product_uuid / serial / cloud instance-id). Primary global node-identity key; fingerprint is the fallback when empty.
          type: string
        nebulaPubkey:
          description: Node Nebula public key PEM (from nebula-cert keygen)
          type: string
        ramGb:
          type: integer
        runtime:
          description: 'Node runtime detected by enroll.sh: qemu (VFIO/KVM passthrough) or gvisor (container GPUs). Default gvisor.'
          type: string
        signature:
          description: base64 ed25519 signature (v2) proving possession of identityPubkey over the identity-critical enroll fields (token hash, identity pubkey, nebula pubkey hash, fingerprint, machineId, hostname, signedAt). Required iff identityPubkey is set.
          type: string
        signedAt:
          description: Unix seconds when the enroll body was signed (v2). Rejected if more than 300s from server time.
          type: integer
        token:
          description: Provisioning token (vtk_...)
          type: string
      required:
      - token
      - hardwareFingerprint
      - nebulaPubkey
      type: object
    EnrollNodeBundle:
      properties:
        dataPlaneCa:
          description: CertIssuer CA the gateway pins; optional
          type: string
        dataPlaneCert:
          description: node data-plane mTLS cert (gateway tunnel); optional
          type: string
        dataPlaneKey:
          description: node data-plane mTLS key; optional
          type: string
        datacenter:
          type: string
        gatewayAddr:
          description: host:port the node-agent dials (QUIC/UDP); optional
          type: string
        gatewayServerName:
          description: expected CN on the gateway server cert; optional
          type: string
        nebulaCa:
          type: string
        nebulaCert:
          type: string
        nebulaLighthouses:
          items:
            properties:
              endpoint:
                description: publicIp:4242
                type: string
              nebulaIp:
                type: string
            required:
            - nebulaIp
            - endpoint
            type: object
          type: array
        nebulaOverlayIp:
          type: string
        nodeAgentToken:
          description: durable node token for the node-agent self-update fetch (GET /v1/nodes/agent); optional
          type: string
        nodeId:
          type: string
        nomadCa:
          type: string
        nomadClientCert:
          type: string
        nomadClientKey:
          type: string
        nomadIntroToken:
          type: string
        nomadPool:
          type: string
        nomadServers:
          description: server Nebula RPC addrs (ip:4647)
          items:
            type: string
          type: array
      required:
      - nodeId
      - nebulaCert
      - nebulaCa
      - nebulaOverlayIp
      - nebulaLighthouses
      - nomadCa
      - nomadClientCert
      - nomadClientKey
      - nomadServers
      - nomadIntroToken
      - nomadPool
      - datacenter
      - dataPlaneCert
      - dataPlaneKey
      - dataPlaneCa
      - gatewayAddr
      - gatewayServerName
      type: object
  securitySchemes:
    apiKey:
      description: 'OpenRelay API key. Send it as `Authorization: Bearer vl_…`.'
      scheme: bearer
      type: http