Skip to content
Coritan Docs

Client API: Reverse Proxy

User-managed reverse-proxy routes (TLS, upstreams, WAF settings).

View as Markdown

User-managed reverse-proxy routes (TLS, upstreams, WAF settings).

Base URL: https://api.coritan.com/api/v1. Paths below are complete.

To try these requests in the browser, open the interactive Client API reference.

Method Path Summary
GET /api/v1/proxy/routes List proxy routes owned by the current user
POST /api/v1/proxy/routes Create a proxy route for a domain you own
POST /api/v1/proxy/routes/connect-domain Connect a user's domain to their container server
GET /api/v1/proxy/routes/{route_id} Get details of a proxy route you own
PATCH /api/v1/proxy/routes/{route_id} Update a proxy route you own
DELETE /api/v1/proxy/routes/{route_id} Delete a proxy route you own
POST /api/v1/proxy/routes/{route_id}/cache/purge Drop copies of this website's files on every edge node
POST /api/v1/proxy/routes/{route_id}/certificate Serve your own certificate on this website instead of a free one
POST /api/v1/proxy/routes/{route_id}/error-page/preview Render the page visitors would see, for a block that is not saved yet
GET /api/v1/proxy/routes/{route_id}/redirect-rules List redirect rules for a route you own
POST /api/v1/proxy/routes/{route_id}/redirect-rules Create a redirect rule for a route you own
PATCH /api/v1/proxy/routes/{route_id}/redirect-rules/{rule_id} Update a redirect rule for a route you own; send only what changes
DELETE /api/v1/proxy/routes/{route_id}/redirect-rules/{rule_id} Delete a redirect rule for a route you own
POST /api/v1/proxy/routes/{route_id}/ssl Request SSL certificate issuance for a proxy route you own
GET /api/v1/proxy/routes/{route_id}/waf-rules Your own WAF rules on a website, oldest first, and what the account uses
POST /api/v1/proxy/routes/{route_id}/waf-rules Add a WAF rule of your own to a website
PATCH /api/v1/proxy/routes/{route_id}/waf-rules/{rule_id} Change a WAF rule of your own; send only what changes
DELETE /api/v1/proxy/routes/{route_id}/waf-rules/{rule_id} Delete a WAF rule of your own
GET /api/v1/proxy/traffic Requests your web proxies served for a domain, by hour and by hostname

List proxy routes owned by the current user

Section titled List proxy routes owned by the current user

GET /api/v1/proxy/routes

List proxy routes owned by the current user.

The list stays slim: what the Proxies list and the website's WAF tab show for a row, so neither reads a route or a certificate per row. That is the origin and whether it speaks TLS, the redirect, the extra origins, the switches, development mode as the edge reads it and the certificate GET /ssl/certificates/{domain}/status would name. Each row also says whether its origins follow its proxied DNS records (origin_follows_dns), whether the cache, Under attack mode and hotlink protection are on, and the HSTS max age (0 is off). Origin protocol, gRPC, outbound PROXY and the other site settings are on create/update and the detail.

Authentication: an access token, sent as Authorization: Bearer <token>.

Name In Type Required Description
page query integer no Default: 1.
per_page query integer no Default: 50.
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Create a proxy route for a domain you own

Section titled Create a proxy route for a domain you own

POST /api/v1/proxy/routes

Create a proxy route for a domain you own. Ownership is verified via domain registration or DNS zone.

The domain must be a full hostname such as app.example.com. It is stored in lowercase without a trailing dot. A name with * in it answers 422, because the edge looks a route up by its exact hostname.

Authentication: an access token, sent as Authorization: Bearer <token>.

application/json (required)

Field Type Required Description
domain string yes A full hostname such as app.example.com, stored in lowercase without a trailing dot. A wildcard name ('*.example.com') answers 422: add a route for each hostname.
upstream_host string or null no
upstream_port integer no
upstream_ssl boolean no
force_https boolean no
websocket_enabled boolean no
waf_enabled boolean no
send_proxy_protocol boolean no
upstream_protocol string no
grpc_enabled boolean no
max_body_size_mb integer no
timeout_seconds integer no
auto_ssl boolean no
redirect_to string or null no
redirect_status_code integer no
redirect_preserve_path boolean no
redirect_preserve_query boolean no
strip_path_prefix string or null no
upstream_path_prefix string or null no
custom_headers any or null no
upstream_backends any or null no
Status Meaning
201 Success.
422 The request is not valid. detail lists each problem.

Connect a user's domain to their container server

Section titled Connect a user's domain to their container server

POST /api/v1/proxy/routes/connect-domain

Connect a user's domain to their container server. Creates or updates a proxy route pointing the domain at the container's IP/port, and optionally provisions an SSL certificate.

Requirements:

  • User must own the domain (via registration or DNS zone)
  • User must own the server

The domain must be a full hostname. A name with * in it answers 422.

Authentication: an access token, sent as Authorization: Bearer <token>.

application/json (required)

Field Type Required Description
server_uuid string yes
domain string yes A full hostname such as app.example.com. A wildcard name ('*.example.com') answers 422.
auto_ssl boolean no
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Get details of a proxy route you own

Section titled Get details of a proxy route you own

GET /api/v1/proxy/routes/{route_id}

Get details of a proxy route you own.

Besides the route's own columns, the answer says whether its origins follow its proxied DNS records (origin_follows_dns: a proxied A or AAAA record made it, and the records' addresses are its origins), and holds the site settings PATCH takes, typed: upstream_tls_verify, cache_bypass_cookie (null when none), hsts_max_age (0 sends no HSTS header), hsts_include_subdomains, hsts_preload, under_attack, hotlink_protection and response_headers ({} when none).

Authentication: an access token, sent as Authorization: Bearer <token>.

Name In Type Required
route_id path integer yes
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

PATCH /api/v1/proxy/routes/{route_id}

Update a proxy route you own. Send only what changes.

cache_enabled, cache_max_age and cache_bypass_cookie answer 402 when the plan leaves out cache_controls, and only when they would change something.

The site settings answer 422 with the reason when they do not check out: hsts_preload on needs hsts_max_age of at least 31536000 (one year) and hsts_include_subdomains on, judged on the values after the change; cache_bypass_cookie must be a cookie name; and response_headers takes up to 20 headers, refusing a name our network sets (such as Set-Cookie, Strict-Transport-Security or Content-Length), a name sent twice in different case, and a value with a line break.

A web proxy whose origins follow its proxied DNS records (origin_follows_dns) answers 409 origin_follows_dns to a body that changes upstream_host or upstream_backends: change the A or AAAA records at its name instead. Its port, TLS, certificate check and origin protocol stay yours to change, and a new port or TLS setting applies to every one of its origins.

Authentication: an access token, sent as Authorization: Bearer <token>.

Name In Type Required
route_id path integer yes

application/json (required)

Field Type Required Description
upstream_tls_verify boolean or null no Whether our network checks the certificate of your origin when it connects over HTTPS.
cache_bypass_cookie string or null no A cookie name. A request that carries this cookie skips the cache and goes to your origin. Up to 128 characters, with no spaces. null or an empty string clears it.
hsts_max_age integer or null no Seconds browsers must use HTTPS for this website, sent in a Strict-Transport-Security header. 0 sends no header; at most 63072000 (two years).
hsts_include_subdomains boolean or null no Whether the HSTS policy also covers every subdomain of this website.
hsts_preload boolean or null no Whether the HSTS header asks browsers to add the website to their preload list. Needs a max age of at least 31536000 seconds (one year) and include subdomains on.
under_attack boolean or null no Whether every visitor answers a short math question before a page opens.
hotlink_protection boolean or null no Whether our network refuses a picture that another website's page asks for.
response_headers object or null no Headers our network sets on every answer from your website, as {name: value}. Up to 20; a name is 1 to 64 characters with no spaces and a value up to 1024 printable characters on one line. null or {} clears them.
response_headers_remove array of string or null no Header names our network removes from every answer from your website, such as Server or X-Powered-By. Up to 20 names; a header our network sets cannot be removed. null or [] clears them.
upstream_host string or null no
upstream_port integer or null no
upstream_ssl boolean or null no
force_https boolean or null no
websocket_enabled boolean or null no
waf_enabled boolean or null no
send_proxy_protocol boolean or null no
upstream_protocol string or null no
grpc_enabled boolean or null no
max_body_size_mb integer or null no
timeout_seconds integer or null no
redirect_to string or null no
redirect_status_code integer or null no
redirect_preserve_path boolean or null no
redirect_preserve_query boolean or null no
strip_path_prefix string or null no
upstream_path_prefix string or null no
custom_headers any or null no
upstream_backends any or null no
development_mode boolean or null no
development_mode_minutes integer or null no
error_page any or null no
cache_enabled boolean or null no
cache_max_age integer or null no
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

DELETE /api/v1/proxy/routes/{route_id}

Delete a proxy route you own.

A web proxy whose origins follow its proxied DNS records answers 409 origin_follows_dns: its records would make it again. Turn their proxy status off on the DNS tab, or PUT each record with proxied: false, and the web proxy goes with the last one.

Authentication: an access token, sent as Authorization: Bearer <token>.

Name In Type Required
route_id path integer yes
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Drop copies of this website's files on every edge node

Section titled Drop copies of this website's files on every edge node

POST /api/v1/proxy/routes/{route_id}/cache/purge

Drop copies of this website's files on every edge node.

With no body, or a body without urls, every file goes and the answer says "cleared": "everything". With urls (1 to 30), only those addresses go: each is a path such as /pricing?plan=pro or a full http or https URL on the website's own hostname, and the answer says "cleared": "urls" and lists each path as the edge stores it. An address on another hostname answers 422 naming that hostname.

Each file comes from your origin again on its next request, and the edge caches it again from there. Needs cache_controls under plans v2 (402 without it). 30 purges per website per hour, whatever they clear; the next one answers 429 with Retry-After.

Authentication: an access token, sent as Authorization: Bearer <token>.

Name In Type Required
route_id path integer yes

application/json

Field Type Required Description
urls array of string or null no Only these addresses, 1 to 30: a path such as /pricing?plan=pro, or a full http or https URL on the website's own hostname.
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Serve your own certificate on this website instead of a free one

Section titled Serve your own certificate on this website instead of a free one

POST /api/v1/proxy/routes/{route_id}/certificate

Serve your own certificate on this website instead of a free one.

The key must belong to the certificate, the certificate must cover the website's name, be valid now and come from a certificate authority, and a chain must start with the certificate's issuer. The certificate field may hold the whole chain, as a full-chain file does. Anything else answers 422 with the reason; a key with a passphrase is refused. The key is stored encrypted and never logged or returned.

About 30 days before the certificate expires, a free certificate replaces it, unless a newer one is uploaded first. Needs custom_certificates under plans v2 (402 without it). 10 uploads per website per hour.

Authentication: an access token, sent as Authorization: Bearer <token>.

Name In Type Required
route_id path integer yes

application/json (required)

Field Type Required
certificate_pem string or null no
private_key_pem string or null no
chain_pem string or null no
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Render the page visitors would see, for a block that is not saved yet

Section titled Render the page visitors would see, for a block that is not saved yet

POST /api/v1/proxy/routes/{route_id}/error-page/preview

Render the page visitors would see, for a block that is not saved yet.

error_page: null shows the inherited page instead, so the console can put "with" and "without" side by side.

Authentication: an access token, sent as Authorization: Bearer <token>.

Name In Type Required
route_id path integer yes

application/json (required)

Field Type Required
error_page any or null no
status integer no
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

List redirect rules for a route you own

Section titled List redirect rules for a route you own

GET /api/v1/proxy/routes/{route_id}/redirect-rules

List redirect rules for a route you own.

Authentication: an access token, sent as Authorization: Bearer <token>.

Name In Type Required
route_id path integer yes
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Create a redirect rule for a route you own

Section titled Create a redirect rule for a route you own

POST /api/v1/proxy/routes/{route_id}/redirect-rules

Create a redirect rule for a route you own.

Refusals: 400 for a match_type other than exact, prefix or regex, a status_code other than 301, 302, 307 or 308, or a regex source that is not a valid regular expression or uses something our network does not support (the message names it).

Authentication: an access token, sent as Authorization: Bearer <token>.

Name In Type Required
route_id path integer yes

application/json (required)

Field Type Required
source_pattern string yes
match_type string no
target_url string yes
status_code integer no
preserve_query boolean no
priority integer no
enabled boolean no
Status Meaning
201 Success.
422 The request is not valid. detail lists each problem.

Update a redirect rule for a route you own; send only what changes

Section titled Update a redirect rule for a route you own; send only what changes

PATCH /api/v1/proxy/routes/{route_id}/redirect-rules/{rule_id}

Update a redirect rule for a route you own; send only what changes.

Refusals: 400 as when you create a rule. A regex source is checked when source_pattern or match_type changes.

Authentication: an access token, sent as Authorization: Bearer <token>.

Name In Type Required
route_id path integer yes
rule_id path integer yes

application/json (required)

Field Type Required
source_pattern string or null no
match_type string or null no
target_url string or null no
status_code integer or null no
preserve_query boolean or null no
priority integer or null no
enabled boolean or null no
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Delete a redirect rule for a route you own

Section titled Delete a redirect rule for a route you own

DELETE /api/v1/proxy/routes/{route_id}/redirect-rules/{rule_id}

Delete a redirect rule for a route you own.

Authentication: an access token, sent as Authorization: Bearer <token>.

Name In Type Required
route_id path integer yes
rule_id path integer yes
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Request SSL certificate issuance for a proxy route you own

Section titled Request SSL certificate issuance for a proxy route you own

POST /api/v1/proxy/routes/{route_id}/ssl

Request SSL certificate issuance for a proxy route you own.

Authentication: an access token, sent as Authorization: Bearer <token>.

Name In Type Required
route_id path integer yes
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Your own WAF rules on a website, oldest first, and what the account uses

Section titled Your own WAF rules on a website, oldest first, and what the account uses

GET /api/v1/proxy/routes/{route_id}/waf-rules

Your own WAF rules on a website, oldest first, and what the account uses.

managed_rules counts the enabled rules of the managed set the website was created with. account counts the enabled rules of your own on every website and every deployment (a deployment's rule once, however many addresses carry it), which is what the plan counts; limits is the plan's allowance while plans v2 applies to the account, else null (-1 is no limit). per_website holds the caps every plan shares.

Authentication: an access token, sent as Authorization: Bearer <token>.

Name In Type Required
route_id path integer yes
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Add a WAF rule of your own to a website

Section titled Add a WAF rule of your own to a website

POST /api/v1/proxy/routes/{route_id}/waf-rules

Add a WAF rule of your own to a website.

field is one of path, query, method, user_agent, referer, cookie, country or ip; operator is is, is_not, contains, not_contains, starts_with or ends_with (a method, a country or an address takes only is and is_not); values holds 1 to 50 plain words, matched without regard to case. For ip each value is an address or a range, such as 203.0.113.7 or 198.51.100.0/24, and is matches a visitor whose address is in any of them. An ip rule needs no waf_country_rules. A rate limit takes requests (1 to 100,000) and period (10, 60, 600 or 3600 seconds) and answers 429 past them.

Refusals: 422 with the reason for a rule that does not check out, or a website that already holds 200 rules of your own (50 rate limits); 400 for values whose condition our network cannot run (the message says why); 402 under plans v2 for a rule added switched on past waf_custom_rules (a rate limit also past waf_rate_limit_rules) or a country rule without waf_country_rules; 429 past 60 rule changes a minute. A rule added with enabled: false needs room in the plan only when it is switched on.

Authentication: an access token, sent as Authorization: Bearer <token>.

Name In Type Required
route_id path integer yes

application/json (required)

Field Type Required
kind string no
description string or null no
field string or null no
operator string or null no
values array of string or null no
action string or null no
requests integer or null no
period integer or null no
enabled boolean no
Status Meaning
201 Success.
422 The request is not valid. detail lists each problem.

Change a WAF rule of your own; send only what changes

Section titled Change a WAF rule of your own; send only what changes

PATCH /api/v1/proxy/routes/{route_id}/waf-rules/{rule_id}

Change a WAF rule of your own; send only what changes.

Switching a rule on counts like adding one, and a rule that ends up on a country needs waf_country_rules when its condition changes or it is switched on (402). Switching a rule off or changing its description is always allowed. A rule support has rewritten comes back with editable: false and takes only enabled and description. A new condition is refused with 400 as when you add a rule.

Authentication: an access token, sent as Authorization: Bearer <token>.

Name In Type Required
route_id path integer yes
rule_id path integer yes

application/json (required)

Field Type Required
description string or null no
field string or null no
operator string or null no
values array of string or null no
action string or null no
requests integer or null no
period integer or null no
enabled boolean or null no
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

DELETE /api/v1/proxy/routes/{route_id}/waf-rules/{rule_id}

Delete a WAF rule of your own. The managed rules cannot be deleted here.

Authentication: an access token, sent as Authorization: Bearer <token>.

Name In Type Required
route_id path integer yes
rule_id path integer yes
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Requests your web proxies served for a domain, by hour and by hostname

Section titled Requests your web proxies served for a domain, by hour and by hostname

GET /api/v1/proxy/traffic

Requests your web proxies served for a domain, by hour and by hostname.

The counts cover every web proxy of yours whose hostname is domain or ends in .domain, over the last hours hours. The range is made of whole UTC hours and ends with the current one, so series always holds hours entries. A domain with no web proxy of yours answers with zeros and empty lists.

A request appears in the counts within about two minutes, so the current hour fills in as it passes. A visitor who is shown a challenge page is not counted.

More than 24 hours needs site_analytics in the account's plan (Pro and above), and answers 402 entitlement_exceeded without it. While account plans do not apply to the account, every domain shows all 30 days. A route_id that is not yours, or not under domain, answers 404.

Authentication: an access token, sent as Authorization: Bearer <token>.

Name In Type Required Description
domain query string yes A domain such as example.com, or one hostname such as shop.example.com. The answer covers your web proxies on that name and on every name under it. Case and a trailing dot make no difference.
hours query integer no How many hours to cover, from 1 to 720 (30 days), ending with the current hour. More than 24 needs a plan that includes site_analytics (Pro and above) while account plans apply to your account. Default: 24.
route_id query integer or null no One web proxy's route ID, to narrow totals and series to its hostname. hostnames and by_hostname still list every hostname. The route must be yours and on domain or under it.
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Fields of a 200 response:

Field Type Description
domain string The domain you asked about, in lowercase and without a trailing dot.
hours integer How many hours the counts cover.
since string The start of the oldest hour, in ISO 8601 UTC. The range runs from here to the end of the current hour.
hostnames array of TrafficHostname Your web proxies on the domain and under it: the domain itself first, then by name.
hostnames[].route_id integer The web proxy's route ID, as GET /api/v1/proxy/routes lists it.
hostnames[].hostname string The hostname the web proxy serves, in lowercase.
totals TrafficTotals Sums over the range, for every hostname, or for route_id alone when you send one.
totals.requests integer Requests the edge answered, blocked ones included.
totals.blocked integer Requests the edge refused with 403 or 429 to protect the website: the WAF, the website's own rules and settings, and rate limits. They count in requests and status_4xx too.
totals.bytes_in integer Bytes the edge received from visitors.
totals.bytes_out integer Bytes the edge sent to visitors.
totals.status_2xx integer Answers with a 2xx status.
totals.status_3xx integer Answers with a 3xx status, such as a redirect.
totals.status_4xx integer Answers with a 4xx status, blocked requests included.
totals.status_5xx integer Answers with a 5xx status: the origin failed, or the edge could not reach it.
totals.websocket_connections integer WebSocket connections the edge opened between a visitor and the origin.
totals.latency_avg_ms integer or null How long the edge took to answer a request, on average, in milliseconds. Each hour counts as much as its requests. null when there were no requests.
series array of TrafficHour One entry for each hour of the range, oldest first, with zeros for an hour without traffic. Covers the same hostnames as totals.
series[].hour string The start of the hour, in ISO 8601 UTC, such as 2026-09-15T14:00:00Z.
series[].requests integer Requests the edge answered in the hour, blocked ones included.
series[].blocked integer Requests refused in the hour with 403 or 429.
series[].bytes_out integer Bytes sent to visitors in the hour.
series[].status_4xx integer Answers with a 4xx status in the hour.
series[].status_5xx integer Answers with a 5xx status in the hour.
by_hostname array of TrafficByHostname Every hostname in hostnames with its sums over the range, busiest first, with zeros for one without traffic.
by_hostname[].route_id integer The web proxy's route ID.
by_hostname[].hostname string The hostname the web proxy serves, in lowercase.
by_hostname[].requests integer Requests over the range, blocked ones included.
by_hostname[].blocked integer Requests refused over the range with 403 or 429.
by_hostname[].bytes_out integer Bytes sent to visitors over the range.
by_hostname[].status_5xx integer Answers with a 5xx status over the range.