Skip to content
Developers

How Practicl is organised

Five ideas, and everything else follows from them. Worth ten minutes before you integrate: most of what goes wrong later is one of these assumed rather than read.

Product

The organising unit. A product is a thing you sell — an instrument, a module, a software release — and every document belongs to exactly one.

This matters more than it looks. Share links are scoped to a product or to specific documents, and the answers a customer gets are drawn from that product’s documents and no others. Choosing the wrong granularity is the one mistake that is expensive to undo: if you create a single product called “Instruments” and upload forty datasheets into it, every share link you issue opens all forty.

A useful test: if two documents would never be sent to the same customer, they probably belong to different products.

Document

A PDF you upload, and what we make of it. Ingestion reads the file, splits it into passages that each make sense on their own, and computes an embedding for every passage so a question can find them.

Processing takes about fifteen minutes for a fifty-page document, and that is rounded up from real measurements rather than set as a target — two documents of that size took 13.9 and 14.6 minutes. Longer documents take longer, roughly in proportion to page count.

Ingestion is single-threaded, so a second upload queues behind the first. Uploading five documents does not take about fifteen minutes; it takes five times that. Plan a first import accordingly, and upload the document you want to demonstrate first.

Nothing is lost while you wait — the upload is accepted immediately and you are emailed when the document is ready. But a document that is still processing cannot answer questions, and asking it returns nothing rather than a partial answer.

Share link

A URL you send to one customer. They open it and ask your document questions. They never sign in, never create an account, and never see your dashboard.

This is the part worth understanding properly: the link is the credential. There is no second factor and no login behind it — holding the URL is what grants access, in the same way that holding a Google Docs “anyone with the link” URL does. That is deliberate, because the alternative is asking a prospective customer to create an account before they can read your datasheet, and most of them will not.

Two consequences follow, and both are worth saying plainly. A forwarded link works for whoever receives it. And a link you need to withdraw is revoked rather than changed — revoking it stops it working for everyone who holds it, including the customer you meant to keep.

Each link carries its own scope, and can carry its own persona, so two customers can hold links to the same document and get answers in a different register — see Share links.

Scope

What a key opens. A share link is scoped to specific documents, or to a product — in which case it opens every document in that product, including ones you add later.

Scope is enforced on every request, not just when the link is created. If a document is moved out of a product, links scoped to that product stop opening it immediately.

If a key you know is valid returns 403, it is almost always scope. The message is Access denied, and it means the key works but this document is not in what it opens — not that your credential is wrong. Check the key’s scope in the dashboard under API keys, or use a key scoped to that document. A key that is genuinely invalid says Invalid or expired API key instead, which is a different problem with a different fix.

A key with no scope at all opens nothing, and cannot be made active — that state is unrepresentable rather than merely discouraged, because a key that silently opened everything is the failure worth designing out.

Persona

How the assistant answers. A persona sets the register and the boundaries — how much detail, whether it volunteers alternatives, whether it declines to speculate beyond the document.

A persona attaches to a link, not to a document or a product. Each share link can carry its own; a link that names none uses your organisation’s default. That is what lets you send the same datasheet to a procurement contact and to an application engineer and have each get an answer pitched at them, without maintaining two copies of the document.

Session

One conversation. The first question creates a session and the answer carries its session_id; passing that id on the next question continues the conversation, so follow-ups like “and at what temperature?” resolve against what came before.

Every answer carries its own sources[] — the passages it drew on, with page numbers into the original PDF. Citations are per answer, not per session, so a long conversation does not accumulate a bibliography.

Each source carries a similarity score between 0 and 1. A lower score is not necessarily a worse citation. A precise answer often comes from a short passage that shares very few words with the question — a table row giving a wavelength range scores lower against “what is the spectral range?” than a paragraph of prose that merely discusses spectral ranges, while being the better source. Use the score to compare passages within one answer, not as a confidence rating for the answer itself.

Keys, and which one you want

Share keys are the credential inside a share link and inside an embedded widget. They are scoped, they are safe to put in a page a customer loads, and they can do nothing but read the sources in their scope (for a share link, the documents you chose; for a widget, your website source) and ask questions of them.

Backend keys are for your own server-to-server calls. They are shown once when you create them and never again — we do not keep a copy you could retrieve, so store it when you see it.

Neither kind can administer anything. Creating keys, inviting colleagues, uploading documents and changing settings all require a signed-in dashboard session, so a key that leaks cannot be used to widen its own access.