Docs

Leads via API

Last updated: 2026-10-035 min read

This section gives programmatic access to your own CRM leads: a website or an external form can send inquiries straight into the cabinet, and your system can read them and move them through statuses.

Base URL: https://developers.grem.capital/api/v1.

Leads are private. Unlike the public listing catalog, there is no access without the right scope: reading needs leads:read, changes need leads:write. You see only the leads where you are the sender or the recipient. Requests are not charged.

List

GET /leads?status=new&type=buy&priority=hot&page=1&limit=20
Authorization: Bearer gsk_live_...

Filters: status, type, priority, source, role, archived, pool, from, to, page, limit, sort. Archived leads are not in the normal list - add archived=true. pool=true (agency keys only) - the leads in the agency's shared pool; a personal key ignores it.

limit (1-50, default 20) and page (from 1) outside the range are cut into it, not refused. Other invalid values of a known parameter (an unknown enum value, a non-integer page, an invalid date in from or to) are refused with 400 validation naming the field.

One lead

GET /leads/{id}?expand=history,documents

expand adds the status and action history (history) and the attached documents (documents).

Lead shape

  • id, status, type, priority, source, tags, isArchived; type - buy, rent, viewing, sell, contract, transfer or user
  • createdAt, updatedAt, lastActivityAt
  • customer - name, country, messenger and a contact block (phone, email, messengerHandle, profileUrl)
  • budget - { value, currency }
  • intent - city, districts, deal type and the client's intent
  • comments - the client's comment and your own, separately
  • object - the listing the inquiry is about
  • agency - only on agency leads: the agency id and whether the lead sits in the shared pool

Other brokers' contacts, internal scores and service flags are never returned.

Send in an inquiry

curl -X POST https://developers.grem.capital/api/v1/leads \
  -H "Authorization: Bearer gsk_live_xxx" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: form-2026-09-07-0001" \
  -d '{
    "customer": {
      "name": "Olena Kovalchuk",
      "country": "UA",
      "contact": { "phone": "+380971234567", "email": "[email protected]" }
    },
    "type": "buy",
    "budget": { "value": 120000, "currency": "USD" },
    "intent": { "targetCity": "Kyiv", "leadIntent": "buyer" },
    "comments": "Looking for a 2-room flat near the metro",
    "priority": "warm",
    "consent": true
  }'

Required: customer.name and at least one way to reach the client in customer.contact. type - buy (default) or rent. priority - hot, warm or cold. Add objectId if the inquiry is about a specific listing, and up to ten of your own tags.

Idempotency-Key saves you from duplicates: if your form repeats the request after a timeout, the lead is not created twice. See Idempotency.

pool: true sends the inquiry to the shared distribution pool instead of your CRM. By default the lead comes to you.

Every lead created through the API is marked with the «API» source in the cabinet, so you can tell it apart.

Change a lead

PATCH /leads/{id}
{ "status": "in progress", "priority": "hot", "tags": ["mortgage"], "brokerComments": "..." }

You can change the status, priority, tags and your own comment. One field is enough. Statuses: new, in progress, processing, agreement, closed, not target, failed. The cabinet rules apply: a lead with a listing is closed through finalization in the cabinet (code: finalize), a lead waiting for the commission keeps its status (fee_pending), a closed deal under a contract changes only in the cabinet (closed) - 422 with the reason in code. Other reasons: sender (you passed the lead on - its recipient handles it), module (a Swipe Match lead, its status follows the module), agreement, network_readonly, forbidden.

Remove a lead

DELETE /leads/{id}

This archives the lead rather than deleting it: it leaves the normal list but stays available with ?archived=true. A lead with an active contract or a finalization agreement, a closed lead with a listing that is not finalized, and a lead waiting for the commission are not archived: 422 with code contract_active, agreement, finalize or fee_pending.

Listings for a lead

GET /leads/{id}/matches?page=1&limit=20

Returns listings that fit the client's request: type, city and budget come from the lead itself or from the linked listing. Free.

Agency pool

Agency keys have two pool actions:

POST /leads/{id}/claim               take a lead from the pool
POST /leads/{id}/claim?assignTo=...  assign it to a team member
POST /leads/{id}/return-to-pool      return a lead to the pool
  • Claim: by default the lead goes to the agency owner; assignTo (member id) can be passed by the owner or a manager.
  • Return to pool: a manager and above, or the agent the lead is assigned to. Optional body: {"reason": "..."}. A lead the pool rules archived - 422 with code: pool_archived: restore it in the cabinet first.
  • A personal key or an insufficient role - 403 with title: forbidden; claiming a lead that is no longer in the pool - 404.
  • Both actions send a lead.updated event.

Watching for changes

Instead of polling the list, subscribe to lead.created and lead.updated - see Webhooks. The event has no personal data: it only says which lead changed; you read the card with a separate request.

Was this article helpful?