Guides
Send signups to Qualia
Call Qualia from your signup handler, send the context that improves research, and backfill existing users.
This guide shows you how to send every new signup to Qualia from your backend without slowing down sign-up, what to include so research works well, and how to send users you already have.
The examples use the TypeScript SDK. Any HTTP client works the same way: one POST /v1/actors request per signup.
Call Qualia from your backend
Send the signup from your server, after your own sign-up logic succeeds. Never call Qualia from the browser or a mobile app, because the request needs your secret API key.
Create one client and reuse it:
import { Qualia } from "@qualiaso/sdk";
export const qualia = new Qualia({
auth: () => process.env.QUALIA_API_KEY!,
});Then add a function your signup handler can call:
import { qualia } from "./qualia";
interface NewUser {
id: string;
email: string;
name?: string;
company?: string;
}
export async function sendSignupToQualia(user: NewUser) {
const { data, error, response } = await qualia.createActor({
body: {
email: user.email,
name: user.name,
source: "signup_form",
metadata: { company: user.company, userId: user.id },
},
});
if (error) {
console.error("Qualia rejected the request", response.status, error);
return null;
}
// Save data.actorId on your user record to read the briefing later.
return data.actorId;
}Keep sign-up fast
Your users should never wait on Qualia or see an error because of it.
- Run the call after you send the sign-up response, or in a background job.
- Catch errors. The SDK throws on network failures and timeouts, and returns API errors in
error. - If a call fails, retry it later. Repeat requests for the same email are safe.
import { sendSignupToQualia } from "../lib/send-signup";
// After the user account is created:
sendSignupToQualia(user).catch((err) => {
console.error("Could not reach Qualia", err);
});On serverless platforms, a function can stop as soon as the response is sent. Use your platform's way to run work after the response, such as after() in Next.js, or send the signup through a job queue.
Send context with each signup
Qualia only needs an email. More context gives it a better starting point.
| Field | Why it helps |
|---|---|
name | Confirms which person Qualia is looking for. Needed for most personal email addresses. |
source | Tells your signup paths apart, such as signup_form, google_oauth, or team_invite. You can filter by it in the dashboard and in Slack. |
metadata.company | Points research at the right employer, even when the email is personal. |
metadata.title | Gives Qualia a job title to confirm. |
metadata.linkedinUrl | Identifies the exact person. |
Other metadata keys | Anything else you know, such as plan, UTM parameters, or onboarding answers. Qualia uses it as extra context. |
Signups from personal email addresses, such as Gmail or Proton, need a name or at least one company, title, LinkedIn, or work email key in metadata. Without them, Qualia rejects the signup with insufficient_context. Actors lists every key Qualia recognizes.
If your product verifies email addresses, consider sending the signup after verification. Signups Qualia declines use no credits, but a fake account with a real-looking address gets researched and uses one.
Retry safely
Each email maps to one actor. Sending the same email again returns the same actorId with 200 OK and "status": "already_exists". Qualia does not research the person twice, and the repeat uses no credit. You can retry failed calls and replay a queue without creating duplicates.
Backfill existing users
You can send users who signed up before you added Qualia. Plan for two limits:
- Rate limit. Each API key can make 60 requests per minute. Polling for results with the same key counts too.
- Credits. Each user Qualia researches uses one credit. Send only the users you want briefings for.
Send one request per second, and wait when Qualia asks you to:
import { qualia } from "../lib/qualia";
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
for (const user of users) {
while (true) {
const { error, response } = await qualia.createActor({
body: { email: user.email, name: user.name, source: "backfill" },
});
if (response.status === 429) {
const waitSeconds = Number(response.headers.get("Retry-After") ?? "60");
await sleep(waitSeconds * 1000);
continue;
}
if (response.status === 402) {
throw new Error("Out of briefing credits. Add credits, then run again.");
}
if (error) {
console.error(`Skipped ${user.email}`, response.status, error);
}
break;
}
await sleep(1_000);
}Here users is your list of existing users. Running the script again is safe: users Qualia already has come back as already_exists.
Next steps
- Get briefing results. Read each briefing once research finishes.
- Handle rejected signups. What to do when Qualia declines a signup.
- Handle errors and rate limits. Every error code and how to recover.