FreePrivacyPolicy

Integre páginas legais ao seu app

Uma requisição escreve sua política de privacidade, termos de serviço, EULA e padrões de segurança infantil e os hospeda com uma página da empresa e app-ads.txt em {slug}.freeprivacypolicy.app. Grátis, sem limite de políticas.

Endpoints
16
Limite de requisições
60/min
Especificação
OpenAPI 3.1

POST /api/v1/policies

{
    "name": "Pocket Notes",
    "product_type": "mobile_app",
    "country": "Portugal",
    "services": [
        "admob",
        "firebase_analytics"
    ]
}

201 Created, já no ar

  • pocket-notes.freeprivacypolicy.app/ (Página da empresa)
  • pocket-notes.freeprivacypolicy.app/privacy-policy (Política de privacidade)
  • pocket-notes.freeprivacypolicy.app/terms-of-service (Termos de serviço)
  • pocket-notes.freeprivacypolicy.app/end-user-license-agreement (EULA)
  • pocket-notes.freeprivacypolicy.app/child-safety-standards (Padrões de segurança infantil)
  • pocket-notes.freeprivacypolicy.app/ads.txt (ads.txt)
  • pocket-notes.freeprivacypolicy.app/app-ads.txt (app-ads.txt)
Nesta página

Início rápido

Três etapas do zero a um URL de política de privacidade que você pode colar no App Store Connect ou no Google Play.

  1. Criar uma conta grátis

    Políticas, empresas e a chave pertencem à sua conta. Não há plano para escolher nem cartão para cadastrar.

  2. Crie sua chave pessoal

    Abra a página do assistente e selecione Criar minha chave. Ela é exibida uma única vez, então guarde-a imediatamente, por exemplo como FPP_API_KEY nos segredos do seu CI ou no seu shell.

    Shell
    export FPP_API_KEY="fpp_your_key_here"
  3. Publique sua primeira política

    Envie o nome, o tipo de produto e o seu país. Adicione os serviços que o seu app usa para que a política os divulgue.

    Requisição
    curl -X POST "https://freeprivacypolicy.app/api/v1/policies" \
      -H "Authorization: Bearer $FPP_API_KEY" \
      -H "Accept: application/json" \
      -H "Content-Type: application/json" \
      -d '{"name": "Pocket Notes", "product_type": "mobile_app", "country": "Portugal", "services": ["admob", "firebase_analytics"]}'

    A resposta traz todos os endereços, já no ar:

    Resposta 201
    {
        "data": {
            "slug": "pocket-notes",
            "name": "Pocket Notes",
            "published": true,
            "public_urls": {
                "landing": "https://pocket-notes.freeprivacypolicy.app",
                "privacy_policy": "https://pocket-notes.freeprivacypolicy.app/privacy-policy",
                "terms": "https://pocket-notes.freeprivacypolicy.app/terms-of-service",
                "eula": "https://pocket-notes.freeprivacypolicy.app/end-user-license-agreement",
                "child_safety": "https://pocket-notes.freeprivacypolicy.app/child-safety-standards",
                "ads_txt": "https://pocket-notes.freeprivacypolicy.app/ads.txt",
                "app_ads_txt": "https://pocket-notes.freeprivacypolicy.app/app-ads.txt"
            }
        }
    }

Autenticação

Toda requisição leva a sua chave pessoal, em qualquer um dos cabeçalhos. Requisições sem uma chave válida recebem 401.

  • Uma chave, dois usos. A mesma chave conecta o Claude Code e o Codex por MCP e chama a API REST.
  • Uma nova chave substitui a antiga. Criar uma chave desconecta a chave anterior em todos os lugares ao mesmo tempo.
  • Somente a sua conta. Uma chave lê e altera apenas as suas próprias políticas e empresas. Registros de outras contas respondem 404.
  • Mantenha-a no servidor. Nunca inclua a chave dentro do binário de um app ou de uma página web. Chame a API a partir do CI, de um backend ou da sua máquina.
  • 60 requisições por minuto por chave. Toda resposta inclui X-RateLimit-Remaining.
curl "https://freeprivacypolicy.app/api/v1/me" \
  -H "Authorization: Bearer $FPP_API_KEY" \
  -H "Accept: application/json"

Receitas de integração

Fluxos prontos para copiar para as tarefas que os desenvolvedores mais automatizam. Escolha uma linguagem uma vez e todos os exemplos da página seguem essa escolha.

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 the slug it 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://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

Fill in App Store Connect and Google Play

Every policy response carries public_urls. Paste them into the store fields below once; the addresses never change, even when you update the text.

App Store Connect: Privacy Policy URL
privacy_policy
App Store Connect: License Agreement (custom EULA)
eula
Google Play Console: Privacy policy
privacy_policy
Google Play Console: Child safety standards
child_safety
Store listing: Website (used by ad networks for app-ads.txt)
landing
Terms link inside your app or website
terms
curl -s "https://freeprivacypolicy.app/api/v1/policies/pocket-notes" \
  -H "Authorization: Bearer $FPP_API_KEY" \
  -H "Accept: application/json" \
  | jq '.data.public_urls'

Keep app-ads.txt in sync for ad networks

AdMob, AppLovin, Unity and other networks read app-ads.txt from the website on your store listing. Set that website to the policy address (public_urls.landing) and keep the lines on your company: every policy subdomain serves the lines of all your companies, merged and without duplicates.

  • Send the whole file: app_ads_txt replaces the previous lines.
  • Changes are live at https://{slug}.freeprivacypolicy.app/app-ads.txt right away. Ad networks re-crawl on their own schedule, usually within 24 hours.
  • ads_txt works the same way for websites and is served per company.
curl -X PATCH "https://freeprivacypolicy.app/api/v1/companies/42" \
  -H "Authorization: Bearer $FPP_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "app_ads_txt": "google.com, pub-1234567890123456, DIRECT, f08c47fec0942fa0\napplovin.com, 0123456789abcdef, DIRECT"
  }'

# Check what ad networks will read
curl -s https://pocket-notes.freeprivacypolicy.app/app-ads.txt

Update the policy when you add an SDK

Each service adds its own disclosure. services replaces the whole list, so read the current one, add the new key and send it back. Valid keys come from GET /options.

SERVICES=$(curl -s "https://freeprivacypolicy.app/api/v1/policies/pocket-notes" \
  -H "Authorization: Bearer $FPP_API_KEY" -H "Accept: application/json" \
  | jq -c '.data.services + ["openai"] | unique')

curl -X PATCH "https://freeprivacypolicy.app/api/v1/policies/pocket-notes" \
  -H "Authorization: Bearer $FPP_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d "{\"services\": $SERVICES, \"clauses\": [\"accounts\", \"ai\"]}"

Share one company across several apps

A company holds the publisher details shown on every page, plus ads.txt and app-ads.txt. Create it once, then pass its id as company_id to each new policy. Upload a logo in the dashboard; the API does not accept files.

# 1. Create the company
curl -X POST "https://freeprivacypolicy.app/api/v1/companies" \
  -H "Authorization: Bearer $FPP_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"company_name": "Acme Labs Ltd.", "email": "[email protected]", "address": "1 Market Street, Lisbon"}'

# 2. Publish each app with its id
curl -X POST "https://freeprivacypolicy.app/api/v1/policies" \
  -H "Authorization: Bearer $FPP_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"name": "Pocket Notes", "product_type": "mobile_app", "country": "Portugal", "company_id": 42}'

# 3. List everything in the account
curl -s "https://freeprivacypolicy.app/api/v1/companies?per_page=100" -H "Authorization: Bearer $FPP_API_KEY" -H "Accept: application/json"

Servidor MCP em https://freeprivacypolicy.app/mcp

Prefere pedir ao seu assistente de IA?

A mesma chave conecta o Claude Code, o Claude Desktop, o Codex, o Cursor e o VS Code. O assistente lê suas dependências, escolhe os serviços que o seu app realmente usa e chama estes endpoints por você: publicar, atualizar, empresas, app-ads.txt.

Claude Code por Anthropic

Execute no seu terminal
claude mcp add --transport http --scope user freeprivacypolicy https://freeprivacypolicy.app/mcp --header "Authorization: Bearer YOUR_KEY"

Claude Desktop por Anthropic

claude_desktop_config.json
{
    "mcpServers": {
        "freeprivacypolicy": {
            "command": "npx",
            "args": [
                "-y",
                "mcp-remote",
                "https://freeprivacypolicy.app/mcp",
                "--header",
                "Authorization:${AUTH_HEADER}",
                "--transport",
                "http-only"
            ],
            "env": {
                "AUTH_HEADER": "Bearer YOUR_KEY"
            }
        }
    }
}

Codex por OpenAI

~/.codex/config.toml
[mcp_servers.freeprivacypolicy]
url = "https://freeprivacypolicy.app/mcp"
http_headers = { "Authorization" = "Bearer YOUR_KEY" }

Cursor por Anysphere

~/.cursor/mcp.json
{
    "mcpServers": {
        "freeprivacypolicy": {
            "url": "https://freeprivacypolicy.app/mcp",
            "headers": {
                "Authorization": "Bearer YOUR_KEY"
            }
        }
    }
}

O Cursor também faz a instalação por um link: entre e conecte o Cursor para obter o seu com a chave já preenchida.

VS Code por Microsoft · modo agente do GitHub Copilot

Execute no seu terminal
code --add-mcp '{"name":"freeprivacypolicy","type":"http","url":"https://freeprivacypolicy.app/mcp","headers":{"Authorization":"Bearer YOUR_KEY"}}'

O VS Code também faz a instalação por um link: entre e conecte o VS Code para obter o seu com a chave já preenchida.

Conectar um assistente

Referência da API

Gerada a partir do documento OpenAPI, versão 1.0.0.

URL base https://freeprivacypolicy.app/api/v1

Account

The account the API key belongs to.

Get the current account

GET /me

Returns the account the API key belongs to, with how many policies and companies it has. Handy to check that a key works.

Respostas
  • 200

    The account.

  • 401

    The key is missing, invalid, revoked or its account is suspended.

  • 429

    More than 60 requests in a minute with this key.

curl -X GET "https://freeprivacypolicy.app/api/v1/me" \
  -H "Authorization: Bearer $FPP_API_KEY" \
  -H "Accept: application/json"
Resposta 200
{
    "data": {
        "id": 7,
        "name": "Ada Lovelace",
        "email": "[email protected]",
        "policies_count": 2,
        "companies_count": 1
    }
}

Catalog

Product types, third-party services, optional sections and countries a policy can use.

List policy options

GET /options

Everything a policy can cover: product types, third-party services (each adds its own disclosure), optional sections, document languages and countries. Use the key values in product_type, services and clauses, a country name in country and a language code in language.

Respostas
  • 200

    The catalog.

  • 401

    The key is missing, invalid, revoked or its account is suspended.

  • 429

    More than 60 requests in a minute with this key.

curl -X GET "https://freeprivacypolicy.app/api/v1/options" \
  -H "Authorization: Bearer $FPP_API_KEY" \
  -H "Accept: application/json"
Resposta 200
{
    "data": {
        "product_types": [
            {
                "key": "mobile_app",
                "label": "Mobile App"
            }
        ],
        "services": [
            {
                "key": "admob",
                "label": "AdMob",
                "group": "Ads",
                "description": "We use Google AdMob to serve personalized and non-personalized ads in our product...",
                "products": [
                    "mobile_app",
                    "game"
                ],
                "ads": true
            }
        ],
        "clauses": [
            {
                "key": "accounts",
                "label": "Accounts and sign-in",
                "category": "Data you collect",
                "description": "Explain the details collected when people create an account."
            }
        ],
        "languages": [
            {
                "code": "en",
                "name": "English"
            },
            {
                "code": "pt_BR",
                "name": "Português (Brasil)"
            }
        ],
        "countries": [
            {
                "code": "PT",
                "name": "Portugal"
            }
        ]
    }
}

Policies

Generate, publish, update and take down the legal pages hosted on {slug}.freeprivacypolicy.app.

List policies

GET /policies

Your policies, published or not, sorted by name.

Parâmetros
  • page integer em query

    Page number, starting at 1. Padrão 1.

  • per_page integer em query

    Items per page, 1 to 100. Padrão 25.

Respostas
  • 200

    A page of policies.

  • 401

    The key is missing, invalid, revoked or its account is suspended.

  • 422

    The request is invalid. errors lists the messages per field.

  • 429

    More than 60 requests in a minute with this key.

curl -X GET "https://freeprivacypolicy.app/api/v1/policies?per_page=25" \
  -H "Authorization: Bearer $FPP_API_KEY" \
  -H "Accept: application/json"
Resposta 200
{
    "data": [
        {
            "id": 1287,
            "slug": "pocket-notes",
            "name": "Pocket Notes",
            "product_type": "mobile_app",
            "country": "Portugal",
            "services": [
                "admob",
                "firebase_analytics",
                "revenuecat"
            ],
            "clauses": [
                "accounts",
                "metadata"
            ],
            "markdown": "# Privacy Policy\n\nThis Privacy Policy explains how Acme Labs Ltd. collects, uses and protects information when you use Pocket Notes...",
            "html": "<h1>Privacy Policy</h1>\n<p>This Privacy Policy explains how Acme Labs Ltd. collects, uses and protects information when you use Pocket Notes...</p>",
            "published": true,
            "published_at": "2026-09-20T08:30:00+00:00",
            "noindex": false,
            "company_id": 42,
            "contact": {
                "id": 42,
                "company_name": "Acme Labs Ltd.",
                "address": "1 Market Street, Lisbon, Portugal",
                "email": "[email protected]",
                "about": "Acme Labs builds productivity apps for small teams.",
                "ads_txt": "google.com, pub-1234567890123456, DIRECT, f08c47fec0942fa0",
                "app_ads_txt": "google.com, pub-1234567890123456, DIRECT, f08c47fec0942fa0",
                "show_resources_publicly": true
            },
            "public_urls": {
                "landing": "https://pocket-notes.freeprivacypolicy.app",
                "privacy_policy": "https://pocket-notes.freeprivacypolicy.app/privacy-policy",
                "child_safety": "https://pocket-notes.freeprivacypolicy.app/child-safety-standards",
                "eula": "https://pocket-notes.freeprivacypolicy.app/end-user-license-agreement",
                "terms": "https://pocket-notes.freeprivacypolicy.app/terms-of-service",
                "ads_txt": "https://pocket-notes.freeprivacypolicy.app/ads.txt",
                "app_ads_txt": "https://pocket-notes.freeprivacypolicy.app/app-ads.txt"
            },
            "created_at": "2026-09-20T08:30:00+00:00",
            "updated_at": "2026-09-20T08:30:00+00:00"
        }
    ],
    "links": {
        "first": "https://freeprivacypolicy.app/api/v1/policies?page=1",
        "last": "https://freeprivacypolicy.app/api/v1/policies?page=1",
        "prev": null,
        "next": null
    },
    "meta": {
        "current_page": 1,
        "from": 1,
        "last_page": 1,
        "links": [
            {
                "url": null,
                "label": "&laquo; Previous",
                "page": null,
                "active": false
            },
            {
                "url": "https://freeprivacypolicy.app/api/v1/policies?page=1",
                "label": "1",
                "page": 1,
                "active": true
            },
            {
                "url": null,
                "label": "Next &raquo;",
                "page": null,
                "active": false
            }
        ],
        "path": "https://freeprivacypolicy.app/api/v1/policies",
        "per_page": 25,
        "to": 1,
        "total": 1
    }
}

Generate and publish a policy

POST /policies

Writes the policy from the settings you send and publishes it right away on {slug}.freeprivacypolicy.app.

The publisher shown on the pages comes from, in order:

  1. company_id: one of your companies (GET /companies), shared between policies;
  2. contact: a new company used only by this policy;
  3. nothing: a new company named after the policy, with {slug}@freeprivacypolicy.app as the email.

company_id and contact cannot be sent together.

Corpo PolicyInput
  • name string obrigatório

    Name of the app, game, website or company, as users know it.

  • product_type string obrigatório

    What the product is. See GET /options for labels.

    website mobile_app saas game desktop_app browser_extension

  • country string obrigatório

    Country you operate from, as an English name (see countries in GET /options).

  • language string

    Language the legal documents and public pages are written in (see languages in GET /options). Defaults to en.

    Padrão "en".

    en pt_BR es fr de it ja

  • services string[] | null

    Third-party services the product uses. Each one adds its own disclosure. Replaces the whole list on update.

    37 valores aceitos

    admob facebook_audience_network facebook_pixel firebase_analytics firebase_crashlytics google_analytics google_sign_in sign_in_with_apple facebook_login firebase_cloud_messaging onesignal revenuecat stripe sentry mixpanel amplitude appsflyer unity_ads applovin google_maps openai qonversion adapty superwall adjust branch ironsource paddle auth0 clerk posthog segment hotjar intercom hubspot zendesk anthropic

  • clauses string[] | null

    Optional sections, such as accounts, location or gdpr. Replaces the whole list on update.

    30 valores aceitos

    accounts metadata location contacts camera_media microphone biometrics health purchases financial identity_verification credit_partners notifications marketing ugc ai advertising analytics no_sale retention account_deletion international_transfers third_party_links children gdpr ccpa lgpd us_states canada mexico

  • slug string | null

    Subdomain of the public pages ({slug}.freeprivacypolicy.app). Lowercase letters, numbers and hyphens; defaults to the name. When taken, a numeric suffix is added (pocket-notes-2); reserved words (www, api, docs, ...) are rejected with 422.

  • markdown string | null

    Your own policy text in Markdown. When sent, it is published as given instead of the generated text.

  • noindex boolean | null

    true asks search engines not to index the public pages (they stay online).

    Padrão false.

  • company_id integer | null

    Id of one of your companies (GET /companies). Its contact details, logo and ads.txt are used. Cannot be combined with contact.

  • contact object

    Publisher details for a company used only by this policy.

  • contact.company_name string

    Legal or trading name shown as the publisher. Defaults to the policy name.

  • contact.email string

    Where users reach you about privacy. When left out on create, {slug}@freeprivacypolicy.app is used.

  • contact.address string | null

    Postal address, only when you want it published.

  • contact.about string | null

    Short description shown on the company page.

  • contact.ads_txt string | null

    Full ads.txt content for websites, one seller line per row.

  • contact.app_ads_txt string | null

    Full app-ads.txt content for mobile apps, one seller line per row.

  • contact.show_resources_publicly boolean

    List the ads.txt and app-ads.txt links on the company page.

    Padrão false.

  • accent_color string | null

    Accent color of the public pages as #RRGGBB, or null for the default. Links and buttons use it; text shades are darkened automatically to keep AA contrast.

  • theme string

    Look of the public pages: classic (default), minimal (plain document) or card (document on a raised card under a band in the accent color).

    Padrão "classic".

    classic minimal card

Respostas
  • 201

    The policy was published.

  • 401

    The key is missing, invalid, revoked or its account is suspended.

  • 422

    The request is invalid. errors lists the messages per field.

  • 429

    More than 60 requests in a minute with this key.

curl -X POST "https://freeprivacypolicy.app/api/v1/policies" \
  -H "Authorization: Bearer $FPP_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Pocket Notes",
    "product_type": "mobile_app",
    "country": "Portugal",
    "services": [
        "admob",
        "firebase_analytics",
        "revenuecat"
    ],
    "clauses": [
        "accounts",
        "metadata"
    ],
    "slug": "pocket-notes",
    "contact": {
        "company_name": "Acme Labs Ltd.",
        "email": "[email protected]",
        "address": "1 Market Street, Lisbon, Portugal",
        "app_ads_txt": "google.com, pub-1234567890123456, DIRECT, f08c47fec0942fa0",
        "show_resources_publicly": true
    }
}'
Corpo da requisição: Only the required fields
{
    "name": "Pocket Notes",
    "product_type": "mobile_app",
    "country": "Portugal"
}
Resposta 201
{
    "data": {
        "id": 1287,
        "slug": "pocket-notes",
        "name": "Pocket Notes",
        "product_type": "mobile_app",
        "country": "Portugal",
        "language": "en",
        "services": [
            "admob",
            "firebase_analytics",
            "revenuecat"
        ],
        "clauses": [
            "accounts",
            "metadata"
        ],
        "markdown": "# Privacy Policy\n\nThis Privacy Policy explains how Acme Labs Ltd. collects, uses and protects information when you use Pocket Notes...",
        "html": "<h1>Privacy Policy</h1>\n<p>This Privacy Policy explains how Acme Labs Ltd. collects, uses and protects information when you use Pocket Notes...</p>",
        "published": true,
        "published_at": "2026-09-20T08:30:00+00:00",
        "noindex": false,
        "app_icon_url": null,
        "logo_url": null,
        "accent_color": null,
        "theme": "classic",
        "company_id": 42,
        "contact": {
            "id": 42,
            "company_name": "Acme Labs Ltd.",
            "address": "1 Market Street, Lisbon, Portugal",
            "email": "[email protected]",
            "about": "Acme Labs builds productivity apps for small teams.",
            "ads_txt": "google.com, pub-1234567890123456, DIRECT, f08c47fec0942fa0",
            "app_ads_txt": "google.com, pub-1234567890123456, DIRECT, f08c47fec0942fa0",
            "show_resources_publicly": true
        },
        "public_urls": {
            "landing": "https://pocket-notes.freeprivacypolicy.app",
            "privacy_policy": "https://pocket-notes.freeprivacypolicy.app/privacy-policy",
            "child_safety": "https://pocket-notes.freeprivacypolicy.app/child-safety-standards",
            "eula": "https://pocket-notes.freeprivacypolicy.app/end-user-license-agreement",
            "terms": "https://pocket-notes.freeprivacypolicy.app/terms-of-service",
            "ads_txt": "https://pocket-notes.freeprivacypolicy.app/ads.txt",
            "app_ads_txt": "https://pocket-notes.freeprivacypolicy.app/app-ads.txt"
        },
        "created_at": "2026-09-20T08:30:00+00:00",
        "updated_at": "2026-09-20T08:30:00+00:00"
    }
}

Get a policy

GET /policies/{slug}

One of your policies, with its Markdown and HTML text and the addresses of its public pages.

Parâmetros
  • slug string em path obrigatório

    The policy slug (its subdomain).

Respostas
  • 200

    The policy.

  • 401

    The key is missing, invalid, revoked or its account is suspended.

  • 404

    No such record in this account.

  • 429

    More than 60 requests in a minute with this key.

curl -X GET "https://freeprivacypolicy.app/api/v1/policies/pocket-notes" \
  -H "Authorization: Bearer $FPP_API_KEY" \
  -H "Accept: application/json"
Resposta 200
{
    "data": {
        "id": 1287,
        "slug": "pocket-notes",
        "name": "Pocket Notes",
        "product_type": "mobile_app",
        "country": "Portugal",
        "language": "en",
        "services": [
            "admob",
            "firebase_analytics",
            "revenuecat"
        ],
        "clauses": [
            "accounts",
            "metadata"
        ],
        "markdown": "# Privacy Policy\n\nThis Privacy Policy explains how Acme Labs Ltd. collects, uses and protects information when you use Pocket Notes...",
        "html": "<h1>Privacy Policy</h1>\n<p>This Privacy Policy explains how Acme Labs Ltd. collects, uses and protects information when you use Pocket Notes...</p>",
        "published": true,
        "published_at": "2026-09-20T08:30:00+00:00",
        "noindex": false,
        "app_icon_url": null,
        "logo_url": null,
        "accent_color": null,
        "theme": "classic",
        "company_id": 42,
        "contact": {
            "id": 42,
            "company_name": "Acme Labs Ltd.",
            "address": "1 Market Street, Lisbon, Portugal",
            "email": "[email protected]",
            "about": "Acme Labs builds productivity apps for small teams.",
            "ads_txt": "google.com, pub-1234567890123456, DIRECT, f08c47fec0942fa0",
            "app_ads_txt": "google.com, pub-1234567890123456, DIRECT, f08c47fec0942fa0",
            "show_resources_publicly": true
        },
        "public_urls": {
            "landing": "https://pocket-notes.freeprivacypolicy.app",
            "privacy_policy": "https://pocket-notes.freeprivacypolicy.app/privacy-policy",
            "child_safety": "https://pocket-notes.freeprivacypolicy.app/child-safety-standards",
            "eula": "https://pocket-notes.freeprivacypolicy.app/end-user-license-agreement",
            "terms": "https://pocket-notes.freeprivacypolicy.app/terms-of-service",
            "ads_txt": "https://pocket-notes.freeprivacypolicy.app/ads.txt",
            "app_ads_txt": "https://pocket-notes.freeprivacypolicy.app/app-ads.txt"
        },
        "created_at": "2026-09-20T08:30:00+00:00",
        "updated_at": "2026-09-20T08:30:00+00:00"
    }
}

Update a policy

PATCH /policies/{slug}

Only the fields you send change.

  • Settings (name, product_type, country, language, services, clauses, contact, company_id) regenerate the text, which replaces edits made by hand. Send markdown in the same request to keep your own text.
  • markdown alone replaces the text as given.
  • published: false takes every public page offline (404); true puts them back.
  • noindex and slug never touch the text.
  • company_id: null detaches the company; the pages then use the contact details saved with the policy.
Parâmetros
  • slug string em path obrigatório

    The policy slug (its subdomain).

Corpo PolicyUpdate
  • name string

    Name of the app, game, website or company, as users know it.

  • product_type string

    What the product is. See GET /options for labels.

    website mobile_app saas game desktop_app browser_extension

  • country string

    Country you operate from, as an English name (see countries in GET /options).

  • language string

    Language the legal documents and public pages are written in. Changing it regenerates the text, like the other settings.

    en pt_BR es fr de it ja

  • services string[] | null

    Third-party services the product uses. Each one adds its own disclosure. Replaces the whole list on update.

    37 valores aceitos

    admob facebook_audience_network facebook_pixel firebase_analytics firebase_crashlytics google_analytics google_sign_in sign_in_with_apple facebook_login firebase_cloud_messaging onesignal revenuecat stripe sentry mixpanel amplitude appsflyer unity_ads applovin google_maps openai qonversion adapty superwall adjust branch ironsource paddle auth0 clerk posthog segment hotjar intercom hubspot zendesk anthropic

  • clauses string[] | null

    Optional sections, such as accounts, location or gdpr. Replaces the whole list on update.

    30 valores aceitos

    accounts metadata location contacts camera_media microphone biometrics health purchases financial identity_verification credit_partners notifications marketing ugc ai advertising analytics no_sale retention account_deletion international_transfers third_party_links children gdpr ccpa lgpd us_states canada mexico

  • slug string | null

    Subdomain of the public pages ({slug}.freeprivacypolicy.app). Lowercase letters, numbers and hyphens; defaults to the name. When taken, a numeric suffix is added (pocket-notes-2); reserved words (www, api, docs, ...) are rejected with 422.

  • markdown string | null

    Your own policy text in Markdown. When sent, it is published as given instead of the generated text.

  • company_id integer | null

    Id of one of your companies, or null to detach the current one. Cannot be combined with contact.

  • contact object

    Publisher details for a company used only by this policy.

  • contact.company_name string

    Legal or trading name shown as the publisher. Defaults to the policy name.

  • contact.email string

    Where users reach you about privacy. When left out on create, {slug}@freeprivacypolicy.app is used.

  • contact.address string | null

    Postal address, only when you want it published.

  • contact.about string | null

    Short description shown on the company page.

  • contact.ads_txt string | null

    Full ads.txt content for websites, one seller line per row.

  • contact.app_ads_txt string | null

    Full app-ads.txt content for mobile apps, one seller line per row.

  • contact.show_resources_publicly boolean

    List the ads.txt and app-ads.txt links on the company page.

    Padrão false.

  • noindex boolean

    true asks search engines not to index the public pages (they stay online).

  • published boolean

    false takes every public page offline (404); true publishes them again.

  • accent_color string | null

    Accent color of the public pages as #RRGGBB, or null for the default. Links and buttons use it; text shades are darkened automatically to keep AA contrast.

  • theme string

    Look of the public pages: classic (default), minimal (plain document) or card (document on a raised card under a band in the accent color).

    Padrão "classic".

    classic minimal card

Respostas
  • 200

    The updated policy.

  • 401

    The key is missing, invalid, revoked or its account is suspended.

  • 404

    No such record in this account.

  • 422

    The request is invalid. errors lists the messages per field.

  • 429

    More than 60 requests in a minute with this key.

curl -X PATCH "https://freeprivacypolicy.app/api/v1/policies/pocket-notes" \
  -H "Authorization: Bearer $FPP_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "services": [
        "admob",
        "firebase_analytics",
        "revenuecat",
        "openai"
    ],
    "clauses": [
        "accounts",
        "metadata",
        "ai"
    ]
}'
Corpo da requisição: Add a service and a section
{
    "services": [
        "admob",
        "firebase_analytics",
        "revenuecat",
        "openai"
    ],
    "clauses": [
        "accounts",
        "metadata",
        "ai"
    ]
}
Resposta 200
{
    "data": {
        "id": 1287,
        "slug": "pocket-notes",
        "name": "Pocket Notes",
        "product_type": "mobile_app",
        "country": "Portugal",
        "language": "en",
        "services": [
            "admob",
            "firebase_analytics",
            "revenuecat"
        ],
        "clauses": [
            "accounts",
            "metadata"
        ],
        "markdown": "# Privacy Policy\n\nThis Privacy Policy explains how Acme Labs Ltd. collects, uses and protects information when you use Pocket Notes...",
        "html": "<h1>Privacy Policy</h1>\n<p>This Privacy Policy explains how Acme Labs Ltd. collects, uses and protects information when you use Pocket Notes...</p>",
        "published": true,
        "published_at": "2026-09-20T08:30:00+00:00",
        "noindex": false,
        "app_icon_url": null,
        "logo_url": null,
        "accent_color": null,
        "theme": "classic",
        "company_id": 42,
        "contact": {
            "id": 42,
            "company_name": "Acme Labs Ltd.",
            "address": "1 Market Street, Lisbon, Portugal",
            "email": "[email protected]",
            "about": "Acme Labs builds productivity apps for small teams.",
            "ads_txt": "google.com, pub-1234567890123456, DIRECT, f08c47fec0942fa0",
            "app_ads_txt": "google.com, pub-1234567890123456, DIRECT, f08c47fec0942fa0",
            "show_resources_publicly": true
        },
        "public_urls": {
            "landing": "https://pocket-notes.freeprivacypolicy.app",
            "privacy_policy": "https://pocket-notes.freeprivacypolicy.app/privacy-policy",
            "child_safety": "https://pocket-notes.freeprivacypolicy.app/child-safety-standards",
            "eula": "https://pocket-notes.freeprivacypolicy.app/end-user-license-agreement",
            "terms": "https://pocket-notes.freeprivacypolicy.app/terms-of-service",
            "ads_txt": "https://pocket-notes.freeprivacypolicy.app/ads.txt",
            "app_ads_txt": "https://pocket-notes.freeprivacypolicy.app/app-ads.txt"
        },
        "created_at": "2026-09-20T08:30:00+00:00",
        "updated_at": "2026-09-20T08:30:00+00:00"
    }
}

Delete a policy

DELETE /policies/{slug}

Deletes the policy for good. Its public pages answer 404 and the slug becomes free. Its company is kept. To only take the pages offline, send published: false instead.

Parâmetros
  • slug string em path obrigatório

    The policy slug (its subdomain).

Respostas
  • 204

    Deleted.

  • 401

    The key is missing, invalid, revoked or its account is suspended.

  • 404

    No such record in this account.

  • 429

    More than 60 requests in a minute with this key.

curl -X DELETE "https://freeprivacypolicy.app/api/v1/policies/pocket-notes" \
  -H "Authorization: Bearer $FPP_API_KEY" \
  -H "Accept: application/json"

204 não tem corpo.

Upload the app icon

POST /policies/{slug}/app-icon

Sends the app icon as multipart/form-data. It must be a square PNG, JPG or WebP of at least 128 × 128 px and up to 1 MB. The public pages show it next to the name and use it as favicon, touch icon and share image. Replaces the current icon.

Parâmetros
  • slug string em path obrigatório

    The policy slug (its subdomain).

Corpo
  • app_icon string obrigatório

    Square PNG, JPG or WebP, at least 128 × 128 px, up to 1 MB.

Respostas
  • 200

    The policy with its new app_icon_url.

  • 401

    The key is missing, invalid, revoked or its account is suspended.

  • 404

    No such record in this account.

  • 429

    More than 60 requests in a minute with this key.

  • 422

    The request is invalid. errors lists the messages per field.

curl -X POST "https://freeprivacypolicy.app/api/v1/policies/pocket-notes/app-icon" \
  -H "Authorization: Bearer $FPP_API_KEY" \
  -H "Accept: application/json" \
  -F "[email protected]"

200 não tem corpo.

Remove the app icon

DELETE /policies/{slug}/app-icon

Deletes the app icon. The pages fall back to the company logo, or to the initial of the name.

Parâmetros
  • slug string em path obrigatório

    The policy slug (its subdomain).

Respostas
  • 200

    The policy, with app_icon_url null.

  • 401

    The key is missing, invalid, revoked or its account is suspended.

  • 404

    No such record in this account.

  • 429

    More than 60 requests in a minute with this key.

curl -X DELETE "https://freeprivacypolicy.app/api/v1/policies/pocket-notes/app-icon" \
  -H "Authorization: Bearer $FPP_API_KEY" \
  -H "Accept: application/json"

200 não tem corpo.

Companies

Publisher details shown on the policy pages, their logo, plus the ads.txt and app-ads.txt lines they serve.

List companies

GET /companies

Your companies, sorted by name, with how many policies use each one.

Parâmetros
  • page integer em query

    Page number, starting at 1. Padrão 1.

  • per_page integer em query

    Items per page, 1 to 100. Padrão 25.

Respostas
  • 200

    A page of companies.

  • 401

    The key is missing, invalid, revoked or its account is suspended.

  • 422

    The request is invalid. errors lists the messages per field.

  • 429

    More than 60 requests in a minute with this key.

curl -X GET "https://freeprivacypolicy.app/api/v1/companies?per_page=25" \
  -H "Authorization: Bearer $FPP_API_KEY" \
  -H "Accept: application/json"
Resposta 200
{
    "data": [
        {
            "id": 42,
            "company_name": "Acme Labs Ltd.",
            "email": "[email protected]",
            "address": "1 Market Street, Lisbon, Portugal",
            "about": "Acme Labs builds productivity apps for small teams.",
            "ads_txt": "google.com, pub-1234567890123456, DIRECT, f08c47fec0942fa0",
            "app_ads_txt": "google.com, pub-1234567890123456, DIRECT, f08c47fec0942fa0",
            "show_resources_publicly": true,
            "logo_url": null,
            "policies_count": 2,
            "created_at": "2026-09-01T12:00:00+00:00",
            "updated_at": "2026-09-20T08:30:00+00:00"
        }
    ],
    "links": {
        "first": "https://freeprivacypolicy.app/api/v1/companies?page=1",
        "last": "https://freeprivacypolicy.app/api/v1/companies?page=1",
        "prev": null,
        "next": null
    },
    "meta": {
        "current_page": 1,
        "from": 1,
        "last_page": 1,
        "links": [
            {
                "url": null,
                "label": "&laquo; Previous",
                "page": null,
                "active": false
            },
            {
                "url": "https://freeprivacypolicy.app/api/v1/companies?page=1",
                "label": "1",
                "page": 1,
                "active": true
            },
            {
                "url": null,
                "label": "Next &raquo;",
                "page": null,
                "active": false
            }
        ],
        "path": "https://freeprivacypolicy.app/api/v1/companies",
        "per_page": 25,
        "to": 1,
        "total": 1
    }
}

Create a company

POST /companies

Creates a publisher you can attach to policies with company_id.

ads_txt is served at {slug}/ads.txt for the policies using this company. app_ads_txt lines of all your companies are merged, de-duplicated and served at {slug}/app-ads.txt on every one of your policies.

Logos are uploaded in the dashboard; the API returns logo_url but does not accept files.

Corpo CompanyInput
  • company_name string obrigatório

  • email string obrigatório

  • address string | null

  • about string | null

  • ads_txt string | null

    Full ads.txt content, one seller line per row.

  • app_ads_txt string | null

    Full app-ads.txt content, one seller line per row.

  • show_resources_publicly boolean

    List the ads.txt and app-ads.txt links on the company page.

    Padrão false.

Respostas
  • 201

    The company was created.

  • 401

    The key is missing, invalid, revoked or its account is suspended.

  • 422

    The request is invalid. errors lists the messages per field.

  • 429

    More than 60 requests in a minute with this key.

curl -X POST "https://freeprivacypolicy.app/api/v1/companies" \
  -H "Authorization: Bearer $FPP_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "company_name": "Acme Labs Ltd.",
    "email": "[email protected]",
    "address": "1 Market Street, Lisbon, Portugal",
    "about": "Acme Labs builds productivity apps for small teams.",
    "app_ads_txt": "google.com, pub-1234567890123456, DIRECT, f08c47fec0942fa0\nunity.com, 1234567, DIRECT, 96cabb5fbdde37a7",
    "show_resources_publicly": true
}'
Corpo da requisição: Company with app-ads.txt lines
{
    "company_name": "Acme Labs Ltd.",
    "email": "[email protected]",
    "address": "1 Market Street, Lisbon, Portugal",
    "about": "Acme Labs builds productivity apps for small teams.",
    "app_ads_txt": "google.com, pub-1234567890123456, DIRECT, f08c47fec0942fa0\nunity.com, 1234567, DIRECT, 96cabb5fbdde37a7",
    "show_resources_publicly": true
}
Resposta 201
{
    "data": {
        "id": 42,
        "company_name": "Acme Labs Ltd.",
        "email": "[email protected]",
        "address": "1 Market Street, Lisbon, Portugal",
        "about": "Acme Labs builds productivity apps for small teams.",
        "ads_txt": "google.com, pub-1234567890123456, DIRECT, f08c47fec0942fa0",
        "app_ads_txt": "google.com, pub-1234567890123456, DIRECT, f08c47fec0942fa0",
        "show_resources_publicly": true,
        "logo_url": null,
        "policies_count": 0,
        "created_at": "2026-09-01T12:00:00+00:00",
        "updated_at": "2026-09-20T08:30:00+00:00"
    }
}

Get a company

GET /companies/{id}

One of your companies.

Parâmetros
  • id integer em path obrigatório

    The company id.

Respostas
  • 200

    The company.

  • 401

    The key is missing, invalid, revoked or its account is suspended.

  • 404

    No such record in this account.

  • 429

    More than 60 requests in a minute with this key.

curl -X GET "https://freeprivacypolicy.app/api/v1/companies/42" \
  -H "Authorization: Bearer $FPP_API_KEY" \
  -H "Accept: application/json"
Resposta 200
{
    "data": {
        "id": 42,
        "company_name": "Acme Labs Ltd.",
        "email": "[email protected]",
        "address": "1 Market Street, Lisbon, Portugal",
        "about": "Acme Labs builds productivity apps for small teams.",
        "ads_txt": "google.com, pub-1234567890123456, DIRECT, f08c47fec0942fa0",
        "app_ads_txt": "google.com, pub-1234567890123456, DIRECT, f08c47fec0942fa0",
        "show_resources_publicly": true,
        "logo_url": null,
        "policies_count": 2,
        "created_at": "2026-09-01T12:00:00+00:00",
        "updated_at": "2026-09-20T08:30:00+00:00"
    }
}

Update a company

PATCH /companies/{id}

Only the fields you send change. ads_txt and app_ads_txt replace the whole file: send the current lines too when adding one. The policy pages show the new details at once; their text is not regenerated.

Parâmetros
  • id integer em path obrigatório

    The company id.

Corpo CompanyUpdate
  • company_name string

  • email string

  • address string | null

  • about string | null

  • ads_txt string | null

  • app_ads_txt string | null

  • show_resources_publicly boolean

Respostas
  • 200

    The updated company.

  • 401

    The key is missing, invalid, revoked or its account is suspended.

  • 404

    No such record in this account.

  • 422

    The request is invalid. errors lists the messages per field.

  • 429

    More than 60 requests in a minute with this key.

curl -X PATCH "https://freeprivacypolicy.app/api/v1/companies/42" \
  -H "Authorization: Bearer $FPP_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "app_ads_txt": "google.com, pub-1234567890123456, DIRECT, f08c47fec0942fa0\napplovin.com, 0123456789abcdef, DIRECT"
}'
Corpo da requisição: Replace the app-ads.txt lines
{
    "app_ads_txt": "google.com, pub-1234567890123456, DIRECT, f08c47fec0942fa0\napplovin.com, 0123456789abcdef, DIRECT"
}
Resposta 200
{
    "data": {
        "id": 42,
        "company_name": "Acme Labs Ltd.",
        "email": "[email protected]",
        "address": "1 Market Street, Lisbon, Portugal",
        "about": "Acme Labs builds productivity apps for small teams.",
        "ads_txt": "google.com, pub-1234567890123456, DIRECT, f08c47fec0942fa0",
        "app_ads_txt": "google.com, pub-1234567890123456, DIRECT, f08c47fec0942fa0",
        "show_resources_publicly": true,
        "logo_url": null,
        "policies_count": 2,
        "created_at": "2026-09-01T12:00:00+00:00",
        "updated_at": "2026-09-20T08:30:00+00:00"
    }
}

Delete a company

DELETE /companies/{id}

Deletes the company with its logo and its ads.txt and app-ads.txt lines. Policies that used it stay online without a company, using the contact details saved with them.

Parâmetros
  • id integer em path obrigatório

    The company id.

Respostas
  • 204

    Deleted.

  • 401

    The key is missing, invalid, revoked or its account is suspended.

  • 404

    No such record in this account.

  • 429

    More than 60 requests in a minute with this key.

curl -X DELETE "https://freeprivacypolicy.app/api/v1/companies/42" \
  -H "Authorization: Bearer $FPP_API_KEY" \
  -H "Accept: application/json"

204 não tem corpo.

Erros

Erros são JSON com um message. Erros de validação adicionam errors, indexado por campo.

Status Quando
401 Não autenticado A chave está ausente, incorreta, foi substituída por uma mais nova ou a conta dela está suspensa. Crie uma nova chave e atualize o seu segredo.
404 Não encontrado Não existe nesta conta nenhuma política ou empresa com esse slug ou id. Liste seus registros com GET /policies ou GET /companies.
422 Falha na validação Um campo está ausente ou é inválido. errors lista as mensagens por campo. Confira as chaves em GET /options.
429 Requisições demais Mais de 60 requisições em um minuto com a mesma chave. Aguarde os segundos indicados em Retry-After e tente de novo.
5xx Erro do servidor Algo falhou do nosso lado. Tente de novo com um intervalo crescente. Antes de repetir um POST, confira com um GET se ele não foi processado.
Resposta 422
{
    "message": "The selected product type is invalid.",
    "errors": {
        "product_type": [
            "The selected product type is invalid."
        ]
    }
}

Paginação e limites

  • As listas são paginadas. GET /policies e GET /companies aceitam page e per_page (1 a 100, padrão 25).
  • Siga links.next até que seja null. meta.total conta todos os registros.
  • 60 requisições por minuto por chave. Um 429 informa quanto tempo esperar em Retry-After.
  • Somente JSON. Envie Accept: application/json e, quando houver corpo, Content-Type: application/json.
GET /policies
{
    "data": [
        "…"
    ],
    "links": {
        "first": "https://freeprivacypolicy.app/api/v1/policies?page=1",
        "last": "https://freeprivacypolicy.app/api/v1/policies?page=3",
        "prev": null,
        "next": "https://freeprivacypolicy.app/api/v1/policies?page=2"
    },
    "meta": {
        "current_page": 1,
        "from": 1,
        "last_page": 3,
        "path": "https://freeprivacypolicy.app/api/v1/policies",
        "per_page": 25,
        "to": 25,
        "total": 61
    }
}

Versionamento e mudanças

A versão fica no caminho: /api/v1. Dentro da v1 só adicionamos coisas, como novos campos, novos endpoints e novos serviços ou seções em GET /options, então ignore os campos que você não conhece. Uma mudança que possa quebrar um cliente sai como /api/v2, com a v1 mantida em funcionamento.

  1. 1.0.0, setembro 2026

    Chaves pessoais de todas as contas, compartilhadas com o servidor MCP. Novidades: GET /me, GET /options, listagem e exclusão de políticas, company_id e published nas políticas e os endpoints de empresas.