From ee597606b2b5574a90b1c8be665f16916bb64334 Mon Sep 17 00:00:00 2001 From: Shana Matthews Date: Tue, 8 Aug 2023 15:04:52 -0700 Subject: [PATCH] Add basic API tutorials (#7433) - Add tutorial for generating API keys - Add basic tutorial for creating and listing projects - Add unpublished draft guide for projects-related APIs --------- Co-authored-by: getsantry[bot] <66042841+getsantry[bot]@users.noreply.github.com> --- src/api/guides/create-auth-token.mdx | 66 +++++ src/api/guides/index.mdx | 5 + src/api/guides/projects-guide.mdx | 107 +++++++++ src/api/guides/teams-tutorial.mdx | 279 ++++++++++++++++++++++ src/api/index.mdx | 2 + src/components/apiSidebar.tsx | 13 +- src/gatsby/createPages/createApiGuides.ts | 72 ++++++ src/gatsby/createPages/index.ts | 2 + 8 files changed, 545 insertions(+), 1 deletion(-) create mode 100644 src/api/guides/create-auth-token.mdx create mode 100644 src/api/guides/index.mdx create mode 100644 src/api/guides/projects-guide.mdx create mode 100644 src/api/guides/teams-tutorial.mdx create mode 100644 src/gatsby/createPages/createApiGuides.ts diff --git a/src/api/guides/create-auth-token.mdx b/src/api/guides/create-auth-token.mdx new file mode 100644 index 0000000000000..c05c6c8d24b24 --- /dev/null +++ b/src/api/guides/create-auth-token.mdx @@ -0,0 +1,66 @@ +--- +title: "Tutorial: Create a Sentry Authentication Token" +sidebar_order: 8 +--- + +To use Sentry's APIs, you must have an authentication token. This tutorial walks you through creating an organizational auth token through an internal integration. Sentry recommends using organizational auth tokens whenever possible, as they aren't linked to specific user accounts. + +See our documentation on [authentication](/api/auth/) to learn more about the different types of authentication tokens available. + +## Prerequisites + +- A Sentry account with an organization-level role of Manager or Admin. + +## Create an Internal Integration + +[Internal integrations](/product/integrations/integration-platform/internal-integration/) are used to create custom Sentry integrations for your organization. They can also be used to create and manage your organization auth tokens. + +1. Open [sentry.io](https://sentry.io/) + +1. Click "Settings" in the left menu to open the **Organization Settings** page. + +1. Click "Custom Integrations" in the left side panel to create a new internal integration and org-level auth token. + +1. Press the "Create New Integration" button. + +1. Make sure "Internal Integration" is selected in the modal and press "Next". + +1. Enter a name for your integration. + +
+ +
+ +## Create a API Authentication Token + +1. Under "Permissions" select the permissions required for the APIs you wish to call. + + Each API endpoint docs page lists the required permissions, in the "Scopes" section. For example, the [Create a New Project](/api/projects/create-a-new-project/) endpoint requires project:write permissions or higher. + +1. Click "Save Changes". + +1. Scroll down to the bottom of the page and copy the generated token under "Tokens". + +
+ +
+ +Keep your auth token around on your clipboard or in an environment variable to use in API calls. diff --git a/src/api/guides/index.mdx b/src/api/guides/index.mdx new file mode 100644 index 0000000000000..f2bfe7f1defb3 --- /dev/null +++ b/src/api/guides/index.mdx @@ -0,0 +1,5 @@ +--- +title: API Guides +--- + + diff --git a/src/api/guides/projects-guide.mdx b/src/api/guides/projects-guide.mdx new file mode 100644 index 0000000000000..bb9416ffa20f9 --- /dev/null +++ b/src/api/guides/projects-guide.mdx @@ -0,0 +1,107 @@ +--- +title: "Guide: Create and Configure a Project with the Sentry API" +sidebar_order: 8 +--- + +This guide provides a high-level overview of how to use Sentry's API to create a new project and configure advanced settings on that project. It assumes a intermediate level of familiarity with Sentry and Sentry's APIs. + +For a beginner-friendly tutorial, check out the [Create and List Teams with the Sentry API](/api/guides/teams-tutorial/) tutorial. + +Endpoints used in this guide: + +- [Create a New Project](/api/projects/create-a-new-project/) +- [Update an Inbound Data Filter](/api/projects/update-an-inbound-data-filter/) +- [Update a Project](/api/projects/update-a-project/) +- [Update a Client Key](/api/projects/update-a-client-key/) +- [Add a Team to a Project](/api/projects/add-a-team-to-a-project/) + +## Prerequisites + +- One or more Sentry authentication tokens with the required scope(s) for each endpoint. + + > If you don't have an authentication token, follow the [Create a Sentry Authentication Token](/api/guides/create-auth-token) tutorial to create an organization auth token. + +We recommend using a free [Sentry developer account](https://sentry.io/pricing/) for this tutorial. + +## Create a Project + +To programmatically create a new project in Sentry, use the [Create a New Project](/api/projects/create-a-new-project/) endpoint. + +### Auth scope + +This endpoint requires an auth token with a scope of `project:write` or higher. + +### Required parameters + +As with most Project APIs, you must specify the `organization_slug` and `team_slug` for an existing organization and team to add the project to to as path parameters in the API call. You must also specify the project name, `name`, as a query parameter. + +### Other parameters + +If you don't specify a `platform`, the default platform is JavaScript. The `default_rules` param specifies whether the default alert rule (users are notified for every new issue) should be turned on for the project. Today, other than this setting, alert rules can only be modified or created through the Sentry UI. + +Here's an example cURL call that shows creating a new project with the following parameters: + +- Path Parameters + + - `organization_slug`: `test-org` + - `team_slug`: `test-team` + +- Query Parameters + - `name`: `proj-name` + - `platform`: + - `default_rules=false` = + +```cURL +url https://sentry.io/api/0/teams/{organization_slug}/{team_slug}/projects/ \ + -H 'Authorization: Bearer ' \ + -H 'Content-Type: application/json' +``` + +## Add an Inbound Data Filter to the Project + +- [Update an Inbound Data Filter](https://docs.sentry.io/api/projects/update-an-inbound-data-filter/) endpoint + - Path Parameters + - `organization_slug` + - `team_slug` + - `filter_id` + - Query Parameters + - `active` + - `subfilters` + +## Add a Custom Inbound Data Filter to the Project + +- [Update a Project](https://docs.sentry.io/api/projects/update-a-project/) endpoint + - Path Parameters + - `organization_slug` + - `team_slug` + - Query Parameters + - `options` + { + options: { + filters:react-hydration-errors: true, + filters:blacklisted_ips: "127.0.0.1\n192.168. 0.1" + filters:releases: "[!3]\n4" + filters:error_messages: "TypeError*\n*ConnectionError\*" + } + } + +## Update the DSN Client Key of the Project's Rate Limits + +- [Update a Client Key](https://docs.sentry.io/api/projects/update-a-client-key/) endpoint + - Path Parameters + - `organization_slug` + - `team_slug` + - `key_id` + - Query Parameters + - `rateLimit` + { + "rateLimit": { + "window": 7200, // time in seconds + "count": 1000 // error cap + } + } + +## Add a Team to the Project + +- [Add team to a project](https://docs.sentry.io/api/projects/add-a-team-to-a-project/) endpoint +- [Remove team from project](https://docs.sentry.io/api/projects/delete-a-team-from-a-project/) endpoint diff --git a/src/api/guides/teams-tutorial.mdx b/src/api/guides/teams-tutorial.mdx new file mode 100644 index 0000000000000..089a7f40c2eab --- /dev/null +++ b/src/api/guides/teams-tutorial.mdx @@ -0,0 +1,279 @@ +--- +title: "Tutorial: Create and List Teams with the Sentry API" +sidebar_order: 7 +--- + +This guide walks you through the basics of using Sentry's API to list the teams in an organization and create a new team. + +APIs used in this tutorial: + +- [List an Organization's Teams](/api/teams/list-an-organizations-teams/) +- [Create a New Team](/api/teams/create-a-new-team/) + +## Prerequisites + +- A Sentry authentication token with team:write scopes or higher and project:read scopes or higher. + + > If you don't have an authentication token, follow the [Create a Sentry Authentication Token](/api/guides/create-auth-token) tutorial to create an organization auth token with the following permissions, or higher: + > + > - Organization: Read + > - Team: Write + +We recommend using a free [Sentry developer account](https://sentry.io/pricing/) for this tutorial. + +## List an Organization's Teams + +First, you will use the [List an Organization's Teams](/api/teams/list-an-organizations-teams/) API to list all the teams in our organization. + +### Find your organization ID + +The list teams API requires you to pass in the an organization id to list teams for. + +You can find your organization ID in the browser URL of your Sentry instance. For example, https://test-org.sentry.io/. + +### Make the cURL call + +1. Open your terminal. + +1. Save your auth token and organization ID as environment variables for ease of use. Paste the following commands into your terminal, replacing `` with your organization ID and `` with the auth token you copied previously: + + ```bash + export SENTRY_ORG_ID= + export SENTRY_AUTH_TOKEN= + ``` + +1. Paste the following cURL command into your terminal: + + ```bash + curl "https://sentry.io/api/0/organizations/$SENTRY_ORG_ID/teams/?detailed=0" \ + -H 'Authorization: Bearer '$SENTRY_AUTH_TOKEN + ``` + +1. Here's an example of what the output of the command should be, for an organization that has a team called "test-team": + + ```json + [ + { + "id": "4505449964175360", + "slug": "test-team", + "name": "test-team", + "dateCreated": "2023-06-30T18:44:59.196618Z", + "isMember": false, + "teamRole": null, + "flags": { + "idp:provisioned": false + }, + "access": [ + "alerts:read", + "team:read", + "member:read", + "org:read", + "project:releases", + "project:read", + "event:write", + "event:read" + ], + "hasAccess": true, + "isPending": false, + "memberCount": 1, + "avatar": { + "avatarType": "letter_avatar", + "avatarUuid": null + }, + "orgRole": null + } + ] + ``` + + The output gives you details about the teams within the specified organization. + + If your organization has enough teams, the API will return paginated results. See our docs on [Pagination](/api/pagination/) to learn how to handle paginated results. + +1. [Optional] To list information about the projects associated with each team you can set the `detailed` query parameter to `1`: + + ```bash + curl "https://sentry.io/api/0/organizations/$SENTRY_ORG_ID/teams/?detailed=1" \ + -H 'Authorization: Bearer '$SENTRY_AUTH_TOKEN + ``` + + Here's an example of what that output might look like if "test-team" has one associated project named "test-project": + + ```json + [ + { + ... + "orgRole": null, + "externalTeams": [], + "projects": [ + { + "id": "4505506997403648", + "slug": "test-project", + "name": "test-project", + "platform": "javascript-react", + "dateCreated": "2023-07-10T20:29:17.426792Z", + "isBookmarked": false, + "isMember": false, + "features": [ + "alert-filters", + "minidump", + "race-free-group-creation", + "similarity-indexing", + "similarity-view", + "releases" + ], + "firstEvent": "2023-07-10T20:39:35.811000Z", + "firstTransactionEvent": true, + "access": [], + "hasAccess": true, + "hasMinifiedStackTrace": true, + "hasMonitors": false, + "hasProfiles": false, + "hasReplays": true, + "hasSessions": true, + "isInternal": false, + "isPublic": false, + "avatar": { + "avatarType": "letter_avatar", + "avatarUuid": null + }, + "color": "#bf853f", + "status": "active" + } + ] + } + ] + ``` + +## Create a Team + +Now that you know what teams already exist in your org, use the [Create a New Team](/api/teams/create-a-new-team/) API to create another. + +1. Make sure your auth token and organization ID are both still stored as environment variables in your shell. + +1. Paste the following cURL command into your terminal: + + ```bash + curl -d "name=tutorial-team" -X POST "https://sentry.io/api/0/organizations/$SENTRY_ORG_ID/teams/" \ + -H 'Authorization: Bearer '$SENTRY_AUTH_TOKEN + ``` + + The `name` query parameter means the name of the created team should be "tutorial-team". + +1. Here's an example of what the output of the command should be: + + ```json + { + "id": "4505524553711616", + "slug": "tutorial-team", + "name": "tutorial-team", + "dateCreated": "2023-07-13T22:54:05.074990Z", + "isMember": false, + "teamRole": null, + "flags": { + "idp:provisioned": false + }, + "access": [ + "event:write", + "member:read", + "alerts:read", + "project:releases", + "project:read", + "event:read", + "team:read", + "org:read" + ], + "hasAccess": true, + "isPending": false, + "memberCount": 0, + "avatar": { + "avatarType": "letter_avatar", + "avatarUuid": null + }, + "orgRole": null + } + ``` + +1. [Optional] To create a team where the `slug` value is different than the `name` value, you can specify both in your POST call, like so: + + ```bash + curl -d "name=tutorial-team&slug=tutorial-team-slug" -X POST "https://sentry.io/api/0/organizations/$SENTRY_ORG_ID/teams/" \ + -H 'Authorization: Bearer '$SENTRY_AUTH_TOKEN + ``` + +## List an Organization's Teams + +Finally, call the [List an Organization's Teams](/api/teams/list-an-organizations-teams/) API one more time to make sure your new team is returned. + +1. Make sure your auth token and organization ID are both still stored as environment variables in your shell. + +1. Paste the following cURL command into your terminal: + + ```bash + curl "https://sentry.io/api/0/organizations/$SENTRY_ORG_ID/teams/?detailed=0" \ + -H 'Authorization: Bearer '$SENTRY_AUTH_TOKEN + ``` + +1. Your response should contain an entry for your new "tutorial-team" and look something like this: + + ```json + [ + { + "id": "4505524236910592", + "slug": "test-team", + "name": "test-team", + "dateCreated": "2023-07-13T21:33:31.686812Z", + "isMember": false, + "teamRole": null, + "flags": { + "idp:provisioned": false + }, + "access": [ + "member:read", + "alerts:read", + "org:read", + "project:read", + "team:read", + "project:releases", + "event:read", + "event:write" + ], + "hasAccess": true, + "isPending": false, + "memberCount": 1, + "avatar": { + "avatarType": "letter_avatar", + "avatarUuid": null + }, + "orgRole": null + }, + { + "id": "4505524616167424", + "slug": "tutorial-team", + "name": "tutorial-team", + "dateCreated": "2023-07-13T23:09:58.243168Z", + "isMember": false, + "teamRole": null, + "flags": { + "idp:provisioned": false + }, + "access": [ + "member:read", + "alerts:read", + "org:read", + "project:read", + "team:read", + "project:releases", + "event:read", + "event:write" + ], + "hasAccess": true, + "isPending": false, + "memberCount": 0, + "avatar": { + "avatarType": "letter_avatar", + "avatarUuid": null + }, + "orgRole": null + } + ] + ``` diff --git a/src/api/index.mdx b/src/api/index.mdx index 9c4102ab8b8a0..1cc66825f444c 100644 --- a/src/api/index.mdx +++ b/src/api/index.mdx @@ -18,3 +18,5 @@ Sentry's web API is **v0** and under development. Public endpoints, especially t - [Permissions](/api/permissions/) - [Rate Limits](/api/ratelimits) - [Requests](/api/requests/) +- [Tutorial: Create a Sentry Authentication Token](/api/guides/create-auth-token/) +- [Tutorial: Create and List Teams with the Sentry API](/api/guides/teams-tutorial/) diff --git a/src/components/apiSidebar.tsx b/src/components/apiSidebar.tsx index 34a368bcec6c8..e794fb45e702f 100644 --- a/src/components/apiSidebar.tsx +++ b/src/components/apiSidebar.tsx @@ -21,7 +21,10 @@ const query = graphql` export function ApiSidebar() { const data = useStaticQuery(query); const tree = toTree(data.allSitePage.nodes.filter(n => !!n.context)); - const endpoints = tree[0].children.filter(curr => curr.children.length > 1); + const endpoints = tree[0].children.filter( + curr => curr.children.length > 1 && !curr.name.includes('guides') + ); + const guides = tree[0].children.filter(curr => curr.name.includes('guides')); const location = useLocation(); const isActive = path => location && location.pathname.startsWith(path); @@ -32,6 +35,14 @@ export function ApiSidebar() { root="api" title="API Reference" tree={tree} + exclude={endpoints + .map(elem => elem.node.path) + .concat(guides.map(elem => elem.node.path))} + /> + elem.node.path)} />
  • diff --git a/src/gatsby/createPages/createApiGuides.ts b/src/gatsby/createPages/createApiGuides.ts new file mode 100644 index 0000000000000..bec55e093620a --- /dev/null +++ b/src/gatsby/createPages/createApiGuides.ts @@ -0,0 +1,72 @@ +import {GatsbyNode} from 'gatsby'; + +import {getChild, getDataOrPanic} from '../helpers'; + +type CreatePageArgs = Parameters>[0]; + +export const createApiGuides = async ({actions, graphql, reporter}: CreatePageArgs) => { + const data = await getDataOrPanic( + ` + query { + allFile(filter: {absolutePath: {}, relativePath: {in: ["guides/index.mdx", "guides/create-auth-token.mdx", "guides/teams-tutorial.mdx"]}, dir: {regex: "/api/"}}) { + nodes { + id + childMarkdownRemark { + frontmatter { + title + description + draft + noindex + sidebar_order + sidebar_title + redirect_from + keywords + } + fields { + slug + legacy + } + excerpt(pruneLength: 5000) + } + childMdx { + frontmatter { + title + description + draft + noindex + sidebar_order + sidebar_title + redirect_from + keywords + } + fields { + slug + legacy + } + excerpt(pruneLength: 5000) + } + } + } + } + `, + graphql, + reporter + ); + + const component = require.resolve(`../../templates/doc.tsx`); + data.allFile.nodes.forEach((node: any) => { + const child = getChild(node); + if (child && child.fields) { + actions.createPage({ + path: `api${child.fields.slug}`, + component, + context: { + excerpt: child.excerpt, + ...child.frontmatter, + id: node.id, + legacy: child.fields.legacy, + }, + }); + } + }); +}; diff --git a/src/gatsby/createPages/index.ts b/src/gatsby/createPages/index.ts index 57ed6d4f4a9a1..2354149b5a6bf 100644 --- a/src/gatsby/createPages/index.ts +++ b/src/gatsby/createPages/index.ts @@ -1,6 +1,7 @@ import {GatsbyNode} from 'gatsby'; import {createApiDocPages} from './createApiDocPages'; +import {createApiGuides} from './createApiGuides'; import {createApiPages} from './createApiPages'; import {createApiReference} from './createApiReference'; import {createDocPages} from './createDocPages'; @@ -14,6 +15,7 @@ const createPages: GatsbyNode['createPages'] = async params => { createApiPages(params), createApiDocPages(params), createApiReference(params), + createApiGuides(params), ]; if (process.env.NODE_ENV !== 'production') { promises.push(createWizardDebugPages(params));