npm package: @mappa-ai/mappa-node
Description: Official TypeScript/Node SDK for the Mappa API
Latest version: 2.0.11
Deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.

# @mappa-ai/mappa-node

[![npm version](https://img.shields.io/npm/v/@mappa-ai/mappa-node.svg)](https://www.npmjs.com/package/@mappa-ai/mappa-node)
[![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue.svg)](https://www.typescriptlang.org/)

Behavioral intelligence for your app. Type-safe. Async-first. Production-ready.

## Install

```bash
# npm
npm install @mappa-ai/mappa-node

# yarn
yarn add @mappa-ai/mappa-node

# pnpm
pnpm add @mappa-ai/mappa-node

# bun
bun add @mappa-ai/mappa-node
```

## Runtime support

Runs anywhere fetch runs. Node, Bun, Deno, Cloudflare Workers. Browser blocked by default — your API key stays secret.

## Security

Your API key is secret. We enforce it.

- Keep `MAPPA_API_KEY` server-side.
- Proxy requests through your backend.
- Browser calls throw unless you set `dangerouslyAllowBrowser: true`.

## Choose a workflow

Three paths. Pick yours.

| Method | When to use |
| --- | --- |
| `generateFromFile` / `generateFromUrl` | One call. Done. |
| `createJob` + `webhook` | Fire and forget. We call you. |
| `createJob` + `wait()` / `stream()` | Stay in control. |

## Webhooks — the production path

Submit jobs. Move on. Mappa calls your endpoint when it's done. Signatures included.

### Publish

One field. That's it.

```ts
import { Mappa } from "@mappa-ai/mappa-node"

const mappa = new Mappa({ apiKey: process.env.MAPPA_API_KEY! })

const receipt = await mappa.reports.createJobFromFile({
  file: audioBlob,
  output: { template: "general_report" },
  target: { strategy: "dominant" },
  webhook: {
    url: "https://your-app.com/api/webhooks/mappa",
    headers: { "x-tenant-id": "tenant_123" },
  },
})

console.log(receipt.jobId)
```

Already have media uploaded? Same idea.

```ts
await mappa.reports.createJob({
  media: { mediaId: "media_abc123" },
  output: { template: "general_report" },
  target: { strategy: "dominant" },
  webhook: { url: "https://your-app.com/api/webhooks/mappa" },
})
```

### Consume

Verify. Parse. React.

```ts
import { Mappa } from "@mappa-ai/mappa-node"

const mappa = new Mappa({ apiKey: process.env.MAPPA_API_KEY! })

export async function POST(req: Request): Promise<Response> {
  const payload = await req.text()

  await mappa.webhooks.verifySignature({
    payload,
    headers: Object.fromEntries(req.headers),
    secret: process.env.MAPPA_WEBHOOK_SECRET!,
  })

  const event = mappa.webhooks.parseEvent(payload)

  if (event.type === "report.completed") {
    const report = await mappa.reports.get(event.data.reportId)
    console.log("done", report.id)
    return new Response("ok", { status: 200 })
  }

  if (event.type === "report.failed") {
    console.error("failed", event.data.jobId, event.data.error.code)
    return new Response("ok", { status: 200 })
  }

  return new Response("ignored", { status: 200 })
}
```

## Polling — when you want to wait

Sometimes you need the answer now.

### `wait()`

```ts
import { Mappa } from "@mappa-ai/mappa-node"

const mappa = new Mappa({ apiKey: process.env.MAPPA_API_KEY! })

const media = await mappa.files.upload({ file: audioBlob })

const job = await mappa.reports.createJob({
  media: { mediaId: media.mediaId },
  output: { template: "general_report" },
  target: { strategy: "dominant" },
})

const report = await job.handle?.wait()
console.log(report?.id)
```

### `stream()`

```ts
for await (const event of job.handle?.stream() ?? []) {
  if (event.type === "stage") {
    console.log(event.stage, event.progress)
  }
}
```

## Helpers

### `generateFromFile`

Upload, process, return. One call.

```ts
const report = await mappa.reports.generateFromFile({
  file: audioBlob,
  output: { template: "general_report" },
  target: { strategy: "dominant" },
})

console.log(report.id)
```

### `generateFromUrl`

Got a URL? We fetch it.

```ts
const report = await mappa.reports.generateFromUrl({
  url: "https://example.com/recording.wav",
  output: { template: "general_report" },
  target: { strategy: "dominant" },
})

console.log(report.id)
```

## Node/Bun file paths

Working with file paths? Use the `/node` subpath.

```ts
import { Mappa } from "@mappa-ai/mappa-node"
import { generateReportFromPath, uploadFromPath } from "@mappa-ai/mappa-node/node"

const mappa = new Mappa({ apiKey: process.env.MAPPA_API_KEY! })

const media = await uploadFromPath(mappa, { path: "./recording.wav" })

const report = await generateReportFromPath(mappa, {
  path: "./recording.wav",
  output: { template: "general_report" },
  target: { strategy: "dominant" },
})

console.log(media.mediaId, report.id)
```

## Error handling

Things break. We tell you why.

```ts
import { isInsufficientCreditsError, isMappaError, isStreamError } from "@mappa-ai/mappa-node"

try {
  // ...
} catch (err) {
  if (isInsufficientCreditsError(err)) {
    console.error(err.required, err.available)
    return
  }

  if (isStreamError(err)) {
    console.error(err.jobId, err.retryCount)
    return
  }

  if (isMappaError(err)) {
    console.error(err.requestId, err.code, err.message)
  }
}
```

## Scope

API-key workflows. Reports, files, jobs, webhooks, feedback, entities. Billing lives in the dashboard.

---

Questions? [api-docs.mappa.ai](https://api-docs.mappa.ai)

For SDK maintenance, see `README_INTERNAL.md`.