Back to Guides
🛠️Tecnico / API

API Pubblica Afflyt: Documentazione Tecnica Completa

Documentazione tecnica dell'API REST Afflyt per generare link tracciati e monitorare l'utilizzo. Autenticazione, endpoint, rate limits, esempi curl e gestione errori.

15 min
Avanzato
Updated December 15, 2024

Questa documentazione descrive l'API REST pubblica di Afflyt per la generazione di link tracciati e il monitoraggio delle quote di utilizzo.

Attenzione

L'API pubblica richiede un piano BETA_TESTER o BUSINESS. I piani FREE e PRO non includono l'accesso API.

Informazioni Base

ParametroValore
Base URLhttps://api.afflyt.io/public/v1
AutenticazioneHeader X-API-Key
FormatoJSON
EncodingUTF-8

Autenticazione

Tutte le richieste richiedono un header X-API-Key con una chiave API valida.

Generare una API Key

  1. Accedi alla sezione Developer nelle impostazioni
  2. Clicca "Genera nuova chiave"
  3. Assegna un nome identificativo (es. "Bot Telegram Offerte")
  4. Copia la chiave — viene mostrata una sola volta

Formato della Chiave

afflyt_sk_<43-caratteri-base64url>

Esempio: afflyt_sk_aBcDeFgHiJkLmNoPqRsTuVwXyZ0123456789_-abc

Sicurezza

  • La chiave viene hashata (SHA-256) prima di essere salvata
  • Afflyt non memorizza la chiave in chiaro
  • Se perdi la chiave, devi generarne una nuova
  • Puoi avere massimo 5 chiavi attive per account
  • Revoca le chiavi non utilizzate dalla dashboard

Info

Non condividere mai la tua API key. Trattala come una password. Se sospetti che sia stata compromessa, revocala immediatamente.


Endpoint

POST /links

Genera un link tracciato per un prodotto Amazon.

Request

curl -X POST https://api.afflyt.io/public/v1/links \
  -H "Content-Type: application/json" \
  -H "X-API-Key: afflyt_sk_your_key_here" \
  -d '{
    "asin": "B09V3KXJPB",
    "amazonTag": "tuotag-21",
    "utm_medium": "telegram",
    "utm_campaign": "offerte-tech",
    "utm_content": "post-123",
    "channel_id": "canale-principale"
  }'

Parametri Body

CampoTipoObbligatorioDescrizione
asinstringASIN Amazon (10 caratteri alfanumerici)
amazonTagstringIl tuo tag Amazon Associates
utm_mediumstringNoCanale di acquisizione (default: api)
utm_campaignstringNoNome campagna per tracking
utm_contentstringNoIdentificatore contenuto specifico
channel_idstringNoID del canale per analytics cross-channel

Attenzione

Il prodotto con l'ASIN specificato deve esistere nel database Afflyt. Se il prodotto non esiste, riceverai un errore 404.

Response (201 Created)

{
  "id": "clx1abc123def456",
  "shortUrl": "https://afflyt.io/r/aBc1234?utm_source=afflyt&utm_medium=telegram&utm_campaign=offerte-tech&utm_content=post-123&ch=canale-principale&p=1705312800",
  "amazonUrl": "https://www.amazon.it/dp/B09V3KXJPB?tag=tuotag-21",
  "asin": "B09V3KXJPB",
  "createdAt": "2025-01-15T12:00:00.000Z",
  "quota": {
    "used": 42,
    "limit": 1000,
    "resetDate": "2025-02-01"
  }
}
CampoDescrizione
idID univoco del link nel database
shortUrlURL breve da pubblicare (con tracking UTM)
amazonUrlURL Amazon diretto (senza UTM)
asinASIN del prodotto
createdAtTimestamp di creazione
quota.usedLink generati questo mese
quota.limitLimite mensile del piano
quota.resetDateData reset quota (primo del mese successivo)

GET /usage

Restituisce l'utilizzo corrente delle quote mensili.

Request

curl -X GET https://api.afflyt.io/public/v1/usage \
  -H "X-API-Key: afflyt_sk_your_key_here"

Response (200 OK)

{
  "period": "monthly",
  "resetDate": "2025-02-01",
  "links": {
    "used": 42,
    "limit": 1000,
    "remaining": 958
  },
  "clicks": {
    "used": 1523,
    "limit": 10000,
    "remaining": 8477
  }
}

Rate Limits

L'API applica due tipi di limiti:

1. Rate Limit (richieste/minuto)

PianoLimite
BETA_TESTER60 req/min
BUSINESS300 req/min

Quando superi il rate limit, ricevi un errore 429 Too Many Requests con l'header Retry-After.

2. Quote Mensili

PianoLink/meseClick tracciati/mese
BETA_TESTER1.00010.000
BUSINESS10.000100.000

Info

Soft Limit vs Hard Limit: I piani BETA_TESTER hanno un soft limit — ricevi un warning nella response ma la richiesta viene comunque processata. I piani BUSINESS hanno un hard limit — la richiesta viene rifiutata con errore 429.

Response con Warning (BETA_TESTER)

Quando superi il soft limit, la response include un campo warnings:

{
  "id": "clx1abc123def456",
  "shortUrl": "https://afflyt.io/r/aBc1234?...",
  "warnings": [
    {
      "type": "quota_exceeded",
      "resource": "links",
      "used": 1050,
      "limit": 1000
    }
  ]
}

Gestione Errori

Tutti gli errori seguono un formato consistente:

{
  "error": "ERROR_CODE",
  "message": "Descrizione leggibile dell'errore",
  "details": [...]
}

Codici di Errore

HTTPCodiceDescrizioneAzione
400VALIDATION_ERRORBody malformato o parametri invalidiControlla il formato dei parametri
401API key mancante o invalidaVerifica l'header X-API-Key
403UPGRADE_REQUIREDPiano non include API accessUpgrade a BETA_TESTER o BUSINESS
404PRODUCT_NOT_FOUNDASIN non presente nel databaseVerifica l'ASIN
429QUOTA_EXCEEDEDQuota mensile esauritaAttendi il reset o fai upgrade
500INTERNAL_ERRORErrore serverRiprova più tardi

Esempio: Errore di Validazione

{
  "error": "VALIDATION_ERROR",
  "message": "Invalid request body",
  "details": [
    {
      "field": "asin",
      "message": "Invalid ASIN format (must be 10 alphanumeric characters)"
    },
    {
      "field": "amazonTag",
      "message": "Amazon tag is required"
    }
  ]
}

Esempio: Quota Esaurita

{
  "error": "QUOTA_EXCEEDED",
  "message": "Monthly link quota exceeded (1000/1000)",
  "resetDate": "2025-02-01",
  "upgradeUrl": "/settings/subscription"
}

Esempio: Piano Non Supportato

{
  "error": "UPGRADE_REQUIRED",
  "message": "API Access is available from BUSINESS plan",
  "currentPlan": "PRO",
  "currentPlanLabel": "Pro",
  "requiredFeature": "api_access",
  "suggestedPlan": "BUSINESS",
  "suggestedPlanLabel": "Business",
  "suggestedPlanPrice": 199,
  "upgradeUrl": "/settings/subscription"
}

Esempi di Integrazione

Python

import requests

API_KEY = "afflyt_sk_your_key_here"
BASE_URL = "https://api.afflyt.io/public/v1"

def generate_link(asin: str, amazon_tag: str, channel_id: str = None) -> dict:
    """Genera un link tracciato per un prodotto Amazon."""
    response = requests.post(
        f"{BASE_URL}/links",
        headers={
            "Content-Type": "application/json",
            "X-API-Key": API_KEY
        },
        json={
            "asin": asin,
            "amazonTag": amazon_tag,
            "utm_medium": "telegram",
            "channel_id": channel_id
        }
    )

    if response.status_code == 201:
        return response.json()
    elif response.status_code == 429:
        raise Exception(f"Quota esaurita: {response.json()['message']}")
    else:
        raise Exception(f"Errore API: {response.text}")

# Utilizzo
link = generate_link("B09V3KXJPB", "tuotag-21", "canale-tech")
print(f"Short URL: {link['shortUrl']}")
print(f"Quota: {link['quota']['used']}/{link['quota']['limit']}")

Node.js

const API_KEY = 'afflyt_sk_your_key_here';
const BASE_URL = 'https://api.afflyt.io/public/v1';

async function generateLink(asin, amazonTag, options = {}) {
  const response = await fetch(`${BASE_URL}/links`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': API_KEY
    },
    body: JSON.stringify({
      asin,
      amazonTag,
      utm_medium: options.utmMedium || 'api',
      utm_campaign: options.utmCampaign,
      utm_content: options.utmContent,
      channel_id: options.channelId
    })
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(`API Error: ${error.message}`);
  }

  return response.json();
}

// Utilizzo
const link = await generateLink('B09V3KXJPB', 'tuotag-21', {
  utmMedium: 'telegram',
  channelId: 'canale-tech'
});
console.log(`Short URL: ${link.shortUrl}`);

Bot Telegram (Python + python-telegram-bot)

from telegram import Update
from telegram.ext import Application, CommandHandler, ContextTypes
import requests

API_KEY = "afflyt_sk_your_key_here"
AMAZON_TAG = "tuotag-21"

async def genera_link(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """Handler per /link <ASIN>"""
    if not context.args:
        await update.message.reply_text("Uso: /link <ASIN>")
        return

    asin = context.args[0].upper()

    response = requests.post(
        "https://api.afflyt.io/public/v1/links",
        headers={"X-API-Key": API_KEY, "Content-Type": "application/json"},
        json={
            "asin": asin,
            "amazonTag": AMAZON_TAG,
            "utm_medium": "telegram",
            "channel_id": str(update.effective_chat.id)
        }
    )

    if response.status_code == 201:
        data = response.json()
        await update.message.reply_text(
            f"Link generato:\n{data['shortUrl']}\n\n"
            f"Quota: {data['quota']['used']}/{data['quota']['limit']}"
        )
    elif response.status_code == 404:
        await update.message.reply_text("Prodotto non trovato nel database.")
    else:
        await update.message.reply_text(f"Errore: {response.json().get('message')}")

# Setup bot
app = Application.builder().token("BOT_TOKEN").build()
app.add_handler(CommandHandler("link", genera_link))
app.run_polling()

Best Practices

1. Gestisci gli Errori

Non assumere che ogni richiesta abbia successo. Implementa retry con backoff esponenziale per errori 5xx.

import time

def api_request_with_retry(func, max_retries=3):
    for attempt in range(max_retries):
        try:
            return func()
        except Exception as e:
            if attempt == max_retries - 1:
                raise
            wait_time = 2 ** attempt  # 1, 2, 4 secondi
            time.sleep(wait_time)

2. Monitora le Quote

Controlla il campo quota in ogni response. Implementa alerting quando ti avvicini al limite.

def check_quota_warning(response_data):
    quota = response_data.get('quota', {})
    usage_percent = quota['used'] / quota['limit'] * 100

    if usage_percent > 80:
        send_alert(f"Attenzione: quota API al {usage_percent:.0f}%")

3. Usa channel_id per Analytics

Il parametro channel_id ti permette di segmentare le analytics per canale nella dashboard Afflyt.

# Ogni canale Telegram ha un ID univoco
channel_id = f"telegram_{update.effective_chat.id}"

Se pubblichi lo stesso prodotto su più canali, considera di cachare il link per evitare richieste duplicate.

from functools import lru_cache

@lru_cache(maxsize=1000)
def get_or_create_link(asin: str) -> str:
    # La prima chiamata genera il link, le successive usano la cache
    return generate_link(asin, AMAZON_TAG)['shortUrl']

FAQ


Changelog

DataVersioneNote
2025-01-15v1.0Release iniziale con POST /links e GET /usage

Supporto

Guide completed?

Sign up for free to access all Afflyt features.

API Pubblica Afflyt: Documentazione Tecnica Completa | Afflyt Guide | Afflyt Pro