Skip to main content
Send end_user_id on every request that runs a model or a workflow. It must identify the real person who asked for the content: the last person in your chain of customers. Never send a random or per-request ID.end_user_id and every rule on this page apply now. A missing, random or false ID can get your requests refused and your whole organization permanently suspended, including every API key.
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

  1. Always send it. Send end_user_id on every request to api.eachlabs.ai that runs a model or a workflow. Treat a missing ID as a bug in your code.
  2. 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.
    Signed-out visitors are not an exception. Require sign-in, or send one stable ID per visitor at your risk.
  3. 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.
  4. 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.
  5. 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.
The End-user ID reference shows where each endpoint takes the field, its format and its error codes. each::sense does not take 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_id links 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_id identifies 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.
Our Acceptable Use Policy and Terms of Service prohibit child sexual abuse and exploitation, and our Child Safety Policy sets out how we act on it. The rules on this page explain what that requires of your integration.

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.
  1. 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.
  2. 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)).
  3. 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_id sent 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.
  4. 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)).
  5. We preserve it. We keep the reported contents for at least one year after the report, as the law requires (§ 2258A(h)).
  6. 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.
If you provide an electronic communication service or a remote computing service, 18 U.S.C. § 2258A may require you to report apparent child sexual abuse material to NCMEC yourself. Our reports do not replace yours. Ask your counsel. Never send the material to us. Do not copy, forward or attach it except as the law requires or NCMEC instructs you. Holding or sending it can be a crime. If the law requires you to report it, it also requires you to preserve what you report. If you report to NCMEC yourself, follow NCMEC’s instructions.

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 you client_33:staff_7, and you send cust_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_4f9a2c to 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_id a 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 ID 4471. 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:
  1. We remove our copies of the flagged files from public access, and we can permanently block usr_4471 in your organization.
  2. We report it to NCMEC, as US law requires. The report identifies your organization by its each::labs account ID, with usr_4471 as the end user. See How reporting works under US law.
  3. 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.
  4. 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.
You are responsible for your users.

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 as cust_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.
Never use one ID for several of your business customers, for your own direct users, or for all of your traffic.

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 example emp_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 in end_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, test and 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.
We may review the 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_id you 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.
When we email you about a flagged end user, send these records to [email protected] within 24 hours. The 24 hours start when we send the email and run on every day of the year. Send records and IDs only, never the material itself. This one-year period is yours. Separately, we keep the contents of each report for at least one year after we send it, as the law requires.

For AI agents writing integration code

If you are an AI coding agent adding each::labs calls to a codebase, follow these rules exactly:
  1. Add end_user_id to every call to api.eachlabs.ai that 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.
  2. Never copy the sample value usr_4f9a2c from 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.
  3. 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.
  4. 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.
  5. 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.
  6. If the product serves other businesses, add end_user_id to your product’s own API. Before making it required, tell the person: rejecting requests without it is a breaking change for their customers.
  7. In OpenAI SDKs, send it as a top-level end_user_id body field. In Python, pass extra_body={"end_user_id": value}. In TypeScript, add end_user_id to the request params and put // @ts-expect-error on the line above it, because the field is not in the OpenAI types. OpenAI’s user and safety_identifier fields are not used as end_user_id, and POST /v1/responses rejects both fields.
  8. Treat 403 END_USER_BLOCKED as a final error: never retry, never resend under another ID or without one. Surface it to the person; banning the user is their decision.
  9. When you are done, search the codebase for every call to api.eachlabs.ai that runs a model or a workflow and confirm each one passes end_user_id.
Pass the value in from the caller, as in these examples. The function takes the end user’s ID as a parameter, and the caller supplies the signed-in user’s own ID:

Further reading

Last modified on November 10, 2026