LinconwavesLinconwavesUnified docs
Minlink

Smart Links API

Build and manage Smart Links via the developer API.

  • Base URL: https://cm.minlink.io/v1/api
  • Auth header: x-minlink-api-key: <your-key>
  • Responses: { status, message, data }; errors: { status: "error", error: { code, message } }
  • Each Smart Link has a slug (e.g., snd/abcd) and a type.
  • Public redirects live at https://<frontend>/{type-prefix}/{slug-part} and also at /smart-links/:slug (catch-all), which auto-chooses app store vs web for appDownload.
  • Public helpers:
    • GET /smart-links/slug/:slug - fetch public JSON for rendering.
    • GET /smart-links/:slug - public redirect with click tracking.
    • GET /smart-links/track/:slug - tracking pixel.
    • POST /smart-links/slug/:slug/survey - submit survey answers (only for surveyLink).

Supported types + create payload examples (Node.js)

const BASE = 'https://cm.minlink.io/v1/api';
const headers = {
  'content-type': 'application/json',
  'x-minlink-api-key': process.env.MINLINK_API_KEY!,
};
  • myBio - profile / bio page
await fetch(`${BASE}/smart-links`, {
  method: 'POST',
  headers,
  body: JSON.stringify({
    title: 'My bio',
    type: 'myBio',
    tags: ['creator'],
    urls: [
      { title: 'Website', url: 'https://example.com' },
      { title: 'YouTube', url: 'https://youtube.com/handle' },
    ],
  }),
});
  • appDownload - choose App Store / Play Store by device
await fetch(`${BASE}/smart-links`, {
  method: 'POST',
  headers,
  body: JSON.stringify({
    title: 'Get the app',
    type: 'appDownload',
    appstoreLink: 'https://apps.apple.com/app/123',
    playstoreLink: 'https://play.google.com/store/apps/details?id=com.example',
  }),
});
  • musicLink - multi-platform music landing
await fetch(`${BASE}/smart-links`, {
  method: 'POST',
  headers,
  body: JSON.stringify({
    title: 'New single',
    type: 'musicLink',
    platforms: [
      { name: 'Spotify', url: 'https://open.spotify.com/track/123' },
      { name: 'Apple Music', url: 'https://music.apple.com/track/123' },
    ],
    cover: 'https://cdn.example.com/cover.jpg',
  }),
});
  • videoLink - video landing(s)
await fetch(`${BASE}/smart-links`, {
  method: 'POST',
  headers,
  body: JSON.stringify({
    title: 'Feature demo',
    type: 'videoLink',
    videos: [
      { title: 'Teaser', url: 'https://youtube.com/watch?v=abc' },
      { title: 'Full demo', url: 'https://vimeo.com/xyz', ctaText: 'Book a call' },
    ],
  }),
});
  • webinarLink - webinar or event landing
await fetch(`${BASE}/smart-links`, {
  method: 'POST',
  headers,
  body: JSON.stringify({
    title: 'Product webinar',
    type: 'webinarLink',
    description: 'Live overview + Q&A',
    urls: [{ title: 'Register', url: 'https://example.com/register' }],
  }),
});
  • surveyLink - survey/lead form
await fetch(`${BASE}/smart-links`, {
  method: 'POST',
  headers,
  body: JSON.stringify({
    title: 'Feedback survey',
    type: 'surveyLink',
    questions: [
      { question: 'How satisfied are you?', type: 'rating', required: true },
      { question: 'What should we improve?', type: 'text' },
    ],
    submissionDetails: { email: '[email protected]' }, // optional destination
  }),
});

Authenticated endpoints

  • POST /smart-links
  • Body (JSON or multipart/form-data for uploads):
PropTypeWhat it controls
titlestring (required)Display name for the Smart Link.
descriptionstringOptional copy for landing/supporting text.
type

string (required)
myBio | appDownload | musicLink | videoLink | webinarLink | surveyLink

Determines rendering + required fields.
tagsstring[] or CSVOptional labels for search/filtering.
urlsarrayCommon list content: { title, url, description? }.
appstoreLink / playstoreLinkstringApp download destinations (for appDownload).
platformsarrayMusic platforms: { name, url, icon? } (for musicLink).
videosarrayVideo entries for videoLink: { title, url?, description?, subLink?, ctaText?, file?, storageCode?, cover? }.
questionsarraySurvey prompts for surveyLink: { question, type, required?, options? }.
submissionDetailsobjectSurvey submission target (e.g., { email }).
image / coverfile or URLHero/preview assets; send as multipart for uploads.
videoFilesfile[]Optional uploads for videos; map via videoFileIndexes when needed.
statusstringOptional lifecycle toggle; defaults to active.
  • Notes:
    • Duplicate (title + type per owner) returns 409 with LINK_ALREADY_EXISTS.
    • Plan limits apply (smartLinks quota).

Code samples (create)

const BASE = 'https://cm.minlink.io/v1/api';
const API_KEY = process.env.MINLINK_API_KEY!;

async function createSmartLink() {
  const res = await fetch(`${BASE}/smart-links`, {
    method: 'POST',
    headers: {
      'content-type': 'application/json',
      'x-minlink-api-key': API_KEY,
    },
    body: JSON.stringify({
      title: 'My bio',
      type: 'myBio',
      tags: ['creator'],
      urls: [{ title: 'Website', url: 'https://example.com' }],
    }),
  });
  console.log(await res.json());
}

createSmartLink().catch(console.error);
  • GET /smart-links - returns all smart links for the API key owner, newest first.
  • GET /smart-links/:id
  • PUT /smart-links/:id
  • Accepts the same fields as create (JSON or multipart with cover, image, videoFiles, optional videoFileIndexes).
  • Updates emit webhook events.
  • DELETE /smart-links/:id

Analytics

  • GET /smart-links/:id/analytics
  • Returns (under data.analytics):
    • totalClicks
    • uniqueVisitors
    • clicksData (per-day counts)
    • topCountries
    • devices
    • timeOfDay
    • topReferrers
    • topBrowsers

Fetch QR/Tracking

  • Smart Links rely on redirects and tracking pixels; there is no separate QR endpoint. Use the Links QR API if you need QR codes.

Public-facing behavior

  • Redirect: GET /smart-links/:slug chooses the destination based on type and user agent (e.g., appDownload routes to App Store/Play Store when possible).
  • Tracking pixel: GET /smart-links/track/:slug?ua=...&screen=WxH&event=...&meta=....
  • Public JSON (for rendering landing pages): GET /smart-links/slug/:slug.
  • Survey submit: POST /smart-links/slug/:slug/survey with { answers, submissionType?, submissionDetails? }.

Frontend integration

  • Render from public JSON: fetch https://cm.minlink.io/v1/smart-links/slug/:slug to get data.link (title, type, urls/platforms/videos, covers/images, tags) without exposing an API key.
  • Buttons/links: map platforms, urls, or videos[].url to your own UI; for appDownload, you can still let the server redirect by linking to /smart-links/:slug.
  • Tracking: if you host the landing yourself, include <img src="https://cm.minlink.io/v1/smart-links/track/:slug?ua=${encodeURIComponent(navigator.userAgent)}&screen=${window.innerWidth}x${window.innerHeight}&event=pageview"> to keep server analytics in sync.
  • Surveys: post your UI form to https://cm.minlink.io/v1/smart-links/slug/:slug/survey with { answers, submissionType?, submissionDetails? } (e.g., { submissionType: "email", submissionDetails: { email: "[email protected]" } }).
  • Assets: cover, image, videos[].cover are absolute URLs-use directly in <img> or video players.

Error cases

  • 401/403 for missing/invalid API key, inactive key, suspended owner, or missing permissions.
  • 402 if the developer account is paused (low balance).
  • 404 if a Smart Link is not found (including after delete).
  • 409 if a duplicate Smart Link exists for the owner.

Typical flow

  1. Create a Smart Link (optionally with uploads).
  2. Share the public slug (frontend renders /bio/..., /snd/..., etc., or use /smart-links/:slug).
  3. Poll GET /smart-links/:id/analytics for performance.
  4. Update or delete as needed.