Skip to content

REST API 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:

OperationRequest
List the organizations you can accessGET /organizations/api/organizations/
List vulnerabilitiesGET /api/v1/org/<organization_slug>/vulnerabilities/
Get one vulnerabilityGET /api/v1/org/<organization_slug>/vulnerabilities/<slug>/
List the vulnerabilities in a groupGET /api/v1/org/<organization_slug>/vulnerability-buckets/<id>/vulnerabilities/

For anything else, use the Fencer CLI or the MCP server.

  • 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:read to list vulnerabilities (see Roles and Permissions).

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.

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.

List endpoints are paginated by page number:

ParameterDescriptionDefault
pageThe page number to retrieve1
page_sizeNumber of results per page100

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": []
}
CallerLimit
Bearer token (service account, personal API key, or OAuth)1,200 requests per minute, per token
Signed-in browser session600 requests per minute, per user
Unauthenticated60 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.

The API uses standard HTTP status codes:

CodeMeaning
200Success
201Resource created
204Success with no response body
400Validation error — check the request body or query parameters
403Missing or rejected credentials, or your role lacks the ability
404Not found, including organizations your token cannot access
410The resource existed but was deleted
426Fencer CLI below the minimum supported version (see Upgrading)
429Rate 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.

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.

ResourceURL
Raw schemahttps://app.fencer.dev/api/schema/ (YAML; add ?format=json for JSON)
Swagger UIhttps://app.fencer.dev/api/schema/swagger-ui/
ReDochttps://app.fencer.dev/api/schema/redoc/
Terminal window
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.

Terminal window
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.

Terminal window
curl -H "Authorization: Bearer fcr_..." \
"https://app.fencer.dev/api/v1/org/acme/vulnerabilities/VULN-1A2/"
  • 403 with Authentication credentials were not provided. — the Authorization header is missing or the token was not recognised. See API Authentication.
  • 404 for an organization you belong to — check the organization_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 the Retry-After seconds, and pace requests using the X-RateLimit-Remaining header.