Files
2026-11-09 14:55:36 +03:30

6.7 KiB

REST API contract

Cross-origin browser access is allowed only from https://git.sadentel.net, with GET, POST and OPTIONS and the request headers X-API-Key, X-Viewer-Token and Content-Type (plus the framework's standard safelisted headers). Preflight OPTIONS requires no API key; POST authentication and private-read permissions remain enforced. Cookie credentials are not enabled. Authentication for upload is X-API-Key. Private reads accept the same service key or X-Viewer-Token, returned only at creation. The service uses one integration key, not multi-tenant user authentication. Use a gateway for organization-specific account roles, key rotation, quotas and rate limits.

POST /api/v1/schematics/render accepts exactly one multipart file field file, with .SchDoc suffix (case insensitive). The client-provided content type is not trusted. The request body is capped before multipart spooling, and extracted file bytes are separately capped. Initial format identification accepts OLE signature or an ASCII SchDoc header; complete structural/version validation runs asynchronously in an isolated worker.

Optional fields:

  • access: private (default) or unlisted.
  • expires_in: -1 for unlimited retention, or positive integer seconds up to LINK_TTL_SECONDS. Omit to use the configured finite default. 0 and values below -1 are invalid. Finite expiry starts at upload acceptance, including queue time.

HTTP 202 includes id, status, viewer_url, status_url, expires_at (Unix seconds, or -1 for no expiry), access, and a viewer_token for private uploads. Location points to status and Retry-After: 1 provides a polling interval. Do not automatically retry a POST after a transport failure: each accepted request creates a new resource. Idempotency keys are not implemented.

GET .../{id}/status returns HTTP 200 for existing, accessible, unexpired jobs, including failed jobs with success: false and a stable error.code. Failed artifacts return HTTP 422. Status does not disclose the original filename, source bytes or read token. The returned base viewer_url omits the original token: retain the initial URL or append your retained read token as a fragment.

Completed responses add schema_version, compatibility (partial / supported_subset), record_count, component_count, primitive_count, and diagnostics (severity, code, message, record id/type, count). Current font metric warnings mean typical documents are explicitly partial. Warnings must be checked by applications where accurate reproduction matters.

GET .../{id}/data returns the document schema from backend/app/models/schematic.py:

  • schema_version, document_type, id, filename, and metadata (source SHA-256, format/header, streams/counts).
  • sheet (original properties, page bounds/background), bounds (content bounds).
  • components / symbols / objects with ownership IDs, placement, raw properties, active visibility, pin anchors and primitive references.
  • primitives in source paint order (paths, text, sanitized embedded rasters).
  • diagnostics with compatibility failures/warnings. Raw properties are data, never executable DOM content.

Coordinates use 10 mil units, X to the right and Y downward (inverted once at parse time). The page begins at (0, -height) and ends at (width, 0). Page dimensions are independent of content bounds. Consumers should not rotate/mirror placed component children again.

GET .../{id}/svg uses the same document primitives and page dimensions as the viewer; it has no interaction code. The interactive /view/{id} loads it and changes only its camera viewBox. Wheel zoom retains the point beneath the cursor; pointer events support drag/pinch. Double-click or Home resets fit; +/− and arrows provide keyboard control. Browser zoom, exact font availability and gesture behavior need actual browser validation.

Error code examples:

HTTP Code
401 unauthorized
404 not_found (also private permission denied)
409 not_ready
410 link_expired (until retention cleanup)
413 upload_too_large
415 unsupported_file_type
422 invalid_request / invalid_expiry / invalid_schematic / parse_timeout / parse_resource_limit
503 queue_full / storage_unavailable / database_unavailable

A worker crash is retried after its lease expires, at most twice total. A parse failure is terminal for that upload. No automatic retry of side-effecting API requests is performed. Data and SVG reads are immutable after a successful attempt; access/expiry remain server-authoritative on every read. HTTP caches are disabled to protect private drawings.

Schematic comparisons

POST /api/v1/comparisons (alias /api/compare) accepts old_file and new_file, with the same API key, private tokens, expiry, durable queue and error conventions. GET /api/v1/comparisons/{id} (alias /api/compare/{id}) returns status and the completed structural diff. /compare/{id} opens the side-by-side workspace. See the comparison contract.

PCB preview and comparison

POST /api/v1/pcbs/render accepts file; POST /api/v1/pcbs/comparisons accepts old_file and new_file. Both require native .PcbDoc and reuse the existing asynchronous status, authentication, access and expiry conventions. They do not change schematic routes. See PCB API and read/viewer endpoints.

All four creation operations (and the schematic comparison alias) accept expires_in=-1. The initial response and every status response return expires_at: -1. This sentinel is stored in the existing non-null timestamp column; no schema migration is required. Unlimited jobs remain claimable, count toward pending queue limits, retain private-token authorization, and are excluded from automatic expiry cleanup in both local and S3 storage. Other finite expiry behavior is unchanged. This is durable storage retention, not permanent RAM residency. External administrator deletion or provider lifecycle policies can still remove objects.

The upload results and authenticated/accessible viewers provide a Share button. It reveals a copyable iframe snippet using the complete viewer URL, including the read-token fragment for a private design. Sharing that snippet shares read access; it does not make the job unlisted, expose the service API key or bypass CSP. The viewer recovers its token from the resource-specific browser session if the fragment was already removed. Embedding remains restricted to the service itself and https://git.sadentel.net.

<iframe
  src="https://render.sadentel.net/view/pcb/PCB_ID#token=READ_TOKEN"
  width="100%"
  height="800"
  title="Altium design viewer"
  loading="lazy"
  referrerpolicy="no-referrer"
  allowfullscreen
></iframe>