Create Customer Portal Session
curl --request POST \
--url https://api.devkit4ai.com/api/v1/payments/stripe/customer-portal \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"return_url": "<string>"
}
'import requests
url = "https://api.devkit4ai.com/api/v1/payments/stripe/customer-portal"
payload = { "return_url": "<string>" }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({return_url: '<string>'})
};
fetch('https://api.devkit4ai.com/api/v1/payments/stripe/customer-portal', 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.devkit4ai.com/api/v1/payments/stripe/customer-portal",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'return_url' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.devkit4ai.com/api/v1/payments/stripe/customer-portal"
payload := strings.NewReader("{\n \"return_url\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
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.devkit4ai.com/api/v1/payments/stripe/customer-portal")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"return_url\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.devkit4ai.com/api/v1/payments/stripe/customer-portal")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"return_url\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"portal_url": "<string>"
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}Stripe Subscriptions
Create Customer Portal Session
Create a Stripe Customer Portal session for users to manage billing
POST
/
api
/
v1
/
payments
/
stripe
/
customer-portal
Create Customer Portal Session
curl --request POST \
--url https://api.devkit4ai.com/api/v1/payments/stripe/customer-portal \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"return_url": "<string>"
}
'import requests
url = "https://api.devkit4ai.com/api/v1/payments/stripe/customer-portal"
payload = { "return_url": "<string>" }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({return_url: '<string>'})
};
fetch('https://api.devkit4ai.com/api/v1/payments/stripe/customer-portal', 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.devkit4ai.com/api/v1/payments/stripe/customer-portal",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'return_url' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.devkit4ai.com/api/v1/payments/stripe/customer-portal"
payload := strings.NewReader("{\n \"return_url\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
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.devkit4ai.com/api/v1/payments/stripe/customer-portal")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"return_url\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.devkit4ai.com/api/v1/payments/stripe/customer-portal")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"return_url\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"portal_url": "<string>"
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}Create a Stripe Customer Portal session that lets users manage their subscriptions, payment methods, and billing details directly in Stripe’s hosted interface.
Authentication
This endpoint requires end user authentication via HTTP Bearer Token with project scope.
Query Parameters
boolean
default:"true"
Use test mode credentials. Set to
false for production.Request Body
string
required
URL to redirect user after they exit the portal
Response
string
URL to redirect user to the Stripe Customer Portal
Example Request
curl -X POST "https://api.devkit4ai.com/api/v1/payments/stripe/customer-portal?test_mode=true" \
-H "Authorization: Bearer {end_user_jwt}" \
-H "Content-Type: application/json" \
-d '{
"return_url": "https://myapp.com/account/billing"
}'
Example Response
{
"portal_url": "https://billing.stripe.com/p/session/test_YWNjdF8xQUJDMTIzZG"
}
Portal Flow
Portal Capabilities
The Customer Portal allows users to:| Capability | Description |
|---|---|
| View Invoices | See and download past invoices |
| Update Payment Method | Add or change credit/debit cards |
| Cancel Subscription | End their subscription |
| Change Plan | Upgrade or downgrade (if configured) |
| Update Billing Info | Change billing email and address |
Configure portal features in Stripe Dashboard > Settings > Customer Portal.
Integration Example
// Manage billing button component
function ManageBillingButton() {
const [loading, setLoading] = useState(false);
const handleManageBilling = async () => {
setLoading(true);
try {
const response = await fetch('/api/customer-portal', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
return_url: window.location.href
})
});
const { portal_url } = await response.json();
window.location.href = portal_url;
} catch (error) {
console.error('Failed to open portal:', error);
} finally {
setLoading(false);
}
};
return (
<button onClick={handleManageBilling} disabled={loading}>
{loading ? 'Loading...' : 'Manage Billing'}
</button>
);
}
Portal Configuration
Configure allowed actions in Stripe Dashboard: (((REPLACE_THIS_WITH_IMAGE: stripe-customer-portal-settings.png: Stripe Dashboard Customer Portal configuration page showing subscription and invoice settings)))Prerequisites
The user must have an existing Stripe Customer ID from a previous checkout. If the user has never subscribed, this endpoint will return an error.
Error Responses
| Status | Description |
|---|---|
401 | Unauthorized - Invalid or missing authentication |
404 | No Stripe customer found for user |
404 | Project not found or Stripe not configured |
422 | Validation error - Invalid return_url |
Related Pages
Get My Subscription
Check subscription status
Cancel Subscription
Cancel programmatically
Update Subscription
Change plans via API
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Query Parameters
Use test mode
Body
application/json
Request to create a customer portal session.
Minimum string length:
1Response
Successful Response
Customer portal session response.

