RateHawk API IP Whitelisting: Register Source IPs and Fix not_allowed_host

Two ways to use this guide: Setting up the integration yourself? Start with the Quickstart. Working with an AI coding agent? Share this page and use the in-depth reference sections below to help it configure the integration, verify the connection and troubleshoot issues.

To let your agent set up and test the connection, provide the required proxy connection details through its secure credential mechanism rather than sharing your QuotaGuard account password. Review any changes it proposes.

Give ETG a stable source address for your backend

ETG requires APIv3 callers to submit their source IPs. If your backend lacks stable outbound addresses, QuotaGuard can supply a managed pair for the connections you route through it, subject to ETG accepting that pair for your integration. ETG requirements, section 1.4, QuotaGuard outbound.

The job is concrete: choose the outbound route, register its addresses, configure the supplier client, then verify Sandbox access. This guide covers server-side ETG APIv3 B2B access. It does not validate card processing, reservation workflows, or certification.

Already seeing not_allowed_host? Jump to the failure table.

Guided setup (Quickstart)

1. Choose your outbound route

Keep an existing stable, ETG-approved route if it already meets your needs. If you need managed egress, select the QuotaGuard product and region, then check whether ETG accepts its assigned pair for your integration. See route selection.

2. Submit both addresses and confirm access

For QuotaGuard, submit both dashboard-assigned outbound IPv4 addresses through your established ETG onboarding channel. Ask ETG to confirm shared-address acceptance where applicable, which keys and environments the approval covers, and that the addresses are active for your intended Sandbox access. See the registration checklist.

3. Configure the Sandbox client securely

Have your backend’s secret mechanism supply QUOTAGUARDSTATIC_URL, QG_IP_A, QG_IP_B, ETG_SANDBOX_KEY_ID and ETG_SANDBOX_API_KEY. The examples use Static’s HTTP proxy URL and explicitly attach it to the requesting client. Keep the Sandbox key with the Sandbox host; follow the client configuration and runtime setup for your chosen language.

4. Run the matching diagnostic from your backend

Follow the installation, save-file and invocation instructions in Python with Requests or Node.js with an explicit Undici dispatcher. After ETG confirms Sandbox access, run the saved example from the deployed worker. It checks an IP echo, then makes one read-only Sandbox overview request without making a reservation.

5. Check the result and retain a sanitized record

A passing example exits with status 0 and reports echo_in_assigned_pair: true, overview_accepted: true and diagnostic_passed: true. ETG overview must return HTTP 200, status: "ok", error: null and a data array. If a valid debug.real_ip is present, it must match either assigned address; absent or unusable metadata is non-fatal and leaves ETG’s observed source unconfirmed. See verification evidence and its limits, and use the failure table if a check fails.

Programmatic setup and reference

Use the sections below for the full registration checklist, route and environment choices, copyable client examples, verification evidence, troubleshooting and operating considerations.

Prepare IP registration before certification

ETG requires implementation of its integration requirements before certification starts. Production access follows certification and partnership formalisation. Treat IP registration as onboarding preparation, without promising an IP-approval turnaround. Certification.

The registration requirement concerns your backend’s calling IPs. ETG can separately supply its IPs if your firewall needs to approve connections from ETG. Keep these directions separate. Its Security features page instead covers host/return_path validation. Requirements, Security features.

For your onboarding record, prepare:

  • ETG contract/account identifier and integration owner. Do not include the API secret.
  • Environment and nonsecret key identifier associated with the request.
  • Both dashboard-assigned outbound IPv4 addresses if using QuotaGuard.
  • Whether addresses are shared or customer-exclusive, and the requested cutover date.
  • A request for confirmation of address count, shared-address acceptance, and which keys/environments the approval covers.

This is a proposed information checklist, not an ETG form or a prescribed support channel. Public requirements do not specify a self-service IP-registration screen, an address maximum, or shared-proxy acceptance. Prepare the list before certification, submit it through your established ETG onboarding channel, and obtain confirmation that it is active for the intended access before verification. Submission alone is not evidence of activation. The reviewed pages do not establish activation timing.

Choose the route before you submit addresses

Your situation Practical choice
Your existing backend already exits through stable, ETG-approved addresses Keep that route unless there is a concrete operating reason to change.
Your cloud architecture already has a public NAT gateway and allocated egress addresses Register those addresses. Confirm all workers and failover routes use the approved set.
You control a proxy-capable backend but do not want to operate egress infrastructure Evaluate QuotaGuard, subject to ETG’s address policy and your client/runtime support.
ETG requires customer-exclusive addresses Evaluate dedicated QuotaGuard infrastructure or native dedicated egress. A shared plan does not meet exclusivity.
A hosted connector makes requests on infrastructure you cannot configure Establish whether it offers a supported proxy or static-egress route before selecting a service.

AWS documents public NAT gateways associated with Elastic IPs. QuotaGuard is an alternative operating model, not a required extra hop for a backend already meeting the requirement. No cost advantage is assumed. AWS NAT gateways.

Each QuotaGuard subscription has a pair. Register both even if a short check observes only one. A shared pair is stable but used by other subscribers; ETG’s own authentication remains necessary. For exclusive addresses, request dedicated infrastructure through QuotaGuard Support; it is available on Enterprise and above and is manually provisioned on request, not automatically activated by a tier change. Dedicated infrastructure addresses exclusivity, but does not establish ETG approval or solve an unknown one-address limit. Do not promise acceptance before the customer’s policy is confirmed. QuotaGuard outbound.

Keep the environment and authentication together

Environment Current host Diagnostic policy
Sandbox https://api-sandbox.ratehawk.com Sandbox key only; use the read-only overview request below.
Test https://api.ratehawk.com Excluded from this diagnostic.
Production https://api.ratehawk.com Excluded from this diagnostic.

ETG documents HTTP Basic authentication: KEY_ID is the username and API_KEY is the password. The worldota.net hosts are deprecated. Keep keys and data within their environment; separate environments alone do not establish a requirement for separate egress pairs. Authorization, Requirements.

Important source conflict: Authorization warns that Test hotel bookings carry financial responsibility; Requirements describes Test as non-production. Use Sandbox for this exercise and make no booking calls. Authorization, Requirements.

Keep ETG credentials and the proxy URL in server-side secrets. A browser must never receive them. Application authentication should protect whatever business operation invokes the supplier client. Use fixed destination URLs rather than exposing a caller-controlled forwarding endpoint.

Route the client that actually calls ETG

Setting QUOTAGUARDSTATIC_URL stores configuration; your HTTP client must read and use it. Use the exact connection URL and both IPs from the dashboard. Do not register the addresses returned by resolving the proxy hostname. QuotaGuard outbound.

Both Static and Shield preserve the HTTPS payload’s encryption to ETG. Shield adds TLS on the application-to-proxy connection. Choose the product and region before registration, since changing either can require new approved IPs. The examples below use Static’s HTTP proxy URL. How proxying works.

Before either example, inject the following environment variables into the backend process using your deployment’s secret manager or approved local secret-loading tool. Both programs read these exact names; the commands below contain no credential values.

Variable Required value and role
QUOTAGUARDSTATIC_URL Exact authenticated Static HTTP proxy URL from your dashboard. Keep secret.
QG_IP_A First assigned outbound IPv4 address from your dashboard.
QG_IP_B Second assigned outbound IPv4 address from your dashboard.
ETG_SANDBOX_KEY_ID Your existing Sandbox key’s Basic-auth username.
ETG_SANDBOX_API_KEY That Sandbox key’s Basic-auth password. Keep secret.

Before any network call, the programs validate all five variable names. A missing value produces only its known variable name and a configuration-stage failure, never arbitrary exception text. Each HTTP response emits its status and a normalized, allowlisted content type before JSON decoding. Parameters are removed, media types are limited to 64 characters, and unrecognized values become other; raw headers and bodies are not printed. JSON decoding failure is reported separately as json_parse: failed.

Use the selected runtime releases below, with their normal trusted CA certificates and network access to the dashboard-specified proxy. Keep destination TLS verification enabled. The setup commands assume a POSIX shell; run them in your own example directory. Configure the same environment variables in the deployed worker before invoking the diagnostic there.

Python with Requests

This setup selects CPython 3.14.10 and Requests 2.34.2. The Python release is published; Requests 2.34.2 declares Python >=3.10 and lists Python 3.14 support. These exact versions were checked in primary release/package metadata for this guide. Install CPython 3.14.10 through your approved runtime image or the official release, with venv and pip available. Requests version metadata.

In an empty Python example directory, confirm python3.14 --version reports 3.14.10, create an isolated environment and install the pinned top-level dependency:

python3.14 --version
python3.14 -m venv .venv
.venv/bin/python -m pip install 'requests==2.34.2'

The remaining imports are Python standard-library modules. This pins Requests; its transitive dependencies are resolved by pip, not supplied as a frozen environment here. Python venv, PyPA installation guidance.

Supply existing Sandbox credentials through your deployment’s secret mechanism. This deliberately uses an explicit proxy for each request, disables environment proxy inheritance, and sends ETG authentication only to ETG. Requests documents per-request proxies and Basic authentication; this is a REST client, not the ETG SDK. Requests documentation.

Save the following code as ratehawk_overview.py in that directory.

import ipaddress
import json
import os
import requests
from urllib.parse import urlsplit

SETTING_NAMES = ("QUOTAGUARDSTATIC_URL", "QG_IP_A", "QG_IP_B",
                 "ETG_SANDBOX_KEY_ID", "ETG_SANDBOX_API_KEY")

class ConfigurationError(Exception):
    def __init__(self, variable):
        super().__init__("Missing required setting")
        self.variable = variable if variable in SETTING_NAMES else "unknown_setting"

def required(name):
    value = os.environ.get(name)
    if not value:
        raise ConfigurationError(name)
    return value

def http_metadata(stage, status, raw_type):
    media = raw_type.split(";", 1)[0].strip().lower() if isinstance(raw_type, str) else ""
    allowed = {"application/json", "application/problem+json", "text/html",
               "text/plain", "application/octet-stream"}
    content_type = media if len(media) <= 64 and media in allowed else "other"
    if not media:
        content_type = "unavailable"
    return {"stage": stage if stage in ("echo", "etg") else "unknown",
            "http_status": status if type(status) is int and 100 <= status <= 599 else None,
            "content_type": content_type}

def read_json_response(stage, response):
    print(json.dumps(http_metadata(stage, response.status_code,
                                   response.headers.get("content-type"))))
    try:
        result = json.loads(response.content)
    except (ValueError, UnicodeError, TypeError):
        print(json.dumps({"stage": stage, "json_parse": "failed"}))
        return None, False
    print(json.dumps({"stage": stage, "json_parse": "ok"}))
    return result, True

def source_evidence(result, approved):
    debug = result.get("debug")
    raw = debug.get("real_ip") if isinstance(debug, dict) else None
    if raw is None:
        return "unavailable"
    if not isinstance(raw, str):
        return "unusable"
    try:
        observed = str(ipaddress.ip_address(raw))
    except ValueError:
        return "unusable"
    return "match" if observed in approved else "mismatch"

def overview_outcome(status, result, approved):
    shape_ok = isinstance(result, dict)
    evidence = source_evidence(result, approved) if shape_ok else "unavailable"
    accepted = (shape_ok and status == 200 and result.get("status") == "ok"
                and result.get("error") is None and isinstance(result.get("data"), list))
    return {"overview_accepted": accepted, "etg_source_evidence": evidence,
            "diagnostic_passed": accepted and evidence != "mismatch"}

def failure_summary(error):
    if isinstance(error, ConfigurationError):
        return {"stage": "configuration", "missing_variable": error.variable,
                "diagnostic_passed": False}
    return {"stage": "transport_or_validation", "diagnostic_passed": False}

def main():
    config = {name: required(name) for name in SETTING_NAMES}
    proxy = config["QUOTAGUARDSTATIC_URL"]
    if urlsplit(proxy).scheme != "http":
        raise ValueError("Static HTTP proxy URL required")
    approved = {str(ipaddress.IPv4Address(config[name])) for name in ("QG_IP_A", "QG_IP_B")}
    with requests.Session() as session:
        session.trust_env = False
        options = {"proxies": {"https": proxy},
                   "timeout": (10, 20), "allow_redirects": False}
        echo = session.get("https://ip.quotaguard.com", **options)
        echo_data, parsed = read_json_response("echo", echo)
        if not parsed or echo.status_code != 200 or not isinstance(echo_data, dict):
            return 1
        observed = str(ipaddress.IPv4Address(echo_data["ip"]))
        if observed not in approved:
            print(json.dumps({"stage": "echo", "echo_in_assigned_pair": False}))
            return 1
        response = session.get(
            "https://api-sandbox.ratehawk.com/api/b2b/v3/overview/",
            auth=(config["ETG_SANDBOX_KEY_ID"], config["ETG_SANDBOX_API_KEY"]), **options)
        result, parsed = read_json_response("etg", response)
        if not parsed:
            return 1
        outcome = overview_outcome(response.status_code, result, approved)
        print(json.dumps({"echo_in_assigned_pair": True, **outcome}))
        return 0 if outcome["diagnostic_passed"] else 1

try:
    raise SystemExit(main())
except Exception as exc:
    print(json.dumps(failure_summary(exc)))
    raise SystemExit(1)

After the five environment variables are supplied and ETG has confirmed Sandbox access for the addresses, invoke the saved file from that directory:

.venv/bin/python ratehawk_overview.py

ETG’s overview success example uses a data array and places real_ip directly under debug, beside request. The rejection example also uses debug.real_ip. Both clients check that optional value without printing it. Missing, null or unparseable metadata leaves source corroboration unavailable and does not fail an otherwise accepted request; a valid address outside the assigned pair stops the diagnostic for investigation. No debug.request.real_ip path is assumed. Overview example, rejection example. Treat an unexpected body as a diagnostic failure to inspect privately, not proof of an IP rejection. These illustrative timeouts are for this metadata diagnostic, not recommended booking timeouts. Retrieve endpoints.

Node.js with an explicit Undici dispatcher

This setup selects Node.js 26.13.0 LTS, its bundled npm 11.20.0, and Undici 8.12.3. Undici’s exact-version metadata requires Node >=22.19.0, which the selected Node release satisfies. Install Node using your approved runtime image or official release. Its release index records the bundled npm version. On Linux, follow the release’s system-library requirements, including libatomic where needed. Undici version metadata, ProxyAgent documentation for v8.12.3.

In a separate empty Node example directory, confirm the versions below report v26.13.0 and 11.20.0, then initialize the local package and install Undici exactly:

node --version
npm --version
npm init -y
npm install --save-exact undici@8.12.3

This creates local package.json and package-lock.json files for the example. The .mjs filename explicitly selects ES modules, so no type edit is required. node:net is built into Node. npm initialization, exact dependency installation, Node module selection.

Use the undici package with a compatible Node runtime. The ProxyAgent token belongs to the proxy; the Authorization header belongs to ETG. The same dispatcher serves both destinations, but they may use different connections and therefore different members of the assigned pair. Undici ProxyAgent.

Save the following code as ratehawk-overview.mjs in that directory.

import { ProxyAgent, fetch } from 'undici';
import { isIP, isIPv4 } from 'node:net';

const SETTING_NAMES = ['QUOTAGUARDSTATIC_URL', 'QG_IP_A', 'QG_IP_B',
  'ETG_SANDBOX_KEY_ID', 'ETG_SANDBOX_API_KEY'];

class ConfigurationError extends Error {
  constructor(variable) {
    super('Missing required setting');
    this.variable = SETTING_NAMES.includes(variable) ? variable : 'unknown_setting';
  }
}

function required(name) {
  const value = process.env[name];
  if (!value) throw new ConfigurationError(name);
  return value;
}

function httpMetadata(stage, status, rawType) {
  const media = typeof rawType === 'string' ? rawType.split(';', 1)[0].trim().toLowerCase() : '';
  const allowed = new Set(['application/json', 'application/problem+json', 'text/html',
    'text/plain', 'application/octet-stream']);
  const contentType = !media ? 'unavailable' :
    media.length <= 64 && allowed.has(media) ? media : 'other';
  return { stage: ['echo', 'etg'].includes(stage) ? stage : 'unknown',
    http_status: Number.isInteger(status) && status >= 100 && status <= 599 ? status : null,
    content_type: contentType };
}

async function readJsonResponse(stage, response) {
  console.log(JSON.stringify(httpMetadata(stage, response.status,
    response.headers.get('content-type'))));
  try {
    const result = JSON.parse(await response.text());
    console.log(JSON.stringify({ stage, json_parse: 'ok' }));
    return { result, parsed: true };
  } catch {
    console.log(JSON.stringify({ stage, json_parse: 'failed' }));
    return { result: null, parsed: false };
  }
}

function sourceEvidence(result, approved) {
  const raw = result?.debug?.real_ip;
  if (raw === undefined || raw === null) return 'unavailable';
  if (typeof raw !== 'string' || isIP(raw) === 0) return 'unusable';
  return approved.has(raw) ? 'match' : 'mismatch';
}

function overviewOutcome(status, result, approved) {
  const shapeOK = result !== null && typeof result === 'object' && !Array.isArray(result);
  const evidence = shapeOK ? sourceEvidence(result, approved) : 'unavailable';
  const accepted = shapeOK && status === 200 && result.status === 'ok' &&
    result.error === null && Array.isArray(result.data);
  return { overview_accepted: accepted, etg_source_evidence: evidence,
    diagnostic_passed: accepted && evidence !== 'mismatch' };
}

function failureSummary(error) {
  return error instanceof ConfigurationError ?
    { stage: 'configuration', missing_variable: error.variable, diagnostic_passed: false } :
    { stage: 'transport_or_validation', diagnostic_passed: false };
}

let dispatcher;
try {
  const config = Object.fromEntries(SETTING_NAMES.map(name => [name, required(name)]));
  const proxy = new URL(config.QUOTAGUARDSTATIC_URL);
  if (proxy.protocol !== 'http:') throw new Error('Static URL required');
  const credentials = decodeURIComponent(proxy.username) + ':' +
    decodeURIComponent(proxy.password);
  proxy.username = '';
  proxy.password = '';
  dispatcher = new ProxyAgent({
    uri: proxy.href,
    token: 'Basic ' + Buffer.from(credentials).toString('base64')
  });
  const approved = new Set([config.QG_IP_A, config.QG_IP_B]);
  if (![...approved].every(isIPv4)) throw new Error('IPv4 values required');
  const options = () => ({ dispatcher, redirect: 'error',
    signal: AbortSignal.timeout(30000) });
  const echo = await fetch('https://ip.quotaguard.com', options());
  const echoBody = await readJsonResponse('echo', echo);
  if (!echoBody.parsed || echo.status !== 200 || !echoBody.result ||
      typeof echoBody.result !== 'object') throw new Error('Echo failed');
  if (!approved.has(echoBody.result.ip)) {
    console.log(JSON.stringify({ stage: 'echo', echo_in_assigned_pair: false }));
    throw new Error('Unexpected egress');
  }
  const response = await fetch(
    'https://api-sandbox.ratehawk.com/api/b2b/v3/overview/', {
      ...options(),
      headers: { Authorization: 'Basic ' + Buffer.from(
        config.ETG_SANDBOX_KEY_ID + ':' + config.ETG_SANDBOX_API_KEY).toString('base64') }
    });
  const decoded = await readJsonResponse('etg', response);
  if (!decoded.parsed) {
    process.exitCode = 1;
  } else {
    const outcome = overviewOutcome(response.status, decoded.result, approved);
    console.log(JSON.stringify({ echo_in_assigned_pair: true, ...outcome }));
    process.exitCode = outcome.diagnostic_passed ? 0 : 1;
  }
} catch (error) {
  console.error(JSON.stringify(failureSummary(error)));
  process.exitCode = 1;
} finally {
  try { await dispatcher?.close(); } catch {
    console.error(JSON.stringify({ stage: 'cleanup', diagnostic_passed: false }));
    process.exitCode = 1;
  }
}

After supplying the same five environment variables and confirming ETG’s Sandbox approval, run:

node ratehawk-overview.mjs

Other clients and ETG SDKs

Client Documented attachment point and limitation
curl Explicit –proxy; –noproxy “” overrides bypass rules. Keep credentials out of pasted command arguments. curl manual.
Go net/http Attach http.ProxyURL(parsedProxyURL) to a dedicated Transport. Configure the ETG request’s Basic auth separately. net/http.
PHP Guzzle Explicit proxy request option; keep auth separate, disable redirects for this diagnostic. Guzzle options.
Official ETG Python SDK, inspected revision overview forwards request kwargs to Requests; BASE_PATH is read at import, with a deprecated default. Set the correct Sandbox base before import and attach proxies explicitly. Verify the installed revision. Client, endpoints.
Official ETG PHP SDK, inspected revision Constructor forwards Guzzle defaults, but overview($options) discards its options. Absolute endpoint constants use the deprecated host, so base_uri alone cannot replace them. Use an updated, reviewed implementation or direct Guzzle for this diagnostic. Client, endpoints.

Use the attachment point supported by your installed client version and verify the deployed process. Node’s built-in fetch can use environment proxies on documented versions when enabled: NODE_USE_ENV_PROXY=1 supports fetch in v22.21.0 and v24.0.0+, while –use-env-proxy is documented from v22.21.0 and v24.5.0. Custom dispatchers and NO_PROXY affect the route. The example above explicitly uses Undici. Node proxy configuration, CLI flag.

If adapting this to axios, its current Node http adapter’s httpVersion: 2 path ignores environment proxies and rejects an explicit proxy configuration. That is a documented adapter limitation, not a claim that every custom HTTP/2 transport is impossible. axios configuration, HTTP/2 scope, v1.13.0+.

Verify in layers without making a reservation

Use this procedure from the deployed backend:

  1. Obtain ETG’s confirmation for the selected addresses and Sandbox access. Confirm overview is available to the Sandbox key.
  2. Run an IP-echo check from the deployed worker using the intended supplier client’s proxy configuration, without ETG credentials on that request. The returned address must belong to the dashboard pair.
  3. Issue one authenticated GET to https://api-sandbox.ratehawk.com/api/b2b/v3/overview/. No body, guest data, card data, booking identifiers, or write endpoints are needed.
  4. Check the HTTP result and ETG’s status/error fields. Success establishes this key’s access to overview over this route at that time. If present and parseable, debug.real_ip corroborates ETG’s observed source. Compare it with both assigned addresses, not just the echo result. Missing debug must not prevent an otherwise successful access result; a valid mismatch requires investigation. The field is optional and may change.
  5. Retain only a sanitized internal record: UTC time, deployment/client versions, environment, method/path, HTTP status, ETG error and request ID if supplied, and whether the observed address belongs to the assigned pair.

The endpoint and its limited availability are documented under Retrieve endpoints. Sandbox restrictions are documented under Sandbox.

An echo success is routing evidence for the echo destination. An overview success is access evidence for that ETG endpoint; a matching debug.real_ip adds destination-reported source evidence. Without that metadata, the response alone does not independently establish the source address ETG observed. Neither demonstrates both proxy nodes, booking behavior, production permission, retries, or failover. Repeated checks may remain on one IP because connections and DNS are reused. Obtain approval of both addresses; plan any controlled per-node verification separately using supported QuotaGuard connection details.

Match the failure to the responsible layer

Observation Next diagnostic action
Proxy 407 Inspect proxy authentication before investigating ETG credentials.
Echo outside assigned pair Stop. Inspect the actual client, deployment secrets, dispatcher/transport attachment and bypass rules.
ETG not_allowed_host Documented host/IP permission failure, listed under HTTP 400. Compare ETG’s observed address if supplied and the registration record.
no_auth_header / invalid_auth_header / incorrect_credentials Inspect ETG Basic auth and the environment/key pairing.
not_allowed / endpoint_not_found / endpoint_not_active / api_access_disabled Inspect key permissions, endpoint activation or account access.
endpoint_exceeded_limit, HTTP 429 Respect the key’s current endpoint limit; stop rapid retries.
lock / overdue_debt Treat as a duplicate-request state or account billing issue respectively, not an IP diagnosis.
DNS, TLS or connection timeout Inspect the network/client layer. A timeout alone does not establish an allowlist failure.
Generic 401/403 or a non-JSON response Preserve a sanitized diagnostic privately. Do not label it an IP rejection without specific evidence.

ETG error names and meanings come from Errors; 407 is a proxy-layer signal documented in the curl manual. Resolve unauthorized errors before repeating requests; ETG warns prolonged unauthorized traffic can lead to an IP ban. With shared addresses, an IP-level restriction could affect more than one subscriber. That is a risk inference, not evidence of an ETG collateral-ban incident. Dedicated addresses can address exclusivity, but do not bypass ETG policy. This guide does not prescribe booking retries.

Size and operate the chosen route

Budget for request and response bandwidth, including TLS/tunnel overhead. Hotel content transfers can make bandwidth more relevant than call count. Keep large downloads out of this metadata diagnostic. For production content or dump retrieval, establish the endpoint-specific approved route before deciding whether to proxy it; do not switch it directly merely to avoid metering if source-IP registration still applies. With HTTPS CONNECT, a metered QuotaGuard request is a tunnel opening, so pooled API calls are not necessarily billed individually. Account for reconnects and compare total operating costs with existing native egress. Public request-counting rules.

HTTPS CONNECT tunnels have a 600-second maximum lifetime. Retire pooled connections before that age and use endpoint-appropriate timeouts; a timeout or disconnect during an eventual booking workflow needs ETG’s operation-specific handling. Do not add automatic booking retries based on this connectivity guide. QuotaGuard also documents SOCKS5 and QGTunnel as options without this fixed lifetime cap, using the same assigned static IPs. Their suitability for a particular ETG client and workflow still needs verification; this is not an ETG compatibility claim. Technical FAQ, longer time-outs.

Before changing region, shared/dedicated allocation or Static/Shield product, arrange approval of the new addresses and coordinate the cutover. Keep rollback possible until the new route is verified. Confirm the exact new connection details and overlap arrangement with Support for the specific move. Dedicated-move credential behavior is operation-specific. Address stability is scoped to the active subscription and allocation, not ownership after cancellation.

Questions before selecting QuotaGuard

Do I need a separate pair for every ETG environment? Public documentation establishes environment separation, not an address-allocation rule. Confirm how approvals attach to keys and contracts.

Can shared addresses work? They are a candidate only if ETG accepts them for your case. If exclusivity is required, use dedicated infrastructure and still confirm address count and approval.

Do fixed IPs replace API credentials? No. Keep destination HTTPS, ETG Basic auth and key permissions.

What should I bring to QuotaGuard? Your runtime/client version, region, whether ETG accepts a shared pair, expected bandwidth and sanitized error details. Never include API or proxy secrets in a public ticket or screenshot.

For the broader app architecture, see connecting a Lovable travel app. This guide covers the ETG-specific registration and diagnostic details.

If your backend needs managed outbound identity and ETG accepts the proposed route, compare QuotaGuard plans or discuss the client setup. If your existing NAT route meets the need, keep it.


Ready to Get Started?

Get in touch or create a free trial account

Back to top ↑

Copyright © 2009 - 2026 QuotaGuard. All rights reserved.

Copyright © 2009 - 2026 QuotaGuard. All rights reserved.