> For the complete documentation index, see [llms.txt](https://docs.baas.sh/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.baas.sh/baas-console/automations/reference/plugins.md).

# Plugins object

The four methods Function code can call for HTTP requests, email, push notifications, and message signing.

`plugins` is the set of calls a [Function](/baas-console/automations/actions/function.md) can make: HTTP requests, emails, pushes, and signatures with a key from your Vault. It is the third argument, and it exists only in code. Use `plugins` when a call has to be conditional, computed, or repeated. Each call runs inside the function's step, sharing its timeout and its single entry in the run.

To show the calls in context, the method sections extend one example: the `Transfer alerts` automation from the [Monitor](/baas-console/automations/triggers/monitor.md) page, where the [function](/baas-console/automations/actions/function.md) also emails the finance team whenever a transfer is large enough.

## Before you call

The first three methods run through their [Action Plugin](/baas-console/action-plugins.md), which must be active and configured. `vault.signMessage` instead needs a key and a network, picked in the **Key (optional)** field of the [Function action](/baas-console/automations/actions/function.md). If a requirement is missing, the call throws `failed-precondition`.

| Method              | Needs                        |
| ------------------- | ---------------------------- |
| `api.call`          | The API plugin               |
| `email.send`        | The Email plugin             |
| `notification.send` | The Notification plugin      |
| `vault.signMessage` | The action's key and network |

## plugins.api.call

```js
await plugins.api.call({ method, url, headers?, body? })
```

| Parameter | What it takes                                                                                                                                                                 |
| --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `method`  | `GET`, `POST`, `PUT`, `PATCH`, or `DELETE`                                                                                                                                    |
| `url`     | An HTTPS URL                                                                                                                                                                  |
| `headers` | Optional headers, merged over the [plugin defaults](/baas-console/action-plugins.md#api-defaults)                                                                             |
| `body`    | Optional request body, sent with `POST`, `PUT`, and `PATCH`. An object is sent as JSON; a string is sent as is, and must be JSON unless `headers` sets another `content-type` |

Returns `{ status, responseData }`: the HTTP status code and the response body. A non-2xx response throws: `resource-exhausted` for 429; `unavailable` for 408, 500, 502–504 or a timeout; `failed-precondition` for other 4xx responses; `internal` otherwise. In our example, the function could report each large transfer to your backend with a single call.

## plugins.email.send

```js
await plugins.email.send({ to, subject, html, from?, replyTo? })
```

| Parameter         | What it takes                                                             |
| ----------------- | ------------------------------------------------------------------------- |
| `to`              | One or more addresses, separated by commas                                |
| `subject`         | The subject line                                                          |
| `html`            | The message body, as HTML                                                 |
| `from`, `replyTo` | Optional sender addresses; `from` falls back to the Email plugin settings |

Returns `{ messageId, accepted, rejected }`:

| Field                  | What it holds                                                                                                                               |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `messageId`            | The id reported by the SMTP transport, the same value the [Email action](/baas-console/automations/actions/email.md) hands to the next step |
| `accepted`, `rejected` | The recipient addresses, sorted by outcome. Available only here                                                                             |

In our example, the function sends the extra email like this:

```js
async (trigger, context, plugins) => {
  const hash = trigger.event.raw.transactionHash;
  const tokens = Number(trigger.event.args.value.formatted);

  if (tokens > 10000) {
    await plugins.email.send({
      to: "finance@example.com",
      subject: `Large transfer: ${tokens} tokens`,
      html: `<p>Transaction ${hash}</p>`,
    });
  }

  return { shortHash: `${hash.slice(0, 10)}…${hash.slice(-8)}` };
}
```

The email's result goes unused: for a one-way alert, the `await` is enough. The next step receives the `return` value, here the short hash.

## plugins.notification.send

```js
await plugins.notification.send({ tokens, title, body, data? })
```

| Parameter       | What it takes                                   |
| --------------- | ----------------------------------------------- |
| `tokens`        | An array of FCM device tokens                   |
| `title`, `body` | The notification texts                          |
| `data`          | Optional JSON object, passed to your app's code |

Returns `{ userCount, tokenCount }`. `tokenCount` counts the tokens FCM accepted, stale ones excluded; `userCount` stays `0` for a direct token list, as on the [Notification action](/baas-console/automations/actions/notification.md). In our example, a push could replace the email, reusing the same condition with the finance team's device tokens.

## plugins.vault.signMessage

```js
await plugins.vault.signMessage(message)
```

This method takes a plain string, up to 4096 characters, rather than an object. It returns `{ signature }`: the signature of your message, produced by the key and network picked on the action. Vault never picks a key by itself, and signing a message sends no transaction. In our example, the function could sign a receipt of the alert, `"transfer:" + trigger.event.raw.transactionHash`, and hand the signature to the next step for your app to verify.

## Errors

A failed call throws an `HttpsError` carrying a `code` and a `message`. Uncaught, it fails the action, as any `throw` does; catch it when the rest of the run should go on anyway.

| Code                  | When                                                                                                                                  |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `invalid-argument`    | The parameters are malformed                                                                                                          |
| `failed-precondition` | A plugin is inactive, the key is missing, not set up or disabled on the selected network, or an upstream answered a non-transient 4xx |
| `not-found`           | The call targeted something that does not exist                                                                                       |
| `unavailable`         | A transient upstream failure, worth retrying                                                                                          |
| `resource-exhausted`  | A quota was hit, or an upstream answered 429                                                                                          |
| `aborted`             | The call was aborted before it completed                                                                                              |
| `internal`            | Anything else; the details stay server-side                                                                                           |

Your own code can throw one too: `throw new HttpsError("failed-precondition", "...")` fails the action with the code you chose. Any code in the table above works, and `ok` is refused.

## Quotas and the shared timeout

Plugin calls are answered one at a time, in the order the code made them. Starting a batch with `Promise.all` queues them rather than running them in parallel, so their durations add up.

Two caps bound that queue: 256 calls each time the function runs, and 16 unanswered at any moment. A call past either cap comes back as `resource-exhausted` while the function keeps running, so your code can catch it and back off.

Every call draws on the function's single time budget, so watch [`context.getRemainingTimeInMillis()`](/baas-console/automations/reference/context.md#in-function-code) to stay inside it.

{% hint style="info" %}
**Always await.** The function ends when your code returns; a call you didn't await loses its result and isn't guaranteed to run.
{% endhint %}

## Next

* [Function](/baas-console/automations/actions/function.md): the action that runs this code.
* [Action Plugins](/baas-console/action-plugins.md): activate and configure the engines behind the calls.
* [Context object](/baas-console/automations/reference/context.md): the identifiers and the budget your code reads.
