---
title: "Create a signed link"
method: POST
path: "/v1/signed-links"
tags: ["Signed links"]
---

# Create a signed link

`POST /v1/signed-links`

## Request

- Base URL: `https://api-eu.dynamicdocumentapi.com`
- URL: `https://api-eu.dynamicdocumentapi.com/v1/signed-links`
- Auth: one of:
  - HTTP bearer
  - API key in header `X-API-Key`

Returns `base_url` and the HMAC `secret` **once**; SDKs sign URLs locally with it. Use `access: "open"` for tools that cannot compute an HMAC.

## Headers

- `Idempotency-Key` string

## Request body

- SignedLinkWrite
  - `access` 'signed' | 'open': `open` accepts unsigned requests within `allowed_params` and `param_limits`. * `signed` - signed * `open` - open
  - `allowed_params` string[]: Dynamic properties callers may set, e.g. `title.text`.
  - `allowed_referrers` string[]
  - `cache_ttl_seconds` integer, nullable
  - `defaults` object
  - `enabled` boolean
  - `expires_at` string, date-time, nullable
  - `fallback_image_asset_id` string, nullable: Ready image asset (`ast_…`) returned instead of 402 `render_limit_reached`; null clears.
  - `formats` string[], required
  - `name` string, required
  - `param_limits` object
  - `quota_total` integer, nullable
  - `rate_limit_per_ip_per_hour` integer, nullable
  - `template_id` string, required

## Response `201`

Created; `secret` is shown once.

- SignedLinkWithSecret: Create response: the HMAC secret SDKs sign with locally is returned once.
  - `access` 'signed' | 'open', required: * `signed` - signed * `open` - open
  - `allowed_params` string[], required
  - `allowed_referrers` string[], nullable, required
  - `base_url` string, uri, required: Append `/{any-name}.{ext}?…` and a signature.
  - `cache_ttl_seconds` integer, nullable, required
  - `created_at` string, date-time, required
  - `defaults` object, required: Parameter values used when the URL omits them.
  - `enabled` boolean, required
  - `expires_at` string, date-time, nullable, required
  - `fallback_image_asset_id` string, nullable, required: `ast_…`: image served instead of 402 `render_limit_reached`.
  - `formats` string[], required
  - `id` string, required: `lnk_…`
  - `name` string, required
  - `object` string
  - `param_limits` object, required: e.g. `{"title.text": {"max_length": 80}}`.
  - `quota_total` integer, nullable, required
  - `quota_used` integer, required
  - `rate_limit_per_ip_per_hour` integer, nullable, required
  - `secret` string, required: base64url HMAC-SHA256 key. Shown once.
  - `template_id` string, required

## Other responses

- `400`: Invalid request body (`errors[]` with JSON pointers).
- `401`: Missing, invalid, expired or revoked credentials.
- `403`: Insufficient scope, IP not allowed, workspace suspended or scheduled for deletion, or email not verified.
- `404`: Template not found.
- `429`: Rate limited (`Retry-After`).
- `503`: The control plane is unreachable (`Retry-After`).

---

[API](https://skmtc.dev/dynamicdocumentapi/apis/dynamic-document-api.md) · [All operations](https://skmtc.dev/dynamicdocumentapi/apis/dynamic-document-api/llms.txt) · [OpenAPI document](https://skmtc.dev/dynamicdocumentapi/apis/dynamic-document-api/revisions/0f14bc0000f4?raw)
