---
title: "Publish a template as a public link"
method: POST
path: "/presets/{id}/share"
---

# Publish a template as a public link

`POST /presets/{id}/share`

## Request

- Base URL: `https://rendry.io/api/v1`
- URL: `https://rendry.io/api/v1/presets/{id}/share`
- Auth: one of:
  - HTTP bearer
  - HTTP bearer
  - HTTP bearer

Returns a stable URL that renders the template for anyone, no key required. The most expensive decision available: a published link cannot be recalled from the internet, only disabled for future requests. Spending is bounded: repeat hits are served from cache and cost nothing, while NEW combinations of query values are capped at 200 renders a day per link for a small canvas (fewer for costlier canvases — the cap is set in credits, not pictures). The exact number for this link comes back as daily_render_budget. Past it the public URL answers 429 with error url_link_budget_exhausted, charges nothing, and keeps serving every variant already in cache. For a template that computes some of its values the reply also carries variables (the query parameters a visitor's page passes) and inputs (InputDescriptor: what the template computes from them); a query parameter named after a computed value overrides it.

## Path parameters

- `id` string, required

## Headers

- `X-Rendry-Account` string

## Request body

- object
  - `enabled` boolean: true or absent opens the link; false closes it — the public URL stops working immediately and the reply is {"enabled": false}
  - `rotate` boolean: true issues a NEW url and kills the previous one (rotated:true in the reply); every place the old link was pasted stops working

## Response `200`

The link's state: {enabled:true, url, rotated, daily_render_budget, …} when open, {enabled:false} when closed

- ShareLink: The public link of a template, as POST and GET /presets/{id}/share report it.
  - `enabled` boolean, required: true while the link is open; {enabled: false} is the whole reply of a closed link
  - `url` string: Path of the public picture, /u/{token}.png — prefix https://rendry.io; absent while closed. Template variables go on as query parameters (`example` shows this template's own); a parameter named after a computed value overrides it
  - `daily_render_budget` integer: NEW pictures this link may render a day; cached variants are free
  - `rotated` boolean: POST only: true when rotate: true issued a NEW url and killed the previous one; false when the reply re-reports the live url (opening an open link never replaces it)
  - `hint` string: POST only: how to use the link
  - `example` string: POST only: the url with this template's own first variable and its sample as a query parameter (the same example share_preset_url gives); the bare url when the template has no variables
  - `inputs` InputDescriptor[]: Present for a template that computes some of its values (a template or formula definition): the class, mode and dependencies of every name. Absent otherwise.
    - `name` string, required
    - `class` 'required' | 'defaulted' | 'computed' | 'fact', required: required: referenced and never authored — send it, or the render refuses. defaulted: an authored text a caller may replace. computed: a template or formula the template evaluates; a literal a caller sends replaces it for that call and cuts its dependencies. fact: page or pages, the engine's — cannot be supplied.
    - `mode` 'text' | 'template' | 'formula': The authored mode of a definition; absent for a name that has none.
    - `dependencies` string[]: The names a computed definition references, sorted.
    - `used` boolean, required: Content reaches this name, directly or through computed definitions. An unused authored definition is still listed: removing one is an explicit act. Not what a render needs: every template and formula is evaluated on every render, drawn or not, so a required name that only an undrawn definition reads is still required and is listed in `variables`.
    - `format` DisplayFormat: One deterministic display vocabulary. Numbers use exact arithmetic and half away from zero rounding. Currency needs symbol (a symbol or ISO code), with explicit spacing in that text. Percent multiplies a raw ratio by 100. Dates accept strict YYYY-MM-DD only and patterns D, DD, M, MM, MMM, MMMM, YY, YYYY with English month names. upper/lower use Unicode simple case mapping; no locale or multi-character expansions. No format leaves existing text untouched. Fields unrelated to the selected type are refused.
      - `type` 'number' | 'currency' | 'percent' | 'date' | 'upper' | 'lower', required
      - `decimals` integer
      - `grouping` boolean
      - `decimal_mark` string
      - `group_mark` string
      - `symbol` string
      - `symbol_position` 'prefix' | 'suffix'
      - `prefix` string
      - `suffix` string
      - `pattern` string
  - `variables` string[]: Present with inputs: the names a caller supplies — not the computed ones, which a value sent under their name overrides for the call.

## Other responses

- `403`: API key scope does not allow publishing
- `404`: `preset_not_found`. A key this door does not read is refused 400 `unknown_field` (a near miss is renamed and reported in `autofixes`).

---

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