Skip to content
This repository was archived by the owner on Sep 29, 2023. It is now read-only.
Merged
Changes from 48 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
eac7677
Add auth examples to REST page
Nov 2, 2022
5562751
Add multipart file handling
Nov 8, 2022
f37c549
add formdata format
Nov 8, 2022
8d08e41
Add REST API example using fetch
Nov 9, 2022
7c753f8
Let's just use raw HTTP requests as examples
Nov 10, 2022
574adb8
permission magic strings
Nov 11, 2022
341d8d4
Added more magic strings
Nov 11, 2022
bf03417
Added Open API specs
Nov 11, 2022
6219a22
check formatting
Nov 11, 2022
878fd46
Cleaned up empty cells for review
Nov 11, 2022
62dd93d
Fix HTTP formatting
Nov 11, 2022
94b006f
Update app/views/docs/rest.phtml
gewenyu99 Nov 15, 2022
d839c5a
Update app/views/docs/rest.phtml
gewenyu99 Nov 15, 2022
a77bccf
Update app/views/docs/rest.phtml
gewenyu99 Nov 15, 2022
356d1d2
Update app/views/docs/rest.phtml
gewenyu99 Nov 15, 2022
5662348
Fix permission field description
Nov 15, 2022
b87b47a
Adds missing headers and query information
Nov 18, 2022
228277e
Added membership string to REST docs
Nov 21, 2022
be72373
Update app/views/docs/rest.phtml
gewenyu99 Nov 24, 2022
7666746
Update app/views/docs/rest.phtml
gewenyu99 Nov 24, 2022
4f93fea
Update app/views/docs/rest.phtml
gewenyu99 Nov 24, 2022
6d64a04
Update app/views/docs/rest.phtml
gewenyu99 Nov 24, 2022
675cc36
Update app/views/docs/rest.phtml
gewenyu99 Nov 24, 2022
1c43c6b
Update app/views/docs/rest.phtml
gewenyu99 Nov 24, 2022
6bb5629
Addes best practice note and fixes permission string format
Nov 24, 2022
5016a3f
Update app/views/docs/rest.phtml
gewenyu99 Dec 19, 2022
f6b9799
Update app/views/docs/rest.phtml
gewenyu99 Dec 19, 2022
d5d626e
Update app/views/docs/rest.phtml
gewenyu99 Dec 19, 2022
01beb69
Update app/views/docs/rest.phtml
gewenyu99 Dec 19, 2022
005f27e
Update app/views/docs/rest.phtml
gewenyu99 Dec 19, 2022
cd3ea22
Update app/views/docs/rest.phtml
gewenyu99 Dec 19, 2022
d42c4d2
Update app/views/docs/rest.phtml
gewenyu99 Dec 19, 2022
d641d13
Update app/views/docs/rest.phtml
gewenyu99 Dec 19, 2022
d5a522e
Update app/views/docs/rest.phtml
gewenyu99 Dec 19, 2022
0aa41fa
Update app/views/docs/rest.phtml
gewenyu99 Dec 19, 2022
4491d00
Update app/views/docs/rest.phtml
gewenyu99 Dec 19, 2022
1583b8e
Update app/views/docs/rest.phtml
gewenyu99 Dec 19, 2022
bfe5e45
Update app/views/docs/rest.phtml
gewenyu99 Dec 19, 2022
0efe403
Update app/views/docs/rest.phtml
gewenyu99 Dec 19, 2022
e8adca2
Update app/views/docs/rest.phtml
gewenyu99 Dec 19, 2022
8c2d227
Update app/views/docs/rest.phtml
gewenyu99 Dec 19, 2022
220bdb1
Update app/views/docs/rest.phtml
gewenyu99 Dec 19, 2022
cd349da
Test required pill, fix formating suggestions
gewenyu99 Dec 19, 2022
078e023
add cookie examples
Dec 19, 2022
3d64491
Removes unnecessary space in session examples
Dec 19, 2022
f457071
Check status in own column
Dec 19, 2022
10cb24c
updates all requried tags to be pills
Dec 19, 2022
8e81b36
Update app/views/docs/rest.phtml
gewenyu99 Dec 20, 2022
6b2f038
Tag color change, add link to headers
Dec 20, 2022
aa50c66
add JWT to docs
Dec 20, 2022
bbcfe3b
Fixes accound endpoint
Dec 20, 2022
ac49a79
Add link for create endpoints
Dec 20, 2022
adc194d
Ran through grammarly for double checks
Dec 20, 2022
4a0ba0c
Add space in request formatting to fix highlighting issue
Dec 20, 2022
8f343ca
Formatting
abnegate Dec 22, 2022
d4b735b
Remove extra space in request line
abnegate Dec 22, 2022
7f3161d
Remove extra space in request line
abnegate Dec 22, 2022
676b5f9
Truncate cookies
abnegate Dec 22, 2022
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
377 changes: 371 additions & 6 deletions app/views/docs/rest.phtml
Original file line number Diff line number Diff line change
@@ -1,12 +1,377 @@
<p>Appwrite supports multiple protocols for accessing the server, including <a href="/docs/rest">REST</a>, <a href="/docs/graphql">GraphQL</a>, and <a href="/docs/realtime">Realtime</a>.</p>

<p>The REST API allows you to manipulate your Appwrite server through many endpoints, each representing a specific method of modification to a specific resource type.</p>
<p>The REST API allows you to access your Appwrite server through HTTP requests, without the need for an SDK. Each endpoint in the API represents a specific operation on a specific resource.</p>

<p>Requests and responses through the REST API follow a rigid structure - that is, they always expect the same structure for requests to a specific endpoint, and responses from that endpoint will also always have the same structure. </p>
<h2><a href="/docs/rest#headers" id="headers">Headers</a></h2>
<p>Appwrite's REST APIs expect certain headers to be included with each request:</p>

<p>The specific structures used for Appwrite resources and their related endpoints can be found in the <b>References</b> section for each service.</p>
<table class="full text-size-small">
<thead>
<tr>
<td style="width: 300px">Header</td>
<td style="width: 80px"></td>
<td>Description</td>
</tr>
</thead>
<tbody>
<tr>
<td><code>X-Appwrite-Project: [PROJECT-ID]</code></td>
<td><span class="tag red">required</span></td>
<td>Provides the ID of your Appwrite Project to the REST API.</td>
</tr>
<tr>
<td><code>Content-Type: application/json</code></td>
<td><span class="tag red">required</span></td>
<td>Declares content type of the HTTP request.</td>
</tr>
<tr>
<td><code>X-Appwrite-Key: [API-KEY]</code></td>
<td><span class="tag red">optional</span></td>
<td>Used for authentication in server integrations. <b>Do not use API keys in client applications.</b></td>
</tr>
<tr>
<td><code>X-Appwrite-Response-Format: [VERSION-NUMBER]</code></td>
<td><span class="tag red">optional</span></td>
<td>Used for backwards compatibility. The response will be formatted to be compatible the provided version number.</td>
</tr>
<tr>
<td><code>X-Fallback-Cookies: [FALLBACK-COOKIES]</code></td>
<td><span class="tag red">optional</span></td>
<td>Used in scenarios where browsers do not allow third-party cookies. Often used when there is no <a href="/docs/custom-domains">Custom Domain</a>.</td>
</tr>
</tbody>
</table>

<h2><a href="/docs/realtime#authentication" id="authentication">Authentication</a></h2>
<p>The REST API authenticates using Appwrite accounts and sessions. Both accounts and sessions can be created with REST using the <b>POST</b> <b>/v1/account</b>, <b>/v1/account/sessions/email</b>, <b>/v1/account/sessions/anonymous</b>, or <b>/v1/account/sessions/phone</b> endpoints.</p>
<h3><a href="/docs/rest#no-headers" id="no-headers">Using Appwrite Without Headers</a></h3>
<p>Some use cases do not allow the use of custom headers, such as when embedding images from Appwrite in HTML. In these cases, you can provide the Appwrite project ID using the query parameter <code>project</code>.</p>
<div class="ide margin-bottom" data-lang="html" data-lang-label="HTML">
<pre class="line-numbers"><code class="prism language-html" data-prism><?php echo htmlentities('<img src="https://[HOSTNAME_OR_IP]/v1/storage/buckets/[BUCKET_ID]/files/[FILE_ID]/preview?project=[PROJECT_ID]">'); ?></code></pre>
</div>

<p>More information and examples of authenticating users can be found in the dedicated <a href="/docs/authentication">authentication guide</a>.</p>
<h3>Client Authentication</h3>
<p>You can create account sessions with POST requests to the <a href="docs/client/account">Account API</a>. Sessions are persisted using cookies. You can learn more about session persistence in the <a href="/docs/authentication#persistence">Authentication Guide</a>.</p>
<p>The example below shows creating an account session with the <a href="/docs/client/account#accountCreateEmailSession">Create Account Session with Email</a> endpoint.</p>
<div class="ide margin-bottom" data-lang="http" data-lang-label="HTTP">
<pre class="line-numbers"><code class="prism language-http" data-prism>POST /v1/account/sessions/email HTTP/1.1
Host: [HOSTNAME_OR_IP]
Content-Type: application/json
X-Appwrite-Project: 5df5acd0d48c2
X-Appwrite-Response-Format: 1.0.0

{"email":"[email protected]","password":"password"}</code></pre>
</div>

Copy link
Member

Choose a reason for hiding this comment

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

Let's include a response to this request that shows the Set-Cookie header (you can use --dump-header - with curl), and a subsequent request to GET /v1/account that send the cookie value in the Cookie header

<p>The cookies used to persist the session can be found in the response headers.</p>
<div class="ide margin-bottom" data-lang="http" data-lang-label="HTTP">
<pre class="line-numbers"><code class="prism language-http" data-prism>set-cookie: a_session_61e71ec784ab035f7259_legacy=eyJpZCI6IjYzYTBkM2E1MWQ3ZGQ0NzQxOGY3Iiwic2VjcmV0IjoiYmZmN2ExZGIwYmQ3MjcyZGI5Yjg3ZmMwOGY3MzQ3MDZhYmJlYTE1ZGIzN2ViOThlZmRkMmE1OWU4NTNkODRmOGViYTAwY2E4ZjcxYzgzZTUyNDU1OTA3NDhlNTRkMDEwOTcxOTcyNTg1NWNmNDFlODg4MDg3NmI4OTk3NDJkZGFiMGQzODM1MDY0NGJlYzJkYWFiZGUyYjYyY2M1NDIwMTNjYzE0MDFhYjhiYjI2ZDdlM2E1MDgxNGVjMTc4ZDhjNTE4N2YzYzYxNWJhNTBiYWI2MjQxYTRiZjFiODA4ZDhjNGUwMTFhN2NlMzJkODRlYTI4MTU2MDVmYzkxZjg0MSJ9; expires=Tue, 19-Dec-2023 21:26:51 GMT; path=/; domain=.demo.appwrite.io; secure; httponly
set-cookie: a_session_61e71ec784ab035f7259=eyJpZCI6IjYzYTBkM2E1MWQ3ZGQ0NzQxOGY3Iiwic2VjcmV0IjoiYmZmN2ExZGIwYmQ3MjcyZGI5Yjg3ZmMwOGY3MzQ3MDZhYmJlYTE1ZGIzN2ViOThlZmRkMmE1OWU4NTNkODRmOGViYTAwY2E4ZjcxYzgzZTUyNDU1OTA3NDhlNTRkMDEwOTcxOTcyNTg1NWNmNDFlODg4MDg3NmI4OTk3NDJkZGFiMGQzODM1MDY0NGJlYzJkYWFiZGUyYjYyY2M1NDIwMTNjYzE0MDFhYjhiYjI2ZDdlM2E1MDgxNGVjMTc4ZDhjNTE4N2YzYzYxNWJhNTBiYWI2MjQxYTRiZjFiODA4ZDhjNGUwMTFhN2NlMzJkODRlYTI4MTU2MDVmYzkxZjg0MSJ9; expires=Tue, 19-Dec-2023 21:26:51 GMT; path=/; domain=.demo.appwrite.io; secure; httponly; samesite=None</code></pre>
</div>

<p>You will see these cookies included in subsequent requests for authentication.</p>
<div class="ide margin-bottom" data-lang="http" data-lang-label="HTTP">
<pre class="line-numbers"><code class="prism language-http" data-prism>GET /v1/account/ HTTP/1.1
Host: demo.appwrite.io
Cookie: a_session_61e71ec784ab035f7259_legacy=eyJpZCI6IjYzYTBkM2E1MWQ3ZGQ0NzQxOGY3Iiwic2VjcmV0IjoiYmZmN2ExZGIwYmQ3MjcyZGI5Yjg3ZmMwOGY3MzQ3MDZhYmJlYTE1ZGIzN2ViOThlZmRkMmE1OWU4NTNkODRmOGViYTAwY2E4ZjcxYzgzZTUyNDU1OTA3NDhlNTRkMDEwOTcxOTcyNTg1NWNmNDFlODg4MDg3NmI4OTk3NDJkZGFiMGQzODM1MDY0NGJlYzJkYWFiZGUyYjYyY2M1NDIwMTNjYzE0MDFhYjhiYjI2ZDdlM2E1MDgxNGVjMTc4ZDhjNTE4N2YzYzYxNWJhNTBiYWI2MjQxYTRiZjFiODA4ZDhjNGUwMTFhN2NlMzJkODRlYTI4MTU2MDVmYzkxZjg0MSJ9; a_session_61e71ec784ab035f7259=eyJpZCI6IjYzYTBkM2E1MWQ3ZGQ0NzQxOGY3Iiwic2VjcmV0IjoiYmZmN2ExZGIwYmQ3MjcyZGI5Yjg3ZmMwOGY3MzQ3MDZhYmJlYTE1ZGIzN2ViOThlZmRkMmE1OWU4NTNkODRmOGViYTAwY2E4ZjcxYzgzZTUyNDU1OTA3NDhlNTRkMDEwOTcxOTcyNTg1NWNmNDFlODg4MDg3NmI4OTk3NDJkZGFiMGQzODM1MDY0NGJlYzJkYWFiZGUyYjYyY2M1NDIwMTNjYzE0MDFhYjhiYjI2ZDdlM2E1MDgxNGVjMTc4ZDhjNTE4N2YzYzYxNWJhNTBiYWI2MjQxYTRiZjFiODA4ZDhjNGUwMTFhN2NlMzJkODRlYTI4MTU2MDVmYzkxZjg0MSJ9
Content-Type: application/json
X-Appwrite-Project: 5df5acd0d48c2
X-Appwrite-Response-Format: 1.0.0</code></pre>
</div>

<h2>Server Authentication</h2>
<p>Server integrations use API keys to authenticate and are typically used for backend applications.</p>
<p>Server APIs are authenticated with API keys instead of account sessions. Simply pass an <a href="/docs/keys">API key</a> in the <code>X-Appwrite-key: [API-KEY]</code> header with the appropriate scopes.</p>

<div class="ide margin-bottom" data-lang="http" data-lang-label="HTTP">
<pre class="line-numbers"><code class="prism language-http" data-prism>GET /v1/databases/{databaseId}/collections/{collectionId}/documents HTTP/1.1
Host: [HOSTNAME_OR_IP]
Content-Type: application/json
X-Appwrite-Project: [PROJECT_ID]
X-Appwrite-Key: [API_KEY]
X-Appwrite-Response-Format: 1.0.0</code></pre>
</div>

<h2>File Handling</h2>
<p>Appwrite implements resumable, chunked uploads for files larger than 5MB. Chunked uploads send files in chunks of 5MB to reduce memory footprint and increase resilience when handling large files. Appwrite SDKs will automatically handle chunked uploads but it is possible to implement this with the REST API directly.</p>

<p>Upload endpoints in Appwrite such as Create File and Create Deployment are different from other endpoints. These endpoints take multipart form data instead of JSON data. To implement chunked uploads, you will need to implement the following headers:</p>

<table class="full text-size-small">
<thead>
<tr>
<td style="width: 280px">Header</td>
<td style="width: 80px"></td>
<td>Description</td>
</tr>
</thead>
<tbody>
<tr>
<td><code>X-Appwrite-Project: [PROJECT-ID]</code></td>
<td><span class="tag red">required</span></td>
<td>Contains the ID of your Appwrite Project to the REST API.</td>
</tr>
<tr>
<td><code>Content-Type: multipart/form-data; boundary=[FORM-BOUNDRY]</code></td>
<td><span class="tag red">required</span></td>
<td>Contains the content type of the HTTP request and provides a <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST">boundry</a> which is used to parse the form data.</td>
</tr>
<tr>
<td><code>Content-Range: bytes [BYTE-RANGE]</code></td>
<td><span class="tag red">required</span></td>
<td>Contains information about which bytes are being transmitted in this chunk, with the format <code>[FIRST-BYTE]-[LAST-BYTE]/[TOTAL-BYTES]</code>.</td>
</tr>
<tr>
<td><code>X-Appwrite-ID: [FILE-ID]</code></td>
<td><span class="tag red">required</span></td>
<td>Contains ID of the file this chunk belongs to.</td>
</tr>
<tr>
<td><code>X-Appwrite-Key: [API-KEY]</code></td>
<td><span class="tag red">optional</span></td>
<td>Used for authentication in server integrations. <b>Do not use API keys in client applications.</b></td>
</tr>
</tbody>
</table>

<p>The multipart form data is structured as follows:</p>

<table class="full text-size-small">
<thead>
<tr>
<td style="width: 100px">Key</td>
<td style="width: 80px"></td>
<td style="width: 150px">Value</td>
<td style="width: 100px">File Name</td>
<td>Description</td>
</tr>
</thead>
<tbody>
<tr>
<td>fileId</td>
<td><span class="tag red">optional</span></td>
<td><code>[FILE-ID]</code></td>
<td>n/a</td>
<td>Contains the file ID of the new file. Only used by file chunks following the first chunk uploaded.</td>
</tr>
<tr>
<td>file</td>
<td><span class="tag red">required</span></td>
<td><code>[CHUNK-DATA]</code></td>
<td><code>[FILE-NAME]</code></td>
<td>Contains file chunk data.</td>
</tr>
<tr>
<td>permissions</td>
<td><span class="tag red">required</span></td>
<td><code>[PERMISSION ARRAY]</code></td>
<td>n/a</td>
<td>Contains an array of permission strings about who can access the new file.</td>
</tr>
</tbody>
</table>

<p>While cURL and fetch are great tools to explore other REST endpoints, it's impractical to use for chunked file uploads because you need to split files into chunks.</p>

<p>The multipart form data posted to file upload endpoints has the following format:</p>

<div class="ide margin-bottom" data-lang="http" data-lang-label="HTTP">
<pre class="line-numbers"><code class="prism language-http" data-prism>POST /v1/storage/buckets/default/files HTTP/1.1
Host: [HOSTNAME_OR_IP]
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarye0m6iNBQNHlzTpVM
X-Appwrite-Project: demo-project
Content-Range: bytes 10485760-12582912/12582912
X-Appwrite-ID: 6369b0bc1dcf4ff59051

------WebKitFormBoundarye0m6iNBQNHlzTpVM
Content-Disposition: form-data; name="fileId"

unique()
------WebKitFormBoundarye0m6iNBQNHlzTpVM
Content-Disposition: form-data; name="file"; filename="file.txt"
Content-Type: application/octet-stream

[CHUNKED-DATA]
------WebKitFormBoundarye0m6iNBQNHlzTpVM
Content-Disposition: form-data; name="permissions[]"

read("user:627a958ded6424a98a9f")
------WebKitFormBoundarye0m6iNBQNHlzTpVM--</code></pre>
</div>

<h2>Permissions</h2>

<p>Appwrite SDKs have helpers to generate permission strings, but when using Appwrite without SDKs, you'd need to create the strings yourself.</p>

<h3>Permission Types</h3>

<table class="full text-size-small">
<thead>
<tr>
<td style="width: 250px">SDK</td>
<td>Permission String</td>
</tr>
</thead>
<tbody>
<tr>
<td><code>Permission.read()</code></td>
<td><code>read("[PERMISSION_ROLE]")</code></td>
</tr>
<tr>
<td><code>Permission.create()</code></td>
<td><code>create("[PERMISSION_ROLE]")</code></td>
</tr>
<tr>
<td><code>Permission.update()</code></td>
<td><code>update("[PERMISSION_ROLE]")</code></td>
</tr>
<tr>
<td><code>Permission.delete()</td>
<td><code>delete("[PERMISSION_ROLE]")</code></td>
</tr>
<tr>
<td><code>Permission.write()</td>
<td><code>write("[PERMISSION_ROLE]")</code></td>
</tr>
</tbody>
</table>

<h3>Permission Roles</h3>

<table class="full text-size-small">
<thead>
<tr>
<td style="width: 250px">SDK</td>
<td>Role String</td>
</tr>
</thead>
<tbody>
<tr>
<td><code>Role.any()</code></td>
<td><code>any</code></td>
</tr>
<tr>
<td><code>Role.guests()</code></td>
<td><code>guests</code></td>
</tr>
<tr>
<td><code>Role.users()</code></td>
<td><code>users</code></td>
</tr>
<tr>
<td><code>Role.users([STATUS])</code></td>
<td><code>users/[STATUS]</code></td>
</tr>
<tr>
<td><code>Role.user([USER_ID])</td>
<td><code>user:[USER_ID]</code></td>
</tr>
<tr>
<td><code>Role.user([USER_ID], [STATUS])</td>
<td><code>user:[USER_ID]/[STATUS]</code></td>
</tr>
<tr>
<td><code>Role.team([TEAM_ID])</td>
<td><code>team:[TEAM_ID]</code></td>
</tr>
<tr>
<td><code>Role.team([TEAM_ID], [ROLE])</td>
<td><code>team:[TEAM_ID]/[ROLE]</code></td>
</tr>
<tr>
<td><code>Role.member([MEMBERSHIP_ID])</td>
<td><code>member:[MEMBERSHIP_ID]</code></td>
</tr>
</tbody>
</table>

<ul>
<li class="margin-bottom"><a href="/docs/permissions" rel="noopener"><i class="icon-angle-circled-right margin-start-negative-tiny margin-end-tiny"></i> Learn more about permissions</a></li>
</ul>

<h2>Unique ID</h2>
<p>
Appwrite's SDKs have a helper <code>ID.unqiue()</code> to generate unique IDs. When using Appwrite without an SDK, pass the string <code>"unique()"</code> into the ID parameter.
</p>

<h2>Query Methods</h2>
<p>
Appwrite's SDKs provides a <code>Query</code> class to generate query strings. When using Appwrite without an SDK, you can template your own strings with the format below.
</p>

<p>Query strings are passed to Appwrite using the <code>queries</code> parameter. You can attach multiple query strings by including the array parameter multiple times in the query string: <code>queries[]="..."&queries[]="..."</code></p>

<table cellspacing="0" cellpadding="0" border="0" class="full margin-bottom-large">
<thead>
<tr>
<th style="width: 150px">Query Method</th>
<th>Query String</th>
</tr>
</thead>
<tbody>
<tr>
<td>equal</td>
<td><code>equal("attribute", [value])</code></td>
</tr>
<tr>
<td>notEqual</td>
<td><code>notEqual("attribute", [value])</code></td>
</tr>
<tr>
<td>lessThan</td>
<td><code>lessThan("attribute", [value])</code></td>
</tr>
<tr>
<td>lessThanEqual</td>
<td><code>lessThanEqual("attribute", [value])</code></td>
</tr>
<tr>
<td>greaterThan</td>
<td><code>greaterThan("attribute", [value])</code></td>
</tr>
<tr>
<td>greaterThanEqual</td>
<td><code>greaterThanEqual("attribute", [value])</code></td>
</tr>
<tr>
<td>search</td>
<td><code>search("attribute", [value1])</code></td>
</tr>
<tr>
<td>orderDesc</td>
<td><code>orderDesc("attribute")</code></td>
</tr>
<tr>
<td>orderAsc</td>
<td><code>orderAsc("attribute")</code></td>
</tr>
<tr>
<td>cursorAfter</td>
<td><code>cursorAfter("documentId")</code></td>
</tr>
<tr>
<td>cursorBefore</td>
<td><code>cursorBefore("documentId")</code></td>
</tr>
<tr>
<td>limit</td>
<td><code>limit(0)</code></td>
</tr>
<tr>
<td>offset</td>
<td><code>offset(0)</code></td>
</tr>
</tbody>
</table>

<div class="notice margin-bottom">
<h3>Best Practice</h3>
<p>When using greater than, greater than or equal to, less than, or less than or equal to, it is not recommended to pass in multiple values. While the API will accept multiple values and return results with <b>or logic</b>, it's best practice to pass in only one value for performance reasons.</p>
</div>


<h2>OpenAPI and Swagger Specs</h2>
<p>
Appwrite provides a full REST API specification in the OpenAPI 3 and Swagger 2 formats every release. These can be accessed through Appwrite's GitHub repository and rendered using a variety of parsers and tools.
</p>
<ul>
<li class="margin-bottom"><a href="https://github.com/appwrite/appwrite/tree/master/app/config/specs" target="_blank" rel="noopener"><i class="icon-angle-circled-right margin-start-negative-tiny margin-end-tiny"></i> Find the REST API specification for your Appwrite version</a></li>
</ul>