zoodealio 0.3.1-dev.1641 → 0.4.0-dev.1648

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +38 -12
  2. package/package.json +1 -1
  3. package/src/commands.js +13 -11
package/README.md CHANGED
@@ -132,7 +132,7 @@ Route IDs are GUIDs and are checked before any request is made.
132
132
  Write bodies come from `--body '<json>'`, `--body @file.json` or `--body -` (stdin). Where
133
133
  a body is trivial, convenience flags build it instead; use one or the other, not both.
134
134
  List commands accept `--page` and `--page-size`. `--if-match <etag>` sends optimistic
135
- concurrency on `properties update`, `offers accept` and `offers request-details`.
135
+ concurrency on `properties update` and `comping start`.
136
136
 
137
137
  ## Commands
138
138
 
@@ -148,14 +148,16 @@ concurrency on `properties update`, `offers accept` and `offers request-details`
148
148
  | `properties documents list\|add\|delete` | documents | same shape as photos |
149
149
  | `properties import-status <id> <importId>` | GET imports/{importId} | Photo and document imports |
150
150
  | `offers list` | GET Offers | `--property` required, `--status` |
151
- | `offers get <id>`, `offers history <id>` | GET | |
152
- | `offers accept <id>` | POST accept | `--yes` required; `--attributes <json\|@file>`, `--if-match` |
153
- | `offers request-details <id>` | POST request-details | `--if-match` |
151
+ | `offers get <id>` | GET Offers/{id} | Read-only: `amount` for actual offers, `estimatedRange` for estimates |
154
152
  | `transactions get <id>` | GET Transactions/{id} | |
155
153
  | `transactions active` | GET Transactions/active | `--property` required |
156
- | `comping status <transactionId>` | GET Transactions/{id}/comping | |
154
+ | `comping start <transactionId>` | POST Transactions/{id}/comping | `--if-match`; starts cash-offer comping |
155
+ | `comping status <transactionId>` | GET Transactions/{id}/comping | `status` and `links` |
156
+ | `ai-comping start <propertyId>` | POST Properties/{id}/ai-comping | Starts an AI Comping report; returns `{transactionId}` |
157
+ | `ai-comping status <transactionId>` | GET Transactions/{id}/ai-comping | `status` (`running`, `ready`, `failed`), values, `offers`, `links` |
157
158
  | `team members`, `team get <id>`, `teams list` | GET Team | `--search`; `team members` also lists pending invites (`kind: "invite"`) |
158
159
  | `team invite` | POST Team/members | `--email` (+ `--first-name`, `--last-name`, `--team`, `--admin-team`) or `--body` |
160
+ | `team join-codes list\|save\|delete` | GET, PUT, DELETE Team/join-codes | `save`: `--body` (create or update); `delete <id>` needs `--yes` |
159
161
  | `team remove <id>` | DELETE Team/members/{id} | `--yes` required |
160
162
  | `webhooks event-types\|list\|deliveries` | GET Webhooks | `deliveries`: `--subscription`, `--status` |
161
163
  | `webhooks create` | POST Webhooks | `--url` and `--event` (repeatable) or `--body` |
@@ -169,7 +171,7 @@ concurrency on `properties update`, `offers accept` and `offers request-details`
169
171
  | `api <METHOD> <path>` | any `/openapi/...` | `--query k=v` (repeatable), `--body`; `DELETE` needs `--yes` |
170
172
  | `commands` | | Command catalogue as JSON |
171
173
 
172
- Destructive commands (`keys revoke`, `offers accept`, `team remove`, `properties photos delete`,
174
+ Destructive commands (`keys revoke`, `team remove`, `team join-codes delete`, `properties photos delete`,
173
175
  `properties documents delete`, `webhooks rotate`, `webhooks delete`, and `api ... DELETE`)
174
176
  refuse to run without `--yes`, exit 2, and send nothing. `--dry-run` previews them
175
177
  without `--yes`, since it sends nothing either.
@@ -177,6 +179,27 @@ without `--yes`, since it sends nothing either.
177
179
  `api` accepts `Properties` or `/openapi/Properties`. Paths that are absolute URLs, contain
178
180
  `..`, or fall outside `/openapi/` are rejected.
179
181
 
182
+ ## Core flow and links
183
+
184
+ Partners create properties, start comping, read amounts and send people to Zoodealio for
185
+ everything else (terms, documents, acceptance). The loop:
186
+
187
+ 1. `properties create`, then `offers list --property <id>` for the estimated range.
188
+ 2. `transactions active --property <id>`, then `comping start <transactionId>`.
189
+ 3. Wait for the `comping.completed` webhook, or poll `comping status <transactionId>`.
190
+ 4. Read amounts with `offers list`; open the `links` for the rest.
191
+
192
+ `comping status`, `ai-comping status` and transactions carry a `links` object:
193
+
194
+ ```json
195
+ { "links": { "agent": "https://.../properties/<id>/offer-reveal", "homeowner": "https://.../dashboard/<id>/<ref>?next=reveal" } }
196
+ ```
197
+
198
+ `agent` is the agent's page for the transaction's current step. `homeowner` is the
199
+ homeowner's sign-in link for the same step, or `null` when the property has no homeowner
200
+ (for AI Comping, `null` until the agent shares the report). Offers are read-only and carry
201
+ `amount` only (actual offers); there is no accept or request-details command.
202
+
180
203
  ## Examples
181
204
 
182
205
  ```sh
@@ -185,15 +208,18 @@ zoodealio properties list --search "Elm St" --state AZ
185
208
  zoodealio properties photos add <propertyId> --url https://example.com/front.jpg
186
209
  zoodealio properties import-status <propertyId> <importId>
187
210
 
188
- # Offers: list for a property, preview an accept, then accept
211
+ # Offers (read-only): the estimated range, then actual amounts once comping is done
189
212
  zoodealio offers list --property <propertyId>
190
- zoodealio offers accept <offerId> --dry-run
191
- zoodealio offers accept <offerId> --yes
192
213
 
193
- # Transactions and comping
214
+ # Transactions and comping: start, check, then hand the user the links
194
215
  zoodealio transactions active --property <propertyId>
216
+ zoodealio comping start <transactionId>
195
217
  zoodealio comping status <transactionId>
196
218
 
219
+ # AI Comping report
220
+ zoodealio ai-comping start <propertyId>
221
+ zoodealio ai-comping status <transactionId>
222
+
197
223
  # Team
198
224
  zoodealio team invite --email new@example.com --first-name Ada --team <teamId>
199
225
 
@@ -213,10 +239,10 @@ zoodealio api GET Properties --query pageSize=5
213
239
  - Run writes with `--dry-run` first and check the URL and body, then run them again
214
240
  without it.
215
241
  - `--yes` is a gate for explicit human intent. Pass it only when the person asked for that
216
- destructive action (accepting an offer, removing a member, deleting or rotating a
242
+ destructive action (removing a member, deleting or rotating a
217
243
  webhook); do not add it to make an error go away.
218
244
  - For request body shapes run `zoodealio openapi`, which prints the partner OpenAPI document.
219
- - Prefer webhooks, or polling `comping status` and `import-status`, to long waits. The
245
+ - Prefer webhooks, or polling `comping status`, `ai-comping status` and `import-status`, to long waits. The
220
246
  [developer docs](https://zoodealio.ai/developers#webhooks) cover events, signatures and delivery.
221
247
 
222
248
  ## Limits
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zoodealio",
3
- "version": "0.3.1-dev.1641",
3
+ "version": "0.4.0-dev.1648",
4
4
  "description": "Zoodealio command line tool: the partner API as JSON, built for people, scripts and AI agents",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {
package/src/commands.js CHANGED
@@ -1,5 +1,4 @@
1
1
  const { usage } = require('./errors');
2
- const { parseJsonArg } = require('./input');
3
2
 
4
3
  /**
5
4
  * @typedef {{name: string, type: 'string' | 'boolean', description: string, multiple?: boolean,
@@ -86,20 +85,20 @@ const COMMANDS = [
86
85
  flags: [str('property', 'Property id', { query: 'propertyId', required: true }), str('status', 'Offer status filter', { query: 'status' }), ...PAGING],
87
86
  }),
88
87
  cmd('offers get', 'Get one offer', 'GET', '/openapi/Offers/{id}', { args: [id('id', 'Offer id')] }),
89
- cmd('offers history', 'Get an offer\'s revision history', 'GET', '/openapi/Offers/{id}/history', { args: [id('id', 'Offer id')] }),
90
- cmd('offers accept', 'Accept an offer; returns the transaction', 'POST', '/openapi/Offers/{id}/accept', {
91
- args: [id('id', 'Offer id')], destructive: true, body: 'optional', convenience: ['attributes'],
92
- flags: [str('attributes', 'Homeowner-confirmed property attributes: JSON or @file'), IF_MATCH],
93
- build: (f) => (f.attributes === undefined ? undefined : { attributes: parseJsonArg(f.attributes, '--attributes') }),
94
- }),
95
- cmd('offers request-details', 'Ask the agent for the offer\'s full breakdown', 'POST', '/openapi/Offers/{id}/request-details', {
96
- args: [id('id', 'Offer id')], flags: [IF_MATCH],
97
- }),
98
88
  cmd('transactions get', 'Get one transaction', 'GET', '/openapi/Transactions/{id}', { args: [id('id', 'Transaction id')] }),
99
89
  cmd('transactions active', 'Get a property\'s active transaction', 'GET', '/openapi/Transactions/active', {
100
90
  flags: [str('property', 'Property id', { query: 'propertyId', required: true })],
101
91
  }),
102
- cmd('comping status', 'Get AI comping status for a transaction', 'GET', '/openapi/Transactions/{transactionId}/comping', {
92
+ cmd('comping start', 'Start comping for a transaction', 'POST', '/openapi/Transactions/{transactionId}/comping', {
93
+ args: [id('transactionId', 'Transaction id')], flags: [IF_MATCH],
94
+ }),
95
+ cmd('comping status', 'Get comping status and links for a transaction', 'GET', '/openapi/Transactions/{transactionId}/comping', {
96
+ args: [id('transactionId', 'Transaction id')],
97
+ }),
98
+ cmd('ai-comping start', 'Start an AI Comping report for a property', 'POST', '/openapi/Properties/{propertyId}/ai-comping', {
99
+ args: [id('propertyId', 'Property id')],
100
+ }),
101
+ cmd('ai-comping status', 'Get an AI Comping report\'s status, values, offers and links', 'GET', '/openapi/Transactions/{transactionId}/ai-comping', {
103
102
  args: [id('transactionId', 'Transaction id')],
104
103
  }),
105
104
  cmd('team members', 'List team members, including pending invites', 'GET', '/openapi/Team/members', {
@@ -123,6 +122,9 @@ const COMMANDS = [
123
122
  cmd('teams list', 'List teams', 'GET', '/openapi/Team/teams', {
124
123
  flags: [str('search', 'Free-text search', { query: 'search' }), ...PAGING],
125
124
  }),
125
+ cmd('team join-codes list', 'List workspace join codes', 'GET', '/openapi/Team/join-codes'),
126
+ cmd('team join-codes save', 'Create or update a join code', 'PUT', '/openapi/Team/join-codes', { body: 'required', flags: [BODY] }),
127
+ cmd('team join-codes delete', 'Delete a join code', 'DELETE', '/openapi/Team/join-codes/{id}', { args: [id('id', 'Join code id')], destructive: true }),
126
128
  cmd('webhooks event-types', 'List webhook event types', 'GET', '/openapi/Webhooks/event-types'),
127
129
  cmd('webhooks list', 'List webhook subscriptions', 'GET', '/openapi/Webhooks'),
128
130
  cmd('webhooks create', 'Create a webhook subscription', 'POST', '/openapi/Webhooks', {