DEVELOPERS
AI apps
The Live request object
AI apps connected over MCP (OAuth), and live requests waiting for a human.
ATTRIBUTES
- object enum
- live_request
- id string
- action enum
The operation (LiveRequestCreate lists each one with its params).
- create_live_api_key
- publish_flow_live
- set_billing_source
- create_webhook_endpoint
- update_webhook_endpoint
- delete_webhook_endpoint
- test_webhook_endpoint
- create_attribute_definition
- update_attribute_definition
- create_customer
- update_customer
- set_customer_attributes
- record_usage_event
- record_usage_events
- create_subscription
- update_subscription
- record_payment
- title string
The operation's name, e.g. Add a live webhook endpoint.
- summary string
What approving does, written by NoChurn from the params (never by the AI app).
- params object
The operation's params as checked by NoChurn (LiveRequestParams*), e.g. a customer reference resolved to its cst_… id.
- precondition object | null
What must still hold at approval, else the request fails without acting.
Show child attributesHide child attributes
- kind enum
- draft_digest
- current_value
- record_version
- record_exists
- object string | null
flow, billing_source, webhook_endpoint, attribute_definition, customer, subscription
- id string | null
- expected string | null
current_value only: the value when the app asked.
- status enum | null
Pending requests only: checked now.
- holds
- changed
- description string
-
- reason string | null
Written by the AI app: untrusted text, show it as text.
Show 11 more attributesHide 11 attributes
- status enum
- pending
- approved
- rejected
- expired
- failed
- requested_by object
- approval_url string
Dashboard page where an owner or admin approves or rejects it.
- decided_by object | null
- result object
What the approval produced: object and id only (plus api_key_id, flow_version_id, billing_source for the first three operations). Never live data.
- error string | null
failed: why the action did not run.
- api_key object | null
Approval of create_live_api_key only: the new live key with its secret, shown once to the approver.
Show child attributesHide child attributes
- object enum
- api_key
- id string
- name string
- kind enum
- secret
- publishable
- mode enum
- live
- test
- access enum
full: every resource. restricted: see permissions.
- full
- restricted
- permissions object | null
Level per resource (none, read, write). null for publishable keys.
Show child attributesHide child attributes
- account enum
- none
- read
- write
- api_keys enum
- none
- read
- write
- team enum
- none
- read
- write
- events enum
- none
- read
- write
- customers enum
- none
- read
- write
- billing enum
- none
- read
- write
- stripe_connections enum
- none
- read
- write
- logs enum
- none
- read
- write
- flows enum
- none
- read
- write
- email_domains enum
- none
- read
- write
- messages enum
- none
- read
- write
- webhooks enum
- none
- read
- write
- cancel_sessions enum
- none
- read
- write
- reviews enum
- none
- read
- write
- dashboard enum
- none
- read
- write
- insights enum
- none
- read
- write
- integrations enum
- none
- read
- write
- queries enum
- none
- read
- write
- disputes enum
- none
- read
- write
- sandbox enum
- none
- read
- write
-
- last4 string
- allowed_origins array of strings | null
Publishable keys: origins allowed to call the public endpoints (null on secret keys).
- token string | null
Secret keys: only on creation, store it now. Publishable keys: always.
-
First call made with this key (onboarding: waiting for your first event).
-
- response object | null
Approval answer only, to the approver: the operation's API response (it may hold a secret shown once: a live key's token, a webhook endpoint's signing secret). Never stored.
Schema: LiveRequest
{
"object": "live_request",
"id": "lrq_FpLTMa8X3rjugaNz",
"action": "create_live_api_key",
"title": "Create a live API key",
"summary": "Create a live secret (nc_live_…) API key named “Production server”, full access",
"params": {
"kind": "secret",
"name": "Production server",
"access": "full",
"permissions": {}
},
"precondition": null,
"reason": "Ready for production",
"status": "approved",
"requested_by": {
"type": "ai_agent",
"name": "Claude Code",
"grant_id": "ogr_TH3UBPgpw5dZYQcm"
},
"approval_url": "http://localhost:5173/live-requests/lrq_FpLTMa8X3rjugaNz?account=acc_SHWzbh3KJWUUN6ez",
"decided_by": {
"id": "usr_4NwxZDGRUAd3xyBn",
"email": "user1@example.test"
},
"decided_at": "2026-11-04T10:00:00.000Z",
"result": {
"object": "api_key",
"id": "key_wjS3tDF9X8143ppr",
"api_key_id": "key_wjS3tDF9X8143ppr"
},
"error": null,
"api_key": {
"object": "api_key",
"id": "key_wjS3tDF9X8143ppr",
"name": "Production server",
"kind": "secret",
"mode": "live",
"access": "full",
"permissions": {
"account": "write",
"api_keys": "write",
"team": "write",
"events": "write",
"customers": "write",
"billing": "write",
"stripe_connections": "write",
"logs": "write",
"flows": "write",
"email_domains": "write",
"messages": "write",
"webhooks": "write",
"cancel_sessions": "write",
"reviews": "write",
"dashboard": "write",
"insights": "write",
"integrations": "write",
"queries": "write",
"disputes": "write",
"sandbox": "write"
},
"last4": "QbM5",
"allowed_origins": null,
"token": "nc_live_EXAMPLE00000000000000000",
"first_used_at": null,
"last_used_at": null,
"revoked_at": null,
"created_at": "2026-11-04T10:00:00.000Z"
},
"response": {
"object": "api_key",
"id": "key_wjS3tDF9X8143ppr",
"name": "Production server",
"kind": "secret",
"mode": "live",
"access": "full",
"permissions": {
"account": "write",
"api_keys": "write",
"team": "write",
"events": "write",
"customers": "write",
"billing": "write",
"stripe_connections": "write",
"logs": "write",
"flows": "write",
"email_domains": "write",
"messages": "write",
"webhooks": "write",
"cancel_sessions": "write",
"reviews": "write",
"dashboard": "write",
"insights": "write",
"integrations": "write",
"queries": "write",
"disputes": "write",
"sandbox": "write"
},
"last4": "QbM5",
"allowed_origins": null,
"token": "nc_live_EXAMPLE00000000000000000",
"first_used_at": null,
"last_used_at": null,
"revoked_at": null,
"created_at": "2026-11-04T10:00:00.000Z"
},
"expires_at": "2026-11-11T10:00:00.000Z",
"created_at": "2026-11-04T10:00:00.000Z"
} Ask a human to do something in live mode (AI apps)
OAuth tokens only (configure scope, plus the scope the operation needs in test mode: sandbox for customers, usage, subscriptions and payments). AI apps never change live mode directly: they ask for one operation (action) with its params (one schema per operation, see LiveRequestCreate) and give approval_url to an owner or admin. NoChurn checks the params, looks the target up in live mode, writes its own summary and captures what must still hold at approval (precondition). Nothing runs until a human approves it in the dashboard; it then runs in live mode as that human. Asked in any mode (the NoChurn-Mode header is ignored here). The same pending request asked again is returned as is. Never possible: the team, AI app access, 2FA, NoChurn's own plan, editing or revoking existing keys, deleting the account.
- AI apps only: an OAuth access token (
ncat_…) with theconfigurescope. An API key is refused (403).
BODY PARAMETERS
One of:
-
- create_live_api_key
-
Params of create_live_api_key: Create a live API key.
Show child parametersHide child parameters
- kind enum
- secret
- publishable
- access enum
- full
- restricted
- permissions object
-
Shown to the human as the app's note (untrusted text).
-
- publish_flow_live
-
Params of publish_flow_live: Publish a flow to live mode.
Show child parametersHide child parameters
-
flw_… or a kind: prevention, recovery, cancel, winback
-
-
Shown to the human as the app's note (untrusted text).
-
- set_billing_source
-
Params of set_billing_source: Change the billing source.
Show child parametersHide child parameters
-
- stripe
- api
-
-
Shown to the human as the app's note (untrusted text).
-
- create_webhook_endpoint
-
Params of create_webhook_endpoint: Add a live webhook endpoint.
Show child parametersHide child parameters
- events enum | array of enums
-
Shown to the human as the app's note (untrusted text).
-
- delete_webhook_endpoint
-
Params of delete_webhook_endpoint: Remove a live webhook endpoint.
Show child parametersHide child parameters
-
Shown to the human as the app's note (untrusted text).
-
- test_webhook_endpoint
-
Params of test_webhook_endpoint: Send a test webhook to a live endpoint.
Show child parametersHide child parameters
- type enum
- recovery.opened
- recovery.recovered
- recovery.lost
- outcome.confirmed
- outcome.reverted
- billing.retry_requested
- billing.cancel_requested
- billing.discount_requested
- billing.pause_requested
- billing.downgrade_requested
- customer.scored
- customer.flagged
- customer.access_restricted
- customer.access_restored
- cancel_session.started
- cancel_session.offer_accepted
- cancel_session.completed
- winback.reactivated
-
Shown to the human as the app's note (untrusted text).
-
- create_attribute_definition
-
Params of create_attribute_definition: Declare a live customer attribute.
-
Shown to the human as the app's note (untrusted text).
-
- update_attribute_definition
-
Params of update_attribute_definition: Change a live customer attribute.
-
Shown to the human as the app's note (untrusted text).
-
- create_customer
-
Params of create_customer: Create a live customer.
Show child parametersHide child parameters
-
Shown to the human as the app's note (untrusted text).
-
- update_customer
-
Params of update_customer: Change a live customer.
Show child parametersHide child parameters
- attributes object
Custom attributes; null removes a key.
-
Shown to the human as the app's note (untrusted text).
-
- set_customer_attributes
-
Params of set_customer_attributes: Set attributes on a live customer.
Show child parametersHide child parameters
-
Custom attributes; null removes a key.
-
Shown to the human as the app's note (untrusted text).
-
- record_usage_event
-
Params of record_usage_event: Record a live usage event.
Show child parametersHide child parameters
-
ISO 8601
- properties object
-
Shown to the human as the app's note (untrusted text).
-
- record_usage_events
-
Params of record_usage_events: Record live usage events.
Show child parametersHide child parameters
-
Show child parametersHide child parameters
-
ISO 8601
- properties object
-
-
Shown to the human as the app's note (untrusted text).
-
- create_subscription
-
Params of create_subscription: Record a live subscription.
Show child parametersHide child parameters
-
cst_…, cus_… or your own id, or { external_id, email, name }
string
- interval enum
- day
- week
- month
- year
-
ISO 8601
- cancel_at_period_end boolean
-
ISO 8601
-
Shown to the human as the app's note (untrusted text).
-
- update_subscription
-
Params of update_subscription: Change a live subscription.
Show child parametersHide child parameters
- interval enum
- day
- week
- month
- year
-
ISO 8601
- cancel_at_period_end boolean
-
ISO 8601
-
Shown to the human as the app's note (untrusted text).
-
- record_payment
-
Params of record_payment: Record a live payment attempt.
Show child parametersHide child parameters
-
cst_…, cus_… or your own id, or { external_id, email, name }
string
-
- failed
- succeeded
-
ISO 8601
-
Shown to the human as the app's note (untrusted text).
RETURNS
-
201pending, with its approval link — the Live request object
ERRORS
-
400invalid_request unknown action -
403forbidden an API key (act in live mode directly instead)
curl https://api.nochurn.sh/v1/live_requests \
-H "Authorization: Bearer nc_test_…" \
-H "Content-Type: application/json" \
-d '{
"action": "create_live_api_key",
"params": {
"name": "Production server"
},
"reason": "Integration verified in test mode"
}'const res = await fetch("https://api.nochurn.sh/v1/live_requests", {
method: "POST",
headers: {
Authorization: "Bearer nc_test_…",
"Content-Type": "application/json",
},
body: JSON.stringify({
"action": "create_live_api_key",
"params": {
"name": "Production server"
},
"reason": "Integration verified in test mode"
}),
});
const liveRequest = await res.json();import requests
res = requests.post(
"https://api.nochurn.sh/v1/live_requests",
headers={
"Authorization": "Bearer nc_test_…",
},
json={
"action": "create_live_api_key",
"params": {
"name": "Production server"
},
"reason": "Integration verified in test mode"
},
)
live_request = res.json()require "net/http"
require "json"
uri = URI("https://api.nochurn.sh/v1/live_requests")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer nc_test_…"
req["Content-Type"] = "application/json"
req.body = {
"action" => "create_live_api_key",
"params" => {
"name" => "Production server"
},
"reason" => "Integration verified in test mode"
}.to_json
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
live_request = JSON.parse(res.body) {
"object": "live_request",
"id": "lrq_7y3fem7wpcHdUx1s",
"action": "create_live_api_key",
"title": "Create a live API key",
"summary": "Create a live secret (nc_live_…) API key named “Production server”, full access",
"params": {
"name": "Production server",
"kind": "secret",
"access": "full",
"permissions": {}
},
"precondition": null,
"reason": "Integration verified in test mode",
"status": "pending",
"requested_by": {
"type": "ai_agent",
"name": "Claude Code",
"grant_id": "ogr_A9AUMTA8qUFrqLLZ"
},
"approval_url": "http://localhost:5173/live-requests/lrq_7y3fem7wpcHdUx1s?account=acc_itN4DgVRL8A9caPs",
"decided_by": null,
"decided_at": null,
"result": {},
"error": null,
"api_key": null,
"response": null,
"expires_at": "2026-11-11T10:00:00.000Z",
"created_at": "2026-11-04T10:00:00.000Z"
} Retrieve a live request
AI apps poll it to know whether a human approved.
- Secret key (
nc_test_…ornc_live_…). Restricted keys need read access. - AI apps (OAuth):
readscope.
PATH PARAMETERS
RETURNS
-
200the request — the Live request object
curl https://api.nochurn.sh/v1/live_requests/lrq_a29dDA8tYCJq8KTP \
-H "Authorization: Bearer nc_test_…"const res = await fetch("https://api.nochurn.sh/v1/live_requests/lrq_a29dDA8tYCJq8KTP", {
headers: {
Authorization: "Bearer nc_test_…",
},
});
const liveRequest = await res.json();import requests
res = requests.get(
"https://api.nochurn.sh/v1/live_requests/lrq_a29dDA8tYCJq8KTP",
headers={
"Authorization": "Bearer nc_test_…",
},
)
live_request = res.json()require "net/http"
require "json"
uri = URI("https://api.nochurn.sh/v1/live_requests/lrq_a29dDA8tYCJq8KTP")
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer nc_test_…"
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
live_request = JSON.parse(res.body) {
"object": "live_request",
"id": "lrq_a29dDA8tYCJq8KTP",
"action": "publish_flow_live",
"title": "Publish a flow to live mode",
"summary": "Publish the current draft of Cancel flow to live mode (customers in live mode get it)",
"params": {
"flow_id": "flw_K13CEko818VgKSAc",
"flow_kind": "cancel",
"flow_name": "Cancel flow"
},
"precondition": {
"kind": "draft_digest",
"object": "flow",
"id": "flw_K13CEko818VgKSAc",
"expected": null,
"status": "holds",
"description": "The flow draft must be the one the app asked to publish."
},
"reason": "Ready for production",
"status": "pending",
"requested_by": {
"type": "ai_agent",
"name": "Claude Code",
"grant_id": "ogr_CxuaJ9mcH429DzBw"
},
"approval_url": "http://localhost:5173/live-requests/lrq_a29dDA8tYCJq8KTP?account=acc_ptg1cVcxU237ywmi",
"decided_by": null,
"decided_at": null,
"result": {},
"error": null,
"api_key": null,
"response": null,
"expires_at": "2026-11-11T10:00:00.000Z",
"created_at": "2026-11-04T10:00:00.000Z"
} List live requests
An AI app sees its own requests; the dashboard sees every request of the account.
- Secret key (
nc_test_…ornc_live_…). Restricted keys need read access. - AI apps (OAuth):
readscope.
QUERY PARAMETERS
- status enum
- pending
- approved
- rejected
- failed
- limit integer
- starting_after string
RETURNS
-
200the requests — a list of Live request object (LiveRequestList)
curl https://api.nochurn.sh/v1/live_requests \
-H "Authorization: Bearer nc_test_…"const res = await fetch("https://api.nochurn.sh/v1/live_requests", {
headers: {
Authorization: "Bearer nc_test_…",
},
});
const page = await res.json();import requests
res = requests.get(
"https://api.nochurn.sh/v1/live_requests",
headers={
"Authorization": "Bearer nc_test_…",
},
)
page = res.json()require "net/http"
require "json"
uri = URI("https://api.nochurn.sh/v1/live_requests")
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer nc_test_…"
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
page = JSON.parse(res.body) {
"object": "list",
"data": [
{
"object": "live_request",
"id": "lrq_x1S3mBZzebRmeJkX",
"action": "set_billing_source",
"title": "Change the billing source",
"summary": "Set the billing source to your own billing (API) (test and live modes)",
"params": {
"billing_source": "api"
},
"precondition": {
"kind": "current_value",
"object": "billing_source",
"id": null,
"expected": "stripe",
"status": "holds",
"description": "The billing source must still be stripe."
},
"reason": "Ready for production",
"status": "pending",
"requested_by": {
"type": "ai_agent",
"name": "Claude Code",
"grant_id": "ogr_9Gp8DnTNkPEsTAAU"
},
"approval_url": "http://localhost:5173/live-requests/lrq_x1S3mBZzebRmeJkX?account=acc_n31kFwAhaVTBRdpZ",
"decided_by": null,
"decided_at": null,
"result": {},
"error": null,
"api_key": null,
"response": null,
"expires_at": "2026-11-11T10:00:00.000Z",
"created_at": "2026-11-04T10:00:00.000Z"
}
],
"has_more": false,
"next_cursor": null
} Approve a live request (dashboard, owner or admin)
Runs the operation now, as the approver, in live mode (its Events carry via: the AI app). Its API answer is returned once, to the approver only, in response (and api_key for create_live_api_key): a live key's token, a webhook endpoint's signing secret. Fails (status failed, error) without changing anything if the precondition no longer holds or the operation is refused.
- Secret key (
nc_test_…ornc_live_…). Restricted keys need write access. - AI apps (OAuth): not available.
PATH PARAMETERS
HEADER PARAMETERS
- X-Requested-With string
RETURNS
-
200approved: the live key, shown once — the Live request object
ERRORS
curl https://api.nochurn.sh/v1/live_requests/lrq_x1S3mBZzebRmeJkX/approve \
-X POST \
-H "Authorization: Bearer nc_test_…"const res = await fetch("https://api.nochurn.sh/v1/live_requests/lrq_x1S3mBZzebRmeJkX/approve", {
method: "POST",
headers: {
Authorization: "Bearer nc_test_…",
},
});
const liveRequest = await res.json();import requests
res = requests.post(
"https://api.nochurn.sh/v1/live_requests/lrq_x1S3mBZzebRmeJkX/approve",
headers={
"Authorization": "Bearer nc_test_…",
},
)
live_request = res.json()require "net/http"
require "json"
uri = URI("https://api.nochurn.sh/v1/live_requests/lrq_x1S3mBZzebRmeJkX/approve")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer nc_test_…"
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
live_request = JSON.parse(res.body) {
"object": "live_request",
"id": "lrq_FpLTMa8X3rjugaNz",
"action": "create_live_api_key",
"title": "Create a live API key",
"summary": "Create a live secret (nc_live_…) API key named “Production server”, full access",
"params": {
"kind": "secret",
"name": "Production server",
"access": "full",
"permissions": {}
},
"precondition": null,
"reason": "Ready for production",
"status": "approved",
"requested_by": {
"type": "ai_agent",
"name": "Claude Code",
"grant_id": "ogr_TH3UBPgpw5dZYQcm"
},
"approval_url": "http://localhost:5173/live-requests/lrq_FpLTMa8X3rjugaNz?account=acc_SHWzbh3KJWUUN6ez",
"decided_by": {
"id": "usr_4NwxZDGRUAd3xyBn",
"email": "user1@example.test"
},
"decided_at": "2026-11-04T10:00:00.000Z",
"result": {
"object": "api_key",
"id": "key_wjS3tDF9X8143ppr",
"api_key_id": "key_wjS3tDF9X8143ppr"
},
"error": null,
"api_key": {
"object": "api_key",
"id": "key_wjS3tDF9X8143ppr",
"name": "Production server",
"kind": "secret",
"mode": "live",
"access": "full",
"permissions": {
"account": "write",
"api_keys": "write",
"team": "write",
"events": "write",
"customers": "write",
"billing": "write",
"stripe_connections": "write",
"logs": "write",
"flows": "write",
"email_domains": "write",
"messages": "write",
"webhooks": "write",
"cancel_sessions": "write",
"reviews": "write",
"dashboard": "write",
"insights": "write",
"integrations": "write",
"queries": "write",
"disputes": "write",
"sandbox": "write"
},
"last4": "QbM5",
"allowed_origins": null,
"token": "nc_live_EXAMPLE00000000000000000",
"first_used_at": null,
"last_used_at": null,
"revoked_at": null,
"created_at": "2026-11-04T10:00:00.000Z"
},
"response": {
"object": "api_key",
"id": "key_wjS3tDF9X8143ppr",
"name": "Production server",
"kind": "secret",
"mode": "live",
"access": "full",
"permissions": {
"account": "write",
"api_keys": "write",
"team": "write",
"events": "write",
"customers": "write",
"billing": "write",
"stripe_connections": "write",
"logs": "write",
"flows": "write",
"email_domains": "write",
"messages": "write",
"webhooks": "write",
"cancel_sessions": "write",
"reviews": "write",
"dashboard": "write",
"insights": "write",
"integrations": "write",
"queries": "write",
"disputes": "write",
"sandbox": "write"
},
"last4": "QbM5",
"allowed_origins": null,
"token": "nc_live_EXAMPLE00000000000000000",
"first_used_at": null,
"last_used_at": null,
"revoked_at": null,
"created_at": "2026-11-04T10:00:00.000Z"
},
"expires_at": "2026-11-11T10:00:00.000Z",
"created_at": "2026-11-04T10:00:00.000Z"
} Reject a live request (dashboard, owner or admin)
- Secret key (
nc_test_…ornc_live_…). Restricted keys need write access. - AI apps (OAuth): not available.
PATH PARAMETERS
HEADER PARAMETERS
- X-Requested-With string
RETURNS
-
200rejected: nothing runs — the Live request object
curl https://api.nochurn.sh/v1/live_requests/lrq_x1S3mBZzebRmeJkX/reject \
-X POST \
-H "Authorization: Bearer nc_test_…"const res = await fetch("https://api.nochurn.sh/v1/live_requests/lrq_x1S3mBZzebRmeJkX/reject", {
method: "POST",
headers: {
Authorization: "Bearer nc_test_…",
},
});
const liveRequest = await res.json();import requests
res = requests.post(
"https://api.nochurn.sh/v1/live_requests/lrq_x1S3mBZzebRmeJkX/reject",
headers={
"Authorization": "Bearer nc_test_…",
},
)
live_request = res.json()require "net/http"
require "json"
uri = URI("https://api.nochurn.sh/v1/live_requests/lrq_x1S3mBZzebRmeJkX/reject")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer nc_test_…"
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
live_request = JSON.parse(res.body) {
"object": "live_request",
"id": "lrq_qjEB7xxu8ZAoUT4y",
"action": "publish_flow_live",
"title": "Publish a flow to live mode",
"summary": "Publish the current draft of Cancel flow to live mode (customers in live mode get it)",
"params": {
"flow_id": "flw_pr839pHikX4wkNpw",
"flow_kind": "cancel",
"flow_name": "Cancel flow"
},
"precondition": {
"kind": "draft_digest",
"object": "flow",
"id": "flw_pr839pHikX4wkNpw",
"expected": null,
"status": null,
"description": "The flow draft must be the one the app asked to publish."
},
"reason": "Ready for production",
"status": "rejected",
"requested_by": {
"type": "ai_agent",
"name": "Claude Code",
"grant_id": "ogr_cpYehACptMsaMRM6"
},
"approval_url": "http://localhost:5173/live-requests/lrq_qjEB7xxu8ZAoUT4y?account=acc_E8fCBPuUNqCUVdoq",
"decided_by": {
"id": "usr_GPLLsThB1vdVkV4j",
"email": "user1@example.test"
},
"decided_at": "2026-11-04T10:00:00.000Z",
"result": {},
"error": null,
"api_key": null,
"response": null,
"expires_at": "2026-11-11T10:00:00.000Z",
"created_at": "2026-11-04T10:00:00.000Z"
} List the AI apps connected to the account
Settings › Connected AI apps: MCP clients authorized through OAuth, with their scopes and last use.
- Secret key (
nc_test_…ornc_live_…). Restricted keys need read access. - AI apps (OAuth): not available.
QUERY PARAMETERS
- limit integer
- starting_after string
RETURNS
-
200the connected apps — a list of OauthGrant (OauthGrantList)
curl https://api.nochurn.sh/v1/oauth/grants \
-H "Authorization: Bearer nc_test_…"const res = await fetch("https://api.nochurn.sh/v1/oauth/grants", {
headers: {
Authorization: "Bearer nc_test_…",
},
});
const page = await res.json();import requests
res = requests.get(
"https://api.nochurn.sh/v1/oauth/grants",
headers={
"Authorization": "Bearer nc_test_…",
},
)
page = res.json()require "net/http"
require "json"
uri = URI("https://api.nochurn.sh/v1/oauth/grants")
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer nc_test_…"
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
page = JSON.parse(res.body) {
"object": "list",
"data": [
{
"object": "oauth_grant",
"id": "ogr_ga9szsdYbQPGuhay",
"client": {
"id": "mcpc_8NeN1E6YEpZvJ7vh",
"name": "Cursor",
"verified": false,
"verified_name": null,
"client_uri": null
},
"user": {
"id": "usr_DgKVbPfoFB5vggGt",
"email": "user1@example.test",
"name": "User"
},
"scopes": ["read", "configure", "sandbox"],
"live_read": false,
"live_write": "approval_required",
"last_used_at": null,
"revoked_at": null,
"created_at": "2026-11-04T10:00:00.000Z"
}
],
"has_more": false,
"next_cursor": null
} Allow or stop an AI app's live reads
live_read: whether the app may read live data (NoChurn-Mode: live, reads only). Owner or admin, or the member who connected it. Turning it on needs a person in a dashboard session (never an API key or an OAuth token); turning it off works from any of them. Every change writes an Event.
- Secret key (
nc_test_…ornc_live_…). Restricted keys need write access. - AI apps (OAuth): not available.
PATH PARAMETERS
HEADER PARAMETERS
- X-Requested-With string
BODY PARAMETERS
RETURNS
-
200live reads allowed — a OauthGrant
ERRORS
-
403forbidden turning live reads on with an API key
curl https://api.nochurn.sh/v1/oauth/grants/ogr_s9Y7BkukioSRcJSa \
-X PATCH \
-H "Authorization: Bearer nc_test_…" \
-H "Content-Type: application/json" \
-d '{
"live_read": true
}'const res = await fetch("https://api.nochurn.sh/v1/oauth/grants/ogr_s9Y7BkukioSRcJSa", {
method: "PATCH",
headers: {
Authorization: "Bearer nc_test_…",
"Content-Type": "application/json",
},
body: JSON.stringify({
"live_read": true
}),
});
const oauthGrant = await res.json();import requests
res = requests.patch(
"https://api.nochurn.sh/v1/oauth/grants/ogr_s9Y7BkukioSRcJSa",
headers={
"Authorization": "Bearer nc_test_…",
},
json={
"live_read": True
},
)
oauth_grant = res.json()require "net/http"
require "json"
uri = URI("https://api.nochurn.sh/v1/oauth/grants/ogr_s9Y7BkukioSRcJSa")
req = Net::HTTP::Patch.new(uri)
req["Authorization"] = "Bearer nc_test_…"
req["Content-Type"] = "application/json"
req.body = {
"live_read" => true
}.to_json
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
oauth_grant = JSON.parse(res.body) {
"object": "oauth_grant",
"id": "ogr_s9Y7BkukioSRcJSa",
"client": {
"id": "mcpc_JGFoYmVEQ9hSQq9T",
"name": "Cursor",
"verified": false,
"verified_name": null,
"client_uri": null
},
"user": {
"id": "usr_Znx8PDYTc71YL9kP",
"email": "user2@example.test",
"name": "User"
},
"scopes": ["read", "configure", "sandbox"],
"live_read": true,
"live_write": "approval_required",
"last_used_at": null,
"revoked_at": null,
"created_at": "2026-11-04T10:00:00.000Z"
} Revoke an AI app's access
Every token of the app stops working at once, and its pending live requests are cancelled (status expired, with the reason in error and a live_request.expired Event). Owner or admin, or the member who connected it.
- Secret key (
nc_test_…ornc_live_…). Restricted keys need write access. - AI apps (OAuth): not available.
PATH PARAMETERS
HEADER PARAMETERS
- X-Requested-With string
RETURNS
-
200revoked — a OauthGrant
ERRORS
curl https://api.nochurn.sh/v1/oauth/grants/ogr_aAN5xuUxRriy3UW2 \
-X DELETE \
-H "Authorization: Bearer nc_test_…"const res = await fetch("https://api.nochurn.sh/v1/oauth/grants/ogr_aAN5xuUxRriy3UW2", {
method: "DELETE",
headers: {
Authorization: "Bearer nc_test_…",
},
});
const oauthGrant = await res.json();import requests
res = requests.delete(
"https://api.nochurn.sh/v1/oauth/grants/ogr_aAN5xuUxRriy3UW2",
headers={
"Authorization": "Bearer nc_test_…",
},
)
oauth_grant = res.json()require "net/http"
require "json"
uri = URI("https://api.nochurn.sh/v1/oauth/grants/ogr_aAN5xuUxRriy3UW2")
req = Net::HTTP::Delete.new(uri)
req["Authorization"] = "Bearer nc_test_…"
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
oauth_grant = JSON.parse(res.body) {
"object": "oauth_grant",
"id": "ogr_aAN5xuUxRriy3UW2",
"client": {
"id": "mcpc_bvMfrNFty8PB8882",
"name": "Cursor",
"verified": false,
"verified_name": null,
"client_uri": null
},
"user": {
"id": "usr_8FSUTy7n5pyHtBp9",
"email": "user2@example.test",
"name": "User"
},
"scopes": ["read", "configure", "sandbox"],
"live_read": false,
"live_write": "approval_required",
"last_used_at": null,
"revoked_at": "2026-11-04T10:00:00.000Z",
"created_at": "2026-11-04T10:00:00.000Z"
}