Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .optimize-cache.json
Original file line number Diff line number Diff line change
Expand Up @@ -1594,6 +1594,42 @@
"static/images/docs/network/edges-map.png": "12ecc1ea200905ba75eb7cfd17055a156fd51fccf746869a1058f923dfd7ac1b",
"static/images/docs/network/pops-map.png": "205ead599703cf47d0df316db8fcc4f48d5eed01508109fc740d17914275e9ab",
"static/images/docs/network/regions-map.png": "c65f1423ab19c3048bf8bf93117e8f2e1d13a2bc705c00307de7ee821e5668a1",
"static/images/docs/partners/apps/account-applications.png": "85b60bff922db940aafe30a3eb5c1646d66a30f6d7894df2f0c14c65bd79d7e6",
"static/images/docs/partners/apps/consent-screen.png": "5c6875f7d9af0180d0c5859bac2c57bb620a2243aac72530ca122a40f3758b50",
"static/images/docs/partners/apps/dark/account-applications.png": "03389413091ae6530ebb592d9aade7248b0b8b1a34e4a1b90c3f48480bf01ae3",
"static/images/docs/partners/apps/dark/consent-screen.png": "cfb1385940b821a39a90e2c2010d6a9d86b7d02373adb564e78711088acd092c",
"static/images/docs/partners/apps/dark/device-code.png": "e84f23cfcd904cf5fa5aef2642738fb6ce2289135c8f7d74c5b85d36b3da127c",
"static/images/docs/partners/apps/dark/diagram-consent.png": "cdf260c28c98ebebe8e553eb8600dece94989d160bece85c1fee63e9cf21de21",
"static/images/docs/partners/apps/dark/diagram-device.png": "208a3dc343bfd1c4ea16d64b6b19e8efec363855231b0eaf467de1397bc29a64",
"static/images/docs/partners/apps/dark/diagram-overview.png": "1fd06d30fc53efa69157f3c6be62c991610acdc7c97463e58341310d6fc0ebe5",
"static/images/docs/partners/apps/dark/diagram-registration.png": "66abebb561a61bc51923f42c6f85ec63a4de4ce57901f74072fa3efb50277f30",
"static/images/docs/partners/apps/dark/diagram-scopes.png": "ee95a74b1ab45607c4ab72f8522ecc624471f81b74139cf5288066e3c8fe9c2f",
"static/images/docs/partners/apps/dark/diagram-tokens.png": "99c1951b4640fba1d7e116ef0dd75ed5c171f843f6ff312bc16f2b0f08e2239f",
"static/images/docs/partners/apps/dark/quick-start-consent.png": "7b5c60b821ea7d3cc037ba77f97e858429c6a63a99b453ac063fbe9628e458c5",
"static/images/docs/partners/apps/dark/quick-start-provider-setup.png": "55a2bd989f7d7237d17d2bdae78d5d1cce8adadd01e6c155ff1c766cb26a1fb2",
"static/images/docs/partners/apps/dark/registration-general.png": "790e305253b5371db9997c07234a9f464fb8b1f2529206f4b737ddca4a1729a5",
"static/images/docs/partners/apps/dark/registration-legal.png": "aa1e4180df13f90e2d2797b2166bb401d05c7d90307bf9553f6fe06c0ecf00cf",
"static/images/docs/partners/apps/dark/registration-marketplace.png": "e7af87266c488d7627d5334f9b4264afbbbcdf26f61e3cef1d44685e19008948",
"static/images/docs/partners/apps/dark/registration-oauth-client.png": "5cedae65dc096c51c644b7a8946525171a62398b20ffa593db86b6ad4aef7972",
"static/images/docs/partners/apps/dark/registration-publish.png": "e50dd334c7df7d926821ee37c07762e0fea196fd3da8a5bf6ff7b92d21b8b09f",
"static/images/docs/partners/apps/dark/registration-secrets.png": "fb81e51364c7ff4267fcc985b9556e697b5541b16b7520e9b5780b1cb3477dc2",
"static/images/docs/partners/apps/dark/registration-support.png": "f2d54e58b11f638401b0f4888dc5f404816dac86584af3fa571f6c045e7b3053",
"static/images/docs/partners/apps/device-code.png": "1afe19a6a183e2a0da2a4777db710d2b88e28e3dc51d0fedaed3dbcee1b29580",
"static/images/docs/partners/apps/diagram-consent.png": "3ba2989ce6f09ea5c3a0e49665d005c6f6b2fb1b92b624c2c2c30460649f96ae",
"static/images/docs/partners/apps/diagram-device.png": "f620b3b450ca3b34fc9326cb1b4bd9fc7066e4c912b229c211e1ef30ff77010d",
"static/images/docs/partners/apps/diagram-overview.png": "81932121776e4ac7af3a93fe4cfdd93a44aa8c4dbc739bfc08a56c92665bb612",
"static/images/docs/partners/apps/diagram-registration.png": "46b85ba2d4bbcb932c6b15d338586542d67346d981f204d36aa3e4f5bdd6debb",
"static/images/docs/partners/apps/diagram-scopes.png": "cc01f8f049ce13956c0311f3192c41ce964f89819e016e61deb29475ca5a600c",
"static/images/docs/partners/apps/diagram-tokens.png": "c1f169da1c3c4abb51936a117d41dba5a71c721c508a1a91bc6cd8cf0b25149b",
"static/images/docs/partners/apps/quick-start-consent.png": "43ceef1d6e6a1f4b73ae0150508909f7af903332dc2817ba168fef361b185e57",
"static/images/docs/partners/apps/quick-start-provider-setup.png": "1c3dce9dc68df86c0744d86cfa0e2bcb2185fdc52f5fe22138ab8d21b1f571f2",
"static/images/docs/partners/apps/registration-general.png": "78b66e81d64fcb3bc421ac8ae923f03753ee730996c56e16fe3d4aeedac591c2",
"static/images/docs/partners/apps/registration-legal.png": "7d11e03dbf12709c2a349accd813e86315e85cc1fbf74d7e4c69f69ede48d39f",
"static/images/docs/partners/apps/registration-marketplace.png": "0b9aa3fb30a5c8dc0fa857c177f6bc714c490933c395c14957c56d27f099ccc3",
"static/images/docs/partners/apps/registration-oauth-client.png": "bf6d7c6afb0d8f75371ca261386c06a3f0a8e1942a1cec2fb910a296c2f707fb",
Comment thread
greptile-apps[bot] marked this conversation as resolved.
"static/images/docs/partners/apps/registration-publish.png": "734184fab22320d2c473d25ee8218ee6ebaed5971787d1e1930057d0135cad8c",
"static/images/docs/partners/apps/registration-secrets.png": "92e6ecff867e92d64aa6ceea0b67a711b7e1d715c9f3f99dc4df10e663a68aa0",
"static/images/docs/partners/apps/registration-support.png": "da585bd47fa71c9277a8f98a2b561c9fd31bc99a11a9169367a82bd3e744f8ae",
"static/images/docs/platform/add-platform.png": "5a05bb9d75a8d5270bfa5e67df7e6de20a9fad174476a112b5bdab72e7bdad30",
"static/images/docs/platform/create-api-key.png": "7661b3845e13704643f8ff4f763faa8e61efb90878c3ffa7466ece0910b8ecab",
"static/images/docs/platform/create-webhook.png": "77e08173da6ac534524e025433cf75e532d853a135944a7c6ba2278357d88b2d",
Expand Down
7 changes: 7 additions & 0 deletions src/routes/docs/Sidebar.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,13 @@
icon: 'icon-briefcase',
isParent: true,
new: isNewUntil('22 Aug 2026')
},
{
label: 'Apps',
href: '/docs/partners/apps',
icon: 'icon-key',
isParent: true,
new: isNewUntil('31 Aug 2026')
}
]
},
Expand Down
55 changes: 55 additions & 0 deletions src/routes/docs/partners/apps/+layout.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<script lang="ts">
import Docs from '$lib/layouts/Docs.svelte';
import Sidebar, { type NavParent, type NavTree } from '$lib/layouts/Sidebar.svelte';

const parent: NavParent = {
href: '/docs',
label: 'Apps'
};

const navigation: NavTree = [
{
label: 'Getting started',
items: [
{
label: 'Overview',
href: '/docs/partners/apps'
},
{
label: 'Quick start',
href: '/docs/partners/apps/quick-start'
}
]
},
{
label: 'Concepts',
items: [
{
label: 'Registration',
href: '/docs/partners/apps/registration'
},
{
label: 'Scopes',
href: '/docs/partners/apps/scopes'
},
{
label: 'Consent',
href: '/docs/partners/apps/consent'
},
{
label: 'Tokens',
href: '/docs/partners/apps/tokens'
},
{
label: 'Device flow',
href: '/docs/partners/apps/device-flow'
}
]
}
];
</script>

<Docs variant="two-side-navs">
<Sidebar {navigation} {parent} />
<slot />
</Docs>
79 changes: 79 additions & 0 deletions src/routes/docs/partners/apps/+page.markdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
---
layout: article
title: Sign in with Appwrite
description: Build apps that access your users' Appwrite projects and organizations with consent-based, scoped OAuth2 tokens instead of pasted API keys.
back: /docs
---

Appwrite is an **OAuth 2.1 and OpenID Connect provider**. Your app can send any Appwrite user to a consent screen, ask for access to the projects and organizations they choose, and receive tokens that call their project APIs directly. This is **Sign in with Appwrite**: the same consent flow users know from "Sign in with Google", pointed at their Appwrite account and backend.

Before this, a tool that worked with a user's Appwrite project asked them to create an API key and paste it in. The key carried whatever scopes and expiry the user picked at creation, worked for one project only, and lived outside their control once pasted. With Sign in with Appwrite, the user approves once, picks the projects your app can reach, and can revoke everything from their account page at any time.

{% info title="Building your own provider?" %}
This section is for apps that build on top of Appwrite itself. To make your own product an OAuth2 provider so that third parties can offer "Sign in with your product", see the [OAuth2 server](/docs/products/auth/oauth-server) documentation.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Provider Link 404s

This callout still links to /docs/products/auth/oauth-server, but that route is not present in the tree. A reader looking for provider-side OAuth docs from this new overview page lands on a 404 unless a separate docs change deploys first. Please point this to a route that ships here, or keep the link out until the target page exists.

Knowledge Base Used: Docs section routing and layout

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/routes/docs/partners/apps/+page.markdoc
Line: 13

Comment:
**Provider Link 404s**

This callout still links to `/docs/products/auth/oauth-server`, but that route is not present in the tree. A reader looking for provider-side OAuth docs from this new overview page lands on a 404 unless a separate docs change deploys first. Please point this to a route that ships here, or keep the link out until the target page exists.

**Knowledge Base Used:** [Docs section routing and layout](https://app.greptile.com/appwrite/-/custom-context/knowledge-base/appwrite/website/-/docs/docs-section.md)

How can I resolve this? If you propose a fix, please make it concise.

Fix in Claude Code Fix in Codex

{% /info %}

# What you can build {% #what-you-can-build %}

Your app authenticates the user once and then acts on their Appwrite resources with the scopes they granted.

- **Dashboards and monitors** that read usage, logs, and data across the projects a user selects.
- **Deployment tools** that push functions and sites into a customer's project without holding a key.
- **CLIs and devices** that sign in with a short user code instead of a browser redirect.
- **AI agents and MCP clients** that operate under scopes the user can narrow to read-only.

# How it works {% #how-it-works %}

{% only_dark %}
![Your app sends the user through the Appwrite consent screen and calls their projects with the issued tokens](/images/docs/partners/apps/dark/diagram-overview.avif)
{% /only_dark %}
{% only_light %}
![Your app sends the user through the Appwrite consent screen and calls their projects with the issued tokens](/images/docs/partners/apps/diagram-overview.avif)
{% /only_light %}

Sign in with Appwrite is the authorization code flow from OAuth 2.1, served by Appwrite.

1. **Your app redirects the user** to the Appwrite authorization endpoint with the scopes it needs.
2. **Appwrite shows the consent screen.** The user sees your app's name and logo, reviews the requested permissions, and picks which projects and organizations they apply to. They can grant fewer projects than you asked for, or decline entirely.
3. **Your app receives an authorization code** at its redirect URI and exchanges it for an access token, a refresh token, and an ID token.
4. **Your app calls Appwrite APIs** with the access token as a bearer token, on any of the granted projects, in any region.

Because the provider is spec-compliant, any OAuth2 or OIDC library works against the discovery document without Appwrite-specific code:

```text
https://cloud.appwrite.io/v1/oauth2/console/.well-known/openid-configuration
```

Users stay in control after the redirect too. Every authorization appears on their account's applications page, where they see the scopes your app holds and the tokens issued under it, and can revoke a token family or the whole authorization at any time.

# Explore {% #explore %}

{% cards %}
{% cards_item href="/docs/partners/apps/quick-start" title="Quick start" %}
Register an app and run the full flow, from consent to your first authorized API call.
{% /cards_item %}
{% cards_item href="/docs/partners/apps/registration" title="Registration" %}
Register your app in the Console and shape its consent screen listing.
{% /cards_item %}
{% cards_item href="/docs/partners/apps/scopes" title="Scopes" %}
The scope catalog and how grants target specific projects and organizations.
{% /cards_item %}
{% cards_item href="/docs/partners/apps/consent" title="Consent" %}
What users see, what they can change, and what your app receives.
{% /cards_item %}
{% cards_item href="/docs/partners/apps/tokens" title="Tokens" %}
Use, refresh, and revoke the tokens Appwrite issues to your app.
{% /cards_item %}
{% cards_item href="/docs/partners/apps/dashboards" title="Dashboards" %}
Build a read-only dashboard over the projects a user selects.
{% /cards_item %}
{% cards_item href="/docs/partners/apps/deployments" title="Deployments" %}
Deploy functions and sites into a user's project with write scopes.
{% /cards_item %}
{% cards_item href="/docs/partners/apps/device-flow" title="Device flow" %}
Sign in from CLIs and devices with a short user code.
{% /cards_item %}
{% cards_item href="/docs/partners/apps/agents" title="Agents" %}
Comment on lines +67 to +76

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Forward Cards Still 404

The device-flow card now has a route, but the dashboards, deployments, and agents cards still point to pages that are not present under src/routes/docs/partners/apps. A reader who clicks any of these Explore cards from the new landing page reaches a docs 404. Please add those pages with this PR or remove these cards until the routes exist.

Knowledge Base Used: Docs section routing and layout

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/routes/docs/partners/apps/+page.markdoc
Line: 67-76

Comment:
**Forward Cards Still 404**

The `device-flow` card now has a route, but the `dashboards`, `deployments`, and `agents` cards still point to pages that are not present under `src/routes/docs/partners/apps`. A reader who clicks any of these Explore cards from the new landing page reaches a docs 404. Please add those pages with this PR or remove these cards until the routes exist.

**Knowledge Base Used:** [Docs section routing and layout](https://app.greptile.com/appwrite/-/custom-context/knowledge-base/appwrite/website/-/docs/docs-section.md)

How can I resolve this? If you propose a fix, please make it concise.

Fix in Claude Code Fix in Codex

Connect AI agents and MCP clients to your users' projects.
Comment on lines +67 to +77

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Forward Cards Hit Missing Routes

When this Overview page is deployed before the follow-up pages, the Dashboards, Deployments, Device flow, and Agents cards send readers to routes that are not in this change. Those prominent links become 404s from the new docs landing page.

Knowledge Base Used:

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/routes/docs/partners/apps/+page.markdoc
Line: 60-70

Comment:
**Forward Cards Hit Missing Routes**

When this Overview page is deployed before the follow-up pages, the Dashboards, Deployments, Device flow, and Agents cards send readers to routes that are not in this change. Those prominent links become 404s from the new docs landing page.

**Knowledge Base Used:**
- [Docs section routing and layout](https://app.greptile.com/appwrite/-/custom-context/knowledge-base/appwrite/website/-/docs/docs-section.md)
- [Markdoc content pipeline](https://app.greptile.com/appwrite/-/custom-context/knowledge-base/appwrite/website/-/docs/markdoc-content-pipeline.md)

How can I resolve this? If you propose a fix, please make it concise.

Fix in Claude Code Fix in Codex

{% /cards_item %}
{% /cards %}
67 changes: 67 additions & 0 deletions src/routes/docs/partners/apps/consent/+page.markdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
---
layout: article
title: Consent
description: What users see on the Sign in with Appwrite consent screen, what they can change, and what your app receives.
back: /docs/partners/apps
---

{% only_dark %}
![The consent screen turns your request into a granted token response or an access_denied redirect](/images/docs/partners/apps/dark/diagram-consent.avif)
{% /only_dark %}
{% only_light %}
![The consent screen turns your request into a granted token response or an access_denied redirect](/images/docs/partners/apps/diagram-consent.avif)
{% /only_light %}

Consent is where the user decides. Appwrite hosts the screen, renders what your app asked for, and gives the user the final say over scopes and targets. Your app never sees the screen; it sees the outcome.

# The consent screen {% #consent-screen %}

{% only_dark %}
![Consent screen showing app identity, requested permissions, and project selection](/images/docs/partners/apps/dark/consent-screen.avif)
{% /only_dark %}
{% only_light %}
![Consent screen showing app identity, requested permissions, and project selection](/images/docs/partners/apps/consent-screen.avif)
{% /only_light %}

The screen is built from your [registration](/docs/partners/apps/registration) and your request:

- **Your app's identity**: the name, logo, and tagline you registered.
- **Permissions**: each requested scope as a plain-language line, under a one-line summary of the overall reach.
- **Project access**: a picker for the projects or organizations the grant covers when the request carries project or organization scopes.

The user signs in first if no session exists, and can switch accounts from the screen itself.

# Users can grant less {% #partial-grants %}

What you request is not always what you get. On the consent screen, the user can:

- Deselect projects or organizations, shrinking where the grant applies.
- Decline the whole request.

The permission list itself is not editable. Scopes are granted as you requested them or not at all, which is another reason to request the smallest set that serves your app.

The token response tells you what you got: `scope` holds the granted scopes, `authorization_details` the granted projects. Build for this from the start. A dashboard that asked for five projects but got two should show two projects, not an error.

# When the screen is skipped {% #consent-reuse %}

Appwrite remembers approvals. When a returning user's request asks for nothing new, they skip the screen and land straight back in your app. When anything differs from the stored approval, the screen reappears. Send the same authorization parameters on every sign-in and returning users sign in silently.

Two `prompt` values override this:

- `prompt=consent` always shows the screen, even when an approval exists.
- `prompt=none` never shows it, returning `error=consent_required` or `error=login_required` instead. Use it to check for existing access silently.

# Revocation {% #revocation %}

{% only_dark %}
![Account applications page listing authorized apps with their token families](/images/docs/partners/apps/dark/account-applications.avif)
{% /only_dark %}
{% only_light %}
![Account applications page listing authorized apps with their token families](/images/docs/partners/apps/account-applications.avif)
{% /only_light %}

Every approval appears on the user's account applications page. From there, the user revokes a single token or the whole app, which kills every token your app holds for them.

Your app gets no notification. Calls and refreshes start returning `401`, and the fix is to send the user through authorization again.

Revocation goes both ways: when a user disconnects your app on your side, revoke the tokens you hold at the [revocation endpoint](/docs/partners/apps/tokens#revocation).
Loading
Loading