# react-native-appwrite: the Appwrite SDK for React Native apps

> The official Appwrite client for React Native, published as react-native-appwrite and installed through Expo. It wraps the Appwrite REST API in typed services, and it is pinned to Appwrite server 2.2.x, which is the constraint that decides whether you can use it.

**appwrite/sdk-for-react-native** — [READ ONLY] Official Appwrite React Native SDK 💙 ⚛︎

- Repository: https://github.com/appwrite/sdk-for-react-native
- Website: https://appwrite.io
- Stars: 4,253 · Forks: 36
- Language: TypeScript
- License: BSD-3-Clause
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/appwrite-sdk-for-react-native

## What react-native-appwrite is for

Appwrite is a backend server that exposes accounts, databases, storage and other services over REST. The React Native SDK is the client half of that pair: it turns those endpoints into JavaScript methods you can call from a phone app. The package on npm is named react-native-appwrite, not appwrite, which matters because the web SDK and this one are separate artifacts with separate release histories.

The audience is narrow and specific. You are building a React Native app, you have an Appwrite project, and you want registration, sessions and document reads without writing your own HTTP layer. The README's first example is exactly that: create a Client, point it at an endpoint and a project ID, then call account.create. If your backend is not Appwrite, nothing here applies to you.

The README also notes the SDK is auto-generated by Appwrite's SDK Generator, and the repository carries a matching note in its description calling it read only. Practically, that means the source layout in src/ is generated output rather than hand-authored code, and pull requests that change method signatures are unlikely to be reviewed as normal library patches.

## The version pin that decides everything

The README states plainly that the SDK targets Appwrite server version 2.2.x as shipped on Appwrite Cloud, and adds that self-hosted releases can lag behind Cloud. It then tells you what to do about it: if you run an older self-hosted build, use a matching older SDK from previous releases when APIs differ.

This is the single most consequential fact about the package. Appwrite Cloud and self-hosted Appwrite are the same software on different release cadences, and a client built against 2.2.x can call endpoints a 2.1.x server does not have. The failure is not a compile error. It is a runtime AppwriteException from a server that does not recognise the route.

The release history backs the cadence claim. Version 1.0.0 landed on 2026-09-21, 0.35.0 on 2026-09-07, and 0.34.0 on 2026-07-13. The jump from 0.35.0 to 1.0.0 is a stability signal for the API surface, but it does not loosen the server-side pin. If you self-host, check your server version before you pick an SDK version, not after.

## Installing react-native-appwrite and making a first request

The README gives one install command, and it goes through Expo. There is no plain npm install line in the README, and the package declares expo and react-native in its peer dependencies, so an Expo project is the supported path.

```bash
npx expo install react-native-appwrite react-native-url-polyfill
```

That pulls in two packages: the SDK itself and a URL polyfill. The polyfill is not optional. The setup section says to import it in index.js before anything else runs, because React Native's URL implementation is not complete enough for the SDK's request handling.

```js
import 'react-native-url-polyfill/auto'
```

If you build for iOS, the README adds a pod step: cd ios && pod install && cd ...

Next, initialise the client. The endpoint and project ID come from your Appwrite project settings page, and setPlatform takes your application ID or bundle ID.

```js
import { Client, Account } from 'react-native-appwrite';

const client = new Client();

client
    .setEndpoint('http://localhost/v1')
    .setProject('455x34dfkj')
    .setPlatform('com.example.myappwriteapp');

const account = new Account(client);
```

The README's first real call registers a user. Note that the example passes ID.unique() for the user ID, so the server generates it.

```js
account.create(ID.unique(), 'me@example.com', 'password', 'Jane Doe')
    .then(function (response) {
        console.log(response);
    }, function (error) {
        console.log(error);
    });
```

Before any of this works you have to register the app as a platform in the Appwrite console. The README walks through both cases: for iOS, add the app name and Bundle ID, found in the General tab of your primary target in Xcode, or in app.json for Expo projects. For Android, add the app name and package name, generally the applicationId in your app-level build.gradle, or again app.json for Expo. Skipping this step is the most common reason a first request fails.

## Typed documents and the appwrite types command

The feature that separates this SDK from a thin REST wrapper is generic typing on database methods. listDocuments, getDocument and others accept a type parameter, so the documents array is typed as your model rather than a generic map.

```typescript
interface Book {
    name: string;
    author: string;
    releaseYear?: string;
    isCheckedOut: boolean;
}

const databases = new Databases(client);
const documents = await databases.listDocuments<Book>(
    'your-database-id',
    'your-collection-id'
);
```

The README also shows the JavaScript equivalent using a JSDoc typedef and a Models.DocumentList<Book> annotation, which gives IDE hints without a TypeScript build step. Both paths are documented, so this is not a TypeScript-only library.

One caveat the README itself raises: the generic parameter is a promise you make to the compiler, not something the SDK verifies at runtime. If your interface drifts from the collection schema, the types will not catch it. To close that gap, the README points at the appwrite types command, which generates TypeScript interfaces from your Appwrite database schema. That is the honest workflow: generate the interfaces, then pass them as the generic argument rather than hand-writing them.

## Where it breaks: errors, versions and platform setup

Errors surface as an AppwriteException carrying message, code and response properties. The README's error-handling example catches the exception and prints error.message. That is fine for a console, and thin for a production screen. The SDK does not classify errors for you, so mapping code values to user-facing text is your job, and the README does not enumerate them.

The version pin is the second failure mode, and it is the one that bites self-hosters. Because the SDK ships in lockstep with Appwrite Cloud releases, a self-hosted instance a few minor versions behind will reject calls the SDK is happy to make. The README's answer is to downgrade the SDK, which means reading the releases page and matching versions by hand.

Platform configuration is the third. setPlatform takes a bundle ID or Android package name that must match what you registered in the console. A mismatch produces an auth-style rejection that looks like a credentials problem but is not.

Finally, this is the wrong tool if you are not on Appwrite. There is no adapter layer here for Supabase, Firebase or a custom backend. The SDK is a client for one server.

## How it compares with supabase-js in React Native

The closest alternative for the same job is supabase-js, which also targets React Native and also wraps a hosted backend. The difference is in what the client is allowed to do.

Supabase leans on Postgres row-level security: the client holds an anon key, queries tables directly, and the database enforces who can read which row. Appwrite puts the policy in the server's collections and permissions, and the SDK calls named service methods like listDocuments against a collection ID rather than composing queries against tables. If you want SQL-shaped access with policies expressed as database rules, supabase-js is the better fit. If you would rather call a method per operation and keep policy out of the client's query text, this SDK matches that model.

The typing story differs too. supabase-js generates types from your Postgres schema through its CLI. This SDK offers generics plus the appwrite types command. Both push you toward generating types rather than writing them, which is the right instinct either way.

A second option is writing fetch calls against the Appwrite REST API yourself. That removes the dependency and the version pin, at the cost of reimplementing request signing, the URL polyfill handling and the exception shape.

## Licence and the cost of keeping it current

The package is BSD-3-Clause, and the LICENSE file sits at the repository root. That is a permissive licence: you can ship it inside a closed-source app, and the main obligation is retaining the copyright notice and licence text in distributions of the source. This is not legal advice; read the LICENSE file for the actual terms.

Upgrade cost is the part worth budgeting for. The SDK is generated, so a new server release can produce a new SDK release with changed method signatures rather than deprecation shims. The README's own guidance for self-hosted users is to pick a matching older SDK when APIs differ, which is a manual process each time you move either side. If you are on Appwrite Cloud, the server moves for you and the SDK should follow; if you self-host, pin the SDK version in package.json and move it deliberately alongside the server, not ahead of it.

## Conclusion

Adopt it if your app already talks to Appwrite Cloud or a self-hosted server on the 2.2.x line and you want typed database calls instead of hand-written fetch wrappers. Do not adopt it if you need the SDK to work against an older self-hosted Appwrite, or if you are not using Expo: the README installs it with npx expo install and the package declares expo as a peer dependency. Before writing app code, confirm your server version in the Appwrite console and add the platform entry (bundle ID or Android package name) that setPlatform expects, because a mismatch there fails before any request leaves the device.

## FAQ

### How do I install the Appwrite SDK for React Native?

The README gives a single command: npx expo install react-native-appwrite react-native-url-polyfill. You then import 'react-native-url-polyfill/auto' in index.js, and on iOS run pod install in the ios directory.

### Which Appwrite server version does react-native-appwrite target?

The README states the SDK targets Appwrite server version 2.2.x as shipped on Appwrite Cloud, and warns that self-hosted releases can lag behind. For an older self-hosted build it directs you to a matching older SDK from previous releases.

### Does react-native-appwrite support TypeScript types for database documents?

Yes. Methods like listDocuments and getDocument accept a generic type parameter, so you can pass your own model interface and get typed documents back. There is also a JavaScript path using a JSDoc typedef and a Models.DocumentList annotation.

### How do I generate TypeScript interfaces from my Appwrite database schema?

The README points at the appwrite types command, which generates TypeScript interfaces based on your Appwrite database schema, and links to the type generation documentation for details.

### What does react-native-appwrite raise when a request fails?

It raises an AppwriteException object with message, code and response properties. The README's example catches the error and logs error.message.

## Sources

- [appwrite/sdk-for-react-native on GitHub](https://github.com/appwrite/sdk-for-react-native)
- [License: BSD-3-Clause](https://github.com/appwrite/sdk-for-react-native/blob/main/LICENSE)
- [Project website](https://appwrite.io)
- [README](https://github.com/appwrite/sdk-for-react-native/blob/main/README.md)
- [Releases](https://github.com/appwrite/sdk-for-react-native/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/appwrite-sdk-for-react-native
