Log in Sign up
Docs/Utility/Echo

Echo v1.0 1 credit / call

GET|POST /api/v1/echo

Echoes your request back — the hello-world of Ksty.ch, free to try.

100 free/month Test keys supported OpenAPI spec Try it in the console
At a glance
Base path
/api/v1/echo
Methods
GET or POST — parameters are read identically from the query string or a JSON body
Auth
X-Api-Key header (never Authorization: Bearer)
Price
1–2 credits per call, by endpoint · about $0.0010 at 1,000 credits/USD
Free tier
100 credits, refilled every month — drawn down before your paid balance
Test mode
Supported — ksty_test_ keys call this API free of charge
Rate limit
60 calls/minute per key by default, raisable per key

Echo API

The Echo API sends back whatever you send it, wrapped in the metadata the gateway saw while processing your request. It runs no upstream, touches no third party, and always succeeds — which is exactly what makes it the fastest way to prove your integration works end to end before you wire in a real API.

Why an echo endpoint exists

Every call on Ksty.ch passes through the same pipeline — key authentication, scope and region checks, rate limiting, then credit metering — before it reaches a handler. When you are setting up a new client, a failure anywhere in that chain looks identical from the outside: a non-200 response. Echo lets you isolate your half of the problem. If Echo returns 200 with your payload intact, then your key, headers, base URL and request encoding are all correct, and any failure against a real API is about that API's parameters rather than your plumbing.

What comes back

A successful call returns your parsed parameters under echo, alongside the request context the gateway attached:

POST /api/v1/echo
X-Api-Key: ksty_test_...
Content-Type: application/json

{"hello": "world"}
{
  "echo": { "hello": "world" },
  "endpoint": "",
  "mode": "test",
  "request_id": "req_8f21c..."
}
  • echo — your parameters exactly as the gateway parsed them, so you can confirm a GET query string or a POST body decodes the way you expect.
  • endpoint — which sub-endpoint ran (empty for the root, delay for the delay endpoint).
  • mode — test for a ksty_test_ key or live for a ksty_live_ key, so you can verify which credential you actually sent.
  • request_id — the stable id for this call; log it and quote it to support.

Test vs live mode

Echo is sandbox-enabled, so a ksty_test_ key calls it for free and the response reports "mode": "test". Swap in a ksty_live_ key and the identical call is metered against your balance and reports "mode": "live". Running the same request under both keys is the simplest way to confirm your production and sandbox credentials are wired to the right environments before you flip a real integration live.

The delay endpoint

echo.delay echoes your payload after pausing for a number of seconds (0–5). Use it to exercise the timeout, backoff and retry behaviour of your client against a slow-but-successful response, without needing a real API that happens to be slow.

The delay endpoint costs 2 credits rather than 1, because it holds a worker for the duration of the pause. Keep seconds small in automated tests so you are not paying — or waiting — more than the scenario needs.

When to use it

  • The first call from a new SDK, language or environment, to confirm auth and encoding.
  • Verifying a key's mode (test vs live) and capturing the request_id format for your logs.
  • Load-testing your own client's timeout and retry paths via echo.delay.

Endpoints

GETPOST /api/v1/echo 1 credit

Echo the request payload and metadata

Parameters
ParameterTypeDescription
message optional string Any payload to echo back
Request
curl -X POST "https://ksty.ch/api/v1/echo" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"message":"example"}'
<?php
$ch = curl_init('https://ksty.ch/api/v1/echo');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => [
        'X-Api-Key: YOUR_API_KEY',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => '{    "message": "example"}',
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);
const response = await fetch('https://ksty.ch/api/v1/echo', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    "message": "example"
})
});
const data = await response.json();
import requests

response = requests.post(
    'https://ksty.ch/api/v1/echo',
    headers={'X-Api-Key': 'YOUR_API_KEY'},
    json={
    "message": "example"
},
)
data = response.json()
Response 200 OK
{
    "echo": {
        "message": "hello"
    },
    "endpoint": "",
    "mode": "test",
    "request_id": "req_8f21c4a0"
}
Response fields
FieldTypeDescription
echo object Your parameters exactly as the gateway parsed them — query string and JSON body are merged into one map.
endpoint string Which endpoint answered. Empty string for the root endpoint, "delay" for echo.delay.
mode string Whether the key that made the call was live or test — the quickest way to confirm you are using the key you meant to.
request_id string Identifier for this call, also returned in the X-Request-Id header and shown in your usage log.
GETPOST /api/v1/echo.delay 2 credits

Echo after N seconds (max 2) — for testing client timeouts

Holds the response open for a fixed number of seconds before answering, so you can exercise the paths that only appear under latency: client read timeouts, retry logic, circuit breakers, and whether your worker pool copes with a slow upstream.

Values above 2 are clamped to 2 rather than rejected — a timeout test should not fail on a validation error. Kept low deliberately: this endpoint is free under a test-mode key and holds a web worker for the pause (see F13 in the project audit), so a longer ceiling here is an invitation to abuse, not a testing convenience. Note the delay happens after metering, so a call that your client abandons mid-flight has still been charged; that is the honest simulation of a real slow upstream.

Parameters
ParameterTypeDescription
seconds optional integer 0–2 Delay in seconds, 0-2 (higher values are clamped) Defaults to 1
Request
curl -X POST "https://ksty.ch/api/v1/echo.delay" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"seconds":1}'
<?php
$ch = curl_init('https://ksty.ch/api/v1/echo.delay');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => [
        'X-Api-Key: YOUR_API_KEY',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => '{    "seconds": 1}',
]);
$data = json_decode(curl_exec($ch), true);
curl_close($ch);
const response = await fetch('https://ksty.ch/api/v1/echo.delay', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    "seconds": 1
})
});
const data = await response.json();
import requests

response = requests.post(
    'https://ksty.ch/api/v1/echo.delay',
    headers={'X-Api-Key': 'YOUR_API_KEY'},
    json={
    "seconds": 1
},
)
data = response.json()
Response 200 OK
{
    "echo": {
        "seconds": 1
    },
    "delayed": 1
}
Response fields
FieldTypeDescription
echo object Your parameters, echoed back unchanged.
delayed integer Seconds actually waited before answering — the clamped value, so you can see when 9 became 2.

Errors

Errors are JSON with a stable error.code — branch on the code, never on the message. Everything below carries the X-Request-Id of the failed call. Requests rejected by this API are not charged, and a 502 after a charge is refunded automatically.

CodeHTTPCause & what to do
missing_key platform 401 No API key was sent. Send your key in the X-Api-Key header (or an api_key parameter).
invalid_key platform 401 The key is not recognised — mistyped, truncated or never issued. Copy the key again from the API keys page. Repeated bad keys from one address are throttled, so fix it rather than retrying.
insufficient_credits platform 402 The balance can't cover the call. Top up on the Billing page. Nothing is charged and the call never reaches the API.
key_suspended platform 403 The key is suspended (for example after an abuse review). The reason is shown on the API keys page; contact support to have it restored.
key_revoked platform 403 The key was revoked, or it belongs to a team you have left. Create or use another key.
key_expired platform 403 The key is past the expiry date set on it. Create a new key, or one without an expiry.
out_of_scope platform 403 The key is valid but not scoped to this API. Add this API to the key's scopes, or use a key scoped to all APIs.
sandbox_disabled platform 403 A test (ksty_test_) key was used on an API with no sandbox. Use a live key for this API.
ip_blocked platform 403 The key has an IP allowlist and the calling address isn't on it. Call from an allowed address, or edit the key's allowlist.
geo_blocked platform 403 Calls from this country aren't permitted for this API. Contact support if you believe this is wrong.
spend_cap_reached platform 403 The account has the credits, but this API's monthly spend cap is used up. Raise or clear the cap on the API's page in your dashboard — topping up won't help.
unknown_api platform 404 No public API has that slug. Check the slug against the catalog.
unknown_endpoint platform 404 The API has no endpoint with that name. Check the endpoint list on the API's reference page.
method_not_allowed platform 405 The endpoint accepts only GET or only POST. Use the method shown for the endpoint.
rate_limited platform 429 A rate limit was exceeded — per key, per account across all your keys, or the tighter per-account limit on AI APIs. Wait for Retry-After seconds. A second key shares the account limit, so it won't help.
api_unavailable platform 502 The API is temporarily unavailable. Nothing was charged. Retry later; check the status page.
upstream_error platform 502 The API failed while processing the call. Safe to retry — any credits taken are refunded automatically.

Response headers

Every successful call reports its own cost, so you never have to guess what a request spent or reconcile it later.

HeaderMeaning
X-Request-Id Identifier for this call — on every response, in every error body and in your usage log. Quote it in support requests.
X-Credits-Charged Credits taken for this call. Zero on test-mode calls and on errors raised before the work started.
X-Credits-Remaining Balance left afterwards, across per-API grants, promotional and paid credits.
X-RateLimit-Limit Requests allowed per minute by the limit you are closest to (key, account or AI tier).
X-RateLimit-Remaining Requests left in the current window of that limit.
X-RateLimit-Reset Unix time when that window resets.
Retry-After On a 429 only: seconds to wait before retrying.