sign.ytDocs

Core concepts

Authentication and scopes

Every API request carries an organization API key as a Bearer token. A key belongs to exactly one organization and acts on behalf of the admin who created it.

Send the key#

GET /api/v1/documents HTTP/1.1
Host: sign.yt
Authorization: Bearer sk_live_9f2c...

Keys start with sk_live_. Requests without a valid key return 401 with code unauthenticated and a WWW-Authenticate: Bearer header. Use HTTPS only and never ship a key to a browser or mobile app; call the API from your server.

Create and manage keys#

  • Keys are created in the app under API keys by an organization admin. API keys cannot create other keys.
  • The full key is shown once. sign.yt stores only a SHA-256 hash and a short prefix for display, so a lost key cannot be recovered: revoke it and create a new one.
  • Each key has a name, one or more scopes and an optional expiry. Revoked or expired keys return 401.
  • API access is a plan feature (Business and Enterprise). If the organization's plan does not include it, every key request returns 402 with code feature_not_in_plan.

Scopes#

Scopes are checked centrally by path prefix and HTTP method, deny by default. GET and HEAD need the :read scope of the family; every other method needs :write. A :write scope does not imply :read, so grant both when you need both.

ScopeGrantsPath prefixes
documents:readGET/HEAD/api/v1/documents, /api/v1/lookup
documents:writePOST/PUT/PATCH/DELETE/api/v1/documents, /api/v1/lookup
templates:readGET/HEAD/api/v1/templates, /api/v1/template-catalog
templates:writePOST/PUT/PATCH/DELETE/api/v1/templates, /api/v1/template-catalog
webhooks:readGET/HEAD/api/v1/webhooks
webhooks:writePOST/PUT/PATCH/DELETE/api/v1/webhooks
webhooks:manageUmbrella (legacy, kept for existing keys)webhooks:read + webhooks:write
flows:readGET/HEAD/api/v1/flows, /api/v1/flow-runs
flows:writePOST/PUT/PATCH/DELETE/api/v1/flows, /api/v1/flow-runs
adminUmbrellaAll of the above, read and write

A request outside these prefixes (organization settings, billing, users, API keys, campaigns, smart document packages and other app-only areas) returns 403 with the message "API keys cannot access this endpoint". GET /api/v1/documents/inbox is personal to a logged-in user and is also blocked for keys. A key that lacks the needed scope gets:

{
  "code": "insufficient_scope",
  "message": "Missing scope documents:write",
  "detail": "Missing scope documents:write",
  "request_id": "9f2c1a7e4b0d3e11"
}

Effective permissions#

A key's identity is the pair (key creator, key organization). What a request may do is the intersection of the key's scopes and the creator's current role in that organization:

  • Role-gated endpoints apply the creator's role. For example, webhooks require the creator to be an organization admin, even with webhooks:manage.
  • The key stops working (401) when the organization is deleted, when the creator leaves the organization or is locked, or when the key is revoked or expires. Rotate keys owned by people who leave.
  • Platform-level roles of the creator are never carried by a key.
  • Documents are visible to a key the same way they are visible to its creator in the app (team and folder access rules apply).

Tenancy and custom domains#

All data is scoped to the key's organization. Resources of other organizations are reported as 404 not_found, never 403, so the API does not reveal whether an ID exists elsewhere.

The API is served on https://api.sign.yt/v1 (also reachable as https://sign.yt/api/v1) and also on each organization's custom domain (for example https://sign.example.com/api/v1). On a custom domain the key must belong to that domain's organization, otherwise the request is rejected with 403. Using https://api.sign.yt/v1 everywhere is the simplest choice. That host accepts API keys only; browser session cookies are ignored there.

Restrict a key to IP addresses#

A key can carry an allowlist of IP addresses or CIDR ranges. Requests from any other address are rejected before the scope check and do not update the key's last-used time. Leave the list empty to accept any address (the default).

  • Set it under API keys when creating a key, or edit it later (pencil icon). Admins see their current IP next to the field.
  • IPv4 and IPv6 addresses and CIDR ranges, one per entry, up to 50 per key (for example 203.0.113.7, 10.0.0.0/24, 2001:db8::/32). Host bits are normalized away. 0.0.0.0/0 and ::/0 are rejected: leave the list empty instead.
  • IPv4-mapped IPv6 addresses (::ffff:203.0.113.7) are treated as the IPv4 address.
  • The address is the one sign.yt sees for your connection. Proxy headers such as X-Forwarded-For sent by clients are ignored, so they cannot be used to bypass the list. If you call from behind a NAT or a proxy, allow its public egress address.
  • Each blocked address is recorded in the organization's audit log (API_KEY_IP_DENIED), at most once per ten minutes per key and address. Changes to the list are audited too.
{
  "code": "ip_not_allowed",
  "message": "Requests from IP 198.51.100.4 are not allowed for this API key",
  "detail": "Requests from IP 198.51.100.4 are not allowed for this API key",
  "request_id": "9f2c1a7e4b0d3e11"
}

Key hygiene#

  • One key per integration and environment, with the smallest set of scopes it needs.
  • Set an expiry for keys used by contractors or short projects.
  • Keys are bearer secrets: keep them out of source control, logs, URLs and client-side code.
  • Each key is limited to 100 requests per second; see Rate limits.