What a Provider's Content Policy Differences Mean for Existing Use Cases
9 min read · updated August 11, 2026
Somebody assessed your use case against a provider’s policy once, probably before launch, and wrote “approved” in a ticket. That assessment was against one document, and it does not transfer. What follows is how to redo it without turning it into a legal exercise.
Three layers, routinely collapsed into one
“Content policy” in a migration conversation usually means three different things at once, and untangling them decides who does the work.
- The published usage policy. A document stating which uses are permitted, prohibited, or permitted subject to conditions. It binds you contractually and is not observable from the API. Only reading it tells you anything.
- Account-level enablement. Some categories of use are not flatly prohibited but sit behind an application, an attestation or an account setting. The distinction between “you may not” and “you may once you have asked” is invisible in a runtime test, and it is a schedule item rather than an engineering one.
- Runtime refusal behaviour. What the model declines in the moment. This is observable, testable, and the only layer your evaluation harness can see — which is why teams over-index on it and conclude from a clean test run that the policy question is settled. It is not: a model that answers a request is not a statement that the use is permitted.
Policies are not structured the same way
The reason a like-for-like comparison is hard is that providers do not organise their policies along the same axis. Some enumerate prohibited uses and treat everything unlisted as allowed. Some enumerate high-risk domains and attach conditions to them — a human in the loop, a disclosure to the end user, an age assurance step, a restriction on fully automated decisions. Some scope by deployment context rather than by topic, distinguishing an internal tool from a consumer-facing product regardless of subject matter.
The practical consequence is that a use case does not simply move from “allowed” to “prohibited”. Far more often it moves from “allowed” to “allowed with conditions”, and the conditions are the migration work: adding a review step, adding a disclosure to the interface, restricting a feature to authenticated adults, keeping a log you were not keeping. Those are product changes with lead times, which is why this assessment belongs at the start of a migration rather than in the week before cutover.
The domains where scoping most often differs in kind rather than degree are predictable enough to check first: health and medical guidance, legal and financial advice, anything touching minors, biometric or identity inference, security research and offensive tooling, political and election content, and adult material. If your product does not touch any of these, the assessment is short. If it touches one, that is where the conditions will be.
The one layer you can actually test
Runtime refusal behaviour is worth testing even though it does not answer the policy question, because it tells you what your users will experience and because the mechanics of a refusal differ between providers in a way your code will trip over.
The Messages API signals a policy decline as a successful HTTP 200 with a stop_reason of refusal, and Anthropic’s documentation describes a companion stop_details object carrying a category, while warning that it can be null and that code should branch on the stop reason rather than on the details. OpenAI-shaped APIs express the same outcome in two other places: a finish_reason of content_filter on the choice, and an optional refusal string on the assistant message which is null when absent. Some hosted deployments instead return an HTTP 400 with the filter result in the error body, so the refusal arrives as an exception rather than a response.
Three shapes, three code paths. Building the detector is a separate job, covered in migrating refusal-handling logic. What matters for the policy assessment is that you can now count declines per category on a sample of real traffic and compare the rate against the old provider — not to argue about who is stricter, but to find the request classes where your product now degrades.
Write the use case down, then read the policy
The failure mode of a policy re-read is reading the document against your product name rather than against what the system actually does. The fix is a paragraph, written before you open the policy, answering four questions: what the model is asked to do, on whose data, who is in the loop before the output has an effect, and what the output is used for downstream.
“A support assistant” is not that paragraph. “Given a customer’s ticket history and our knowledge base, drafts a reply which a human agent edits and sends; the draft is never sent automatically; the assistant also proposes a refund amount which the agent approves” is. Written that way, the clauses that apply become obvious — the refund proposal is an automated decision about a person’s money with a human approval step, and whether that approval step is sufficient is a question the policy will answer directly.
Keep the paragraph in the repository next to the prompt it describes, not in a ticket. It is the artefact the next migration re-reads, and it is the thing that makes the next assessment a morning rather than a fortnight. Version it, and record which policy version it was assessed against and on what date.
Your own commitments did not move
One category of obligation is easy to lose in a migration because it points the other way. Whatever you told your own customers — in a privacy notice, a data processing agreement, a security questionnaire, a trust page — about how their content is handled by subprocessors is unchanged by the fact that the subprocessor changed. If any of it names the previous provider, describes a retention period, or asserts that content is not used for training, those statements now need to be true of the new arrangement or need updating, and some of them may require notice to customers.
Keep that as a short register alongside the use-case statement: one row per external commitment, where it is published, and what it asserts. It is a five-line file that prevents the most embarrassing class of migration finding, which is a public page describing an architecture you replaced two quarters ago.