GraphQL API

GoToApi Leads GraphQL API

Cursor-paginated queries + SSE real-time subscriptions. Auth via X-API-Key header or ?api_key= query param.

Endpoints

POST /api/graphql

Queries with cursor pagination

GET /api/graphql/subscription

SSE real-time new-lead stream

Get your key from the dashboard → Settings → Private API Key.

Schema

type Query {
  # Simple flat list (max 1000 results, no cursor)
  leads(district: String): [Lead!]!

  # Cursor-paginated — RECOMMENDED for production CRM integration
  leadsConnection(
    district: String   # filter by Warsaw district name
    first:    Int      # page size  default: 20  max: 100
    after:    String   # cursor from pageInfo.endCursor of previous page
  ): LeadsConnection!

  totalCount: Int!
  me: UserPlan!
}

type LeadsConnection {
  edges:      [LeadEdge!]!
  pageInfo:   PageInfo!
  totalCount: Int!        # total matching leads across ALL pages
}

type LeadEdge {
  cursor: String!         # opaque — pass as "after" to fetch next page
  node:   Lead!
}

type PageInfo {
  hasNextPage:     Boolean!
  hasPreviousPage: Boolean!
  startCursor:     String
  endCursor:       String  # pass this as "after" on next request
}

type Lead {
  id         String
  source     String   # "olx" | "gratka"
  title      String
  url        String
  price      String
  priceValue Float
  district   String
  location   String
  image      String
  areaM2     Float
  rooms      String
  floor      String
  createdAt  String   # RFC3339
  isNew      Boolean
}

type UserPlan {
  uid                String
  email              String
  planId             String
  subscriptionStatus String
  selectedDistricts  [String]
}

1. Cursor-Paginated Query

RECOMMENDED

First page — no after needed:

query Page1 {
  leadsConnection(district: "Mokotow", first: 20) {
    totalCount
    pageInfo { hasNextPage endCursor }
    edges {
      cursor
      node {
        id title price priceValue
        district location url source
        areaM2 rooms floor createdAt
      }
    }
  }
}

Next page — use endCursor as after:

query Page2 {
  leadsConnection(district: "Mokotow", first: 20, after: "MTc5MDg1NzUwMzQ0ODow") {
    pageInfo { hasNextPage endCursor }
    edges { cursor node { id title price url createdAt } }
  }
}

2. cURL

# First page
curl -X POST https://yourdomain.pl/api/graphql \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_KEY" \
  -d '{"query":"{ leadsConnection(district:\"Mokotow\",first:20){ totalCount pageInfo{hasNextPage endCursor} edges{cursor node{id title price url createdAt}} } }"}'

# Next page (replace CURSOR with endCursor from above)
curl -X POST https://yourdomain.pl/api/graphql \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_KEY" \
  -d '{"query":"{ leadsConnection(first:20,after:\"CURSOR\"){ pageInfo{hasNextPage endCursor} edges{cursor node{id title price url}} } }"}'

3. JavaScript — Full Pagination Loop

async function fetchAllLeads(district = 'Mokotow', pageSize = 50) {
  const API = 'https://yourdomain.pl/api/graphql';
  const KEY = 'YOUR_API_KEY';
  let after = null;
  const all = [];

  do {
    const afterPart = after ? ', after: "' + after + '"' : '';
    const query = '{ leadsConnection(district: "' + district + '", first: ' + pageSize + afterPart + ') { pageInfo { hasNextPage endCursor } edges { node { id title price url district createdAt } } } }';

    const res = await fetch(API, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json', 'X-API-Key': KEY },
      body: JSON.stringify({ query }),
    });
    const { data } = await res.json();
    const conn = data.leadsConnection;
    all.push(...conn.edges.map(e => e.node));
    after = conn.pageInfo.hasNextPage ? conn.pageInfo.endCursor : null;
  } while (after);

  return all;  // all leads across all pages
}

4. SSE Subscription — Real-Time New Leads

curl -N -H "X-API-Key: YOUR_KEY" \
  "https://yourdomain.pl/api/graphql/subscription?district=Mokotow"
const sse = new EventSource(
  '/api/graphql/subscription?api_key=YOUR_KEY&district=Mokotow'
);
sse.addEventListener('next', (e) => {
  const { data } = JSON.parse(e.data);
  console.log('New lead:', data.leadAdded);
});
sse.addEventListener('connected', (e) => console.log('Connected:', JSON.parse(e.data)));

Rate Limits

← Back to Lead Monitor