Concepts
The operation
The unit that gets worked, moved and closed.
A contact is not a deal. Neither is a property. What a brokerage actually works is one concrete intention held by one concrete person: this woman wants to buy, this man wants to rent, this owner wants to sell. That is an operation, and it is the object the whole API turns around.
What hangs off it
lead (the person)
└─ operation (buy · rent · sell)
├─ stage + assigned agent
├─ opportunities → candidate properties
├─ viewings
├─ offers
└─ documents and signatures
A property does not belong to the operation: it is related to it through an opportunity. That is why the same apartment can sit in three buyers' operations at once without being duplicated, and why a buy operation can narrow from six candidates to one without losing the history.
One open operation per type
A lead has at most one open operation per type. If Ana already has an open
buy operation and writes again about another apartment, no second deal opens:
one more opportunity is added.
That has a direct consequence in the API:
curl -X POST "$ORKASA_API/operations" \
-H "Authorization: Bearer $ORKASA_KEY" \
-H 'Content-Type: application/json' \
-d '{ "lead_id": "4af8…", "operation_type": "buy" }'
returns 200 with the operation that already existed — not a 409, not a
duplicate. 201 means it was created now. A repeated POST is safe: it is the
normal way to write a find-or-create Zap.
Demand and supply
The operation type decides which side of the market a lead sits on, and there is no separate field that says so:
operation_type | side | what it means |
|---|---|---|
buy | demand | looking to buy |
rent | demand | looking to rent |
sell | supply | wants to list a property (captación) |
If you filter demand leads, filter on operation_type. There is no
lead_type field: deriving it from something else is the fastest way to
miscount the funnel.
POST /leads accepts buy and rent. sell is rejected with 422, on
purpose: a listing is negotiated with an owner and ends in a signed mandate; it
never starts from an API call, and forcing it into a demand operation would be
worse than refusing it.
An operation does not close by accident
Terminal states are won · sold · rented and lost · expired ·
cancelled. The first group is only reachable from the last active stage of
the flow, gate passed: you cannot win a deal you never worked. The second is
reachable from anywhere — a deal can die at any point — and lost requires its
lost_reason.
A closed operation no longer moves: any attempt returns 422 with
details.reason = "operation_closed".
The full journey per operation type, and why it changes by country.