Deals
A deal is a revenue opportunity. It has a name, a stage, an amount, a currency, a close date and a status (open, won or lost), and it can be linked to a company, a contact, or both.
Deals exist only in Pathbound. No integration brings them in from a CRM: a deal is created through this API, by an AI agent through the MCP server, or by a person in the dashboard. To mirror deals from another system, create them here and put that system’s id in external_deal_id. A deal cannot be a member of a segment, and a change to a deal is not delivered to a stream.
The MCP tools list_deals, get_deal, create_deal, create_deals_bulk, update_deal, delete_deal, list_deal_notes, create_deal_note, update_deal_note, delete_deal_note, add_deal_tags and remove_deal_tags call the endpoints on this page. See the tools reference.
| Endpoint | Scope | What it does |
|---|---|---|
POST /v1/deals | deals:write | Creates a deal, or updates the one that has your external_deal_id. |
POST /v1/deals/bulk | deals:write | Creates or updates up to 1,000 deals in one request. |
GET /v1/deals | deals:read | Lists and filters deals. |
GET /v1/deals/:deal_id | deals:read | Returns one deal with its company and contact. |
PUT /v1/deals/:deal_id | deals:write | Changes a deal’s properties or links. |
DELETE /v1/deals/:deal_id | deals:write | Deletes a deal. |
GET /v1/deals/:deal_id/notes | deals:read | Lists a deal’s notes. |
POST /v1/deals/:deal_id/notes | deals:write | Adds a note to a deal. |
PATCH /v1/deals/:deal_id/notes/:note_id | deals:write | Changes a note’s text. |
DELETE /v1/deals/:deal_id/notes/:note_id | deals:write | Deletes a note. |
POST /v1/deals/:deal_id/tags | deals:write | Adds tags to one deal. See Tags. |
DELETE /v1/deals/:deal_id/tags | deals:write | Removes tags from one deal. See Tags. |
POST /v1/deals/tags/bulk | deals:write | Adds and removes tags on up to 1,000 deals. See Tags. |
Neither scope is opt-in. See Scopes.
Deals can also be read through POST /v1/batch/details (up to 25 by id) and summed or counted through POST /v1/aggregate. To total a pipeline by stage, use the aggregate endpoint instead of paging through this list.
Usage and Metering
Section titled “Usage and Metering”Reading a deal counts as reading the customer it belongs to: the deal’s company or, failing that, its contact. A deal linked to neither counts as a customer of its own. GET /v1/deals/:deal_id always counts. GET /v1/deals counts for every deal on the page, unless you ask for fields=ids or count_only=true. A customer you have already read in the billing cycle is not counted again. The notes endpoints, the tag endpoints and every write are free. The deal endpoints have no dry_run: to learn what a read would cost, use dry_run on POST /v1/batch/details. See Usage and metering.
The Deal Object
Section titled “The Deal Object”{ "deal_id": "6acd7a3e9b1c4d2e8f012345", "_id": "6acd7a3e9b1c4d2e8f012345", "properties": { "name": "Northwind annual plan", "stage": "negotiation", "amount": 24000, "currency": "USD", "status": "open", "close_date": "2026-10-30T00:00:00.000Z", "createdate": "2026-10-13T09:14:02.118Z", "lastmodifieddate": "2026-10-13T09:14:02.118Z" }, "company_id": "665f1c2ab3d4e5f601234567", "contact_id": "665f1c2ab3d4e5f6012345ab", "external_deal_id": "crm-48213", "notes": [], "tags": ["renewal", "q4"], "creation_source": "api", "first_seen_at": "2026-10-13T09:14:02.118Z", "created_at": "2026-10-13T09:14:02.118Z", "updated_at": "2026-10-13T09:14:02.118Z"}| Field | Description |
|---|---|
deal_id | The deal’s id. _id repeats it; use deal_id. |
properties.name | The deal’s name. |
properties.stage | The pipeline stage. Stages are your own names: Pathbound keeps no list of them. |
properties.amount | The deal’s value, a number from 0 to 1e15. |
properties.currency | A three-letter code, uppercase. |
properties.status | open, won or lost. |
properties.close_date | The expected or actual close date. |
properties.createdate, properties.lastmodifieddate | Set by Pathbound when the deal is created and when its properties change. |
properties.* | Any other key you stored. |
company_id, contact_id | The linked company and contact. Absent when the deal is not linked. |
external_deal_id | Your own id for the deal, when you gave one. |
notes | Every note on the deal. See List Deal Notes for a note’s fields. |
tags | The deal’s tags. Always an array. |
creation_source | api for a deal created through this API or the MCP server, manual for one created in the dashboard. |
first_seen_at, created_at | When the deal was created. |
updated_at | When the deal last changed. |
Create a Deal
Section titled “Create a Deal”POST /v1/dealsRequired scope: deals:write
Creates one deal. No field is required: an empty body creates a deal with status: "open", currency: "USD" and nothing else.
With an external_deal_id the call is an upsert on it: when a deal in your workspace already has that id, the call updates that deal and is answered 200 with "created": false. The same request sent twice therefore leaves one deal, unchanged by the second call. On an update:
- a property you send replaces the stored value, and one you leave out, or send as
null, keeps it; statusandcurrencyare not reset to their defaults;- a
company_id,contact_id,companyorcontactyou send replaces the link, and one you leave out keeps it. A company inherited from the contact only fills a deal that has none; tagsare added to the deal’s own.
Request Body
Section titled “Request Body”| Field | Type | Required | Description |
|---|---|---|---|
properties | object | no | The deal’s fields. See the table below. |
company_id | string | no | The company to link. It must exist in your workspace. |
company | object | no | The company to link, by your own key instead of its Pathbound id: { "external_id": "…" } (the id you gave the account on Create a Company) or { "domain": "…" }. Not with company_id. |
contact_id | string | no | The contact to link. It must exist in your workspace. When you send a contact and no company, the deal is also linked to that contact’s company, if the contact has one. |
contact | object | no | The contact to link, by your own key: { "external_id": "…" } (the id you gave the person on Create a Contact or identify) or { "email": "…" }. Not with contact_id. |
external_deal_id | string | no | Your own id for the deal, up to 255 characters, unique in the workspace. It cannot be changed afterwards. A deal that already has it is updated. |
tags | string[] | no | Up to 50 tags to put on the deal. |
Fields of properties:
| Field | Type | Description |
|---|---|---|
name | string | The deal’s name. |
stage | string | The pipeline stage, in your own words (discovery, negotiation). Use the same spelling each time. |
amount | number | From 0 to 1e15. A numeric string is converted to a number. |
currency | string | Three letters, stored uppercase. Defaults to USD. It is not checked against a list of currencies. |
status | string | open (the default), won or lost. Stored lowercase. |
close_date | string | An ISO 8601 date. It may be in the future. |
| any other key | Stored as a custom property. A string value can be at most 1,000 characters. |
Pathbound sets createdate and lastmodifieddate itself, whatever you send for them.
A company or contact key only looks a record up: one that finds nothing is a 422 and no deal is created or changed, never a new company or contact. Write the account and the person first, then their deal.
curl -X POST https://api.pathbound.ai/v1/deals \ -H "Authorization: Bearer $PATHBOUND_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "properties": { "name": "Northwind annual plan", "stage": "negotiation", "amount": 24000, "close_date": "2026-10-30" }, "company_id": "665f1c2ab3d4e5f601234567", "contact_id": "665f1c2ab3d4e5f6012345ab", "external_deal_id": "crm-48213", "tags": ["renewal", "q4"] }'Response — 201 Created
Section titled “Response — 201 Created”A deal created. A deal updated through its external_deal_id is answered 200 OK in the same shape, with "created": false and "message": "Deal updated successfully".
{ "status": "success", "message": "Deal created successfully", "created": true, "deal": { "deal_id": "6acd7a3e9b1c4d2e8f012345", "_id": "6acd7a3e9b1c4d2e8f012345", "properties": { "name": "Northwind annual plan", "stage": "negotiation", "amount": 24000, "close_date": "2026-10-30T00:00:00.000Z", "status": "open", "currency": "USD", "createdate": "2026-10-13T09:14:02.118Z", "lastmodifieddate": "2026-10-13T09:14:02.118Z" }, "company_id": "665f1c2ab3d4e5f601234567", "contact_id": "665f1c2ab3d4e5f6012345ab", "external_deal_id": "crm-48213", "notes": [], "tags": ["renewal", "q4"], "creation_source": "api", "first_seen_at": "2026-10-13T09:14:02.118Z", "created_at": "2026-10-13T09:14:02.118Z", "updated_at": "2026-10-13T09:14:02.118Z" }, "timestamp": "2026-10-13T09:14:02.201Z"}Error Codes
Section titled “Error Codes”| Status | Meaning |
|---|---|
400 | A field has the wrong type or a property was refused. See Errors. code: "INVALID_LINK" when company or contact is not an object with exactly one of its two keys, or is sent beside company_id or contact_id. |
404 | company_id or contact_id names no record in your workspace. The error text is Company not found or Contact not found. |
422 | code: "CONTACT_NOT_FOUND" or "COMPANY_NOT_FOUND": the contact or company key finds no record. |
429 | The workspace has reached its limit on stored deals (code: "QUOTA_EXCEEDED"). An update of an existing deal is never refused for it. |
Create Deals in Bulk
Section titled “Create Deals in Bulk”POST /v1/deals/bulkRequired scope: deals:write
Creates up to 1,000 deals in one request. Each item is handled on its own: a bad item is reported as that item’s error and the others are still created.
The same rules apply as for a single create. Sending the same request twice creates every deal twice, except the items that carry an external_deal_id: an item whose id a deal already has updates that deal, as Create a Deal does, and comes back as updated.
Request Body
Section titled “Request Body”| Field | Type | Required | Description |
|---|---|---|---|
deals | object[] | yes | 1 to 1,000 items. Each takes the fields of Create a Deal: properties, company_id, company, contact_id, contact, external_deal_id, tags. |
An item’s tags are put on the deal it creates or updates.
Response — 200 OK
Section titled “Response — 200 OK”{ "status": "success", "requested": 3, "created": 1, "updated": 1, "errors": 1, "results": [ { "index": 0, "external_deal_id": "crm-48213", "name": "Northwind annual plan", "status": "updated", "id": "6acd7a3e9b1c4d2e8f012345" }, { "index": 1, "external_deal_id": "crm-48214", "name": "Northwind add-on seats", "status": "created", "id": "6acd7b109b1c4d2e8f012377" }, { "index": 2, "name": "Contoso pilot", "status": "error", "error": "Invalid amount. Must be a number >= 0." } ], "timestamp": "2026-10-13T09:15:40.512Z"}| Field | Description |
|---|---|
requested | The number of items you sent. created, updated and errors add up to it. |
results[].index | The item’s position in deals, from 0. |
results[].external_deal_id, results[].name | Echoed from the item when it had them. |
results[].status | created, updated or error. |
results[].id | The deal’s id, for created and updated. |
results[].error | Why the item was refused, for error. |
results[].code | For an item refused over its company or contact: INVALID_LINK, CONTACT_NOT_FOUND or COMPANY_NOT_FOUND, as on Create a Deal. |
The request is answered with 200 even when every item failed, so read errors and results. A 400 means deals itself is missing, empty or longer than 1,000. A 429 with code: "QUOTA_EXCEEDED" means the new deals in the batch would take the workspace past its limit on stored deals, and nothing was created; an item that updates a deal does not count toward it.
List Deals
Section titled “List Deals”GET /v1/dealsRequired scope: deals:read
Returns deals, most recently changed first, one page at a time. All filters combine with AND.
Query Parameters
Section titled “Query Parameters”| Parameter | Type | Default | Description |
|---|---|---|---|
page | number | 1 | Page number. See Pagination. |
limit | number | 25 | Deals per page (1 to 100). |
fields | string | The shape of each row: ids, summary, or omit it for the full deal. The table under the response describes each. A comma-separated list of field names is not a projection here, as it is for contacts. | |
count_only | boolean | false | If true, return only { "status": "success", "count": 62 }. Not metered. |
status | string | open, won or lost. | |
stage | string | The stage, whole value, case-insensitive. | |
company_id | string | Only deals linked to this company. | |
contact_id | string | Only deals linked to this contact. | |
external_deal_id | string | The deal with exactly this id of yours. | |
close_date_after | string | Only deals closing on or after this ISO 8601 date. | |
close_date_before | string | Only deals closing on or before this ISO 8601 date. | |
min_amount | number | Only deals worth at least this much. | |
max_amount | number | Only deals worth at most this much. | |
tags_any | string | Only deals with at least one of these tags, comma-separated. See Filter Lists by Tag. | |
tags_all | string | Only deals with every one of these tags. When both are sent, tags_any is ignored. | |
search | string | Text to find in the name, the stage or external_deal_id, case-insensitive. At most 100 characters. | |
filters | string | Typed filters as a JSON array [{"field","op","value"}], at most 10. field is name, stage, status, currency, amount, close_date, createdate, lastmodifieddate or the key of a custom property. op is one of eq, neq, in, nin, exists, contains, gt, gte, lt, lte. GET /v1/schema?entity=deals lists the typed fields and the operators each one takes. Use the parameters above for the company, the contact and tags. | |
sort_by | string | lastmodifieddate | name, stage, status, amount, close_date, createdate, lastmodifieddate, created_at or updated_at. |
sort_dir | string | desc | asc or desc. |
include | string | provenance adds properties_provenance to each full row: for each property, where its value came from (api or manual) and when. |
curl "https://api.pathbound.ai/v1/deals?status=open&close_date_before=2026-12-31&sort_by=amount&fields=summary" \ -H "Authorization: Bearer $PATHBOUND_API_KEY"Response — 200 OK
Section titled “Response — 200 OK”{ "status": "success", "deals": [ { "deal_id": "6acd7a3e9b1c4d2e8f012345", "id": "6acd7a3e9b1c4d2e8f012345", "name": "Northwind annual plan", "stage": "negotiation", "status": "open", "amount": 24000, "currency": "USD", "close_date": "2026-10-30T00:00:00.000Z", "company_id": "665f1c2ab3d4e5f601234567", "company_name": "Northwind Traders", "contact_id": "665f1c2ab3d4e5f6012345ab", "contact_name": "Dana Lee", "tags": ["renewal", "q4"] } ], "pagination": { "page": 1, "limit": 25, "total_pages": 3, "total_items": 62 }, "timestamp": "2026-10-13T09:16:12.730Z"}What a row holds depends on fields:
fields | Each row | Counts against your plan |
|---|---|---|
omitted, or full | The deal object, plus company_name and contact_name. | yes |
summary | The row shown above. | yes |
ids | deal_id, id, company_id and contact_id only. | no |
company_name is the linked company’s name, or its domain when it has no name. contact_name is the linked contact’s first and last name, or their email address when they have neither. Both are null when the deal has no such link. In the summary and ids shapes, company_id and contact_id are null for a deal that is not linked, and id repeats deal_id.
Get a Deal
Section titled “Get a Deal”GET /v1/deals/:deal_idRequired scope: deals:read
Returns one deal with a short description of the company and the contact it is linked to. This read is metered.
Path Parameters
Section titled “Path Parameters”| Parameter | Type | Description |
|---|---|---|
deal_id | string | The deal’s id (24 hex characters). Any other value is a 400. |
Query Parameters
Section titled “Query Parameters”| Parameter | Type | Default | Description |
|---|---|---|---|
include | string | provenance adds properties_provenance to the deal. |
Response — 200 OK
Section titled “Response — 200 OK”{ "status": "success", "deal": { "deal_id": "6acd7a3e9b1c4d2e8f012345", "_id": "6acd7a3e9b1c4d2e8f012345", "properties": { "name": "Northwind annual plan", "stage": "negotiation", "amount": 24000, "currency": "USD", "status": "open", "close_date": "2026-10-30T00:00:00.000Z", "createdate": "2026-10-13T09:14:02.118Z", "lastmodifieddate": "2026-10-13T09:14:02.118Z" }, "company_id": "665f1c2ab3d4e5f601234567", "contact_id": "665f1c2ab3d4e5f6012345ab", "external_deal_id": "crm-48213", "notes": [], "tags": ["renewal", "q4"], "creation_source": "api", "first_seen_at": "2026-10-13T09:14:02.118Z", "created_at": "2026-10-13T09:14:02.118Z", "updated_at": "2026-10-13T09:14:02.118Z" }, "company": { "company_id": "665f1c2ab3d4e5f601234567", "name": "Northwind Traders", "domain": "example.com" }, "contact": { "contact_id": "665f1c2ab3d4e5f6012345ab", "firstname": "Dana", "lastname": "Lee", "jobtitle": "VP Operations" }, "timestamp": "2026-10-13T09:17:03.044Z"}company and contact are null when the deal has no such link, or when the linked record no longer exists.
A deal that is not in your workspace is a 404 with code: "not_found".
Update a Deal
Section titled “Update a Deal”PUT /v1/deals/:deal_idRequired scope: deals:write
Changes a deal’s properties, its links, or both. Only what you send changes, so an update that leaves out status does not reopen a won deal.
Request Body
Section titled “Request Body”| Field | Type | Required | Description |
|---|---|---|---|
properties | object | no | Properties to set, with the same fields as in Create a Deal. They are merged into the stored ones. One rule differs from a create: only lastmodifieddate is set by Pathbound here, so a createdate you send is stored. Do not send it. |
company_id | string | null | no | An id links the deal to that company. null removes the link. Leave it out to keep the link. |
contact_id | string | null | no | The same, for the contact. |
Things this endpoint does not do:
- It has no supported way to remove a property. A property sent as
nullor""is skipped and the stored value stays. A string that holds only spaces is the exception, and an unintended one: it removes the property,statusandcurrencyincluded, so trim what you send.close_dateis stricter: when it is present it must be a valid date. - It cannot change
external_deal_id. A request that carries the field is refused with400. - It does not read
tags. Use the tag endpoints. - It does not fill in the company. Linking a contact here leaves
company_idas it was. Only Create a Deal takes the company from the contact.
curl -X PUT https://api.pathbound.ai/v1/deals/6acd7a3e9b1c4d2e8f012345 \ -H "Authorization: Bearer $PATHBOUND_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "properties": { "stage": "closed", "status": "won", "amount": 26500 } }'Response — 200 OK
Section titled “Response — 200 OK”{ "status": "success", "message": "Deal updated successfully", "deal": { "deal_id": "6acd7a3e9b1c4d2e8f012345", "_id": "6acd7a3e9b1c4d2e8f012345", "properties": { "name": "Northwind annual plan", "stage": "closed", "amount": 26500, "currency": "USD", "status": "won", "close_date": "2026-10-30T00:00:00.000Z", "createdate": "2026-10-13T09:14:02.118Z", "lastmodifieddate": "2026-10-28T15:02:44.390Z" }, "company_id": "665f1c2ab3d4e5f601234567", "contact_id": "665f1c2ab3d4e5f6012345ab", "external_deal_id": "crm-48213", "notes": [], "tags": ["renewal", "q4"], "creation_source": "api", "first_seen_at": "2026-10-13T09:14:02.118Z", "created_at": "2026-10-13T09:14:02.118Z", "updated_at": "2026-10-28T15:02:44.390Z" }, "timestamp": "2026-10-28T15:02:44.431Z"}lastmodifieddate moves when the request carries properties. updated_at moves on every update.
A 404 means the deal, or the company or contact you asked to link, is not in your workspace. The error text says which.
Delete a Deal
Section titled “Delete a Deal”DELETE /v1/deals/:deal_idRequired scope: deals:write
To record a deal that did not close, set its status to lost instead. Delete a deal that should never have existed, such as the copy a repeated import made: a copy marked lost still counts in every total of amounts.
Response — 200 OK
Section titled “Response — 200 OK”{ "status": "success", "message": "Deal deleted successfully", "timestamp": "2026-10-28T15:10:09.118Z"}List Deal Notes
Section titled “List Deal Notes”GET /v1/deals/:deal_id/notesRequired scope: deals:read
Returns every note on the deal, newest first. There is no pagination. This read is not metered.
Response — 200 OK
Section titled “Response — 200 OK”{ "status": "success", "notes": [ { "_id": "6acd80f29b1c4d2e8f0123a1", "content": "Procurement wants the DPA signed before the order form.", "created_at": "2026-10-14T11:32:18.006Z", "created_by": "b3f1c2d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d", "source": "api" } ], "timestamp": "2026-10-14T11:40:00.251Z"}| Field | Description |
|---|---|
_id | The note’s id. It is the note_id of the two endpoints below. |
content | The note’s text. |
created_at | When the note was written. Changing the text does not move it. |
created_by | The id of the user who wrote it. For a note written through this API, that is the user the API key belongs to. |
source | api for a note written through this API or the MCP server, manual for one written in the dashboard. |
Create a Deal Note
Section titled “Create a Deal Note”POST /v1/deals/:deal_id/notesRequired scope: deals:write
Request Body
Section titled “Request Body”| Field | Type | Required | Description |
|---|---|---|---|
content | string | yes | The note’s text, 1 to 10,000 characters. Surrounding whitespace is removed. |
curl -X POST https://api.pathbound.ai/v1/deals/6acd7a3e9b1c4d2e8f012345/notes \ -H "Authorization: Bearer $PATHBOUND_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "content": "Procurement wants the DPA signed before the order form." }'Response — 201 Created
Section titled “Response — 201 Created”{ "status": "success", "note": { "_id": "6acd80f29b1c4d2e8f0123a1", "content": "Procurement wants the DPA signed before the order form.", "created_at": "2026-10-14T11:32:18.006Z", "created_by": "b3f1c2d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d", "source": "api" }, "timestamp": "2026-10-14T11:32:18.019Z"}A 429 with code: "QUOTA_EXCEEDED" and resource: "notes_per_deal" means the deal has reached its limit on notes.
Update a Deal Note
Section titled “Update a Deal Note”PATCH /v1/deals/:deal_id/notes/:note_idRequired scope: deals:write
Replaces a note’s text. The body takes content, with the same rule as in Create a Deal Note.
Response — 200 OK
Section titled “Response — 200 OK”{ "status": "success", "message": "Note updated", "timestamp": "2026-10-14T11:45:27.660Z"}The response does not return the note. A 404 means the deal or the note was not found.
Delete a Deal Note
Section titled “Delete a Deal Note”DELETE /v1/deals/:deal_id/notes/:note_idRequired scope: deals:write
Deletes the note for good.
Response — 200 OK
Section titled “Response — 200 OK”{ "status": "success", "message": "Note deleted", "timestamp": "2026-10-14T11:50:03.305Z"}Deal Tags
Section titled “Deal Tags”A deal carries tags like a contact or a company does, with the same rules and the same limit of 50. Three endpoints change them, all with deals:write:
POST /v1/deals/:deal_id/tagsDELETE /v1/deals/:deal_id/tagsPOST /v1/deals/tags/bulkThey are documented with the other tag endpoints on the Tags page. You can also set tags when you create a deal, and filter the list with tags_any and tags_all.
Errors
Section titled “Errors”The error format and the errors every endpoint shares (a missing or invalid key, rate limits) are described in the API overview. These are the ones specific to deals.
| Status | code | Meaning |
|---|---|---|
400 | Validation failed: a parameter or a body field has the wrong type or format, for example a deal_id that is not an id, a limit over 100 or a close_date that is not ISO 8601. details lists each problem. | |
400 | A property was refused. The error text says why: an unknown status, a currency that is not three letters, an amount that is not a number from 0 to 1e15, a string value over 1,000 characters, too many or too large properties, or external_deal_id sent on an update. | |
400 | Invalid search parameter: search is longer than 100 characters or contains characters that are not allowed, such as $. | |
400 | invalid_filter | An entry of filters is malformed: not a JSON array, more than 10 entries, an unknown operator, or a value of the wrong type for the field. |
402 | BILLING_PLAN_LIMIT, BILLING_TRIAL_EXPIRED, BILLING_SUBSCRIPTION_PAUSED, BILLING_SUBSCRIPTION_INACTIVE | A read would take the workspace over its plan’s allowance, or the workspace has no active plan. No deal is returned. See Usage and metering. |
403 | The API key lacks deals:read or deals:write. | |
404 | not_found on Get a Deal, none elsewhere | The deal or the note is not in your workspace, or the company or contact you asked to link is not. |
400 | INVALID_LINK | Create a Deal: company or contact is not an object with exactly one of its keys, or is sent beside company_id or contact_id. |
422 | CONTACT_NOT_FOUND, COMPANY_NOT_FOUND | Create a Deal: the contact or company key finds no record in your workspace. |
429 | QUOTA_EXCEEDED | A storage limit was reached. resource says which: deals for the workspace’s deals, notes_per_deal for one deal’s notes. |