Link Previews
Overview
When a user pastes a URL, you can ask the Speakap API to provide metadata associated with the URL. A single endpoint answers for both external links and links to Speakap's own content, so you make one request and branch on the answer.
GET /urls/meta/?url={url}The url parameter must be URL-encoded. That matters for Speakap links in particular: they carry
the resource identifier in their own query string (/news?item=<eid>), so the ? and = have to
be encoded rather than passed through as part of the request's query string. The endpoint requires
an authenticated user.
API version
Speakap links are described with provider: "speakap" only from API version 2026.3.0. Before that
version, every URL, Speakap links included, is answered in the older embedly format, so a Speakap
link gets general information about Speakap rather than the content it points at.
The response
Every successful response has the same shape:
{
"url": "https://example.com/article",
"provider": "embedly",
"desktopThumbnailUrl": "https://.../thumbnail.jpg",
"metadata": {
"title": "Example Article Title",
"description": "A brief description of the article content.",
"type": "article",
"site_name": "Example"
}
}Read provider first. It tells you which of two very different payloads you are holding.
provider | Meaning |
|---|---|
embedly | An external link. metadata carries title, description, type, site_name and providerUrl. |
speakap | A link to content inside a Speakap network. metadata carries contentType and eid. |
provider decides which keys metadata contains, so read it before reaching into metadata.
External links
For provider: "embedly", use metadata and desktopThumbnailUrl to build a preview card. Both
may be partially populated — a destination without an image gives you no desktopThumbnailUrl, and
metadata fields are individually optional. Degrade gracefully rather than assuming any field is
present.
metadata does not carry contentType or eid for external links.
{
"url": "https://vimeo.com/18150336",
"provider": "embedly",
"desktopThumbnailUrl": "https://.../vimeo-thumb.jpg",
"metadata": {
"title": "Wingsuit Basejumping",
"type": "video",
"site_name": "Vimeo"
}
}Speakap links
For provider: "speakap", the URL points into a Speakap network. Read metadata.contentType next.
When metadata.contentType is set, the URL points at a resource the current user may open.
Render your own styling for that kind of content — the API does not return a title, description or
thumbnail for Speakap content, so build the card from the type alone.
{
"url": "https://acme.speakap.com/news?item=5d64c74303029f80",
"provider": "speakap",
"desktopThumbnailUrl": null,
"metadata": {
"contentType": "news",
"eid": "5d64c74303029f80"
}
}metadata.eid is the identifier of the resource, so you can fetch it from its own endpoint if you
want more than the type.
Which Speakap URLs are recognised
A Speakap link is recognised when it addresses a single resource, in one of the exact shapes the product hands out. The EID is 16 hexadecimal characters.
| URL shape | Describes |
|---|---|
/news?item={eid}, /news?messageEID={eid}, /news/{eid} | the news item |
/events?event={eid}, /events?messageEID={eid}, /events/{eid} | the event |
/tasks?task={eid}, /tasks?messageEID={eid}, /tasks/{eid} | the task |
/update/{eid} | the update |
/poll/{eid} | the poll |
/file/{eid} | the file |
/group/{eid} | the group |
/drive/{eid} | the drive folder, as drive with the folder eid |
/user/{eid} | the profile, by network profile EID |
/journey/{eid} | the journey |
/journey/join/{eid} | the journey, as a participant follows it |
/journey/{journeyEid}/step/{eid} | the step, page or question |
/journey/join/{journeyEid}?stepId={eid} | the step, as a participant follows it |
/knowledge-base/page/{eid}, /knowledge-base/edit/{eid} | the knowledge base article |
/knowledge-base?category={eid} | the knowledge base category |
/journeys | the journeys collection, as journey_collection with a null eid |
/news | the news collection, as news_collection with a null eid; /news?item={eid} stays the item |
/events | the events collection, as event_collection with a null eid; /events?event={eid} stays the event |
/tasks | the tasks collection, as task_collection with a null eid; /tasks?task={eid} stays the task |
/groups | the groups collection, as group_collection with a null eid |
/organization | the organization page, as organization with a null eid |
/people | the people page, as people with a null eid |
/drive, /files | the drive, as drive with a null eid |
/knowledge-base | the knowledge base home, as knowledge_base with a null eid; ?category={eid} stays the category |
A collection addresses a page rather than a resource, so metadata.eid is null for it. A resource
shape always wins over its section, and a /news, /events or /tasks link that names an item
stays that item even when the EID is malformed. journey_collection is described only while journeys
are enabled for the network; news_collection, event_collection, task_collection,
group_collection, organization, people and drive carry no such feature gate. A drive folder is
described only while the requester may view it.
For messages, metadata.contentType follows the resource the EID belongs to rather than the section
it was pasted under, so a comment EID in any of those shapes answers comment. A journey step works
the same way: journey_page and journey_question are told apart from the step itself, so the
?type= parameter the editor puts on its own URLs is ignored, and
/journey/{journeyEid}/step/new-draft describes nothing because an unsaved step is not a resource
yet. A step URL that names a journey the step does not belong to describes nothing either.
The draft URL /knowledge-base/draft?page={eid} is not recognised, and an article is described only
once it is published — an unpublished one is a plain link through either article URL. A category is
described only while it is visible to the requester; anything else is a Speakap link with a null
contentType. The knowledge base home is described only while the knowledge base is enabled, like the
article and the category.
A knowledge_base, knowledge_base_article or knowledge_base_category answer also carries
metadata.knowledgeBaseAlias, the network's own name for the knowledge base, when the network names its
knowledge base after the knowledge base home title. Otherwise the key is absent; fall back to your default label.
Recognition is deliberately narrow, so a link that merely starts with a supported section is not recognised:
| URL | Recognised |
|---|---|
https://acme.speakap.com/news?item=5d64c74303029f80 | yes |
https://acme.speakap.com/news?messageEID=5d64c74303029f80 | yes |
https://acme.speakap.com/news/5d64c74303029f80 | yes |
https://acme.speakap.com/tasks/5d64c74303029f80 | yes |
https://acme.speakap.com/user/5d64c74303029f80 | yes |
https://acme.speakap.com/group/5d64c74303029f80 | yes |
https://acme.speakap.com/group/5d64c74303029f80/members | no — deeper than the group |
https://acme.speakap.com/groups | yes — the groups collection, with a null eid |
https://acme.speakap.com/organization | yes — the organization page, with a null eid |
https://acme.speakap.com/organization/5d64c74303029f80 | no — deeper than the section |
https://acme.speakap.com/people | yes — the people page, with a null eid |
https://acme.speakap.com/people/5d64c74303029f80 | no — deeper than the section |
https://acme.speakap.com/drive | yes — the drive, with a null eid |
https://acme.speakap.com/files | yes — the drive, with a null eid |
https://acme.speakap.com/drive/5d64c74303029f80 | yes — the folder, as drive with its eid |
https://acme.speakap.com/files/5d64c74303029f80 | no — not a drive URL |
https://acme.speakap.com/knowledge-base/page/5d64c74303029f80 | yes |
https://acme.speakap.com/knowledge-base/edit/5d64c74303029f80 | yes |
https://acme.speakap.com/knowledge-base?category=5d64c74303029f80 | yes |
https://acme.speakap.com/knowledge-base/ | yes — the knowledge base home, with a null eid |
https://acme.speakap.com/news | yes — the news collection, with a null eid |
https://acme.speakap.com/news/post/5d64c74303029f80 | no — deeper than the section |
https://acme.speakap.com/newsletter/5d64c74303029f80 | no — a different section |
https://acme.speakap.com/journey/5fa03516790f961c | yes |
https://acme.speakap.com/journey/join/5fa03516790f961c?stepId=5fa03521a10f9980 | yes |
https://acme.speakap.com/journeys | yes — the journeys collection, with a null eid |
https://acme.speakap.com/events | yes — the events collection, with a null eid |
https://acme.speakap.com/events?event=notaneid | no — an event link, and not 16 hexadecimal characters |
https://acme.speakap.com/tasks | yes — the tasks collection, with a null eid |
https://acme.speakap.com/tasks?task=notaneid | no — a task link, and not 16 hexadecimal characters |
https://acme.speakap.com/journey | no — the singular section page is not a resource |
https://acme.speakap.com/journey/5fa03516790f961c/step/new-draft | no — an unsaved step |
https://acme.speakap.com/news?item=notaneid | no — not 16 hexadecimal characters |
Everything in the "no" column comes back as a Speakap link with metadata.contentType: null, which
you render as a plain link.
Every Speakap answer also carries metadata.type, always link, and metadata.url, repeating the
top-level url. Both are present whether or not contentType is null.
Supported values of metadata.contentType:
contentType | Resource |
|---|---|
news | A news item |
update | An update |
event | An event |
poll | A poll |
task | A task |
file | A file or document |
comment | A comment on one of the above |
user | A profile |
group | A group |
journey | A journey |
journey_page | A page step inside a journey |
journey_question | A question step inside a journey |
journey_collection | The journeys collection page |
news_collection | The news collection page |
event_collection | The events collection page |
task_collection | The tasks collection page |
group_collection | The groups collection page |
organization | The organization page |
people | The people page |
drive | The drive, or a folder in it |
knowledge_base | The knowledge base home page |
knowledge_base_article | A published knowledge base article |
knowledge_base_category | A knowledge base category |
More types will be added over time. Treat an unrecognised contentType as you would a link with no
type: show a plain link rather than failing.
When metadata.contentType is null, the URL belongs to Speakap but there is nothing to
describe. Show a plain link. This is a normal outcome, not an error, and you will see it for several
reasons:
- the URL points at a kind of resource that is not supported yet
- the URL points at a resource that no longer exists
- the URL is a Speakap page that is not a resource at all, such as an inbox or a chat
- the current user is not a member of the network the URL belongs to
- the current user may not open that particular resource
You do not need to distinguish between these. They all mean the same thing for display purposes.
metadata.type is always link for a Speakap answer, for backwards compatibility with mobile.
{
"url": "https://acme.speakap.com/inbox",
"provider": "speakap",
"desktopThumbnailUrl": null,
"metadata": {
"contentType": null,
"eid": null,
"type": "link",
"url": "https://acme.speakap.com/inbox"
}
}Custom domains
A network reachable at its own domain rather than a Speakap subdomain works the same way. Paste
https://intranet.acme.com/news?item=5d64c74303029f80 and you get the same response you would for
https://acme.speakap.com/news?item=5d64c74303029f80.
Errors
| Status | Meaning | Suggested handling |
|---|---|---|
400 | The url parameter is missing or is not a usable URL. | Do not retry. Show a plain link. |
400 with code -16 | A preview could not be retrieved for an external URL. | Show a plain link. Retrying later may succeed. |