qualiaDocs

Get started

Quickstart

Send one signup to Qualia and read the briefing it writes, with curl, the TypeScript SDK, JavaScript, or Python.

In this quickstart you send one signup to the Qualia API, wait for Qualia to research it, and read the briefing. You need a terminal and about ten minutes.

Before you begin

  • A Qualia account with briefing credits. Each briefing uses one credit. Check your balance in Settings → Billing.
  • An ICP. You describe your ideal customer during onboarding, and you can refine it in Settings → ICP. Qualia needs it to score signups. Without it, you still get the briefing, but score is null.
  • A real work email to test with. Your own is the best choice, because you can check the briefing against what you know. The examples below use anna@ridgeline.co, a fictional person.

1. Create an API key

  1. Open Settings → API Keys and select Create key.
  2. Name the key, for example Quickstart, and select Create.
  3. Copy the key. It starts with qk_live_.

Save it as an environment variable in your terminal:

export QUALIA_API_KEY="qk_live_..."

Check that the key works:

curl https://qualia.so/v1/ping \
  -H "Authorization: Bearer $QUALIA_API_KEY"

A working key returns 200 OK with "ok": true and the IDs of your organization and key. A 401 means the key is wrong or revoked. This check uses no credits and does not count toward your rate limit.

Keep your key on the server

Anyone with the key can send signups and read briefings for your organization. Call Qualia from your backend only. Never put the key in browser or mobile code.

2. Send a signup

Send the person's email with POST /v1/actors. Add a name if you have one, and a source label that tells you where the signup came from.

If you use the SDK, install it first with npm install @qualiaso/sdk. Put the TypeScript code from steps 2 and 3 in one file named quickstart.mts and run it with npx tsx quickstart.mts.

import { Qualia } from "@qualiaso/sdk";

const qualia = new Qualia({
  auth: () => process.env.QUALIA_API_KEY!,
});

const { data, error, response } = await qualia.createActor({
  body: {
    email: "anna@ridgeline.co",
    name: "Anna Park",
    source: "quickstart",
  },
});

if (error) {
  throw new Error(`Qualia returned ${response.status}: ${JSON.stringify(error)}`);
}

console.log(data);

Qualia replies with 201 Created and the new actor's ID:

{
  "actorId": "q3ab8fnt2kzw7yx1mvd05hce",
  "status": "created"
}

Keep the actorId. You use it to read the result.

Sending the same email again is safe. You get the same actorId back with 200 OK and "status": "already_exists", and Qualia does not research the person twice.

3. Wait for the research to finish

Research runs in the background and can take a few minutes. Read the actor with GET /v1/actors/{actorId} and check status:

  • pending or enriching: research is still running. Check again in 15 seconds.
  • enriched: the briefing is ready.
  • rejected or failed: there is no briefing. See If there is no briefing.
const { actorId } = data;

while (true) {
  const result = await qualia.getActor({ path: { actorId } });
  if (result.error) {
    throw new Error(`Qualia returned ${result.response.status}`);
  }

  const actor = result.data;
  if (actor.status !== "pending" && actor.status !== "enriching") {
    console.log(actor);
    break;
  }

  console.log(`Status: ${actor.status}. Checking again in 15 seconds.`);
  await new Promise((resolve) => setTimeout(resolve, 15_000));
}

With curl, run the command again every 15 seconds until status changes. While research runs, every research field in the response is null.

4. Read the briefing

When status is enriched, the response carries the briefing:

{
  "id": "q3ab8fnt2kzw7yx1mvd05hce",
  "email": "anna@ridgeline.co",
  "name": "Anna Park",
  "status": "enriched",
  "rejectionReason": null,
  "failureReason": null,
  "score": 82,
  "scoringStatus": "ok",
  "title": "Head of Platform Engineering",
  "linkedinUrl": "https://www.linkedin.com/in/annapark-ridgeline",
  "location": "Denver, Colorado",
  "companyName": "Ridgeline",
  "companyDomain": "ridgeline.co",
  "industry": "Logistics software",
  "companyLocation": "Denver, Colorado",
  "createdAt": "2026-09-29T14:02:11.482Z",
  "enrichedAt": "2026-09-29T14:04:37.915Z",
  "summary": "Anna Park leads platform engineering at Ridgeline, a logistics software company that builds route planning tools for regional freight carriers. She joined in 2024 after six years on infrastructure teams at larger SaaS companies.",
  "highlights": [
    "Ridgeline raised a Series A in June 2026.",
    "Ridgeline lists four open backend and data engineering roles.",
    "Anna spoke about moving Ridgeline's event pipeline to managed infrastructure at a DevOps meetup in 2025."
  ],
  "bio": "Platform engineer focused on developer tooling and reliable data pipelines.",
  "companyDescription": "Ridgeline builds route planning and dispatch software for regional freight carriers."
}

The fields you will use most:

FieldWhat it tells you
summaryWho the person is and what their company does, in two or three sentences.
highlightsShort facts worth knowing before you reach out.
scoreICP fit from 0 to 100. Higher means a closer match to your ICP.
title, companyName, industryThe person's role and employer.

Any research field can be null if Qualia could not find it. Briefings and ICP fit explains every field. You can also open the signup in the dashboard to see the reasoning behind the score.

If there is no briefing

StatusWhat happenedWhat to do
rejectedQualia declined the signup before researching it, for example a disposable email address. rejectionReason says why. Rejected signups use no credits.Follow Handle rejected signups.
failedThe research run hit an error. failureReason says why. Failed runs use no credits.Qualia retries failed runs automatically. See Get briefing results.

Next steps