REST API Overview
Overview
Section titled “Overview”Fencer exposes a JSON REST API over HTTPS at https://app.fencer.dev. The Fencer web app, the
Fencer CLI, and the MCP server all use it.
The documented API is the set of operations in the OpenAPI schema Fencer serves (see OpenAPI schema). Today that is:
| Operation | Request |
|---|---|
| List the organizations you can access | GET /organizations/api/organizations/ |
| List vulnerabilities | GET /api/v1/org/<organization_slug>/vulnerabilities/ |
| Get one vulnerability | GET /api/v1/org/<organization_slug>/vulnerabilities/<slug>/ |
| List the vulnerabilities in a group | GET /api/v1/org/<organization_slug>/vulnerability-buckets/<id>/vulnerabilities/ |
For anything else, use the Fencer CLI or the MCP server.
Prerequisites
Section titled “Prerequisites”- A Fencer account with membership in at least one organization.
- A token: a service-account token, a personal API key, or an OAuth access token (see API Authentication).
- A role with the abilities the endpoint needs, such as
vulnerabilities:readto list vulnerabilities (see Roles and Permissions).
Authentication
Section titled “Authentication”Send a bearer token on every request:
Authorization: Bearer <token>Service-account tokens and personal API keys start with fcr_; create them as described in
API Access. HTTP Basic authentication is not supported. Details,
including the OAuth flow, are in API Authentication.
Base URL and versioning
Section titled “Base URL and versioning”Organization-scoped endpoints live under:
https://app.fencer.dev/api/v1/org/<organization_slug>/<organization_slug> is the slug in your organization’s URLs (/a/<organization_slug>/…), also
returned by the organizations list.
The version is in the path (/api/v1/). Responses carry Content-Type: application/vnd.fencer.v1+json. Send Accept: application/vnd.fencer.v1+json, application/json;
plain application/json also works, for both Accept and a request body’s Content-Type.
When an endpoint is deprecated, its responses carry Deprecation: true, a Sunset date, and, when
available, a Link header with rel="deprecation" pointing at upgrade notes.
Pagination
Section titled “Pagination”List endpoints are paginated by page number:
| Parameter | Description | Default |
|---|---|---|
page | The page number to retrieve | 1 |
page_size | Number of results per page | 100 |
page_size goes up to 1000 on the documented list endpoints. A page past the last page returns
404. Responses wrap the results with the total count and links to the next and previous
pages (null at either end):
{ "count": 254, "next": "https://app.fencer.dev/api/v1/org/acme/vulnerabilities/?page=2", "previous": null, "results": []}Rate limits
Section titled “Rate limits”| Caller | Limit |
|---|---|
| Bearer token (service account, personal API key, or OAuth) | 1,200 requests per minute, per token |
| Signed-in browser session | 600 requests per minute, per user |
| Unauthenticated | 60 requests per minute, per IP |
Some endpoints have their own lower limit, such as OAuth client registration (30 per minute) and
the remote MCP endpoint (120 per minute). Responses include X-RateLimit-Limit,
X-RateLimit-Remaining, and X-RateLimit-Reset (Unix time when the window resets). Over the limit,
the API returns 429 Too Many Requests with a Retry-After header in seconds.
Errors
Section titled “Errors”The API uses standard HTTP status codes:
| Code | Meaning |
|---|---|
200 | Success |
201 | Resource created |
204 | Success with no response body |
400 | Validation error — check the request body or query parameters |
403 | Missing or rejected credentials, or your role lacks the ability |
404 | Not found, including organizations your token cannot access |
410 | The resource existed but was deleted |
426 | Fencer CLI below the minimum supported version (see Upgrading) |
429 | Rate limit exceeded |
Most error bodies carry a detail message. A request with no usable credentials also carries
"code": "not_authenticated":
{ "detail": "Authentication credentials were not provided.", "code": "not_authenticated"}Validation errors map each field to its messages, with non_field_errors for errors that are not
about one field:
{ "status": ["Select a valid choice. invalid is not one of the available choices."]}Every response carries an X-Request-Id header (you can send your own: letters, digits, ., _,
and -, up to 128 characters) and X-Fencer-Server-Version. Include both when you contact
support@fencer.dev.
OpenAPI schema
Section titled “OpenAPI schema”Fencer serves an OpenAPI 3.0 schema of the documented operations. Open these URLs in a browser where you are signed in to Fencer; they do not accept API tokens.
| Resource | URL |
|---|---|
| Raw schema | https://app.fencer.dev/api/schema/ (YAML; add ?format=json for JSON) |
| Swagger UI | https://app.fencer.dev/api/schema/swagger-ui/ |
| ReDoc | https://app.fencer.dev/api/schema/redoc/ |
Examples
Section titled “Examples”List organizations
Section titled “List organizations”curl -H "Authorization: Bearer fcr_..." \ "https://app.fencer.dev/organizations/api/organizations/"A service-account token sees only its own organization. Personal API keys cannot call this endpoint (it is not organization-scoped); use the slug from your organization’s URL instead.
List critical, open vulnerabilities
Section titled “List critical, open vulnerabilities”curl -H "Authorization: Bearer fcr_..." \ "https://app.fencer.dev/api/v1/org/acme/vulnerabilities/?severity=0&status=open&order_by=-first_seen&page_size=50"severity takes 0 (Critical), 1 (High), 2 (Medium), 3 (Low), or 4 (Info), and can be
repeated. status takes open, ready_for_verification, or resolved. q searches titles,
descriptions, and slugs. order_by takes a field such as severity, first_seen, priority_level,
or sla_deadline, with - for descending. The list returns live findings only. The OpenAPI schema
lists every filter.
Get one vulnerability
Section titled “Get one vulnerability”curl -H "Authorization: Bearer fcr_..." \ "https://app.fencer.dev/api/v1/org/acme/vulnerabilities/VULN-1A2/"Troubleshooting
Section titled “Troubleshooting”403withAuthentication credentials were not provided.— theAuthorizationheader is missing or the token was not recognised. See API Authentication.404for an organization you belong to — check theorganization_slug. A service-account token only reaches its own organization, and a personal API key only reaches organizations that approved it.429 Too Many Requests— wait for theRetry-Afterseconds, and pace requests using theX-RateLimit-Remainingheader.