## TL;DR

Use the client_id and secret pair that belongs to the environment you are calling. Plaid issues separate credentials per environment, so sandbox keys sent to development (or any cross-environment mix) fail with INVALID_API_KEYS. Match the pair to the environment.

```text
plaid API error: INVALID_API_KEYS invalid client_id or secret
```

## Steps

1. Note which Plaid environment your code targets: sandbox, development, or production. Expected: you know the intended environment.

2. In the Plaid dashboard, open the API keys section for that exact environment. Expected: you have the canonical client_id and secret for it.

3. Compare against what your code actually sends, watching for copied whitespace, truncated values, or keys from a different environment. Expected: you spot the mismatch or confirm the values are stale.

4. Replace the stored credentials with the correct pair for the target environment and keep environments in separate config. Expected: each environment's config holds only its own keys.

5. Re-run the API call. Expected: Plaid authenticates and the error is gone.

## Use this when

- Plaid returns exactly "INVALID_API_KEYS invalid client_id or secret".
- The integration worked in one environment and broke in another.
- Keys were copied by hand or rotated recently.

## Not for this skill when

- A public_token or link_token is invalid (those are per-user, not API keys).
- The end user's bank login fails (that is the item's credentials, not yours).
- Another provider rejects your keys with different wording.

## Variant phrasings

- Plaid invalid client_id or secret
- Plaid INVALID_API_KEYS error fix
- Plaid API keys not working wrong environment

## Why it happens

Plaid credentials are environment-scoped: the sandbox client_id only works with the sandbox secret against the sandbox host. Generated clients commonly promote code from sandbox to production while leaving the old keys in config, or they paste keys with trailing whitespace from the dashboard. The API cannot tell a wrong-environment key from a typo, so both surface as INVALID_API_KEYS.

## Edge cases

- Rotating a secret invalidates the old one immediately; every deployed copy must be updated at once.
- The client_id is not secret but the secret is; a leaked secret should be rotated, not just re-copied.
- Some dashboards show the secret only once at creation; if it is lost, generate a new one rather than guessing.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_iTw9NJwwil-GEIwbu4Y8RQ
