Skip to content
PacSpace
Talk to us

SDK overview

Two SDKs, TypeScript and Python, with the same four records calls and the fingerprint helper. What each one needs, how errors and retries reach your agent's code, and where the two differ.

Both SDKs wrap the same records API and speak in the same words: record is your id for a record, entry is an entry's number counted from 1, as every page counts it, and the SDK maps them to the wire's entityId and seq for you. On the wire seq counts the same positions from 0; the SDK converts at its boundary, so you never send a seq, and an entry below 1 is refused before anything is sent. The history file and the webhook payloads keep the wire's seq; add 1 to get the entry. If your code passed the wire's numbers to an SDK before 0.11.0 or 0.4.0, add 1.

Put the calls where your system already logs what an agent did, such as the harness or the tool router, so the key stays with your code and the agent never holds it.

TypeScriptPython
Package@pacspace-io/sdk on npmpacspace-sdk on PyPI
Version these docs are written to0.12.00.5.0
NeedsNode.js 20.19 or laterPython 3.10 or later; the calls on these pages use only the standard library
Hosthttps://app.pacspace.io, chosen by the keyThe same
LicenseMITMIT

What both carry

CallWhat it doesPage
fingerprint(...)Fingerprints a file, bytes, or a stream where it lives. Nothing leaves.Fingerprint a file
records.emit(...)Writes one entry.Write an entry
records.history(...)Reads the record's history file.History
records.receipt(...)Reads one committed entry's receipt.Receipts
records.check(...)Checks a history from your code.Check
webhooks.verify(...), webhooks.verifyFromHeaders(...)Checks a webhook delivery's signature before you act on it.Signature verification

Sharing a record is a plain HTTP call in both languages today; see Share a record.

Where they differ

The check. The TypeScript records.check runs the whole check in your process: every seal, the order of entries, and the file's own fingerprint. The Python records.check compares the files and fingerprints you hold with the committed ones and reads each entry's status; it does not recompute the seals. From Python, hand the history file to the standalone checker, npx @pacspace-io/check history.json, for the whole check.

Chosen fields. TypeScript has records.disclose, which builds a file that shows only the fields you choose of chosen entries. Python has verify_record_link_copy_v1 and verify_record_disclosure_v1, which check such a file's shown fields against the record's seal history without recomputing the seals.

Return values. TypeScript returns typed objects in the SDK's words. Python returns plain dicts carrying the wire's field names, so a Python answer has entityId and seq where the TypeScript one has typed fields.

Webhook middleware. TypeScript has webhooks.middleware() for Express-style servers. Python has verify and verify_from_headers and leaves the framework to you.

A write that keeps failing. TypeScript holds it and keeps sending it in the background; Python raises the error. See below.

Errors

Both raise one family, PacSpaceError, with the HTTP status in statusCode (status_code in Python), a code, and the API's message. Which code you read depends on the answer:

The API answersThe SDKs raisecode
400 with a code, 403, 409, 413, 422, or 500PacSpaceErrorThe API's code, exactly as the registry names it, such as RECORD_TITLE_TOO_LONG.
400 with no code: a body the route could not readValidationErrorThe SDK's own.
401InvalidApiKeyErrorThe SDK's own.
402, such as PLAN_LIMIT_REACHEDInsufficientCreditsErrorThe SDK's own.
404, such as RECORD_NOT_FOUNDNotFoundErrorThe SDK's own.
412, such as RECORDS_CONTRACT_NOT_READYContractNotDeployedErrorThe SDK's own.
429 RATE_LIMIT_EXCEEDEDRateLimitError, with the wait in retryAfter (retry_after)The SDK's own.
503ServiceUnavailableErrorThe SDK's own.
No answer: the host could not be reached, or the request timed outPacSpaceError with statusCode 0The SDK's own.

Where the SDK raises its own class, the class names the case and message carries the API's sentence; the API's code is not passed on. The SDKs also raise ValidationError themselves, before anything is sent: for an entry below 1, and for a blinding file that does not belong to the bytes. records.check never raises on a failed check; the result names what failed. IDEMPOTENCY_PENDING is returned, never raised.

Retries and timeouts

Both SDKs send a request again after a network error or a timeout, or an answer of 408, 429, 500, 502, 503, or 504: twice by default (maxRetries, max_retries). A 429 or a 503 that names its wait in retryAfterSeconds is sent again after exactly that wait; otherwise the wait grows between tries. Each request times out after 30 seconds (timeout, in milliseconds). In TypeScript, records.history and records.disclose are sent once, without these retries, and a network failure there reaches you as the runtime's own error.

When a write still fails after its retries, TypeScript holds it in memory and keeps sending it in the background (bufferWrites, on by default), so the records.emit promise settles only when the write lands or the SDK gives up. An agent loop that must not wait on it can set bufferWrites: false and handle the error. Python raises the error after its retries.

A write is safe to send again because one idempotency key is one write: a retry of a finished write returns the original answer, and a retry while the first is still running returns IDEMPOTENCY_PENDING with retryAfterSeconds, which the SDKs return rather than raise.

What else is in the package

Both SDKs also expose balance and customers, used by another PacSpace product. They are outside these docs.