> ## Documentation Index
> Fetch the complete documentation index at: https://docs.asteroid.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Secrets & 2FA

> How Asteroid stores secrets, attaches them to login profiles, and injects them without exposing the value.

Secrets live in your organization, on the **Secrets** tab of the **Logins** page. A
[login profile](/concepts/profiles) attaches the secrets it needs. A workflow that runs with that
profile can then fill usernames, passwords, API keys, cards, and two-factor codes without the real
values ever reaching the model.

Create and edit them there. Attach them in the profile's **Secrets** section. The API calls a secret a vault item.

Asteroid encrypts every value at rest, and decrypts it only at the moment a workflow uses it. List
and get responses are masked. They never include write-only values. See
[Security](/support-security/security).

## Secrets

A secret is a named bundle of fields. It has an editable UPPER\_SNAKE key. Many secrets in an
organization may share a key. A profile cannot attach two secrets with the same key. The key stays
the same when you rename the secret, so scripts keep working. Omit `itemKey` on create and the server
derives it from the name. Related fields belong on one secret:

| Kind | Typical fields |
| :- | :- |
| Username and password | Username or email, password, TOTP seed, portal URL |
| API key | A token or key the workflow sends to an API |
| Payment card | Card number, expiry, CVV, cardholder name |
| Custom | Any other secret, with fields you define |

One secret can attach to many profiles. A profile can attach many secrets. Give two username and
password secrets the same key when one script should fill the same portal for different profiles.

## Placeholders

Each field has a placeholder of the form `##ITEM_KEY.FIELD##`.

The prefix is the secret's key. Key `AVAILITY_LOGIN` and field key `USERNAME` give
`##AVAILITY_LOGIN.USERNAME##`.

Reference the placeholder in node instructions or a browser automation script. The runtime replaces
it with the real value at the tool boundary, so the value never passes through the model. In a
script, the runtime fills the decrypted value into the script run only, for a browser input or
`asteroid.generateTotp`. It never injects it into shell or file tools. This is separate from the `args` a scripted node receives, which come from the node's
declared inputs. See [Nodes](/concepts/nodes).

```javascript theme={null}
await page.fill('#username', '##AVAILITY_LOGIN.USERNAME##');
await page.fill('#password', '##AVAILITY_LOGIN.PASSWORD##');
```

<Warning>
  Never paste a real secret into instructions or scripts as plain text. Use a secret placeholder.
</Warning>

In instructions, prefer intent over naming the token ("sign in with the credentials available to
you"). The runtime tells the workflow which placeholders exist. Name one only when several secrets
are attached.

On the API, MCP server, and SDKs:

1. Create the secret (`POST /secrets`, or MCP `vaultItemsCreate`).
2. Attach it to the profile (`vaultItemIds` on `POST`/`PATCH /profiles`, or MCP `agentProfileUpdate`).

To collect a secret from someone else, send a request from the **Requests** tab. The recipient fills
it in on a hosted page, or on your own page. See [Collect secrets in your own app](/integrate/collect-credentials).

The profile fields `credentials`, `credentialsToAdd`, `credentialsToUpdate`, and
`credentialsToDelete` are deprecated. They still work. Prefer secrets (`vaultItemIds`).

## Two-factor codes

A username and password secret can hold a TOTP seed, so the workflow generates its own authenticator codes. Asteroid
supports every standard TOTP provider, including Google Authenticator, Microsoft Authenticator,
Authy and 1Password.

<Steps>
  <Step title="Get the TOTP secret key">
    Ask the target service for the manual setup key rather than the QR code. Most sites offer it behind a
    **Can't scan it?**, **manual entry** or **setup key** link.

    The key is a Base32 string of 16–32 characters.
  </Step>

  <Step title="Store it on a secret">
    Add a TOTP seed field to the username and password secret for that portal. Paste the key as the value.

    Do not type the seed placeholder into an authenticator field. The field holds a seed, not a code.
    The workflow uses the Generate TOTP skill to produce a code, then types that code.
  </Step>

  <Step title="Reference it">
    The workflow generates a code from the seed when the site asks for 2FA. A node script generates it
    with `asteroid.generateTotp('##MY_PORTAL.TOTP_SEED##')`. See
    [Two-factor codes](/concepts/scripting-runtime#two-factor-codes).
  </Step>
</Steps>

Codes expire on the target service's period, 30 seconds by default. Some services use a different
period, so tell the workflow to generate a code immediately before it submits.

For codes that arrive by email instead, see [Workflow emails](/concepts/emails).

<Tip>
  Some 2FA setups are more complex than a standard TOTP secret. [Get in touch](https://asteroid.ai/demo) and
  we can help you set it up.
</Tip>

See [Profiles](/concepts/profiles) for how to attach secrets to a profile.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.