---
title: "Calling the API from backend JavaScript"
description: "Call the API from the JavaScript of a backend module with the session of the backend user: read, change and handle errors."
canonical: javascript.html
navigation-title: "JavaScript"
---

<a id="usage-javascript"></a>

<a id="calling-the-api-from-backend-javascript"></a>

# Calling the API from backend JavaScript

The JavaScript of a backend module can call the API with the module
`@typo3/core/action/request`. You need no app and no token of your own: the
request uses the session of the logged-in backend user, so the permissions of
this user apply. The action must have the target `Target::backend`, see
[Targets](../developer/targets.md#developer-targets). The record and file actions have this target.

The module is for the TYPO3 backend only. An external application uses the HTTP
API with a token, see [Authentication](authentication.md#usage-authentication).

1. **Import the function**
   Import `action` in an ES module of your extension. Register the
   module in `Configuration/JavaScriptModules.php` of your extension,
   as for all backend JavaScript.

   ```javascript
   import { action } from '@typo3/core/action/request.js';
   ```
2. **Read data**
   The first argument is the path of the action with its version, without
   `/typo3/api`. The function adds this prefix. The second argument gives
   the values of the placeholders in the path, for example `{uid}`.
   `resolve()` returns the result as JSON.

   ```javascript
   const request = action('/v1/records/{schema}/{identifier}', {
       schema: 'pages',
       identifier: '3',
   });
   const response = await request.get();
   const { record } = await response.resolve();
   ```

   To send query parameters, use `withQueryArguments()`:

   ```javascript
   const request = action('/v1/records/{schema}', {
       schema: 'pages',
   });
   const response = await request
       .withQueryArguments({ limit: 10 })
       .get();
   const { items, next } = await response.resolve();
   ```
3. **Change data**
   `action()` returns an `AjaxRequest` of TYPO3. It has the methods
   `get()`, `post()`, `put()`, `patch()` and
   `delete()`. For a JSON body, set the header `Content-Type`:

   ```javascript
   await action('/v1/records/{schema}/{identifier}', {
       schema: 'pages',
       identifier: '3',
   }).patch(
       { record: { _schema: 'pages', title: 'New title' } },
       { headers: { 'Content-Type': 'application/json' } },
   );
   ```
4. **Handle errors**
   If the status is not 2xx, the request throws the response. The
   body is problem details with the content type
   `application/problem+json`, so call `resolve('json')`. See
   [Responses and errors](responses.md#usage-responses).

   ```javascript
   try {
       await action('/v1/records/{schema}/{identifier}', {
           schema: 'pages',
           identifier: '999999',
       }).get();
   } catch (response) {
       const problem = await response.resolve('json');
       console.error(response.raw().status, problem.detail);
       // 404 Record not found
   }
   ```

> [!NOTE]
> The session cookie alone is not enough. The module also sends a bearer
> token, which the backend adds to its document for the logged-in user. The
> token must belong to the user of the session. This prevents that other
> websites call actions in the name of a logged-in backend user.
