Consent
Record Consent
Record a customer’s consent for marketing, billing, or data processing activities.
POST
/
v1
/
consents
Record customer consent
curl --request POST \
--url https://billing.example.com/v1/consents \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"customer_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"granted": true,
"subscription_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"consent_text": "<string>"
}
'import requests
url = "https://billing.example.com/v1/consents"
payload = {
"customer_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"granted": True,
"subscription_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"consent_text": "<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({
customer_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
granted: true,
subscription_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
consent_text: '<string>'
})
};
fetch('https://billing.example.com/v1/consents', 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://billing.example.com/v1/consents",
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([
'customer_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'granted' => true,
'subscription_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'consent_text' => '<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://billing.example.com/v1/consents"
payload := strings.NewReader("{\n \"customer_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"granted\": true,\n \"subscription_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"consent_text\": \"<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://billing.example.com/v1/consents")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"customer_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"granted\": true,\n \"subscription_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"consent_text\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://billing.example.com/v1/consents")
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 \"customer_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"granted\": true,\n \"subscription_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"consent_text\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"tenant_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"customer_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"subscription_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"consent_type": "recurring_billing",
"granted": true,
"granted_at": "2023-11-07T05:31:56Z",
"revoked_at": "2023-11-07T05:31:56Z",
"ip_address": "<string>",
"user_agent": "<string>",
"consent_text": "<string>",
"version": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z"
}{
"error": {
"code": "BAD_REQUEST",
"message": "<string>"
}
}{
"error": {
"code": "BAD_REQUEST",
"message": "<string>"
}
}Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
customer_id | string | Yes | The unique identifier of the customer (e.g., cust_abc123). |
type | string | Yes | The consent category. One of: marketing, billing, data_processing. |
channel | string | Yes | The communication channel. One of: email, sms, phone. |
granted | boolean | Yes | Whether consent is being granted (true) or denied (false). |
ip_address | string | No | The IP address of the user at the time of consent. Recommended for audit trails. |
user_agent | string | No | The browser user agent string at the time of consent. |
Example Request
curl -X POST https://api.recurso.dev/v1/consents \
-H "Authorization: Bearer rsk_live_7f3a9b2c1d4e8f0a" \
-H "Content-Type: application/json" \
-d '{
"customer_id": "cust_8Hx4kLm2Qr",
"type": "marketing",
"channel": "email",
"granted": true,
"ip_address": "203.0.113.42",
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36"
}'
Response
{
"id": "cons_Tn4vW9xKpL",
"customer_id": "cust_8Hx4kLm2Qr",
"type": "marketing",
"channel": "email",
"granted": true,
"ip_address": "203.0.113.42",
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36",
"timestamp": "2026-06-23T14:32:10Z",
"revoked_at": null,
"created_at": "2026-06-23T14:32:10Z"
}
Notes
- Each consent record is immutable for audit purposes. To revoke consent, use the Revoke Consent endpoint.
- Recording consent with
granted: falsecreates an explicit denial record, which differs from revoking a previously granted consent. - Providing
ip_addressanduser_agentis strongly recommended for GDPR and compliance audit trails.
Ensure you collect consent before sending marketing communications. Recurso will block outbound messages to customers without the appropriate consent on record.
Authorizations
Tenant API key obtained from POST /auth/register or POST /v1/developer/keys.
Body
application/json
Available options:
recurring_billing, email_marketing, data_processing, terms_of_service, privacy_policy Exact text shown to the customer. Defaults to the standard recurring-billing text.
Response
Consent recorded.
Available options:
recurring_billing, email_marketing, data_processing, terms_of_service, privacy_policy Exact text shown to the customer.
Version of the consent text.
⌘I
Record customer consent
curl --request POST \
--url https://billing.example.com/v1/consents \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"customer_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"granted": true,
"subscription_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"consent_text": "<string>"
}
'import requests
url = "https://billing.example.com/v1/consents"
payload = {
"customer_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"granted": True,
"subscription_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"consent_text": "<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({
customer_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
granted: true,
subscription_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
consent_text: '<string>'
})
};
fetch('https://billing.example.com/v1/consents', 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://billing.example.com/v1/consents",
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([
'customer_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'granted' => true,
'subscription_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'consent_text' => '<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://billing.example.com/v1/consents"
payload := strings.NewReader("{\n \"customer_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"granted\": true,\n \"subscription_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"consent_text\": \"<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://billing.example.com/v1/consents")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"customer_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"granted\": true,\n \"subscription_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"consent_text\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://billing.example.com/v1/consents")
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 \"customer_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"granted\": true,\n \"subscription_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"consent_text\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"tenant_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"customer_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"subscription_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"consent_type": "recurring_billing",
"granted": true,
"granted_at": "2023-11-07T05:31:56Z",
"revoked_at": "2023-11-07T05:31:56Z",
"ip_address": "<string>",
"user_agent": "<string>",
"consent_text": "<string>",
"version": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z"
}{
"error": {
"code": "BAD_REQUEST",
"message": "<string>"
}
}{
"error": {
"code": "BAD_REQUEST",
"message": "<string>"
}
}