API Reference
search
hubGraphQL · v2.5.0

Catálogo Iterpec via GraphQL

Endpoint autenticado POST /api/catalog/graphql que serve o conteúdo dos ZIPs oficiais (hotéis + destinos) já normalizado, paginado e versionado por release. Use este endpoint para montar e manter o seu catálogo local; chame Hotel.svc/HotelDetail só sob demanda para enriquecer (fotos, amenities, descrições).

lockPré-requisitos

  • Token de workspace wsk_* emitido pela Iterpec após contrato assinado e formuláriocliente preenchido.
  • O mesmo token usado no MCP Server autentica o GraphQL — não há chave separada.
  • Rate-limit por workspace: 120 req/min. Resposta 429 vem com header Retry-After.

schemaSchema

# GraphQL Schema (read-only)
type Destination {
  id: ID!
  name: String!
  countryCode: String
  type: String
  nameEn: String
  namePt: String
}

type Hotel {
  id: ID!
  name: String!
  destinationId: ID
  category: String
  address: String
  latitude: Float
  longitude: Float
  lastUpdateSource: String
}

type Release {
  id: ID!
  version: String!
  releasedAt: String!
  hotelsCount: Int!
  destinationsCount: Int!
  hotelsSha256: String
}

type SyncStatus {
  workspaceCid: ID!
  currentReleaseId: ID
  lastFullSyncAt: String
  daysSinceSync: Int
  isStale: Boolean!
  note: String
}

type Query {
  currentRelease: Release
  destinations(country: String, search: String, limit: Int = 100, offset: Int = 0): [Destination!]!
  hotels(destinationId: ID, search: String, limit: Int = 100, offset: Int = 0): [Hotel!]!
  hotel(id: ID!): Hotel
  syncStatus: SyncStatus!
}

receipt_longHeaders de resposta

  • X-Catalog-Release-Id — id do release atual; mude o cache local quando mudar.
  • X-Catalog-Version — versão semântica do release.
  • X-RateLimit-Limit / X-RateLimit-Remaining — controle de quota.

terminalExemplo cURL — hotéis de um destino

curl -X POST https://iterpec.com/api/catalog/graphql \
  -H "Authorization: Bearer wsk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "query": "query($d:ID!,$l:Int!,$o:Int!){ hotels(destinationId:$d,limit:$l,offset:$o){ id name category latitude longitude } }",
    "variables": { "d": "1006065", "l": 500, "o": 0 }
  }'

syncFull sync paginado (Node.js)

Inclua destinations e hotels na mesma operação para o servidor marcar last_full_sync_at do workspace.

// Full sync paginado (destinos + hotéis) — marca last_full_sync_at no workspace
const ENDPOINT = "https://iterpec.com/api/catalog/graphql";
const TOKEN = process.env.ITERPEC_WORKSPACE_TOKEN; // wsk_*

async function gql(query, variables) {
  const res = await fetch(ENDPOINT, {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${TOKEN}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ query, variables }),
  });
  if (res.status === 429) {
    const retry = Number(res.headers.get("Retry-After") ?? 30);
    await new Promise(r => setTimeout(r, retry * 1000));
    return gql(query, variables);
  }
  const releaseId = res.headers.get("X-Catalog-Release-Id");
  const body = await res.json();
  if (body.errors) throw new Error(JSON.stringify(body.errors));
  return { data: body.data, releaseId };
}

const LIMIT = 500;
const all = { destinations: [], hotels: [] };
let offset = 0;
while (true) {
  const { data, releaseId } = await gql(
    `query($l:Int!,$o:Int!){
        destinations(limit:$l, offset:$o){ id name countryCode type }
        hotels(limit:$l, offset:$o){ id name destinationId category latitude longitude }
      }`,
    { l: LIMIT, o: offset },
  );
  all.destinations.push(...data.destinations);
  all.hotels.push(...data.hotels);
  console.log(`offset=${offset} release=${releaseId} +${data.hotels.length} hotels`);
  if (data.hotels.length < LIMIT && data.destinations.length < LIMIT) break;
  offset += LIMIT;
}
console.log("done", all.destinations.length, all.hotels.length);

monitoringStatus de sincronização

Workspaces que ficam >30 dias sem full sync entram em isStale=true. Após >50 dias, comercial@iterpec.com é notificado automaticamente.

query {
  syncStatus {
    workspaceCid
    currentReleaseId
    lastFullSyncAt
    daysSinceSync
    isStale
  }
  currentRelease {
    id version releasedAt hotelsCount destinationsCount hotelsSha256
  }
}

schedulePolítica de refresh

  • A Iterpec publica novo release mensal — nosso cron ingere automaticamente.
  • Cacheie por release_id. Se mudar → re-sync completo.
  • Não chame HotelDetail para todos os hotéis — só para os tops do Search.
  • Não re-sincronize todo dia: o release só muda mensalmente.

play_circleTry it — executar query agora

Cole seu token wsk_* e dispare uma query real contra /api/catalog/graphql. Útil para validar headers de release, paginação e rate-limit antes de codar.

O token fica apenas no seu navegador (não é enviado para nenhum servidor da Iterpec além do GraphQL endpoint).

errorErros comuns

  • 401 — token ausente, expirado ou não é wsk_* de workspace.
  • 429 — quota excedida; respeite Retry-After.
  • 422 — query inválida; valide com a aba Playground antes.
Dica MCP: peça à sua IA cliente para chamar as tools get_catalog_graphql_recipe e get_catalog_sync_status antes de implementar — elas retornam queries prontas e o estado atual do seu catálogo.