Convert an ngrok Traffic Policy

POST /v1/tools/convert-ngrok-policy

Turn an ngrok Traffic Policy file (YAML or JSON) into the equivalent ngris policy YAML, with a report of what was converted, what was approximated and what was skipped. Nothing is created or changed on your account: save ngris_yaml as a file and pass it to the agent with ngris http 3000 --traffic-policy policy.yaml (see Traffic rules), or add the rules to an endpoint with Add Rule.

How it converts:

  • An ngrok rule holds several actions; an ngris rule is one action. Each action becomes its own ngris rule carrying the ngrok rule's name and its expressions joined with &&. Phases and order are kept. on_tcp_connect rules go to on_udp_connect when tunnel_type is udp.
  • In expressions only req.url.path is renamed (to req.path); everything else is copied as written — check the result with Test a Rule Expression.
  • Converted directly: add-headers, remove-headers, restrict-ips (with allow / deny lists), url-rewrite, redirect, custom-response, compress-response.
  • Converted with a warning to review: rate-limit (ngrok's token bucket becomes a fixed window), deny (becomes a custom-response, 403 by default), request-body-find-replace / response-body-find-replace (one literal replace-body rule per replacement), owasp-crs-request / owasp-crs-response (the waf rule in detect mode), and jwt-validation, verify-webhook, set-vars, circuit-breaker (config copied as is; the fields differ).
  • Skipped with a warning: oauth, oidc and basic-auth (sign-in is an endpoint setting on ngris — see Update Endpoint Auth), restrict-ips that only references ngrok IP policies, forward-internal, http-request, close-connection, log, terminate-tls, sse-find-replace, any unknown action, and every action under on_event_stream_message.

Any signed-in member can call it; only a suspended account is refused.

Request body

policy string Req
The ngrok Traffic Policy document, YAML or JSON, as a string. The whole request body may be up to 256 KiB.
tunnel_type string
http (default), tcp or udp. Only udp changes the result (connect-phase rules go to on_udp_connect).

Response (200 OK)

ngris_yaml string
The ngris policy: rules grouped under on_tcp_connect, on_udp_connect, on_http_request and on_http_response, each with type and, when set, name, expression and config. {} when nothing could be converted.
converted integer
ngris rules produced.
skipped integer
ngrok actions with no ngris equivalent.
warnings array of string | null
One line per approximated or skipped action, saying what to check or redo by hand. null when there are none.

Errors

400 Bad Request
invalid request body (not JSON, or over 256 KiB), empty policy, or could not parse ngrok policy: … (the document isn't valid YAML / JSON).
401 Unauthorized
Missing or invalid auth.
403 Forbidden
The account is suspended (account_suspended).
415 Unsupported Media Type
The request has no Content-Type: application/json header.
policy.yml (ngrok)
on_http_request: - expressions: - "req.url.path.startsWith('/admin')" actions: - type: restrict-ips config: allow: - 203.0.113.0/24 - actions: - type: rate-limit config: capacity: 100 rate: 60s bucket_key: - conn.client_ip - type: log
Request
jq -n --rawfile policy policy.yml '{policy: $policy, tunnel_type: "http"}' | \ curl -X POST "https://api.ngris.com/v1/tools/convert-ngrok-policy" \ -H "X-API-KEY: <your_api_key>" \ -H "Content-Type: application/json" \ --data-binary @-
Response — 200 OK
{ "converted": 2, "ngris_yaml": "on_http_request:\n - type: restrict-ips\n expression: req.path.startsWith('/admin')\n config:\n allow:\n - 203.0.113.0/24\n - type: rate-limit\n config:\n key_name: \"\"\n limit: 100\n scope: ip\n window: 60\n", "skipped": 1, "warnings": [ "rate-limit: ngrok token-bucket (capacity/rate/bucket_key) mapped to ngris fixed-window (limit/window/scope) — close but not identical; verify limit=100 window=60s", "log: no ngris traffic-policy equivalent — skipped" ] }