Cancel a signer's passkey recovery
Stops the signer’s open passkey recovery before Conduit co-approves it, for example during the cooling-off when the signer did not ask for it. Nothing changes on the signer’s passkeys, and wallet_ceremony.failed fires with status cancelled. A repeat call on a cancelled recovery succeeds. 404 RECOVERY_NOT_FOUND when the signer has no recovery; 409 CEREMONY_NOT_CANCELLABLE when the recovery already ended another way or Conduit is applying it.
curl --request POST \
--url https://api.sandbox.conduit.financial/v2/customers/{customerId}/wallet-signers/{signerId}/recovery/cancel \
--header 'Idempotency-Key: <idempotency-key>' \
--header 'x-api-key: <api-key>'import requests
url = "https://api.sandbox.conduit.financial/v2/customers/{customerId}/wallet-signers/{signerId}/recovery/cancel"
headers = {
"Idempotency-Key": "<idempotency-key>",
"x-api-key": "<api-key>"
}
response = requests.post(url, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Idempotency-Key': '<idempotency-key>', 'x-api-key': '<api-key>'}
};
fetch('https://api.sandbox.conduit.financial/v2/customers/{customerId}/wallet-signers/{signerId}/recovery/cancel', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.sandbox.conduit.financial/v2/customers/{customerId}/wallet-signers/{signerId}/recovery/cancel",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"Idempotency-Key: <idempotency-key>",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.sandbox.conduit.financial/v2/customers/{customerId}/wallet-signers/{signerId}/recovery/cancel"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("Idempotency-Key", "<idempotency-key>")
req.Header.Add("x-api-key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.sandbox.conduit.financial/v2/customers/{customerId}/wallet-signers/{signerId}/recovery/cancel")
.header("Idempotency-Key", "<idempotency-key>")
.header("x-api-key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sandbox.conduit.financial/v2/customers/{customerId}/wallet-signers/{signerId}/recovery/cancel")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Idempotency-Key"] = '<idempotency-key>'
request["x-api-key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"type": "INVALID_OID_FORMAT",
"title": "Invalid Object ID Format",
"status": 400,
"detail": "A path or query parameter expected a valid object identifier but received a value that does not match the expected format.",
"resolution": "Verify that all IDs in the request URL and query parameters are correctly formatted. IDs are typically prefixed strings like 'cus_...', 'app_...', or 'doc_...'.",
"docs": "https://conduit-v2.mintlify.app/errors#invalid-oid-format",
"instance": "/v2/...",
"correlationId": "00469ea4-52c1-4ffa-bd05-9f28b236a5fe",
"timestamp": "2026-01-15T09:30:00.000Z"
}{
"type": "API_KEY_MISSING",
"title": "API Key Missing",
"status": 401,
"detail": "The request did not include an API key. All API requests must be authenticated.",
"resolution": "Include your API key in the 'x-api-key' header with every request.",
"docs": "https://conduit-v2.mintlify.app/errors#api-key-missing",
"instance": "/v2/...",
"correlationId": "00469ea4-52c1-4ffa-bd05-9f28b236a5fe",
"timestamp": "2026-01-15T09:30:00.000Z"
}{
"type": "ORGANIZATION_ACCESS_SUSPENDED",
"title": "Organization Access Suspended",
"status": 403,
"detail": "Conduit has suspended this organization's access. Requests with the organization's API keys and from its users are refused until Conduit restores access.",
"resolution": "Contact Conduit support.",
"docs": "https://conduit-v2.mintlify.app/errors#organization-access-suspended",
"instance": "/v2/...",
"correlationId": "00469ea4-52c1-4ffa-bd05-9f28b236a5fe",
"timestamp": "2026-01-15T09:30:00.000Z"
}{
"type": "RECOVERY_NOT_FOUND",
"title": "Recovery Not Found",
"status": 404,
"detail": "The signer has no passkey recovery.",
"resolution": "Start a recovery with POST /v2/customers/{customerId}/wallet-signers/{signerId}/recovery.",
"docs": "https://conduit-v2.mintlify.app/errors#recovery-not-found",
"instance": "/v2/...",
"correlationId": "00469ea4-52c1-4ffa-bd05-9f28b236a5fe",
"timestamp": "2026-01-15T09:30:00.000Z"
}{
"type": "IDEMPOTENCY_KEY_CONFLICT",
"title": "Idempotency Key Conflict",
"status": 409,
"detail": "The idempotency key was previously used with a different request body, and that request succeeded or ended in a `5xx`. A `4xx` response does not bind the key. Idempotency keys are bound to the exact request shape — replays must match the original.",
"resolution": "Use a fresh idempotency key for the new request, or replay the original request unchanged.",
"docs": "https://conduit-v2.mintlify.app/errors#idempotency-key-conflict",
"instance": "/v2/...",
"correlationId": "00469ea4-52c1-4ffa-bd05-9f28b236a5fe",
"timestamp": "2026-01-15T09:30:00.000Z"
}{
"type": "UNSUPPORTED_MEDIA_TYPE",
"title": "Unsupported Media Type",
"status": 415,
"detail": "The request carries a body with a Content-Type this endpoint cannot parse. JSON endpoints accept 'application/json'; a body with no Content-Type header at all is assumed to be JSON. File-upload endpoints accept only 'multipart/form-data' — JSON or undeclared bodies are rejected there.",
"resolution": "Send the request body with the 'Content-Type: application/json' header. For file uploads, use 'Content-Type: multipart/form-data' — upload endpoints accept no other body type.",
"docs": "https://conduit-v2.mintlify.app/errors#unsupported-media-type",
"instance": "/v2/...",
"correlationId": "00469ea4-52c1-4ffa-bd05-9f28b236a5fe",
"timestamp": "2026-01-15T09:30:00.000Z"
}{
"type": "RATE_LIMITED",
"title": "Rate Limited",
"status": 429,
"detail": "Too many requests. This error is returned by three independent checks: the per-organization bucket applied to every authenticated API request; the per-IP bucket applied to unauthenticated traffic before an API key is validated; and the per-IP bucket applied when repeated invalid API keys are submitted from the same address. Honor the Retry-After header (also exposed as retryAfterSeconds in the body) before retrying. Current limits and remaining budget are visible in X-RateLimit-Limit (the bucket size), X-RateLimit-Remaining, and X-RateLimit-Reset (seconds until the bucket refills) on every response once your API key is accepted.",
"resolution": "Sleep until Retry-After seconds have elapsed, then retry. For sustained workloads exceeding the per-organization defaults, request a rate-limit increase through your support contact.",
"docs": "https://conduit-v2.mintlify.app/errors#rate-limited",
"instance": "/v2/...",
"correlationId": "00469ea4-52c1-4ffa-bd05-9f28b236a5fe",
"timestamp": "2026-01-15T09:30:00.000Z",
"retryAfterSeconds": 3
}{
"type": "INTERNAL_ERROR",
"title": "Internal Error",
"status": 500,
"detail": "An unexpected error occurred while processing your request.",
"resolution": "Retry the request after a brief delay. If the error persists, contact support and include the correlationId from the error response for investigation.",
"docs": "https://conduit-v2.mintlify.app/errors#internal-error",
"instance": "/v2/...",
"correlationId": "00469ea4-52c1-4ffa-bd05-9f28b236a5fe",
"timestamp": "2026-01-15T09:30:00.000Z"
}Authorizations
Headers
Caller-generated unique key that lets the server safely replay this request. The original response is returned for 30 days on any retry with the same key from the same organization, with the response header Idempotency-Replayed: true. Required on every state-changing money-moving or resource-creating POST.
1 - 128^[A-Za-z0-9_.:-]{1,128}$"01J7B3K2X9M8N5P6Q7R8S9T0V1"
Path Parameters
"cus_1A2b3C4d5E6f7G8h9I0jKl"
"wsg_1A2b3C4d5E6f7G8h9I0jKl"
Response
Recovery cancelled
curl --request POST \
--url https://api.sandbox.conduit.financial/v2/customers/{customerId}/wallet-signers/{signerId}/recovery/cancel \
--header 'Idempotency-Key: <idempotency-key>' \
--header 'x-api-key: <api-key>'import requests
url = "https://api.sandbox.conduit.financial/v2/customers/{customerId}/wallet-signers/{signerId}/recovery/cancel"
headers = {
"Idempotency-Key": "<idempotency-key>",
"x-api-key": "<api-key>"
}
response = requests.post(url, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Idempotency-Key': '<idempotency-key>', 'x-api-key': '<api-key>'}
};
fetch('https://api.sandbox.conduit.financial/v2/customers/{customerId}/wallet-signers/{signerId}/recovery/cancel', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.sandbox.conduit.financial/v2/customers/{customerId}/wallet-signers/{signerId}/recovery/cancel",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"Idempotency-Key: <idempotency-key>",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.sandbox.conduit.financial/v2/customers/{customerId}/wallet-signers/{signerId}/recovery/cancel"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("Idempotency-Key", "<idempotency-key>")
req.Header.Add("x-api-key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.sandbox.conduit.financial/v2/customers/{customerId}/wallet-signers/{signerId}/recovery/cancel")
.header("Idempotency-Key", "<idempotency-key>")
.header("x-api-key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sandbox.conduit.financial/v2/customers/{customerId}/wallet-signers/{signerId}/recovery/cancel")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Idempotency-Key"] = '<idempotency-key>'
request["x-api-key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"type": "INVALID_OID_FORMAT",
"title": "Invalid Object ID Format",
"status": 400,
"detail": "A path or query parameter expected a valid object identifier but received a value that does not match the expected format.",
"resolution": "Verify that all IDs in the request URL and query parameters are correctly formatted. IDs are typically prefixed strings like 'cus_...', 'app_...', or 'doc_...'.",
"docs": "https://conduit-v2.mintlify.app/errors#invalid-oid-format",
"instance": "/v2/...",
"correlationId": "00469ea4-52c1-4ffa-bd05-9f28b236a5fe",
"timestamp": "2026-01-15T09:30:00.000Z"
}{
"type": "API_KEY_MISSING",
"title": "API Key Missing",
"status": 401,
"detail": "The request did not include an API key. All API requests must be authenticated.",
"resolution": "Include your API key in the 'x-api-key' header with every request.",
"docs": "https://conduit-v2.mintlify.app/errors#api-key-missing",
"instance": "/v2/...",
"correlationId": "00469ea4-52c1-4ffa-bd05-9f28b236a5fe",
"timestamp": "2026-01-15T09:30:00.000Z"
}{
"type": "ORGANIZATION_ACCESS_SUSPENDED",
"title": "Organization Access Suspended",
"status": 403,
"detail": "Conduit has suspended this organization's access. Requests with the organization's API keys and from its users are refused until Conduit restores access.",
"resolution": "Contact Conduit support.",
"docs": "https://conduit-v2.mintlify.app/errors#organization-access-suspended",
"instance": "/v2/...",
"correlationId": "00469ea4-52c1-4ffa-bd05-9f28b236a5fe",
"timestamp": "2026-01-15T09:30:00.000Z"
}{
"type": "RECOVERY_NOT_FOUND",
"title": "Recovery Not Found",
"status": 404,
"detail": "The signer has no passkey recovery.",
"resolution": "Start a recovery with POST /v2/customers/{customerId}/wallet-signers/{signerId}/recovery.",
"docs": "https://conduit-v2.mintlify.app/errors#recovery-not-found",
"instance": "/v2/...",
"correlationId": "00469ea4-52c1-4ffa-bd05-9f28b236a5fe",
"timestamp": "2026-01-15T09:30:00.000Z"
}{
"type": "IDEMPOTENCY_KEY_CONFLICT",
"title": "Idempotency Key Conflict",
"status": 409,
"detail": "The idempotency key was previously used with a different request body, and that request succeeded or ended in a `5xx`. A `4xx` response does not bind the key. Idempotency keys are bound to the exact request shape — replays must match the original.",
"resolution": "Use a fresh idempotency key for the new request, or replay the original request unchanged.",
"docs": "https://conduit-v2.mintlify.app/errors#idempotency-key-conflict",
"instance": "/v2/...",
"correlationId": "00469ea4-52c1-4ffa-bd05-9f28b236a5fe",
"timestamp": "2026-01-15T09:30:00.000Z"
}{
"type": "UNSUPPORTED_MEDIA_TYPE",
"title": "Unsupported Media Type",
"status": 415,
"detail": "The request carries a body with a Content-Type this endpoint cannot parse. JSON endpoints accept 'application/json'; a body with no Content-Type header at all is assumed to be JSON. File-upload endpoints accept only 'multipart/form-data' — JSON or undeclared bodies are rejected there.",
"resolution": "Send the request body with the 'Content-Type: application/json' header. For file uploads, use 'Content-Type: multipart/form-data' — upload endpoints accept no other body type.",
"docs": "https://conduit-v2.mintlify.app/errors#unsupported-media-type",
"instance": "/v2/...",
"correlationId": "00469ea4-52c1-4ffa-bd05-9f28b236a5fe",
"timestamp": "2026-01-15T09:30:00.000Z"
}{
"type": "RATE_LIMITED",
"title": "Rate Limited",
"status": 429,
"detail": "Too many requests. This error is returned by three independent checks: the per-organization bucket applied to every authenticated API request; the per-IP bucket applied to unauthenticated traffic before an API key is validated; and the per-IP bucket applied when repeated invalid API keys are submitted from the same address. Honor the Retry-After header (also exposed as retryAfterSeconds in the body) before retrying. Current limits and remaining budget are visible in X-RateLimit-Limit (the bucket size), X-RateLimit-Remaining, and X-RateLimit-Reset (seconds until the bucket refills) on every response once your API key is accepted.",
"resolution": "Sleep until Retry-After seconds have elapsed, then retry. For sustained workloads exceeding the per-organization defaults, request a rate-limit increase through your support contact.",
"docs": "https://conduit-v2.mintlify.app/errors#rate-limited",
"instance": "/v2/...",
"correlationId": "00469ea4-52c1-4ffa-bd05-9f28b236a5fe",
"timestamp": "2026-01-15T09:30:00.000Z",
"retryAfterSeconds": 3
}{
"type": "INTERNAL_ERROR",
"title": "Internal Error",
"status": 500,
"detail": "An unexpected error occurred while processing your request.",
"resolution": "Retry the request after a brief delay. If the error persists, contact support and include the correlationId from the error response for investigation.",
"docs": "https://conduit-v2.mintlify.app/errors#internal-error",
"instance": "/v2/...",
"correlationId": "00469ea4-52c1-4ffa-bd05-9f28b236a5fe",
"timestamp": "2026-01-15T09:30:00.000Z"
}