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

# Framework guide: protect the API key

> Why Angular needs an intermediary backend and how to structure it.

# Framework guide: protect the API key

Angular is a **frontend** framework: all your application code is downloaded and executed in the user's browser. Any value included in the bundle — including a API key set to constant or `environment.ts` — is visible to anyone who opens the developer tools or inspects network traffic.

<Warning>
  `@markpdf/angular` should **never** be set with your actual API Flash key PDF to Markdown pointing directly to `https://api.markpdf.tech`. It always goes through its own backend that stores the server-side key.
</Warning>

## Arquitectura recomendada

```
Angular (navegador)  →  tu backend (Node/Nest/.NET/Django/...)  →  API de Flash PDF to Markdown
     without API key            API key in environment variable            vavalidates x-api-key
```

`MarkpdfService` is configured with `baseUrl` pointing to **your backend**, not the public API:

```ts app.config.ts theme={null}
provideMarkpdf({ baseUrl: "/api/markpdf" }); // ruta relativa de TU backend
```

Your backend exposes that route and forwards the request to the real API using the SDK of [Node.js](/docs/sdks/nodejs/installation) (or another SDK if your backend is not Node) with the key saved as a server secret.

## Proxy backend example (Express + `@markpdf/sdk`)

```ts server/routes/markpdf.ts theme={null}
import { Router } from "express";
import multer from "multer";
import { MarkpdfClient } from "@markpdf/sdk";

const router = Router();
const upload = multer();
const client = new MarkpdfClient({ apiKey: process.env.MARKPDF_API_KEY! });

router.post("/api/markpdf/convert", upload.single("file"), async (req, res) => {
  try {
    const markdown = await client.convertFile(req.file!.buffer, {
      filename: req.file!.originalname,
      mode: (req.query.mode as string) || "fast",
    });
    res.type("text/markdown").send(markdown);
  } catch (err: any) {
    res.status(err.statusCode ?? 502).json({ error: err.detail ?? String(err) });
  }
});

export default router;
```

Angular calls `/api/markpdf/convert`, your Express backend calls the actual API. The browser never sees `YOUR_API_KEY`.

## Configure `MarkpdfService` to talk to your backend

```ts app.config.ts theme={null}
import { provideMarkpdf } from "@markpdf/angular";

provideMarkpdf({
  baseUrl: "/api/markpdf",     // or "https://your-backend.com/api/markpdf" in production
  convertPath: "/convert",      // ruta relativa dentro de baseUrl, default "/convert"
  withCredentials: true,        // si tu backend usa cookies de sesión para autenticar al user
});
```

`MarkpdfService` internally constructs normal `HttpClient` requests — you can combine it with your app's own auth interceptors (JWT, session cookies) just like any other Angular HTTP service.

## Error interceptor

```ts app.config.ts theme={null}
import { provideHttpClient, withInterceptors } from "@angular/common/http";
import { markpdfErrorInterceptor } from "@markpdf/angular";

provideHttpClient(withInterceptors([markpdfErrorInterceptor]));
```

`markpdfErrorInterceptor` normalizes error responses from your backend (provided you forward the `status` and body `{ error: string }` as in the Express example above) to instances of `MarkpdfClientError`, consistent with those documented by [Error Handling](/docs/sdks/angular/error-handling).

## Authenticate the end user against your backend

`MarkpdfService` does not manage user sessions — that is the responsibility of your own app. Combine it with your usual auth interceptor:

```ts app.config.ts theme={null}
provideHttpClient(
  withInterceptors([authTokenInterceptor, markpdfErrorInterceptor])
);
```

<Tip>
  This pattern (no secret frontend → own backend with API key → API public) is the same as what [Next.js](/docs/sdks/nextjs/framework-guide) recommends for Route Handlers, only in Angular the "own backend" is explicitly a separate service instead of being integrated into the same project.
</Tip>
