REST API
Resources
Resources: 15 endpoints of the REST API.
/resource-typesList resource types
Resource types of this environment, newest first. Archived ones are left out unless status=archived.
Secret key scope (any of): links:read, links:write
Parameters
| Field | Type | Description |
|---|---|---|
limit (query) | integer | Items per page (1–100). |
cursor (query) | string |
|
status (query) | "active" | "archived" | Only types with this status. Archived types are left out by default. |
Responses
200 A page of resource types.
| Field | Type | Description |
|---|---|---|
datarequired | object[] | |
data[].idrequired | string | |
data[].keyrequired | string | |
data[].namerequired | string | |
data[].statusrequired | "active" | "archived" | |
data[].created_atrequired | string (date-time) | |
data[].updated_atrequired | string (date-time) | |
next_cursorrequired | string | null | Pass as |
Example
curl -X GET "https://api.becklinks.com/v1/resource-types" \
-H "Authorization: Bearer $SECRET_KEY"/resource-typesCreate a resource type
Defines something you share through URL templates, for example challenge. The key is used in payloads and cannot be changed. An environment can have 20 resource types.
Secret key scope (any of): links:write
Request body
| Field | Type | Description |
|---|---|---|
keyrequired | string | Stable machine name (for example |
namerequired | string |
Responses
201 The new resource type.
| Field | Type | Description |
|---|---|---|
idrequired | string | |
keyrequired | string | |
namerequired | string | |
statusrequired | "active" | "archived" | |
created_atrequired | string (date-time) | |
updated_atrequired | string (date-time) |
Example
curl -X POST "https://api.becklinks.com/v1/resource-types" \
-H "Authorization: Bearer $SECRET_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"key":"string","name":"string"}'/resource-types/{type}Get a resource type
One resource type, archived ones included.
Secret key scope (any of): links:read, links:write
Parameters
| Field | Type | Description |
|---|---|---|
type (path)required | string | The ID of the resource type. |
Responses
200 The resource type.
| Field | Type | Description |
|---|---|---|
idrequired | string | |
keyrequired | string | |
namerequired | string | |
statusrequired | "active" | "archived" | |
created_atrequired | string (date-time) | |
updated_atrequired | string (date-time) |
Example
curl -X GET "https://api.becklinks.com/v1/resource-types/{type}" \
-H "Authorization: Bearer $SECRET_KEY"/resource-types/{type}Update a resource type
Renames a resource type or archives it (status: archived). Templates of an archived type stop resolving; their patterns stay reserved. The key cannot change.
Secret key scope (any of): links:write
Parameters
| Field | Type | Description |
|---|---|---|
type (path)required | string | The ID of the resource type. |
Request body
| Field | Type | Description |
|---|---|---|
name | string | |
status | "active" | "archived" | Archive a type to stop its templates resolving; its key stays taken. |
Responses
200 The updated resource type.
| Field | Type | Description |
|---|---|---|
idrequired | string | |
keyrequired | string | |
namerequired | string | |
statusrequired | "active" | "archived" | |
created_atrequired | string (date-time) | |
updated_atrequired | string (date-time) |
Example
curl -X PATCH "https://api.becklinks.com/v1/resource-types/{type}" \
-H "Authorization: Bearer $SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{}'/resource-types/{type}/metadata-apiGet the metadata API of a resource type
The endpoint, field mapping and cache settings. The credential is never returned: auth.secret_set says whether one is stored and auth.secret_hint shows its last characters.
Secret key scope (any of): links:read, links:write
Parameters
| Field | Type | Description |
|---|---|---|
type (path)required | string | The ID of the resource type. |
Responses
200 The configuration.
| Field | Type | Description |
|---|---|---|
idrequired | string | |
resource_type_idrequired | string | |
statusrequired | "active" | "disabled" | |
url_templaterequired | string | |
authrequired | object | |
auth.typerequired | "none" | "bearer" | "api_key_header" | |
auth.header_namerequired | string | null | |
auth.secret_setrequired | boolean | |
auth.secret_hintrequired | string | null | The last characters of the stored credential, to tell keys apart. |
headersrequired | object | |
timeout_msrequired | integer | |
ttl_secondsrequired | integer | |
negative_ttl_secondsrequired | integer | |
stale_if_error_secondsrequired | integer | |
max_concurrencyrequired | integer | |
max_requests_per_minuterequired | integer | |
field_mappingrequired | object | |
field_mapping.title | string | |
field_mapping.description | string | |
field_mapping.image_url | string | |
field_mapping.canonical_url | string | |
field_mapping.deep_link_path | string | |
field_mapping.web_fallback_url | string | |
field_mapping.resource_status | string | |
field_defaultsrequired | object | |
field_defaults.title | string | |
field_defaults.description | string | |
field_defaults.image_url | string | |
field_defaults.canonical_url | string | |
field_defaults.deep_link_path | string | |
field_defaults.web_fallback_url | string | |
required_fieldsrequired | "title" | "description" | "image_url" | "canonical_url" | "deep_link_path" | "web_fallback_url"[] | |
status_valuesrequired | object | |
status_values.published | string[] | |
status_values.unpublished | string[] | |
status_values.deleted | string[] | |
allowed_image_hostsrequired | string[] | |
created_atrequired | string (date-time) | |
updated_atrequired | string (date-time) |
Example
curl -X GET "https://api.becklinks.com/v1/resource-types/{type}/metadata-api" \
-H "Authorization: Bearer $SECRET_KEY"/resource-types/{type}/metadata-apiSet the metadata API of a resource type
Creates or replaces the configuration (one per resource type). url_template is an https URL on a public host name with {type} and {id} in the path or query. Previews of this type then show each item’s own title, description and image from your API: it is called only for link-preview bots, its answers are cached, and a failing API never slows a visitor down. Omit auth.secret to keep the stored credential.
Secret key scope (any of): links:write
Parameters
| Field | Type | Description |
|---|---|---|
type (path)required | string | The ID of the resource type. |
Request body
| Field | Type | Description |
|---|---|---|
status | "active" | "disabled" |
|
url_templaterequired | string | HTTPS URL of your metadata endpoint, with {type} and {id} in the path or query, for example |
auth | object | |
headers | object | Extra, non-secret request headers. |
timeout_ms | integer | |
ttl_seconds | integer | How long an answer is used without asking again. |
negative_ttl_seconds | integer | How long a 404 or 410 ("no such item") is remembered. |
stale_if_error_seconds | integer | How long past its TTL an answer may still be shown when your API fails. |
max_concurrency | integer | |
max_requests_per_minute | integer | |
field_mappingrequired | object | |
field_mapping.title | string | |
field_mapping.description | string | |
field_mapping.image_url | string | |
field_mapping.canonical_url | string | |
field_mapping.deep_link_path | string | |
field_mapping.web_fallback_url | string | |
field_mapping.resource_status | string | |
field_defaults | object | |
field_defaults.title | string | |
field_defaults.description | string | |
field_defaults.image_url | string | |
field_defaults.canonical_url | string | |
field_defaults.deep_link_path | string | |
field_defaults.web_fallback_url | string | |
required_fields | "title" | "description" | "image_url" | "canonical_url" | "deep_link_path" | "web_fallback_url"[] | |
status_values | object | |
status_values.published | string[] | |
status_values.unpublished | string[] | |
status_values.deleted | string[] | |
allowed_image_hosts | string[] | Hosts an image may come from. An image on any other host is left out of the card. |
Responses
200 The saved configuration.
| Field | Type | Description |
|---|---|---|
idrequired | string | |
resource_type_idrequired | string | |
statusrequired | "active" | "disabled" | |
url_templaterequired | string | |
authrequired | object | |
auth.typerequired | "none" | "bearer" | "api_key_header" | |
auth.header_namerequired | string | null | |
auth.secret_setrequired | boolean | |
auth.secret_hintrequired | string | null | The last characters of the stored credential, to tell keys apart. |
headersrequired | object | |
timeout_msrequired | integer | |
ttl_secondsrequired | integer | |
negative_ttl_secondsrequired | integer | |
stale_if_error_secondsrequired | integer | |
max_concurrencyrequired | integer | |
max_requests_per_minuterequired | integer | |
field_mappingrequired | object | |
field_mapping.title | string | |
field_mapping.description | string | |
field_mapping.image_url | string | |
field_mapping.canonical_url | string | |
field_mapping.deep_link_path | string | |
field_mapping.web_fallback_url | string | |
field_mapping.resource_status | string | |
field_defaultsrequired | object | |
field_defaults.title | string | |
field_defaults.description | string | |
field_defaults.image_url | string | |
field_defaults.canonical_url | string | |
field_defaults.deep_link_path | string | |
field_defaults.web_fallback_url | string | |
required_fieldsrequired | "title" | "description" | "image_url" | "canonical_url" | "deep_link_path" | "web_fallback_url"[] | |
status_valuesrequired | object | |
status_values.published | string[] | |
status_values.unpublished | string[] | |
status_values.deleted | string[] | |
allowed_image_hostsrequired | string[] | |
created_atrequired | string (date-time) | |
updated_atrequired | string (date-time) |
Example
curl -X PUT "https://api.becklinks.com/v1/resource-types/{type}/metadata-api" \
-H "Authorization: Bearer $SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{"url_template":"string","field_mapping":{}}'/resource-types/{type}/metadata-api/testTest the metadata API with a real item
Calls your API for the item id with the saved configuration and reports what came back: the HTTP status, the time it took, the metadata that was read, and why anything was left out. Nothing is cached or counted.
Secret key scope (any of): links:write
Parameters
| Field | Type | Description |
|---|---|---|
type (path)required | string | The ID of the resource type. |
Request body
| Field | Type | Description |
|---|---|---|
idrequired | string | The id of a real item to ask your API for. |
Responses
200 The result of the call.
| Field | Type | Description |
|---|---|---|
outcomerequired | "ok" | "missing" | "invalid" | "error" | "skipped" |
|
reasonrequired | string | null | A short stable code for invalid and error. |
statusrequired | integer | null | The HTTP status your API answered. |
latency_msrequired | integer | null | |
request_urlrequired | string | null | The URL that was called, with the sample id filled in. Never includes a credential. |
metadatarequired | object | null | |
warningsrequired | object[] | |
warnings[].fieldrequired | string | |
warnings[].coderequired | string | |
warnings[].detailrequired | string | |
issuesrequired | object[] | |
issues[].fieldrequired | string | |
issues[].coderequired | string | |
issues[].detailrequired | string |
Example
curl -X POST "https://api.becklinks.com/v1/resource-types/{type}/metadata-api/test" \
-H "Authorization: Bearer $SECRET_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"id":"string"}'/resources/invalidateInvalidate remembered metadata
Call it when items changed or were deleted in your system. Beck Link forgets what it remembered about them (up to 1,000 ids per call), so the next link preview asks your metadata API again. Link previews that chat apps and social networks already stored are refreshed by those services, not by this call.
Secret key scope (any of): links:write
Request body
| Field | Type | Description |
|---|---|---|
resource_typerequired | string | The key of the resource type, for example |
idsrequired | string[] | The ids of the changed items, at most 1000. |
Responses
200 How many were removed.
| Field | Type | Description |
|---|---|---|
resource_typerequired | string | |
requestedrequired | integer | How many ids were sent. |
removedrequired | integer | How many of them had a remembered answer that is now gone. |
Example
curl -X POST "https://api.becklinks.com/v1/resources/invalidate" \
-H "Authorization: Bearer $SECRET_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"resource_type":"string","ids":["string"]}'/resources/previewPreview a shared URL
Resolves a URL such as https://shop.becklinks.com/c/4521 to its template and item, asks your metadata API for it right now, and returns the card a link-preview bot would see together with the state of the shared cache.
Secret key scope (any of): links:read, links:write
Request body
| Field | Type | Description |
|---|---|---|
pathrequired | string | A shared URL or path such as |
Responses
200 The preview.
| Field | Type | Description |
|---|---|---|
resultrequired | "match" | "invalid_id" | "no_template" | |
resourcerequired | object | null | |
metadata_apirequired | "active" | "disabled" | "none" | |
fetchrequired | object | null | |
cacherequired | object | |
cache.staterequired | "none" | "fresh" | "stale" | "missing" | |
cache.fetched_atrequired | string (date-time) | null | |
cache.expires_atrequired | string (date-time) | null | |
cardrequired | object | |
card.kindrequired | "item" | "unavailable" | "generic" |
|
card.titlerequired | string | null | |
card.descriptionrequired | string | null | |
card.image_urlrequired | string | null | |
card.large_imagerequired | boolean | |
detailrequired | string |
Example
curl -X POST "https://api.becklinks.com/v1/resources/preview" \
-H "Authorization: Bearer $SECRET_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"path":"string"}'/resources/statsGet the analytics of resource links
Per resource type: non-bot clicks, the most clicked items, how link previews were answered (cache hit rate) and how your metadata API behaved (calls, errors, latency) over the last 7 or 30 project-local days. Item clicks are read from the raw click log; API figures are flushed every few seconds, so the newest minutes may be missing.
Secret key scope (any of): analytics:read
Parameters
| Field | Type | Description |
|---|---|---|
range (query) | "7d" | "30d" | The last 7 or 30 project-local days, today included. Default |
Responses
200 The analytics.
| Field | Type | Description |
|---|---|---|
rangerequired | "7d" | "30d" | |
fromrequired | string (date) | First day of the range (project-local). |
torequired | string (date) | Last day of the range, today (project-local). |
timezonerequired | string | |
typesrequired | object[] | |
types[].resource_typerequired | string | The key of the resource type. |
types[].clicksrequired | integer | Non-bot clicks on items of this type. |
types[].top_itemsrequired | object[] | The 10 most clicked items. |
types[].top_items[].idrequired | string | The item id as it appeared in the URL. |
types[].top_items[].clicksrequired | integer | Non-bot clicks on this item. |
types[].previewsrequired | object | |
types[].previews.servedrequired | integer | Link previews built for bots and social apps. |
types[].previews.from_memoryrequired | integer | Answered from the memory of a redirect process. |
types[].previews.from_databaserequired | integer | Answered from the shared cache. |
types[].previews.from_negative_cacherequired | integer | Answered from a remembered "item not found". |
types[].previews.stalerequired | integer | Answered with an expired copy while the API was refreshed or failing. |
types[].previews.fallbackrequired | integer | Answered with the generic card (no item data available). |
types[].previews.cache_hit_raterequired | number | null | Share of previews that did not call your API; null without previews. |
types[].metadata_apirequired | object | |
types[].metadata_api.callsrequired | integer | Calls to your metadata API. |
types[].metadata_api.okrequired | integer | Calls that returned an item. |
types[].metadata_api.missingrequired | integer | Calls that said the item does not exist. |
types[].metadata_api.errorsrequired | integer | Calls that failed (HTTP error or network). |
types[].metadata_api.timeoutsrequired | integer | Calls that ran out of time. |
types[].metadata_api.invalidrequired | integer | Calls whose answer could not be used. |
types[].metadata_api.breaker_openrequired | integer | Calls skipped because the circuit breaker was open. |
types[].metadata_api.throttledrequired | integer | Calls skipped by the concurrency or per-minute limit. |
types[].metadata_api.error_raterequired | number | null | |
types[].metadata_api.avg_latency_msrequired | integer | null | |
types[].metadata_api.p95_bucketrequired | "lt_100" | "lt_300" | "lt_1000" | "ge_1000" | null | The latency bucket that holds the 95th percentile (a rough value by design). |
Example
curl -X GET "https://api.becklinks.com/v1/resources/stats" \
-H "Authorization: Bearer $SECRET_KEY"/url-templatesList URL templates
Templates of this environment, newest first. Filter by resource_type_id and status; archived ones are left out unless status=archived.
Secret key scope (any of): links:read, links:write
Parameters
| Field | Type | Description |
|---|---|---|
limit (query) | integer | Items per page (1–100). |
cursor (query) | string |
|
resource_type_id (query) | string | Only templates of this type. |
status (query) | "active" | "disabled" | "archived" | Only templates with this status. Archived templates are left out by default. |
Responses
200 A page of templates.
| Field | Type | Description |
|---|---|---|
datarequired | object[] | |
data[].idrequired | string | |
data[].resource_type_idrequired | string | |
data[].resource_typerequired | string | Key of the resource type. |
data[].path_patternrequired | string | |
data[].url_examplerequired | string | The pattern on the environment’s shared host, for example |
data[].id_formatrequired | object | How the id in the URL is validated: a preset (numeric, alnum, uuid, ulid, base64url) or an explicit character set with length bounds. |
data[].deep_link_pathrequired | string | |
data[].datarequired | object | |
data[].redirectsrequired | object | |
data[].redirects.iosrequired | string | null | |
data[].redirects.androidrequired | string | null | |
data[].redirects.webrequired | string | null | |
data[].redirects.desktoprequired | string | null | |
data[].redirects.fallbackrequired | string | null | |
data[].allow_param_passthroughrequired | boolean | |
data[].statusrequired | "active" | "disabled" | "archived" | |
data[].created_atrequired | string (date-time) | |
data[].updated_atrequired | string (date-time) | |
next_cursorrequired | string | null | Pass as |
Example
curl -X GET "https://api.becklinks.com/v1/url-templates" \
-H "Authorization: Bearer $SECRET_KEY"/url-templatesCreate a URL template
Shares path_pattern (for example /c/{id}) for a resource type on the environment’s link host. id_format says what an id looks like; deep_link_path, data and redirects may contain {id} and {type}. The pattern cannot change later. A type can have 5 templates. A destination URL that looks suspicious is saved and listed in warnings; one that is listed as dangerous is refused with 422 url_blocked.
Secret key scope (any of): links:write
Request body
| Field | Type | Description |
|---|---|---|
resource_type_idrequired | string | The resource type this pattern shares. |
path_patternrequired | string | The URL pattern, for example |
id_formatrequired | object | How the id in the URL is validated: a preset (numeric, alnum, uuid, ulid, base64url) or an explicit character set with length bounds. |
deep_link_pathrequired | string | In-app route handed to the SDK, for example |
data | object | Custom JSON delivered with the link; |
redirects | object | null | Per-platform destinations. |
allow_param_passthrough | boolean | Pass query parameters added to the short URL on to the app payload (LNK-005). |
Responses
201 The new template.
| Field | Type | Description |
|---|---|---|
idrequired | string | |
resource_type_idrequired | string | |
resource_typerequired | string | Key of the resource type. |
path_patternrequired | string | |
url_examplerequired | string | The pattern on the environment’s shared host, for example |
id_formatrequired | object | How the id in the URL is validated: a preset (numeric, alnum, uuid, ulid, base64url) or an explicit character set with length bounds. |
deep_link_pathrequired | string | |
datarequired | object | |
redirectsrequired | object | |
redirects.iosrequired | string | null | |
redirects.androidrequired | string | null | |
redirects.webrequired | string | null | |
redirects.desktoprequired | string | null | |
redirects.fallbackrequired | string | null | |
allow_param_passthroughrequired | boolean | |
statusrequired | "active" | "disabled" | "archived" | |
created_atrequired | string (date-time) | |
updated_atrequired | string (date-time) | |
warningsrequired | object[] | |
warnings[].coderequired | "destination_suspicious" | |
warnings[].pointerrequired | string | JSON Pointer to the field the warning is about. |
warnings[].detailrequired | string | |
warnings[].reasonsrequired | string[] | Stable reason codes of the URL check. |
Example
curl -X POST "https://api.becklinks.com/v1/url-templates" \
-H "Authorization: Bearer $SECRET_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"resource_type_id":"string","path_pattern":"string","id_format":{"kind":"preset","preset":"numeric"},"deep_link_path":"string"}'/url-templates/testTest a URL against the templates
Shows which template and id a URL or path resolves to and what it would render. Nothing is counted or stored.
Secret key scope (any of): links:read, links:write
Request body
| Field | Type | Description |
|---|---|---|
pathrequired | string | A URL path such as |
Responses
200 The outcome.
| Field | Type | Description |
|---|---|---|
resultrequired | "match" | "invalid_id" | "no_template" | |
template_idrequired | string | null | |
resource_typerequired | string | null | |
idrequired | string | null | The id taken from the URL, decoded. |
renderedrequired | object | null | |
detailrequired | string | Why the path resolved, or did not, in a sentence. |
Example
curl -X POST "https://api.becklinks.com/v1/url-templates/test" \
-H "Authorization: Bearer $SECRET_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"path":"string"}'/url-templates/{template}Get a URL template
One template, archived ones included.
Secret key scope (any of): links:read, links:write
Parameters
| Field | Type | Description |
|---|---|---|
template (path)required | string | The ID of the URL template. |
Responses
200 The template.
| Field | Type | Description |
|---|---|---|
idrequired | string | |
resource_type_idrequired | string | |
resource_typerequired | string | Key of the resource type. |
path_patternrequired | string | |
url_examplerequired | string | The pattern on the environment’s shared host, for example |
id_formatrequired | object | How the id in the URL is validated: a preset (numeric, alnum, uuid, ulid, base64url) or an explicit character set with length bounds. |
deep_link_pathrequired | string | |
datarequired | object | |
redirectsrequired | object | |
redirects.iosrequired | string | null | |
redirects.androidrequired | string | null | |
redirects.webrequired | string | null | |
redirects.desktoprequired | string | null | |
redirects.fallbackrequired | string | null | |
allow_param_passthroughrequired | boolean | |
statusrequired | "active" | "disabled" | "archived" | |
created_atrequired | string (date-time) | |
updated_atrequired | string (date-time) |
Example
curl -X GET "https://api.becklinks.com/v1/url-templates/{template}" \
-H "Authorization: Bearer $SECRET_KEY"/url-templates/{template}Update a URL template
Changes the fields sent. The pattern and the resource type stay as they are, because links already shared depend on them. status: disabled keeps the pattern and answers with a status page; archived frees the pattern. A destination URL that looks suspicious is saved and listed in warnings; one that is listed as dangerous is refused with 422 url_blocked.
Secret key scope (any of): links:write
Parameters
| Field | Type | Description |
|---|---|---|
template (path)required | string | The ID of the URL template. |
Request body
| Field | Type | Description |
|---|---|---|
id_format | object | How the id in the URL is validated: a preset (numeric, alnum, uuid, ulid, base64url) or an explicit character set with length bounds. |
deep_link_path | string | In-app route handed to the SDK, for example |
data | object | Custom JSON delivered with the link; |
redirects | object | null | Per-platform destinations. |
allow_param_passthrough | boolean | Pass query parameters added to the short URL on to the app payload (LNK-005). |
status | "active" | "disabled" | "archived" |
|
Responses
200 The updated template.
| Field | Type | Description |
|---|---|---|
idrequired | string | |
resource_type_idrequired | string | |
resource_typerequired | string | Key of the resource type. |
path_patternrequired | string | |
url_examplerequired | string | The pattern on the environment’s shared host, for example |
id_formatrequired | object | How the id in the URL is validated: a preset (numeric, alnum, uuid, ulid, base64url) or an explicit character set with length bounds. |
deep_link_pathrequired | string | |
datarequired | object | |
redirectsrequired | object | |
redirects.iosrequired | string | null | |
redirects.androidrequired | string | null | |
redirects.webrequired | string | null | |
redirects.desktoprequired | string | null | |
redirects.fallbackrequired | string | null | |
allow_param_passthroughrequired | boolean | |
statusrequired | "active" | "disabled" | "archived" | |
created_atrequired | string (date-time) | |
updated_atrequired | string (date-time) | |
warningsrequired | object[] | |
warnings[].coderequired | "destination_suspicious" | |
warnings[].pointerrequired | string | JSON Pointer to the field the warning is about. |
warnings[].detailrequired | string | |
warnings[].reasonsrequired | string[] | Stable reason codes of the URL check. |
Example
curl -X PATCH "https://api.becklinks.com/v1/url-templates/{template}" \
-H "Authorization: Bearer $SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{}'