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

# Secrets and outbound HTTPS

> Store app-specific credentials and call approved public HTTPS hosts.

Managed secrets and egress let an app call an API that does not have a Marina
connection. Use a [connection](/connections/overview) for a shared, governed
provider integration. Use secrets and egress for an app-specific API.

Declare every secret name the app may read and every host it may call in
`marina.json`:

```json marina.json theme={null}
{
  "schema": 1,
  "entrypoint": "src/worker.ts",
  "runtime": { "secrets": ["PAYMENTS_API_KEY"] },
  "egress": { "hosts": ["api.payments.example"] }
}
```

## Store a secret

Set or rotate a value without putting it in source code or a deployment
archive:

```bash theme={null}
printf %s "$PAYMENTS_API_KEY" | marina secrets set PAYMENTS_API_KEY --app my-tool
```

You can also read the exact bytes from a file:

```bash theme={null}
marina secrets set PAYMENTS_API_KEY --file /path/to/value --app my-tool
```

List names and update times, or delete a value:

```bash theme={null}
marina secrets --app my-tool
marina secrets delete PAYMENTS_API_KEY --app my-tool
```

Marina encrypts values in its credential vault. List operations never return
them. A deployed version can read only the names declared by that version.
Rotating a value takes effect immediately and does not require a redeploy.

## Read a secret at runtime

Use `marina.secrets.get(name)` inside the app handler. It returns `null` when
the declared value has not been configured.

```ts theme={null}
import { defineApp } from "@marina/runtime";

export default defineApp({
  async fetch(_request, marina) {
    const key = await marina.secrets.get("PAYMENTS_API_KEY");
    if (!key) return new Response("Secret not configured", { status: 503 });

    const upstream = await fetch("https://api.payments.example/status", {
      headers: { Authorization: `Bearer ${key}` },
    });
    return new Response(upstream.body, { status: upstream.status });
  },
});
```

During `marina dev`, the same call reads the managed value when the directory
is linked to an app, the signed-in developer has edit access, and the live
version declares that secret name.

## Allow outbound hosts

App code uses the standard Web `fetch()` API. Marina applies the published
version's `egress.hosts` policy to every outbound call.

| Configuration | Result |
| - | - |
| Omitted or `[]` | Deny all outbound requests. |
| `["api.example.com"]` | Allow that host and its subdomains. |
| `["api.example.com", "uploads.example.net"]` | Allow each listed host and its subdomains. |
| `["*"]` | Allow any public HTTPS destination. |

You can list up to 32 hostnames. The wildcard must be the only entry when
used. Policies allow HTTPS only. Private addresses, local networks, and Marina
internal endpoints remain blocked, including when an allowed server redirects
to one. Redirect responses are returned to app code so it can decide whether
to follow them.

## Review egress logs

Each outbound attempt writes an audit entry to the app's runtime logs. This
includes allowed requests, blocked requests, upstream failures, and redirects.
The entry contains the destination hostname, HTTP method, status, and outcome.
It excludes URL paths, queries, headers, request and response bodies, and
secret values.

Marina durably records an intent before sending a permitted request, then
replaces the pending customer-log entry with the response status and outcome.
If the audit service cannot accept the intent, the request does not reach the
network. If only the completion event fails after an upstream action, the
intent remains visible and the app receives the upstream response, avoiding
an accidental retry of a successful mutation.

```bash theme={null}
marina logs --app my-tool
```

New secret names and newly allowed hosts appear as effects when a version is
proposed, so a workspace publisher can review the expanded access before the
version becomes live.


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