# Developer Platform

Welcome to your team’s developer platform

<h2 align="center">ToS;DR Documentation</h2>

<p align="center">Welcome to the ToS;DR Documentation!</p>

<table data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><i class="fa-book-open">:book-open:</i></td><td>Documentation</td><td>How-To's, Non-Developer resources.</td><td><a href="/spaces/WfdmHZOEGPuFLotizO3c">/spaces/WfdmHZOEGPuFLotizO3c</a></td></tr><tr><td><h4><i class="fa-book">:book:</i></h4></td><td><strong>Site Policy</strong></td><td>Read all policies regarding ToS;DR</td><td><a href="/spaces/9kp7gNxyfP6a2S1Xzi72">/spaces/9kp7gNxyfP6a2S1Xzi72</a></td></tr><tr><td><h4><i class="fa-brackets-curly">:brackets-curly:</i></h4></td><td><strong>Developer</strong></td><td>Learn more about our systems and how to use our APIs.</td><td><a href="/spaces/o2hfDXWiqOOxeRqBMeiO">/spaces/o2hfDXWiqOOxeRqBMeiO</a></td></tr><tr><td><i class="fa-pen">:pen:</i></td><td><strong>Phoenix</strong></td><td>Learn more about Phoenix, our editing platform.</td><td><a href="/spaces/3UVAu5jaPYNy6ClkobBc">/spaces/3UVAu5jaPYNy6ClkobBc</a></td></tr></tbody></table>

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th></th><th></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td><h4><i class="fa-tower-broadcast">:tower-broadcast:</i></h4></td><td><strong>ToS;DR Communities</strong></td><td>Join one of our communities to discuss all things ToS;DR!</td><td><a href="https://tosdr.org/en/sites/communities" class="button secondary">Join</a></td><td></td></tr><tr><td><h4><i class="fa-heart">:heart:</i></h4></td><td><strong>Contribute</strong></td><td>ToS;DR needs contributers like you to stay alive. Consider creating PRs or helping us on Phoenix!</td><td><a href="https://github.com/tosdr" class="button secondary">Submit a PR</a></td><td></td></tr></tbody></table>


# Welcome to the ToS;DR Documentation

Here we offer some how-to guides, resources and more to help you efficiently use ToS;DR!

If you are looking for the Developer Documentation, please [click here!](https://docs.tosdr.org/developer/)

### Jump right in

<table data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><h4><i class="fa-laptop-arrow-down">:laptop-arrow-down:</i></h4></td><td><strong>Install Extension on macOS</strong></td><td>Learn how to install the macOS Safari Extension, step-by-step!</td><td></td><td></td><td><a href="/pages/QPzbTvC6XsT5gERiU43E">/pages/QPzbTvC6XsT5gERiU43E</a></td></tr></tbody></table>


# How to install the Safari Extension on macOS

Learn how to install the Safari Extension on macOS

## How-To Video

{% embed url="<https://assets.tosdr.org/docs/tosdr-instructions.mp4>" %}

## Written Instructions

1. Install the ToS;DR App from the [App Store](https://apps.apple.com/en/app/tos-dr/id6470998202?l=en-GB).
2. Open the app and go through the initial setup.
3. Once you are on the main screen, open Safari.
4. In Safari, under "Safari - Settings - Extensions" toggle on ToS;DR.
5. The database should download and you should be greeted by the extensions settings page.

## FAQ

1. Question: Why does the ToS;DR Extension ask for so many permissions?

> See [Browser Extension FAQ](/documentation/faq/browser-extension-faq) for more details.


# Browser Extension FAQ

Commonly asked questions regarding the browser extension answered!

1. Why does the ToS;DR Browser Extension ask for so many permissions, like reading every visited website's data?

> ToS;DR requires the permission to read website's data to fetch the URL of the site you are currently on. All website content is not visible to us in any way. You can verify this behavior by browsing through our browser extensions [source code](https://github.com/tosdr/browser-extensions).

2. Does ToS;DR send a server request for every website I visit?

> No. The ToS;DR extension comes with a built-in database of all rated services and their URLs, so it can locally check the sites you visit without contacting our servers. A request is only made when you actively interact with the extension to view details. Even then, we don’t send the full URL—just the domain. For example, `drive.google.com/drive?...` would be reduced to `drive.google.com`.


# Welcome!

Welcome to our site policies!

This space includes our rules on how to behave in official ToS;DR Groups, our Privacy Policies, Terms of Use and more.

Questions? [Reach out to us!](mailto:team@tosdr.org)


# Community Etiquette

ToS;DR strives to be an all-inclusive community for all ages, ethnicities, and genders. To achieve this goal, we maintain a set of ground rules split into **requirements** and **suggestions**.

## Rules

### Requirements

1. **Treat others with respect.** Always remember you are talking to another person.
2. **Respect other people's opinions.** Differing views are welcome, and it is fine to point out when someone is being extreme.
3. **Do not push your narrative.** Opinions are accepted, but making others feel bad or forcing your view on them will be penalized.
4. **Anything that is illegal in your country is illegal here.** Severe violations can be reported to authorities.
5. **Spam is not okay.** Multiple messages are fine when they are essential to the topic, but repeating the same message is not.
6. **Do not DM others without permission.** Exceptions apply to moderators or team members if they are online and not set to “Do not Disturb”.
7. **Hate speech is not tolerated.** Keep harmful opinions—especially those targeting minorities—out of our spaces.
8. **Do not impersonate anyone.** Even joking impersonations can be harmful.
9. **Follow the Discord** [**Community Guidelines**](https://discord.com/guidelines) when you are on Discord.

### Suggestions

1. **Avoid texting when you have had a really bad day.** It is easy to sound agitated and make others uncomfortable.
2. **Stay open to new opinions.**
3. **Be kind.**

## Appealing

Follow these steps if you believe a ban should be reconsidered:

* **Mistreatment / disrespecting opinions:** Apologise to the people involved. A reinstatement is not guaranteed if moderators consider the apology insincere or you are a repeat offender.
* **DMing without permission:** Apologise to the recipient and explain what you will do differently in the future.
* **Spam:**
  * Automated spam will remain banned.
  * For human mistakes, a simple “sorry, it will not happen again” is usually enough.


# tosdr.org Terms of Contribution

Thank you for contributing! We need you to license your contributions under free and open licenses.

**Copyright**\
By contributing to this project (e.g. by sending an email or by submitting through our interfaces), you agree – unless simultaneously and expressly stated otherwise – that

your contribution may be included in the source code of ToS;DR and published under the following copyright license: [CC BY-SA 3.0](http://creativecommons.org/licenses/by-sa/3.0/) (or any later version approved by more than 50% of voting contributors) with a special exception to allow distribution in a "larger program" under the [GNU AGPL-3.0](http://www.gnu.org/licenses/agpl-3.0-standalone.html) or later.

* <http://creativecommons.org/licenses/by-sa/3.0/>
* <http://www.gnu.org/licenses/agpl-3.0-standalone.html>

**Definition of contributor**\
A "contributor" is any person, excluding legal persons (e.g. corporations), who wrote at least one email to the group at least 90 days before the start of the poll.

**Changes**\
to these terms shall be approved by more than 70% of voting contributors.

**Votes**\
All polls shall be organized by a Contributor announcing the intention to create a poll to the public email group. The poll shall occur if not less than three people agree to a vote using the final text of the given poll within a seven day period of the final text being posted. The poll shall take place and be officiated by a Team member no less than 10 days from a poll being organized, and no more than 25 days. Team members maintain special privilege to call a poll at any time as long as said poll is announced no less than 10 days prior. No poll shall be valid if less than three Contributors cast votes.

**Definition of Team member**\
A Team member is any person, excluding legal persons, who is listed on the team page of the project website, or who has been granted write access to the project's source code repository.


# tosdr.org Privacy Policy

We only use cookies to store your language, theme preferences or sessions and not any tracking technology.

We anonymize all IP addresses in our nginx logs, but store them for up to 1 day in our Redis Ratelimiting server.

Your IP address will temporarily be visible in to Netcup who provide infrastructure.

We employ anonymized IP logging, this means nginx collects web requests but anonymizes IPs in the process.

(Private IP used in the example below)

```
192.115.194.0 - - [01/May/2021:08:21:12 +0200] "GET /api/1/all.json HTTP/2.0" 200 753375 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0" "-"
```

Your IP may be stored temporarily in our Redis Cache in order to enforce rate limits.

The only time your IP Address is stored in logs without any path or user agent is to block malicious IPs using fail2ban:

```
log_format fail2ban '$remote_addr [$time_local] $status';
```

For our assets such as logos, branding images we use a selfhosted S3: Minio.

Our forum software is self hosted using Discourse

#### Nginx IP logging configuration <a href="#tosdr.orgprivacypolicy-nginxiploggingconfiguration" id="tosdr.orgprivacypolicy-nginxiploggingconfiguration"></a>

```
map $remote_addr $ip_anonym1 {
    default 0.0.0;
    "~(?P<ip>(\d+)\.(\d+)\.(\d+))\.\d+" $ip;
    "~(?P<ip>[^:]+:[^:]+):" $ip;
}

map $remote_addr $ip_anonym2 {
    default .0;
    "~(?P<ip>(\d+)\.(\d+)\.(\d+))\.\d+" .0;
    "~(?P<ip>[^:]+:[^:]+):" ::;
}

map $ip_anonym1$ip_anonym2 $ip_anonymized {
    default 0.0.0.0;
    "~(?P<ip>.*)" $ip;
}

log_format anonymized '$ip_anonymized - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent '
                    '"$http_user_agent" "$http_x_forwarded_for"';

log_format fail2ban '$remote_addr [$time_local] $status';
access_log  /var/log/nginx/access.log  anonymized;
access_log  /var/log/nginx/access-f2b.log  fail2ban;
```


# ToS;DR Security Policy

* [Reporting a Vulnerability](#Reporting-a-Vulnerability)
* [Security Announcements](#Security-Announcements)
* [Acknowledgements](#Acknowledgements)

### Reporting a Vulnerability <a href="#tos-drsecuritypolicy-reportingavulnerability" id="tos-drsecuritypolicy-reportingavulnerability"></a>

If you think you've identified a security issue in any ToS;DR Project, please\
**do not** report the issue publicly via a mailing list, IRC, a public issue on\
our issue trackers, a merge request, or any other public venue.

Instead, report a\
[Security Vulnerability via Service Desk](https://security.tosdr.org) or via email to <security@tosdr.org>. Please include as many\
details as possible, including a minimal reproducible example of the issue, and\
an idea of how exploitable/severe you think it is.

**Do not** provide a merge request to fix the issue, as there is currently no\
way to make confidential merge requests on <http://github.com> .

If you have patches which fix the security issue, please attach them to your security vulnerability report as\
patch files.

Security vulnerability reports are only visible to the reporter and the ToS;DR Staff.

The next steps are then:

* The report is triaged.
* Code is audited to find any potential similar problems.
* The fix is prepared for the most recent stable branch.
* The fix is submitted to the public repository.
* On the day the issue and fix are made public, an announcement is made on the\
  [public channels listed below](#Security-Announcements).
* The fix will be deployed into production.

### Security Announcements <a href="#tos-drsecuritypolicy-securityannouncements" id="tos-drsecuritypolicy-securityannouncements"></a>

Security announcements are made publicly via the [Confluence Docs](https://tosdrconfluence.atlassian.net/wiki/label/NEWS/security).

### Acknowledgements <a href="#tos-drsecuritypolicy-acknowledgements" id="tos-drsecuritypolicy-acknowledgements"></a>

This text was partially based on the\
[github.com/containers security policy](https://github.com/containers/common/blob/master/SECURITY.md),\
[flatpak security policy](https://github.com/flatpak/flatpak/blob/master/SECURITY.md),\
[gnome security policy](https://gitlab.gnome.org/GNOME/glib/-/blob/master/SECURITY.md).


# Security Vulnerability Safe Harbor

#### Summary <a href="#securityvulnerabilitysafeharbor-summary" id="securityvulnerabilitysafeharbor-summary"></a>

1. We want you to responsibly disclose through our security vulnerability program, and don't want researchers put in fear of legal consequences because of their good faith attempts to comply with our Security Vulnerability Safe Harbor policy. We cannot bind any third party, so do not assume this protection extends to any third party. If in doubt, ask us before engaging in any specific action you think *might* go outside the bounds of our policy.
2. Because both identifying and non-identifying information can put a researcher at risk, we limit what we share with third parties. We may provide non-identifying substantive information from your report to an affected third party, but only after notifying you and receiving a commitment that the third party will not pursue legal action against you. We will only share identifying information (name, email address, phone number, etc.) with a third party if you give your written permission.
3. If your security research as part of the Security Vulnerability program violates certain restrictions in our site policies, the safe harbor terms permit a limited exemption.
4. Never attempt non-technical attacks such as social engineering, phishing, or physical attacks against our employees, users, or infrastructure.
5. When in doubt, contact us at [`team@tosdr.org`](mailto:team@tosdr.org)
6. Only test for vulnerabilities on sites you know to be operated by ToS;DR and are supported. Some sites hosted on subdomains of tosdr.org, tosback.com, tosback.org or tosback.net are operated by third parties and should not be tested.

#### Performing your research <a href="#securityvulnerabilitysafeharbor-performingyourresearch" id="securityvulnerabilitysafeharbor-performingyourresearch"></a>

* Do not impact other users with your testing, this includes testing vulnerabilities in repositories or organizations you do not own. If you are attempting to find an authorization bypass, you must use accounts you own.
* The following are **never** allowed. We may suspend your ToS;DR accounts and ban your IP address for:
  * Performing distributed denial of service (DDoS) or other volumetric attacks
  * Spamming content
  * Large-scale vulnerability scanners, scrapers, or automated tools which produce excessive amounts of traffic.
    * Note: We do allow the use of automated tools so long as they do not produce excessive amounts of traffic. For example, running one `nmap` scan against one host is allowed, but sending 65,000 requests in two minutes using Burp Suite Intruder is excessive.
* Researching denial-of-service attacks is allowed only if you follow these rules:
  * There are no limits for researching denial of service vulnerabilities against your own instance of CrispCMS, Phoenix, Tosback or our crawler. We strongly recommend/prefer this method for researching denial of service issues. If you have no ability to self-host our services, we provide staging environments you can test on.<br>
    * CrispCMS - staging.tosdr.org
    * API - api.staging.tosdr.org
    * Phoenix - edit.staging.tosdr.org
    * Shields - shields.staging.tosdr.org
  * If you choose to test on our production environment<br>
    * Stop **immediately** if you believe you have affected the availability of our services. Don't worry about demonstrating the full impact of your vulnerability, ToS;DR's team will be able to determine the impact.

#### Handling personally identifiable information (PII) <a href="#securityvulnerabilitysafeharbor-handlingpersonallyidentifiableinformation-pii" id="securityvulnerabilitysafeharbor-handlingpersonallyidentifiableinformation-pii"></a>

* Personally identifying information (PII) includes:
  * legal and/or full names
  * names or usernames combined with other identifiers like phone numbers or email addresses
  * health or financial information (including insurance information, social security numbers, etc.)
  * information about political or religious affiliations
  * information about race, ethnicity, sexual orientation, gender, or other identifying information that could be used for discriminatory purposes
* Do not intentionally access others' PII. If you suspect a service provides access to PII, limit queries to your own personal information.
* Report the vulnerability *immediately* and do not attempt to access any other data. The ToS;DR team will assess the scope and impact of the PII exposure.
* Limit the amount of data returned from services. For SQL injection, for example, limit the number of rows returned
* You must delete all your local, stored, or cached copies of data containing PII as soon as possible. We may ask you to sign a certificate of deletion and confidentiality agreement regarding the exact information you accessed.
* We may ask you for the usernames and IP addresses used during your testing to assess the impact of the vulnerability

#### 1. Safe Harbor Terms <a href="#securityvulnerabilitysafeharbor-1.safeharborterms" id="securityvulnerabilitysafeharbor-1.safeharborterms"></a>

To encourage research and responsible disclosure of security vulnerabilities, we will not pursue civil or criminal action, or send notice to law enforcement for accidental or good faith violations of this policy. We consider security research and vulnerability disclosure activities conducted consistent with this policy to be “authorized” conduct under the Computer Fraud and Abuse Act, the DMCA, and other applicable computer use laws such as Cal. Penal Code 502(c). We waive any potential DMCA claim against you for circumventing the technological measures we have used to protect the applications in this security vulnerability program's scope.

Please understand that if your security research involves the networks, systems, information, applications, products, or services of a third party (which is not us), we cannot bind that third party, and they may pursue legal action or law enforcement notice. We cannot and do not authorize security research in the name of other entities, and cannot in any way offer to defend, indemnify, or otherwise protect you from any third party action based on your actions.

You are expected, as always, to comply with all laws applicable to you, and not to disrupt or compromise any data beyond what this security vulnerability program permits.

Please contact us before engaging in conduct that may be inconsistent with or unaddressed by this policy. We reserve the sole right to make the determination of whether a violation of this policy is accidental or in good faith, and proactive contact to us before engaging in any action is a significant factor in that decision. If in doubt, ask us first!

#### 2. Third Party Safe Harbor <a href="#securityvulnerabilitysafeharbor-2.thirdpartysafeharbor" id="securityvulnerabilitysafeharbor-2.thirdpartysafeharbor"></a>

If you submit a report through our Security Vulnerability program which affects a third party service, we will limit what we share with any affected third party. We may share non-identifying content from your report with an affected third party, but only after notifying you that we intend to do so and getting the third party's written commitment that they will not pursue legal action against you or initiate contact with law enforcement based on your report. We will not share your identifying information with any affected third party without first getting your written permission to do so.

Please note that we cannot authorize out-of-scope testing in the name of third parties, and such testing is beyond the scope of our policy. Refer to that third party's safe harbor policy, if they have one, or contact the third party either directly or through a legal representative before initiating any testing on that third party or their services. This is not, and should not be understood as, any agreement on our part to defend, indemnify, or otherwise protect you from any third party action based on your actions.

That said, if legal action is initiated by a third party, including law enforcement, against you because of your participation in this security vulnerability program, and you have sufficiently complied with our safe harbor policy (i.e. have not made intentional or bad faith violations), we will take steps to make it known that your actions were conducted in compliance with this policy. While we consider submitted reports both confidential and potentially privileged documents, and protected from compelled disclosure in most circumstances, please be aware that a court could, despite our objections, order us to share information with a third party.

#### 3. Limited Waiver of Other Site Polices <a href="#securityvulnerabilitysafeharbor-3.limitedwaiverofothersitepolices" id="securityvulnerabilitysafeharbor-3.limitedwaiverofothersitepolices"></a>

To the extent that your security research activities are inconsistent with certain restrictions in our [relevant legal policy](https://tosdr.org/legal) but consistent with the terms of our security vulnerability program, we waive those restrictions for the sole and limited purpose of permitting your security research under this security vulnerability program. Just like above, if in doubt, ask us first!


# ToS;DR Sponsorship Independence Disclosure

ToS;DR is a not-for-profit organization that primarily relies on the contributions of volunteers, as well as donations, sponsorships, and similar support to sustain our operations. These financial contributions help us continue our work, but they do not influence our ratings or assessment criteria in any way.

Sponsorship does not imply endorsement, nor should our list of sponsors be considered a guarantee that their services align with all aspects of digital rights, such as privacy, data portability, or freedom from network lock-in. While we do not partner with companies we believe to be fundamentally harmful to user rights, sponsorship should not be seen as a certification of their policies or practices.

Our commitment remains to providing independent and unbiased evaluations of online services.

For transparency, we list all of our past and current sponsors, starting in mid-2024.

#### Current Sponsorships: <a href="#tos-drsponsorshipindependencedisclosure-currentsponsorships" id="tos-drsponsorshipindependencedisclosure-currentsponsorships"></a>

* Fastly
* Betterstack
* Atlassian
* Startmail
* GitBook

#### Past Sponsorships: <a href="#tos-drsponsorshipindependencedisclosure-pastsponsorships" id="tos-drsponsorshipindependencedisclosure-pastsponsorships"></a>

* JetBrains
* DuckDuckGo
* Google Entrepreneurship


# Browser Extension Privacy

## Below is our extension privacy policy <a href="#browserextensionprivacy-belowisourextensionprivacypolicy" id="browserextensionprivacy-belowisourextensionprivacypolicy"></a>

Upon loading the extension, we retrieve a single json file containing all services and their respective urls from our API.

Additionally, when opening a popup the service data gets retrieved with all points and documents in it.

We also check for extension updates by calling the same service DB API which is hosted on the same API server.

The extension also displays hyperlinks to our website, but that will not affect your privacy if you don't actively click on them.

Other than that, installing this extensions does not expose information to us or to any of the websites you visit.

Your IP address will temporarily be visible in to Netcup who provide infrastructure.

We employ anonymized IP logging, this means nginx collects web requests but anonymizes IPs in the process

(Private IP used in the example below)

```
192.115.194.0 - - [01/May/2021:08:21:12 +0200] "GET /api/1/all.json HTTP/2.0" 200 753375 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0" "-"
```

Your IP may be stored temporarily in our Redis Cache in order to enforce rate limits.

For our assets such as logos, branding images we use a selfhosted S3: Minio.

#### Nginx IP logging configuration <a href="#browserextensionprivacy-nginxiploggingconfiguration" id="browserextensionprivacy-nginxiploggingconfiguration"></a>

```
map $remote_addr $ip_anonym1 {
    default 0.0.0;
    "~(?P<ip>(\d+)\.(\d+)\.(\d+))\.\d+" $ip;
    "~(?P<ip>[^:]+:[^:]+):" $ip;
}

map $remote_addr $ip_anonym2 {
    default .0;
    "~(?P<ip>(\d+)\.(\d+)\.(\d+))\.\d+" .0;
    "~(?P<ip>[^:]+:[^:]+):" ::;
}

map $ip_anonym1$ip_anonym2 $ip_anonymized {
    default 0.0.0.0;
    "~(?P<ip>.*)" $ip;
}

log_format anonymized '$ip_anonymized - $remote_user [$time_local] ' 
                      '"$request" $status $body_bytes_sent ' 
                      '"$http_referer" "$http_user_agent"';
access_log  /var/log/nginx/access.log  anonymized;
```


# AI Policy

In the context of artificial intelligence systems such as large language models (LLMs), we have established a policy to be followed internally and by anyone who wishes to contribute to ToS;DR.

## Permitted use of AI

You may use AI tools for coding and for creating pull requests or patches across all of our codebases. Any such use **must be disclosed in your pull request**, without exception.

This requirement is not intended to shame or penalize contributors. Rather, it allows us to dedicate appropriate time to thoroughly reviewing and testing the changes, ensuring they behave as intended, are reliable, and meet our code quality standards.

You do **not** need to disclose AI usage when relying solely on code completion tools (such as GitHub Copilot).

**Rule of thumb:** if more than 20% of the work was generated by AI, it must be attributed.

## AI and ML inside ToS;DR

Reviewing and interpreting terms of service and privacy policies is a sensitive task that requires careful human judgment and expertise. While we embrace careful and deliberate use of AI tools to help with the tedious parts of analysis, we take seriously their unreliability and won't jeopardize our user's trust through over-reliance. Therefore we will *not*:

1. Publish official ToS;DR grades and analysis points that have not gone through human review
2. Use generative LLMs to directly summarize privacy policies
3. Use LLMs or machine learning as part of our analyses without publishing technical details, and open-sourcing the code

## DocBot — our ML analysis tool

Internally we have developed and deployed a machine learning tool, called DocBot, to help us with the first step of analyzing privacy documents -- highlighting [cases](https://edit.tosdr.org/cases/) that a user might want to know about a particular service.

All outputs generated by DocBot are always reviewed by humans before being included in the grading formula for official ToS;DR grades. Reviews are carried out by a small, trusted group of contributors with proven expertise in evaluating terms of service and privacy policies. This human-in-the-loop process ensures accuracy, consistency, and reliability, while maintaining the high standards our users expect from ToS;DR.

For technical details on DocBot, you can read a [blog post here](https://www.soundsandwords.io/privacy-policies/) from its developer, Evan Radkoff


# edit.tosdr.org Terms of Service

Nothing here should be considered legal advice. We express our opinion with no guarantee and we do not endorse any service in any way. Please refer to a qualified attorney for legal advice. Reading ToS;DR is in no way a replacement for reading the full terms to which you are bound.\
**Disclosure**: our list of donors and supporters is [public](https://tosdr.org/thanks.html).


# edit.tosdr.org Privacy Policy

When you log in, you need to use at least an email and a password. Nicknames are optional. Passwords are hashed in our database with the bcrypt algorithm. When cancelling your account, we scramble your data in our database so you cannot recover your account and we don't lose your contributions.

**Cookies**

We only use first party cookies. These cookies are used to store your login information (*i.e. When you tick the **remember** box*).\
A cookie is a small file containing a string of characters that is sent to your computer when you visit a website. When you visit the site again, the cookie allows that site to recognize your browser. Cookies may store user preferences and other information. *You can configure your browser to refuse all cookies or to indicate when a cookie is being sent*.\
Disabling cookies will only affect your login attempts, but other features of the site will remain unaffected.\
**We do not sell your data**.\
**We do not use third party trackers/cookies for the use of this site**.\
**We do not track you**.


# Data Breach Post-Mortem 28th of July, 2026

On the 28th of July 2026, at around 14:00 CET, we found a dump of our production database checked into GitHub, uploaded in 2018. After some hours, we checked inside the dump and found that it contained real user data. 370 users are affected, with their email, password hash and IP address being affected.

We understand 8 years is a long time to not catch this, the only reason we did is because we were approved in the Claude Cybersecurity program, and we scanned our repository Phoenix for issues, where it was flagged. It was in a stale branch, hence why it was not caught earlier. Never checked into Master.

Upon realizing the scale of the problem, we immediately reset all affected user passwords and contacted the Autoriteit Persoonsgegevens (the Dutch Data Protection Authority) as mandated by law. To protect our users and ensure the public exposure was fully resolved before drawing further attention to the incident, emails were sent to affected individuals after the file was permanently secured. Because the data had been publicly accessible over an eight-year period, we are unable to determine the precise extent of exposure during that time.

For transparency, here is a rough timeline of events:

28.07.2026 - 14:00 CET: Claude flagged the exposed credentials in the stale branch, the affected branch has been deleted.&#x20;

29.07.2026 - 16:42 CET: The Autoriteit Persoonsgegevens (NL) has been notified.&#x20;

30.07.2026 - 09:33 CET: We have made contact with GitHub to get the exposed credentials removed from caches and forks.&#x20;

15.08.2026: GitHub has removed all forks of Phoenix and emailed everyone that had forked us about the breach. Blob Caches have yet to be deleted.&#x20;

17.08.2026 - 11:13 CET: We have made the Repository edit.tosdr.org private to prevent further exposure, this resulted in a purge of the blob cache as well. The direct reference to the file came up with a 404 (Not Found).

We have also sent everyone affected the following mail:

```
Dear ToS;DR contributor,

We’re sorry to let you know that a subset of personal data, including yours, had been accidentally leaked on a development platform for edit.tosdr.org (also known as Phoenix). The data that was disclosed, while not directly readable or searchable, included the email address you used to contribute to edit.tosdr.org in 2018; IP addresses of your connections at the time, as well as a cryptographic hash of your password. This means that your password itself was not disclosed. However as a security measure, your account password has been reset on edit.tosdr.org to mitigate any attempts to sign in with previous credentials.

More details below or at: https://docs.tosdr.org/site-policy/post-mortems/data-breach-post-mortem-28th-of-july-2026

What you can do next:

We’ve already taken all steps available to us to mitigate this accidental leak as soon as we became aware of it (see further below for details). 
If you want to use Phoenix again, the system will ask you to set a new password for your account. There is nothing else required of you as such, and we’ve ensured removal of the leak from publicly available records that we were aware of. However as good measures of precaution we recommend the following:

- Review the passwords you use elsewhere to ensure that if you might have reused them, you should also reset your credentials where relevant
- Be careful and look out for phishing emails posing as ToS;DR. We will NEVER ask for your password. 

And of course the ToS;DR team remains fully available if you have any questions or need any assistance to help secure your account. You can send us a mail to team@tosdr.org for help.

Details of what happened:
On 28 July 2026, we used a new tool for scanning our codebases for security vulnerabilities, and it found that 8 years ago, a member of the development team accidentally disclosed a copy of our production database (as a “dump” file) to the publicly available source code repository at GitHub. This database dump notably contained details of 370 contributors to edit.tosdr.org including: email address of their account, alongside a hashed version of their password and the IP address used to connect. 
The reason it took so long to be found is because it was in a stale branch not part of the active development, so no one had it on their radar.

What we’ve done since discovery:
Since discovery on 28 July 2026, our initial actions have been to assess the extent of the leak and address it wherever we could to stop it. We’ve also immediately reset the impacted passwords.

Given the leak was first disclosed via GitHub, we’ve filed multiple security reports per their processes to purge the accidental leak from available repositories, including forks controlled by other users of GitHub not part of the ToS;DR team using take-down notices for exposed credentials. As far as our knowledge, they have all been removed.

As per our legal obligation, we've filed a report on this situation to the Autoriteit Persoonsgegevens, the Netherlands’ Data Protection Authority on 29 July. We’re following up with them as progress is being made.

We are looking at more ways to prevent this from happening again through automated scanning and pre-commit checks. You can follow this process along on our GitHub.

We really want to make sure this never happens again, and have published a public post-mortem (https://docs.tosdr.org/site-policy/post-mortems/data-breach-post-mortem-28th-of-july-2026) with the steps we are taking to make sure. We will continue to update that page as the situation develops if anything relevant comes up. 

We’re sincerely sorry for all this. While we believe this was an honest mistake by a well-intended contributor - whom we thank for many important contributions to the project - we wish we’d identified this error sooner. This isn’t the high standard we hold ourselves to, but ToS;DR remains a small and benevolent project run by volunteers around the world and we welcome good-faith contributors from all around the world regardless of background.
The current development team will continue its efforts to improve the security of our processes and help ensure this kind of event does not happen again. 

Feel free to email us at team@tosdr.org if you have any further questions.

the ToS;DR team
```

We were in contact with GitHub early on to request the removal of the affected data. However, their standard process included notifying all fork owners of the incident and providing specific details, including the branch name, filename, and commit hash.

Dump files are already ignored, and this has been standard procedure at ToS;DR for years; unfortunately, it was missed during early development cycles. In the future, we will be making sure all dump file formats, such as .dump, are added to .gitignore across all of our repositories that might be created in the future, and I will personally brief the entire development team to be more careful before pushing. Our systems were not affected and are still secure, we will do our best to protect your current data and make sure that it never gets released.

Thank you for reading, and we are sorry this happened.

Erik from ToS;DR


# Branding

Branding Guidelines/Infographics

### Typography <a href="#brandingguidelines-infographics-typography" id="brandingguidelines-infographics-typography"></a>

***

#### Font <a href="#brandingguidelines-infographics-font" id="brandingguidelines-infographics-font"></a>

![](/files/GBVDqoVIxOlN41x385MK)

**Header**

**Subheader**

### Color Guide <a href="#brandingguidelines-infographics-colorguide" id="brandingguidelines-infographics-colorguide"></a>

***

![](/files/auuTqwcL5giPo51O3h9X)

### Logo Variations <a href="#brandingguidelines-infographics-logovariations" id="brandingguidelines-infographics-logovariations"></a>

***

![](/files/BGPI6I2opZKwocRXtgf5)

## [Download Presskit](https://s3.tosdr.org/branding/ToSDR.zip) <a href="#brandingguidelines-infographics-downloadpresskit" id="brandingguidelines-infographics-downloadpresskit"></a>


# Welcome!

Welcome to the Developer Documentation!

This space brings together everything you need to integrate with ToS;DR or run our software yourself.

## What's inside

* [Self-Hosting Phoenix](/developer/self-hosting-phoenix) — current notes on deploying your own Phoenix instance, plus supporting material such as [useful SQL queries](/developer/self-hosting-phoenix/useful-sql-queries).
* [ToS;DR Developers](/developer/tos-dr-developers) — API reference material for interacting with our public services.

## Get involved

We welcome improvements to the tooling and the documentation itself. If you already know your way around the project, consider [contributing](https://github.com/tosdr).


# Self-Hosting Phoenix

This section is a work in progress. For now it gathers notes that support running your own Phoenix instance, including [useful SQL queries](/developer/self-hosting-phoenix/useful-sql-queries) collected by the team.


# Useful SQL Queries

This Page is more or less targeted at ToS;DR Staff with access to Production or Staging Databases.

Though they may be useful for anyone self hosting Phoenix as well.

* [Top 10 Services with most approved points](#UsefulSQLQueries-Top10Serviceswithmostapprovedpoints)
* [Get amount of services a rating has](#UsefulSQLQueries-Getamountofservicesaratinghas)
  * [Excluding N/A Ratings](#UsefulSQLQueries-ExcludingN/ARatings)
* [Top 10 Services on ToS;DR with the “highest” possible rating.](#UsefulSQLQueries-Top10ServicesonToS;DRwiththe“highest”possiblerating.)
* [Top 10 Services on ToS;DR with the “worst” possible rating.](#UsefulSQLQueries-Top10ServicesonToS;DRwiththe“worst”possiblerating.)

### Top 10 Services with most approved points <a href="#usefulsqlqueries-top10serviceswithmostapprovedpoints" id="usefulsqlqueries-top10serviceswithmostapprovedpoints"></a>

```
SELECT COUNT(POINTS.ID) AS POINTSUM,
	SERVICES.NAME As SERVICENAME,
	SERVICES.RATING
FROM POINTS
INNER JOIN SERVICES ON POINTS.SERVICE_ID = SERVICES.ID
WHERE POINTS.STATUS = 'approved'
GROUP BY SERVICES.ID
ORDER BY POINTSUM DESC
LIMIT 10
```

### Get amount of services a rating has <a href="#usefulsqlqueries-getamountofservicesaratinghas" id="usefulsqlqueries-getamountofservicesaratinghas"></a>

```
SELECT COUNT(RATING) AS AMOUNT,
	RATING,
	CONCAT((COUNT(RATING) * 100 /
										(SELECT COUNT(RATING)
											FROM SERVICES
											WHERE RATING IS NOT NULL )), '%') AS PERCENTAGE
FROM SERVICES
WHERE RATING IS NOT NULL
GROUP BY RATING
ORDER BY RATING ASC;
```

#### Excluding N/A Ratings <a href="#usefulsqlqueries-excludingn-aratings" id="usefulsqlqueries-excludingn-aratings"></a>

```
SELECT COUNT(RATING) AS AMOUNT,
	RATING,
	CONCAT((COUNT(RATING) * 100 /
										(SELECT COUNT(RATING)
											FROM SERVICES
											WHERE RATING IS NOT NULL
												AND RATING != 'N/A')), '%') AS PERCENTAGE
FROM SERVICES
WHERE RATING IS NOT NULL
	AND RATING != 'N/A'
GROUP BY RATING
ORDER BY RATING ASC;
```

### Top 10 Services on ToS;DR with the “highest” possible rating. <a href="#usefulsqlqueries-top10servicesontos-drwiththe-highest-possiblerating" id="usefulsqlqueries-top10servicesontos-drwiththe-highest-possiblerating"></a>

Counts all Services with an “A” rating and the most “good” cases.

```
SELECT SERVICES.NAME,
	SERVICES.RATING,
	COUNT(CASES.CLASSIFICATION) AS AMOUNTGOODCASES
FROM SERVICES
INNER JOIN POINTS ON POINTS.SERVICE_ID = SERVICES.ID
INNER JOIN CASES ON CASES.ID = POINTS.CASE_ID
WHERE SERVICES.RATING = 'A'
    AND POINTS.STATUS = 'approved'
	AND SERVICES.IS_COMPREHENSIVELY_REVIEWED = TRUE
	AND CASES.CLASSIFICATION = 'good'
	AND SERVICES.ID != 969 /* Exluding ToS;DR Phoenix */
	AND SERVICES.ID != 596 /* Excluding ToS;DR */
GROUP BY SERVICES.ID,
	CASES.CLASSIFICATION
ORDER BY AMOUNTGOODCASES DESC
LIMIT 10;
```

### Top 10 Services on ToS;DR with the “worst” possible rating. <a href="#usefulsqlqueries-top10servicesontos-drwiththe-worst-possiblerating" id="usefulsqlqueries-top10servicesontos-drwiththe-worst-possiblerating"></a>

Counts all Services with an “E” rating and the most “bad” and “blocker” cases

```
SELECT SERVICES.NAME,
	SERVICES.RATING,
	COUNT(CASES.CLASSIFICATION) AS AMOUNTBADCASES
FROM SERVICES
INNER JOIN POINTS ON POINTS.SERVICE_ID = SERVICES.ID
INNER JOIN CASES ON CASES.ID = POINTS.CASE_ID
WHERE SERVICES.RATING = 'E'
    AND POINTS.STATUS = 'approved'
	AND SERVICES.IS_COMPREHENSIVELY_REVIEWED = TRUE
	AND (CASES.CLASSIFICATION = 'bad'
						OR CASES.CLASSIFICATION = 'blocker')
GROUP BY SERVICES.ID,
	CASES.CLASSIFICATION
ORDER BY AMOUNTBADCASES DESC
LIMIT 10;
```


# ToS;DR Developers

## Goal

These pages make it easier to integrate ToS;DR within your systems.

## Contents

* [Search](/developer/tos-dr-developers/search)
* [Service](/developer/tos-dr-developers/service)
* [Document](/developer/tos-dr-developers/document)
* [Points](/developer/tos-dr-developers/points)
* [Case](/developer/tos-dr-developers/case)
* [Broken mention](broken://pages/9ca57b49792a093692eb05615a11cfa046d18a46)

## Core team for API

* Erik Hering — Developer
* Evan Radkoff — Developer


# RESTful API

Use these references to work with the REST endpoints offered by ToS;DR.

## Available sections

* [Search API](/developer/tos-dr-developers/restful-api/search-api) — look up services that match a query.
* [Service API](/developer/tos-dr-developers/restful-api/service-api) — retrieve metadata about a specific service.
* [Case API](/developer/tos-dr-developers/restful-api/case-api) — access curated case information.
* [Document API](/developer/tos-dr-developers/restful-api/document-api) — fetch legal documents stored by ToS;DR.
* [Privacy Shields API](/developer/tos-dr-developers/restful-api/privacy-shields-api) — retrieve the SVG rating badge for a service.


# Search API

Use these endpoints to retrieve services that match a query string.

* [GET /search/v5](/developer/tos-dr-developers/restful-api/search-api/get-search-v5)
* [GET /search/v4](/developer/tos-dr-developers/restful-api/search-api/get-search-v4)
* [Previous search versions](/developer/tos-dr-developers/restful-api/search-api/previous-search-versions)


# Previous Search Versions

Historical documentation for search endpoints that have since been replaced.

* [GET /search/v3](/developer/tos-dr-developers/restful-api/search-api/previous-search-versions/get-search-v3) — retrieves services with ElasticSearch queries (only the `query` parameter is supported). Superseded by `GET /search/v4`.
* [GET /search/v2](/developer/tos-dr-developers/restful-api/search-api/previous-search-versions/get-search-v2) — searches services from our database in JSON format. Superseded by `GET /search/v3`.


# GET /search/v2

Search for services in JSON format. This version has been superseded by `GET /search/v3`.

## Endpoint

```
https://api.tosdr.org/search/v2/<query>.json
```

## Parameters

| Parameter | Type   | Description       |
| --------- | ------ | ----------------- |
| query     | String | Your search query |

## Global rate limit

| Benefit | Second | Hour   | Day    |
| ------- | ------ | ------ | ------ |
| Guest   | 15     | 1000   | 15000  |
| Staff   | 15000  | 100000 | 150000 |
| Office  | 15000  | 100000 | 150000 |
| Partner | 150    | 10000  | 50000  |

## Implemented error codes

| Error code    |
| ------------- |
| QUERY\_FAILED |

## JSON schema

```
{
    "$schema": "http://json-schema.org/draft-06/schema#",
    "$ref": "#/definitions/Welcome",
    "definitions": {
        "Welcome": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
                "error": {
                    "type": "integer"
                },
                "message": {
                    "type": "string"
                },
                "parameters": {
                    "$ref": "#/definitions/Parameters"
                }
            },
            "required": [],
            "title": "Welcome"
        },
        "Parameters": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
                "service": {
                    "type": "array",
                    "items": {
                        "$ref": "#/definitions/Service"
                    }
                },
                "grid": {
                    "type": "string"
                }
            },
            "required": [],
            "title": "Parameters"
        },
        "Service": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
                "id": {
                    "type": "integer"
                },
                "name": {
                    "type": "string"
                },
                "url": {
                    "type": "string"
                },
                "created_at": {
                    "type": "string"
                },
                "updated_at": {
                    "type": "string"
                },
                "wikipedia": {
                    "anyOf": [
                        {
                            "type": "null"
                        },
                        {
                            "type": "string",
                            "format": "uri",
                            "qt-uri-protocols": [
                                "https"
                            ]
                        }
                    ]
                },
                "keywords": {
                    "type": "string"
                },
                "related": {
                    "type": "string"
                },
                "slug": {
                    "type": "string"
                },
                "is_comprehensively_reviewed": {
                    "type": "boolean"
                },
                "user_id": {
                    "type": "null"
                },
                "rating": {
                    "type": "string"
                },
                "status": {
                    "type": "null"
                },
                "nice_service": {
                    "type": "string"
                },
                "has_image": {
                    "type": "boolean"
                },
                "image": {
                    "type": "string"
                }
            },
            "required": [],
            "title": "Service"
        }
    }
}
```


# GET /search/v3

Retrieve services with ElasticSearch queries. This version only supports the `query` parameter and has been superseded by `GET /search/v4`.

## Endpoint

```
https://api.tosdr.org/search/v3/
```

## Parameters

| Parameter | Type   | Description       |
| --------- | ------ | ----------------- |
| query     | String | The search string |

## Global rate limit

| Benefit | Second | Hour   | Day    |
| ------- | ------ | ------ | ------ |
| Guest   | 15     | 1000   | 15000  |
| Staff   | 15000  | 100000 | 150000 |
| Office  | 15000  | 100000 | 150000 |
| Partner | 150    | 10000  | 50000  |

## Implemented error codes

| Error code    |
| ------------- |
| QUERY\_FAILED |
| WIP           |

## JSON schema

`WIP`


# GET /search/v4

Use this endpoint to retrieve services with a query.

## Endpoint

```
https://api.tosdr.org/search/v4/
```

## Parameters

| Parameter | Type   | Description       |
| --------- | ------ | ----------------- |
| query     | String | The search string |

## Global rate limit

This interface applies the shared platform rate limits shown below. Individual endpoints may define additional limits.

| Benefit | Second | Hour   | Day    |
| ------- | ------ | ------ | ------ |
| Guest   | 15     | 1000   | 15000  |
| Staff   | 15000  | 100000 | 150000 |
| Office  | 15000  | 100000 | 150000 |
| Partner | 150    | 10000  | 50000  |

## Implemented error codes

| Error code    |
| ------------- |
| QUERY\_FAILED |


# GET /search/v5

Use this endpoint to retrieve services that match a query.

## Endpoint

```
https://api.tosdr.org/search/v5/
```

## Parameters

| Parameter | Type   | Description       |
| --------- | ------ | ----------------- |
| query     | String | The search string |

## Rate limiting

The endpoint is rate limited. For higher limits, contact the team at `team@tosdr.org`.

## Example response

`GET /search/v5?query=tosdr`

```
{
    "services": [
        {
            "id": 596,
            "is_comprehensively_reviewed": true,
            "urls": [
                "tosdr.org",
                "tosdr.community",
                "ybf3byfbutzozmau4elus7zm5feo3cqvy74er4qnxkgicbatzfq3qhqd.onion",
                "cphdgvjdcet6ctztiqxabspxqojhafygqtfcjztxxn5jfngizzsp7tqd.onion",
                "xkp3bueakhnea3hw4t4izybudyysnoc4jt746z7555mpv2w4p73ihhyd.onion",
                "6tc72lnilgt4dn2u6qk44vfns2qca552smajbilfcl6zs7ezf7emhbad.onion",
                "5qicbosngbkejsqpkywunvechlmcivsnhy2u5pbhtxd2laq5p7ufohid.onion"
            ],
            "name": "ToS;DR",
            "updated_at": "2023-11-17T18:01:03.518737",
            "created_at": "2018-07-09T08:24:52.683422",
            "slug": "tosdr",
            "rating": "B"
        },
        {
            "id": 969,
            "is_comprehensively_reviewed": true,
            "urls": [
                "edit.tosdr.org"
            ],
            "name": "ToS;DR Phoenix",
            "updated_at": "2021-05-14T14:37:48.921336",
            "created_at": "2018-12-21T00:57:18.464734",
            "slug": "tosdr_phoenix",
            "rating": "A"
        }
    ]
}
```


# Service API

Use these endpoints to interact with services stored in our database.

* [GET /service/v3](/developer/tos-dr-developers/restful-api/service-api/get-service-v3)
* [GET /service/v2](/developer/tos-dr-developers/restful-api/service-api/get-service-v2)


# GET /service/v2

Use this interface to retrieve a list of services (or a specific service) from our database in JSON format.

As a reference, you can also manually browse or search services at <https://edit.tosdr.org/services>.

## Endpoint

```
https://api.tosdr.org/service/v2/
```

## Parameters

| Parameter | Type    | Description                                                          |
| --------- | ------- | -------------------------------------------------------------------- |
| id        | Integer | Optional ID of the service. Omit the parameter to list all services. |
| page      | Integer | Pagination number (starts at `1`).                                   |

## Repository

Code for this endpoint lives at <https://github.com/tosdr/API/tree/master/functions/Service/GET/v2>.

## Implemented error codes

| Error code       |
| ---------------- |
| INVALID\_SERVICE |

## Example responses

### Specific service

```
{
    "error": 256,
    "message": "OK",
    "parameters": {
        "id": 353,
        "is_comprehensively_reviewed": false,
        "name": "Yammer",
        "updated_at": "2021-03-31T01:04:42.630Z",
        "created_at": "2018-05-08T12:19:43.120Z",
        "slug": "yammer",
        "rating": null,
        "urls": [
            "yammer.com"
        ],
        "image": "https://s3.tosdr.org/logos/353.png",
        "documents": [],
        "points": [
            {
                "id": 2145,
                "title": "Yammer.com (Microsoft Enterprise Social Network solution)",
                "source": "https://groups.google.com/forum#!topic/tosdr/Gw8zB2bMUoU",
                "status": "declined",
                "analysis": "Yammer.com (Microsoft Enterprise Social Network solution)",
                "created_at": "2018-05-15T09:12:15.999Z",
                "updated_at": "2021-02-06T03:50:33.404Z",
                "case": {
                    "id": 235,
                    "classification": "neutral",
                    "weight": 0,
                    "title": "none",
                    "description": "Do not select this case, because points with this case will not show up on tosdr.org",
                    "topic_id": 53
                },
                "quoteText": null,
                "document_id": null,
                "quoteStart": null,
                "quoteEnd": null
            }
        ]
    }
}
```

### All services

```
{
    "error": 256,
    "message": "All services below",
    "parameters": {
        "_page": {
            "total": 7390,
            "current": 1,
            "start": 1,
            "end": 74
        },
        "services": [
            {
                "id": 440,
                "is_comprehensively_reviewed": false,
                "name": "pebble",
                "urls": [
                    "pebble.com"
                ],
                "updated_at": "2021-03-25T03:19:30.208Z",
                "created_at": "2018-05-08T12:19:44.833Z",
                "slug": "pebble",
                "rating": null
            },
            {
                "id": 330,
                "is_comprehensively_reviewed": false,
                "name": "SeenThis",
                "urls": [
                    "seenthis.net"
                ],
                "updated_at": "2021-03-25T03:19:33.465Z",
                "created_at": "2018-03-05T08:40:47.818Z",
                "slug": "seenthis",
                "rating": null
            }
            ...
        ]
    }
}
```


# GET /service/v3

Use this interface to retrieve a specific service from our database in JSON format.

As a reference, you can also manually browse or search services at <https://edit.tosdr.org/services>.

## Endpoint

```
https://api.tosdr.org/service/v3/
```

## Parameters

| Parameter | Type    | Description                                                                                                                                          |
| --------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| id        | Integer | ID of the service.                                                                                                                                   |
| lang      | String  | Optional 2-letter language code (`de`, `nl`, `fr`, `es`). If omitted, no localized titles are loaded and all `localized_title` fields remain `null`. |

## Example response

### Specific service

```
{
    "id": 596,
    "is_comprehensively_reviewed": true,
    "name": "ToS;DR",
    "updated_at": "2023-11-17T18:01:03.518737",
    "created_at": "2018-07-09T08:24:52.683422",
    "slug": "tosdr",
    "rating": "B",
    "urls": [
        "tosdr.org",
        "tosdr.community"
    ],
    "image": "https://s3.tosdr.org/logos/596.png",
    "documents": [
        {
            "id": 1269,
            "name": "Terms of Contribution",
            "url": "https://docs.tosdr.org/sp/tosdr-org-terms-of-contribution",
            "updated_at": "2024-11-08T11:35:59.829096",
            "created_at": "2019-05-11T22:55:02.368371"
        },
        ...
    ],
    "points": [
        {
            "id": 4523,
            "title": "The terms for ToS;DR are easy to read",
            "source": "https://edit.tosdr.org/about#tos",
            "status": "approved",
            "analysis": "Altogether, ToS and PP only make up eight lines of text.",
            "case": {
                "id": 199,
                "weight": 15,
                "title": "The terms for this service are easy to read",
                "localized_title": null,
                "description": "The Agreements are well-organised, define legal terms (where applicable), aren't needlessly long and may be pleasant to read.",
                "updated_at": "2021-05-14T12:47:00.376324",
                "created_at": "2018-01-16T15:26:09.875993",
                "topic_id": 36,
                "classification": "good"
            },
            "document_id": null,
            "updated_at": "2018-08-27T08:20:58.063021",
            "created_at": "2018-08-24T04:32:06.765518"
        },
        ...
    ]
}
```


# Case API

Use this interface to retrieve a specific case from our database in JSON, or to list all cases.

As a reference, cases are also listed at <https://edit.tosdr.org/cases/>.

* [GET /case/v2](/developer/tos-dr-developers/restful-api/case-api/get-case-v2)


# GET /case/v2

Use this interface to retrieve a specific case from our database in JSON, or to list all cases.

As a reference, cases are also listed at <https://edit.tosdr.org/cases/>.

## Endpoint

```
https://api.tosdr.org/case/v2/
```

## Parameters

| Parameter | Type    | Description                                                |
| --------- | ------- | ---------------------------------------------------------- |
| id        | Integer | Case ID to retrieve. Omit the parameter to list all cases. |
| page      | Integer | Pagination number (defaults to `1`).                       |

## Repository

<https://github.com/tosdr/API/tree/master/functions/Case/GET/v2>

## Implemented error codes

| Error                                | HTTP status | Bitmask             |
| ------------------------------------ | ----------- | ------------------- |
| An invalid case id has been supplied | 404         | `INVALID_PARAMETER` |

## Example response

```
{
  "error": 256,
  "message": "OK",
  "parameters": {
      "id": 122,
      "weight": 0,
      "title": "The terms may be changed at any time, but you will receive notification of the changes",
      "description": "The Terms may be updated without prior notice, but users will be notified of the changes at the moment they will start applying.",
      "updated_at": "2021-05-07T16:23:11.148Z",
      "created_at": "2018-01-16T15:26:08.192Z",
      "topic_id": 46,
      "classification": "neutral"
    }
}
```


# Document API

Use this interface to retrieve a document from our database.

* [GET /document/v1](/developer/tos-dr-developers/restful-api/document-api/get-document-v1)


# GET /document/v1

Use this interface to retrieve a document from our database.

## Endpoint

```
https://api.tosdr.org/document/v1
```

## Parameters

| Parameter | Type    | Description                                                                                     |
| --------- | ------- | ----------------------------------------------------------------------------------------------- |
| id        | Integer | Document ID to retrieve. Omit the parameter to list all document IDs and `text_version` values. |

## Repository

<https://github.com/tosdr/API/tree/master/functions/public/Document/GET/v1>

## Implemented error codes

| Error                               | HTTP status | Bitmask             |
| ----------------------------------- | ----------- | ------------------- |
| An invalid doc id has been supplied | 404         | `INVALID_PARAMETER` |

## Example response

```
{
  "error": 256,
  "message": "OK",
  "parameters": {
      "id": 1378,
      "name": "Example",
      "url": "http://example.com/",
      "text": " Example Domain <p>This domain is for use in illustrative examples in documents.\nYou may use this domain in literature without prior coordination or asking for permission.</p>\n<p>More information...</p> ",
      "updated_at": "2020-12-14T22:20:50.860Z",
      "created_at": "2019-05-18T21:01:08.897Z",
      "text_version": null,
      "service_id": "502"
    }
}
```


# Privacy Shields API

Use this interface to retrieve a privacy shield (SVG badge) for a service.

![](https://shields.tosdr.org/en_596.svg)

## Endpoint

```
https://shields.tosdr.org/<locale>_<service_id>.svg
```

## Parameters

| Parameter   | Type            | Description                                   |
| ----------- | --------------- | --------------------------------------------- |
| service\_id | String\|Integer | ID of the service.                            |
| locale      | String          | Locale code for the badge (for example `en`). |


# Search

## GET /search/v5

> Search Services V5

```json
{"openapi":"3.0.0","info":{"title":"ToS;DR API","version":"1.0.0"},"servers":[{"url":"https://api.tosdr.org","description":"Production server"},{"url":"https://api.staging.tosdr.org","description":"Staging server"}],"paths":{"/search/v5":{"get":{"summary":"Search Services V5","tags":["Search"],"parameters":[{"name":"query","in":"query","required":true,"description":"Search query string (e.g., facebook)","schema":{"type":"string"}},{"name":"Accept","in":"header","required":false,"description":"Expected content type","schema":{"type":"string","deprecated":false}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","properties":{"services":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","description":"Unique ID of the service"},"is_comprehensively_reviewed":{"type":"boolean","description":"Indicates if the service has a comprehensive review"},"urls":{"type":"array","items":{"type":"string","description":"URL associated with the service"}},"name":{"type":"string","description":"Name of the service"},"updated_at":{"type":"string","format":"date-time","description":"Last update timestamp"},"created_at":{"type":"string","format":"date-time","description":"Creation timestamp"},"slug":{"type":"string","description":"URL-friendly identifier for the service"},"rating":{"type":"string","description":"Service's privacy rating (e.g., N/A, A, E)"}}}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}}}}}},"components":{"schemas":{"ValidationError":{"type":"object","properties":{"detail":{"type":"array","items":{"$ref":"#/components/schemas/ValidationErrorItem"}}}},"ValidationErrorItem":{"type":"object","properties":{"loc":{"type":"array","items":{"type":"string"}},"msg":{"type":"string"},"type":{"type":"string"}}}}}}
```

## GET /search/v4

> Search Services V4

```json
{"openapi":"3.0.0","info":{"title":"ToS;DR API","version":"1.0.0"},"servers":[{"url":"https://api.tosdr.org","description":"Production server"},{"url":"https://api.staging.tosdr.org","description":"Staging server"}],"paths":{"/search/v4":{"get":{"summary":"Search Services V4","tags":["Search","Deprecated"],"parameters":[{"name":"query","in":"query","required":true,"description":"Search query string (e.g., facebook)","schema":{"type":"string"}},{"name":"Accept","in":"header","required":false,"description":"Expected content type","schema":{"type":"string","deprecated":false}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"integer"},"message":{"type":"string"},"parameters":{"type":"object","properties":{"services":{"type":"array","items":{"$ref":"#/components/schemas/ServiceV4"}}}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}}}}}},"components":{"schemas":{"ServiceV4":{"type":"object","properties":{"id":{"type":"string","description":"Unique ID of the service"},"is_comprehensively_reviewed":{"type":"boolean","description":"Indicates if the service has a comprehensive review"},"urls":{"type":"array","items":{"type":"string"}},"name":{"type":"string"},"status":{"type":"string"},"updated_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"},"slug":{"type":"string"},"wikipedia":{"type":"string","format":"uri"},"rating":{"$ref":"#/components/schemas/RatingV4"},"links":{"type":"object","properties":{"phoenix":{"$ref":"#/components/schemas/LinkCategory"},"crisp":{"$ref":"#/components/schemas/LinkCategory"}}}}},"RatingV4":{"type":"object","properties":{"hex":{"type":"string"},"human":{"type":"string"},"letter":{"type":"string"}}},"LinkCategory":{"type":"object","properties":{"service":{"$ref":"#/components/schemas/LinkValue"},"documents":{"$ref":"#/components/schemas/LinkValue"},"new_comment":{"$ref":"#/components/schemas/LinkValue"},"edit":{"$ref":"#/components/schemas/LinkValue"},"api":{"$ref":"#/components/schemas/LinkValue"},"badge":{"$ref":"#/components/schemas/LinkValue"}}},"LinkValue":{"type":"object","properties":{"value":{"type":"string"}}},"ValidationError":{"type":"object","properties":{"detail":{"type":"array","items":{"$ref":"#/components/schemas/ValidationErrorItem"}}}},"ValidationErrorItem":{"type":"object","properties":{"loc":{"type":"array","items":{"type":"string"}},"msg":{"type":"string"},"type":{"type":"string"}}}}}}
```


# Service

## GET /service/v3

> Get Service V3

```json
{"openapi":"3.0.0","info":{"title":"ToS;DR API","version":"1.0.0"},"servers":[{"url":"https://api.tosdr.org","description":"Production server"},{"url":"https://api.staging.tosdr.org","description":"Staging server"}],"paths":{"/service/v3":{"get":{"summary":"Get Service V3","tags":["Service"],"parameters":[{"name":"id","in":"query","required":false,"description":"Service ID, omit to list all services","schema":{"type":"integer"}},{"name":"lang","in":"query","required":false,"description":"Language code (2 letters)","schema":{"type":"string","enum":["en","de","nl","fr","es"]}},{"name":"show_all","in":"query","required":false,"description":"Show all points including non-approved ones","schema":{"type":"boolean"}},{"name":"page","in":"query","required":false,"description":"Page number when id is not provided","schema":{"type":"integer"}},{"name":"Accept","in":"header","required":false,"description":"Expected content type","schema":{"type":"string","deprecated":false}}],"responses":{"200":{"description":"Successful Response","headers":{"Server":{"schema":{"type":"string"}},"Date":{"schema":{"type":"string"}},"Content-Type":{"schema":{"type":"string"}},"Content-Length":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceV3"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}}}}}},"components":{"schemas":{"ServiceV3":{"type":"object","properties":{"id":{"type":"integer"},"is_comprehensively_reviewed":{"type":"boolean"},"name":{"type":"string"},"updated_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"},"slug":{"type":"string"},"rating":{"type":"string"},"urls":{"type":"array","items":{"type":"string"}},"image":{"type":"string","format":"uri"},"documents":{"type":"array","items":{"$ref":"#/components/schemas/DocumentReference"}},"points":{"type":"array","items":{"$ref":"#/components/schemas/PointV3"}}}},"DocumentReference":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"url":{"type":"string","format":"uri"},"updated_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"}}},"PointV3":{"type":"object","properties":{"id":{"type":"integer"},"title":{"type":"string"},"source":{"type":"string","format":"uri"},"status":{"type":"string"},"analysis":{"type":"string"},"case":{"$ref":"#/components/schemas/CaseV3"},"document_id":{"type":"integer","nullable":true},"updated_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"}}},"CaseV3":{"type":"object","properties":{"id":{"type":"integer"},"weight":{"type":"integer"},"title":{"type":"string"},"localized_title":{"type":"string","nullable":true},"description":{"type":"string"},"updated_at":{"type":"string"},"created_at":{"type":"string"},"topic_id":{"type":"integer"},"classification":{"type":"string"}}},"ValidationError":{"type":"object","properties":{"detail":{"type":"array","items":{"$ref":"#/components/schemas/ValidationErrorItem"}}}},"ValidationErrorItem":{"type":"object","properties":{"loc":{"type":"array","items":{"type":"string"}},"msg":{"type":"string"},"type":{"type":"string"}}}}}}
```

## GET /service/v2

> Get Service V2

```json
{"openapi":"3.0.0","info":{"title":"ToS;DR API","version":"1.0.0"},"servers":[{"url":"https://api.tosdr.org","description":"Production server"},{"url":"https://api.staging.tosdr.org","description":"Staging server"}],"paths":{"/service/v2":{"get":{"summary":"Get Service V2","tags":["Service","Deprecated"],"parameters":[{"name":"id","in":"query","required":false,"description":"Service ID, omit to list all services","schema":{"type":"integer"}},{"name":"page","in":"query","required":false,"description":"Page number when id is not provided","schema":{"type":"integer"}},{"name":"Accept","in":"header","required":false,"description":"Expected content type","schema":{"type":"string","deprecated":false}}],"responses":{"200":{"description":"Successful Response","headers":{"Server":{"schema":{"type":"string"}},"Date":{"schema":{"type":"string"}},"Content-Type":{"schema":{"type":"string"}},"Content-Length":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ResponseWrapper"},{"type":"object","properties":{"parameters":{"$ref":"#/components/schemas/ServiceV3"}}}]}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}}}}}},"components":{"schemas":{"ResponseWrapper":{"type":"object","properties":{"error":{"type":"integer","description":"Status code (e.g., 256 for OK)"},"message":{"type":"string","description":"Status message"},"parameters":{"type":"object","description":"The main response payload"}}},"ServiceV3":{"type":"object","properties":{"id":{"type":"integer"},"is_comprehensively_reviewed":{"type":"boolean"},"name":{"type":"string"},"updated_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"},"slug":{"type":"string"},"rating":{"type":"string"},"urls":{"type":"array","items":{"type":"string"}},"image":{"type":"string","format":"uri"},"documents":{"type":"array","items":{"$ref":"#/components/schemas/DocumentReference"}},"points":{"type":"array","items":{"$ref":"#/components/schemas/PointV3"}}}},"DocumentReference":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"url":{"type":"string","format":"uri"},"updated_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"}}},"PointV3":{"type":"object","properties":{"id":{"type":"integer"},"title":{"type":"string"},"source":{"type":"string","format":"uri"},"status":{"type":"string"},"analysis":{"type":"string"},"case":{"$ref":"#/components/schemas/CaseV3"},"document_id":{"type":"integer","nullable":true},"updated_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"}}},"CaseV3":{"type":"object","properties":{"id":{"type":"integer"},"weight":{"type":"integer"},"title":{"type":"string"},"localized_title":{"type":"string","nullable":true},"description":{"type":"string"},"updated_at":{"type":"string"},"created_at":{"type":"string"},"topic_id":{"type":"integer"},"classification":{"type":"string"}}},"ValidationError":{"type":"object","properties":{"detail":{"type":"array","items":{"$ref":"#/components/schemas/ValidationErrorItem"}}}},"ValidationErrorItem":{"type":"object","properties":{"loc":{"type":"array","items":{"type":"string"}},"msg":{"type":"string"},"type":{"type":"string"}}}}}}
```


# Document

## GET /document/v2

> Get Document V2

```json
{"openapi":"3.0.0","info":{"title":"ToS;DR API","version":"1.0.0"},"servers":[{"url":"https://api.tosdr.org","description":"Production server"},{"url":"https://api.staging.tosdr.org","description":"Staging server"}],"paths":{"/document/v2":{"get":{"summary":"Get Document V2","tags":["Document"],"parameters":[{"name":"id","in":"query","required":true,"description":"Document ID","schema":{"type":"integer"}},{"name":"Accept","in":"header","required":false,"description":"Expected content type","schema":{"type":"string","deprecated":false}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentV2"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}}}}}},"components":{"schemas":{"DocumentV2":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"url":{"type":"string","format":"uri"},"text":{"type":"string"},"updated_at":{"type":"string"},"created_at":{"type":"string"},"text_version":{"type":"string","nullable":true},"service_id":{"type":"integer"}}},"ValidationError":{"type":"object","properties":{"detail":{"type":"array","items":{"$ref":"#/components/schemas/ValidationErrorItem"}}}},"ValidationErrorItem":{"type":"object","properties":{"loc":{"type":"array","items":{"type":"string"}},"msg":{"type":"string"},"type":{"type":"string"}}}}}}
```

## GET /document/v1

> Get Document V1

```json
{"openapi":"3.0.0","info":{"title":"ToS;DR API","version":"1.0.0"},"servers":[{"url":"https://api.tosdr.org","description":"Production server"},{"url":"https://api.staging.tosdr.org","description":"Staging server"}],"paths":{"/document/v1":{"get":{"summary":"Get Document V1","tags":["Document","Deprecated"],"parameters":[{"name":"id","in":"query","required":true,"description":"Document ID","schema":{"type":"integer"}},{"name":"Accept","in":"header","required":false,"description":"Expected content type","schema":{"type":"string","deprecated":false}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ResponseWrapper"},{"type":"object","properties":{"parameters":{"$ref":"#/components/schemas/DocumentV2"}}}]}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}}}}}},"components":{"schemas":{"ResponseWrapper":{"type":"object","properties":{"error":{"type":"integer","description":"Status code (e.g., 256 for OK)"},"message":{"type":"string","description":"Status message"},"parameters":{"type":"object","description":"The main response payload"}}},"DocumentV2":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"url":{"type":"string","format":"uri"},"text":{"type":"string"},"updated_at":{"type":"string"},"created_at":{"type":"string"},"text_version":{"type":"string","nullable":true},"service_id":{"type":"integer"}}},"ValidationError":{"type":"object","properties":{"detail":{"type":"array","items":{"$ref":"#/components/schemas/ValidationErrorItem"}}}},"ValidationErrorItem":{"type":"object","properties":{"loc":{"type":"array","items":{"type":"string"}},"msg":{"type":"string"},"type":{"type":"string"}}}}}}
```


# Points

## GET /point/v1

> Get Point V1

```json
{"openapi":"3.0.0","info":{"title":"ToS;DR API","version":"1.0.0"},"servers":[{"url":"https://api.tosdr.org","description":"Production server"},{"url":"https://api.staging.tosdr.org","description":"Staging server"}],"paths":{"/point/v1":{"get":{"summary":"Get Point V1","tags":["Points"],"parameters":[{"name":"id","in":"query","required":false,"description":"Point ID","schema":{"type":"integer"}},{"name":"case_id","in":"query","required":false,"description":"Case ID, to get all points for a Case","schema":{"type":"integer"}},{"name":"page","in":"query","required":false,"description":"Page number","schema":{"type":"integer"}},{"name":"Accept","in":"header","required":false,"description":"Expected content type","schema":{"type":"string","deprecated":false}}],"responses":{"200":{"description":"Successful Response","headers":{"Content-Length":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid request (e.g., both 'id' and 'case_id' provided)","content":{"application/json":{"schema":{"type":"object","properties":{"detail":{"type":"string"}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}}}}}},"components":{"schemas":{"ValidationError":{"type":"object","properties":{"detail":{"type":"array","items":{"$ref":"#/components/schemas/ValidationErrorItem"}}}},"ValidationErrorItem":{"type":"object","properties":{"loc":{"type":"array","items":{"type":"string"}},"msg":{"type":"string"},"type":{"type":"string"}}}}}}
```


# Case

## GET /case/v3

> Get Case V3

```json
{"openapi":"3.0.0","info":{"title":"ToS;DR API","version":"1.0.0"},"servers":[{"url":"https://api.tosdr.org","description":"Production server"},{"url":"https://api.staging.tosdr.org","description":"Staging server"}],"paths":{"/case/v3":{"get":{"summary":"Get Case V3","tags":["Case"],"parameters":[{"name":"id","in":"query","required":false,"description":"Case ID","schema":{"type":"integer"}},{"name":"Accept","in":"header","required":false,"description":"Expected content type","schema":{"type":"string","deprecated":false}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseV3"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}}}}}},"components":{"schemas":{"CaseV3":{"type":"object","properties":{"id":{"type":"integer"},"weight":{"type":"integer"},"title":{"type":"string"},"localized_title":{"type":"string","nullable":true},"description":{"type":"string"},"updated_at":{"type":"string"},"created_at":{"type":"string"},"topic_id":{"type":"integer"},"classification":{"type":"string"}}},"ValidationError":{"type":"object","properties":{"detail":{"type":"array","items":{"$ref":"#/components/schemas/ValidationErrorItem"}}}},"ValidationErrorItem":{"type":"object","properties":{"loc":{"type":"array","items":{"type":"string"}},"msg":{"type":"string"},"type":{"type":"string"}}}}}}
```

## GET /case/v2

> Get Case V2

```json
{"openapi":"3.0.0","info":{"title":"ToS;DR API","version":"1.0.0"},"servers":[{"url":"https://api.tosdr.org","description":"Production server"},{"url":"https://api.staging.tosdr.org","description":"Staging server"}],"paths":{"/case/v2":{"get":{"summary":"Get Case V2","tags":["Case","Deprecated"],"parameters":[{"name":"id","in":"query","required":false,"description":"Case ID","schema":{"type":"integer"}},{"name":"page","in":"query","required":false,"description":"Page number when id is not provided","schema":{"type":"integer"}},{"name":"Accept","in":"header","required":false,"description":"Expected content type","schema":{"type":"string","deprecated":false}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ResponseWrapper"},{"type":"object","properties":{"parameters":{"$ref":"#/components/schemas/CaseV3"}}}]}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}}}}}},"components":{"schemas":{"ResponseWrapper":{"type":"object","properties":{"error":{"type":"integer","description":"Status code (e.g., 256 for OK)"},"message":{"type":"string","description":"Status message"},"parameters":{"type":"object","description":"The main response payload"}}},"CaseV3":{"type":"object","properties":{"id":{"type":"integer"},"weight":{"type":"integer"},"title":{"type":"string"},"localized_title":{"type":"string","nullable":true},"description":{"type":"string"},"updated_at":{"type":"string"},"created_at":{"type":"string"},"topic_id":{"type":"integer"},"classification":{"type":"string"}}},"ValidationError":{"type":"object","properties":{"detail":{"type":"array","items":{"$ref":"#/components/schemas/ValidationErrorItem"}}}},"ValidationErrorItem":{"type":"object","properties":{"loc":{"type":"array","items":{"type":"string"}},"msg":{"type":"string"},"type":{"type":"string"}}}}}}
```


# Models

## The ValidationErrorItem object

```json
{"openapi":"3.0.0","info":{"title":"ToS;DR API","version":"1.0.0"},"components":{"schemas":{"ValidationErrorItem":{"type":"object","properties":{"loc":{"type":"array","items":{"type":"string"}},"msg":{"type":"string"},"type":{"type":"string"}}}}}}
```

## The ValidationError object

```json
{"openapi":"3.0.0","info":{"title":"ToS;DR API","version":"1.0.0"},"components":{"schemas":{"ValidationError":{"type":"object","properties":{"detail":{"type":"array","items":{"$ref":"#/components/schemas/ValidationErrorItem"}}}},"ValidationErrorItem":{"type":"object","properties":{"loc":{"type":"array","items":{"type":"string"}},"msg":{"type":"string"},"type":{"type":"string"}}}}}}
```

## The ResponseWrapper object

```json
{"openapi":"3.0.0","info":{"title":"ToS;DR API","version":"1.0.0"},"components":{"schemas":{"ResponseWrapper":{"type":"object","properties":{"error":{"type":"integer","description":"Status code (e.g., 256 for OK)"},"message":{"type":"string","description":"Status message"},"parameters":{"type":"object","description":"The main response payload"}}}}}}
```

## The RatingV4 object

```json
{"openapi":"3.0.0","info":{"title":"ToS;DR API","version":"1.0.0"},"components":{"schemas":{"RatingV4":{"type":"object","properties":{"hex":{"type":"string"},"human":{"type":"string"},"letter":{"type":"string"}}}}}}
```

## The LinkValue object

```json
{"openapi":"3.0.0","info":{"title":"ToS;DR API","version":"1.0.0"},"components":{"schemas":{"LinkValue":{"type":"object","properties":{"value":{"type":"string"}}}}}}
```

## The LinkCategory object

```json
{"openapi":"3.0.0","info":{"title":"ToS;DR API","version":"1.0.0"},"components":{"schemas":{"LinkCategory":{"type":"object","properties":{"service":{"$ref":"#/components/schemas/LinkValue"},"documents":{"$ref":"#/components/schemas/LinkValue"},"new_comment":{"$ref":"#/components/schemas/LinkValue"},"edit":{"$ref":"#/components/schemas/LinkValue"},"api":{"$ref":"#/components/schemas/LinkValue"},"badge":{"$ref":"#/components/schemas/LinkValue"}}},"LinkValue":{"type":"object","properties":{"value":{"type":"string"}}}}}}
```

## The ServiceV4 object

```json
{"openapi":"3.0.0","info":{"title":"ToS;DR API","version":"1.0.0"},"components":{"schemas":{"ServiceV4":{"type":"object","properties":{"id":{"type":"string","description":"Unique ID of the service"},"is_comprehensively_reviewed":{"type":"boolean","description":"Indicates if the service has a comprehensive review"},"urls":{"type":"array","items":{"type":"string"}},"name":{"type":"string"},"status":{"type":"string"},"updated_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"},"slug":{"type":"string"},"wikipedia":{"type":"string","format":"uri"},"rating":{"$ref":"#/components/schemas/RatingV4"},"links":{"type":"object","properties":{"phoenix":{"$ref":"#/components/schemas/LinkCategory"},"crisp":{"$ref":"#/components/schemas/LinkCategory"}}}}},"RatingV4":{"type":"object","properties":{"hex":{"type":"string"},"human":{"type":"string"},"letter":{"type":"string"}}},"LinkCategory":{"type":"object","properties":{"service":{"$ref":"#/components/schemas/LinkValue"},"documents":{"$ref":"#/components/schemas/LinkValue"},"new_comment":{"$ref":"#/components/schemas/LinkValue"},"edit":{"$ref":"#/components/schemas/LinkValue"},"api":{"$ref":"#/components/schemas/LinkValue"},"badge":{"$ref":"#/components/schemas/LinkValue"}}},"LinkValue":{"type":"object","properties":{"value":{"type":"string"}}}}}}
```

## The DocumentReference object

```json
{"openapi":"3.0.0","info":{"title":"ToS;DR API","version":"1.0.0"},"components":{"schemas":{"DocumentReference":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"url":{"type":"string","format":"uri"},"updated_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"}}}}}}
```

## The CaseV3 object

```json
{"openapi":"3.0.0","info":{"title":"ToS;DR API","version":"1.0.0"},"components":{"schemas":{"CaseV3":{"type":"object","properties":{"id":{"type":"integer"},"weight":{"type":"integer"},"title":{"type":"string"},"localized_title":{"type":"string","nullable":true},"description":{"type":"string"},"updated_at":{"type":"string"},"created_at":{"type":"string"},"topic_id":{"type":"integer"},"classification":{"type":"string"}}}}}}
```

## The PointV3 object

```json
{"openapi":"3.0.0","info":{"title":"ToS;DR API","version":"1.0.0"},"components":{"schemas":{"PointV3":{"type":"object","properties":{"id":{"type":"integer"},"title":{"type":"string"},"source":{"type":"string","format":"uri"},"status":{"type":"string"},"analysis":{"type":"string"},"case":{"$ref":"#/components/schemas/CaseV3"},"document_id":{"type":"integer","nullable":true},"updated_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"}}},"CaseV3":{"type":"object","properties":{"id":{"type":"integer"},"weight":{"type":"integer"},"title":{"type":"string"},"localized_title":{"type":"string","nullable":true},"description":{"type":"string"},"updated_at":{"type":"string"},"created_at":{"type":"string"},"topic_id":{"type":"integer"},"classification":{"type":"string"}}}}}}
```

## The ServiceV3 object

```json
{"openapi":"3.0.0","info":{"title":"ToS;DR API","version":"1.0.0"},"components":{"schemas":{"ServiceV3":{"type":"object","properties":{"id":{"type":"integer"},"is_comprehensively_reviewed":{"type":"boolean"},"name":{"type":"string"},"updated_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"},"slug":{"type":"string"},"rating":{"type":"string"},"urls":{"type":"array","items":{"type":"string"}},"image":{"type":"string","format":"uri"},"documents":{"type":"array","items":{"$ref":"#/components/schemas/DocumentReference"}},"points":{"type":"array","items":{"$ref":"#/components/schemas/PointV3"}}}},"DocumentReference":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"url":{"type":"string","format":"uri"},"updated_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"}}},"PointV3":{"type":"object","properties":{"id":{"type":"integer"},"title":{"type":"string"},"source":{"type":"string","format":"uri"},"status":{"type":"string"},"analysis":{"type":"string"},"case":{"$ref":"#/components/schemas/CaseV3"},"document_id":{"type":"integer","nullable":true},"updated_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"}}},"CaseV3":{"type":"object","properties":{"id":{"type":"integer"},"weight":{"type":"integer"},"title":{"type":"string"},"localized_title":{"type":"string","nullable":true},"description":{"type":"string"},"updated_at":{"type":"string"},"created_at":{"type":"string"},"topic_id":{"type":"integer"},"classification":{"type":"string"}}}}}}
```

## The DocumentV2 object

```json
{"openapi":"3.0.0","info":{"title":"ToS;DR API","version":"1.0.0"},"components":{"schemas":{"DocumentV2":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"url":{"type":"string","format":"uri"},"text":{"type":"string"},"updated_at":{"type":"string"},"created_at":{"type":"string"},"text_version":{"type":"string","nullable":true},"service_id":{"type":"integer"}}}}}}
```


# Phoenix for Beginners

The Phoenix Site, our database, where we review the Terms…

In this topic we’ll look at the different kinds of stuff you can do, aswell as different tips and tricks.

If you have any questions, feedback or suggestions, don’t hesitate to contact the [ToS;DR Team](mailto:team@tosdr.org), or create a new Topic!

### Functionalities of the Site <a href="#functionalities-of-the-site" id="functionalities-of-the-site"></a>

#### Types of Users <a href="#types-of-users" id="types-of-users"></a>

There are currently two types of users on the Site:

* ***Reviewers***\
  As a reviewer, the main catch is to read Documents (ToS, PrivPol, Cookie Policy, etc.), so that the user may highlight a certain text and assign a Case to it, one by one. The point is then submitted for review, which gets us to the next type of User…
* ***Curators***\
  Curators serve the same purpose as Reviewers, but with the ability to *Review* other users’ points (not their own). A Curator has the responsibility both to provide the necessary feedback in their reviews, and also to review a point correctly.

***

#### Review States. <a href="#review-states" id="review-states"></a>

In the [Phoenix](https://edit.tosdr.org/) Site, there are five review states that Points can have:

* **Approved**: The point has been approved and is clear of *caveats*, so now it affects the Rating for its respective Service, and will be uploaded to the [ToS;DR Site](https://tosdr.org/) through the API **ASAP**. Only Curators can give this Review State to other users’ points.
* **Changes-Requested**: The point has a generally solid structure, but some *caveats* have been found by a Curator while reviewing it. The user has *two months* to change the point, or else it will be switched to ***Declined*** (To avoid clutter).
* **Declined**: The point has been deemed not valid and therefore it won’t display as highlighted text in its respectide Document. Reviewers can mark their own point as declined aswell.
* **Draft**: Reviewers can mark their own points as *Draft*, usually to modify them later, or even for testing purposes.
* **Pending**: When creating a new point, this state will be the default for that point. It indicates that the point is up for review. It can also be assigned manually by the owner, specially after changing their own point.

***

#### Definitions <a href="#definitions" id="definitions"></a>

What does each word mean? Let’s take a look:

* **Case**: A `category` which specifies either keywords or concepts. Cases arise usually from common wordings throughout ToS.\
  A Case is made of:
  * A Rating: `Good`/`Bad`/`Neutral`/`Blocker`. These will indicate, essentially, how the `weight` affects a Service’s Class (whether *good*, *bad*, *none*, or *extremely bad*, respectively).\
    [More info → 4](https://tosdr.org/classification.html)
  * Weight: A ‘score’ which tells our Database how is a Service’s `Class` assigned, aswell as their positioning on the Service’s Listing.\
    [Check the Displayed Services → 7](https://tosdr.org/)
  * Keywords/Content: ‘*What does the case tell you?*’ ‘*What keywords does it need?*’\
    This is what a Case’s Name tells you.
* **Point**: A quoted text from a Document which has been assigned its appropriate Case, carries a certain `Weight` and may even have some additional information.\
  [Check our points for reference →](https://edit.tosdr.org/points)
* **Document**: *Terms of Service*, *Privacy Policy*, etc… It’s the actual ToS, and other legal documentation, that each Service provides; i.e. `The biggest lies on the web`.\
  [Check the Documents → 2](https://edit.tosdr.org/documents)
* **Topic**: Cases are split into their own ‘Categories’ pertinent to their respective common themes. There, ‘Categories’ are the **Topics**.\
  [Check the current Topics → 1](https://edit.tosdr.org/topics)
* **Service**: Facebook, Google, Microsoft, etc. In essence, the company that provides their respective ToS, and host their respective websites/products.\
  [Check the current Services →](https://edit.tosdr.org/services)

***

### *Do’s and Don’t’s* <a href="#dos-and-dont-s" id="dos-and-dont-s"></a>

We are going to be filling this at a later date, check back later!

***

#### Rules <a href="#rules" id="rules"></a>

To ensure both a good workflow, and accurate data, our rules are:

* ***No spam.***
* ***No illegal content.***
* ***No harassment/discrimination.***
* ***Be civil, there is no need for hostility.***

***

#### My Advice <a href="#my-advice" id="my-advice"></a>

While the following points are optional, I personally believe they will be useful for everyone contributing:

* *If you have any doubts, don’t hesitate to ask! Your questions are excellent both to inform and to improve!*
* *When adding a Service*:
  * *Always look for different domains (e.g. ‘*[![](https://static.files.bbci.co.uk/bbcdotcom/web/20250905-110137-f27f908f49-web-2.29.1-3/favicon-16x16.png)BBC Home - Breaking News, World News, US News, Sports, Business, Innovation, Climate, Culture, Travel, Video & Audio](http://bbc.com/) *,*[![](https://static.files.bbci.co.uk/core/website/assets/static/icons/favicon/bbc/favicon-16.0752fabca0.png)BBC - Home](http://bbc.co.uk/) *’…), usually found when switching Language, or Signing Up.*
  * ***Search the*** [***Phoenix***](https://edit.tosdr.org/) ***Site for the Service you’re adding.*** We want to avoid duplicates!
  * *Double-check for a Service’s Wikipedia Article.*
* When annotating Documents:
  * *Avoid creating duplicated points. They will be declined when reviewed, otherwise.*
  * *Use* `CTRL + F` (shortcut used to search within a webpage) *each time you review a Document, so that keywords are much faster to find!*
  * *Be sure to actually quote the Document, don’t rely on transcripts!*
* When reviewing points (***for Curators***):
  * *Always state a a reason for* ***Declining*** *a Point, or* **Requesting Changes** *to it.*
  * *Check all the existing points for a Service, in case you find duplicated points, or incongruent ones!*

***

### Epilogue <a href="#epilogue" id="epilogue"></a>

Reviewing Terms is a mighty task, some would say, and it’s best when communicated properly!\
If you have any feedback on this Topic, please let me know!

Also, thank you for your contributions!


# What is a curator?

You have probably seen the "Curator" role on a few places, whether it is

* On [Discord](https://discord.gg/tosdr):\
  ![](/files/rjOCH6yCevyqMcPJ2qbW)
* On [Phoenix](https://edit.tosdr.org):\
  ![](/files/AG8sgfWpMsA1QsoB0uzT)
* On our [Forum](https://tosdr.community):\
  ![](/files/mA0eJVuKCLiolLQSsMpE)

Curators serve the same purpose as registered contributors, but with the ability to *curate* other users’ points (not their own), create and update services, create and update documents, create and update cases and lastly create and update topics.


# How are classifications calculated?

Feel free to check the most up-to-date version of our algorithm [here](https://github.com/tosdr/edit.tosdr.org/blob/master/app/models/service.rb#L88-L109).

Basically, as of Sept 2025, a blocker counts as 3 bad points, and the algorithm looks at the balance:

number of good points − number of bad points − (3 × number of blockers).

* If there are no points at all, the grade is N/A.
* If the balance is −10 or lower, or if the number of blockers is greater than the number of good points, you get an E.
* Otherwise, if you have at least 3 blockers or if you have more bad points than good points, you get a D.
* Otherwise, if the balance is less than 5, you get a C.
* Otherwise, if you still have any bad points, you get a B.
* Only if you have no blockers and no bad points at all, you get an A.


