curl --request GET \
--url https://jmpy.me/api/v1/analytics/click-details/:shortUrlId \
--header 'Authorization: Bearer <token>'{
"data": [
{
"id": "<string>",
"short_code": "<string>",
"original_url": "<string>",
"clicked_at": "<string>",
"ip_address": "<string>",
"user_agent": "<string>",
"referrer": "<string>",
"country": "<string>",
"city": "<string>",
"device_type": "<string>",
"browser": "<string>",
"os": "<string>"
}
],
"pagination": {
"limit": 123,
"offset": 123,
"total": 123
}
}Get detailed click data for a short URL or all your URLs
curl --request GET \
--url https://jmpy.me/api/v1/analytics/click-details/:shortUrlId \
--header 'Authorization: Bearer <token>'{
"data": [
{
"id": "<string>",
"short_code": "<string>",
"original_url": "<string>",
"clicked_at": "<string>",
"ip_address": "<string>",
"user_agent": "<string>",
"referrer": "<string>",
"country": "<string>",
"city": "<string>",
"device_type": "<string>",
"browser": "<string>",
"os": "<string>"
}
],
"pagination": {
"limit": 123,
"offset": 123,
"total": 123
}
}shortUrlId parameter is optional. If omitted, returns click details for all your URLs.550e8400-e29b-41d4-a716-446655440000abc123my-custom-linkShow Click Record Object
mobile, desktop, tablet.# Get clicks for a specific URL by UUID
curl -X GET "https://jmpy.me/api/v1/analytics/click-details/550e8400-e29b-41d4-a716-446655440000?limit=50" \
-H "Authorization: Bearer YOUR_API_KEY"
# Get clicks for a URL by short code
curl -X GET "https://jmpy.me/api/v1/analytics/click-details/abc123?limit=100&offset=0" \
-H "Authorization: Bearer YOUR_API_KEY"
# Get clicks for a URL by custom alias
curl -X GET "https://jmpy.me/api/v1/analytics/click-details/my-promo-link" \
-H "Authorization: Bearer YOUR_API_KEY"
# Get all clicks (no shortUrlId)
curl -X GET "https://jmpy.me/api/v1/analytics/click-details?limit=50&offset=0" \
-H "Authorization: Bearer YOUR_API_KEY"
const fetch = require('node-fetch');
// Get clicks for a specific URL
const shortUrlId = '550e8400-e29b-41d4-a716-446655440000';
const response = await fetch(
`https://jmpy.me/api/v1/analytics/click-details/${shortUrlId}?limit=100`,
{
headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
}
);
const data = await response.json();
// Process click data
data.data.data.forEach(click => {
console.log(`${click.clicked_at}: ${click.country} - ${click.browser}`);
});
import axios from 'axios';
interface ClickRecord {
id: string;
short_code: string;
original_url: string;
clicked_at: string;
ip_address: string;
user_agent: string;
referrer: string;
country: string;
city: string;
device_type: 'mobile' | 'desktop' | 'tablet';
browser: string;
os: string;
}
interface ClickDetailsResponse {
data: ClickRecord[];
pagination: {
limit: number;
offset: number;
total: number;
};
}
const shortUrlId = '550e8400-e29b-41d4-a716-446655440000';
const response = await axios.get<{ success: boolean; data: ClickDetailsResponse }>(
`https://jmpy.me/api/v1/analytics/click-details/${shortUrlId}`,
{
headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
params: { limit: 100, offset: 0 }
}
);
import requests
short_url_id = '550e8400-e29b-41d4-a716-446655440000'
response = requests.get(
f'https://jmpy.me/api/v1/analytics/click-details/{short_url_id}',
headers={'Authorization': 'Bearer YOUR_API_KEY'},
params={'limit': 100, 'offset': 0}
)
data = response.json()
for click in data['data']['data']:
print(f"{click['clicked_at']}: {click['country']} - {click['browser']}")
<?php
$client = new GuzzleHttp\Client();
$shortUrlId = '550e8400-e29b-41d4-a716-446655440000';
$response = $client->request('GET',
"https://jmpy.me/api/v1/analytics/click-details/{$shortUrlId}", [
'headers' => [
'Authorization' => 'Bearer YOUR_API_KEY'
],
'query' => [
'limit' => 100,
'offset' => 0
]
]);
$data = json_decode($response->getBody(), true);
foreach ($data['data']['data'] as $click) {
echo $click['clicked_at'] . ': ' . $click['country'] . "\n";
}
?>
package main
import (
"fmt"
"net/http"
"io"
)
func main() {
shortUrlId := "550e8400-e29b-41d4-a716-446655440000"
url := fmt.Sprintf(
"https://jmpy.me/api/v1/analytics/click-details/%s?limit=100&offset=0",
shortUrlId,
)
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer YOUR_API_KEY")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.URI;
import java.net.http.HttpResponse;
String shortUrlId = "550e8400-e29b-41d4-a716-446655440000";
String url = String.format(
"https://jmpy.me/api/v1/analytics/click-details/%s?limit=100&offset=0",
shortUrlId
);
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer YOUR_API_KEY")
.GET()
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
{
"success": true,
"data": {
"data": [
{
"id": "click-uuid-1",
"short_code": "abc123",
"original_url": "https://example.com/page",
"clicked_at": "2024-01-15T14:32:00Z",
"ip_address": "192.168.xxx.xxx",
"user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0...",
"referrer": "https://twitter.com",
"country": "US",
"city": "New York",
"device_type": "mobile",
"browser": "Safari",
"os": "iOS"
},
{
"id": "click-uuid-2",
"short_code": "abc123",
"original_url": "https://example.com/page",
"clicked_at": "2024-01-15T14:28:00Z",
"ip_address": "10.0.xxx.xxx",
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)...",
"referrer": "https://google.com",
"country": "UK",
"city": "London",
"device_type": "desktop",
"browser": "Chrome",
"os": "Windows"
}
],
"pagination": {
"limit": 100,
"offset": 0,
"total": 2
}
}
}
{
"success": false,
"error": {
"code": "NOT_FOUND",
"message": "Short URL not found",
"details": "No short URL found with code or alias: invalid-code"
}
}
Export click data to CSV
async function exportClicksToCSV(shortUrlId) {
let allClicks = [];
let offset = 0;
const limit = 1000;
// Paginate through all clicks
while (true) {
const response = await fetch(
`https://jmpy.me/api/v1/analytics/click-details/${shortUrlId}?limit=${limit}&offset=${offset}`,
{ headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
const { data } = await response.json();
allClicks = allClicks.concat(data.data);
if (data.data.length < limit) break;
offset += limit;
}
// Convert to CSV
const headers = 'clicked_at,country,city,device_type,browser,os,referrer';
const rows = allClicks.map(c =>
`${c.clicked_at},${c.country},${c.city},${c.device_type},${c.browser},${c.os},${c.referrer}`
);
return [headers, ...rows].join('\n');
}
Real-time click monitoring
async function monitorClicks(shortUrlId, onNewClick) {
let lastClickId = null;
setInterval(async () => {
const response = await fetch(
`https://jmpy.me/api/v1/analytics/click-details/${shortUrlId}?limit=10`,
{ headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
const { data } = await response.json();
const clicks = data.data;
if (clicks.length > 0 && clicks[0].id !== lastClickId) {
// New clicks detected
const newClicks = lastClickId
? clicks.slice(0, clicks.findIndex(c => c.id === lastClickId))
: clicks;
newClicks.forEach(click => onNewClick(click));
lastClickId = clicks[0].id;
}
}, 5000); // Poll every 5 seconds
}
Analyze traffic by country
import requests
from collections import Counter
def analyze_by_country(short_url_id):
response = requests.get(
f'https://jmpy.me/api/v1/analytics/click-details/{short_url_id}',
headers={'Authorization': 'Bearer YOUR_API_KEY'},
params={'limit': 1000}
)
clicks = response.json()['data']['data']
countries = Counter(click['country'] for click in clicks)
total = len(clicks)
for country, count in countries.most_common():
percentage = (count / total) * 100
print(f"{country}: {count} clicks ({percentage:.1f}%)")