DEVELOPERS
Logs
The Log entry object
The unified log: API requests, webhooks and decisions.
ATTRIBUTES
- object enum
- log_entry
- id string
- livemode boolean
-
Millisecond precision.
- source enum
stripe (webhooks), api (your calls with an API key), nochurn (decisions), widget, webhook (outgoing), a billing tool (chargebee, zuora…: its webhooks and what NoChurn reads from it), a support tool (intercom, crisp, zendesk, hubspot, helpscout, gorgias).
- stripe
- api
- nochurn
- widget
- webhook
- chargebee
- recurly
- maxio
- zuora
- paddle
- lemon_squeezy
- polar
- braintree
- mollie
- gocardless
- razorpay
- app_store
- google_play
- custom
- intercom
- crisp
- zendesk
- hubspot
- helpscout
- gorgias
- type string
- customer object | null
The customer this line is about (open it with /v1/customers/{id}).
- summary string | null
Show 5 more attributesHide 5 attributes
- status string
HTTP status ("200", "500") or ok, received, ignored, failed.
- error boolean
- why string | null
Why this happened (the reason of the NoChurn decision).
- ref object | null
- request_id string | null
Schema: LogEntry
{
"object": "log_entry",
"id": "log_FtFYHxFSjx7e96PG",
"livemode": false,
"occurred_at": "2026-11-04T09:59:00.000Z",
"source": "api",
"type": "POST /v1/customers",
"customer": null,
"summary": null,
"status": "500",
"error": true,
"why": null,
"ref": null,
"request_id": null
} Retrieve a line with its payload
- Secret key (
nc_test_…ornc_live_…). Restricted keys need read access. - AI apps (OAuth):
readscope.
PATH PARAMETERS
RETURNS
-
200the line, payload filtered — a LogEntryDetail
ERRORS
-
404not_found line of another account
curl https://api.nochurn.sh/v1/logs/log_6NzztFYECRW8iXtw \
-H "Authorization: Bearer nc_test_…"const res = await fetch("https://api.nochurn.sh/v1/logs/log_6NzztFYECRW8iXtw", {
headers: {
Authorization: "Bearer nc_test_…",
},
});
const logEntry = await res.json();import requests
res = requests.get(
"https://api.nochurn.sh/v1/logs/log_6NzztFYECRW8iXtw",
headers={
"Authorization": "Bearer nc_test_…",
},
)
log_entry = res.json()require "net/http"
require "json"
uri = URI("https://api.nochurn.sh/v1/logs/log_6NzztFYECRW8iXtw")
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) }
log_entry = JSON.parse(res.body) {
"object": "log_entry",
"id": "log_6NzztFYECRW8iXtw",
"livemode": false,
"occurred_at": "2026-11-04T10:00:00.000Z",
"source": "nochurn",
"type": "x.y",
"customer": null,
"summary": null,
"status": "ok",
"error": false,
"why": null,
"ref": null,
"request_id": null,
"payload": {
"id": "in_1",
"client_secret": "EXAMPLE000"
}
} List the unified log, newest first
Stripe webhooks, your API calls, NoChurn decisions (and later the widget, outgoing webhooks and support tools), kept 90 days. Live view: poll with after=<poll_cursor> every few seconds.
- Secret key (
nc_test_…ornc_live_…). Restricted keys need read access. - AI apps (OAuth):
readscope.
QUERY PARAMETERS
- source string
Comma-separated: stripe, api, nochurn, widget, webhook, chargebee, recurly, maxio, zuora, paddle, lemon_squeezy, polar, braintree, mollie, gocardless, razorpay, app_store, google_play, custom, intercom, crisp, zendesk, hubspot, helpscout, gorgias; billing stands for every billing tool (stripe, chargebee, recurly, maxio, zuora, paddle, lemon_squeezy, polar, braintree, mollie, gocardless, razorpay, app_store, google_play, custom).
- errors boolean
Errors only.
- q string
A customer (cst_, cus_, your id, email), an id (log_, nevt_, iwh_) or text.
- customer string
cst_…, cus_… or your id.
-
Default: 24 hours before until. The window is 31 days at most.
- starting_after string
Older lines.
- after string
Only newer lines (polling).
RETURNS
-
200live polling: nothing new keeps the cursor — a list of Log entry object (LogEntryPage)
ERRORS
-
400invalid_request unknown source -
403forbidden restricted key without logs access
curl "https://api.nochurn.sh/v1/logs?source=billing,api" \
-H "Authorization: Bearer nc_test_…"const res = await fetch("https://api.nochurn.sh/v1/logs?source=billing,api", {
headers: {
Authorization: "Bearer nc_test_…",
},
});
const page = await res.json();import requests
res = requests.get(
"https://api.nochurn.sh/v1/logs?source=billing,api",
headers={
"Authorization": "Bearer nc_test_…",
},
)
page = res.json()require "net/http"
require "json"
uri = URI("https://api.nochurn.sh/v1/logs?source=billing,api")
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": "log_entry",
"id": "log_FtFYHxFSjx7e96PG",
"livemode": false,
"occurred_at": "2026-11-04T09:59:00.000Z",
"source": "api",
"type": "POST /v1/customers",
"customer": null,
"summary": null,
"status": "500",
"error": true,
"why": null,
"ref": null,
"request_id": null
},
{
"object": "log_entry",
"id": "log_6DtqCEhQ718CVQtU",
"livemode": false,
"occurred_at": "2026-11-04T09:58:00.000Z",
"source": "stripe",
"type": "invoice.payment_failed",
"customer": {
"id": "cst_TbLNas4T3Y6wWvgN",
"name": null,
"email": "customer1@acme-corp.dev"
},
"summary": "$49.00 · insufficient_funds",
"status": "received",
"error": false,
"why": null,
"ref": null,
"request_id": null
}
],
"has_more": false,
"next_cursor": null,
"poll_cursor": "log_FtFYHxFSjx7e96PG",
"retention_days": 90
} Count of today's lines and of the errors of a window
today_count: today in the account's time zone, all lines. errors_count: the error lines of the window and filters passed (same params as GET /v1/logs, 24 hours by default).
- Secret key (
nc_test_…ornc_live_…). Restricted keys need read access. - AI apps (OAuth):
readscope.
QUERY PARAMETERS
- source string
Comma-separated sources, or billing (every billing tool), as GET /v1/logs.
- errors boolean
Accepted for symmetry with GET /v1/logs: errors_count only counts errors anyway.
- q string
- customer string
-
Default: 24 hours before until. The window is 31 days at most.
RETURNS
-
200errors of one source over 7 days — a LogStats
ERRORS
-
400invalid_request unknown source
curl https://api.nochurn.sh/v1/logs/stats \
-H "Authorization: Bearer nc_test_…"const res = await fetch("https://api.nochurn.sh/v1/logs/stats", {
headers: {
Authorization: "Bearer nc_test_…",
},
});
const logStats = await res.json();import requests
res = requests.get(
"https://api.nochurn.sh/v1/logs/stats",
headers={
"Authorization": "Bearer nc_test_…",
},
)
log_stats = res.json()require "net/http"
require "json"
uri = URI("https://api.nochurn.sh/v1/logs/stats")
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) }
log_stats = JSON.parse(res.body) {
"object": "log_stats",
"livemode": false,
"timezone": "Europe/Paris",
"today_count": 4,
"errors_count": 3,
"retention_days": 90
}