Skip to Content
APITesting your integration

Testing your integration

There is no test mode

Asky has no sandbox, no test keys, and no separate test data, and you do not need them.

There is no sandbox. Developing against your real workspace has the advantage that you are testing against the data shapes you will actually receive rather than fixtures that drift, and reads cannot damage anything.

Be deliberate about the write endpoints, which are real. DELETE on a topic removes the prompts beneath it and the measured history attached to them. Use dry_run=true first: it reports exactly what would be removed and removes nothing.

What you do need to test is how your integration behaves when a request fails. That is what this page covers.

Use a dedicated key for development

Create a key named for the purpose, Local development or CI, rather than reusing a production key. You can then revoke it without touching anything that matters, and usage separates your test traffic from real traffic.

If you work on one brand, restrict the key to it. Development then cannot accidentally read across your whole workspace.

Provoking each error

Every failure mode is reachable deliberately, which means you can test your handling rather than hoping it works.

To testDo thisExpect
Missing credentialsOmit the Authorization header401 invalid_token
Bad credentialsSend Bearer asky_sk_not_a_real_key401 invalid_token
Revoked keyCreate a key, revoke it, then use it401 token_revoked
Expired keyCreate a key with an expiry a minute away, wait401 token_expired
Wrong permissionsRequest a brand your key is not permitted to reach404 not_found
Unknown resourceUse a well-formed id that does not exist404 not_found
Malformed requestSend ?limit=99999 or ?start_date=12-08-2026400 invalid_request
Unknown parameterSend ?engnie=chatgpt400 invalid_request
Bad cursorSend ?cursor=nonsense400 invalid_cursor
Wrong methodSend POST to any endpoint405 method_not_allowed
Rate limitingLoop requests past 300 in a minute429 rate_limited with Retry-After
# Unknown parameter, the most common real-world 400 curl -G https://api.askylabs.com/v1/brands \ -H "Authorization: Bearer $ASKY_API_KEY" \ -d limt=10

Test the 429 path deliberately at least once. Backoff code is written early, rarely exercised, and discovered to be wrong during the first busy backfill. Provoking it on purpose is far cheaper than finding out later.

What to assert

Retry only what is retryable. A test that a 400 is not retried is as valuable as one that a 429 is. Retry loops over permanent failures burn your budget and delay you noticing the real problem.

Pagination terminates. Walk a list to the end and assert you saw every item exactly once. Assert too that your loop stops on next_cursor: null rather than on a short page, since a page can be short and still have more after it.

Unknown fields are ignored. Add an invented property to a fixture and assert your parser does not throw. Strict parsers that reject unrecognised fields are the single most common cause of an integration breaking on an additive change that nobody else notices.

Empty results are handled. Assert your code does something sensible with zero rows, since a valid request can legitimately return none.

No key in your logs. Assert your error paths log the request_id and never the Authorization header.

Recording real responses

For fast, offline tests, record real responses once and replay them. Redact the key from any recording before it is committed, since request headers are captured by most recording libraries by default.

Refresh recordings periodically. Fixtures that never change stop reflecting the API, and a test suite passing against a two-year-old shape is a false sense of safety.

In CI

Store the key in your CI provider’s secret store, never in the workflow file, and confirm your provider masks it in logs.

Keep CI traffic light. A test suite that walks full result sets on every commit competes with production for the same rate limit if it shares a key, which is another reason CI should have its own.

If your CI runs on forked pull requests, make sure secrets are not exposed to them. Most providers withhold secrets from forks by default; confirm rather than assume.

Before you go live

  • A 401 on your scheduled job raises an alert to a person, not just a log line.
  • Backoff has been exercised against a real 429.
  • The job alerts when it does not run, not only when it errors.
  • Your key’s expiry, if it has one, is on a calendar or the reminder emails reach a monitored address.
  • You can find a request in your own logs by request_id.
Last updated on