From 2677bbc71c742e9cd656d7423a42bfc3ce9cc021 Mon Sep 17 00:00:00 2001 From: lambdabaa Date: Tue, 14 Apr 2026 17:28:33 -0700 Subject: [PATCH 1/3] Add Dewey to independent publisher connectors --- .../Dewey/README.md | 56 ++ .../Dewey/apiDefinition.swagger.json | 662 ++++++++++++++++++ .../Dewey/apiProperties.json | 23 + 3 files changed, 741 insertions(+) create mode 100644 independent-publisher-connectors/Dewey/README.md create mode 100644 independent-publisher-connectors/Dewey/apiDefinition.swagger.json create mode 100644 independent-publisher-connectors/Dewey/apiProperties.json diff --git a/independent-publisher-connectors/Dewey/README.md b/independent-publisher-connectors/Dewey/README.md new file mode 100644 index 0000000000..4fabe59287 --- /dev/null +++ b/independent-publisher-connectors/Dewey/README.md @@ -0,0 +1,56 @@ +# Dewey +Dewey turns document collections into a research-grade knowledge base. Ingest PDFs, Word docs, and more; then search and extract structured insights — all from your Power Automate flows. + +## Publisher: Dewey + +## Prerequisites +You need a Dewey account with an active subscription. Sign up at [meetdewey.com](https://meetdewey.com). + +## Supported Operations + +### Triggers +#### When a document is ready +Fires when a document finishes processing and is fully indexed. Use this to kick off downstream steps (notify a team, search the document, run an AI step) as soon as a newly uploaded file is searchable. + +#### When a document has an error +Fires when document processing fails. Use this to alert your team or retry ingestion automatically. + +### Actions +#### List collections +Returns all collections in your organisation. + +#### Get collection +Returns metadata for a single collection by ID. + +#### Get document upload URL +Returns a pre-signed S3 URL for a file upload, along with a document ID. After uploading directly to that URL with an HTTP PUT, call **Confirm document upload** to begin processing. + +#### Confirm document upload +Tells Dewey that the file upload to S3 is complete and processing should begin. + +#### Wait for document +Blocks until the document reaches a terminal state (ready or error) and returns the result. Times out after 5 minutes. Use this after **Confirm document upload** to pause a flow until the document is searchable. + +#### Search collection +Runs a hybrid semantic and keyword search against a collection and returns the most relevant text chunks. Ideal for RAG flows where you want to feed context into a subsequent AI Builder or Azure OpenAI step. + +## Obtaining Credentials +API keys are created in the Dewey dashboard under **Settings → API Keys**. Keys start with `dwy_live_`. When creating a connection in Power Automate, enter the key in the form `Bearer dwy_live_...` (include the `Bearer ` prefix). + +## Getting Started +A typical SharePoint → Dewey ingestion flow: + +1. **[SharePoint]** When a file is created in library +2. **[SharePoint]** Get file content +3. **[Dewey]** Get document upload URL *(collectionId, filename, contentType, fileSizeBytes, contentHash)* +4. **[HTTP]** PUT file to `uploadUrl` *(built-in HTTP action, no auth header needed)* +5. **[Dewey]** Confirm document upload *(collectionId, documentId)* +6. **[Dewey]** Wait for document *(documentId — blocks until ready or error)* +7. **[Teams / Email]** Notify team — document is now searchable + +API reference: [meetdewey.com/docs](https://meetdewey.com/docs) + +## Known Issues and Limitations +- **Research queries** use Server-Sent Events and cannot be used as a connector action. Use **Search collection** to retrieve relevant chunks and feed them into an AI Builder or Azure OpenAI step instead. +- **Wait for document** holds the flow connection open for up to 5 minutes. For high-volume ingestion flows, set trigger concurrency to limit parallel executions. +- SHA-256 is not natively available in Power Automate expressions. Use `base64(sha256(fileContent))` with `dataUriToString()`, or pass the SharePoint `eTag` as a consistent alternative for deduplication. diff --git a/independent-publisher-connectors/Dewey/apiDefinition.swagger.json b/independent-publisher-connectors/Dewey/apiDefinition.swagger.json new file mode 100644 index 0000000000..8c9a634408 --- /dev/null +++ b/independent-publisher-connectors/Dewey/apiDefinition.swagger.json @@ -0,0 +1,662 @@ +{ + "swagger": "2.0", + "info": { + "title": "Dewey", + "description": "Dewey turns document collections into a research-grade knowledge base. Ingest PDFs, Word docs, and more; then search, query, and extract structured insights — all from your automation flows.", + "version": "1.0.0", + "contact": { + "name": "Dewey Support", + "url": "https://meetdewey.com", + "email": "support@meetdewey.com" + } + }, + "host": "api.meetdewey.com", + "basePath": "/v1", + "schemes": ["https"], + "consumes": ["application/json"], + "produces": ["application/json"], + "securityDefinitions": { + "api_key": { + "type": "apiKey", + "in": "header", + "name": "Authorization" + } + }, + "x-ms-connector-metadata": [ + { + "propertyName": "Website", + "propertyValue": "https://meetdewey.com" + }, + { + "propertyName": "Privacy policy", + "propertyValue": "https://meetdewey.com/privacy" + }, + { + "propertyName": "Categories", + "propertyValue": "AI;Productivity" + } + ], + "paths": { + "/integration/webhooks/document-ready": { + "x-ms-notification-content": { + "description": "Document ready event payload", + "schema": { "$ref": "#/definitions/WebhookPayload" } + }, + "post": { + "summary": "When a document is ready", + "description": "Triggers when a document finishes processing and is ready to search. Use this to start a flow as soon as a newly uploaded document has been indexed.", + "operationId": "TriggerDocumentReady", + "x-ms-trigger": "single", + "security": [{ "api_key": [] }], + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "type": "object", + "required": ["url"], + "properties": { + "url": { + "type": "string", + "title": "Webhook URL", + "x-ms-notification-url": true, + "x-ms-visibility": "internal" + } + } + } + } + ], + "responses": { + "201": { + "description": "Subscription registered", + "schema": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "Subscription ID", + "x-ms-summary": "Subscription ID" + } + } + } + } + } + } + }, + + "/integration/webhooks/document-error": { + "x-ms-notification-content": { + "description": "Document error event payload", + "schema": { "$ref": "#/definitions/WebhookPayload" } + }, + "post": { + "summary": "When a document has an error", + "description": "Triggers when a document fails to process. Use this to alert your team or retry ingestion when processing fails.", + "operationId": "TriggerDocumentError", + "x-ms-trigger": "single", + "security": [{ "api_key": [] }], + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "type": "object", + "required": ["url"], + "properties": { + "url": { + "type": "string", + "title": "Webhook URL", + "x-ms-notification-url": true, + "x-ms-visibility": "internal" + } + } + } + } + ], + "responses": { + "201": { + "description": "Subscription registered", + "schema": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "Subscription ID", + "x-ms-summary": "Subscription ID" + } + } + } + } + } + } + }, + + "/integration/webhooks/{id}": { + "delete": { + "summary": "Unsubscribe from document event", + "description": "Removes a webhook subscription. Called automatically when a flow is deleted or disabled.", + "operationId": "UnsubscribeDocumentEvent", + "x-ms-visibility": "internal", + "security": [{ "api_key": [] }], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "type": "string", + "x-ms-summary": "Subscription ID", + "x-ms-url-encoding": "single" + } + ], + "responses": { + "204": { + "description": "Unsubscribed successfully" + } + } + } + }, + + "/collections": { + "get": { + "summary": "List collections", + "description": "Returns all collections in your organisation.", + "operationId": "ListCollections", + "security": [{ "api_key": [] }], + "responses": { + "200": { + "description": "List of collections", + "schema": { + "type": "array", + "items": { "$ref": "#/definitions/Collection" } + } + } + } + } + }, + + "/collections/{collectionId}": { + "get": { + "summary": "Get collection", + "description": "Returns details for a single collection.", + "operationId": "GetCollection", + "security": [{ "api_key": [] }], + "parameters": [{ "$ref": "#/parameters/collectionId" }], + "responses": { + "200": { + "description": "Collection details", + "schema": { "$ref": "#/definitions/Collection" } + }, + "404": { "description": "Collection not found" } + } + } + }, + + "/collections/{collectionId}/documents/upload-url": { + "post": { + "summary": "Get document upload URL", + "description": "Returns a pre-signed S3 URL to upload a document. After uploading the file directly to that URL with an HTTP PUT, call 'Confirm document upload' to begin processing. Use 'Wait for document' to block until the document is indexed.", + "operationId": "GetDocumentUploadUrl", + "security": [{ "api_key": [] }], + "parameters": [ + { "$ref": "#/parameters/collectionId" }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "type": "object", + "required": [ + "filename", + "contentType", + "fileSizeBytes", + "contentHash" + ], + "properties": { + "filename": { + "type": "string", + "title": "Filename", + "x-ms-summary": "Filename", + "description": "Original filename including extension (e.g. report.pdf)" + }, + "contentType": { + "type": "string", + "title": "Content Type", + "x-ms-summary": "Content Type", + "description": "MIME type of the file (e.g. application/pdf)" + }, + "fileSizeBytes": { + "type": "integer", + "title": "File Size (bytes)", + "x-ms-summary": "File Size (bytes)", + "description": "Exact byte length of the file" + }, + "contentHash": { + "type": "string", + "title": "SHA-256 Hash", + "x-ms-summary": "SHA-256 Hash", + "description": "SHA-256 hex digest of the file contents, used for deduplication" + } + } + } + } + ], + "responses": { + "201": { + "description": "Upload URL ready. documentId is always returned; uploadUrl is null when the file was already indexed (duplicate).", + "schema": { + "type": "object", + "properties": { + "documentId": { + "type": "string", + "title": "Document ID", + "x-ms-summary": "Document ID" + }, + "uploadUrl": { + "type": "string", + "title": "Upload URL", + "x-ms-summary": "Upload URL", + "description": "Pre-signed S3 URL. PUT your file to this URL (expires in 15 minutes). Null when the file is already indexed." + } + } + } + } + } + } + }, + + "/collections/{collectionId}/documents/{documentId}/confirm": { + "post": { + "summary": "Confirm document upload", + "description": "Tells Dewey that the file upload to S3 is complete and processing should begin. Call this after a successful PUT to the upload URL.", + "operationId": "ConfirmDocumentUpload", + "security": [{ "api_key": [] }], + "parameters": [ + { "$ref": "#/parameters/collectionId" }, + { "$ref": "#/parameters/documentId" } + ], + "responses": { + "200": { + "description": "Processing started", + "schema": { "$ref": "#/definitions/Document" } + }, + "404": { "description": "Document not found" } + } + } + }, + + "/documents/{documentId}": { + "get": { + "summary": "Get document", + "description": "Returns the current status and metadata for a document.", + "operationId": "GetDocument", + "security": [{ "api_key": [] }], + "parameters": [{ "$ref": "#/parameters/documentId" }], + "responses": { + "200": { + "description": "Document details", + "schema": { "$ref": "#/definitions/Document" } + }, + "404": { "description": "Document not found" } + } + } + }, + + "/documents/{documentId}/wait": { + "get": { + "summary": "Wait for document", + "description": "Blocks until the document reaches a terminal state (ready or error) and returns the result. Times out after 5 minutes with a 408 response. Use this after 'Confirm document upload' to pause a flow until the document is searchable.", + "operationId": "WaitForDocument", + "security": [{ "api_key": [] }], + "parameters": [{ "$ref": "#/parameters/documentId" }], + "responses": { + "200": { + "description": "Document reached terminal state", + "schema": { "$ref": "#/definitions/Document" } + }, + "404": { "description": "Document not found" }, + "408": { + "description": "Timed out waiting for processing to complete" + } + } + } + }, + + "/collections/{collectionId}/research/sync": { + "post": { + "summary": "Research collection", + "description": "Runs an agentic research loop against the collection and returns a complete answer with cited sources. Ideal for deep question-answering flows where you need a synthesised response rather than raw chunks.", + "operationId": "ResearchCollection", + "security": [{ "api_key": [] }], + "parameters": [ + { "$ref": "#/parameters/collectionId" }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "type": "object", + "required": ["q"], + "properties": { + "q": { + "type": "string", + "title": "Question", + "x-ms-summary": "Question", + "description": "Research question to answer" + }, + "depth": { + "type": "string", + "title": "Depth", + "x-ms-summary": "Depth", + "description": "Controls how thoroughly the collection is searched (default: balanced)", + "x-ms-visibility": "advanced", + "enum": ["quick", "balanced", "deep", "exhaustive"], + "default": "balanced" + } + } + } + } + ], + "responses": { + "200": { + "description": "Research complete", + "schema": { + "type": "object", + "properties": { + "answer": { + "type": "string", + "title": "Answer", + "x-ms-summary": "Answer", + "description": "Full research answer with inline source citations" + }, + "sessionId": { + "type": "string", + "title": "Session ID", + "x-ms-summary": "Session ID" + }, + "sources": { + "type": "array", + "title": "Sources", + "x-ms-summary": "Sources", + "items": { "$ref": "#/definitions/ResearchSource" } + } + } + } + } + } + } + }, + + "/collections/{collectionId}/query": { + "post": { + "summary": "Search collection", + "description": "Runs a hybrid semantic and keyword search against the collection and returns the most relevant text chunks. Ideal for RAG flows where you want to feed context into a subsequent AI step.", + "operationId": "SearchCollection", + "security": [{ "api_key": [] }], + "parameters": [ + { "$ref": "#/parameters/collectionId" }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "type": "object", + "required": ["q"], + "properties": { + "q": { + "type": "string", + "title": "Query", + "x-ms-summary": "Query", + "description": "Natural language search query" + }, + "limit": { + "type": "integer", + "title": "Result limit", + "x-ms-summary": "Result limit", + "description": "Maximum number of chunks to return (default 10, max 50)", + "x-ms-visibility": "advanced", + "default": 10, + "maximum": 50 + } + } + } + } + ], + "responses": { + "200": { + "description": "Search results", + "schema": { + "type": "array", + "items": { "$ref": "#/definitions/SearchResult" } + } + } + } + } + } + }, + + "parameters": { + "collectionId": { + "name": "collectionId", + "in": "path", + "required": true, + "type": "string", + "x-ms-summary": "Collection", + "description": "The collection ID", + "x-ms-url-encoding": "single", + "x-ms-dynamic-values": { + "operationId": "ListCollections", + "value-collection": "", + "value-path": "id", + "value-title": "name" + } + }, + "documentId": { + "name": "documentId", + "in": "path", + "required": true, + "type": "string", + "x-ms-summary": "Document ID", + "description": "The document ID", + "x-ms-url-encoding": "single" + } + }, + + "definitions": { + "Collection": { + "type": "object", + "properties": { + "id": { "type": "string", "title": "ID", "x-ms-summary": "ID" }, + "name": { "type": "string", "title": "Name", "x-ms-summary": "Name" }, + "description": { + "type": "string", + "title": "Description", + "x-ms-summary": "Description" + }, + "visibility": { + "type": "string", + "title": "Visibility", + "x-ms-summary": "Visibility" + }, + "createdAt": { + "type": "string", + "title": "Created At", + "x-ms-summary": "Created At" + } + } + }, + "Document": { + "type": "object", + "properties": { + "id": { "type": "string", "title": "ID", "x-ms-summary": "ID" }, + "collectionId": { + "type": "string", + "title": "Collection ID", + "x-ms-summary": "Collection ID" + }, + "filename": { + "type": "string", + "title": "Filename", + "x-ms-summary": "Filename" + }, + "status": { + "type": "string", + "title": "Status", + "x-ms-summary": "Status", + "description": "One of: pending, uploading, processing, sectioned, embedded, ready, error" + }, + "pageCount": { + "type": "integer", + "title": "Page Count", + "x-ms-summary": "Page Count" + }, + "sectionCount": { + "type": "integer", + "title": "Section Count", + "x-ms-summary": "Section Count" + }, + "chunkCount": { + "type": "integer", + "title": "Chunk Count", + "x-ms-summary": "Chunk Count" + }, + "fileSizeBytes": { + "type": "integer", + "title": "File Size (bytes)", + "x-ms-summary": "File Size (bytes)" + }, + "errorMessage": { + "type": "string", + "title": "Error Message", + "x-ms-summary": "Error Message" + }, + "createdAt": { + "type": "string", + "title": "Created At", + "x-ms-summary": "Created At" + } + } + }, + "SearchResult": { + "type": "object", + "properties": { + "content": { + "type": "string", + "title": "Content", + "x-ms-summary": "Content" + }, + "documentId": { + "type": "string", + "title": "Document ID", + "x-ms-summary": "Document ID" + }, + "filename": { + "type": "string", + "title": "Filename", + "x-ms-summary": "Filename" + }, + "sectionTitle": { + "type": "string", + "title": "Section Title", + "x-ms-summary": "Section Title" + }, + "score": { + "type": "number", + "title": "Relevance Score", + "x-ms-summary": "Relevance Score" + } + } + }, + "ResearchSource": { + "type": "object", + "properties": { + "chunkId": { + "type": "string", + "title": "Chunk ID", + "x-ms-summary": "Chunk ID" + }, + "content": { + "type": "string", + "title": "Content", + "x-ms-summary": "Content" + }, + "documentId": { + "type": "string", + "title": "Document ID", + "x-ms-summary": "Document ID" + }, + "filename": { + "type": "string", + "title": "Filename", + "x-ms-summary": "Filename" + }, + "sectionId": { + "type": "string", + "title": "Section ID", + "x-ms-summary": "Section ID" + }, + "sectionTitle": { + "type": "string", + "title": "Section Title", + "x-ms-summary": "Section Title" + }, + "sectionLevel": { + "type": "integer", + "title": "Section Level", + "x-ms-summary": "Section Level" + } + } + }, + "WebhookPayload": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "Event ID", + "x-ms-summary": "Event ID" + }, + "type": { + "type": "string", + "title": "Event Type", + "x-ms-summary": "Event Type" + }, + "created": { + "type": "integer", + "title": "Timestamp", + "x-ms-summary": "Timestamp" + }, + "data": { + "type": "object", + "properties": { + "documentId": { + "type": "string", + "title": "Document ID", + "x-ms-summary": "Document ID" + }, + "collectionId": { + "type": "string", + "title": "Collection ID", + "x-ms-summary": "Collection ID" + }, + "filename": { + "type": "string", + "title": "Filename", + "x-ms-summary": "Filename" + }, + "status": { + "type": "string", + "title": "Status", + "x-ms-summary": "Status" + }, + "errorMessage": { + "type": "string", + "title": "Error Message", + "x-ms-summary": "Error Message" + } + } + } + } + } + } +} diff --git a/independent-publisher-connectors/Dewey/apiProperties.json b/independent-publisher-connectors/Dewey/apiProperties.json new file mode 100644 index 0000000000..38f7ec7750 --- /dev/null +++ b/independent-publisher-connectors/Dewey/apiProperties.json @@ -0,0 +1,23 @@ +{ + "properties": { + "connectionParameters": { + "api_key": { + "type": "securestring", + "uiDefinition": { + "displayName": "API Key", + "description": "Your Dewey API key in the form 'Bearer dwy_live_...'. Create one in your dashboard under Settings → API Keys.", + "tooltip": "Enter in the form: Bearer dwy_live_...", + "constraints": { + "tabIndex": 2, + "clearText": false, + "required": "true" + } + } + } + }, + "iconBrandColor": "#da3b01", + "capabilities": [], + "publisher": "Dewey", + "stackOwner": "Dewey" + } +} From f38d47f7110572acc6634e19504d83f5aa546c93 Mon Sep 17 00:00:00 2001 From: lambdabaa Date: Tue, 14 Apr 2026 23:10:53 -0700 Subject: [PATCH 2/3] Update Dewey connector with new actions and improved docs Adds 10 new actions to the connector: - Upload document (simple direct upload, no presigned URL required) - Create collection / Delete collection - List documents / Delete document / Retry document - List sections / Scan sections - Get section / Get section chunks Updates README to document all actions, simplify the Getting Started flow (direct upload is now the primary path), and demote the presigned URL flow to an advanced section. Co-Authored-By: Claude Sonnet 4.6 --- .../Dewey/README.md | 49 +- .../Dewey/apiDefinition.swagger.json | 788 ++++++++++++++++-- 2 files changed, 785 insertions(+), 52 deletions(-) diff --git a/independent-publisher-connectors/Dewey/README.md b/independent-publisher-connectors/Dewey/README.md index 4fabe59287..54f252fa45 100644 --- a/independent-publisher-connectors/Dewey/README.md +++ b/independent-publisher-connectors/Dewey/README.md @@ -19,17 +19,47 @@ Fires when document processing fails. Use this to alert your team or retry inges #### List collections Returns all collections in your organisation. +#### Create collection +Creates a new collection. Requires a project ID from the Dewey dashboard (Settings → Projects). Use this to provision a collection at the start of a flow before uploading documents. + +#### Delete collection +Permanently deletes a collection and all of its documents, sections, and chunks. + #### Get collection Returns metadata for a single collection by ID. -#### Get document upload URL -Returns a pre-signed S3 URL for a file upload, along with a document ID. After uploading directly to that URL with an HTTP PUT, call **Confirm document upload** to begin processing. +#### List documents +Returns documents in a collection, ordered by newest first. Supports optional filtering by status (`uploading`, `processing`, `ready`, `error`, etc.) and pagination via limit/offset. + +#### Delete document +Permanently deletes a document and all of its sections, chunks, and embeddings. + +#### Retry document +Re-queues a document that failed processing. Only works on documents with status `error`. Pair with the **When a document has an error** trigger to build automatic retry flows. + +#### Upload document +Uploads a file directly to a collection and queues it for processing. This is the simplest way to ingest a document — no hash computation, HTTP PUT, or separate confirmation step required. Pair with **Wait for document** to block until the file is fully indexed. + +#### Get document upload URL *(advanced)* +Returns a pre-signed S3 URL for a file upload, along with a document ID. Use this instead of **Upload document** when you need SHA-256 deduplication, want to avoid routing the file payload through Dewey's API (large files), or need to upload from a non-Power Automate client. After uploading directly to that URL with an HTTP PUT, call **Confirm document upload** to begin processing. #### Confirm document upload -Tells Dewey that the file upload to S3 is complete and processing should begin. +Tells Dewey that the file upload to S3 is complete and processing should begin. Only needed when using the **Get document upload URL** flow. #### Wait for document -Blocks until the document reaches a terminal state (ready or error) and returns the result. Times out after 5 minutes. Use this after **Confirm document upload** to pause a flow until the document is searchable. +Blocks until the document reaches a terminal state (ready or error) and returns the result. Times out after 5 minutes. Use this after **Upload document** or **Confirm document upload** to pause a flow until the document is searchable. + +#### List sections +Returns the heading hierarchy extracted from a document — section IDs, titles, levels, and positions. Use this to navigate document structure or feed section titles into a downstream AI step without loading full content. + +#### Scan sections +Searches section titles and summaries across an entire collection using hybrid semantic and keyword matching. Returns a ranked list of the most relevant sections with the document they belong to. Use this to locate the right parts of your corpus before loading content with **Get section** or **Get section chunks**. + +#### Get section +Returns a section's metadata and its full Markdown content. Use this after **Scan sections** or **List sections** to read the actual text of a relevant section without loading the entire document. + +#### Get section chunks +Returns the individual text chunks that make up a section. Use this instead of **Get section** when you want to feed section content into an AI Builder or Azure OpenAI step as pre-split passages rather than a single Markdown block. #### Search collection Runs a hybrid semantic and keyword search against a collection and returns the most relevant text chunks. Ideal for RAG flows where you want to feed context into a subsequent AI Builder or Azure OpenAI step. @@ -40,6 +70,15 @@ API keys are created in the Dewey dashboard under **Settings → API Keys**. Key ## Getting Started A typical SharePoint → Dewey ingestion flow: +1. **[SharePoint]** When a file is created in library +2. **[SharePoint]** Get file content +3. **[Dewey]** Upload document *(collectionId, file content, filename)* +4. **[Dewey]** Wait for document *(documentId — blocks until ready or error)* +5. **[Teams / Email]** Notify team — document is now searchable + +### Advanced: upload via pre-signed URL +Use this flow when you need explicit deduplication or want to avoid routing large file payloads through Dewey's API: + 1. **[SharePoint]** When a file is created in library 2. **[SharePoint]** Get file content 3. **[Dewey]** Get document upload URL *(collectionId, filename, contentType, fileSizeBytes, contentHash)* @@ -53,4 +92,4 @@ API reference: [meetdewey.com/docs](https://meetdewey.com/docs) ## Known Issues and Limitations - **Research queries** use Server-Sent Events and cannot be used as a connector action. Use **Search collection** to retrieve relevant chunks and feed them into an AI Builder or Azure OpenAI step instead. - **Wait for document** holds the flow connection open for up to 5 minutes. For high-volume ingestion flows, set trigger concurrency to limit parallel executions. -- SHA-256 is not natively available in Power Automate expressions. Use `base64(sha256(fileContent))` with `dataUriToString()`, or pass the SharePoint `eTag` as a consistent alternative for deduplication. +- **SHA-256 (advanced flow only)**: SHA-256 is not natively available in Power Automate expressions. If you use **Get document upload URL**, compute the hash with `base64(sha256(fileContent))` and `dataUriToString()`, or pass the SharePoint `eTag` as a consistent proxy. The **Upload document** action handles deduplication internally — no hash required. diff --git a/independent-publisher-connectors/Dewey/apiDefinition.swagger.json b/independent-publisher-connectors/Dewey/apiDefinition.swagger.json index 8c9a634408..a75b1955d4 100644 --- a/independent-publisher-connectors/Dewey/apiDefinition.swagger.json +++ b/independent-publisher-connectors/Dewey/apiDefinition.swagger.json @@ -40,14 +40,20 @@ "/integration/webhooks/document-ready": { "x-ms-notification-content": { "description": "Document ready event payload", - "schema": { "$ref": "#/definitions/WebhookPayload" } + "schema": { + "$ref": "#/definitions/WebhookPayload" + } }, "post": { "summary": "When a document is ready", "description": "Triggers when a document finishes processing and is ready to search. Use this to start a flow as soon as a newly uploaded document has been indexed.", "operationId": "TriggerDocumentReady", "x-ms-trigger": "single", - "security": [{ "api_key": [] }], + "security": [ + { + "api_key": [] + } + ], "parameters": [ { "name": "body", @@ -84,18 +90,23 @@ } } }, - "/integration/webhooks/document-error": { "x-ms-notification-content": { "description": "Document error event payload", - "schema": { "$ref": "#/definitions/WebhookPayload" } + "schema": { + "$ref": "#/definitions/WebhookPayload" + } }, "post": { "summary": "When a document has an error", "description": "Triggers when a document fails to process. Use this to alert your team or retry ingestion when processing fails.", "operationId": "TriggerDocumentError", "x-ms-trigger": "single", - "security": [{ "api_key": [] }], + "security": [ + { + "api_key": [] + } + ], "parameters": [ { "name": "body", @@ -132,14 +143,17 @@ } } }, - "/integration/webhooks/{id}": { "delete": { "summary": "Unsubscribe from document event", "description": "Removes a webhook subscription. Called automatically when a flow is deleted or disabled.", "operationId": "UnsubscribeDocumentEvent", "x-ms-visibility": "internal", - "security": [{ "api_key": [] }], + "security": [ + { + "api_key": [] + } + ], "parameters": [ { "name": "id", @@ -157,50 +171,263 @@ } } }, - "/collections": { "get": { "summary": "List collections", "description": "Returns all collections in your organisation.", "operationId": "ListCollections", - "security": [{ "api_key": [] }], + "security": [ + { + "api_key": [] + } + ], "responses": { "200": { "description": "List of collections", "schema": { "type": "array", - "items": { "$ref": "#/definitions/Collection" } + "items": { + "$ref": "#/definitions/Collection" + } + } + } + } + }, + "post": { + "summary": "Create collection", + "description": "Creates a new collection. A collection is the top-level namespace for documents, sections, and chunks. You need a project ID from the Dewey dashboard (Settings → Projects) to create one.", + "operationId": "CreateCollection", + "security": [ + { + "api_key": [] + } + ], + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "type": "object", + "required": ["name", "projectId"], + "properties": { + "name": { + "type": "string", + "title": "Name", + "x-ms-summary": "Name", + "description": "Display name for the collection (max 100 characters)" + }, + "projectId": { + "type": "string", + "title": "Project ID", + "x-ms-summary": "Project ID", + "description": "ID of the project this collection belongs to. Find it in the Dewey dashboard under Settings → Projects." + }, + "visibility": { + "type": "string", + "title": "Visibility", + "x-ms-summary": "Visibility", + "description": "Whether the collection is accessible without an API key (default: private)", + "x-ms-visibility": "advanced", + "enum": ["private", "public"], + "default": "private" + } + } + } + } + ], + "responses": { + "201": { + "description": "Collection created", + "schema": { + "$ref": "#/definitions/Collection" } } } } }, - "/collections/{collectionId}": { "get": { "summary": "Get collection", "description": "Returns details for a single collection.", "operationId": "GetCollection", - "security": [{ "api_key": [] }], - "parameters": [{ "$ref": "#/parameters/collectionId" }], + "security": [ + { + "api_key": [] + } + ], + "parameters": [ + { + "$ref": "#/parameters/collectionId" + } + ], "responses": { "200": { "description": "Collection details", - "schema": { "$ref": "#/definitions/Collection" } + "schema": { + "$ref": "#/definitions/Collection" + } }, - "404": { "description": "Collection not found" } + "404": { + "description": "Collection not found" + } + } + }, + "delete": { + "summary": "Delete collection", + "description": "Permanently deletes a collection and all of its documents, sections, and chunks. This cannot be undone.", + "operationId": "DeleteCollection", + "security": [ + { + "api_key": [] + } + ], + "parameters": [ + { + "$ref": "#/parameters/collectionId" + } + ], + "responses": { + "204": { + "description": "Collection deleted" + } + } + } + }, + "/collections/{collectionId}/documents": { + "post": { + "summary": "Upload document", + "description": "Uploads a document file directly to a collection and queues it for processing. Simpler than 'Get document upload URL' — no hash computation, HTTP PUT, or separate confirmation step required. Returns immediately; pair with 'Wait for document' if the flow needs to block until the document is fully indexed and searchable.", + "operationId": "UploadDocument", + "security": [ + { + "api_key": [] + } + ], + "consumes": ["multipart/form-data"], + "parameters": [ + { + "$ref": "#/parameters/collectionId" + }, + { + "name": "file", + "in": "formData", + "required": true, + "type": "file", + "x-ms-summary": "File", + "description": "The document file to upload (PDF, DOCX, PPTX, etc.)" + }, + { + "name": "filename", + "in": "query", + "required": false, + "type": "string", + "x-ms-summary": "Filename", + "x-ms-visibility": "advanced", + "description": "Display name stored in Dewey (e.g. 'Q4 Report.pdf'). Set this explicitly when the file comes from a 'Get file content' action that does not preserve the original filename. Leave blank to use the filename from the uploaded file." + } + ], + "responses": { + "202": { + "description": "Document accepted and ingestion queued. Use 'Wait for document' to block until processing is complete.", + "schema": { + "$ref": "#/definitions/Document" + } + } + } + }, + "get": { + "summary": "List documents", + "description": "Returns documents in a collection, ordered by creation date (newest first). Supports pagination and optional status filtering.", + "operationId": "ListDocuments", + "security": [ + { + "api_key": [] + } + ], + "parameters": [ + { + "$ref": "#/parameters/collectionId" + }, + { + "name": "status", + "in": "query", + "required": false, + "type": "string", + "x-ms-summary": "Status filter", + "description": "Return only documents with this status", + "x-ms-visibility": "advanced", + "enum": [ + "uploading", + "processing", + "sectioned", + "embedded", + "ready", + "error" + ] + }, + { + "name": "limit", + "in": "query", + "required": false, + "type": "integer", + "x-ms-summary": "Limit", + "description": "Maximum number of documents to return (default 100, max 500)", + "x-ms-visibility": "advanced", + "default": 100, + "maximum": 500 + }, + { + "name": "offset", + "in": "query", + "required": false, + "type": "integer", + "x-ms-summary": "Offset", + "description": "Number of documents to skip (for pagination)", + "x-ms-visibility": "advanced", + "default": 0 + } + ], + "responses": { + "200": { + "description": "List of documents", + "schema": { + "type": "object", + "properties": { + "documents": { + "type": "array", + "title": "Documents", + "x-ms-summary": "Documents", + "items": { + "$ref": "#/definitions/Document" + } + }, + "total": { + "type": "integer", + "title": "Total", + "x-ms-summary": "Total", + "description": "Total number of documents matching the filter (before pagination)" + } + } + } + } } } }, - "/collections/{collectionId}/documents/upload-url": { "post": { "summary": "Get document upload URL", "description": "Returns a pre-signed S3 URL to upload a document. After uploading the file directly to that URL with an HTTP PUT, call 'Confirm document upload' to begin processing. Use 'Wait for document' to block until the document is indexed.", "operationId": "GetDocumentUploadUrl", - "security": [{ "api_key": [] }], + "security": [ + { + "api_key": [] + } + ], "parameters": [ - { "$ref": "#/parameters/collectionId" }, + { + "$ref": "#/parameters/collectionId" + }, { "name": "body", "in": "body", @@ -265,72 +492,133 @@ } } }, - "/collections/{collectionId}/documents/{documentId}/confirm": { "post": { "summary": "Confirm document upload", "description": "Tells Dewey that the file upload to S3 is complete and processing should begin. Call this after a successful PUT to the upload URL.", "operationId": "ConfirmDocumentUpload", - "security": [{ "api_key": [] }], + "security": [ + { + "api_key": [] + } + ], "parameters": [ - { "$ref": "#/parameters/collectionId" }, - { "$ref": "#/parameters/documentId" } + { + "$ref": "#/parameters/collectionId" + }, + { + "$ref": "#/parameters/documentId" + } ], "responses": { "200": { "description": "Processing started", - "schema": { "$ref": "#/definitions/Document" } + "schema": { + "$ref": "#/definitions/Document" + } }, - "404": { "description": "Document not found" } + "404": { + "description": "Document not found" + } } } }, - "/documents/{documentId}": { "get": { "summary": "Get document", "description": "Returns the current status and metadata for a document.", "operationId": "GetDocument", - "security": [{ "api_key": [] }], - "parameters": [{ "$ref": "#/parameters/documentId" }], + "security": [ + { + "api_key": [] + } + ], + "parameters": [ + { + "$ref": "#/parameters/documentId" + } + ], "responses": { "200": { "description": "Document details", - "schema": { "$ref": "#/definitions/Document" } + "schema": { + "$ref": "#/definitions/Document" + } + }, + "404": { + "description": "Document not found" + } + } + }, + "delete": { + "summary": "Delete document", + "description": "Permanently deletes a document and all of its sections, chunks, and embeddings.", + "operationId": "DeleteDocument", + "security": [ + { + "api_key": [] + } + ], + "parameters": [ + { + "$ref": "#/parameters/documentId" + } + ], + "responses": { + "204": { + "description": "Document deleted" }, - "404": { "description": "Document not found" } + "404": { + "description": "Document not found" + } } } }, - "/documents/{documentId}/wait": { "get": { "summary": "Wait for document", "description": "Blocks until the document reaches a terminal state (ready or error) and returns the result. Times out after 5 minutes with a 408 response. Use this after 'Confirm document upload' to pause a flow until the document is searchable.", "operationId": "WaitForDocument", - "security": [{ "api_key": [] }], - "parameters": [{ "$ref": "#/parameters/documentId" }], + "security": [ + { + "api_key": [] + } + ], + "parameters": [ + { + "$ref": "#/parameters/documentId" + } + ], "responses": { "200": { "description": "Document reached terminal state", - "schema": { "$ref": "#/definitions/Document" } + "schema": { + "$ref": "#/definitions/Document" + } + }, + "404": { + "description": "Document not found" }, - "404": { "description": "Document not found" }, "408": { "description": "Timed out waiting for processing to complete" } } } }, - "/collections/{collectionId}/research/sync": { "post": { "summary": "Research collection", "description": "Runs an agentic research loop against the collection and returns a complete answer with cited sources. Ideal for deep question-answering flows where you need a synthesised response rather than raw chunks.", "operationId": "ResearchCollection", - "security": [{ "api_key": [] }], + "security": [ + { + "api_key": [] + } + ], "parameters": [ - { "$ref": "#/parameters/collectionId" }, + { + "$ref": "#/parameters/collectionId" + }, { "name": "body", "in": "body", @@ -379,7 +667,9 @@ "type": "array", "title": "Sources", "x-ms-summary": "Sources", - "items": { "$ref": "#/definitions/ResearchSource" } + "items": { + "$ref": "#/definitions/ResearchSource" + } } } } @@ -387,15 +677,20 @@ } } }, - "/collections/{collectionId}/query": { "post": { "summary": "Search collection", "description": "Runs a hybrid semantic and keyword search against the collection and returns the most relevant text chunks. Ideal for RAG flows where you want to feed context into a subsequent AI step.", "operationId": "SearchCollection", - "security": [{ "api_key": [] }], + "security": [ + { + "api_key": [] + } + ], "parameters": [ - { "$ref": "#/parameters/collectionId" }, + { + "$ref": "#/parameters/collectionId" + }, { "name": "body", "in": "body", @@ -428,14 +723,197 @@ "description": "Search results", "schema": { "type": "array", - "items": { "$ref": "#/definitions/SearchResult" } + "items": { + "$ref": "#/definitions/SearchResult" + } + } + } + } + } + }, + "/documents/{documentId}/retry": { + "post": { + "summary": "Retry document", + "description": "Re-queues a document that failed processing. Only documents with status 'error' can be retried. Use the 'When a document has an error' trigger to detect failures automatically.", + "operationId": "RetryDocument", + "security": [ + { + "api_key": [] + } + ], + "parameters": [ + { + "$ref": "#/parameters/documentId" + } + ], + "responses": { + "200": { + "description": "Document re-queued for processing", + "schema": { + "$ref": "#/definitions/Document" + } + }, + "404": { + "description": "Document not found" + }, + "409": { + "description": "Document is not in error state" + } + } + } + }, + "/documents/{documentId}/sections": { + "get": { + "summary": "List sections", + "description": "Returns the heading hierarchy extracted from a document — titles, levels, and positions. Use this to navigate document structure before fetching full content, or to feed section titles into a search or AI step.", + "operationId": "ListSections", + "security": [ + { + "api_key": [] + } + ], + "parameters": [ + { + "$ref": "#/parameters/documentId" + } + ], + "responses": { + "200": { + "description": "Section list", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Section" + } + } + }, + "404": { + "description": "Document not found" + } + } + } + }, + "/collections/{collectionId}/sections/scan": { + "post": { + "summary": "Scan sections", + "description": "Searches section titles and summaries (not chunk content) using hybrid semantic and keyword matching. Returns a ranked list of the most relevant sections across all documents in the collection. Use this to identify which parts of the corpus are relevant before loading full chunk content — a cheaper alternative to a full search when you only need to locate the right sections.", + "operationId": "ScanSections", + "security": [ + { + "api_key": [] + } + ], + "parameters": [ + { + "$ref": "#/parameters/collectionId" + }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "type": "object", + "required": ["query"], + "properties": { + "query": { + "type": "string", + "title": "Query", + "x-ms-summary": "Query", + "description": "Natural language query to match against section titles and summaries" + }, + "top_k": { + "type": "integer", + "title": "Result limit", + "x-ms-summary": "Result limit", + "description": "Maximum number of sections to return (default 20, max 100)", + "x-ms-visibility": "advanced", + "default": 20, + "maximum": 100 + } + } + } + } + ], + "responses": { + "200": { + "description": "Ranked section results", + "schema": { + "type": "object", + "properties": { + "results": { + "type": "array", + "title": "Results", + "x-ms-summary": "Results", + "items": { + "$ref": "#/definitions/SectionScanResult" + } + } + } } } } } + }, + "/sections/{sectionId}": { + "get": { + "summary": "Get section", + "description": "Returns a section's metadata and its full Markdown content. Use this after 'Scan sections' or 'List sections' to read the actual text of a relevant section without loading the entire document.", + "operationId": "GetSection", + "security": [ + { + "api_key": [] + } + ], + "parameters": [ + { + "$ref": "#/parameters/sectionId" + } + ], + "responses": { + "200": { + "description": "Section with content", + "schema": { + "$ref": "#/definitions/SectionWithContent" + } + }, + "404": { + "description": "Section not found" + } + } + } + }, + "/sections/{sectionId}/chunks": { + "get": { + "summary": "Get section chunks", + "description": "Returns the individual text chunks that make up a section. Chunks are the unit Dewey uses for embedding and retrieval. Use this instead of 'Get section' when you want to feed section content into an AI Builder or Azure OpenAI step as pre-split passages rather than a single Markdown block.", + "operationId": "GetSectionChunks", + "security": [ + { + "api_key": [] + } + ], + "parameters": [ + { + "$ref": "#/parameters/sectionId" + } + ], + "responses": { + "200": { + "description": "Chunks belonging to the section", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Chunk" + } + } + }, + "404": { + "description": "Section not found" + } + } + } } }, - "parameters": { "collectionId": { "name": "collectionId", @@ -460,15 +938,31 @@ "x-ms-summary": "Document ID", "description": "The document ID", "x-ms-url-encoding": "single" + }, + "sectionId": { + "name": "sectionId", + "in": "path", + "required": true, + "type": "string", + "x-ms-summary": "Section ID", + "description": "The section ID", + "x-ms-url-encoding": "single" } }, - "definitions": { "Collection": { "type": "object", "properties": { - "id": { "type": "string", "title": "ID", "x-ms-summary": "ID" }, - "name": { "type": "string", "title": "Name", "x-ms-summary": "Name" }, + "id": { + "type": "string", + "title": "ID", + "x-ms-summary": "ID" + }, + "name": { + "type": "string", + "title": "Name", + "x-ms-summary": "Name" + }, "description": { "type": "string", "title": "Description", @@ -489,7 +983,11 @@ "Document": { "type": "object", "properties": { - "id": { "type": "string", "title": "ID", "x-ms-summary": "ID" }, + "id": { + "type": "string", + "title": "ID", + "x-ms-summary": "ID" + }, "collectionId": { "type": "string", "title": "Collection ID", @@ -657,6 +1155,202 @@ } } } + }, + "Section": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "Section ID", + "x-ms-summary": "Section ID" + }, + "title": { + "type": "string", + "title": "Title", + "x-ms-summary": "Title" + }, + "level": { + "type": "integer", + "title": "Heading Level", + "x-ms-summary": "Heading Level", + "description": "Heading depth (1 = top-level, 6 = deepest)" + }, + "position": { + "type": "integer", + "title": "Position", + "x-ms-summary": "Position", + "description": "Order of this section within the document" + }, + "markdownOffsetStart": { + "type": "integer", + "title": "Markdown Offset Start", + "x-ms-summary": "Markdown Offset Start" + }, + "markdownOffsetEnd": { + "type": "integer", + "title": "Markdown Offset End", + "x-ms-summary": "Markdown Offset End" + } + } + }, + "SectionScanResult": { + "type": "object", + "properties": { + "score": { + "type": "number", + "title": "Relevance Score", + "x-ms-summary": "Relevance Score" + }, + "section": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "Section ID", + "x-ms-summary": "Section ID" + }, + "title": { + "type": "string", + "title": "Title", + "x-ms-summary": "Title" + }, + "level": { + "type": "integer", + "title": "Heading Level", + "x-ms-summary": "Heading Level" + }, + "summary": { + "type": "string", + "title": "Summary", + "x-ms-summary": "Summary" + }, + "summaryType": { + "type": "string", + "title": "Summary Type", + "x-ms-summary": "Summary Type", + "description": "Whether the summary was AI-generated or extractive" + }, + "position": { + "type": "integer", + "title": "Position", + "x-ms-summary": "Position" + }, + "chunkCount": { + "type": "integer", + "title": "Chunk Count", + "x-ms-summary": "Chunk Count" + } + } + }, + "document": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "Document ID", + "x-ms-summary": "Document ID" + }, + "filename": { + "type": "string", + "title": "Filename", + "x-ms-summary": "Filename" + } + } + } + } + }, + "SectionWithContent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "Section ID", + "x-ms-summary": "Section ID" + }, + "documentId": { + "type": "string", + "title": "Document ID", + "x-ms-summary": "Document ID" + }, + "title": { + "type": "string", + "title": "Title", + "x-ms-summary": "Title" + }, + "level": { + "type": "integer", + "title": "Heading Level", + "x-ms-summary": "Heading Level", + "description": "Heading depth (1 = top-level, 6 = deepest)" + }, + "summary": { + "type": "string", + "title": "Summary", + "x-ms-summary": "Summary" + }, + "summaryType": { + "type": "string", + "title": "Summary Type", + "x-ms-summary": "Summary Type", + "description": "Whether the summary was AI-generated or extractive" + }, + "position": { + "type": "integer", + "title": "Position", + "x-ms-summary": "Position" + }, + "chunkCount": { + "type": "integer", + "title": "Chunk Count", + "x-ms-summary": "Chunk Count" + }, + "content": { + "type": "string", + "title": "Content", + "x-ms-summary": "Content", + "description": "Full Markdown text of the section. Null if the document has not finished processing." + } + } + }, + "Chunk": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "Chunk ID", + "x-ms-summary": "Chunk ID" + }, + "sectionId": { + "type": "string", + "title": "Section ID", + "x-ms-summary": "Section ID" + }, + "documentId": { + "type": "string", + "title": "Document ID", + "x-ms-summary": "Document ID" + }, + "collectionId": { + "type": "string", + "title": "Collection ID", + "x-ms-summary": "Collection ID" + }, + "content": { + "type": "string", + "title": "Content", + "x-ms-summary": "Content" + }, + "position": { + "type": "integer", + "title": "Position", + "x-ms-summary": "Position" + }, + "tokenCount": { + "type": "integer", + "title": "Token Count", + "x-ms-summary": "Token Count" + } + } } } } From 2123e7e226c8a6be0b07d8dfb645dbafa7eadd2b Mon Sep 17 00:00:00 2001 From: lambdabaa Date: Tue, 14 Apr 2026 23:19:00 -0700 Subject: [PATCH 3/3] Remove obsolete SSE caveat from Dewey connector README Co-Authored-By: Claude Sonnet 4.6 --- independent-publisher-connectors/Dewey/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/independent-publisher-connectors/Dewey/README.md b/independent-publisher-connectors/Dewey/README.md index 54f252fa45..972981ebb0 100644 --- a/independent-publisher-connectors/Dewey/README.md +++ b/independent-publisher-connectors/Dewey/README.md @@ -90,6 +90,5 @@ Use this flow when you need explicit deduplication or want to avoid routing larg API reference: [meetdewey.com/docs](https://meetdewey.com/docs) ## Known Issues and Limitations -- **Research queries** use Server-Sent Events and cannot be used as a connector action. Use **Search collection** to retrieve relevant chunks and feed them into an AI Builder or Azure OpenAI step instead. - **Wait for document** holds the flow connection open for up to 5 minutes. For high-volume ingestion flows, set trigger concurrency to limit parallel executions. - **SHA-256 (advanced flow only)**: SHA-256 is not natively available in Power Automate expressions. If you use **Get document upload URL**, compute the hash with `base64(sha256(fileContent))` and `dataUriToString()`, or pass the SharePoint `eTag` as a consistent proxy. The **Upload document** action handles deduplication internally — no hash required.