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:
| Method | Description |
|---|---|
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β
- Jobs Resource - Monitor job status and progress
- Entities Resource - Manage speaker entities
- Webhooks - Real-time job notifications
- Production Guide - Best practices for production