curl --request POST \
--url https://api.example.com/api/billing/invoices/{invoice_ref}/payimport requests
url = "https://api.example.com/api/billing/invoices/{invoice_ref}/pay"
response = requests.post(url)
print(response.text)const options = {method: 'POST'};
fetch('https://api.example.com/api/billing/invoices/{invoice_ref}/pay', 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.example.com/api/billing/invoices/{invoice_ref}/pay",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
]);
$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.example.com/api/billing/invoices/{invoice_ref}/pay"
req, _ := http.NewRequest("POST", url, nil)
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.example.com/api/billing/invoices/{invoice_ref}/pay")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/api/billing/invoices/{invoice_ref}/pay")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
response = http.request(request)
puts response.read_body{
"amount": 123,
"client_secret": "<string>",
"payment_intent_id": "<string>",
"publishable_key": "<string>",
"saved_card_brand": "<string>",
"saved_card_last4": "<string>",
"saved_payment_method_id": "<string>"
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"ctx": {},
"input": "<unknown>"
}
]
}Pay Invoice
Create a payable Stripe invoice for an open Odoo personal usage invoice so the customer can settle it from inside the CodeCobra app (Stripe Elements, no redirect, no saved card required).
This is the postpaid manual-pay path: Odoo issues a due-dated usage invoice and leaves the receivable open (see _create_partner_invoice). The customer views it via GET /api/billing/invoices (payable=true) and calls this endpoint to get a PaymentIntent client_secret, which the frontend confirms with Stripe Elements. On success the invoice.paid webhook records the payment in Odoo, which FIFO-reconciles it against the open installment lines and clears any overdue suspension.
invoice_ref is the odoo_<id> id from the invoice listing. See the
org variant at POST /api/organizations//billing/invoices//pay.
curl --request POST \
--url https://api.example.com/api/billing/invoices/{invoice_ref}/payimport requests
url = "https://api.example.com/api/billing/invoices/{invoice_ref}/pay"
response = requests.post(url)
print(response.text)const options = {method: 'POST'};
fetch('https://api.example.com/api/billing/invoices/{invoice_ref}/pay', 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.example.com/api/billing/invoices/{invoice_ref}/pay",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
]);
$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.example.com/api/billing/invoices/{invoice_ref}/pay"
req, _ := http.NewRequest("POST", url, nil)
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.example.com/api/billing/invoices/{invoice_ref}/pay")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/api/billing/invoices/{invoice_ref}/pay")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
response = http.request(request)
puts response.read_body{
"amount": 123,
"client_secret": "<string>",
"payment_intent_id": "<string>",
"publishable_key": "<string>",
"saved_card_brand": "<string>",
"saved_card_last4": "<string>",
"saved_payment_method_id": "<string>"
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"ctx": {},
"input": "<unknown>"
}
]
}