{
  "info": {
    "name": "GIGABIT Partner API · PL",
    "description": "API jest dostępne po aktywacji konta partnerskiego. Tworzenie i unieważnianie tokenu jest dostępne wyłącznie w panelu GIGABIT. Nowy token zastępuje poprzedni i jest wyświetlany tylko raz.\n\nDłuższa operacja zwraca HTTP 202 i id utworzony przez serwer. Status i wynik są dostępne przez GET /operations/{id}. Sprawdzenie statusu nie tworzy nowej operacji.",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "auth": {
    "type": "bearer",
    "bearer": [
      {
        "key": "token",
        "value": "{{partner_token}}",
        "type": "string"
      }
    ]
  },
  "variable": [
    {
      "key": "base_url",
      "value": "https://api.gigabit.ltd/api/partner/v1"
    },
    {
      "key": "partner_token",
      "value": ""
    },
    {
      "key": "order_id",
      "value": "a1b2c3d4e5f60123456789abcdef0123"
    },
    {
      "key": "operation_id",
      "value": "REPLACE_WITH_RESPONSE_ID"
    },
    {
      "key": "topup_id",
      "value": "ptop_REPLACE_WITH_RESPONSE_ID"
    }
  ],
  "item": [
    {
      "name": "Operacje",
      "item": [
        {
          "name": "Status operacji · W kolejce",
          "request": {
            "method": "GET",
            "header": [],
            "url": "{{base_url}}/operations/{{operation_id}}",
            "description": "Zwraca status i wynik operacji konta. Szybkie sprawdzenie bez ponownego wykonania.\n\n"
          },
          "response": [
            {
              "name": "W kolejce",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": "{{base_url}}/operations/{{operation_id}}",
                "description": "Zwraca status i wynik operacji konta. Szybkie sprawdzenie bez ponownego wykonania.\n\n"
              },
              "status": "OK",
              "code": 200,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"success\": true,\n  \"data\": {\n    \"id\": \"op_0123456789abcdef0123456789abcdef\",\n    \"state\": \"queued\",\n    \"error\": null,\n    \"result\": null,\n    \"created_at\": \"2026-11-10T12:00:00+00:00\",\n    \"status_url\": \"/api/partner/v1/operations/op_0123456789abcdef0123456789abcdef\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Status operacji · Zakończona",
          "request": {
            "method": "GET",
            "header": [],
            "url": "{{base_url}}/operations/{{operation_id}}",
            "description": "Zwraca status i wynik operacji konta. Szybkie sprawdzenie bez ponownego wykonania.\n\n"
          },
          "response": [
            {
              "name": "Zakończona",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": "{{base_url}}/operations/{{operation_id}}",
                "description": "Zwraca status i wynik operacji konta. Szybkie sprawdzenie bez ponownego wykonania.\n\n"
              },
              "status": "OK",
              "code": 200,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"success\": true,\n  \"data\": {\n    \"id\": \"op_0123456789abcdef0123456789abcdef\",\n    \"state\": \"ready\",\n    \"error\": null,\n    \"result\": {\n      \"id\": \"partner_0123456789abcdef0123456789abcdef\",\n      \"state\": \"ready\",\n      \"error\": null,\n      \"order_ids\": [\n        \"a1b2c3d4e5f60123456789abcdef0123\"\n      ],\n      \"amount_cents\": 4050,\n      \"currency\": \"EUR\",\n      \"price\": {\n        \"currency\": \"EUR\",\n        \"base_net_cents\": 4500,\n        \"net_cents\": 4050,\n        \"vat_cents\": 0,\n        \"total_cents\": 4050,\n        \"tax_at_topup\": true,\n        \"discount_percent\": 10,\n        \"months\": 1,\n        \"days\": 30,\n        \"pricing_version\": 1,\n        \"tax\": {\n          \"mode\": \"vat\",\n          \"rate_percent\": 23,\n          \"vat_code\": \"23\",\n          \"reverse_charge\": false\n        }\n      }\n    },\n    \"created_at\": \"2026-11-10T12:00:00+00:00\",\n    \"status_url\": \"/api/partner/v1/operations/op_0123456789abcdef0123456789abcdef\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Status operacji · Błąd",
          "request": {
            "method": "GET",
            "header": [],
            "url": "{{base_url}}/operations/{{operation_id}}",
            "description": "Zwraca status i wynik operacji konta. Szybkie sprawdzenie bez ponownego wykonania.\n\n"
          },
          "response": [
            {
              "name": "Błąd",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": "{{base_url}}/operations/{{operation_id}}",
                "description": "Zwraca status i wynik operacji konta. Szybkie sprawdzenie bez ponownego wykonania.\n\n"
              },
              "status": "OK",
              "code": 200,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"success\": true,\n  \"data\": {\n    \"id\": \"op_0123456789abcdef0123456789abcdef\",\n    \"state\": \"failed\",\n    \"error\": \"insufficient_partner_balance\",\n    \"result\": null,\n    \"created_at\": \"2026-11-10T12:00:00+00:00\",\n    \"status_url\": \"/api/partner/v1/operations/op_0123456789abcdef0123456789abcdef\"\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "Saldo i rozliczenia",
      "item": [
        {
          "name": "Saldo · Saldo",
          "request": {
            "method": "GET",
            "header": [],
            "url": "{{base_url}}/balance",
            "description": "Bieżące saldo, limit kredytowy, dostępne środki, rabat i ceny partnera.\n\n"
          },
          "response": [
            {
              "name": "Saldo",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": "{{base_url}}/balance",
                "description": "Bieżące saldo, limit kredytowy, dostępne środki, rabat i ceny partnera.\n\n"
              },
              "status": "OK",
              "code": 200,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"success\": true,\n  \"data\": {\n    \"currency\": \"EUR\",\n    \"balance_cents\": 10000,\n    \"reserved_cents\": 0,\n    \"credit_limit_cents\": 10000,\n    \"debt_cents\": 0,\n    \"available_cents\": 20000,\n    \"withdrawable_cents\": 10000,\n    \"discount_percent\": 10,\n    \"prefix\": \"astra\",\n    \"api_token_hint\": \"demo12\",\n    \"monthly_net_cents\": 4500,\n    \"payment_method\": \"card\",\n    \"connection_domains\": {\n      \"host\": \"\",\n      \"api\": \"\"\n    },\n    \"paid_in_cents\": 10000,\n    \"prices\": [\n      {\n        \"currency\": \"EUR\",\n        \"base_net_cents\": 4500,\n        \"net_cents\": 4050,\n        \"vat_cents\": 0,\n        \"total_cents\": 4050,\n        \"tax_at_topup\": true,\n        \"discount_percent\": 10,\n        \"months\": 1,\n        \"days\": 30,\n        \"pricing_version\": 1,\n        \"tax\": {\n          \"mode\": \"vat\",\n          \"rate_percent\": 23,\n          \"vat_code\": \"23\",\n          \"reverse_charge\": false\n        }\n      }\n    ],\n    \"topup_tax\": {\n      \"mode\": \"vat\",\n      \"rate_percent\": 23,\n      \"vat_code\": \"23\",\n      \"reverse_charge\": false\n    },\n    \"can_order_new_ports\": true\n  }\n}"
            }
          ]
        },
        {
          "name": "Doładowanie salda · Karta / Stripe",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": "{{base_url}}/topups",
            "description": "Tworzy link do płatności przez Stripe. amount_cents to kwota zasilenia salda w eurocentach; total_cents to kwota do zapłaty z uwzględnieniem należnego VAT.\n\n",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"amount_cents\": 10000\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "name": "Karta / Stripe",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": "{{base_url}}/topups",
                "description": "Tworzy link do płatności przez Stripe. amount_cents to kwota zasilenia salda w eurocentach; total_cents to kwota do zapłaty z uwzględnieniem należnego VAT.\n\n",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"amount_cents\": 10000\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 202,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"success\": true,\n  \"data\": {\n    \"id\": \"op_0123456789abcdef0123456789abcdef\",\n    \"state\": \"queued\",\n    \"error\": null,\n    \"result\": null,\n    \"created_at\": \"2026-11-10T12:00:00+00:00\",\n    \"status_url\": \"/api/partner/v1/operations/op_0123456789abcdef0123456789abcdef\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Status doładowania · Stripe",
          "request": {
            "method": "GET",
            "header": [],
            "url": "{{base_url}}/topups/{{topup_id}}",
            "description": "Zwraca status doładowania konta. paid potwierdza zaksięgowanie środków. Sam powrót ze strony Stripe nie potwierdza płatności.\n\nStatusy: creating, pending, paid, expired, failed."
          },
          "response": [
            {
              "name": "Stripe",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": "{{base_url}}/topups/{{topup_id}}",
                "description": "Zwraca status doładowania konta. paid potwierdza zaksięgowanie środków. Sam powrót ze strony Stripe nie potwierdza płatności.\n\nStatusy: creating, pending, paid, expired, failed."
              },
              "status": "OK",
              "code": 200,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"success\": true,\n  \"data\": {\n    \"id\": \"ptop_0123456789abcdef0123456789abcdef\",\n    \"state\": \"pending\",\n    \"url\": \"https://checkout.stripe.com/c/pay/EXAMPLE_SESSION\",\n    \"amount_cents\": 10000,\n    \"vat_cents\": 2300,\n    \"total_cents\": 12300,\n    \"currency\": \"EUR\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Historia transakcji · Pierwsza strona",
          "request": {
            "method": "GET",
            "header": [],
            "url": "{{base_url}}/transactions?offset=0&limit=30",
            "description": "Operacje od najnowszych do najstarszych, źródła, komentarze, kwoty i saldo po każdej operacji. Techniczne rezerwacje zakupu są domyślnie ukryte.\n\n"
          },
          "response": [
            {
              "name": "Pierwsza strona",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": "{{base_url}}/transactions?offset=0&limit=30",
                "description": "Operacje od najnowszych do najstarszych, źródła, komentarze, kwoty i saldo po każdej operacji. Techniczne rezerwacje zakupu są domyślnie ukryte.\n\n"
              },
              "status": "OK",
              "code": 200,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"success\": true,\n  \"data\": {\n    \"items\": [\n      {\n        \"id\": \"ptop_0123456789abcdef0123456789abcdef:credit\",\n        \"created_at\": \"2026-11-09T12:05:00+00:00\",\n        \"currency\": \"EUR\",\n        \"operation\": \"topup\",\n        \"amount_cents\": 10000,\n        \"reserved_delta_cents\": 0,\n        \"source\": \"stripe\",\n        \"comment\": \"\",\n        \"reference\": \"ptop_0123456789abcdef0123456789abcdef\",\n        \"balance_after_cents\": 10000,\n        \"reserved_after_cents\": 0,\n        \"sequence\": 1\n      }\n    ],\n    \"total\": 1,\n    \"offset\": 0,\n    \"limit\": 30\n  }\n}"
            }
          ]
        },
        {
          "name": "Wniosek o zwrot środków · Wniosek",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": "{{base_url}}/withdrawals",
            "description": "Tworzy wniosek i rezerwuje kwotę do jego rozpatrzenia. Kwota dostępna do wypłaty jest podana w withdrawable_cents; nie obejmuje limitu kredytowego ani bezzwrotnych rekompensat.\n\nPo przetworzeniu wniosku result.state=requested oznacza oczekiwanie na decyzję. Operacja pozostaje processing do potwierdzenia wypłaty lub odrzucenia.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"amount_cents\": 5000,\n  \"comment\": \"Please contact me to confirm payment details.\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "name": "Wniosek",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": "{{base_url}}/withdrawals",
                "description": "Tworzy wniosek i rezerwuje kwotę do jego rozpatrzenia. Kwota dostępna do wypłaty jest podana w withdrawable_cents; nie obejmuje limitu kredytowego ani bezzwrotnych rekompensat.\n\nPo przetworzeniu wniosku result.state=requested oznacza oczekiwanie na decyzję. Operacja pozostaje processing do potwierdzenia wypłaty lub odrzucenia.",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"amount_cents\": 5000,\n  \"comment\": \"Please contact me to confirm payment details.\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 202,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"success\": true,\n  \"data\": {\n    \"id\": \"op_0123456789abcdef0123456789abcdef\",\n    \"state\": \"queued\",\n    \"error\": null,\n    \"result\": null,\n    \"created_at\": \"2026-11-10T12:00:00+00:00\",\n    \"status_url\": \"/api/partner/v1/operations/op_0123456789abcdef0123456789abcdef\"\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "Katalog i zamówienia",
      "item": [
        {
          "name": "Dostępne porty · Dostępność",
          "request": {
            "method": "GET",
            "header": [],
            "url": "{{base_url}}/catalog",
            "description": "Dostępne numery portów pogrupowane według operatora i lokalizacji.\n\nDostępność jest sprawdzana podczas składania zamówienia. Wyświetlenie katalogu nie rezerwuje portów."
          },
          "response": [
            {
              "name": "Dostępność",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": "{{base_url}}/catalog",
                "description": "Dostępne numery portów pogrupowane według operatora i lokalizacji.\n\nDostępność jest sprawdzana podczas składania zamówienia. Wyświetlenie katalogu nie rezerwuje portów."
              },
              "status": "OK",
              "code": 200,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"success\": true,\n  \"data\": {\n    \"items\": [\n      {\n        \"operator\": {\n          \"id\": \"operator-orange\",\n          \"name\": \"Orange\"\n        },\n        \"location\": {\n          \"id\": \"location-warsaw\",\n          \"name\": \"Warsaw\"\n        },\n        \"ports\": [\n          {\n            \"id\": \"b1c2d3e4f5a60123456789abcdef0123\",\n            \"number\": 10001\n          },\n          {\n            \"id\": \"b2c3d4e5f6a70123456789abcdef0123\",\n            \"number\": 10002\n          }\n        ],\n        \"available\": 2\n      }\n    ],\n    \"prices\": [\n      {\n        \"currency\": \"EUR\",\n        \"base_net_cents\": 4500,\n        \"net_cents\": 4050,\n        \"vat_cents\": 0,\n        \"total_cents\": 4050,\n        \"tax_at_topup\": true,\n        \"discount_percent\": 10,\n        \"months\": 1,\n        \"days\": 30,\n        \"pricing_version\": 1,\n        \"tax\": {\n          \"mode\": \"vat\",\n          \"rate_percent\": 23,\n          \"vat_code\": \"23\",\n          \"reverse_charge\": false\n        }\n      }\n    ]\n  }\n}"
            }
          ]
        },
        {
          "name": "Zamówienie portu · Według numeru",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": "{{base_url}}/orders",
            "description": "Zamówienie jednego dostępnego portu na 30 dni według numeru lub ID z katalogu. Koszt jest pobierany z salda.\n\nDłuższa operacja zwraca HTTP 202 i id utworzony przez serwer. Status i wynik są dostępne przez GET /operations/{id}. Sprawdzenie statusu nie tworzy nowej operacji.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"port_number\": 10001\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "name": "Według numeru",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": "{{base_url}}/orders",
                "description": "Zamówienie jednego dostępnego portu na 30 dni według numeru lub ID z katalogu. Koszt jest pobierany z salda.\n\nDłuższa operacja zwraca HTTP 202 i id utworzony przez serwer. Status i wynik są dostępne przez GET /operations/{id}. Sprawdzenie statusu nie tworzy nowej operacji.",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"port_number\": 10001\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 202,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"success\": true,\n  \"data\": {\n    \"id\": \"op_0123456789abcdef0123456789abcdef\",\n    \"state\": \"queued\",\n    \"error\": null,\n    \"result\": null,\n    \"created_at\": \"2026-11-10T12:00:00+00:00\",\n    \"status_url\": \"/api/partner/v1/operations/op_0123456789abcdef0123456789abcdef\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Zamówienie portu · Według ID",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": "{{base_url}}/orders",
            "description": "Zamówienie jednego dostępnego portu na 30 dni według numeru lub ID z katalogu. Koszt jest pobierany z salda.\n\nDłuższa operacja zwraca HTTP 202 i id utworzony przez serwer. Status i wynik są dostępne przez GET /operations/{id}. Sprawdzenie statusu nie tworzy nowej operacji.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"port_id\": \"b1c2d3e4f5a60123456789abcdef0123\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "name": "Według ID",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": "{{base_url}}/orders",
                "description": "Zamówienie jednego dostępnego portu na 30 dni według numeru lub ID z katalogu. Koszt jest pobierany z salda.\n\nDłuższa operacja zwraca HTTP 202 i id utworzony przez serwer. Status i wynik są dostępne przez GET /operations/{id}. Sprawdzenie statusu nie tworzy nowej operacji.",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"port_id\": \"b1c2d3e4f5a60123456789abcdef0123\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 202,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"success\": true,\n  \"data\": {\n    \"id\": \"op_0123456789abcdef0123456789abcdef\",\n    \"state\": \"queued\",\n    \"error\": null,\n    \"result\": null,\n    \"created_at\": \"2026-11-10T12:00:00+00:00\",\n    \"status_url\": \"/api/partner/v1/operations/op_0123456789abcdef0123456789abcdef\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Lista portów · Porty",
          "request": {
            "method": "GET",
            "header": [],
            "url": "{{base_url}}/orders",
            "description": "Bieżące porty konta: termin wynajmu, dane połączenia, IP i timer zmiany IP.\n\nZmiana IP odbywa się przez zapytanie GET pod pełny adres rotation_url z danych portu. Nagłówek Authorization nie jest wymagany. Link zawiera już token portu."
          },
          "response": [
            {
              "name": "Porty",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": "{{base_url}}/orders",
                "description": "Bieżące porty konta: termin wynajmu, dane połączenia, IP i timer zmiany IP.\n\nZmiana IP odbywa się przez zapytanie GET pod pełny adres rotation_url z danych portu. Nagłówek Authorization nie jest wymagany. Link zawiera już token portu."
              },
              "status": "OK",
              "code": 200,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"success\": true,\n  \"data\": {\n    \"items\": [\n      {\n        \"id\": \"a1b2c3d4e5f60123456789abcdef0123\",\n        \"port_id\": \"b1c2d3e4f5a60123456789abcdef0123\",\n        \"number\": 10001,\n        \"host\": \"l1.gigabit.ltd\",\n        \"username\": \"astra_a1b2c3d4e5f\",\n        \"proxy_password\": \"EXAMPLE_ONLY_22_CHARS_x\",\n        \"status\": \"active\",\n        \"expires\": \"2026-12-09T22:59:59+00:00\",\n        \"operator\": \"Orange\",\n        \"cityName\": \"Warsaw\",\n        \"ip\": \"198.51.100.42\",\n        \"rotation_url\": \"https://api.gigabit.ltd/change_ip?token=EXAMPLE_ROTATION_TOKEN_REPLACE_ME\",\n        \"rotation\": true,\n        \"rotation_seconds\": 120,\n        \"connection_options\": {\n          \"custom\": {\n            \"host\": \"proxy.example.com\",\n            \"rotation_url\": \"https://api.example.com/change_ip?token=EXAMPLE_ROTATION_TOKEN_REPLACE_ME\"\n          }\n        }\n      }\n    ]\n  }\n}"
            }
          ]
        },
        {
          "name": "Dane portu · Port",
          "request": {
            "method": "GET",
            "header": [],
            "url": "{{base_url}}/orders/{{order_id}}",
            "description": "Dane zamówienia przypisanego do konta. Niedostępne lub nieistniejące zamówienie zwraca 404.\n\nZmiana IP odbywa się przez zapytanie GET pod pełny adres rotation_url z danych portu. Nagłówek Authorization nie jest wymagany. Link zawiera już token portu."
          },
          "response": [
            {
              "name": "Port",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": "{{base_url}}/orders/{{order_id}}",
                "description": "Dane zamówienia przypisanego do konta. Niedostępne lub nieistniejące zamówienie zwraca 404.\n\nZmiana IP odbywa się przez zapytanie GET pod pełny adres rotation_url z danych portu. Nagłówek Authorization nie jest wymagany. Link zawiera już token portu."
              },
              "status": "OK",
              "code": 200,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"success\": true,\n  \"data\": {\n    \"id\": \"a1b2c3d4e5f60123456789abcdef0123\",\n    \"port_id\": \"b1c2d3e4f5a60123456789abcdef0123\",\n    \"number\": 10001,\n    \"host\": \"l1.gigabit.ltd\",\n    \"username\": \"astra_a1b2c3d4e5f\",\n    \"proxy_password\": \"EXAMPLE_ONLY_22_CHARS_x\",\n    \"status\": \"active\",\n    \"expires\": \"2026-12-09T22:59:59+00:00\",\n    \"operator\": \"Orange\",\n    \"cityName\": \"Warsaw\",\n    \"ip\": \"198.51.100.42\",\n    \"rotation_url\": \"https://api.gigabit.ltd/change_ip?token=EXAMPLE_ROTATION_TOKEN_REPLACE_ME\",\n    \"rotation\": true,\n    \"rotation_seconds\": 120,\n    \"connection_options\": {\n      \"custom\": {\n        \"host\": \"proxy.example.com\",\n        \"rotation_url\": \"https://api.example.com/change_ip?token=EXAMPLE_ROTATION_TOKEN_REPLACE_ME\"\n      }\n    }\n  }\n}"
            }
          ]
        },
        {
          "name": "Przedłużenie portu · Według numeru",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": "{{base_url}}/orders/10001/renew",
            "description": "Przedłuża wynajem jednego portu o 30 dni z płatnością z salda. Wymagany jest tylko numer lub ID portu w adresie.\n\nDłuższa operacja zwraca HTTP 202 i id utworzony przez serwer. Status i wynik są dostępne przez GET /operations/{id}. Sprawdzenie statusu nie tworzy nowej operacji.",
            "body": {
              "mode": "raw",
              "raw": "{}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "name": "Według numeru",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": "{{base_url}}/orders/10001/renew",
                "description": "Przedłuża wynajem jednego portu o 30 dni z płatnością z salda. Wymagany jest tylko numer lub ID portu w adresie.\n\nDłuższa operacja zwraca HTTP 202 i id utworzony przez serwer. Status i wynik są dostępne przez GET /operations/{id}. Sprawdzenie statusu nie tworzy nowej operacji.",
                "body": {
                  "mode": "raw",
                  "raw": "{}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 202,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"success\": true,\n  \"data\": {\n    \"id\": \"op_0123456789abcdef0123456789abcdef\",\n    \"state\": \"queued\",\n    \"error\": null,\n    \"result\": null,\n    \"created_at\": \"2026-11-10T12:00:00+00:00\",\n    \"status_url\": \"/api/partner/v1/operations/op_0123456789abcdef0123456789abcdef\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Przedłużenie portu · Według ID",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": "{{base_url}}/orders/b1c2d3e4f5a60123456789abcdef0123/renew",
            "description": "Przedłuża wynajem jednego portu o 30 dni z płatnością z salda. Wymagany jest tylko numer lub ID portu w adresie.\n\nDłuższa operacja zwraca HTTP 202 i id utworzony przez serwer. Status i wynik są dostępne przez GET /operations/{id}. Sprawdzenie statusu nie tworzy nowej operacji.",
            "body": {
              "mode": "raw",
              "raw": "{}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "name": "Według ID",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": "{{base_url}}/orders/b1c2d3e4f5a60123456789abcdef0123/renew",
                "description": "Przedłuża wynajem jednego portu o 30 dni z płatnością z salda. Wymagany jest tylko numer lub ID portu w adresie.\n\nDłuższa operacja zwraca HTTP 202 i id utworzony przez serwer. Status i wynik są dostępne przez GET /operations/{id}. Sprawdzenie statusu nie tworzy nowej operacji.",
                "body": {
                  "mode": "raw",
                  "raw": "{}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 202,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"success\": true,\n  \"data\": {\n    \"id\": \"op_0123456789abcdef0123456789abcdef\",\n    \"state\": \"queued\",\n    \"error\": null,\n    \"result\": null,\n    \"created_at\": \"2026-11-10T12:00:00+00:00\",\n    \"status_url\": \"/api/partner/v1/operations/op_0123456789abcdef0123456789abcdef\"\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "Dostęp i zmiana IP",
      "item": [
        {
          "name": "Reset tokenu zmiany IP · Nowy link",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": "{{base_url}}/orders/{{order_id}}/rotation-token",
            "description": "Tworzy nowy token zmiany IP i zwraca gotowy link. Poprzedni token i wszystkie linki z nim natychmiast przestają działać. Hasło proxy i timer pozostają bez zmian.\n\nOdpowiedź jest zwracana od razu, bez operacji w tle. Nowy link jest również dostępny w polu rotation_url danych portu.",
            "body": {
              "mode": "raw",
              "raw": "{}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "name": "Nowy link",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": "{{base_url}}/orders/{{order_id}}/rotation-token",
                "description": "Tworzy nowy token zmiany IP i zwraca gotowy link. Poprzedni token i wszystkie linki z nim natychmiast przestają działać. Hasło proxy i timer pozostają bez zmian.\n\nOdpowiedź jest zwracana od razu, bez operacji w tle. Nowy link jest również dostępny w polu rotation_url danych portu.",
                "body": {
                  "mode": "raw",
                  "raw": "{}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"success\": true,\n  \"data\": {\n    \"rotation_token\": \"0123456789abcdef0123456789abcdef\",\n    \"rotation_url\": \"https://api.gigabit.ltd/change_ip?token=0123456789abcdef0123456789abcdef\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Zmiana danych dostępu według ID · Login i hasło",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": "{{base_url}}/orders/{{order_id}}/password",
            "description": "Serwer generuje nowe hasło. Przy change_login=true generuje też nowy login z bieżącym prefiksem partnera. Dostępne wyłącznie dla aktywnego wynajmu.\n\nNowe dane są dostępne w result po zastosowaniu. Błąd operation_superseded oznacza, że nowsze polecenie zmieniło dane dostępu.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"change_login\": true\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "name": "Login i hasło",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": "{{base_url}}/orders/{{order_id}}/password",
                "description": "Serwer generuje nowe hasło. Przy change_login=true generuje też nowy login z bieżącym prefiksem partnera. Dostępne wyłącznie dla aktywnego wynajmu.\n\nNowe dane są dostępne w result po zastosowaniu. Błąd operation_superseded oznacza, że nowsze polecenie zmieniło dane dostępu.",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"change_login\": true\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 202,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"success\": true,\n  \"data\": {\n    \"id\": \"op_0123456789abcdef0123456789abcdef\",\n    \"state\": \"queued\",\n    \"error\": null,\n    \"result\": null,\n    \"created_at\": \"2026-11-10T12:00:00+00:00\",\n    \"status_url\": \"/api/partner/v1/operations/op_0123456789abcdef0123456789abcdef\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Zmiana danych dostępu według ID · Tylko hasło",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": "{{base_url}}/orders/{{order_id}}/password",
            "description": "Serwer generuje nowe hasło. Przy change_login=true generuje też nowy login z bieżącym prefiksem partnera. Dostępne wyłącznie dla aktywnego wynajmu.\n\nNowe dane są dostępne w result po zastosowaniu. Błąd operation_superseded oznacza, że nowsze polecenie zmieniło dane dostępu.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"change_login\": false\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "name": "Tylko hasło",
              "originalRequest": {
                "method": "POST",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": "{{base_url}}/orders/{{order_id}}/password",
                "description": "Serwer generuje nowe hasło. Przy change_login=true generuje też nowy login z bieżącym prefiksem partnera. Dostępne wyłącznie dla aktywnego wynajmu.\n\nNowe dane są dostępne w result po zastosowaniu. Błąd operation_superseded oznacza, że nowsze polecenie zmieniło dane dostępu.",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"change_login\": false\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 202,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"success\": true,\n  \"data\": {\n    \"id\": \"op_0123456789abcdef0123456789abcdef\",\n    \"state\": \"queued\",\n    \"error\": null,\n    \"result\": null,\n    \"created_at\": \"2026-11-10T12:00:00+00:00\",\n    \"status_url\": \"/api/partner/v1/operations/op_0123456789abcdef0123456789abcdef\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Timer zmiany IP · Włączony",
          "request": {
            "method": "GET",
            "header": [],
            "url": "{{base_url}}/orders/{{order_id}}/rotation",
            "description": "Bieżący stan timera. Przy rotation=true zwracane jest rotation_seconds. Gdy timer jest wyłączony, zwracane jest tylko rotation=false.\n\n"
          },
          "response": [
            {
              "name": "Włączony",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": "{{base_url}}/orders/{{order_id}}/rotation",
                "description": "Bieżący stan timera. Przy rotation=true zwracane jest rotation_seconds. Gdy timer jest wyłączony, zwracane jest tylko rotation=false.\n\n"
              },
              "status": "OK",
              "code": 200,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"success\": true,\n  \"data\": {\n    \"rotation\": true,\n    \"rotation_seconds\": 120\n  }\n}"
            }
          ]
        },
        {
          "name": "Timer zmiany IP · Wyłączony",
          "request": {
            "method": "GET",
            "header": [],
            "url": "{{base_url}}/orders/{{order_id}}/rotation",
            "description": "Bieżący stan timera. Przy rotation=true zwracane jest rotation_seconds. Gdy timer jest wyłączony, zwracane jest tylko rotation=false.\n\n"
          },
          "response": [
            {
              "name": "Wyłączony",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": "{{base_url}}/orders/{{order_id}}/rotation",
                "description": "Bieżący stan timera. Przy rotation=true zwracane jest rotation_seconds. Gdy timer jest wyłączony, zwracane jest tylko rotation=false.\n\n"
              },
              "status": "OK",
              "code": 200,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"success\": true,\n  \"data\": {\n    \"rotation\": false\n  }\n}"
            }
          ]
        },
        {
          "name": "Ustawienia timera · Co 120 sekund",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": "{{base_url}}/orders/{{order_id}}/rotation",
            "description": "Włączenie wymaga rotation=true oraz rotation_seconds, liczby całkowitej od 20 do 86400 sekund. Wartość poniżej 20 zwraca błąd rotation_interval_too_short. Wyłączenie wymaga tylko rotation=false.\n\nOperacja pozostaje processing do potwierdzenia zastosowania timera.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"rotation\": true,\n  \"rotation_seconds\": 120\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "name": "Co 120 sekund",
              "originalRequest": {
                "method": "PUT",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": "{{base_url}}/orders/{{order_id}}/rotation",
                "description": "Włączenie wymaga rotation=true oraz rotation_seconds, liczby całkowitej od 20 do 86400 sekund. Wartość poniżej 20 zwraca błąd rotation_interval_too_short. Wyłączenie wymaga tylko rotation=false.\n\nOperacja pozostaje processing do potwierdzenia zastosowania timera.",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"rotation\": true,\n  \"rotation_seconds\": 120\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 202,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"success\": true,\n  \"data\": {\n    \"id\": \"op_0123456789abcdef0123456789abcdef\",\n    \"state\": \"queued\",\n    \"error\": null,\n    \"result\": null,\n    \"created_at\": \"2026-11-10T12:00:00+00:00\",\n    \"status_url\": \"/api/partner/v1/operations/op_0123456789abcdef0123456789abcdef\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Ustawienia timera · Wyłącz",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": "{{base_url}}/orders/{{order_id}}/rotation",
            "description": "Włączenie wymaga rotation=true oraz rotation_seconds, liczby całkowitej od 20 do 86400 sekund. Wartość poniżej 20 zwraca błąd rotation_interval_too_short. Wyłączenie wymaga tylko rotation=false.\n\nOperacja pozostaje processing do potwierdzenia zastosowania timera.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"rotation\": false\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "name": "Wyłącz",
              "originalRequest": {
                "method": "PUT",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": "{{base_url}}/orders/{{order_id}}/rotation",
                "description": "Włączenie wymaga rotation=true oraz rotation_seconds, liczby całkowitej od 20 do 86400 sekund. Wartość poniżej 20 zwraca błąd rotation_interval_too_short. Wyłączenie wymaga tylko rotation=false.\n\nOperacja pozostaje processing do potwierdzenia zastosowania timera.",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"rotation\": false\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 202,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"success\": true,\n  \"data\": {\n    \"id\": \"op_0123456789abcdef0123456789abcdef\",\n    \"state\": \"queued\",\n    \"error\": null,\n    \"result\": null,\n    \"created_at\": \"2026-11-10T12:00:00+00:00\",\n    \"status_url\": \"/api/partner/v1/operations/op_0123456789abcdef0123456789abcdef\"\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "Profil partnera",
      "item": [
        {
          "name": "Prefiks loginów · Prefiks",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": "{{base_url}}/profile",
            "description": "Prefiks to początek loginów portów, np. nazwa marki. Loginy są generowane w formacie prefix_random: przy prefix=astra nowy port otrzyma login taki jak astra_a1b2c3d4e5f. Losowa część jest tworzona osobno dla każdego portu.\n\nZmiana prefiksu nie zmienia już wydanych loginów. Nowe porty oraz zmiana loginu przez change_login=true używają bieżącego prefiksu. Prefiks musi być unikalny; zajęty zwraca 409 partner_prefix_taken.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"prefix\": \"astra\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [
            {
              "name": "Prefiks",
              "originalRequest": {
                "method": "PUT",
                "header": [
                  {
                    "key": "Content-Type",
                    "value": "application/json"
                  }
                ],
                "url": "{{base_url}}/profile",
                "description": "Prefiks to początek loginów portów, np. nazwa marki. Loginy są generowane w formacie prefix_random: przy prefix=astra nowy port otrzyma login taki jak astra_a1b2c3d4e5f. Losowa część jest tworzona osobno dla każdego portu.\n\nZmiana prefiksu nie zmienia już wydanych loginów. Nowe porty oraz zmiana loginu przez change_login=true używają bieżącego prefiksu. Prefiks musi być unikalny; zajęty zwraca 409 partner_prefix_taken.",
                "body": {
                  "mode": "raw",
                  "raw": "{\n  \"prefix\": \"astra\"\n}",
                  "options": {
                    "raw": {
                      "language": "json"
                    }
                  }
                }
              },
              "status": "OK",
              "code": 200,
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "body": "{\n  \"success\": true,\n  \"data\": {\n    \"prefix\": \"astra\"\n  }\n}"
            }
          ]
        }
      ]
    }
  ],
  "event": [
    {
      "listen": "test",
      "script": {
        "type": "text/javascript",
        "exec": [
          "if (pm.response.code >= 200 && pm.response.code < 300) {",
          "  const data = pm.response.json().data;",
          "  if (data && data.status_url) pm.collectionVariables.set(\"operation_id\", data.id);",
          "  const result = data && data.result;",
          "  if (result && result.order_ids && result.order_ids.length) pm.collectionVariables.set(\"order_id\", result.order_ids[0]);",
          "  if (result && result.id && result.id.startsWith(\"ptop_\")) pm.collectionVariables.set(\"topup_id\", result.id);",
          "}"
        ]
      }
    }
  ]
}
