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
| Call | Key scope | How it works |
|---|---|---|
POST /valuation/express | any key | synchronous |
POST /valuation/report | tools:valuation | deferred |
POST /valuation/rent | tools:rent | synchronous |
POST /valuation/review | tools:review | deferred, with a file |
POST /content/generate | tools:contentgen | deferred |
POST /text/generate | tools:text | deferred |
POST /avatar/video | tools:avatar | deferred |
POST /video/create | tools:video | deferred, with a file |
POST /photo/enhance | tools:photo | deferred, with a file |
POST /floorplan/create | tools:floorplan | deferred, with a file |
POST /draft/extract | tools:draft | synchronous, with a file |
POST /site/create | tools:sitegen | synchronous, needs a listing |
POST /pdf/create | tools:pdf | deferred, 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 theRetry-Afterheader.
The full list is in Errors.
Related articles
- Quickstart - your first call in five minutes.
- Webhooks - get the finished result instead of polling.
- Files and results - uploading images and downloading artifacts.