Skip to main content

Overview

What the Novi Kvadrat partner API does, where it lives, how one request travels, and what it deliberately leaves out.

The Novi Kvadrat partner API lets real-estate software (a CRM, an export tool) publish its agencies' sale and rental listings on Novi Kvadrat — with each agency's consent. You push signed JSON; we validate it, stage it, and a worker turns it into listings exactly as the agency's own editor would.

Base URL#

text
https://novikvadrat.rs/api/partners/v1

Sandbox and live use the same base URL. The key you sign with decides the environment: a sandbox key works only with your sandbox apps and their test connections, a live key only with your live app.

Who does what#

  • You (the partner) sign up in the Partner Portal, register an Ed25519 public key, and call the API from your servers.
  • An agency connects your software by generating a connect code in its own Novi Kvadrat portal and handing it to you. Nothing in a payload names an agency: the connection does.
  • Novi Kvadrat staff approve your company, check the first listings of every new connection (certification), and create your live app.

The life of one request#

  1. You build the body bytes, compute Content-Digest, pick a timestamp and a fresh nonce, build the NK-SIG-1 base (method, host, path with query, timestamp, nonce, digest) and sign it with your private key. See NK-SIG-1 signing.
  2. You send the request to https://novikvadrat.rs/api/partners/v1/… with the five signing headers and Content-Type: application/json. No request carries a body on DELETE; data for a delete travels in the signed query (?reason=), and removing a listing is a POST …/remove with a body.
  3. We check, in order: kill switch → body size (4 MiB) → headers → key → app and account → client IP → digest, time, signature → app rate → nonce. The first failure answers with its code; nothing is stored. See Errors.
  4. For a route that names a connection: the connection must belong to the signing app (else 404) and be active (or certifying for listing writes; else 409 connection_not_active with details.status). Listing writes then count against the connection's hourly item budget.
  5. The body is validated against the v1 schema. A single PUT that fails answers 422; a batch answers 202 with per-item rejected results (rejected items are not staged).
  6. Valid items are staged and answered at once (accepted, unchanged, needs_review). The worker imports accepted items of active connections within about a minute (photos can take longer and retry). Items of a paused connection wait and import after the agency resumes.
  7. Final outcomes arrive as webhooks (item.imported, item.failed, …), in the reconcile view and in the Partner Portal. GET /batches/{id} shows each item's push-time result (the answer from step 6) plus the link to its listing once one exists; it is not updated with the final outcome.

Every response carries NK-Request-Id (quote it to support) and Cache-Control: no-store.

What the API does not do#

  • No search or browse of other agencies' listings.
  • No lead or inquiry read (planned for a later version).
  • No photo upload endpoint: photos are HTTPS URLs that our fetcher downloads.
  • No admin or staff operations, no partner-side pause, no way to create an agency, and no way to name an agency except through a connect code.

Where to go next#

Questions? Write to partners@novikvadrat.rs.

Last updated