Smartlink Types & Schemas
The Relink API uses a GraphQL-like reactive body approach where the request body automatically adapts based on the smartlink type specified. This means that different fields become required or optional depending on the smartlinkType you choose.
GraphQL-like Reactive Body Structure
The API intelligently validates your request based on the smartlink type, similar to how GraphQL validates queries:
{
"configuration": {
"smartlinkType": "App|Url|Landing|QRTag|DigiCard|TxtBin|QrMenu",
// Other fields adapt based on type
},
// Additional objects appear based on type
"openGraph": { /* Optional for all types */ },
"shortener": { /* Required for Url type */ },
"landing": { /* Required for Landing type */ },
"landingButtons": [ /* Optional for Landing type */ ],
"qrTag": { /* Required for QRTag type */ },
"qrTagButtons": [ /* Optional for QRTag type */ ],
"digiCard": { /* Required for DigiCard type */ },
"digiCardButtons": [ /* Optional for DigiCard type */ ],
"txtBin": { /* Required for TxtBin type */ },
"qrMenu": { /* Required for QrMenu type */ }
}Common Fields
Configuration Object
Required for all smartlink types:
{
"configuration": {
"smartlinkName": "string (max 64 chars, required)",
"smartlinkUrl": "string (max 64 chars, alphanumeric only, optional)",
"smartlinkType": "App|Url|Landing|QRTag|DigiCard|TxtBin|QrMenu (required)"
}
}Open Graph Metadata
Optional for all smartlink types:
{
"openGraph": {
"title": "string (max 128 chars, optional)",
"description": "string (max 256 chars, optional)",
"imageUrl": "string (URL, optional)"
}
}1. App Type (App Store Redirections)
Purpose: Redirect users to appropriate app stores based on their device.
Required Objects: configuration
Schema:
{
"configuration": {
"smartlinkName": "string (max 64 chars, required)",
"smartlinkUrl": "string (max 64 chars, alphanumeric only, optional)",
"smartlinkType": "App",
"appStoreLink": "string (URL, optional)",
"googlePlayLink": "string (URL, optional)",
"windowsAppLink": "string (URL, optional)",
"macOsAppLink": "string (URL, optional)",
"ipadAppLink": "string (URL, optional)",
"appGalleryLink": "string (URL, optional)",
"amazonStoreLink": "string (URL, optional)",
"fallBackLink": "string (URL, optional)"
},
"openGraph": {
"title": "string (optional)",
"description": "string (optional)",
"imageUrl": "string (URL, optional)"
}
}Minimal Example:
{
"configuration": {
"smartlinkName": "Test App",
"smartlinkType": "App"
}
}Full Example:
{
"configuration": {
"smartlinkName": "Full App",
"smartlinkUrl": "fullapp",
"smartlinkType": "App",
"appStoreLink": "https://apps.apple.com/app/fullapp",
"googlePlayLink": "https://play.google.com/store/apps/details?id=fullapp",
"fallBackLink": "https://fullapp.com"
},
"openGraph": {
"title": "Full App",
"description": "A comprehensive test app",
"imageUrl": "https://fullapp.com/og.jpg"
}
}2. Url Type (URL Shortener)
Purpose: URL shortening with optional password protection.
Required Objects: configuration, shortener
Schema:
{
"configuration": {
"smartlinkName": "string (max 64 chars, required)",
"smartlinkUrl": "string (max 64 chars, alphanumeric only, optional)",
"smartlinkType": "Url"
},
"shortener": {
"url": "string (URL, required)",
"protected": "boolean (optional, default: false)",
"password": "string (min 6 chars, optional - required if protected: true)"
},
"openGraph": {
"title": "string (optional)",
"description": "string (optional)",
"imageUrl": "string (URL, optional)"
}
}Example:
{
"configuration": {
"smartlinkName": "Test URL",
"smartlinkUrl": "testurl",
"smartlinkType": "Url"
},
"shortener": {
"url": "https://google.com"
}
}Password Protected Example:
{
"configuration": {
"smartlinkName": "Protected URL",
"smartlinkType": "Url"
},
"shortener": {
"url": "https://confidential-document.com/secret",
"protected": true,
"password": "mySecurePassword123"
}
}3. Landing Type (Landing Pages)
Purpose: Custom landing pages with multiple action buttons.
Required Objects: configuration, landing
Optional Objects: landingButtons
Schema:
{
"configuration": {
"smartlinkName": "string (max 64 chars, required)",
"smartlinkUrl": "string (max 64 chars, alphanumeric only, optional)",
"smartlinkType": "Landing"
},
"landing": {
"title": "string (max 128 chars, optional)",
"description": "string (max 256 chars, optional)",
"logoLink": "string (URL, optional)",
"themeColor": "string (hex color, optional)",
"layout": "List|Grid (optional, default: List)",
"theme": "Light|Dark|Auto (optional, default: Auto)"
},
"landingButtons": [
{
"title": "string (max 256 chars, required)",
"link": "string (URL/tel/mailto, required)",
"iconUrl": "string (URL, optional)"
}
],
"openGraph": {
"title": "string (optional)",
"description": "string (optional)",
"imageUrl": "string (URL, optional)"
}
}Example:
{
"configuration": {
"smartlinkName": "Test Landing",
"smartlinkUrl": "testlanding",
"smartlinkType": "Landing"
},
"landing": {
"title": "My Landing Page",
"description": "Test landing page",
"themeColor": "#007bff"
},
"landingButtons": [
{
"title": "Button 1",
"link": "https://example.com"
}
]
}4. QRTag Type (QR Code Pages)
Purpose: QR code landing pages with action buttons and presets.
Required Objects: configuration, qrTag
Optional Objects: qrTagButtons
Schema:
{
"configuration": {
"smartlinkName": "string (max 64 chars, required)",
"smartlinkUrl": "string (max 64 chars, alphanumeric only, optional)",
"smartlinkType": "QRTag"
},
"qrTag": {
"title": "string (max 256 chars, optional)",
"description": "string (max 256 chars, optional)",
"logoLink": "string (URL, optional)",
"themeColor": "string (hex color, optional)"
},
"qrTagButtons": [
{
"title": "string (max 256 chars, required)",
"link": "string (required)",
"preset": "string (optional)",
"position": "number (min 0, optional)"
}
],
"openGraph": {
"title": "string (optional)",
"description": "string (optional)",
"imageUrl": "string (URL, optional)"
}
}Button Presets:
link- Generic linkrestaurant- Restaurant/food relateddelivery- Delivery/orderingphone- Phone/contactemail- Email contactcalendar- Calendar/bookingsocial- Social media
Basic Example:
{
"configuration": {
"smartlinkName": "Test QR",
"smartlinkUrl": "testqr",
"smartlinkType": "QRTag"
},
"qrTag": {
"title": "Test QR Tag",
"description": "Test QR description"
},
"qrTagButtons": [
{
"title": "QR Button",
"link": "https://example.com",
"preset": "link"
}
]
}Restaurant Menu Example:
{
"configuration": {
"smartlinkName": "Restaurant QR Menu",
"smartlinkUrl": "menuqr",
"smartlinkType": "QRTag"
},
"qrTag": {
"title": "Our Menu",
"description": "Scan to view our delicious menu",
"logoLink": "https://restaurant.com/logo.png",
"themeColor": "#ff6b35"
},
"qrTagButtons": [
{
"title": "View Menu",
"link": "https://restaurant.com/menu",
"preset": "restaurant"
},
{
"title": "Order Online",
"link": "https://restaurant.com/order",
"preset": "delivery"
},
{
"title": "Call Us",
"link": "tel:+1234567890",
"preset": "phone"
},
{
"title": "Reserve Table",
"link": "https://restaurant.com/reservations",
"preset": "calendar"
}
],
"openGraph": {
"title": "Restaurant Menu",
"description": "Browse our menu and order online",
"imageUrl": "https://restaurant.com/menu-image.jpg"
}
}5. DigiCard Type (Digital Business Cards)
Purpose: Digital business cards with contact information and action buttons.
Required Objects: configuration, digiCard
Optional Objects: digiCardButtons
Schema:
{
"configuration": {
"smartlinkName": "string (max 64 chars, required)",
"smartlinkUrl": "string (max 64 chars, alphanumeric only, optional)",
"smartlinkType": "DigiCard"
},
"digiCard": {
"title": "string (max 256 chars, optional)",
"jobTitle": "string (max 128 chars, optional)",
"company": "string (max 128 chars, optional)",
"logoLink": "string (URL, optional)",
"bgLink": "string (URL, optional)",
"ctaText": "string (max 32 chars, optional)",
"themeColor": "string (hex color, optional)"
},
"digiCardButtons": [
{
"title": "string (max 256 chars, required)",
"link": "string (required)",
"preset": "string (optional)"
}
],
"openGraph": {
"title": "string (optional)",
"description": "string (optional)",
"imageUrl": "string (URL, optional)"
}
}Example:
{
"configuration": {
"smartlinkName": "Test DigiCard",
"smartlinkUrl": "testcard",
"smartlinkType": "DigiCard"
},
"digiCard": {
"title": "John Doe",
"jobTitle": "Developer",
"company": "Test Company"
},
"digiCardButtons": [
{
"title": "Contact",
"link": "mailto:[email protected]",
"preset": "email"
}
]
}6. TxtBin Type (Text Sharing)
Purpose: Text sharing with formatting and syntax highlighting.
Required Objects: configuration, txtBin
Schema:
{
"configuration": {
"smartlinkName": "string (max 64 chars, required)",
"smartlinkUrl": "string (max 64 chars, alphanumeric only, optional)",
"smartlinkType": "TxtBin"
},
"txtBin": {
"title": "string (max 256 chars, optional)",
"description": "string (max 256 chars, optional)",
"text": "string (required)"
},
"openGraph": {
"title": "string (optional)",
"description": "string (optional)",
"imageUrl": "string (URL, optional)"
}
}Example:
{
"configuration": {
"smartlinkName": "Test TxtBin",
"smartlinkUrl": "testtxt",
"smartlinkType": "TxtBin"
},
"txtBin": {
"title": "Test Text",
"description": "Test text description",
"text": "This is a test text content"
}
}Code Snippet Example:
{
"configuration": {
"smartlinkName": "React Component",
"smartlinkType": "TxtBin"
},
"txtBin": {
"title": "React Counter Component",
"description": "A simple React counter with TypeScript",
"text": "import React, { useState } from 'react';\n\nfunction Counter() {\n const [count, setCount] = useState(0);\n return (\n <button onClick={() => setCount(count + 1)}>\n Count: {count}\n </button>\n );\n}\n\nexport default Counter;"
}
}7. QrMenu Type
Digital restaurant menu with categories, items, optional size/variant prices, and photos.
Schema:
{
"configuration": {
"smartlinkName": "string (max 64 chars, required)",
"smartlinkUrl": "string (max 64 chars, alphanumeric only, optional)",
"smartlinkType": "QrMenu"
},
"qrMenu": {
"title": "string (max 128 chars, optional)",
"description": "string (max 256 chars, optional)",
"logoLink": "string (URL, optional)",
"coverLink": "string (URL, optional)",
"themeColor": "string (hex, optional)",
"theme": "Light|Auto|Dark (optional)",
"layout": "List|Grid (optional)",
"currency": "string (max 8 chars, optional, default ₼)",
"categories": [
{
"name": "string (max 64 chars, required)",
"position": "number (optional)",
"items": [
{
"name": "string (max 128 chars, required)",
"description": "string (max 512 chars, optional)",
"price": "number (>= 0, required — from-price when variants exist)",
"variants": [
{
"label": "string (max 64 chars)",
"price": "number (>= 0)"
}
],
"imageLink": "string (URL, optional)",
"badges": ["string"],
"position": "number (optional)",
"active": "boolean (optional, default true)"
}
]
}
]
}
}Example:
{
"configuration": {
"smartlinkName": "Cafe Menu",
"smartlinkUrl": "cafemenu",
"smartlinkType": "QrMenu"
},
"qrMenu": {
"title": "Downtown Cafe",
"currency": "₼",
"layout": "List",
"theme": "Light",
"categories": [
{
"name": "Coffee",
"items": [
{
"name": "Latte",
"description": "Espresso with steamed milk",
"price": 5,
"variants": [
{ "label": "Small", "price": 5 },
{ "label": "Large", "price": 7 }
],
"badges": ["Popular"]
}
]
}
]
}
}When variants is present and non-empty, the public menu lists each size as compact chips under the item (and again in the item detail). Omit variants (or pass []) for a single flat price.
PATCH Operations (Partial Updates)
The API supports GraphQL-like partial updates where you only need to specify the fields you want to update:
Update Only Configuration Fields
{
"id": "clp123abc456def",
"configuration": {
"appStoreLink": "https://apps.apple.com/app/myapp"
}
}Update Only Open Graph
{
"id": "clp123abc456def",
"openGraph": {
"title": "Updated Title",
"description": "Updated description"
}
}Update Type-Specific Data
{
"id": "clp123abc456def",
"digiCard": {
"jobTitle": "Lead Software Engineer",
"company": "New Tech Company Ltd."
}
}Validation Rules
URL Validation
- All URLs are validated against Google Safe Browsing API
- URLs must be properly formatted (include protocol)
- Malicious URLs will be rejected with appropriate error messages
Smartlink URL Rules
- Must be alphanumeric characters only
- Maximum 64 characters
- Cannot be reserved words:
dashboard,welcome,pp,tos - Must be unique across the platform
Character Limits
| Field | Maximum Length |
|---|---|
smartlinkName | 64 characters |
smartlinkUrl | 64 characters |
openGraph.title | 128 characters |
openGraph.description | 256 characters |
landing.title | 128 characters |
landing.description | 256 characters |
qrTag.title | 256 characters |
qrTag.description | 256 characters |
digiCard.title | 256 characters |
digiCard.jobTitle | 128 characters |
digiCard.company | 128 characters |
digiCard.ctaText | 32 characters |
Button title | 256 characters |
Required Fields by Type
| Type | Required Objects | Required Fields |
|---|---|---|
| App | configuration | smartlinkName, smartlinkType |
| Url | configuration, shortener | smartlinkName, smartlinkType, shortener.url |
| Landing | configuration, landing | smartlinkName, smartlinkType |
| QRTag | configuration, qrTag | smartlinkName, smartlinkType |
| DigiCard | configuration, digiCard | smartlinkName, smartlinkType |
| TxtBin | configuration, txtBin | smartlinkName, smartlinkType, txtBin.text |
| QrMenu | configuration, qrMenu | smartlinkName, smartlinkType |
Response Schema
All successful API responses follow this schema:
{
"success": true,
"message": "string",
"data": {
"id": "string",
"status": "Active|Paused|Deleted",
"type": "App|Url|Landing|QRTag|DigiCard|TxtBin|QrMenu",
"userId": "string",
"relink": "string (full URL)",
"createdAt": "string (ISO 8601)",
"updatedAt": "string (ISO 8601)",
"configuration": { /* smartlink configuration */ },
"analytics": {
"totalClicks": "number",
"totalQrCodeScans": "number",
"totalFallBack": "number"
}
// Additional type-specific data
},
"timestamp": "string (ISO 8601)"
}