{
 "openapi": "3.1.0",
 "info": {
  "title": "Gyro Public API",
  "version": "2.30.0",
  "summary": "Manage Gyro cloud servers, SSH keys and billing programmatically.",
  "x-summary-tr": "Gyro bulut sunucularınızı, SSH anahtarlarınızı ve faturalarınızı programla yönetin.",
  "contact": {
   "name": "Gyro Hosting",
   "url": "https://www.gyrohosting.com"
  },
  "license": {
   "name": "Proprietary",
   "identifier": "LicenseRef-Gyro-API-Terms"
  }
 },
 "servers": [
  {
   "url": "https://www.gyrohosting.com/api/v1/client",
   "description": "Production"
  }
 ],
 "paths": {
  "/cloud/containers/{id}": {
   "get": {
    "tags": [
     "Containers"
    ],
    "operationId": "getContainerEnvironment",
    "summary": "Container environment detail (namespace, internal addressing, egress IPs)",
    "x-summary-tr": "Kapsayıcı ortamı ayrıntısı (namespace, iç adresleme, çıkış IP'leri)",
    "x-scope": "services_read",
    "description": "Environment code, Kubernetes **namespace**, in-cluster addressing (`cluster_dns`), plan limits, nodes, quota, ingress IPs and the current **egress IPs**. Egress IPs of a **dedicated** environment = the public IPs of its own nodes + the shared pool node(s) used while an update rolls out (the new copy starts there for about a minute, then moves back to your node). **Serverless** = the shared sandboxed pool nodes (the pool can grow: a new address can appear). Build machines of Gyro Pipeline are listed separately (`build_ips`). The list changes when the nodes change (plan change, node replacement, pool scaling); the owner is notified (Alerts channels, event `egress`). No IPv6 egress; outbound TCP 25 is closed. A fixed egress address is not offered yet.",
    "x-description-tr": "Ortam kodu, Kubernetes **namespace** adı, iç adresleme (`cluster_dns`), paket sınırları, düğümler, kota, giriş IP'leri ve güncel **çıkış IP'leri**. **Ayrılmış** ortamın çıkış IP'leri = kendi düğümlerinin IP'leri + güncelleme sırasında kullanılan paylaşımlı havuz düğümü (yeni kopya yaklaşık bir dakika orada başlar, sonra düğümünüze döner). **Sunucusuz** = paylaşımlı yalıtılmış havuz düğümleri (havuz büyürse yeni adres eklenebilir). Gyro Pipeline derleme makineleri ayrı listelenir (`build_ips`). Düğümler değişince (paket değişimi, düğüm yenileme, havuz ölçeklemesi) liste değişir ve ortam sahibine bildirim gider (Uyarılar kanalları, `egress` olayı). IPv6 çıkışı yok; TCP 25 kapalı.",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer"
      },
      "description": "Service id"
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "data": {
           "$ref": "#/components/schemas/ContainerEnvironment"
          }
         }
        }
       }
      }
     },
     "404": {
      "$ref": "#/components/responses/NotFound"
     }
    },
    "x-cli": {
     "command": "container get",
     "confirm": false
    }
   }
  }
 },
 "components": {
  "responses": {
   "NotFound": {
    "description": "Not found — also returned for objects owned by someone else",
    "content": {
     "application/json": {
      "schema": {
       "$ref": "#/components/schemas/Error"
      }
     }
    }
   }
  },
  "schemas": {
   "Error": {
    "type": "object",
    "required": [
     "error"
    ],
    "properties": {
     "error": {
      "type": "object",
      "required": [
       "code",
       "message"
      ],
      "properties": {
       "code": {
        "type": "string",
        "example": "server_not_found"
       },
       "message": {
        "type": "string"
       },
       "details": {
        "type": "object",
        "additionalProperties": true,
        "description": "Extra data. Limit refusals add the LimitHint fields (`limit_exceeded: true`, `limit_key`, `limit`, `current`, `how_to_increase`, `support_ticket`, `hint`): account limits are raised with a support ticket. Validation errors (length, format) never carry the limit hint.",
        "x-description-tr": "Ek veri. Sınır retlerinde LimitHint alanları gelir: hesap sınırları destek talebiyle artırılır. Doğrulama hataları (uzunluk, biçim) sınır ipucu taşımaz."
       }
      }
     }
    }
   },
   "ContainerEnvironment": {
    "type": "object",
    "properties": {
     "code": {
      "type": "string",
      "example": "ab12cd"
     },
     "namespace": {
      "type": "string",
      "example": "t-canli-12345",
      "description": "Kubernetes namespace of the environment"
     },
     "mode": {
      "type": "string",
      "enum": [
       "dedicated",
       "serverless"
      ]
     },
     "cluster_dns": {
      "type": "object",
      "description": "in-cluster addressing: from the same environment a service is reached at `<service>.<namespace>.svc.cluster.local:80` or `<service>:80` (port 80 is forwarded to the container port; only services with a port)",
      "properties": {
       "namespace": {
        "type": "string"
       },
       "service_domain": {
        "type": "string",
        "example": "t-canli-12345.svc.cluster.local"
       },
       "service_port": {
        "type": "integer",
        "const": 80
       },
       "pattern": {
        "type": "string",
        "example": "<service>.t-canli-12345.svc.cluster.local:80"
       },
       "short_pattern": {
        "type": "string",
        "example": "<service>:80"
       }
      }
     },
     "host_suffix": {
      "type": "string",
      "example": "-ab12cd.gyroapp.net"
     },
     "suspended": {
      "type": "boolean"
     },
     "services": {
      "type": "integer"
     },
     "ready_replicas": {
      "type": "integer"
     },
     "limits": {
      "type": "object"
     },
     "nodes": {
      "type": "array",
      "items": {
       "type": "object"
      }
     },
     "quota": {
      "type": "object"
     },
     "ingress_ips": {
      "type": "array",
      "items": {
       "type": "string"
      },
      "description": "inbound address (apex A record of a custom domain)"
     },
     "egress_ips": {
      "type": "array",
      "items": {
       "type": "string"
      },
      "description": "same as egress.ips"
     },
     "egress_note": {
      "type": "string"
     },
     "egress": {
      "$ref": "#/components/schemas/ContainerEgress"
     },
     "base_nodes": {
      "type": "integer",
      "description": "nodes of the plan"
     },
     "extra_nodes": {
      "type": "integer"
     },
     "node_count": {
      "type": "integer"
     },
     "max_extra_nodes": {
      "type": "integer"
     },
     "max_nodes": {
      "type": "integer",
      "const": 20
     },
     "node_monthly_eur": {
      "type": "number",
      "description": "price of one node per month (an extra node costs the same)"
     },
     "egress_hold_hours": {
      "type": "integer",
      "description": "approval window (0 = off)"
     },
     "egress_change": {
      "$ref": "#/components/schemas/ContainerEgressChange"
     },
     "pending_egress_ips": {
      "type": "array",
      "items": {
       "type": "string"
      },
      "description": "new egress IPs announced but not in use for sure yet; add them to your allow lists now"
     }
    }
   },
   "ContainerEgressChange": {
    "type": [
     "object",
     "null"
    ],
    "description": "Announced change of the egress IPs (plan change, node added / removed). Null when none.",
    "x-description-tr": "Duyurulan çıkış IP değişikliği (paket değişikliği, düğüm ekleme / çıkarma). Yoksa null.",
    "properties": {
     "id": {
      "type": "string",
      "example": "cm3k9x2a1"
     },
     "kind": {
      "type": "string",
      "enum": [
       "plan",
       "add",
       "remove",
       "mixed"
      ]
     },
     "state": {
      "type": "string",
      "enum": [
       "preparing",
       "pending",
       "approved",
       "applied"
      ],
      "description": "preparing = new addresses not known yet; pending = announced (waits for approval when approval_required); approved = old nodes are being drained; applied = done (kept 24 h)"
     },
     "new_ips": {
      "type": "array",
      "items": {
       "type": "string"
      }
     },
     "remove_ips": {
      "type": "array",
      "items": {
       "type": "string"
      }
     },
     "keep_ips": {
      "type": "array",
      "items": {
       "type": "string"
      }
     },
     "approval_required": {
      "type": "boolean"
     },
     "awaiting_approval": {
      "type": "boolean"
     },
     "hold_hours": {
      "type": "integer"
     },
     "pending_since": {
      "type": "string",
      "format": "date-time"
     },
     "deadline": {
      "type": "string",
      "format": "date-time",
      "description": "the change continues by itself at this time without approval"
     },
     "approved_at": {
      "type": "string"
     },
     "approved_by": {
      "type": "string",
      "enum": [
       "",
       "owner",
       "deadline",
       "automatic"
      ]
     },
     "applied_at": {
      "type": "string"
     }
    }
   },
   "ContainerEgress": {
    "type": "object",
    "description": "Public IPv4 addresses the containers of the environment reach the internet from (no NAT gateway: traffic leaves from the node the container runs on).",
    "x-description-tr": "Ortamdaki kapsayıcıların internete çıktığı IPv4 adresleri (NAT kapısı yok: trafik kapsayıcının çalıştığı düğümden çıkar).",
    "properties": {
     "mode": {
      "type": "string",
      "enum": [
       "dedicated",
       "serverless"
      ]
     },
     "ips": {
      "type": "array",
      "items": {
       "type": "string",
       "format": "ipv4"
      },
      "description": "Put ALL of them on the IP allow list of an external service.",
      "example": [
       "31.58.248.114",
       "45.87.174.168"
      ]
     },
     "items": {
      "type": "array",
      "items": {
       "type": "object",
       "properties": {
        "ip": {
         "type": "string"
        },
        "source": {
         "type": "string",
         "enum": [
          "node",
          "rollout",
          "shared_pool"
         ],
         "description": "node = a node of the dedicated pool (always used); rollout = shared pool where the new copy starts during an update (about a minute) before it moves back; shared_pool = serverless pool node"
        },
        "node": {
         "type": "string",
         "example": "node-1"
        }
       }
      }
     },
     "build_ips": {
      "type": "array",
      "items": {
       "type": "string"
      },
      "description": "Gyro Pipeline build machines (git clone / archive download only)"
     },
     "hash": {
      "type": "string",
      "description": "changes whenever `ips` change (compare to detect a change)"
     },
     "ipv6": {
      "type": "boolean",
      "const": false,
      "description": "no IPv6 egress"
     },
     "note": {
      "type": "string"
     },
     "egress_change": {
      "$ref": "#/components/schemas/ContainerEgressChange"
     },
     "pending_egress_ips": {
      "type": "array",
      "items": {
       "type": "string"
      },
      "description": "new egress IPs announced but not in use for sure yet; add them to your allow lists now"
     },
     "egress_hold_hours": {
      "type": "integer",
      "description": "approval window (0 = off)"
     }
    }
   }
  }
 },
 "security": [
  {
   "bearerAuth": []
  }
 ]
}