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

# Application client secret

> Authenticate browser-side application endpoints using a short-lived, scoped client secret instead of exposing a backend bearer token.

The application client secret is a short-lived, scoped credential the Embedded Banking API returns when an application is created. It authenticates follow-up calls against that single application from the browser — typically the white-label hosted app or an embedded widget — without exposing a backend bearer token to the client.

For the broader picture of how an application moves through `DRAFT`, `SUBMITTED`, and `COMPLETE`, and which auth method is required at each step, see the [application lifecycle guide](/embedded-banking/guides/bank-account-applications/overview).

## When to use it

Use the client secret for any browser-side call against an existing application: updating applicant or business details, requesting verification codes, submitting verification, or submitting the application. Server-to-server calls keep using a bearer token from the [client credentials](/embedded-banking/guides/authentication/client-credentials) flow — create the application and read the back-office side from your backend, and hand the client secret to the browser for everything else.

## Token shape and header

The token is a high-entropy random string prefixed with `cs_`. Send it on the `X-Client-Secret` header. On per-application endpoints, requests that carry both `X-Client-Secret` and `Authorization` fail authentication; on collection-level endpoints (such as create and resume) `X-Client-Secret` is ignored and the request authenticates with the bearer token.

```bash title="Example Request" lines theme={null}
curl -X PATCH 'https://api.sandbox.tesouro.com/embedded-banking/v1/bank-account-applications/550e8400-e29b-41d4-a716-446655440001' \
  -H 'X-Client-Secret: cs_...' \
  -H 'Content-Type: application/json' \
  -d '{ "applicant": { ... } }'
```

## Lifecycle

1. **Create.** Your backend creates the application with a bearer token. The response includes `clientSecret`.

   ```json title="Response (201 Created)" lines theme={null}
   {
     "id": "550e8400-e29b-41d4-a716-446655440001",
     "applicant": { ... },
     "businessDetails": { ... },
     "businessOwners": [ ... ],
     "clientSecret": "cs_..."
   }
   ```

2. **Hand off.** Your backend returns the secret to the browser once. The plaintext is not retrievable after this — re-fetching the application via `GET` does not return it.

3. **Use.** The browser calls per-application endpoints (`PATCH`, verification, submission) with `X-Client-Secret`.

4. **Invalidate.** Once the application reaches the `COMPLETE` state through submission, the client secret is invalidated and further calls with it fail authentication.

### Expiry and refresh

Each secret is issued with a twenty-four hour expiry. The expiry extends only on calls made during the final six hours of the window; calls made earlier in the window do not extend it. A secret used at least once during each final six-hour window can stay valid indefinitely while the application remains in `DRAFT`.

If the secret expires before the applicant completes the flow — for example, the applicant returns days later — use the [resume flow](#resume-flow) to re-issue.

## Scope and access

A client secret authenticates calls **only** against the single application it was issued for. The handler reads the application ID from the URL path; requests to any other application — or to non-application endpoints — fail authentication.

`GET` responses on a client-secret-authenticated request return the application with applicant and beneficial-owner PII masked. First and last names are reduced to first-letter-plus-asterisks (`J***`, `D**`); date of birth, social security number, and home address are omitted; phone numbers are masked except the last four digits.

<Warning>
  Masking covers the applicant and beneficial owners only. `BusinessDetails` (legal name, DBA, address, phone, tax ID) and the applicant's `workEmailAddress` are returned in plaintext. If the browser surface must not see the business tax ID, fetch the `GET` response server-side with a bearer token and forward only the fields you want exposed.
</Warning>

## Endpoints that accept the client secret

Per-application paths under bank-account applications accept the client secret. Collection-level endpoints (create, resume) require a bearer token.

| Endpoint                                                                      | Bearer | Client secret | Notes                          |
| :---------------------------------------------------------------------------- | :----- | :------------ | :----------------------------- |
| `POST /embedded-banking/v1/bank-account-applications`                         | Yes    | No            |                                |
| `GET /embedded-banking/v1/bank-account-applications/{id}`                     | Yes    | Yes           | PII masked on client secret    |
| `PATCH /embedded-banking/v1/bank-account-applications/{id}`                   | Yes    | Yes           |                                |
| `POST /embedded-banking/v1/bank-account-applications/{id}/verification-codes` | Yes    | Yes           |                                |
| `POST /embedded-banking/v1/bank-account-applications/{id}/verification`       | Yes    | Yes           |                                |
| `POST /embedded-banking/v1/bank-account-applications/{id}/submission`         | Yes    | Yes           | Invalidates secret on COMPLETE |
| `POST /embedded-banking/v1/bank-account-applications/resume`                  | Yes    | No            |                                |

## Resume flow

The resume endpoint re-issues a client secret for a `DRAFT` application when the prior one has expired. Your backend calls it with the applicant's email; the new secret is delivered to the applicant by email — it is **not** returned in the API response.

```bash title="Resume Request" lines theme={null}
curl -X POST 'https://api.sandbox.tesouro.com/embedded-banking/v1/bank-account-applications/resume' \
  -H 'Authorization: Bearer ACCESS_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{ "email": "applicant@example.com" }'
```

```json title="Response (200 OK)" lines theme={null}
{ "acknowledged": true }
```

The response is always `{ "acknowledged": true }` regardless of whether a matching `DRAFT` application exists for the supplied email — this prevents enumeration of applicant emails. If a match exists, the new secret is emailed to that address; if not, no email is sent. Resume requests are rate-limited per credential and email; excess calls also receive the acknowledgement response, not a `429`.

## Security notes

* Treat the client secret like a bearer credential. It carries write access to the application until submission completes.
* Hand the secret directly from the backend that created the application to the browser context that needs it. Do not log it, persist it in browser storage longer than necessary, or send it to third parties.
* Do not combine `X-Client-Secret` with an `Authorization` header on the same per-application request.
* The plaintext is returned exactly once — at application create or resume delivery. The service stores only a hash; there is no recovery endpoint other than resume.
