Skip to main content

Reports resource

The mappa.reports resource provides methods for creating report jobs, waiting for completion, and retrieving results.

Overview​

Reports are generated asynchronously through jobs. The Reports resource handles:

  • Job creation from various media sources
  • Polling and streaming job progress
  • Retrieving completed reports
  • Template configuration and speaker targeting

Quick start​

// One-liner: download β†’ upload β†’ analyze β†’ wait β†’ return report
const report = await mappa.reports.generateFromUrl({
url: "https://example.com/call.mp3",
output: { template: "sales_playbook" },
target: { strategy: "dominant" },
});

console.info(report.markdown);

Methods​

Job creation​

createJob()​

Create a report job from an already-uploaded media file.

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

console.info(`Job ID: ${receipt.jobId}`);

Parameters:

{
media: { mediaId: string };
output: ReportOutput;
target: TargetSelector;
label?: string;
entityLabel?: string;
webhook?: {
url: string;
headers?: Record<string, string>;
};
idempotencyKey?: string;
requestId?: string;
signal?: AbortSignal;
}

Returns:

{
jobId: string;
status: "queued" | "running";
stage?: JobStage;
estimatedWaitSec?: number;
requestId?: string;
handle?: ReportRunHandle;
}

Example:

const receipt = await mappa.reports.createJob({
media: { mediaId: "media_abc123" },
output: { template: "sales_playbook" },
target: { strategy: "dominant" },
entityLabel: "customer_456",
webhook: {
url: "https://myapp.com/webhooks/mappa",
},
idempotencyKey: "report:customer_456:2026-01-17",
});

createJobFromFile()​

Upload a file and create a report job in one call.

import { readFile } from "node:fs/promises";

const buffer = await readFile("./recording.mp3");

const receipt = await mappa.reports.createJobFromFile({
file: buffer,
label: "recording.mp3",
output: { template: "general_report" },
target: { strategy: "dominant" },
});

Parameters:

Same as createJob() but with file upload fields instead of media:

{
file: Blob | ArrayBuffer | Uint8Array | ReadableStream<Uint8Array>;
label?: string;
signal?: AbortSignal;
// ... rest same as createJob()
}

createJobFromUrl()​

Download a file from a URL, upload it, and create a report job.

const receipt = await mappa.reports.createJobFromUrl({
url: "https://example.com/recording.mp3",
output: { template: "sales_playbook" },
target: { strategy: "dominant" },
});

Parameters:

Same as createJob() but with URL fields instead of media:

{
url: string;
label?: string;
signal?: AbortSignal;
// ... rest same as createJob()
}

Example:

const receipt = await mappa.reports.createJobFromUrl({
url: "https://example.com/interview.mp3",
output: { template: "hiring_report",
templateParams: {
roleTitle: "Senior Engineer",
roleDescription: "Backend development",
companyCulture: "Fast-paced startup",
},
},
target: {
strategy: "magic_hint",
hint: "the candidate",
},
});

Convenience methods (blocking)​

These methods create a job and wait for completion. Use for scripts and testingβ€”not recommended for production.

generate()​

Create a job from an existing mediaId and wait for completion.

const report = await mappa.reports.generate({
media: { mediaId: "media_abc123" },
output: { template: "general_report" },
target: { strategy: "dominant" },
});

generateFromFile()​

Upload a file, create a job, and wait for completion.

const report = await mappa.reports.generateFromFile({
file: fileBuffer,
label: "call.mp3",
output: { template: "sales_playbook" },
target: { strategy: "dominant" },
});

generateFromUrl()​

Download from URL, upload, create job, and wait for completion.

const report = await mappa.reports.generateFromUrl({
url: "https://example.com/call.mp3",
output: { template: "sales_playbook" },
target: { strategy: "dominant" },
});

Report retrieval​

get()​

Get a report by report ID.

const report = await mappa.reports.get("report_xyz789");

if (report.markdown) {
console.info(report.markdown);
}

Parameters:

get(
reportId: string,
opts?: {
requestId?: string;
signal?: AbortSignal;
}
): Promise<Report>

getByJob()​

Get a report by job ID. Returns null if the job hasn't completed.

const report = await mappa.reports.getByJob("job_abc123");

if (report) {
console.info("Report ready!");
} else {
console.info("Job still processing");
}

Parameters:

getByJob(
jobId: string,
opts?: {
requestId?: string;
signal?: AbortSignal;
}
): Promise<Report | null>

Job handles​

makeHandle()​

Create a handle for job operations from a job ID.

const handle = mappa.reports.makeHandle("job_abc123");

// Check status
const job = await handle.job();

// Get report (if ready)
const report = await handle.report();

// Wait for completion
const finalReport = await handle.wait();

// Cancel job
await handle.cancel();

Handle Methods:

MethodDescription
wait(opts?)Poll until completion, return report
stream(opts?)Stream job events as async iterator
cancel()Cancel the job
job()Get current job status
report()Get report (returns null if not ready)

Example:

const handle = mappa.reports.makeHandle("job_abc123");

// Stream progress
for await (const event of handle.stream()) {
if (event.type === "stage") {
console.info(`${event.stage}: ${event.progress}`);
}
if (event.type === "terminal") break;
}

// Get final report
const report = await handle.report();

Report templates​

General report​

General-purpose behavioral analysis:

const report = await mappa.reports.generateFromUrl({
url: "https://example.com/call.mp3",
output: { template: "general_report" },
target: { strategy: "dominant" },
});

Sales playbook​

Sales call analysis:

const report = await mappa.reports.generateFromUrl({
url: "https://example.com/sales-call.mp3",
output: { template: "sales_playbook" },
target: { strategy: "dominant" },
});

Hiring report​

Interview analysis (requires parameters):

const report = await mappa.reports.generateFromUrl({
url: "https://example.com/interview.mp3",
output: { template: "hiring_report",
templateParams: {
roleTitle: "Senior Software Engineer",
roleDescription: "Backend development with Node.js and Python",
companyCulture: "Collaborative, innovative, work-life balance",
},
},
target: { strategy: "dominant" },
});

Profile alignment​

Alignment with an ideal profile (requires parameters):

const report = await mappa.reports.generateFromUrl({
url: "https://example.com/call.mp3",
output: { template: "profile_alignment",
templateParams: {
idealProfile: "Empathetic, patient, excellent listener",
},
},
target: { strategy: "dominant" },
});

Output types​

Reports can be generated in different formats:

Markdown​

const report = await mappa.reports.generateFromUrl({
url: "https://example.com/call.mp3",
output: { template: "sales_playbook" },
target: { strategy: "dominant" },
});

// Type guard
if (report.markdown) {
console.info(report.markdown);
}

JSON​

Structured data with sections:

const report = await mappa.reports.generateFromUrl({
url: "https://example.com/call.mp3",
output: { template: "sales_playbook" },
target: { strategy: "dominant" },
});

if (report.sections) {
for (const section of report.sections) {
console.info(section.section_title);
console.info(section.section_content);
}
}

PDF​

const report = await mappa.reports.generateFromUrl({
url: "https://example.com/interview.mp3",
output: { template: "hiring_report" },
target: { strategy: "dominant" },
});

if (report.pdfUrl) {
console.info(`Download: ${report.pdfUrl}`);
console.info(`Markdown: ${report.markdown}`);
}

URL​

Hosted report with shareable URL:

const report = await mappa.reports.generateFromUrl({
url: "https://example.com/call.mp3",
output: { template: "sales_playbook" },
target: { strategy: "dominant" },
});

if (report.reportUrl) {
console.info(`View report: ${report.reportUrl}`);
}

Speaker targeting​

Control which speaker is analyzed:

Dominant speaker (default)​

const report = await mappa.reports.generateFromUrl({
url: "https://example.com/call.mp3",
output: { template: "general_report" },
target: { strategy: "dominant" },
});

Magic hint​

Natural language description:

const report = await mappa.reports.generateFromUrl({
url: "https://example.com/interview.mp3",
output: { template: "hiring_report" },
target: {
strategy: "magic_hint",
hint: "the candidate being interviewed",
},
});

Time range​

Dominant speaker within a time window:

const report = await mappa.reports.generateFromUrl({
url: "https://example.com/meeting.mp3",
output: { template: "general_report" },
target: {
strategy: "timerange",
timeRange: {
startSeconds: 60, // 1 minute
endSeconds: 300, // 5 minutes
},
},
});

Entity ID​

Target a known speaker entity:

const report = await mappa.reports.generateFromUrl({
url: "https://example.com/call.mp3",
output: { template: "general_report" },
target: {
strategy: "entity_id",
entityId: "ent_abc123xyz",
},
});

Magic hint with fallback​

const report = await mappa.reports.generateFromUrl({
url: "https://example.com/interview.mp3",
output: { template: "hiring_report" },
target: {
strategy: "magic_hint",
hint: "the candidate",
onMiss: "fallback_dominant",
},
});

Common patterns​

Production: job + webhook​

const receipt = await mappa.reports.createJobFromUrl({
url: "https://example.com/call.mp3",
output: { template: "sales_playbook" },
target: { strategy: "dominant" },
webhook: {
url: "https://myapp.com/webhooks/mappa",
headers: { "X-Webhook-Secret": process.env.WEBHOOK_SECRET! },
},
idempotencyKey: `report:${userId}:${timestamp}`,
});

// Store job ID, process webhook later
await db.jobs.create({
id: receipt.jobId,
userId,
status: receipt.status,
});

Streaming progress​

const receipt = await mappa.reports.createJobFromUrl({
url: "https://example.com/call.mp3",
output: { template: "general_report" },
target: { strategy: "dominant" },
});

for await (const event of receipt.handle!.stream()) {
switch (event.type) {
case "stage":
console.info(`${event.stage}: ${Math.round(event.progress! * 100)}%`);
break;
case "terminal":
console.info("Complete!");
break;
}
}

const report = await receipt.handle!.report();

Polling with timeout​

import { JobFailedError } from "@mappa-ai/mappa-node";

const receipt = await mappa.reports.createJobFromUrl({
url: "https://example.com/call.mp3",
output: { template: "general_report" },
target: { strategy: "dominant" },
});

try {
const report = await receipt.handle!.wait({
timeoutMs: 5 * 60_000, // 5 minutes
onEvent: (event) => {
if (event.type === "stage") {
console.info(event.stage);
}
},
});
} catch (err) {
if (err instanceof JobFailedError) {
console.error("Job failed:", err.message);
} else {
throw err;
}
}

Batch processing​

const urls = [
"https://example.com/call1.mp3",
"https://example.com/call2.mp3",
"https://example.com/call3.mp3",
];

// Create all jobs
const receipts = await Promise.all(
urls.map((url, i) =>
mappa.reports.createJobFromUrl({
url,
output: { template: "sales_playbook" },
target: { strategy: "dominant" },
idempotencyKey: `batch:${Date.now()}:${i}`,
})
)
);

console.info(`Created ${receipts.length} jobs`);

// Wait for all to complete
const reports = await Promise.all(
receipts.map((r) => r.handle!.wait())
);

console.info(`Completed ${reports.length} reports`);

Retry on failure​

import { JobFailedError } from "@mappa-ai/mappa-node";

async function generateWithRetry(url: string, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const receipt = await mappa.reports.createJobFromUrl({
url,
output: { template: "general_report" },
target: { strategy: "dominant" },
idempotencyKey: `retry:${url}:${attempt}`,
});

return await receipt.handle!.wait();
} catch (err) {
if (err instanceof JobFailedError && attempt < maxRetries) {
console.warn(`Attempt ${attempt} failed, retrying...`);
await new Promise((r) => setTimeout(r, 2000 * attempt));
continue;
}
throw err;
}
}
}

Error handling​

import {
ValidationError,
JobFailedError,
JobCanceledError,
} from "@mappa-ai/mappa-node";

try {
const report = await mappa.reports.generateFromUrl({
url: "https://example.com/call.mp3",
output: { template: "general_report" },
target: { strategy: "dominant" },
});
} catch (err) {
if (err instanceof ValidationError) {
console.error("Invalid request:", err.details);
} else if (err instanceof JobFailedError) {
console.error(`Job ${err.jobId} failed:`, err.message);
} else if (err instanceof JobCanceledError) {
console.error(`Job ${err.jobId} was canceled`);
}
}

Type reference​

import type {
Report,
ReportCreateJobRequest,
ReportJobReceipt,
ReportRunHandle,
TargetSelector,
ReportOutput,
} from "@mappa-ai/mappa-node";

See TypeScript Types for complete type definitions.


Next steps​