API reference

One endpoint.

Send a question and a starting URL. Get back the passages that answer it, each with the page and the block it came from. Everything below is the whole surface.

Base URL

Base
https://api.aipinto.com

Quickstart

Authenticate with a key in the Authorization header. Keys are issued by hand during the alpha, so ask for one and it arrives with credit already on the account.

Request
curl -X POST https://api.aipinto.com/v1/research \
  -H "Authorization: Bearer sk_live_your_key" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: job-1234" \
  -d '{
    "query": "How do I read a file line by line in Python?",
    "url": "https://docs.python.org/3/tutorial/",
    "maxPages": 4,
    "maxDepth": 2,
    "maxCost": 0.05
  }'
Response
{
  "result": {
    "evidence": [
      {
        "text": "For reading lines from a file, you can loop over the file object.",
        "url": "https://docs.python.org/3/tutorial/inputoutput.html",
        "title": "7. Input and Output",
        "blockIds": ["https://docs.python.org/3/tutorial/inputoutput.html#b062"],
        "relevance": 0.97,
        "answerLikelihood": 0.97,
        "kind": "evidence"
      }
    ],
    "conflicts": [],
    "pagesVisited": [ ... ],
    "stopReason": "sufficient-evidence",
    "usage": { ... }
  },
  "billing": {
    "providerCost": 0.002701,
    "billedCost": 0.020637,
    "chargedUsd": 0.020637,
    "balanceUsd": 4.979363
  }
}

Request fields

FieldNotes
queryRequired. The question to answer, in plain language.
urlThe page to start from. An open web search mode exists in the library but is not enabled on the hosted service yet, so an address is required.
maxPagesCeiling on pages processed. Default 25.
maxDepthHow many link hops from the starting page. Default 3.
maxCostUSD ceiling for this request. Default 0.05, with a hard maximum of 0.50.
HeaderNotes
AuthorizationBearer sk_live_.... Required.
Content-Typeapplication/json.
Idempotency-KeyOptional. Repeating a key returns the original run and does not charge a second time, so a retry after a timeout is safe.
x-seekyo-modelOptional. Pin a specific model, if the deployment allows pinned models.

Response fields

FieldNotes
result.evidence[]The ranked passages. Each carries text, url, optional title, blockIds, relevance, answerLikelihood and kind. Ordered by how well the passage answers the question, not by how on-topic it is.
result.conflicts[]Passages that contradict the others, kept in their own list rather than merged, so a caller can report disagreement instead of averaging it away.
result.pagesVisited[]Every page fetched: url, finalUrl, parentUrl, depth, status, priority and reason.
result.stopReasonWhy the run ended: sufficient-evidence, frontier-exhausted, below-threshold, max-pages, max-depth, max-bytes, max-wall-clock, max-cost, max-semantic-decisions or aborted.
result.usageCounters for the run: fetches by kind, pages processed, semantic questions and tokens, and the cost breakdown.
billing.billedCostWhat the run is worth under the price book.
billing.chargedUsdWhat was actually taken from the balance.
billing.balanceUsdThe balance after the charge.
billing.estimateThe pre-flight estimate, alongside estimateSafetyFactor, the multiplier the gates used.
billing.unbilledUsdPresent only if a run outran both its estimate and the account.

The run's full internal trace is kept on the server for debugging and is not returned, so a response cannot leak the query strings or fragments of pages that were fetched and then rejected.

Errors

Every failure uses one envelope:

Error
{
  "error": {
    "code": "insufficient-funds",
    "message": "The account balance cannot cover the estimated cost of this request.",
    "details": { "balanceUsd": 0.0012, "requiredUsd": 0.0224 }
  }
}
StatusMeaning
400The request body is not valid JSON, or a field is the wrong type.
401No key, a malformed header, an unknown key, or a revoked one.
402The balance, or the request's cost ceiling, cannot cover the estimated work.
404Unknown route.
405Wrong method for that route.
413The request body is too large.
429Rate limited. The default is 60 requests per minute per key.
502A provider or upstream fetch failed in a way the run could not continue through.

Two things worth knowing before you debug

An origin whose robots.txt cannot be read is not crawled. If the file returns a server error, or the fetch fails, Seekyo treats that origin as disallowed and returns nothing from it. That is what RFC 9309 asks for, and it means a flaky robots.txt shows up as an empty result rather than a partial one.

The affordability check is conservative on purpose. Before any work starts, the estimate is multiplied by a safety factor (2 by default) and compared against maxCost and the balance. A request whose raw estimate fits can therefore still be refused. The error carries both figures and the multiplier, and the estimate reported to you is never inflated.

Prices

Each request is priced from what it did. These are the hosted service's current defaults, and a deployment can configure every one of them.

OperationPrice
Page fetched$0.0005
Page processed$0.0005
Semantic input tokens$0.24 per million
Platform fee$0.0005 per request

Questions asked are counted and reported in usage, but they are not billed. What they cost is billed as tokens, and pricing both would charge the same work twice.

A documentation crawl that reads two or three pages and stops as soon as it has the answer comes to roughly two cents. Credit is issued in advance, and a request will not start unless the balance covers it.

Crawler

Every page is fetched by a single identifiable crawler that respects robots.txt, honours noindex and nofollow, and honours a declared Crawl-delay. What it sends, and how to block it, is on the crawler page.