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

# Overview

> Manage API keys and OAuth for your project.

Credentials let Keystroke actions safely call external services like Linear, Gmail, HubSpot, Slack, and more.

An **app** is the service you connect. A **credential** is one connected account or secret for that app. Actions declare the credentials they need, and Keystroke resolves the right organization, project, or user credential when the action runs.

## Example requests

Ask your coding agent which service you want to use. It can wire up the app, credential, and actions that need it.

> "Connect our HubSpot account so our SDR agent can read and update deals."

> "Set up Slack so the team can message the data analyst agent and schedule regular reports."

> "Read the Pylon documentation, create a custom API integration, and add actions that match the endpoints our support agent needs."

## Apps vs credentials

An **app** is a service Keystroke can connect to: Granola, Google Workspace, Slack, Salesforce, Snowflake, and the rest of the integration catalog.

A **credential** is one connected account for that app: an API key, OAuth connection, or managed connection instance. A single app can have several credentials, for example one organization-wide Hubspot connection and a project-level Hubspot connection with additional Hubspot permissions.

| Term                    | What it means                                                                       |
| ----------------------- | ----------------------------------------------------------------------------------- |
| **App**                 | A connectable external service shown in the Apps page and integration catalog       |
| **Credential**          | One connected account or secret for an app                                          |
| **Credential instance** | The stored credential record at an organization, project, or user scope             |
| **Gateway app**         | A messaging surface, like Slack, for messaging agents directly in third-party tools |
| **MCP server**          | A third-party's MCP server that you attach to an agent with `defineMcp()`           |

<Note>
  "Integration" is synonymous with "app". An **app** is the user-facing thing you connect, and **credential** is the runtime binding your code consumes.
</Note>

## Connect apps and credentials

Keystroke supports several connection paths, depending on what you're building.

| Connection type           | Use it for                                                                          | How it works                                                                                                               |
| ------------------------- | ----------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| **Built-in OAuth apps**   | Apps like Google Workspace, GitHub, Gong, Snowflake, and other catalog integrations | Keystroke creates a managed app credential. In the hosted cloud, most of these run through Keystroke's platform MCP layer. |
| **Built-in API key apps** | Apps that need a static secret, such as Exa                                         | Store an API key credential with the CLI or web app.                                                                       |
| **Gateway apps**          | External channels where people talk to agents, such as Slack                        | Connect the app, then bind a channel to an agent. See [external channels](/learn/agents/external-channels).                |
| **Custom credentials**    | Your own API keys or internal services                                              | Define a credential and declare it on actions.                                                                             |
| **Custom MCP servers**    | Connect to any third-party MCP server and enable agents to use its available tools  | Attach a `defineMcp()` tool to an agent, optionally backed by a credential.                                                |

You can browse our [1,000+ built-in integrations](/learn/credentials/built-in-integrations) in the app catalog, or jump to [custom apps and MCP](/learn/credentials/custom-integrations) to learn more about connecting custom apps and MCP servers.

## Credential scopes

Every credential instance is available at one of three scopes:

| Scope            | Use it when                                                   |
| ---------------- | ------------------------------------------------------------- |
| **Organization** | The whole organization should share one connection or API key |
| **Project**      | A specific project(s) gets its own connection or secret       |
| **User**         | The action should run as the user who connected the app       |

When building agents and workflows, Keystroke will automatically resolve credentials for each action (agent tools or workflow steps) in this order:

1. An explicit selection, if one was provided.
2. A pinned scope from `.scope("organization")`, `.scope("project")`, or `.scope("user")`.
3. The project default.
4. The organization default.
5. Throw a missing-credentials error.

User credentials are not part of the unpinned fallback chain. If an action should run as the user, you must specifically pin it with `.scope("user")`. See [using credentials in code](/learn/credentials/use-credentials).

## Cloud and local credentials

Credentials live in the platform: they're scoped to your organization, project, or user, and materialized on demand when a deployed project runs. Deploying does **not** upload `.env` or local secrets, so connect credentials against your cloud project with the web app or CLI.

```bash theme={null}
# Cloud organization credential
keystroke credentials set exa --set apiKey=@env:EXA_API_KEY --scope org
```

If you run a local server with `keystroke dev` / `keystroke start`, it uses a separate local credential store; CLI commands with `--local` write there.

```bash theme={null}
# Local dev credential
keystroke --local credentials set exa --set apiKey=@env:EXA_API_KEY
```

See [connect and manage apps](/learn/credentials/connect-credentials) for the full CLI and web workflow.

## How code consumes credentials

Credentials are declared on [actions](/learn/actions/overview), not on agents or workflows directly. An action lists the credentials it needs:

```ts theme={null}
import { defineAction } from "@keystrokehq/keystroke/action";
import { defineCredential } from "@keystrokehq/keystroke/credentials";
import { z } from "zod";

const exa = defineCredential({
  key: "exa",
  fields: { apiKey: z.string() },
});

export const search = defineAction({
  slug: "search",
  input: z.object({ query: z.string() }),
  output: z.object({ results: z.array(z.string()) }),
  credentials: [exa] as const,
  async run(input, credentials) {
    return callSearchApi(input.query, credentials.exa.apiKey);
  },
});
```

Agents and workflows consume credentials indirectly when they call that action as a tool or step.

## Platform API keys

App credentials are different from Keystroke platform API keys. Platform API keys authenticate your own systems to Keystroke's platform API and are managed under **Settings → API keys** or with `keystroke api-key`. App credentials authenticate Keystroke runs to third-party apps.

## Next steps

<CardGroup cols={2}>
  <Card title="Connect and manage apps" href="/learn/credentials/connect-credentials">
    Use the web app and CLI to connect, scope, rotate, and revoke credentials.
  </Card>

  <Card title="Built-in integrations" href="/learn/credentials/built-in-integrations">
    Use catalog apps and their generated actions.
  </Card>

  <Card title="Using credentials in code" href="/learn/credentials/use-credentials">
    Declare credentials on actions and control resolution with scopes.
  </Card>

  <Card title="Custom apps and MCP" href="/learn/credentials/custom-integrations">
    Add your own credentials, app wrappers, and MCP servers.
  </Card>
</CardGroup>
