What you will learn
- Which keys exist and where each one goes
- Making your first call
- Pagination, idempotency and limits
- Seeing every call in the log
Before you start
- A startup created on Krows
- Your own server: the secret key never goes in the browser
Chapter 1Overview
The Krows API is a REST API, in English, with JSON responses, modelled on Stripe’s. With it you create checkout sessions from your server, read your round, investments, milestones and rewards, and query events. Webhooks tell you what happens without polling.
| Base | https://xvxhouuprjsmpfiwxkzz.supabase.co/functions/v1/api/v1 |
| Authentication | Authorization: Bearer sk_… header |
| Format | JSON, fields and events in English. Krows-Version: 2026-10-17 header on every response. |
| Limit | 100 requests per minute per key. |
| CORS | None: the API does not accept browser calls. |
Chapter 2The keys
| Key | Where it goes | What for |
|---|---|---|
pk_test_… / pk_live_… | Your site (button, widget) | Identifying your startup. It is public. |
sk_test_… / sk_live_… | Only your server | Calling the API. Grants access to your startup. |
| Each endpoint’s signing secret | Only your server | Verifying webhook signatures. |
- Go to your startup › Integration › API for your appOr dashboard › API and webhooks.
- Tap “Create secret key”Copy it and keep it safe (environment variable). For security you will not see it again: if you lose it, roll it.
- Rolling invalidates it instantly. Do it if it leaks.
The secret key never goes in a browser, a mobile app or a public repository.
Chapter 3Your first call
Read your round. With sk_test everything happens in test mode.
curl https://xvxhouuprjsmpfiwxkzz.supabase.co/functions/v1/api/v1/round \
-H "Authorization: Bearer $KROWS_SECRET_KEY"const res = await fetch('https://xvxhouuprjsmpfiwxkzz.supabase.co/functions/v1/api/v1/round', {
headers: { Authorization: `Bearer ${process.env.KROWS_SECRET_KEY}` },
});
const round = await res.json();
console.log(round.raised, round.goal, round.status);import os, requests
r = requests.get("https://xvxhouuprjsmpfiwxkzz.supabase.co/functions/v1/api/v1/round",
headers={"Authorization": f"Bearer {os.environ['KROWS_SECRET_KEY']}"})
round = r.json()
print(round["raised"], round["goal"], round["status"]){
"object": "round",
"mode": "live",
"startup": { "name": "Aurora Solar", "slug": "aurora-solar" },
"status": "open",
"goal": 120000,
"raised": 46800,
"currency": "USDC",
"percent_raised": 39,
"investors": 90,
"tokens": 120000,
"token_price": 1,
"start": "2026-10-03T00:00:00.000Z",
"end": "2027-01-15T00:00:00.000Z",
"contract": "9fQk…",
"network": "mainnet"
}The first successful call marks the “API” integration as detected in Integration, in the key’s mode.
Chapter 4Pagination, idempotency and errors
Pagination
Lists return {"object": "list", "data": [...], "has_more": true|false}. Use limit (1–100, default 20) and starting_after with the last item’s id.
curl "https://xvxhouuprjsmpfiwxkzz.supabase.co/functions/v1/api/v1/investments?limit=20" \
-H "Authorization: Bearer $KROWS_SECRET_KEY"
# Next page: pass the id of the last item
curl "https://xvxhouuprjsmpfiwxkzz.supabase.co/functions/v1/api/v1/investments?limit=20&starting_after=inv_…" \
-H "Authorization: Bearer $KROWS_SECRET_KEY"{
"object": "list",
"data": [ { "object": "investment", "id": "inv_…", … } ],
"has_more": true
}Idempotency
When creating a session, send Idempotency-Key. If you retry after a network failure, you get the same session instead of a new one.
Errors
Standard HTTP codes and a body like this:
{
"error": {
"type": "invalid_request_error",
"code": "amount_invalid",
"message": "amount must be a USDC number, at least 1, with up to 2 decimals."
}
}| HTTP · code | Meaning |
|---|---|
| 400 · invalid_json | The body is not JSON. |
| 400 · amount_invalid / amount_too_large | Invalid amount or above the goal. |
| 400 · email_invalid / url_invalid / metadata_invalid | Field with the wrong format. |
| 401 · api_key_missing / api_key_invalid | Key missing, malformed or rolled. |
| 404 · resource_missing / route_missing / startup_missing | Not found. |
| 409 · session_not_open | The session is already complete or expired. |
| 429 · rate_limit | Over 100 requests per minute. |
| 500 · internal_error | Our error. Retry with the same Idempotency-Key. |
Chapter 5Log and Workbench
In API and webhooks, the “Log” tab shows every API call (method, path, status, time, query, body and response; never the headers, where the key travels) and every webhook delivery, with “Resend”. They are kept for 30 days. The Workbench (W key or “Developers” in the bottom bar) brings together events, logs and integration health; you can hide it in Settings › Developers, where you also choose the API version and the code sample language.
Chapter 6Final review
Before you close this guide, check you have it clear. None of this is sent anywhere: it is just for you.
Where do you put the sk_live key?
Thanks. We will use it to improve.