MCP Server

Support DQE
Support DQE
  • Updated
MCP server - DQE One Standalone

DQE One Standalone exposes a Model Context Protocol (MCP) endpoint so AI assistants such as Claude can list, create and run your processes, check runs and upload files — the same operations as the REST API, driven by conversation.

{DOMAIN} is the host name of your own DQE One Standalone server — it is self-hosted, so this value depends on your deployment. {EMAIL} is your DQE One login and {API_TOKEN} the token generated in My Account > API Token.
Related documentation: DQE One Standalone API — Introduction (the REST API the tools are built on) and Manage your profile in DQE One Standalone (API token).
At a glance: JSON-RPC 2.0 over HTTP at POST https://{DOMAIN}/mcp, protocol version 2024-11-05, 18 tools, 5 prompts, no resources. Plain JSON responses (no streaming).

Connect an AI assistant

The assistant acts as you and only sees your own objects. Behind the scenes every tool calls the REST API with your API token, so you must have generated an API token (My Account > API Token) even when you connect with OAuth.

Option A — with a header (Claude Code, Claude Desktop config file)

Build the Basic credential from your email and token:

# Linux / macOS echo -n "you@example.com:your_api_token" | base64 # Windows PowerShell [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("you@example.com:your_api_token"))

Claude Code (restart the session afterwards; MCP servers load at startup):

claude mcp add --transport http dqe-one https://{DOMAIN}/mcp \ --header "Authorization: Basic <your_base64_credential>"

Claude Desktop — edit claude_desktop_config.json (macOS ~/Library/Application Support/Claude/, Windows %APPDATA%\Claude\) and restart:

{ "mcpServers": { "dqe-one": { "type": "http", "url": "https://{DOMAIN}/mcp", "headers": { "Authorization": "Basic <your_base64_credential>" } } } }

Option B — OAuth (custom connectors, for example in claude.ai)

Enter only the URL https://{DOMAIN}/mcp. The assistant then discovers everything itself:

  1. The server answers 401 with a WWW-Authenticate header pointing to /.well-known/oauth-protected-resource.
  2. The client reads /.well-known/oauth-authorization-server and registers itself with /oauth/register.
  3. It opens /oauth/authorize. You must be signed in to DQE One in the same browser; check the client name and click Authorize.
  4. The client exchanges the code at /oauth/token (PKCE S256 required) and receives a Bearer token valid 1 hour plus a refresh token.
Reachability: for claude.ai the callback and every tool call come from Anthropic’s side, so your server must be reachable over HTTPS from the internet. A server only reachable on your intranet works with Claude Code or Claude Desktop on a machine that can reach it (Option A).

Tools (18)

Arguments marked * are required. A tool that fails still answers HTTP 200 with isError: true and the message of the underlying REST API.

Tool Arguments Returns
list_processes — [{id,name,type,isDraft,lastRunId}] (your processes)
get_process id* Process details: source, file, credentials, ruleSet, lastRunId, dates
list_runs processId, runId, kind One run (with runId) or [{id,processId,type,startedOn,updatedOn,status,outputFile,count,error}]. processId wins over kind.
list_files — [{id,name,headers,rows,process_id}]
get_file id* One file entry
list_rulesets — [{id,setId,label,updatedOn,source}]. No publication status is returned, whatever the tool description says.
list_credentials — [{id,name}]. The connector type is not returned.
get_credential id* {id,login,name,type,status,process}; never the password or key
get_upload_status token* {status: pending|done|expired, file_id, ttl_seconds}
check_dataverse_table credential_id*, table_name* {table,exists,record_count}. Needs a Dynamics credential.
query_dataverse_table credential_id*, table_name*, top (100, max 5000) {table,exists,total_count,returned_count,records} — returns real customer records to the assistant.
start_marketing_campaign — The text of the marketing_campaign prompt; runs nothing.
create_process WRITE name*, kind*, source*, primaryKey*, fields*; optional credential, ruleSet, file, object, input_file_path, output_dir_path, description {"status":"success","id":N}. Same rules as Processes → createProcess.
run_process WRITE id* {"status":"success","message":"Process Enqueue","run_id":"101"} — asynchronous
upload_file WRITE — {url, token, expires_in: 3600, instructions} — a browser upload link
delete_file WRITE DESTRUCTIVE id* Permanent; refused while the file is linked to a process
create_credential WRITE name*, type* (salesforce, sftp, bigquery); login, client_id, endpoint, port, password, email, id, key_id, pvt {"status":"success","id":N}
delete_credential WRITE DESTRUCTIVE id* Refused while a process uses it

What differs from the tool descriptions

  • create_process cannot set filters, sync, autoMerge, mergeThreshold, metaToReparent, allowEmpty, next or reject_dir_path — so SFTP processes cannot be created through MCP. fields has a different shape per kind (see Processes), and for check_duplicate it is {"<setId>": ["<matching rule label>"]}.
  • create_credential offers 3 of the 6 REST types. Its secrets pass through the assistant’s context (and are written to the server’s debug logs): create credentials in the web interface instead.
  • run_process can return a normal result containing {"status":"error"} (draft process, no SFTP file, queue failure): read the body.
  • No tool reads a RuleSet’s matching labels, cancels a run, downloads results, merges or synchronises. Review results in the web interface.

Prompts (5)

prompts/list returns five parameterless prompts. prompts/get returns {description, messages, instructions} (instructions is a non-standard extra). There are no MCP resources.

Prompt Purpose
create_process_dedup Guided creation of a deduplication process (it still asks for filters, reparenting and sync, which create_process cannot set).
marketing_campaign Seven-step Dynamics workflow: query_dataverse_table → create_process + run_process (check_email, check_phone, check_duplicate) → list_runs. SMS sending is “coming soon”.
run_existing_process list_processes → get_process → run_process → list_runs.
check_process_status Check the status of a process.
manage_credentials Credential management workflow.

Uploading a file through MCP

  1. The assistant calls upload_file and gets https://{DOMAIN}/upload/<token>/, valid for 1 hour.
  2. You open the link in a browser and drop a .csv, .xlsx or .xls file (unique headers, no spaces, one file per link).
  3. The assistant polls get_upload_status until done, which gives the file_id.
  4. create_process with "source":"csv" and "file": <file_id>.
The link is the credential. The upload page needs no login: anyone holding the URL can upload into your account for one hour, and the link is shown in the chat. The page says “max 50 MB” but no limit is enforced on the server.

Worked example — deduplicate a CSV

  1. list_rulesets → pick one with source: "csv"; note its id (7) and setId (RS_ABC).
  2. upload_file, give the URL to the user, then get_upload_status until done (file_id 12).
  3. get_file {"id":12} → check that the primary key is in headers.
  4. Find the RuleSet’s matching labels. No MCP tool returns them: ask the user, or read matching.Labels[].value with getRuleset in the REST API.
  5. create_process:
{ "name": "Dedup contacts", "kind": "check_duplicate", "source": "csv", "primaryKey": "id", "file": 12, "ruleSet": 7, "fields": { "RS_ABC": ["Email + Name"] } }
  1. run_process {"id":42} → run_id "101".
  2. list_runs {"runId":101} until status is Finished or Failed.
  3. Review the duplicates in the DQE One web interface.

Limitations and security notes

These describe the current behaviour of the product.

  • No scopes, no read-only mode: a connected assistant can do everything your account can. Only connect assistants you trust.
  • OAuth client registration is open (no authentication): any client can register and choose the name shown on the consent screen. Check the name and the redirect before you click Authorize. You must still be signed in and consent.
  • Refresh tokens never expire and are not rotated; tokens are stored in clear in the database; there is no revocation screen. Administrators can revoke a token in the database.
  • The server writes request bodies and tool arguments — including credential secrets — to its debug output; whether this reaches logs depends on your deployment.
  • No rate limiting; CORS is open to any origin; the legacy SSE transport keeps sessions in memory and works with a single worker only.
JSON-RPC endpoint - DQE One Standalone MCP

The single entry point: send one JSON-RPC message, get one JSON object back.

mcpRpc

Request

Send a JSON-RPC 2.0 body. initialize and ping need no authentication; everything else needs Basic or Bearer.

Calling a tool: {"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"list_processes","arguments":{}}}. The result is {"content":[{"type":"text","text":"<JSON as a string>"}]}; on failure isError is true but the HTTP status stays 200.
Error codes: -32700 parse error (HTTP 400); -32601 unknown method or unknown tool; -32602 unknown prompt. Unauthorized is an HTTP 401 with a WWW-Authenticate header that starts OAuth discovery. There is no batching and resources/* is not implemented.
POSThttps://{DOMAIN}/mcp

Code examples

Send a JSON-RPC request

curl -u "{EMAIL}:{API_TOKEN}" -X POST \ -H "Content-Type: application/json" \ -d '{ "jsonrpc": "2.0", "id": 2, "method": "tools/list" }' \ "https://{DOMAIN}/mcp"
fetch("https://{DOMAIN}/mcp", { method: "POST", headers: { "Authorization": "Basic " + btoa("{EMAIL}:{API_TOKEN}"), "Content-Type": "application/json" }, body: JSON.stringify({ "jsonrpc": "2.0", "id": 2, "method": "tools/list" }) }) .then(r => r.text()) .then(data => console.log(data));
import requests response = requests.post( "https://{DOMAIN}/mcp", auth=("{EMAIL}", "{API_TOKEN}"), json={"jsonrpc": "2.0", "id": 2, "method": "tools/list"}, ) print(response.status_code, response.text)
<?php $ch = curl_init("https://{DOMAIN}/mcp"); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); curl_setopt($ch, CURLOPT_USERPWD, "{EMAIL}:{API_TOKEN}"); $data = ['jsonrpc' => '2.0', 'id' => 2, 'method' => 'tools/list']; curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); echo $status . " " . $response;
const axios = require('axios'); axios({ method: "post", url: "https://{DOMAIN}/mcp", auth: { username: "{EMAIL}", password: "{API_TOKEN}" }, data: { "jsonrpc": "2.0", "id": 2, "method": "tools/list" } }) .then(res => console.log(res.status, res.data)) .catch(err => console.log(err.response ? err.response.status : err.message, err.response && err.response.data));
import java.net.URI; import java.net.http.*; import java.util.Base64; String auth = Base64.getEncoder().encodeToString("{EMAIL}:{API_TOKEN}".getBytes()); String body = "{\"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"tools/list\"}"; HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://{DOMAIN}/mcp")) .header("Authorization", "Basic " + auth) .header("Content-Type", "application/json") .method("POST", HttpRequest.BodyPublishers.ofString(body)) .build(); HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.statusCode() + " " + response.body());
using System.Net.Http; using System.Net.Http.Headers; using System.Text; using var client = new HttpClient(); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue( "Basic", Convert.ToBase64String(Encoding.UTF8.GetBytes("{EMAIL}:{API_TOKEN}"))); using var request = new HttpRequestMessage(HttpMethod.Post, "https://{DOMAIN}/mcp"); request.Content = new StringContent("{\"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"tools/list\"}", Encoding.UTF8, "application/json"); var response = await client.SendAsync(request); Console.WriteLine((int)response.StatusCode + " " + await response.Content.ReadAsStringAsync());
package main import ( "bytes" "fmt" "io" "net/http" ) func main() { body := []byte(`{"jsonrpc":"2.0","id":2,"method":"tools/list"}`) req, _ := http.NewRequest("POST", "https://{DOMAIN}/mcp", bytes.NewBuffer(body)) req.SetBasicAuth("{EMAIL}", "{API_TOKEN}") req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() out, _ := io.ReadAll(resp.Body) fmt.Println(resp.StatusCode, string(out)) }

Parameters

Field Description Type Mand / Opt
jsonrpc
Values: 2.0
String Mandatory
id Integer Optional
method initialize and ping need no authentication. Everything else does. resources/* is not implemented (-32601).
Values: initialize, ping, tools/list, tools/call, prompts/list, prompts/get
String Mandatory
params Object Optional
Authentication: HTTP Basic (email:api_token) or an OAuth Bearer token. The console below uses Basic.

Response

JSON-RPC response. A failing tool still returns HTTP 200 with result.isError = true.. HTTP status 200.

Key Description Type
jsonrpc String
id Integer
result Object
error Object

Response example

Example response
{ "jsonrpc": "2.0", "id": 1, "result": { "protocolVersion": "2024-11-05", "capabilities": { "tools": {}, "prompts": {} }, "serverInfo": { "name": "dqe-one", "version": "1.0.0" } } }

Errors

HTTP Body / meaning
400 Parse error (-32700).
401 Unauthorized. Carries a WWW-Authenticate: Bearer resource_metadata=... header that triggers OAuth discovery.

Test the API

Click the button below to test this endpoint live in your browser.

Heads-up: this console sends a real request to your own server from your browser, with your real API token. tools/call can start runs or delete data.
Open console
Server info - DQE One Standalone MCP

Returns basic server information without authentication. With Accept: text/event-stream it opens the legacy SSE transport instead (Basic auth only; single worker).

mcpInfo

Request

Send a GET request.

GEThttps://{DOMAIN}/mcp

Code examples

Server info, or legacy SSE stream

curl \ "https://{DOMAIN}/mcp"
fetch("https://{DOMAIN}/mcp", { method: "GET" }) .then(r => r.text()) .then(data => console.log(data));
import requests response = requests.get( "https://{DOMAIN}/mcp", ) print(response.status_code, response.text)
<?php $ch = curl_init("https://{DOMAIN}/mcp"); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); echo $status . " " . $response;
const axios = require('axios'); axios({ method: "get", url: "https://{DOMAIN}/mcp" }) .then(res => console.log(res.status, res.data)) .catch(err => console.log(err.response ? err.response.status : err.message, err.response && err.response.data));
import java.net.URI; import java.net.http.*; import java.util.Base64; HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://{DOMAIN}/mcp")) .method("GET", HttpRequest.BodyPublishers.noBody()) .build(); HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.statusCode() + " " + response.body());
using System.Net.Http; using System.Net.Http.Headers; using System.Text; using var client = new HttpClient(); using var request = new HttpRequestMessage(HttpMethod.Get, "https://{DOMAIN}/mcp"); var response = await client.SendAsync(request); Console.WriteLine((int)response.StatusCode + " " + await response.Content.ReadAsStringAsync());
package main import ( "fmt" "io" "net/http" ) func main() { req, _ := http.NewRequest("GET", "https://{DOMAIN}/mcp", nil) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() out, _ := io.ReadAll(resp.Body) fmt.Println(resp.StatusCode, string(out)) }

Parameters

This endpoint takes no parameters.

Authentication: none — this endpoint is public (or secured by a token in the URL, see above).

Response

Server info or event stream.. HTTP status 200.

Response example

Example response
{ "name": "dqe-one", "version": "1.0.0" }

Errors

HTTP Body / meaning
No error response is documented for this endpoint.

Test the API

Click the button below to test this endpoint live in your browser.

Heads-up: this console sends a real request to your own server from your browser, with your real API token.
Open console
OAuth protected resource metadata - DQE One Standalone MCP

RFC 9728 metadata used by clients to discover the authorization server.

oauthProtectedResource

Request

Send a GET request.

GEThttps://{DOMAIN}/.well-known/oauth-protected-resource

Code examples

Protected resource metadata (RFC 9728)

curl \ "https://{DOMAIN}/.well-known/oauth-protected-resource"
fetch("https://{DOMAIN}/.well-known/oauth-protected-resource", { method: "GET" }) .then(r => r.text()) .then(data => console.log(data));
import requests response = requests.get( "https://{DOMAIN}/.well-known/oauth-protected-resource", ) print(response.status_code, response.text)
<?php $ch = curl_init("https://{DOMAIN}/.well-known/oauth-protected-resource"); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); echo $status . " " . $response;
const axios = require('axios'); axios({ method: "get", url: "https://{DOMAIN}/.well-known/oauth-protected-resource" }) .then(res => console.log(res.status, res.data)) .catch(err => console.log(err.response ? err.response.status : err.message, err.response && err.response.data));
import java.net.URI; import java.net.http.*; import java.util.Base64; HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://{DOMAIN}/.well-known/oauth-protected-resource")) .method("GET", HttpRequest.BodyPublishers.noBody()) .build(); HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.statusCode() + " " + response.body());
using System.Net.Http; using System.Net.Http.Headers; using System.Text; using var client = new HttpClient(); using var request = new HttpRequestMessage(HttpMethod.Get, "https://{DOMAIN}/.well-known/oauth-protected-resource"); var response = await client.SendAsync(request); Console.WriteLine((int)response.StatusCode + " " + await response.Content.ReadAsStringAsync());
package main import ( "fmt" "io" "net/http" ) func main() { req, _ := http.NewRequest("GET", "https://{DOMAIN}/.well-known/oauth-protected-resource", nil) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() out, _ := io.ReadAll(resp.Body) fmt.Println(resp.StatusCode, string(out)) }

Parameters

This endpoint takes no parameters.

Authentication: none — this endpoint is public (or secured by a token in the URL, see above).

Response

{resource, authorization_servers, bearer_methods_supported}. HTTP status 200.

Response example

Example response
{ "resource": "https://{DOMAIN}/mcp", "authorization_servers": [ "https://{DOMAIN}" ], "bearer_methods_supported": [ "header" ] }

Errors

HTTP Body / meaning
No error response is documented for this endpoint.

Test the API

Click the button below to test this endpoint live in your browser.

Heads-up: this console sends a real request to your own server from your browser, with your real API token.
Open console
OAuth server metadata - DQE One Standalone MCP

RFC 8414 metadata: endpoints and supported flows.

oauthServerMetadata

Request

Send a GET request.

GEThttps://{DOMAIN}/.well-known/oauth-authorization-server

Code examples

Authorization server metadata (RFC 8414)

curl \ "https://{DOMAIN}/.well-known/oauth-authorization-server"
fetch("https://{DOMAIN}/.well-known/oauth-authorization-server", { method: "GET" }) .then(r => r.text()) .then(data => console.log(data));
import requests response = requests.get( "https://{DOMAIN}/.well-known/oauth-authorization-server", ) print(response.status_code, response.text)
<?php $ch = curl_init("https://{DOMAIN}/.well-known/oauth-authorization-server"); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); echo $status . " " . $response;
const axios = require('axios'); axios({ method: "get", url: "https://{DOMAIN}/.well-known/oauth-authorization-server" }) .then(res => console.log(res.status, res.data)) .catch(err => console.log(err.response ? err.response.status : err.message, err.response && err.response.data));
import java.net.URI; import java.net.http.*; import java.util.Base64; HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://{DOMAIN}/.well-known/oauth-authorization-server")) .method("GET", HttpRequest.BodyPublishers.noBody()) .build(); HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.statusCode() + " " + response.body());
using System.Net.Http; using System.Net.Http.Headers; using System.Text; using var client = new HttpClient(); using var request = new HttpRequestMessage(HttpMethod.Get, "https://{DOMAIN}/.well-known/oauth-authorization-server"); var response = await client.SendAsync(request); Console.WriteLine((int)response.StatusCode + " " + await response.Content.ReadAsStringAsync());
package main import ( "fmt" "io" "net/http" ) func main() { req, _ := http.NewRequest("GET", "https://{DOMAIN}/.well-known/oauth-authorization-server", nil) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() out, _ := io.ReadAll(resp.Body) fmt.Println(resp.StatusCode, string(out)) }

Parameters

This endpoint takes no parameters.

Authentication: none — this endpoint is public (or secured by a token in the URL, see above).

Response

Endpoints, grant types (authorization_code, refresh_token), PKCE S256, auth methods none/client_secret_post.. HTTP status 200.

Response example

Example response
{ "authorization_endpoint": "https://{DOMAIN}/oauth/authorize", "token_endpoint": "https://{DOMAIN}/oauth/token", "registration_endpoint": "https://{DOMAIN}/oauth/register", "response_types_supported": [ "code" ], "grant_types_supported": [ "authorization_code", "refresh_token" ], "code_challenge_methods_supported": [ "S256" ], "token_endpoint_auth_methods_supported": [ "none", "client_secret_post" ] }

Errors

HTTP Body / meaning
No error response is documented for this endpoint.

Test the API

Click the button below to test this endpoint live in your browser.

Heads-up: this console sends a real request to your own server from your browser, with your real API token.
Open console
Register a client - DQE One Standalone MCP

Dynamic client registration (RFC 7591). Open: no authentication.

oauthRegister

Request

Send a JSON body with at least redirect_uris.

POSThttps://{DOMAIN}/oauth/register

Code examples

Dynamic client registration (RFC 7591)

curl -X POST \ -H "Content-Type: application/json" \ -d '{ "redirect_uris": [ "https://client.example.com/callback" ], "client_name": "My connector" }' \ "https://{DOMAIN}/oauth/register"
fetch("https://{DOMAIN}/oauth/register", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ "redirect_uris": [ "https://client.example.com/callback" ], "client_name": "My connector" }) }) .then(r => r.text()) .then(data => console.log(data));
import requests response = requests.post( "https://{DOMAIN}/oauth/register", json={"redirect_uris": ["https://client.example.com/callback"], "client_name": "My connector"}, ) print(response.status_code, response.text)
<?php $ch = curl_init("https://{DOMAIN}/oauth/register"); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); $data = ['redirect_uris' => ['https://client.example.com/callback'], 'client_name' => 'My connector']; curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); echo $status . " " . $response;
const axios = require('axios'); axios({ method: "post", url: "https://{DOMAIN}/oauth/register", data: { "redirect_uris": [ "https://client.example.com/callback" ], "client_name": "My connector" } }) .then(res => console.log(res.status, res.data)) .catch(err => console.log(err.response ? err.response.status : err.message, err.response && err.response.data));
import java.net.URI; import java.net.http.*; import java.util.Base64; String body = "{\"redirect_uris\":[\"https://client.example.com/callback\"],\"client_name\":\"My connector\"}"; HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://{DOMAIN}/oauth/register")) .header("Content-Type", "application/json") .method("POST", HttpRequest.BodyPublishers.ofString(body)) .build(); HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.statusCode() + " " + response.body());
using System.Net.Http; using System.Net.Http.Headers; using System.Text; using var client = new HttpClient(); using var request = new HttpRequestMessage(HttpMethod.Post, "https://{DOMAIN}/oauth/register"); request.Content = new StringContent("{\"redirect_uris\":[\"https://client.example.com/callback\"],\"client_name\":\"My connector\"}", Encoding.UTF8, "application/json"); var response = await client.SendAsync(request); Console.WriteLine((int)response.StatusCode + " " + await response.Content.ReadAsStringAsync());
package main import ( "bytes" "fmt" "io" "net/http" ) func main() { body := []byte(`{"redirect_uris":["https://client.example.com/callback"],"client_name":"My connector"}`) req, _ := http.NewRequest("POST", "https://{DOMAIN}/oauth/register", bytes.NewBuffer(body)) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() out, _ := io.ReadAll(resp.Body) fmt.Println(resp.StatusCode, string(out)) }

Parameters

Field Description Type Mand / Opt
redirect_uris Non-empty list of callback URLs. Array Mandatory
client_name Shown to the user on the consent page. String Optional
token_endpoint_auth_method client_secret_post also returns a client_secret, once.
Values: none, client_secret_post · Default: "none"
String Optional
Authentication: none — this endpoint is public (or secured by a token in the URL, see above).

Response

Client registered (client_secret returned once for client_secret_post).. HTTP status 201.

Response example

Example response
{ "client_id": "kQ3...", "client_name": "My connector", "redirect_uris": [ "https://client.example.com/callback" ], "token_endpoint_auth_method": "none" }

Errors

HTTP Body / meaning
400 Invalid request.
Consent page - DQE One Standalone MCP

The page where you approve a connector. It is opened in a browser, not called from code. You must be signed in to DQE One in the same browser; PKCE S256 is mandatory; the code lasts 5 minutes.

oauthAuthorize

Request

The client redirects your browser to this URL.

GEThttps://{DOMAIN}/oauth/authorize?client_id={client_id}&redirect_uri={redirect_uri}&response_type={response_type}&code_challenge={code_challenge}&code_challenge_method={code_challenge_method}&state={state}

Example URL

https://{DOMAIN}/oauth/authorize?client_id=kQ3...&redirect_uri=https%3A%2F%2Fclient.example.com%2Fcallback&response_type=code&code_challenge=E9Melhoa...&code_challenge_method=S256&state=xyz

Parameters

Field Description Type Mand / Opt
client_id Client id returned by /oauth/register. String Mandatory
redirect_uri Must exactly match one of the registered redirect URIs. String Mandatory
response_type code (default). String Optional
code_challenge PKCE challenge. String Mandatory
code_challenge_method Must be S256. String Mandatory
state Opaque value returned to the client. String Optional
Authentication: none — this endpoint is public (or secured by a token in the URL, see above).

Response

Consent page (Allow / Deny).. HTTP status 200.

Response example

Example response
{ "redirect": "https://client.example.com/callback?code=...&state=xyz" }

Errors

HTTP Body / meaning
400 Invalid request.
Token endpoint - DQE One Standalone MCP

Exchanges an authorization code for tokens, or refreshes an access token. The access token lasts 1 hour; refresh tokens do not expire and are not rotated.

oauthToken

Request

Send a form-encoded POST.

POSThttps://{DOMAIN}/oauth/token

Code examples

Exchange a code or refresh a token

curl -X POST \ --data-urlencode "grant_type=authorization_code" \ --data-urlencode "code=AUTH_CODE" \ --data-urlencode "redirect_uri=https://client.example.com/callback" \ --data-urlencode "code_verifier=PKCE_VERIFIER" \ --data-urlencode "client_id=CLIENT_ID" \ "https://{DOMAIN}/oauth/token"
fetch("https://{DOMAIN}/oauth/token", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams({ "grant_type": "authorization_code", "code": "AUTH_CODE", "redirect_uri": "https://client.example.com/callback", "code_verifier": "PKCE_VERIFIER", "client_id": "CLIENT_ID" }) }) .then(r => r.text()) .then(data => console.log(data));
import requests response = requests.post( "https://{DOMAIN}/oauth/token", data={"grant_type": "authorization_code", "code": "AUTH_CODE", "redirect_uri": "https://client.example.com/callback", "code_verifier": "PKCE_VERIFIER", "client_id": "CLIENT_ID"}, ) print(response.status_code, response.text)
<?php $ch = curl_init("https://{DOMAIN}/oauth/token"); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(['grant_type' => 'authorization_code', 'code' => 'AUTH_CODE', 'redirect_uri' => 'https://client.example.com/callback', 'code_verifier' => 'PKCE_VERIFIER', 'client_id' => 'CLIENT_ID'])); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); echo $status . " " . $response;
const axios = require('axios'); axios({ method: "post", url: "https://{DOMAIN}/oauth/token", data: new URLSearchParams({ "grant_type": "authorization_code", "code": "AUTH_CODE", "redirect_uri": "https://client.example.com/callback", "code_verifier": "PKCE_VERIFIER", "client_id": "CLIENT_ID" }) }) .then(res => console.log(res.status, res.data)) .catch(err => console.log(err.response ? err.response.status : err.message, err.response && err.response.data));
import java.net.URI; import java.net.http.*; import java.util.Base64; String body = "grant_type=authorization_code&code=AUTH_CODE&redirect_uri=https%3A%2F%2Fclient.example.com%2Fcallback&code_verifier=PKCE_VERIFIER&client_id=CLIENT_ID"; HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://{DOMAIN}/oauth/token")) .header("Content-Type", "application/x-www-form-urlencoded") .method("POST", HttpRequest.BodyPublishers.ofString(body)) .build(); HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.statusCode() + " " + response.body());
using System.Net.Http; using System.Net.Http.Headers; using System.Text; using var client = new HttpClient(); using var request = new HttpRequestMessage(HttpMethod.Post, "https://{DOMAIN}/oauth/token"); request.Content = new FormUrlEncodedContent(new Dictionary<string, string> { { "grant_type", "authorization_code" }, { "code", "AUTH_CODE" }, { "redirect_uri", "https://client.example.com/callback" }, { "code_verifier", "PKCE_VERIFIER" }, { "client_id", "CLIENT_ID" } }); var response = await client.SendAsync(request); Console.WriteLine((int)response.StatusCode + " " + await response.Content.ReadAsStringAsync());
package main import ( "fmt" "io" "net/http" "net/url" "strings" ) func main() { form := url.Values{} form.Set("grant_type", "authorization_code") form.Set("code", "AUTH_CODE") form.Set("redirect_uri", "https://client.example.com/callback") form.Set("code_verifier", "PKCE_VERIFIER") form.Set("client_id", "CLIENT_ID") req, _ := http.NewRequest("POST", "https://{DOMAIN}/oauth/token", strings.NewReader(form.Encode())) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() out, _ := io.ReadAll(resp.Body) fmt.Println(resp.StatusCode, string(out)) }

Parameters

Field Description Type Mand / Opt
grant_type
Values: authorization_code, refresh_token
String Mandatory
code Authorization code (5 minutes, single use). String Optional
redirect_uri Same value as in the authorization request. String Optional
code_verifier PKCE verifier. String Optional
refresh_token For grant_type refresh_token. String Optional
client_id String Optional
client_secret Only for clients registered with client_secret_post. String Optional
Authentication: none — this endpoint is public (or secured by a token in the URL, see above).

Response

{access_token, token_type: Bearer, expires_in: 3600, refresh_token, scope}. HTTP status 200.

Response example

Example response
{ "access_token": "...", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "...", "scope": "" }

Errors

HTTP Body / meaning
400 invalid_grant / invalid_client.
Upload page - DQE One Standalone MCP

The browser page behind the link returned by the upload_file tool. The token in the URL is the only credential.

uploadPage

Request

You open the link in a browser.

GEThttps://{DOMAIN}/upload/{token}/

Example URL

https://{DOMAIN}/upload/3f1c0a52-...-9b7e/

Parameters

Field Description Type Mand / Opt
token String Mandatory
Authentication: none — this endpoint is public (or secured by a token in the URL, see above).

Response

HTML page.. HTTP status 200.

Response example

Example response
{ "info": "HTML page" }

Errors

HTTP Body / meaning
No error response is documented for this endpoint.
Upload the file - DQE One Standalone MCP

What the upload page sends when you drop a file. You normally never call it yourself.

uploadFile

Request

A multipart/form-data POST with field file.

One file per link, valid 1 hour. .csv, .xlsx, .xls; headers unique and without spaces. No server-side size limit.
POSThttps://{DOMAIN}/upload/{token}/

Code examples

Upload the file

curl -X POST \ -F "file=@contacts.csv" \ "https://{DOMAIN}/upload/{token}/"
const form = new FormData(); form.append("file", fileInput.files[0]); // <input type="file"> fetch("https://{DOMAIN}/upload/{token}/", { method: "POST", body: form }) .then(r => r.text()) .then(data => console.log(data));
import requests response = requests.post( "https://{DOMAIN}/upload/{token}/", files={"file": open("contacts.csv", "rb")}, ) print(response.status_code, response.text)
<?php $ch = curl_init("https://{DOMAIN}/upload/{token}/"); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); curl_setopt($ch, CURLOPT_POSTFIELDS, ['file' => new CURLFile("contacts.csv")]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); echo $status . " " . $response;
const axios = require('axios'); const FormData = require('form-data'); const fs = require('fs'); const form = new FormData(); form.append('file', fs.createReadStream("contacts.csv")); axios({ method: "post", url: "https://{DOMAIN}/upload/{token}/", headers: form.getHeaders(), data: form }) .then(res => console.log(res.status, res.data)) .catch(err => console.log(err.response ? err.response.status : err.message, err.response && err.response.data));
import java.net.URI; import java.net.http.*; import java.util.Base64; String boundary = "----dqe" + System.nanoTime(); byte[] content = java.nio.file.Files.readAllBytes(java.nio.file.Path.of("contacts.csv")); var out = new java.io.ByteArrayOutputStream(); out.write(("--" + boundary + "\r\nContent-Disposition: form-data; name=\"file\"; filename=\"" + "contacts.csv" + "\"\r\n\r\n").getBytes()); out.write(content); out.write(("\r\n--" + boundary + "--\r\n").getBytes()); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://{DOMAIN}/upload/{token}/")) .header("Content-Type", "multipart/form-data; boundary=" + boundary) .method("POST", HttpRequest.BodyPublishers.ofByteArray(out.toByteArray())) .build(); HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.statusCode() + " " + response.body());
using System.Net.Http; using System.Net.Http.Headers; using System.Text; using var client = new HttpClient(); using var request = new HttpRequestMessage(HttpMethod.Post, "https://{DOMAIN}/upload/{token}/"); var form = new MultipartFormDataContent(); form.Add(new ByteArrayContent(File.ReadAllBytes("contacts.csv")), "file", "contacts.csv"); request.Content = form; var response = await client.SendAsync(request); Console.WriteLine((int)response.StatusCode + " " + await response.Content.ReadAsStringAsync());
package main import ( "bytes" "fmt" "io" "mime/multipart" "net/http" "os" ) func main() { var buf bytes.Buffer w := multipart.NewWriter(&buf) part, _ := w.CreateFormFile("file", "contacts.csv") f, _ := os.Open("contacts.csv") io.Copy(part, f) w.Close() req, _ := http.NewRequest("POST", "https://{DOMAIN}/upload/{token}/", &buf) req.Header.Set("Content-Type", w.FormDataContentType()) resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() out, _ := io.ReadAll(resp.Body) fmt.Println(resp.StatusCode, string(out)) }

Parameters

Field Description Type Mand / Opt
token String Mandatory
file String (file) Mandatory
Authentication: none — this endpoint is public (or secured by a token in the URL, see above).

Response

{status: success, file_id, name}. HTTP status 200.

Response example

Example response
{ "status": "success", "file_id": 12, "name": "contacts.csv" }

Errors

HTTP Body / meaning
400 Wrong extension, bad headers, or link already used.

See also

Related to

Was this article helpful?

0 out of 0 found this helpful