CORE RESOURCES
Billing
The Payment object
Subscriptions and payments sent by your own billing, when you don't use a connected billing tool.
ATTRIBUTES
- object enum
- payment
- id string
- livemode boolean
- customer string
- subscription string | null
- invoice string | null
- external_id string | null
- stripe_charge_id string | null
Show 7 more attributesHide 7 attributes
- status enum
- succeeded
- failed
- pending
- amount_cents integer
- currency string
- decline_code string | null
- failure_code string | null
Schema: Payment
THE PAYMENT OBJECT
{
"object": "payment",
"id": "npay_TBSmR2L4qghkw8q1",
"livemode": false,
"customer": "cst_xWuFumaBvkQ9HWYw",
"subscription": "nsub_Zv2tbZpFo5YxCaPy",
"invoice": "ninv_JKntY71SKsXEe55e",
"external_id": "pay_9",
"stripe_charge_id": null,
"status": "failed",
"amount_cents": 4900,
"currency": "eur",
"decline_code": "do_not_honor",
"failure_code": null,
"occurred_at": "2026-11-04T10:00:00Z",
"created_at": "2026-11-04T10:00:00Z"
} Send a payment (billing by API)
status failed opens recovery: NoChurn plans retries and requests each one with billing.retry_requested. status succeeded pays the invoice and ends recovery. Idempotent on your external_id.
- Secret key (
nc_test_…ornc_live_…). Restricted keys need write access. - AI apps (OAuth):
sandboxscope, test mode only.
BODY PARAMETERS
- subscription string
- invoice string
-
- failed
- succeeded
- decline_code string
- invoice_url string
Where your customer pays this invoice.
RETURNS
-
201a failed payment opens recovery — the Payment object
POST/v1/payments
curl https://api.nochurn.sh/v1/payments \
-H "Authorization: Bearer nc_test_…" \
-H "Content-Type: application/json" \
-d '{
"external_id": "pay_9",
"customer": "user_42",
"subscription": "sub_42",
"invoice": "inv_1",
"amount": 4900,
"currency": "eur",
"status": "failed",
"decline_code": "do_not_honor"
}'const res = await fetch("https://api.nochurn.sh/v1/payments", {
method: "POST",
headers: {
Authorization: "Bearer nc_test_…",
"Content-Type": "application/json",
},
body: JSON.stringify({
"external_id": "pay_9",
"customer": "user_42",
"subscription": "sub_42",
"invoice": "inv_1",
"amount": 4900,
"currency": "eur",
"status": "failed",
"decline_code": "do_not_honor"
}),
});
const payment = await res.json();import requests
res = requests.post(
"https://api.nochurn.sh/v1/payments",
headers={
"Authorization": "Bearer nc_test_…",
},
json={
"external_id": "pay_9",
"customer": "user_42",
"subscription": "sub_42",
"invoice": "inv_1",
"amount": 4900,
"currency": "eur",
"status": "failed",
"decline_code": "do_not_honor"
},
)
payment = res.json()require "net/http"
require "json"
uri = URI("https://api.nochurn.sh/v1/payments")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer nc_test_…"
req["Content-Type"] = "application/json"
req.body = {
"external_id" => "pay_9",
"customer" => "user_42",
"subscription" => "sub_42",
"invoice" => "inv_1",
"amount" => 4900,
"currency" => "eur",
"status" => "failed",
"decline_code" => "do_not_honor"
}.to_json
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
payment = JSON.parse(res.body) RESPONSE 201
{
"object": "payment",
"id": "npay_TBSmR2L4qghkw8q1",
"livemode": false,
"customer": "cst_xWuFumaBvkQ9HWYw",
"subscription": "nsub_Zv2tbZpFo5YxCaPy",
"invoice": "ninv_JKntY71SKsXEe55e",
"external_id": "pay_9",
"stripe_charge_id": null,
"status": "failed",
"amount_cents": 4900,
"currency": "eur",
"decline_code": "do_not_honor",
"failure_code": null,
"occurred_at": "2026-11-04T10:00:00Z",
"created_at": "2026-11-04T10:00:00Z"
} Payments (Stripe and API)
- Secret key (
nc_test_…ornc_live_…). Restricted keys need read access. - AI apps (OAuth):
readscope.
QUERY PARAMETERS
RETURNS
-
200the list — a list of Payment object (PaymentList)
GET/v1/payments
curl https://api.nochurn.sh/v1/payments \
-H "Authorization: Bearer nc_test_…"const res = await fetch("https://api.nochurn.sh/v1/payments", {
headers: {
Authorization: "Bearer nc_test_…",
},
});
const page = await res.json();import requests
res = requests.get(
"https://api.nochurn.sh/v1/payments",
headers={
"Authorization": "Bearer nc_test_…",
},
)
page = res.json()require "net/http"
require "json"
uri = URI("https://api.nochurn.sh/v1/payments")
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) RESPONSE 200
{
"object": "list",
"data": [],
"has_more": false,
"next_cursor": null
} Send a subscription (billing by API)
Idempotent on your external_id: posting it again updates the subscription.
- Secret key (
nc_test_…ornc_live_…). Restricted keys need write access. - AI apps (OAuth):
sandboxscope, test mode only.
BODY PARAMETERS
- plan string
-
- day
- week
- month
- year
- status enum
- incomplete
- incomplete_expired
- trialing
- active
- past_due
- canceled
- unpaid
- paused
RETURNS
-
201created with its customer — a Subscription
ERRORS
-
409conflict the account's billing comes from Stripe
POST/v1/subscriptions
curl https://api.nochurn.sh/v1/subscriptions \
-H "Authorization: Bearer nc_test_…" \
-H "Content-Type: application/json" \
-d '{
"external_id": "sub_42",
"customer": {
"external_id": "user_42",
"email": "lena@globex.io"
},
"plan": "Pro",
"amount": 4900,
"currency": "eur",
"interval": "month"
}'const res = await fetch("https://api.nochurn.sh/v1/subscriptions", {
method: "POST",
headers: {
Authorization: "Bearer nc_test_…",
"Content-Type": "application/json",
},
body: JSON.stringify({
"external_id": "sub_42",
"customer": {
"external_id": "user_42",
"email": "lena@globex.io"
},
"plan": "Pro",
"amount": 4900,
"currency": "eur",
"interval": "month"
}),
});
const subscription = await res.json();import requests
res = requests.post(
"https://api.nochurn.sh/v1/subscriptions",
headers={
"Authorization": "Bearer nc_test_…",
},
json={
"external_id": "sub_42",
"customer": {
"external_id": "user_42",
"email": "lena@globex.io"
},
"plan": "Pro",
"amount": 4900,
"currency": "eur",
"interval": "month"
},
)
subscription = res.json()require "net/http"
require "json"
uri = URI("https://api.nochurn.sh/v1/subscriptions")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer nc_test_…"
req["Content-Type"] = "application/json"
req.body = {
"external_id" => "sub_42",
"customer" => {
"external_id" => "user_42",
"email" => "lena@globex.io"
},
"plan" => "Pro",
"amount" => 4900,
"currency" => "eur",
"interval" => "month"
}.to_json
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
subscription = JSON.parse(res.body) RESPONSE 201
{
"object": "subscription",
"id": "nsub_hd7rffvqSB3fF8LR",
"customer": "cst_XBTW4dWsGxyLYcgT",
"stripe_subscription_id": null,
"external_id": "sub_42",
"livemode": false,
"status": "active",
"plan": "Pro",
"amount_cents": 4900,
"currency": "eur",
"interval": "month",
"interval_count": 1,
"mrr_cents": 4900,
"current_period_end": null,
"cancel_at_period_end": false,
"canceled_at": null,
"paused_until": null,
"trial_end": null,
"created_at": "2026-11-04T10:00:00.000Z"
} Change a subscription sent by API (subscription.cancelled)
- Secret key (
nc_test_…ornc_live_…). Restricted keys need write access. - AI apps (OAuth):
sandboxscope, test mode only.
PATH PARAMETERS
-
nsub_… or your external_id
BODY PARAMETERS
- status enum
- incomplete
- incomplete_expired
- trialing
- active
- past_due
- canceled
- unpaid
- paused
- plan string
- amount integer
- cancel_at_period_end boolean
RETURNS
-
200canceled — a Subscription
PATCH/v1/subscriptions/{id}
curl https://api.nochurn.sh/v1/subscriptions/nsub_Wf9KF5qNWWFiJ6N6 \
-X PATCH \
-H "Authorization: Bearer nc_test_…" \
-H "Content-Type: application/json" \
-d '{
"status": "canceled"
}'const res = await fetch("https://api.nochurn.sh/v1/subscriptions/nsub_Wf9KF5qNWWFiJ6N6", {
method: "PATCH",
headers: {
Authorization: "Bearer nc_test_…",
"Content-Type": "application/json",
},
body: JSON.stringify({
"status": "canceled"
}),
});
const subscription = await res.json();import requests
res = requests.patch(
"https://api.nochurn.sh/v1/subscriptions/nsub_Wf9KF5qNWWFiJ6N6",
headers={
"Authorization": "Bearer nc_test_…",
},
json={
"status": "canceled"
},
)
subscription = res.json()require "net/http"
require "json"
uri = URI("https://api.nochurn.sh/v1/subscriptions/nsub_Wf9KF5qNWWFiJ6N6")
req = Net::HTTP::Patch.new(uri)
req["Authorization"] = "Bearer nc_test_…"
req["Content-Type"] = "application/json"
req.body = {
"status" => "canceled"
}.to_json
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
subscription = JSON.parse(res.body) RESPONSE 200
{
"object": "subscription",
"id": "nsub_Wf9KF5qNWWFiJ6N6",
"customer": "cst_5SJ8JmubQCqFJzQw",
"stripe_subscription_id": null,
"external_id": "sub_42",
"livemode": false,
"status": "canceled",
"plan": null,
"amount_cents": 4900,
"currency": "eur",
"interval": "month",
"interval_count": 1,
"mrr_cents": 0,
"current_period_end": null,
"cancel_at_period_end": false,
"canceled_at": "2026-11-04T10:00:00.000Z",
"paused_until": null,
"trial_end": null,
"created_at": "2026-11-04T10:00:00.000Z"
}