Skip to content

Notes (V1)

Service for managing notes.

V2 provides read-only access; use V1 for create/update/delete.

Source code in affinity/services/v1_only.py
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
class NoteService:
    """
    Service for managing notes.

    V2 provides read-only access; use V1 for create/update/delete.
    """

    def __init__(self, client: HTTPClient):
        self._client = client

    def list(
        self,
        *,
        person_id: PersonId | None = None,
        company_id: CompanyId | None = None,
        opportunity_id: OpportunityId | None = None,
        creator_id: UserId | None = None,
        page_size: int | None = None,
        page_token: str | None = None,
    ) -> PaginatedResponse[Note]:
        """
        Get notes filtered by entity or creator.

        Args:
            person_id: Filter notes associated with this person
            company_id: Filter notes associated with this company
            opportunity_id: Filter notes associated with this opportunity
            creator_id: Filter notes created by this user
            page_size: Number of results per page
            page_token: Pagination token from previous response

        Returns:
            PaginatedResponse with notes and next_page_token
        """
        params: dict[str, Any] = {}
        if person_id:
            params["person_id"] = int(person_id)
        if company_id:
            params["organization_id"] = int(company_id)
        if opportunity_id:
            params["opportunity_id"] = int(opportunity_id)
        if creator_id:
            params["creator_id"] = int(creator_id)
        if page_size:
            params["page_size"] = page_size
        if page_token:
            params["page_token"] = page_token

        data = self._client.get("/notes", params=params or None, v1=True)
        items = data.get("notes", data.get("data", []))
        if not isinstance(items, list):
            items = []
        return PaginatedResponse[Note](
            data=[Note.model_validate(n) for n in items],
            next_page_token=data.get("next_page_token") or data.get("nextPageToken"),
        )

    def get(self, note_id: NoteId) -> Note:
        """Get a single note by ID."""
        data = self._client.get(f"/notes/{note_id}", v1=True)
        return Note.model_validate(data)

    def create(self, data: NoteCreate) -> Note:
        """
        Create a new note.

        Must be associated with at least one person, organization,
        opportunity, or parent note (for replies).
        """
        payload = data.model_dump(by_alias=True, mode="python", exclude_none=True)
        _coerce_isoformat(payload, ("created_at",))
        if not data.person_ids:
            payload.pop("person_ids", None)
        if not data.company_ids:
            payload.pop("organization_ids", None)
        if not data.opportunity_ids:
            payload.pop("opportunity_ids", None)

        result = self._client.post("/notes", json=payload, v1=True)
        return Note.model_validate(result)

    def update(self, note_id: NoteId, data: NoteUpdate) -> Note:
        """Update a note's content."""
        payload = data.model_dump(mode="json", exclude_unset=True, exclude_none=True)
        result = self._client.put(
            f"/notes/{note_id}",
            json=payload,
            v1=True,
        )
        return Note.model_validate(result)

    def delete(self, note_id: NoteId) -> bool:
        """Delete a note."""
        result = self._client.delete(f"/notes/{note_id}", v1=True)
        return bool(result.get("success", False))

    def iter(
        self,
        *,
        person_id: PersonId | None = None,
        company_id: CompanyId | None = None,
        opportunity_id: OpportunityId | None = None,
        creator_id: UserId | None = None,
        page_size: int | None = None,
    ) -> PageIterator[Note]:
        """
        Iterate through all notes with automatic pagination.

        Args:
            person_id: Filter notes associated with this person
            company_id: Filter notes associated with this company
            opportunity_id: Filter notes associated with this opportunity
            creator_id: Filter notes created by this user
            page_size: Number of results per page

        Returns:
            PageIterator that yields Note objects
        """

        def fetch_page(cursor: str | None) -> PaginatedResponse[Note]:
            return self.list(
                person_id=person_id,
                company_id=company_id,
                opportunity_id=opportunity_id,
                creator_id=creator_id,
                page_size=page_size,
                page_token=cursor,
            )

        return PageIterator(fetch_page)

create(data: NoteCreate) -> Note

Create a new note.

Must be associated with at least one person, organization, opportunity, or parent note (for replies).

Source code in affinity/services/v1_only.py
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
def create(self, data: NoteCreate) -> Note:
    """
    Create a new note.

    Must be associated with at least one person, organization,
    opportunity, or parent note (for replies).
    """
    payload = data.model_dump(by_alias=True, mode="python", exclude_none=True)
    _coerce_isoformat(payload, ("created_at",))
    if not data.person_ids:
        payload.pop("person_ids", None)
    if not data.company_ids:
        payload.pop("organization_ids", None)
    if not data.opportunity_ids:
        payload.pop("opportunity_ids", None)

    result = self._client.post("/notes", json=payload, v1=True)
    return Note.model_validate(result)

delete(note_id: NoteId) -> bool

Delete a note.

Source code in affinity/services/v1_only.py
235
236
237
238
def delete(self, note_id: NoteId) -> bool:
    """Delete a note."""
    result = self._client.delete(f"/notes/{note_id}", v1=True)
    return bool(result.get("success", False))

get(note_id: NoteId) -> Note

Get a single note by ID.

Source code in affinity/services/v1_only.py
201
202
203
204
def get(self, note_id: NoteId) -> Note:
    """Get a single note by ID."""
    data = self._client.get(f"/notes/{note_id}", v1=True)
    return Note.model_validate(data)

iter(*, person_id: PersonId | None = None, company_id: CompanyId | None = None, opportunity_id: OpportunityId | None = None, creator_id: UserId | None = None, page_size: int | None = None) -> PageIterator[Note]

Iterate through all notes with automatic pagination.

Parameters:

Name Type Description Default
person_id PersonId | None

Filter notes associated with this person

None
company_id CompanyId | None

Filter notes associated with this company

None
opportunity_id OpportunityId | None

Filter notes associated with this opportunity

None
creator_id UserId | None

Filter notes created by this user

None
page_size int | None

Number of results per page

None

Returns:

Type Description
PageIterator[Note]

PageIterator that yields Note objects

Source code in affinity/services/v1_only.py
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
def iter(
    self,
    *,
    person_id: PersonId | None = None,
    company_id: CompanyId | None = None,
    opportunity_id: OpportunityId | None = None,
    creator_id: UserId | None = None,
    page_size: int | None = None,
) -> PageIterator[Note]:
    """
    Iterate through all notes with automatic pagination.

    Args:
        person_id: Filter notes associated with this person
        company_id: Filter notes associated with this company
        opportunity_id: Filter notes associated with this opportunity
        creator_id: Filter notes created by this user
        page_size: Number of results per page

    Returns:
        PageIterator that yields Note objects
    """

    def fetch_page(cursor: str | None) -> PaginatedResponse[Note]:
        return self.list(
            person_id=person_id,
            company_id=company_id,
            opportunity_id=opportunity_id,
            creator_id=creator_id,
            page_size=page_size,
            page_token=cursor,
        )

    return PageIterator(fetch_page)

list(*, person_id: PersonId | None = None, company_id: CompanyId | None = None, opportunity_id: OpportunityId | None = None, creator_id: UserId | None = None, page_size: int | None = None, page_token: str | None = None) -> PaginatedResponse[Note]

Get notes filtered by entity or creator.

Parameters:

Name Type Description Default
person_id PersonId | None

Filter notes associated with this person

None
company_id CompanyId | None

Filter notes associated with this company

None
opportunity_id OpportunityId | None

Filter notes associated with this opportunity

None
creator_id UserId | None

Filter notes created by this user

None
page_size int | None

Number of results per page

None
page_token str | None

Pagination token from previous response

None

Returns:

Type Description
PaginatedResponse[Note]

PaginatedResponse with notes and next_page_token

Source code in affinity/services/v1_only.py
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
def list(
    self,
    *,
    person_id: PersonId | None = None,
    company_id: CompanyId | None = None,
    opportunity_id: OpportunityId | None = None,
    creator_id: UserId | None = None,
    page_size: int | None = None,
    page_token: str | None = None,
) -> PaginatedResponse[Note]:
    """
    Get notes filtered by entity or creator.

    Args:
        person_id: Filter notes associated with this person
        company_id: Filter notes associated with this company
        opportunity_id: Filter notes associated with this opportunity
        creator_id: Filter notes created by this user
        page_size: Number of results per page
        page_token: Pagination token from previous response

    Returns:
        PaginatedResponse with notes and next_page_token
    """
    params: dict[str, Any] = {}
    if person_id:
        params["person_id"] = int(person_id)
    if company_id:
        params["organization_id"] = int(company_id)
    if opportunity_id:
        params["opportunity_id"] = int(opportunity_id)
    if creator_id:
        params["creator_id"] = int(creator_id)
    if page_size:
        params["page_size"] = page_size
    if page_token:
        params["page_token"] = page_token

    data = self._client.get("/notes", params=params or None, v1=True)
    items = data.get("notes", data.get("data", []))
    if not isinstance(items, list):
        items = []
    return PaginatedResponse[Note](
        data=[Note.model_validate(n) for n in items],
        next_page_token=data.get("next_page_token") or data.get("nextPageToken"),
    )

update(note_id: NoteId, data: NoteUpdate) -> Note

Update a note's content.

Source code in affinity/services/v1_only.py
225
226
227
228
229
230
231
232
233
def update(self, note_id: NoteId, data: NoteUpdate) -> Note:
    """Update a note's content."""
    payload = data.model_dump(mode="json", exclude_unset=True, exclude_none=True)
    result = self._client.put(
        f"/notes/{note_id}",
        json=payload,
        v1=True,
    )
    return Note.model_validate(result)