Vai al contenuto principale
Torna alla documentazione

API pubblica Lunidex v1

Collega un’integrazione server ai dati già sincronizzati con un account Lunidex. Crea una chiave e invia una prima richiesta, poi esplora carte, prodotti sigillati, paginazione e scritture sicure.

URL di basehttps://lunidex.app/api/v1
Gestisci chiavi APIApri la specifica OpenAPI

Chiavi solo lato server

Non inserire mai una chiave API nel codice del browser, in un’app mobile, in un repository pubblico, in un URL, in uno screenshot o in un log condiviso. Conservala in un gestore di segreti lato server e inviala solo nell’intestazione Authorization.

Avvio rapido

L’integrazione richiede una chiave, un segreto conservato sul server e una richiesta HTTPS all’URL di base dell’API.

  1. 1

    Crea una chiave

    Apri la scheda delle chiavi API nella dashboard Lunidex. Assegna un nome e scegli sola lettura oppure lettura e scrittura. Il segreto completo viene mostrato una sola volta: copialo prima di chiudere il messaggio.

  2. 2

    Conserva il segreto sul server

    Salva la chiave come LUNIDEX_API_KEY nel gestore di segreti del tuo provider. Non inserirla nel repository e non inviarla al browser.

  3. 3

    Invia la prima richiesta

    Chiama GET /me dal tuo server. Gli endpoint privati richiedono l’intestazione Authorization: Bearer seguita dalla chiave.

cURL · esegui in un ambiente server affidabile
curl --fail-with-body \
  -H "Authorization: Bearer $LUNIDEX_API_KEY" \
  https://lunidex.app/api/v1/me
Node.js · fetch lato server
const API_BASE_URL = "https://lunidex.app/api/v1";
const apiKey = process.env.LUNIDEX_API_KEY;

if (!apiKey) throw new Error("Missing LUNIDEX_API_KEY");

const response = await fetch(API_BASE_URL + "/me", {
  headers: { Authorization: "Bearer " + apiKey },
});
const result = await response.json();

if (!response.ok) {
  throw new Error(result.error?.code ?? "REQUEST_FAILED");
}

console.log(result.data);

Autenticazione e permessi

Invia la chiave nell’intestazione HTTP Authorization per ogni richiesta privata /api/v1. L’API restituisce JSON nell’involucro data; le risposte private usano Cache-Control: private, no-store.

Lettura

Consente gli endpoint GET. Scegli questo permesso se l’integrazione deve solo mostrare o esportare i dati dell’account.

Lettura e scrittura

Consente sia gli endpoint GET sia quelli di scrittura. Usalo solo per un’integrazione server affidabile che deve modificare la raccolta o il registro dei prodotti sigillati.

L’API vede solo i dati sincronizzati con l’account Lunidex in Neon. I dati presenti soltanto su un dispositivo non sono disponibili. L’identità dell’account non include l’indirizzo email.

Paginazione e filtri

Gli elenchi restituiscono data e meta.nextCursor. Passa il cursore senza modificarlo per chiedere la pagina successiva e termina quando è null.

  • La dimensione predefinita è 25 e il massimo è 100. Il catalogo restituisce al massimo 24 risultati per pagina.
  • Le carte accettano i filtri language e set. Le posizioni sigillate accettano language e productId; le transazioni accettano language, productId, type, includeVoided e voided. Il catalogo accetta q e cursor.
  • Il cursore può diventare obsoleto se cambiano raccolta, registro, prezzi o filtri. L’API restituisce 409; ricomincia senza cursore usando lo stato aggiornato.
Leggi tutte le pagine di carte da un server
const API_BASE_URL = "https://lunidex.app/api/v1";
const apiKey = process.env.LUNIDEX_API_KEY;
let cursor = null;

if (!apiKey) throw new Error("Missing LUNIDEX_API_KEY");

do {
  const query = new URLSearchParams({ limit: "100" });
  if (cursor) query.set("cursor", cursor);

  const response = await fetch(API_BASE_URL + "/cards?" + query, {
    headers: { Authorization: "Bearer " + apiKey },
  });
  const result = await response.json();
  if (!response.ok) throw new Error(result.error?.code ?? "REQUEST_FAILED");

  console.log(result.data);
  cursor = result.meta?.nextCursor ?? null;
} while (cursor);

Endpoint

I percorsi sono relativi all’URL di base dell’API. Ogni riga indica il livello di accesso richiesto e i parametri elencati nel contratto OpenAPI. La specifica leggibile dalle macchine contiene gli schemi completi, esempi di richieste e risposte ed errori per operazione; le sezioni seguenti spiegano i flussi principali.

Account e contratto

  • GETPubblica · nessuna chiave
    /openapi.json

    Contratto pubblico leggibile dalle macchine; non richiede una chiave API.

    Parametri:Nessuno
  • GETChiave di sola lettura
    /me

    Identità limitata dell’account, senza indirizzo email.

    Parametri:Nessuno
  • GETChiave di sola lettura
    /summary

    Statistiche principali, conteggi fisici e distinti delle carte e totali sigillati in centesimi EUR.

    Parametri:Nessuno

Raccolta carte

  • GETChiave di sola lettura
    /cards

    Possedimenti paginati con filtri facoltativi per lingua e set.

    Parametri:
    • cursor(query)
    • limit(query)
    • language(query)
    • set(query)
  • GETChiave di sola lettura
    /cards/{cardId}

    Metadati TCGdex e possedimenti dell’account, senza valutazioni delle carte.

    Parametri:
    • cardId(percorso)· obbligatorio
    • language(query)
  • PUTChiave di lettura e scrittura
    /cards/{cardId}

    Imposta la quantità assoluta per lingua e variante della carta.

    Parametri:
    • cardId(percorso)· obbligatorio

Prodotti sigillati e transazioni

  • GETChiave di sola lettura
    /sealed/catalogue

    Cerca nel catalogo Cardmarket esistente di prodotti sigillati.

    Parametri:
    • q(query)
    • cursor(query)
  • GETChiave di sola lettura
    /sealed/positions

    Posizioni correnti paginate, costo e valore di mercato memorizzato.

    Parametri:
    • cursor(query)
    • limit(query)
    • language(query)
    • productId(query)
  • GETChiave di sola lettura
    /sealed/positions/{productId}

    Posizioni per lingua di un prodotto posseduto.

    Parametri:
    • productId(percorso)· obbligatorio
  • GETChiave di sola lettura
    /sealed/transactions

    Registro privato delle transazioni con revisioni e filtri.

    Parametri:
    • cursor(query)
    • limit(query)
    • language(query)
    • productId(query)
    • type(query)
    • includeVoided(query)
    • voided(query)
  • POSTChiave di lettura e scrittura
    /sealed/transactions

    Crea acquisto, vendita o scambio; chiave di idempotenza obbligatoria.

    Parametri:
    • Idempotency-Key(header)· obbligatorio
  • GETChiave di sola lettura
    /sealed/transactions/{id}

    Legge una transazione appartenente all’account.

    Parametri:
    • id(percorso)· obbligatorio
  • PATCHChiave di lettura e scrittura
    /sealed/transactions/{id}

    Modifica una transazione con controllo delle revisioni.

    Parametri:
    • id(percorso)· obbligatorio
  • POSTChiave di lettura e scrittura
    /sealed/transactions/{id}/void

    Annulla una transazione con controllo delle revisioni.

    Parametri:
    • id(percorso)· obbligatorio

Carte

GET /cards elenca le varianti possedute senza caricare l’intero catalogo TCGdex. Ogni possesso include cardId, setId, language, variant e quantity; i filtri facoltativi sono language e set.

GET /cards/{cardId} restituisce metadati TCGdex utili e i possedimenti di questa carta nell’account. Aggiungi il parametro language per restringere i possedimenti.

PUT /cards/{cardId} accetta language, variant (unspecified, normal, reverse o holo) e una quantità assoluta da 0 a 10.000. Il valore 0 rimuove la variante.

PUT /cards/{cardId} · application/json
{
  "language": "en",
  "variant": "reverse",
  "quantity": 2
}

I vecchi possedimenti senza lingua restano visibili; language può essere null e possono essere contrassegnati legacy.

Questa API non restituisce mai il valore delle carte.

Prodotti sigillati

Le posizioni includono quantità per lingua, costo e valore corrente calcolato dai prezzi già memorizzati in Lunidex. Gli importi sono centesimi interi di EUR. Se manca un prezzo, valueCents è null e missingPrice lo indica; il riepilogo conta anche missingPrices.

In GET /summary, il valore dei prodotti sigillati è null se manca il prezzo di almeno un prodotto posseduto; missingPrices indica il totale.

GET /sealed/catalogue

Cerca prodotti già presenti nel catalogo Cardmarket con q (massimo 150 caratteri) e cursor. Ogni pagina contiene al massimo 24 prodotti; usa il loro ID nelle richieste successive.

GET /sealed/positions

GET /sealed/positions accetta i filtri language e productId. GET /sealed/positions/{productId} restituisce la posizione corrente di un prodotto. Questi endpoint mostrano i totali correnti, non l’intera serie dello storico prezzi.

GET /sealed/transactions

Il registro privato accetta i filtri language, productId, type (buy, sell, exchange), includeVoided e voided. Include revisioni per consentire modifiche sicure.

Scritture, idempotenza e revisioni

Imposta la quantità di una carta

PUT /cards/{cardId} imposta la quantità invece di aggiungere un incremento. Ripetere la stessa richiesta lascia invariata la quantità; invia 0 per rimuovere la variante. Prima di scrivere, l’API verifica carta, set, lingua e variante disponibile.

Crea una transazione sigillata

POST /sealed/transactions accetta movimenti buy, sell ed exchange. Richiede l’intestazione Idempotency-Key (8–200 caratteri) ed expectedRevision. Riutilizza la stessa chiave quando ripeti la stessa richiesta per evitare un secondo movimento. La prima richiesta crea la transazione; una ripetizione restituisce il risultato originale.

Esempio di acquisto · sostituisci ID prodotto e revisione con i valori correnti
curl --request POST "https://lunidex.app/api/v1/sealed/transactions" \
  -H "Authorization: Bearer $LUNIDEX_API_KEY" \
  -H "Idempotency-Key: lunidex-import-example-001" \
  -H "Content-Type: application/json" \
  --data '{
    "expectedRevision": 0,
    "kind": "buy",
    "cardmarketProductId": 12345,
    "language": "en",
    "date": "2026-09-27",
    "quantity": 1,
    "unitPriceCents": 2500
  }'

Prima di scrivere, leggi l’ultima revisione del registro nei metadati di GET /sealed/transactions e usala come expectedRevision. PATCH /sealed/transactions/{id} richiede anche la revision della transazione. Una revisione obsoleta restituisce 409; ricarica transazione e registro prima di decidere se riprovare.

PATCH /sealed/transactions/{id}

POST /sealed/transactions/{id}/void
POST /sealed/transactions/{id}/void richiede revision ed expectedRevision. Creazione, modifica e annullamento riutilizzano le stesse convalide, allocazioni e audit delle transazioni Lunidex.

application/json
{
  "revision": 1,
  "expectedRevision": 0
}

Errori e formato delle risposte

Le risposte riuscite usano { "data": ..., "meta": ... } (meta è facoltativo). Gli errori usano { "error": { "code": ..., "message": ..., "details": ... } } (details è facoltativo).

Risposte comuni: 400 dati della transazione non validi; 401 chiave non valida; 403 permesso insufficiente; 404 risorsa assente o non posseduta; 409 cursore o revisione obsoleti; 410 account in eliminazione; 422 parametro di query o corpo della richiesta non valido; 429 quota raggiunta; 500 errore server imprevisto; 502 dati della carta non disponibili; 503 API non disponibile.

Con 409, recupera la risorsa aggiornata o riavvia l’elenco senza cursore. Non trasformare alla cieca un conflitto in una nuova transazione.

Una risposta 429 include Retry-After. Attendi almeno il numero di secondi indicato prima di riprovare.

Tutte le risposte private dell’API usano Cache-Control: private, no-store. Il documento OpenAPI pubblico è disponibile separatamente su /api/v1/openapi.json.

Quote

I limiti si applicano per account Lunidex e sono condivisi dalle sue chiavi API.

Quote
Letture al minuto60
Scritture al minuto10
Letture al giorno1000
Scritture al giorno100
Dettagli carte per account al giorno100
Calcoli sigillati per account al giorno100
Limite globale giornaliero per categoria costosa5000

I dettagli delle carte e i calcoli dei prodotti sigillati hanno anche limiti globali distinti di 5.000 operazioni al giorno per categoria. Una risposta 429 include Retry-After.

Apri la specifica OpenAPI