@linkforty/core 1.45.1 → 1.45.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -200
- package/llms.txt +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -115,208 +115,9 @@ docker run -d \
|
|
|
115
115
|
|
|
116
116
|
See [DOCKER.md](DOCKER.md) for complete deployment guide.
|
|
117
117
|
|
|
118
|
-
## API Reference
|
|
119
|
-
|
|
120
|
-
### Links
|
|
121
|
-
|
|
122
|
-
#### Create a Link
|
|
123
|
-
|
|
124
|
-
`userId` is optional. When provided, the link is scoped to that user (multi-tenant mode). When omitted, the link has no owner (single-tenant mode).
|
|
125
|
-
|
|
126
|
-
```bash
|
|
127
|
-
POST /api/links
|
|
128
|
-
Content-Type: application/json
|
|
129
|
-
|
|
130
|
-
{
|
|
131
|
-
"userId": "user-uuid",
|
|
132
|
-
"originalUrl": "https://example.com",
|
|
133
|
-
"title": "My Link",
|
|
134
|
-
"description": "Summer campaign link",
|
|
135
|
-
"iosAppStoreUrl": "https://apps.apple.com/app/id123456",
|
|
136
|
-
"androidAppStoreUrl": "https://play.google.com/store/apps/details?id=com.example",
|
|
137
|
-
"webFallbackUrl": "https://example.com/product/123",
|
|
138
|
-
"appScheme": "myapp",
|
|
139
|
-
"iosUniversalLink": "https://example.com/app/product/123",
|
|
140
|
-
"androidAppLink": "https://example.com/app/product/123",
|
|
141
|
-
"deepLinkPath": "/product/123",
|
|
142
|
-
"deepLinkParameters": { "ref": "campaign-1" },
|
|
143
|
-
"utmParameters": {
|
|
144
|
-
"source": "twitter",
|
|
145
|
-
"medium": "social",
|
|
146
|
-
"campaign": "summer-sale"
|
|
147
|
-
},
|
|
148
|
-
"ogTitle": "Check out this deal",
|
|
149
|
-
"ogDescription": "50% off summer sale",
|
|
150
|
-
"ogImageUrl": "https://example.com/og-image.png",
|
|
151
|
-
"targetingRules": {
|
|
152
|
-
"countries": ["US", "CA"],
|
|
153
|
-
"devices": ["ios", "android"],
|
|
154
|
-
"languages": ["en"]
|
|
155
|
-
},
|
|
156
|
-
"attributionWindowHours": 168,
|
|
157
|
-
"customCode": "summer-sale",
|
|
158
|
-
"expiresAt": "2026-12-31T23:59:59Z"
|
|
159
|
-
}
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
All fields except `originalUrl` are optional.
|
|
163
|
-
|
|
164
|
-
Install attribution settings, per link:
|
|
165
|
-
|
|
166
|
-
- `attributionWindowHours` (1–2160, default 168): how long after a click an install can still be matched to it.
|
|
167
|
-
- `attributionWindowMinutes` (5–129600): the same window in minutes, for windows under an hour. Send one or the other; when set it replaces the hours, and updating the link with `attributionWindowHours` clears it.
|
|
168
|
-
- `oneInstallPerClick` (default `false`): a click is matched to one install only. A second install that would have matched the same click is matched to another click, or recorded as organic. Suited to single-use links, such as sign-in links.
|
|
169
|
-
|
|
170
|
-
#### Get All Links
|
|
171
|
-
|
|
172
|
-
```bash
|
|
173
|
-
# Single-tenant (all links)
|
|
174
|
-
GET /api/links
|
|
175
|
-
|
|
176
|
-
# Multi-tenant (scoped to user)
|
|
177
|
-
GET /api/links?userId=user-uuid
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
#### Get a Specific Link
|
|
181
|
-
|
|
182
|
-
```bash
|
|
183
|
-
GET /api/links/:id
|
|
184
|
-
GET /api/links/:id?userId=user-uuid
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
#### Update a Link
|
|
188
|
-
|
|
189
|
-
```bash
|
|
190
|
-
PUT /api/links/:id?userId=user-uuid
|
|
191
|
-
Content-Type: application/json
|
|
192
|
-
|
|
193
|
-
{
|
|
194
|
-
"title": "Updated Title",
|
|
195
|
-
"isActive": false
|
|
196
|
-
}
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
#### Duplicate a Link
|
|
200
|
-
|
|
201
|
-
```bash
|
|
202
|
-
POST /api/links/:id/duplicate?userId=user-uuid
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
#### Delete a Link
|
|
206
|
-
|
|
207
|
-
```bash
|
|
208
|
-
DELETE /api/links/:id?userId=user-uuid
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
### Analytics
|
|
212
|
-
|
|
213
|
-
#### Get Analytics Overview
|
|
214
|
-
|
|
215
|
-
```bash
|
|
216
|
-
# All links
|
|
217
|
-
GET /api/analytics/overview?days=30
|
|
218
|
-
|
|
219
|
-
# Scoped to user
|
|
220
|
-
GET /api/analytics/overview?userId=user-uuid&days=30
|
|
221
|
-
```
|
|
222
|
-
|
|
223
|
-
Returns: `totalClicks`, `uniqueClicks`, `clicksByDate`, `clicksByCountry`, `clicksByDevice`, `clicksByPlatform`, `topLinks`
|
|
224
|
-
|
|
225
|
-
#### Get Link-Specific Analytics
|
|
226
|
-
|
|
227
|
-
```bash
|
|
228
|
-
GET /api/analytics/links/:linkId?days=30
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
### Redirect
|
|
232
|
-
|
|
233
|
-
```bash
|
|
234
|
-
GET /:shortCode
|
|
235
|
-
GET /:templateSlug/:shortCode
|
|
236
|
-
```
|
|
237
|
-
|
|
238
|
-
Redirects users to the appropriate URL based on device type (iOS/Android/web), evaluates targeting rules, and tracks the click asynchronously. See [Redirects](docs/redirects.md) for the not-found page, the mobile interstitial and the Launchpad page.
|
|
239
|
-
|
|
240
|
-
### QR Codes
|
|
241
|
-
|
|
242
|
-
```bash
|
|
243
|
-
GET /api/links/:id/qr?format=png&size=300
|
|
244
|
-
GET /api/links/:id/qr?format=svg
|
|
245
|
-
GET /api/links/:id/qr?url=https://links.example.com/spring/abc123 # encode the link on a custom host / template path
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
Without `url` the code encodes `SHORTLINK_DOMAIN/{shortCode}`. `url` must be an http(s) URL whose path ends in the link's short code; anything else is a 400. The Launchpad page uses it to encode its own address, so a phone that scans the code lands on the same host and path the visitor is on.
|
|
249
|
-
|
|
250
|
-
### Webhooks
|
|
251
|
-
|
|
252
|
-
```bash
|
|
253
|
-
GET /api/webhooks?userId=user-uuid
|
|
254
|
-
POST /api/webhooks # Body: { name, url, events, userId? }
|
|
255
|
-
GET /api/webhooks/:id?userId=user-uuid
|
|
256
|
-
PUT /api/webhooks/:id?userId=user-uuid
|
|
257
|
-
DELETE /api/webhooks/:id?userId=user-uuid
|
|
258
|
-
POST /api/webhooks/:id/test?userId=user-uuid
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
Events: `click_event`, `install_event`, `conversion_event`, `sdk_event`. Payloads are HMAC SHA-256 signed.
|
|
262
|
-
|
|
263
|
-
Which webhooks hear about a link: one with an `organization_id` receives events for every link in that organization; one without receives events for links created by its `user_id`; one with neither receives events for links that have neither. To keep a delivery log, pass a function to `setWebhookDeliveryLogger()`. It is called with the webhook id, the attempt's result and the payload sent.
|
|
264
|
-
|
|
265
|
-
### Mobile SDK Endpoints
|
|
266
|
-
|
|
267
|
-
```bash
|
|
268
|
-
POST /api/sdk/v1/install # Report app install, get deferred deep link
|
|
269
|
-
GET /api/sdk/v1/attribution/:fingerprint # Debug attribution lookups
|
|
270
|
-
POST /api/sdk/v1/event # Track in-app conversion events
|
|
271
|
-
GET /api/sdk/v1/resolve/:shortCode # Resolve link to deep link data (no redirect)
|
|
272
|
-
GET /api/sdk/v1/health # Health check
|
|
273
|
-
```
|
|
274
|
-
|
|
275
|
-
An event whose `installId` this server no longer has is **recovered, not
|
|
276
|
-
refused**: the install is recorded again (marked `recovered`, with no link,
|
|
277
|
-
click or confidence score, so it is never mistaken for a fresh attributed
|
|
278
|
-
install) and the event is stored against it.
|
|
279
|
-
|
|
280
|
-
This matters because the id lives in the app's storage for the life of the
|
|
281
|
-
install while the server's copy may not: a restore from an older backup, a
|
|
282
|
-
manual cleanup, an app build pointed at a fresh database, or an analytics
|
|
283
|
-
retention job all leave a live device holding an id nothing resolves. The
|
|
284
|
-
bundled SDKs store the id once and never re-register, so without recovery
|
|
285
|
-
that device is refused forever with no way back. The 404 that remains carries
|
|
286
|
-
`code: "INSTALL_NOT_FOUND"` and `action: "reregister"`.
|
|
287
|
-
|
|
288
|
-
### Health
|
|
289
|
-
|
|
290
|
-
```bash
|
|
291
|
-
GET /health # Liveness — process is up (no DB access)
|
|
292
|
-
GET /health/ready # Readiness — 503 if the database is unreachable
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
### Debug & Testing
|
|
296
|
-
|
|
297
|
-
```bash
|
|
298
|
-
POST /api/debug/simulate # Simulate a link click with custom parameters
|
|
299
|
-
WS /api/debug/live?userId=user-uuid # WebSocket live click event stream
|
|
300
|
-
GET /api/debug/user-agents # Common UA strings for testing
|
|
301
|
-
GET /api/debug/countries # Common countries list
|
|
302
|
-
GET /api/debug/languages # Common languages list
|
|
303
|
-
```
|
|
304
|
-
|
|
305
|
-
### Well-Known Routes
|
|
306
|
-
|
|
307
|
-
```bash
|
|
308
|
-
GET /.well-known/apple-app-site-association # iOS Universal Links
|
|
309
|
-
GET /.well-known/assetlinks.json # Android App Links
|
|
310
|
-
```
|
|
311
|
-
|
|
312
|
-
### OG Preview
|
|
313
|
-
|
|
314
|
-
```bash
|
|
315
|
-
GET /:shortCode/preview # OG meta tag page for social scrapers
|
|
316
|
-
```
|
|
317
|
-
|
|
318
118
|
## Reference
|
|
319
119
|
|
|
120
|
+
- [API](docs/api.md)
|
|
320
121
|
- [Redirects](docs/redirects.md)
|
|
321
122
|
- [Configuration](docs/configuration.md): server options and hooks, `linkforty.config.json`, reverse proxies, environment variables
|
|
322
123
|
- [Database schema](docs/database-schema.md)
|
package/llms.txt
CHANGED