Testing your integration
There is no separate sandbox host: tests run against the real API with a real key, so the aim is to test as much as possible without spending credits, and to cap what the rest can spend.
Use a separate capped key#
Create a key for tests in the dashboard and give it a credit limit. When the limit is reached calls fail with KEY_BUDGET_EXCEEDED and your balance is untouched, so a loop in a test cannot drain the account.
Start with free calls#
These cost nothing, so a test suite can call them freely (still within the rate limit):
| Call | What it proves |
|---|---|
GET /v1/account | The key works and what the balance is. |
GET /v1/platforms | The catalog and each endpoint's price, parameters and status. |
GET /v1/status | Per-platform health. Public, no key. See Status. |
GET /v1/errors | Every error type your client may need to handle. |
| A request with a bad parameter | A free 422 INVALID_PARAMS or 400 (never charged), so you can test your error path. |
| A repeat of a call within its cache window | A free cache hit: X-Cache: HIT, credits_charged: 0. |
For multi-leg calls, dry_run=true on universal search and the reports returns the plan and the worst-case price for 0 credits.
Record a fixture and test your parser#
Every endpoint page has a recorded response in the real envelope. Save one as a fixture and run your parser against it. Then add cases for the awkward shapes:
- A field that is
null(unknown). Do not coerce it to zero. - A field the endpoint does not map at all (absent). See Data availability.
- An empty list:
data: []is a normal success. - An extra field your code has never seen. It must be ignored.
metadata.stale: trueandmetadata.cached: true.
Test the failure paths#
Send these on purpose and assert what your code does:
| Send | Expect |
|---|---|
No x-api-key or a wrong one | 401 UNAUTHORIZED. Not retried. |
| A missing required parameter | 422. Not retried. |
| A record that does not exist | 404 NOT_FOUND. Not charged, not retried. |
| A burst over the limit | 429 with Retry-After. Your client waits and retries. |
Test retries with idempotency#
Send the same request twice with one Idempotency-Key. The second answer has metadata.idempotent_replay: true, credits_charged: 0 and the header X-Idempotent-Replay: true. Send the same key with different parameters and you get IDEMPOTENCY_KEY_REUSED. See Idempotency.
Test webhook delivery#
For monitors, call POST /v1/monitors/{id}/webhook/test to send a signed test event to your endpoint without waiting for a schedule. Assert that your handler:
- Reads the raw body bytes before parsing.
- Verifies
Onekey-Signaturein constant time and rejects a timestamp more than 300 seconds old. - Answers
2xxwithin 5 seconds. - Ignores a second delivery with the same
Onekey-Delivery-Id.
The webhook verifier tool checks a captured body and signature in your browser.
One live smoke test#
Keep one cheap real call in CI, on a stable endpoint, to catch a bad key or a changed contract:
curl "https://api.onekey.dev/v1/github/profile?username=torvalds" \
-H "x-api-key: $ONEKEY_API_KEY"Clean up#
Delete test monitors when a run finishes (DELETE /v1/monitors/{id}), since a monitor keeps running and billing on its schedule until paused or deleted. See Monitors.