Skip to content

feat: add folder_name to Developer API and conversation webhook#6019

Open
syou6162 wants to merge 7 commits intoBasedHardware:mainfrom
syou6162:feat/webhook_additional_fields
Open

feat: add folder_name to Developer API and conversation webhook#6019
syou6162 wants to merge 7 commits intoBasedHardware:mainfrom
syou6162:feat/webhook_additional_fields

Conversation

@syou6162
Copy link
Copy Markdown
Contributor

@syou6162 syou6162 commented Mar 25, 2026

Summary

Add folder_name to the Developer API conversation endpoints and the conversation_created webhook payload. This allows webhook consumers and API users to directly identify which folder a conversation belongs to, without needing to maintain a separate folder_idfolder_name mapping.

Background

Currently, the webhook payload and API responses include folder_id but not folder_name. Users who want to process conversations by folder via webhooks (e.g., rule-based routing) must separately look up folder names. Since folders are user-created and well-suited for rule-based filtering (unlike AI-generated category), including folder_name directly improves the developer experience.

This follows the same pattern established in #3962 for adding speaker_name to the Developer API and webhook.

Changes

Backend

  • backend/routers/developer.py

    • Added folder_id and folder_name fields to the Conversation Pydantic response model
    • Added _add_folder_names_to_conversations(uid, conversations) helper that batch-fetches all user folders in a single query (N+1 avoidance)
    • Called the helper in GET /v1/dev/user/conversations, GET /v1/dev/user/conversations/{id}, and PATCH /v1/dev/user/conversations/{id}
  • backend/utils/webhooks.py

    • Added _add_folder_name_to_payload(uid, payload) helper that resolves folder_name from folder_id
    • Called the helper in conversation_created_webhook

Tests

  • backend/tests/unit/test_folder_name_enrichment.py: Unit tests for both _add_folder_names_to_conversations and _add_folder_name_to_payload (10 test cases covering normal, edge, and N+1 avoidance scenarios)

Documentation

  • docs/doc/developer/api/conversations.mdx: Added folder_id and folder_name to response examples and Response Fields table
  • docs/doc/developer/apps/Integrations.mdx: Added folder_id and folder_name to webhook payload example

Related

Add folder_name field to the GET /v1/dev/user/conversations, GET
/v1/dev/user/conversations/{id}, and PATCH /v1/dev/user/conversations/{id}
endpoints, and to the conversation_created webhook payload.

The folder_name is resolved from the user's folder settings via folder_id.
This avoids N+1 queries by fetching all folders in a single call for the
list endpoint, and uses a single get_folder lookup for the webhook.

Relates to the pattern established in BasedHardware#3962 for speaker_name enrichment.
…mple

Add folder_id and folder_name fields to the response examples in the
conversations API documentation (both with and without transcript variants),
and add corresponding rows to the Response Fields table.
Add folder_id and folder_name fields to the conversation_created webhook
payload example in the Integration Apps documentation.
@syou6162 syou6162 marked this pull request as ready for review March 25, 2026 01:34
@beastoin
Copy link
Copy Markdown
Collaborator

do we have any tests? @syou6162

@syou6162 syou6162 changed the title feat: add folder_name to developer API and conversation webhook feat: add folder_name to Developer API and conversation webhook Mar 27, 2026
@syou6162 syou6162 marked this pull request as draft March 27, 2026 04:36
@syou6162 syou6162 marked this pull request as ready for review March 27, 2026 04:51
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 27, 2026

Greptile Summary

This PR adds folder_id and folder_name to the Developer API conversation responses (GET /v1/dev/user/conversations, GET /v1/dev/user/conversations/{id}, PATCH /v1/dev/user/conversations/{id}) and to the conversation_created webhook payload, following the same speaker_name enrichment pattern established in #3962. The batch-fetch approach in _add_folder_names_to_conversations correctly avoids N+1 queries for the list endpoint, and the per-call get_folder lookup in the webhook helper is appropriately scoped.\n\n- P1 bug in update_conversation_endpoint: after performing updates, get_conversation is called again and its result is passed directly into _add_folder_names_to_conversations without a None guard. If the conversation is deleted between the two database calls (race condition), None.get('folder_id') raises AttributeError and the endpoint returns a 500 instead of a clean 404 or 422.\n- The webhook helper _add_folder_name_to_payload is clean and handles all None/missing cases correctly.\n- Test coverage is thorough (10 cases) and covers the most important edge cases (empty list, deleted folder, N+1 avoidance).\n- Documentation updates in both MDX files are accurate and consistent with the implementation.

Confidence Score: 4/5

Safe to merge after fixing the None guard in update_conversation_endpoint; all other changes are clean

One targeted P1 fix remains: the missing None guard in update_conversation_endpoint before calling _add_folder_names_to_conversations. The fix is a single-line if-guard. Everything else — the batch helper, the webhook helper, the model changes, and docs — is correct and well-tested.

backend/routers/developer.py — specifically the update_conversation_endpoint around line 1092

Important Files Changed

Filename Overview
backend/routers/developer.py Adds folder_id/folder_name to the Conversation response model and a _add_folder_names_to_conversations batch-fetch helper; one P1 race condition when the second get_conversation call returns None in update_conversation_endpoint
backend/utils/webhooks.py Adds _add_folder_name_to_payload helper using a single get_folder lookup; correctly handles None folder_id and not-found folder; no issues found
backend/tests/unit/test_folder_name_enrichment.py New unit test file with 10 cases covering normal flow, edge cases (empty list, None folder_id, deleted folder), and N+1 avoidance; extensive manual module stubbing is necessary given the import tree but adds maintenance burden
docs/doc/developer/api/conversations.mdx Adds folder_id and folder_name to two response JSON examples and the Response Fields table; straightforward documentation update
docs/doc/developer/apps/Integrations.mdx Adds folder_id and folder_name to the conversation_created webhook payload example; no issues

Sequence Diagram

sequenceDiagram
    participant Client
    participant DevRouter as developer.py
    participant ConvDB as conversations_db
    participant FoldersDB as folders_db

    Client->>DevRouter: GET /v1/dev/user/conversations
    DevRouter->>ConvDB: get_conversations(uid, ...)
    ConvDB-->>DevRouter: [conv1, conv2, ...]
    DevRouter->>FoldersDB: get_folders(uid) [single batch call]
    FoldersDB-->>DevRouter: [{id, name}, ...]
    Note over DevRouter: Build folder_map, enrich each conv with folder_name
    DevRouter-->>Client: [{..., folder_id, folder_name}, ...]

    Client->>DevRouter: PATCH /v1/dev/user/conversations/{id}
    DevRouter->>ConvDB: get_conversation(uid, id) [existence check]
    ConvDB-->>DevRouter: conv
    DevRouter->>ConvDB: update_conversation / set_discarded
    DevRouter->>ConvDB: get_conversation(uid, id) [re-fetch]
    ConvDB-->>DevRouter: conv (or None on race condition ⚠️)
    DevRouter->>FoldersDB: get_folders(uid)
    FoldersDB-->>DevRouter: [{id, name}, ...]
    DevRouter-->>Client: {..., folder_id, folder_name}

    Note over DevRouter,FoldersDB: Webhook path uses get_folder(uid, folder_id) — single lookup
Loading

Reviews (1): Last reviewed commit: "style: fix black formatting in test file" | Re-trigger Greptile

Prevent AttributeError when the conversation is deleted between the
update and re-fetch calls in update_conversation_endpoint.
@syou6162
Copy link
Copy Markdown
Contributor Author

@beastoin Sorry about that. Added test cases in backend/tests/unit/test_folder_name_enrichment.py:

  • _add_folder_names_to_conversations (Developer API): 6 tests covering normal resolution, null/missing folder_id, deleted folder, mixed cases, empty list, and N+1 avoidance verification (get_folders called only once)
  • _add_folder_name_to_payload (Webhook): 4 tests covering normal resolution, null/missing folder_id, and folder not found in DB

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants