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.

providerMeaning
embedlyAn external link. metadata carries title, description, type, site_name and providerUrl.
speakapA 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.

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"
    }
}

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 shapeDescribes
/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
/journeysthe journeys collection, as journey_collection with a null eid
/newsthe news collection, as news_collection with a null eid; /news?item={eid} stays the item
/eventsthe events collection, as event_collection with a null eid; /events?event={eid} stays the event
/tasksthe tasks collection, as task_collection with a null eid; /tasks?task={eid} stays the task
/groupsthe groups collection, as group_collection with a null eid
/organizationthe organization page, as organization with a null eid
/peoplethe people page, as people with a null eid
/drive, /filesthe drive, as drive with a null eid
/knowledge-basethe 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:

URLRecognised
https://acme.speakap.com/news?item=5d64c74303029f80yes
https://acme.speakap.com/news?messageEID=5d64c74303029f80yes
https://acme.speakap.com/news/5d64c74303029f80yes
https://acme.speakap.com/tasks/5d64c74303029f80yes
https://acme.speakap.com/user/5d64c74303029f80yes
https://acme.speakap.com/group/5d64c74303029f80yes
https://acme.speakap.com/group/5d64c74303029f80/membersno — deeper than the group
https://acme.speakap.com/groupsyes — the groups collection, with a null eid
https://acme.speakap.com/organizationyes — the organization page, with a null eid
https://acme.speakap.com/organization/5d64c74303029f80no — deeper than the section
https://acme.speakap.com/peopleyes — the people page, with a null eid
https://acme.speakap.com/people/5d64c74303029f80no — deeper than the section
https://acme.speakap.com/driveyes — the drive, with a null eid
https://acme.speakap.com/filesyes — the drive, with a null eid
https://acme.speakap.com/drive/5d64c74303029f80yes — the folder, as drive with its eid
https://acme.speakap.com/files/5d64c74303029f80no — not a drive URL
https://acme.speakap.com/knowledge-base/page/5d64c74303029f80yes
https://acme.speakap.com/knowledge-base/edit/5d64c74303029f80yes
https://acme.speakap.com/knowledge-base?category=5d64c74303029f80yes
https://acme.speakap.com/knowledge-base/yes — the knowledge base home, with a null eid
https://acme.speakap.com/newsyes — the news collection, with a null eid
https://acme.speakap.com/news/post/5d64c74303029f80no — deeper than the section
https://acme.speakap.com/newsletter/5d64c74303029f80no — a different section
https://acme.speakap.com/journey/5fa03516790f961cyes
https://acme.speakap.com/journey/join/5fa03516790f961c?stepId=5fa03521a10f9980yes
https://acme.speakap.com/journeysyes — the journeys collection, with a null eid
https://acme.speakap.com/eventsyes — the events collection, with a null eid
https://acme.speakap.com/events?event=notaneidno — an event link, and not 16 hexadecimal characters
https://acme.speakap.com/tasksyes — the tasks collection, with a null eid
https://acme.speakap.com/tasks?task=notaneidno — a task link, and not 16 hexadecimal characters
https://acme.speakap.com/journeyno — the singular section page is not a resource
https://acme.speakap.com/journey/5fa03516790f961c/step/new-draftno — an unsaved step
https://acme.speakap.com/news?item=notaneidno — 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:

contentTypeResource
newsA news item
updateAn update
eventAn event
pollA poll
taskA task
fileA file or document
commentA comment on one of the above
userA profile
groupA group
journeyA journey
journey_pageA page step inside a journey
journey_questionA question step inside a journey
journey_collectionThe journeys collection page
news_collectionThe news collection page
event_collectionThe events collection page
task_collectionThe tasks collection page
group_collectionThe groups collection page
organizationThe organization page
peopleThe people page
driveThe drive, or a folder in it
knowledge_baseThe knowledge base home page
knowledge_base_articleA published knowledge base article
knowledge_base_categoryA 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

StatusMeaningSuggested handling
400The url parameter is missing or is not a usable URL.Do not retry. Show a plain link.
400 with code -16A preview could not be retrieved for an external URL.Show a plain link. Retrying later may succeed.