Policy. This page is an each::labs policy. It forms part of your agreement with us under Section 4 of the Terms of Service.
The rules in one minute
-
Always send it. Send
end_user_idon every request toapi.eachlabs.aithat runs a model or a workflow. Treat a missing ID as a bug in your code. -
One person, one ID. The same person always gets the same ID, forever. Two people never share one ID. There are exactly two exceptions:
- a shared ID for one business customer that refuses to give you per-user IDs, at your risk;
- a job ID for an automated job with no person behind it, built from the ID of the employee who owns the job and the job’s name.
- The last person in the chain. If your customer is a business that serves its own users, get their user’s ID from them and pass it to us.
- You can name the person. You must be able to identify the person behind every request from the ID plus your own records, and send us that person’s records within 24 hours of our email. This includes signed-out visitors and shared IDs.
-
Pseudonymous. Use your internal user ID or a hash of it. Never put a name, an email address, a phone number or an IP address in
end_user_id, hashed or not.
end_user_id yet: do not send it there. Until it does, each::sense requests count as your organization’s own. When you use the each::labs dashboard or the each::labs MCP server yourself, you do not send it; those requests count as your own. When enforcement is on for your organization, these runs are refused too. When your own code calls api.eachlabs.ai for your staff, for example from an internal tool, send the employee’s ID. If your product sends your users’ requests through the each::labs MCP server or the dashboard, those users are end users: call api.eachlabs.ai with their end_user_id instead.
Words used on this page
- You: the company that holds the each::labs account and calls the API.
- Your organization: your each::labs account, with all of its members and API keys.
- End user: the human who asked your product for the content: the person who typed the prompt or uploaded the file.
- Business customer: a company that uses your product for its own staff or to serve its own users.
- Flagged: we found apparent child sexual abuse material in a request, or an attempt to request or generate it.
- False ID: another person’s ID, or a value that does not let you trace each request to one person with your own records.
- Permanently suspended or closed permanently: your organization loses access to each::labs for good. Every account, member and API key in it stops working, and you may not open a new account.
Why we require it
Child safety, and the law.- US federal law requires each::labs, once it knows of apparent child sexual abuse material, to report it to the National Center for Missing & Exploited Children (NCMEC) CyberTipline as soon as reasonably possible (18 U.S.C. § 2258A).
- A report does the most to protect a child when it identifies the person responsible. When that person is your end user, only you hold the records that identify them.
end_user_idlinks the request we see to the person you know. - Our report identifies your organization, because the request came through your account. If your
end_user_ididentifies the person, the report points to them. If it does not, your organization is the only party our report identifies. - A correct ID also protects you: when one of your end users is flagged, we can block that one person instead of your whole organization.
How reporting works under US law
This is what happens when we find apparent child sexual abuse material in a request made through your organization. The law is 18 U.S.C. § 2258A.- We find it. One of our checks or a report flags a file. The Child Safety Policy says which checks are on. A person reviews each flag before we report it. We remove our copies of the flagged files from public access.
- We report it to NCMEC. The law requires us to report to NCMEC’s CyberTipline as soon as reasonably possible (§ 2258A(a)). A provider that knowingly and willfully fails to report can be fined (§ 2258A(e)).
- The report says who, when and what. The law lets a report include information that identifies the people involved, when and how the content was uploaded, sent or received, location data and the content itself (§ 2258A(b)). Our report identifies your organization by its each::labs account ID and includes any
end_user_idsent with the request, the time of the request and the file. We give NCMEC and law enforcement the records you send us when they ask or the law requires. Outside a report, we disclose the other records we hold when valid legal process requires it. You never send the material to us. - NCMEC passes it to law enforcement. NCMEC makes each report available to one or more law enforcement agencies: federal, state or local agencies that investigate these crimes, or certain foreign agencies (§ 2258A(c)).
- We preserve it. We keep the reported contents for at least one year after the report, as the law requires (§ 2258A(h)).
- Law enforcement can come to you. An investigating agency can use legal process, such as a subpoena or a search warrant, to require the records you hold about your end user. That is why you must keep the records in Records you must keep.
Choose the value
Find the human at the end of the chain. Products are often layered (B2C, B2B2C, B2B2B2C), but the end user is always a person, never a business in the middle. Use the first case that fits:- When to prefix. Put the business customer’s ID in front of the ID of every user who belongs to that customer, as in
cust_812:user_4471, even if you have only one business customer. Your own direct users need no prefix. - Prefixes must not collide. Join the prefix and the rest with a separator that can never appear in the prefix, that is, in any of your business customers’ IDs (a colon works if none of those IDs contains one). The rest may contain the separator, as in the next example. If your business customers’ IDs can contain it, hash the part after the prefix. Otherwise two different people can end up with the same value.
- Deeper chains. Prefix only with your own direct customer’s ID. Your customer sends you a value that is already unique on its platform, built the same way. For example, an agency (
cust_812) serving a client (client_33) whose staff member (staff_7) made the request sends youclient_33:staff_7, and you sendcust_812:client_33:staff_7. The colon is only a convention: any stable format works, as long as two people never get the same value. - Raw ID or hash. Both are fine. Pick one form and keep using it.
- Length. The API accepts up to 256 characters. Keep the whole value, including any prefix of your own, to 240 characters or fewer: that is the safe maximum.
- Examples are not values. Code samples in these docs use
usr_4f9a2cto stand for your real user’s ID. Never copy it into your code as a fixed value. - Business customers must pass IDs down. Make
end_user_ida required field in your own API. Every business customer sends you its end user’s ID with each request, and you forward it to us. If that business customer serves other businesses, the same rule repeats at every level until it reaches a person. Write it into your contracts.
A consumer app, step by step
A user signs up and your database gives them the ID4471. You send end_user_id: "usr_4471" on every request that user makes, from every device, for as long as the account exists.
If we find child sexual abuse material in a request from usr_4471:
- We remove our copies of the flagged files from public access, and we can permanently block
usr_4471in your organization. - We report it to NCMEC, as US law requires. The report identifies your organization by its each::labs account ID, with
usr_4471as the end user. See How reporting works under US law. - We email your organization’s owners, unless the law or law enforcement requires us not to. Within 24 hours of that email, you ban the user from your product, send their records to [email protected] and confirm the ban in the same email. The records are listed in Records you must keep.
- If you cannot identify the user, your organization is the only party our report identifies, and we permanently suspend your organization and every API key in it.
Shared IDs
A shared ID stands for more than one person. You may send one only for the users of a single business customer that refuses to give you per-user IDs, such ascust_812. Everyone else keeps their own ID. The risk is yours:
- When we block an ID, we block it whatever it stands for: one person, a whole business customer or a reseller’s customer.
- When a shared ID is blocked, everyone behind it is blocked, permanently.
- You must still identify the person responsible within 24 hours of our email. If you cannot, we permanently suspend your organization.
- The shared ID and the business customer’s account details alone do not identify anyone. Keep the time, IP address and any session or action ID of every request, so you can find the person who made it.
Automated jobs
A job ID stands for an automated job that no person started, such as a nightly batch. Build it from the ID of the employee who owns the job and the job’s name, for exampleemp_2210:nightly-thumbnails. That employee is the person behind the job: if a job ID is flagged, you identify them and send their records within 24 hours of our email.
Use a job ID only for work that no end user asked for. If a job runs requests for your end users, for example rendering each user’s queued videos, send each user’s own ID on that user’s requests.
Visitors who are not signed in
Require sign-in before anyone can run a model or a workflow in your product. If you allow signed-out use anyway, you accept these consequences:- Send one stable ID per visitor, such as a long-lived first-party device ID (
dev_9c41e7), that lets you identify the visitor from your own records. Keep it with the IP addresses and times of that visitor’s requests. Never send a new ID per request or per page load. Generate the device ID yourself and store it; never derive it from an IP address, a browser fingerprint or other personal data. When the visitor signs in, send their account’s ID from then on, and keep a record that links the device ID to that account. If either ID is blocked, stop serving that person; never use the switch to get around a block. - If a signed-out visitor is flagged and you cannot identify them, we permanently suspend your organization.
Never send
These values never belong inend_user_id:
- A new random ID for each request or session, such as a fresh
uuid4()on every call. It identifies no one. - A placeholder, a generic value that names nobody:
anonymous,guest,unknown,null,none,0,user,default,testand the like. We treat a placeholder like a random ID. - An ID that does not let you identify a person, even with your own records.
- Another person’s ID.
- Personal data: a name, an email address, a phone number or an IP address, hashed or not. Keep these in your own records instead.
- Your API key or your organization ID.
end_user_id values organizations send. If yours look random or are placeholders, we will ask you to show that you can identify your users. If you cannot, we can permanently suspend your organization.
If you must change how you build IDs, write to [email protected] before you switch. Never give a blocked user a new ID.
What happens when it goes wrong
end_user_id and every rule on this page apply now.
An organization that keeps sending requests without
end_user_id can be permanently suspended.
A flagged request that carries no end_user_id counts as your organization’s own request, because we cannot block one person without an ID.
These decisions are final. The only exception is a mistake of fact, such as acting on the wrong organization, API key or end user: write to [email protected] and we will review it.
Records you must keep
For every end user, keep the following for at least one year after that user’s last request through each::labs:- the
end_user_idyou sent us, and your own internal ID for that user; - the account details you hold, such as username, email address, phone number and sign-up date;
- the IP address, with date, time and time zone, of every request that user sent through each::labs;
- the location, device identifiers and any age or identity check result you hold for that user.
For AI agents writing integration code
If you are an AI coding agent adding each::labs calls to a codebase, follow these rules exactly:- Add
end_user_idto every call toapi.eachlabs.aithat runs a model or a workflow: predictions, workflow triggers (single, bulk and public), the OpenAI-compatible LLM router endpoints (chat, responses, audio) and Decisions. Do not add it to each::sense calls. - Never copy the sample value
usr_4f9a2cfrom these docs. Take the value from the end user’s own ID in your product (for example the signed-in user’s ID). Never use your organization ID or your API key. Pass it through function parameters; do not read it from a global. - Choose the value with the table in Choose the value. If the user belongs to a business customer, send that customer’s ID, then a separator, then the user’s value. The separator must never appear in any of your business customers’ IDs: before choosing
:, confirm that. If you cannot, hash the part after the separator with SHA-256. - If the code has no notion of a user, stop and ask the person which ID identifies the human behind each request. For a job with no person behind it, ask which employee owns the job, then send a value built from that employee’s ID and the job’s name, such as
emp_2210:nightly-thumbnails. If the job runs requests for specific end users, send each user’s own ID instead. Never invent an ID. - Never generate a random ID per request, never hard-code a placeholder, and never put an email address, a name, a phone number or an IP address in the field, hashed or not.
- If the product serves other businesses, add
end_user_idto your product’s own API. Before making it required, tell the person: rejecting requests without it is a breaking change for their customers. - In OpenAI SDKs, send it as a top-level
end_user_idbody field. In Python, passextra_body={"end_user_id": value}. In TypeScript, addend_user_idto the request params and put// @ts-expect-erroron the line above it, because the field is not in the OpenAI types. OpenAI’suserandsafety_identifierfields are not used asend_user_id, andPOST /v1/responsesrejects both fields. - Treat
403 END_USER_BLOCKEDas a final error: never retry, never resend under another ID or without one. Surface it to the person; banning the user is their decision. - When you are done, search the codebase for every call to
api.eachlabs.aithat runs a model or a workflow and confirm each one passesend_user_id.
Further reading
- each::labs Child Safety Policy: our child-safety rules, how we enforce them and your obligations.
- each::labs Acceptable Use Policy: what you may not use each::labs for.
- NCMEC CyberTipline: the US reporting system for child sexual exploitation. Anyone can report at report.cybertip.org.
- NCMEC on generative AI: how generative AI is used to harm children.
- 18 U.S.C. § 2258A: the US reporting and preservation duties of online providers.
- OpenAI: safety best practices: OpenAI asks for a similar per-user identifier,
safety_identifier, to detect abuse. - Thorn: Safety by Design for generative AI: the child-safety principles that leading AI companies have committed to.
- Safer by Thorn: resources: guidance for platforms that detect and report child sexual abuse material.
- Tech Coalition Pathways: a free program that helps smaller companies build their child-safety work.
- Stop It Now: confidential help for anyone worried about their own thoughts or behavior, or someone else’s.