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

# Keeping keys secret

> Where a key never shows up, and the one place it does.

An API key or signing secret never leaves a client except on the wire.

> [card] Never in an error
>
> No message, stack, property or cause holds a key.

> [card] Never in a log
>
> Response hooks and log lines get no header, query or body.

> [card] Never in a dump
>
> Inspecting, printing or serializing a client shows no key.

> [card] Never to another site
>
> Redirects are never followed, so a key never reaches another origin.

Keys stay out of exceptions and their traces, dumps, exports, JSON, log context, and the
`ResponseReceived` / `ConnectionFailed` events Telescope reads (which carry no signature either, nor a
write's bodies). Read one with `$key->token()` / `$key->signingSecret()` when you must.

**1. Queue the slug, never the client**

`serialize()` of anything holding a key refuses, so a `Site` or a client can't land in a queued
job, a cache or a session.

**2. Resolve it in the job**

```php theme={"dark"}
public function handle(): void
{
    Attract::site($this->slug)->blogPosts()->importBlogPost(markdown: $this->markdown);
}
```

> [!NOTE]
>
> Guzzle's debug output is refused: it would print every header, the key among them. Watch calls through
> `log_channel`, Telescope or `Attract::fake()`.

> [!WARNING]
>
> **One place does see the key.** Laravel's `RequestSending` event, `Http::fake()` callbacks and
> `Http::recorded()` get the request as sent, `Authorization` included. A listener or test must never
> log their headers.

> [card] [Next: Agent Skills](https://docs.fetchski-attract.com/agent-skills.md)
>
> The Agent Skill each SDK ships, installed with one command.


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