Docs

Tools over the API

Last updated: 2026-09-074 min read

The same tools you use in the cabinet are available programmatically. Every call is billed from your wallet exactly as work through the interface is: subscription first, then the bundle, then pay as you go. Reads (GET) are never billed.

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

The tools

CallKey scopeHow it works
POST /valuation/expressany keysynchronous
POST /valuation/reporttools:valuationdeferred
POST /valuation/renttools:rentsynchronous
POST /valuation/reviewtools:reviewdeferred, with a file
POST /content/generatetools:contentgendeferred
POST /text/generatetools:textdeferred
POST /avatar/videotools:avatardeferred
POST /video/createtools:videodeferred, with a file
POST /photo/enhancetools:photodeferred, with a file
POST /floorplan/createtools:floorplandeferred, with a file
POST /draft/extracttools:draftsynchronous, with a file
POST /site/createtools:sitegensynchronous, needs a listing
POST /pdf/createtools:pdfdeferred, needs a listing

If the key lacks the scope, the call returns 403. Scopes are granted when you create the key in the cabinet: AI tools → API → Keys. See Authentication.

Synchronous calls

A synchronous tool returns 200 with the finished result in the response body:

curl -X POST https://developers.grem.capital/api/v1/valuation/rent \
  -H "Authorization: Bearer gsk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"propertyCategory":"apartment","totalArea":50,"city":"Kyiv"}'

Deferred calls

Long-running tools (the valuation report, texts, photo, video, avatar, floor plan, PDF) return 202 and a handle for the job:

{ "jobId": "…", "status": "pending", "requestId": "req_…" }

Poll the status at GET /<tool path>/jobs/{jobId}:

curl -H "Authorization: Bearer gsk_live_xxx" \
  https://developers.grem.capital/api/v1/content/generate/jobs/JOB_ID

The response carries a status field. Terminal states are completed (or done, success) and failed. While the job is running, repeat the request every few seconds.

Polling is free: a GET is not counted as an API call and is not billed. Even so, subscribing to an event beats tight polling - see Webhooks.

Every job belongs to the key that created it. Someone else's jobId always returns 404, even when such a job exists.

Tools that take a file

Calls marked "with a file" accept multipart/form-data: the options go into a text field named data as JSON, and the file itself is a separate part.

curl -X POST https://developers.grem.capital/api/v1/photo/enhance \
  -H "Authorization: Bearer gsk_live_xxx" \
  -F 'data={"mode":"enhance"}' \
  -F "image=@room.jpg"

Sending plain JSON to one of these returns 400 with a note that multipart/form-data is expected.

Tools that need a listing

The site generator and the PDF generator build a presentation from an existing listing, so the request body must carry an objectId (or a collectionId for a collection). The listing has to be yours - someone else's id returns an access error.

curl -X POST https://developers.grem.capital/api/v1/pdf/create \
  -H "Authorization: Bearer gsk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"objectId":"64f…","language":"en"}'

The finished files

Results (PDFs, videos, images, pages) come back as links on the GREM domain. Download them through GET /artifacts/… with the same key - see Files and results.

Retrying without duplicates

Creating a job is safe to retry: send an Idempotency-Key header and a retry with the same key replays the original result instead of billing you twice. Details in Idempotency.

What the errors mean

  • 402 - not enough money in the wallet, or the plan quota is used up.
  • 403 - the key has no scope for this tool.
  • 429 - the rate limit was hit; retry after the pause in the Retry-After header.

The full list is in Errors.

Was this article helpful?