Publish the policy when you ship
Run this in your release pipeline. It creates the policy the first time and updates it on every release after that, so the hosted text always matches the SDKs in the build you ship.
- Store the key as a secret named
FPP_API_KEY. Never commit it. - If the slug you ask for is taken, the API adds a suffix (
pocket-notes-2). Keep theslugit returns. - A PATCH that changes settings writes the text again. Text you edited by hand in the dashboard is replaced only when you send
markdown.
# .github/workflows/privacy-policy.yml
name: Privacy policy
on:
push:
tags: ["v*"]
jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Create or update the hosted policy
env:
FPP_API_KEY: ${{ secrets.FPP_API_KEY }}
API: https://com-company-guiacnhsemautoescola.freeprivacypolicy.app/api/v1
SLUG: pocket-notes
run: |
SETTINGS='{"name":"Pocket Notes","product_type":"mobile_app","country":"Portugal","services":["admob","firebase_analytics","revenuecat"]}'
AUTH=(-H "Authorization: Bearer $FPP_API_KEY" -H "Accept: application/json" -H "Content-Type: application/json")
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "${AUTH[@]}" "$API/policies/$SLUG")
if [ "$STATUS" = "404" ]; then
curl -fsS -X POST "$API/policies" "${AUTH[@]}" \
-d "$(echo "$SETTINGS" | jq --arg slug "$SLUG" '. + {slug: $slug}')"
else
curl -fsS -X PATCH "$API/policies/$SLUG" "${AUTH[@]}" -d "$SETTINGS"
fi
// scripts/publish-policy.mjs (node scripts/publish-policy.mjs)
const API = "https://com-company-guiacnhsemautoescola.freeprivacypolicy.app/api/v1";
const slug = "pocket-notes";
const headers = {
Authorization: `Bearer ${process.env.FPP_API_KEY}`,
Accept: "application/json",
"Content-Type": "application/json",
};
const settings = {
name: "Pocket Notes",
product_type: "mobile_app",
country: "Portugal",
services: ["admob", "firebase_analytics", "revenuecat"],
};
const existing = await fetch(`$https://com-company-guiacnhsemautoescola.freeprivacypolicy.app/api/v1/policies/${slug}`, { headers });
const response = existing.status === 404
? await fetch(`$https://com-company-guiacnhsemautoescola.freeprivacypolicy.app/api/v1/policies`, { method: "POST", headers, body: JSON.stringify({ ...settings, slug }) })
: await fetch(`$https://com-company-guiacnhsemautoescola.freeprivacypolicy.app/api/v1/policies/${slug}`, { method: "PATCH", headers, body: JSON.stringify(settings) });
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
const { data } = await response.json();
console.log(data.public_urls.privacy_policy);
import os
import requests
API = "https://com-company-guiacnhsemautoescola.freeprivacypolicy.app/api/v1"
SLUG = "pocket-notes"
session = requests.Session()
session.headers.update({
"Authorization": f"Bearer {os.environ['FPP_API_KEY']}",
"Accept": "application/json",
})
settings = {
"name": "Pocket Notes",
"product_type": "mobile_app",
"country": "Portugal",
"services": ["admob", "firebase_analytics", "revenuecat"],
}
if session.get(f"https://com-company-guiacnhsemautoescola.freeprivacypolicy.app/api/v1/policies/{SLUG}", timeout=30).status_code == 404:
response = session.post(f"https://com-company-guiacnhsemautoescola.freeprivacypolicy.app/api/v1/policies", json={**settings, "slug": SLUG}, timeout=30)
else:
response = session.patch(f"https://com-company-guiacnhsemautoescola.freeprivacypolicy.app/api/v1/policies/{SLUG}", json=settings, timeout=30)
response.raise_for_status()
print(response.json()["data"]["public_urls"]["privacy_policy"])
use Illuminate\Support\Facades\Http;
$api = Http::withToken(config('services.freeprivacypolicy.key'))
->acceptJson()
->baseUrl('https://com-company-guiacnhsemautoescola.freeprivacypolicy.app/api/v1');
$slug = 'pocket-notes';
$settings = [
'name' => 'Pocket Notes',
'product_type' => 'mobile_app',
'country' => 'Portugal',
'services' => ['admob', 'firebase_analytics', 'revenuecat'],
];
$response = $api->get("policies/{$slug}")->notFound()
? $api->post('policies', [...$settings, 'slug' => $slug])
: $api->patch("policies/{$slug}", $settings);
$privacyPolicyUrl = $response->throw()->json('data.public_urls.privacy_policy');