Develop Appwrite Functions

Appwrite Functions offer a familiar interface if you've developed REST endpoints. Each function is handled following a request and response pattern.

Lifecycle

There is a clear lifecycle for all Appwrite Functions, from beginning to end. Here's everything that happens during a function execution.

  1. The function is invoked.

  2. The active deployment's executor will handle the request.

  3. The Executor passes in request information like headers, body or path through the context.req object of your exported function.

  4. The runtime executes the code you defined, you can log through the context.log() or context.error() methods.

  5. Function terminates when you return results using return context.res.text(), return context.res.json() or similar.

Locally developed functions follow the same lifecycle on your local machine.

Entrypoint

You'll find all of these steps in a simple function like this. Notice the exported entry point that the executor will call.

If you prefer to learn through more examples like this, explore the examples page.

Context object

Context is an object passed into every function to handle communication to both the end users, and logging to the Appwrite Console. All input, output, and logging must be handled through the context object passed in.

You'll find these properties in the context object.

PropertyDescription
reqContains request information like method, body, and headers. See full examples in the request section.
resContains methods to build a response and return information. See full examples in the response section.
log()Method to log information to the Appwrite Console, end users will not be able to see these logs. See full examples in the logging section.
error()Method to log errors to the Appwrite Console, end users will not be able to see these errors. See full examples in the logging section.
Depreciation notice

Use req.bodyText instead of req.bodyRaw. Use res.text instead of res.send. Use req.bodyText or req.bodyJson instead of req.body depending on the expected input data type.

Destructuring assignment

Some languages, namely JavaScript, support destructuring. You'll see us use destructuring in examples, which has the following syntax.

Learn more about destructuring assignment.

Request

If you pass data into an Appwrite Function, it'll be found in the request object. This includes all invocation inputs from Appwrite SDKs, HTTP calls, Appwrite events, or browsers visiting the configured domain. Explore the request object with the following function, which logs all request params to the Appwrite Console.

Request types

RequestDescription
req.bodyTextReturns text that has been converted from binary data.
req.bodyJsonParses the body text as JSON.
req.bodyBinaryReturns the binary body.

Headers

Appwrite Functions will always receive a set of headers that provide meta data about the function execution. These are provided alongside any custom headers sent to the function.

VariableDescription
x-appwrite-triggerDescribes how the function execution was invoked. Possible values are http, schedule or event.
x-appwrite-eventIf the function execution was triggered by an event, describes the triggering event.
x-appwrite-keyThe dynamic API key is used for server authentication. Learn more about dynamic api keys.
x-appwrite-user-idIf the function execution was invoked by an authenticated user, display the user ID. This doesn't apply to Appwrite Console users or API keys.
x-appwrite-user-jwtJWT token generated from the invoking user's session. Used to authenticate Server SDKs to respect access permissions. Learn more about JWT tokens.
x-appwrite-country-codeDisplays the country code of the configured locale.
x-appwrite-continent-codeDisplays the continent code of the configured locale.
x-appwrite-continent-euDescribes if the configured local is within the EU.

Response

Use the response object to send a response to the function caller. This could be a user, client app, or an integration. The response information will not be logged to the Appwrite Console. There are several possible ways to send a response, explore them in the following Appwrite Function.

Response types

ResponseDescription
emptySends a response with a code 204 No Content status.
jsonConverts the data into a JSON string and sets the content-type header to application/json.
binaryPackages binary bytes, the status code, and the headers into an object.
redirectRedirects the client to the specified URL link.
textConverts the body using UTF-8 encoding into a binary Buffer.

To get the different response types, set one of the following query parameters in the generated domain of your function.

TypeQuery ParamExample
text/?type=texthttps://64d4d22db370ae41a32e.appwrite.global/?type=text
json/?type=jsonhttps://64d4d22db370ae41a32e.appwrite.global/?type=json
redirect/?type=redirecthttps://64d4d22db370ae41a32e.appwrite.global/?type=redirect
html/?type=htmlhttps://64d4d22db370ae41a32e.appwrite.global/?type=html
empty/https://64d4d22db370ae41a32e.appwrite.global/

Logging

To protect user privacy, the request and response objects are not logged to the Appwrite Console by default.

We support the spread operator across most of the languages, meaning you can write code that is more concise and flexible.

This means, to see logs or debug function executions you need to use the log() and error() methods. These logs are only visible to developers with access to the Appwrite Console.

Here's an example of using logs and errors.

You can access these logs through the following steps.

  1. In Appwrite Console, navigate to Functions.

  2. Click to open a function you wish to inspect.

  3. Under the Executions tab, click on an execution.

  4. In the Response section, you'll be able to view logs under the Logs and Errors tabs.

Accessing environment variables

If you need to pass constants or secrets to Appwrite Functions, you can use environment variables.

VariableDescriptionAvailable at Build and/or Run Time
APPWRITE_FUNCTION_API_ENDPOINTThe API endpoint of the running functionBoth
APPWRITE_VERSIONThe Appwrite version used to run the functionBoth
APPWRITE_REGIONThe region where the function will run fromBoth
APPWRITE_FUNCTION_API_KEYThe function API key is used for server authenticationBuild time
APPWRITE_FUNCTION_IDThe ID of the running function.Both
APPWRITE_FUNCTION_NAMEThe Name of the running function.Both
APPWRITE_FUNCTION_DEPLOYMENTThe deployment ID of the running function.Both
APPWRITE_FUNCTION_PROJECT_IDThe project ID of the running function.Both
APPWRITE_FUNCTION_RUNTIME_NAMEThe runtime of the running function.Both
APPWRITE_FUNCTION_RUNTIME_VERSIONThe runtime version of the running function.Both

Learn to add variables to you function

You can access the environment variables through the systems library of each language.

Dependencies

To install your dependencies before your function is built, you should add the relevant install command to the top your function's Build setting > Commands. You can find this setting under Functions > your function > Settings > Configuration > Build settings.

Make sure to include dependency files like package.json, composer.json, requirements.txt, etc. in your function's configured root directory. Do not include the dependency folders like node_modules, vendor, etc. in your function's root directory. The dependencies installed for your local OS may not work in the executor environments

Your function's dependencies should be managed by the package manager of each language. By default, we include the following package managers in each runtime.

 LanguagePackage ManagerCommands
Node.js logo Node.js logoNode.jsNPMnpm install
PHP logo PHP logoPHPComposercomposer install
Python logo Python logoPythonpippip install -r requirements.txt
Ruby logo Ruby logoRubyBundlerbundle install
Deno logo Deno logoDenodenodeno cache <ENTRYPOINT_FILE>
Go logo Go logoGoGo ModulesN/A
Dart logo Dart logoDartpubpub get
Swift logo Swift logoSwiftSwift Package Managerswift package resolve
.NET logo .NET logo.NETNuGetdotnet restore
Bun logo Bun logoBunbunbun install
Kotlin logo Kotlin logoKotlinGradleN/A
Java logo Java logoJavaGradleN/A
C++ logo C++ logoC++NoneN/A

Using Appwrite in a function

Appwrite can be used in your functions by adding the relevant SDK to your function's dependencies. Authenticating with Appwrite is done via a dynamic API key or a JWT token.

Dynamic API key

Dynamic API keys are the same as API keys but are automatically generated. They are generated in your functions per execution. However, you can only use dynamic API keys inside Appwrite functions.

During the build process, dynamic API keys are automatically provided as the environment variable APPWRITE_FUNCTION_API_KEY. This environment variable doesn't need to be initialized.

During execution, dynamic API keys are automatically provided in the x-appwrite-key header.

Dynamic API keys grant access and operate without sessions. They allow your function to act as an admin-type role instead of acting on behalf of a user. Update the function settings to configure the scopes of the function.

  1. In Appwrite Console, navigate to Functions.

  2. Click to open a function you wish to configure.

  3. Under the Settings tab, navigate to Scopes.

  4. Select the scopes you want to grant the dynamic key.

  5. It is best practice to allow only necessary permissions.

Using with JWT

JWTs allow you to act on behalf of an user in your Appwrite Function. When using JWTs, you will be able to access and change only the resources with the same permissions as the user account that signed the JWT. This preserves the permissions you configured on each resource.

If the Appwrite Function is invoked by an authenticated user, the x-appwrite-user-jwt header is automatically passed in.

Code structure

As your functions grow, you may find yourself needing to split your code into multiple files. This helps you keep your codebase maintainable and easy to read. Here's how you can accomplish code splitting.