Matrix Application Service Framework
matrix-appservice is a Node.js framework designed to facilitate the creation of Matrix application services. It provides a web framework agnostic way to quickly set up performant services that can interact with a Matrix homeserver. The current stable version is 4.0.1, released in April 2026. The project maintains a roughly annual major release cadence, primarily driven by updates to Node.js version support and occasional API adjustments. It differentiates itself from more fully-featured SDKs like `matrix-appservice-bridge` by offering a more minimalist, flexible foundation for building application services, focusing on core communication patterns rather than higher-level bridging abstractions.
Common errors
-
TypeError: AppServiceRegistration is not a constructor
cause Attempting to use `require('matrix-appservice')` as a default import for `AppServiceRegistration` or trying to instantiate it directly when it's a named export, particularly in an ESM context.fixIf using CommonJS, ensure you destructure it: `const { AppServiceRegistration } = require('matrix-appservice');`. If using ES Modules, use `import { AppServiceRegistration } from 'matrix-appservice';`. -
Error: listen EADDRINUSE: address already in use :::8010
cause Another process is already using the port that the application service is trying to bind to (e.g., another instance of the app service, or a different web server).fixEnsure only one instance of the application service is running. If necessary, change the port it listens on in `as.listen(port)` and update the `appServiceUrl` in your `registration.yaml` accordingly. -
Error: Your Node.js version is 22.x, but matrix-appservice requires >=24.
cause The installed Node.js runtime version does not meet the minimum requirement specified by the `matrix-appservice` package.fixUpgrade your Node.js installation to a version that satisfies the `engines.node` requirement in the `matrix-appservice` package's `package.json` (currently `>=24` for v4.0.1). Use a Node.js version manager like `nvm` or `volta` to easily switch versions. -
Error: Homeserver did not return a valid response to transaction <transaction_id>
cause This often occurs when the application service is not properly configured with the homeserver (e.g., `registration.yaml` is incorrect, `url` is wrong, or `homeserver_token` doesn't match).fixVerify that your `registration.yaml` file is correctly uploaded to the homeserver and that its `url` and `as_token` match the `appServiceUrl` and `appServiceToken` you configured in your `AppService` instance. Check homeserver logs for more specific errors related to the app service.
Warnings
- breaking Node.js version support frequently changes between major versions. Always check the release notes for the exact Node.js requirements. For instance, v4.0.0 dropped support for Node 22 and added support for Node 25. v3.0.0 dropped Node 18 & 20, adding 22 & 24. v2.0.0 dropped Node 16, adding 20. v1.0.0 dropped Node 12, adding 18. Running on an unsupported Node.js version will result in errors.
- breaking The legacy `/users`, `/rooms`, and `/transactions` endpoints were removed in v2.0.0 and now redirect to the appropriate spec-compliant paths. Direct calls to these legacy paths will no longer function as expected and will be redirected internally.
- gotcha The documentation and examples may mix CommonJS `require()` and ES Modules `import` syntax. While both might technically work depending on your project's configuration, using named `import` statements for all classes (`AppService`, `AppServiceRegistration`, `AppserviceHttpError`) is the recommended modern approach since the library ships TypeScript types and primarily targets ESM environments for recent Node.js versions.
- gotcha To enable HTTPS listening for your application service, you must define the `MATRIX_AS_TLS_KEY` and `MATRIX_AS_TLS_CERT` environment variables. These variables should point to the absolute or relative paths of your TLS key and certificate files, respectively. If these are not set, the application service will default to HTTP.
- gotcha Error handling for `onUserQuery` and `onAliasQuery` methods should use `AppserviceHttpError` to return specific HTTP statuses and Matrix error codes. Simply throwing a generic `Error` or returning nothing will result in a default 500 Internal Server Error without a custom Matrix error code.
Install
-
npm install matrix-appservice -
yarn add matrix-appservice -
pnpm add matrix-appservice
Imports
- AppService
const { AppService } = require('matrix-appservice')import { AppService } from 'matrix-appservice' - AppServiceRegistration
const AppServiceRegistration = require('matrix-appservice')import { AppServiceRegistration } from 'matrix-appservice' - AppserviceHttpError
import AppserviceHttpError from 'matrix-appservice'
import { AppserviceHttpError } from 'matrix-appservice'
Quickstart
import { AppService, AppServiceRegistration, AppserviceHttpError } from 'matrix-appservice';
import * as fs from 'node:fs';
// Step 1: Generate an app service registration file (only needed once)
const reg = new AppServiceRegistration();
reg.setAppServiceUrl('http://localhost:8010');
reg.setHomeserverToken(AppServiceRegistration.generateToken());
reg.setAppServiceToken(AppServiceRegistration.generateToken());
reg.setSenderLocalpart('example-appservice');
reg.addRegexPattern('users', '@example-.*', true);
reg.addRegexPattern('aliases', '#example_.*', true);
reg.setProtocols(['exampleservice']); // For 3PID lookups
reg.setId('example-service');
const registrationFilePath = 'registration.yaml';
reg.outputAsYaml(registrationFilePath);
console.log(`Generated registration file: ${registrationFilePath}`);
// Step 2: Run the app service
const as = new AppService({
homeserverToken: process.env.HOMESERVER_TOKEN ?? 'your_homeserver_token_here',
appServiceToken: process.env.APPSERVICE_TOKEN ?? 'your_appservice_token_here'
});
as.on('type:m.room.message', (event) => {
console.log(`Received message from ${event.sender}: ${event.content.body}`);
// Handle the incoming message
});
as.onUserQuery = async function(userId) {
console.log(`Received user query for: ${userId}`);
// Example: Validate or create the user
if (userId.startsWith('@baduser-')) {
throw new AppserviceHttpError(
{
errcode: 'M_FORBIDDEN',
error: 'User query or creation failed for this user ID.'
},
403
);
}
console.log(`User ${userId} can be created or queried.`);
// In a real app, you would provision the user on the AS side here.
};
as.onAliasQuery = async function(alias) {
console.log(`Received alias query for: ${alias}`);
// Handle the incoming alias query then respond
};
const port = 8010;
as.listen(port);
console.log(`Matrix Application Service listening on port ${port}`);
console.log('Ensure your homeserver is configured with registration.yaml');
// Optional: Set up TLS if environment variables are present
if (process.env.MATRIX_AS_TLS_KEY && process.env.MATRIX_AS_TLS_CERT) {
console.log('TLS keys found, AppService will attempt to listen with HTTPS.');
// AppService.listen handles HTTPS automatically if these env vars are set
}