Guides
Get briefing results
Poll for each briefing in production, stay within the rate limit, and act on the result.
Qualia researches each signup in the background, so the briefing is not in the create response. This guide shows you how to collect finished briefings reliably and what to do with each outcome.
Choose how to get results
| Option | Best for | Setup |
|---|---|---|
| Poll the API | Saving briefings in your own database or CRM, or triggering your own workflows. | Code, covered on this page. |
| Slack | Telling your team about strong signups as soon as research finishes. | A few clicks. See Deliver briefings to Slack. |
| Dashboard | Reviewing signups by hand. | None. Open the dashboard. |
You can combine them. Webhooks that push results to your server are planned and not yet available.
Poll for the result
Save the actorId from POST /v1/actors, then read the actor until it reaches a final status. Run this in a background job, never inside a user's request.
- Check every 15 to 30 seconds. Research can take a few minutes.
- Stop at a final status:
enriched,rejected, orfailed. - Set a time limit. If an actor is still
pendingorenrichingafter 30 minutes, stop waiting and contact support with the actor ID so we can look into it.
This helper uses the TypeScript SDK:
import type { GetActorResponse } from "@qualiaso/sdk";
import { qualia } from "./qualia";
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
const FINAL_STATUSES = new Set(["enriched", "rejected", "failed"]);
export async function waitForBriefing(
actorId: string,
{ intervalMs = 15_000, timeoutMs = 30 * 60_000 } = {},
): Promise<GetActorResponse> {
const deadline = Date.now() + timeoutMs;
while (true) {
const { data, error, response } = await qualia.getActor({
path: { actorId },
});
if (response.status === 429) {
const waitSeconds = Number(response.headers.get("Retry-After") ?? "60");
await sleep(waitSeconds * 1000);
continue;
}
if (error) {
throw new Error(
`Qualia returned ${response.status}: ${JSON.stringify(error)}`,
);
}
if (FINAL_STATUSES.has(data.status) || Date.now() >= deadline) {
return data;
}
await sleep(intervalMs);
}
}Stay within the rate limit
Every poll is one request, and each API key can make 60 requests per minute. At one poll every 15 seconds, one key can follow about 15 signups at a time while leaving room for new signups. If you have more in flight, poll each one less often.
Every successful response includes X-RateLimit-Remaining, so you can slow down before you reach the limit. See Handle errors and rate limits.
Act on the result
Branch on status, then use score to decide what happens next:
import { waitForBriefing } from "../lib/wait-for-briefing";
export async function processSignup(actorId: string) {
const actor = await waitForBriefing(actorId);
switch (actor.status) {
case "enriched":
// Save the briefing on your user record, then route strong fits.
if (actor.score !== null && actor.score >= 60) {
console.log(`Qualified signup: ${actor.name} at ${actor.companyName}`);
}
break;
case "rejected":
console.log(`Rejected: ${actor.rejectionReason}`);
break;
case "failed":
console.log(`Failed: ${actor.failureReason}`);
break;
default:
// Still pending or enriching when the time limit ran out.
console.log(`Timed out waiting for actor ${actor.id}`);
}
}A score of 60 or more matches the Qualified and Hot labels in the dashboard. Pick the threshold that suits your team. If score is null on an enriched actor, scoringStatus says why. See When the score is null.
For rejected signups, follow Handle rejected signups.
When a run fails
A failed status means the research run hit an error. failureReason gives a short code, such as agent_error. Failed runs use no credits.
Qualia retries a failed run automatically, up to two more times, about a minute apart. During a retry the status moves back to enriching, and the run can still end as enriched. If you stop polling at failed, check the actor again a few minutes later.
An actor that is still failed after the retries stays failed. Sending the same email again does not restart it, and there is no other way to re-run it. If runs fail often, contact support with the actor IDs so we can look into the cause.
Next steps
- Briefings and ICP fit. Every field in the response.
- Deliver briefings to Slack. Get strong signups in a channel without writing code.
- Fetch an actor. The full endpoint reference.