Skip to content
This repository has been archived by the owner on Aug 14, 2024. It is now read-only.

Commit

Permalink
addressing feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
sentaur-athena committed Sep 12, 2023
1 parent abcda6b commit 594b255
Showing 1 changed file with 26 additions and 15 deletions.
41 changes: 26 additions & 15 deletions src/docs/api/design.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: "Designing a New API"
sidebar_order: 2
---
[Django REST framework](https://www.django-rest-framework.org/) is a powerful and flexible toolkit
[Django REST framework](https://www.django-rest-framework.org/)(DRF) is a powerful and flexible toolkit
for building Web APIs. Sentry APIs are built using DRF. Here are some considerations to make when designing APIs at Sentry.

## URL Patterns
Expand Down Expand Up @@ -31,20 +31,26 @@ Here are some additional examples:
- 👍 `/projects/{organization_slug}/{project_slug}/issues/`
- 👎 `/projects/`

**Note:** Hierarchy here does not necessarily mean that one collection belongs to a parent collection. For example `projects/{project_identifier}/teams/` and `teams/{team_identifier}/projects/` can co-exist. The first one means the teams that are working on a specific project and the latter means the projects one specific team is working on.
<Alert title="Note" level="info">

Hierarchy here does not necessarily mean that one collection belongs to a parent collection. For example:
- `projects/{project_identifier}/teams/` refers to the **teams** that have been added to specific project
- `teams/{team_identifier}/projects/` refers to the **projects** a specific team has been added to

</Alert>

### Naming Guidance
- Collection name should be hyphen-ated lower case, e.g. commit-files.
- Collection names must be plural. Avoid using uncountable words because user can’t know if the GET returns one item or a list.
- Query params and body params are CamelCased.
- For sorting and filtering try to stick with the common param names: sortBy (e.g. date_created), orderBy (either asc or desc) groupBy, limit
- Path params are snake_cased
- Collection names should be lowercase and hyphenated, e.g. `commit-files`.
- Collection names must be plural. Avoid using uncountable words because the user can’t know whether the GET returns one item or a list.
- Query params and body params should be `CamelCase`.
- For sorting and filtering, stick with the common param names: sortBy (e.g. date_created), orderBy (either asc or desc), groupBy, limit
- Path params should be `snake_case`

## Functionality
Each API should be **stateless**, have a clear purpose and do one clear thing. To achieve that try to stick with the standard methods below. If you have a need to a more complicated functionality reach out to [owners-api](https://github.com/orgs/getsentry/teams/owners-api) and we can help you achieve it.
Each API should be **stateless**, have a clear purpose, and do one specific thing. To achieve that, stick with the standard methods listed below. If your API needs to be more complicated, work with [owners-api](https://github.com/orgs/getsentry/teams/owners-api) on how to create it.

- 👍 An API that updates project settings: PATCH or PUT
- 👎 An API that creates a project and creates a team and creates alerts for that team about that project
- 👍 An API that updates project settings: PATCH for updating a field or PUT for updating settings
- 👎 An API that creates a project, creates a team, and creates alerts for that team about that project

| Functionality | HTTP Method | Response Object | Example |
| --- | ---- | ---- | ---- |
Expand All @@ -58,7 +64,7 @@ Each API should be **stateless**, have a clear purpose and do one clear thing. T
| Batch Update | PUT | List of serialized updated resources | [Update a list of issues](https://github.com/getsentry/sentry/blob/ea14f740c78b8df68281ffad6a3bf3709ed3d5b5/src/sentry/api/endpoints/organization_group_index.py#L379) |
| Batch Delete | DELETE | None | [Delete a list of issues](https://github.com/getsentry/sentry/blob/ea14f740c78b8df68281ffad6a3bf3709ed3d5b5/src/sentry/api/endpoints/organization_group_index.py#L467)|

Here are some examples where you might think standard methods are not enough but they actually are:
Here are some examples of how to use standard methods to represent complex tasks:
- Get count of a resource
- Count is part of the `List` API and is provided in header X-Total-Count param
- Get latest of a resource
Expand All @@ -68,11 +74,16 @@ Here are some examples where you might think standard methods are not enough but

### Batch vs. Single Resource Methods
Here are some notes that can help you decide between similar methods. We use *Get* here as an example but the same applies to all the other methods in the parenthesis.
- **Get (Update, Delete)**: Use get on the `{resource}DetailsEndpoint` to retreive a resource. For example, `ProjectDetailsEndpoint`.
- **Get (Update, Delete)**: Use get on the `{resource}DetailsEndpoint` to retrieve a resource. For example, `ProjectDetailsEndpoint`.
- **List (Create, Batch Create, Batch Update, Batch Delete)**: Use get on the `{resource-parent}{resource}Endpoint` to retreive all resources that belong to that parent. For example `TeamProjectsEndpoint`.
- **Batch Get (Batch Create, Batch Update, Batch Delete)**: Use get on the `{root-parent}{resource}Endpoint`. The difference between `Batch` and `List` is that batch usually includes a list of `ids` as query parameter and retruns details about those ids. This list does not necessarily belong to one parent. For example, we can't retreive two projects that belong to two different teams in the above example and in that case we use the get method in the root resource, in this case `OrganizationProjectsEndpoint`.
- **Batch Get (Batch Create, Batch Update, Batch Delete)**: Use get on the `{root-parent}{resource}Endpoint`. The difference between `Batch` and `List` is that batch usually includes a list of `ids` as query parameter and returns details about those ids. This list does not necessarily belong to one parent. For example, we can't retrieve two projects that belong to two different teams in the above example and in that case we use the get method in the root resource, in this case `OrganizationProjectsEndpoint`.

## Response Object
Each response object returned from an API should be a serialized version of the django model associated with the resource. You can see all the existing serializers [here](https://github.com/getsentry/sentry/tree/master/src/sentry/api/serializers/models).
Each response object returned from an API should be a serialized version of the Django model associated with the resource. You can see all the existing serializers [here](https://github.com/getsentry/sentry/tree/master/src/sentry/api/serializers/models).

<Alert title="Note" level="info">

**Note:** Some models might have different serializers based on usecase. For example `Project` can be serialized into `DetailedProjectSerializer` or `ProjectSerializer`. Decide which one to use based on your usecase and API scope but **DO NOT RETURN CUSTOM OBJECTS** like `{slug: project_slug, platform: project_platform}`. We want the API responses to be uniform and can be used in multiple automations without adding extra complication to the external developers' code.
Some models might have different serializers based on use case. For example, `Project` can be serialized into `DetailedProjectSerializer` or `ProjectSerializer`. Decide which one to use based on your use case and API scope but **DO NOT RETURN CUSTOM OBJECTS** like {`slug: project_slug, platform: project_platform`}. We want the API responses to be uniform and useable in multiple automations without adding extra complication to the external developers' code.


</Alert>

0 comments on commit 594b255

Please sign in to comment.