v1 · REST · JSON
Winloom API
Push the accounts your team is working into Winloom, and read back what Winloom has established about them. Every fact comes with the public source it was taken from.
- Base URL
https://api.winloom.ai- Format
- JSON request and response bodies, UTF-8
- Versioning
- In the path (
/v1). Additive changes ship within a version; breaking changes get a new one.
Everything you can reach is scoped to your own workspace. The workspace comes from your token, so no request parameter can name another one.
Authentication
Send a bearer token on every request except /health:
Authorization: Bearer <your token>
Tokens are issued by Winloom for your workspace. To get one, or to revoke one, talk to your Winloom contact. We store only a hash of each token, so we can't show it to you again. Keep it somewhere safe.
Unknown, revoked and expired tokens all get the same answer, 401 invalid_token.
That's deliberate.
Scopes
Each token carries one or more scopes. An endpoint that needs a scope your token lacks answers
403 insufficient_scope and names the scope it needed.
| Scope | Allows |
|---|---|
read | List and read accounts, including their sourced facts. |
write | Create accounts. Grant read too if the integration also reads. |
Errors
Every answer from api.winloom.ai is JSON, including errors. You'll never get a
redirect or an HTML page. Errors carry a stable machine code in error:
{ "error": "insufficient_scope", "required": "write" }
| Status | error | Meaning |
|---|---|---|
| 401 | missing_bearer_token | No Authorization: Bearer header. |
| 401 | invalid_token | Unknown, revoked or expired. |
| 403 | insufficient_scope | Token lacks the scope in required. |
| 403 | tenant_disabled | The workspace has been disabled. |
| 403 | token_has_no_tenant | The token isn't bound to a workspace. |
| 404 | not_found | No such route, or no such account in your workspace. |
| 409 | domain_exists | An account with this domain already exists. |
| 422 | (validation) | Body failed validation. See message and per-field errors. |
| 429 | Rate limit reached. See Rate limits. |
The validation error is the only one with a different shape:
{
"message": "The domain field format is invalid.",
"errors": { "domain": ["The domain field format is invalid."] }
}
Rate limits
120 requests per minute per client IP address across /v1/* and
/health. Requests over the limit get 429. Back off and retry after a
short wait. If you need a higher limit, talk to us.
GET /health
Liveness check. No token needed, so it still works when your credentials are the problem.
curl https://api.winloom.ai/health
200 OK
{
"status": "ok",
"service": "winloom-api",
"version": "v1",
"time": "2026-10-05T07:59:29+00:00"
}
GET /v1/accounts
Scope: read
The 100 most recently created accounts in your workspace, newest first.
curl https://api.winloom.ai/v1/accounts \
-H "Authorization: Bearer $WINLOOM_TOKEN"
200 OK
{
"data": [
{ "id": 3, "name": "Example AG", "domain": "example.com",
"created_at": "2026-09-05 15:52:10+00" }
]
}
GET /v1/accounts/{id}
Scope: read
One account, plus the facts Winloom has established about the company from the public record.
Each fact carries its source, meaning the URL it came from and when we fetched it. If
you show these facts to anyone, keep the source with them.
claims is empty until research on the account has finished.
curl https://api.winloom.ai/v1/accounts/3 \
-H "Authorization: Bearer $WINLOOM_TOKEN"
200 OK
{
"data": {
"account": { "id": 3, "domain": "example.com", "name": "Example AG",
"created_at": "2026-09-05 15:52:10+00" },
"claims": [
{
"predicate": "company.industry",
"value": "Industrial automation",
"source": { "url": "https://example.com/", "fetched_at": "2026-09-09 02:31:12+00" }
}
]
}
}
| Field | Notes |
|---|---|
predicate | What the fact is about, e.g. company.industry, company.what_they_do. New predicates can appear within v1, so ignore any you don't recognise. |
value | Any JSON value: a string, number, list or object, depending on the predicate. |
source | url and fetched_at of the page the fact was read from. |
POST /v1/accounts
Scope: write
Adds an account to your workspace and queues research on it. The call returns right away, and
research runs in the background. Poll GET /v1/accounts/{id}
to see the facts arrive.
| Field | Rules |
|---|---|
name | Required. String, up to 200 characters. |
domain | Required. Bare hostname such as example.com: no scheme, path or port. Lower-cased on save. Unique within your workspace. |
curl https://api.winloom.ai/v1/accounts \
-H "Authorization: Bearer $WINLOOM_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "Example AG", "domain": "example.com"}'
201 Created
{ "data": { "id": 3, "domain": "example.com" } }
409 Conflict
{ "error": "domain_exists", "domain": "example.com" }