Making an API Public

Introduction

In this document, we explain both how you make an API public and the considerations to take into account before doing so.

Definitions

Managed Client

A managed client is one that Sentry controls, such as our frontend. In this type of client, we control both which endpoints are used and the attributes used by those endpoints.

Partially Managed Client

A partially-managed client is one that we only partially control, since we do not control the version of the client that is running for our users; for example, our Sentry CLI. While we control the endpoints the CLI uses, once the CLI is installed and running in a customer's implementation, we don't control the version of the client a user runs.

External Client

An external client is a client that Sentry does not control; for example, a script written by a customer run in their repository, or an integration written using the Integration Platform. For this type of client, we have no control over the endpoints they choose to use, nor can we require that they immediately update their endpoint.

Private API

A private API is an undocumented API. Sentry can make breaking changes to this type of API, and no one will blink an eye.

Public API

Our public API is documented at https://docs.sentry.io/api/.

Private Attributes in a Public Endpoint

You can have private attributes within a public endpoint.

As an example: https://docs.sentry.io/api/teams/retrieve-a-team/. The response has multiple attributes:

Copied
{
  "id": "2",
  "slug": "the-interstellar-jurisdiction"
  ...
}

Let's say we also return a nickname for a team. If what is returned is not documented as a response in our public documentation, that attribute is a private attribute within a public endpoint.

API Versioning

Currently, Sentry's API is v0 and is considered to be in draft phase. While we don't expect our public endpoints to change greatly, keep in mind that our API is still under development.

Making an endpoint public

When you make an endpoint public, you're committing to always returning at least the set of defined attributes when that endpoint is called. As a result, the attribute(s) cannot be removed from an endpoint after they are public. Additionally, the type of the attribute cannot be changed once the attribute is public. The reason the attribute and its type cannot be changed is because both external and managed clients are relying on the public attribute to be returned from that endpoint.

You can add attributes to a public endpoint.

When to make an API public?

Making an API public offers considerable benefits. A public API allows our customers to incorporate Sentry into their workflows. It also gives Sentry more visibility in our customers' organizations ("Woah that's cool data, where'd it come from?"..."Sentry!"). Remember, however, making an API public means that once an endpoint is public, you can only add to it: You cannot make any breaking changes.

As a guide, use these questions:

  1. Is the feature for which you're making the public endpoint stable?
  2. Will the API change substantially in the future?

If your answers are Yes and No, you're in business - make the endpoint public. Head over to the public API checklist and ensure that your endpoint conforms to the checklist.

How to make an endpoint public?

We use Open API Spec 3 and the drf-spectacular library to document our APIs. You can find the tests here: https://github.com/getsentry/sentry/tree/master/tests/apidocs.

Local development

To add documentation for a new endpoint: API Documentation consists of a few items:

  • URL and query parameters
  • Request Schema (None if no body)
  • Response Schema
  • Examples

Below we'll describe how to document these for an endpoint.

Declare the endpoint public by setting the public attribute with the appropriate HTTP verbs.

Copied
class OrganizationSCIMMemberDetails(...):
  public = {"GET"}

Tag the endpoint view if needed (a parent class may already be tagged), this is how the endpoint makes it into a particular sidebar endpoint grouping. You can see the current list of tags or add tags here.

Copied
from drf_spectacular.utils import extend_schema

@extend_schema(tags=["SCIM"])
class SCIMEndpoint(...):
  public = {"GET"}

For the rest of the documentation, we'll use @extend_schema on the various endpoint methods, for example:

Copied
@extend_schema(
  operation_id="Retrieve an Organization's details", # What goes in the doc sidebar for the name of the API page
  parameters=[GLOBAL_PARAMS.ORG_SLUG, SCIMQueryParamSerializer], # use the global params, and/or a DRF Serializer
  request=None, # this will usually be a DRF Serializer if the endpoint takes a body
  responses={
            200: OrganizationSerializer, # The Sentry response serializer
            401: RESPONSE_UNAUTHORIZED,
            403: RESPONSE_FORBIDDEN,
            404: RESPONSE_NOTFOUND,
        },
  examples=[OpenApiExample()], # see the link to an existing documented endpoint below for how to define an example
)
def get(self,request, organization):
  pass

Examples can be directly inserted using OpenApiExample, and multiple can be provided.

Specify an operation_id (this is what is shown as the title under the docs site sidebar).

Specify the parameters using a list, and a serializer if needed.

  • DRF serializers work very well for query parameters, try to use them where possible.

Specify the request and response serializers.

  • Request serializers, since they use DRF serializers, can generally just be the serializer itself. There is plenty of customization and if needed can be overriden with inline_serializer. These will be passed to the request parameter in extend_schema.
  • For our response serializers, you must type the serialize function's return with a TypedDict and pass the serializer as a parameter in extend_schema. See here for an example of this.
  • If the response is a wrapper or you need more customization, you can use the inline_sentry_response_serializer function.
Copied
from sentry.apidocs.utils import inline_sentry_response_serializer

@extend_schema(
  responses={
    200: inline_response_serializer(
      "OrganizationList",
      List[OrganizationSerializerResponse])
      # A common use case is to return a list of serialized items
  }
  • Note that you can instead provide OpenAPI JSON, so you can fall back to this if you are running into issues.

See here for an example of an endpoint documented using drf-spectacular, and the drf-spectacular docs here to learn more.

Note that if the endpoint you're modifying previously had JSON documentation, you will need to delete the old documentation found in this file

Write a test here.

Tips:

  • make test-api-docs builds the OpenAPI JSON and runs all API docs tests.
  • To only build the docs, run make build-api-docs. The build will fail if there are any warnings.
  • To see the diff of your newly generated docs with prod, run make diff-api-docs. This requires you to have built the OpenAPI JSON already.

To see your changes in the docs locally:

In sentry:

  1. Run make watch-api-docs. This command will watch API docs files and continuously build an intermediate asset tests/apidocs/openapi-derefed.json.
  2. Copy the full path to tests/apidocs/openapi-derefed.json.

In sentry-docs:

  1. Run OPENAPI_LOCAL_PATH=COPIED_FULL_PATH DISABLE_THUMBNAILS=1 yarn start and substitute COPIED_FULL_PATH with the copied path to your local openapi-derefed.json

See here for detailed doc build instructions.

When you open the pull request, please add a screenshot of the page or pages you're adding.

Build process

The openapi-diff test will fail when CI runs on your pull request, this is expected and meant to highlight the diff. It is not required to merge.

Once you make changes to an endpoint and merge the change into Sentry, a series of GitHub Actions will be triggered to make your changes automatically go live:

  1. The openapi / deref_json GitHub Action in sentry will update the schema in sentry-api-schema with the OpenAPI build artifact.
  2. In sentry-api-schema, the sentry-docs / bump GitHub Action will be triggered and this will bump the SHA that references sentry-api-schema in sentry-docs with the latest.
  3. Finally, a build is triggered in sentry-docs.

Requesting an API to be public

Want an endpoint to be public?

Look at the issues on sentry with the Component: API label. If a request has already been made to make the endpoint public, give it a thumbs up. If not, create a feature request on Sentry and add the Component: API label.

The team responsible for the endpoint will review the stability of the endpoint. If the endpoint will not have breaking changes in future, they can determine whether to make it public.

FAQs

When should an attribute be required?

An attribute is required if it will always be returned by the API.

What does it mean when a response doesn't have a schema?

Some endpoints have no response schema. This means that while the endpoint is public, the attributes within that endpoint can change at any time. This is a relic from migrating the documentation from our prior approach. Note that, going forward, we recommend new endpoints always provide response schema.

I have a question and it has not been answered.

No problem. Send us an email so we can answer your question.

Can customers use private endpoints?

Yes, if they wish. However, private endpoints can change at any time, without notice. As a result, the customer's code could break.

You can edit this page on GitHub.