Skip to content
Sursa Developers

Changelog

Changes of the public Sursa API by version. Each version is additive unless its entry says otherwise: new endpoints, fields, enum values, error codes and event types can appear in any version, so skip what you do not know.

1.62.0 — Unreleased

Added

  • API address. An installation can serve the public API on its own address, for example https://api.example.com. On that address only public endpoints answer, requests are authenticated with API keys only (browser cookies are ignored) and CORS is open to any origin without credentials. servers of the public specification (/openapi.json and GET /v1/openapi-public.json) carries the API address of the installation.
  • `GET /v1/me` returns who is calling: the organization, the API key (never its value), the user, the role, the scopes, the data profile, the expiry and the rate limit class of the key. Any key scope can call it.
  • Idempotency. 43 POST and PATCH endpoints accept an Idempotency-Key header (1–255 printable ASCII characters). A retry with the same key within 24 hours returns the saved status, headers and body with Idempotency-Replayed: true instead of running the request again. 2xx and 4xx responses are saved, except 429; after a 5xx or 429 the key can be used again. New error codes: api.idempotency_key_invalid (400), api.idempotency_mismatch (409, the same key with another method, path, content type or body) and api.idempotency_in_progress (409 with Retry-After: 1, the first request is still running).
  • Rate limit headers. Responses carry RateLimit-Policy and RateLimit (IETF draft draft-ietf-httpapi-ratelimit-headers) next to X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset, which now show the strictest of the limits.
  • Plan quotas. A request above the per-minute, per-day or per-month quota of the plan gets 429 api.quota_exceeded with details.quota, details.limit, details.reset_at and details.retry_after, and a Retry-After header until the end of the window.
  • Event feed. GET /v1/webhook-events lists the events of the organization for 30 days, whether or not a webhook endpoint was subscribed, and GET /v1/webhook-events/{event_id} reads one. Filters: type (repeatable, masks such as card.*), object_type, object_id, created_since, created_until; pagination with limit and cursor. The response is {data, next_cursor, has_more}, and next_cursor is always present, so you can keep polling from the same place. New schemas WebhookEvent, WebhookEventObject and WebhookEventList; new error codes events.not_found (404) and api.cursor_invalid (400).
  • Cards by your own ID. GET /v1/cards-by-external-id/{external_id} reads a card by the external_id of your system, and PUT on the same path creates the card (201) or replaces its content with a new version (200); unchanged content is reported as skipped without a new version. PUT /v1/cards/{card_id}/content replaces the content of a card with new text or a new file.
  • Metadata. Cards, collections and folders have external_id (cards) and metadata: up to 50 key-value pairs, keys of 1–40 characters [A-Za-z0-9_.-], values up to 500 characters, up to 8 KiB in all. PATCH merges keys; "" or null removes a key.
  • Text cards. POST /v1/cards/text accepts body with content_type markdown, html or text (HTML is cleaned), and collection_id, folder_id, external_id and metadata. File uploads (POST /v1/cards) accept collection_id, external_id and metadata; archive uploads accept collection_id.
  • Sync filters. GET /v1/cards and GET /v1/cards/count accept updated_since, metadata[<key>]=<value> (up to three conditions), collection_id and external_id.
  • Developer portal in every installation. The API reference, guides, error codes and this changelog are served at /developers/ of the installation, without internet access; GET / of the API address redirects there, and so does the former /docs page. The doc_url of an error leads to the page of its code.
  • Failed jobs. result.failed_phase of a job names the processing phase where it failed, with the same values as phase.
  • New error codes: api.not_found (404, a path that is not part of the API), api.metadata_invalid (400), cards.external_id_taken (409), cards.managed_by_source (409) and cards.content_whole_access (403).

Changed

  • Responses are in English only: error responses no longer carry a translated message, error.details.params holds the values substituted into the message, and clients translate by error.code with the error code catalog.
  • POST /v1/users/{user_id}/offboard can be called with an API key with the admin role and the admin scope.
  • POST /v1/cards/text no longer requires body_markdown: send body or body_markdown.
  • Webhook deliveries no longer lose events when a change and its delivery are interrupted, and a paused endpoint receives the events of the pause in order after it is resumed. The payloads of the existing events are unchanged.
  • Responses of cards, collections and folders have the new fields external_id and metadata.
  • A request with Idempotency-Key that the client drops before the response (a timeout or a lost connection) still completes, and its response is saved: a retry with the same key gets 409 api.idempotency_in_progress while it runs and then the saved response, instead of running again and creating a second object.
  • A synchronous upload (async: false on POST /v1/cards/text, POST /v1/cards, PUT /v1/cards-by-external-id/{external_id} and PUT /v1/cards/{card_id}/content) that stops waiting for indexing because the client left or the server is restarting answers like an asynchronous one: status: queued with the card and the job, as it already did when the wait time ran out.
  • In a 429 api.rate_limited response the remaining count in RateLimit and X-RateLimit-Remaining is 0.
  • SourceTrigger (triggered_by in last_run and running of a source) lists push: a run started by a change notification from the provider or by data sent to a custom source through the API. The server already returned this value; the specification now describes it and every value of the enum. A run started by a collection reindex is manual.
  • On the API address, responses contain only what the public specification describes, in every endpoint, in expand[] objects, in the events of POST /v1/chat and GET /v1/jobs/stream and in a replayed Idempotency-Key response. A stage event with a value that the specification does not list is not sent; its event number stays used, and resuming with Last-Event-ID works as before. The error event with assistant.unavailable has no details.legacy_code. The main address of the installation keeps its responses.
  • On the API address, objects of a response carry only the fields that the public specification describes for them.
  • A failed table query of an answer is reported by the warning kind table_query_failed.
  • Conversations (ConversationPublic) have the new field quality: the answer mode of the conversation (fast or precise), present when the mode is set.
  • GET /v1/questions/export.csv: the “Answer time, s” column shows the total time of the answer (timings.total_s), the same as the question details; it no longer adds the stage times to it.
  • New error code 409 collections.index_outdated: the index of the collection is outdated, so the card cannot be added or re-indexed until the index is updated with PATCH /v1/collections/{name} and upgrade_index: true.
  • On the API address, exports follow the public specification too: GET /v1/questions/export.csv and the card list in XLSX have no columns for fields that the specification does not describe, and answer documents are titled with the question itself.

Plan features

  • API keys of an organization work only while its plan includes API access (403 api_keys.feature_disabled), and webhook endpoints and the event feed only while it includes webhooks (403 webhooks.feature_disabled). Organizations that already used API keys or webhooks keep them.