- 01Your appContinue with TrustedRouter

- 02TrustedRouter sign-inVerified company email + user consent

- 03Company contextY Combinator, domain, founding year

A sign-in button for your app

Download the image or use its public URL. Connect the button to your app's OAuth start route; a static image is not a complete sign-in integration.

Add it with your agent

Paste this into Claude Code, Codex, or your preferred coding agent.

Add "Sign in with Y Combinator" to this app using TrustedRouter. Follow the guide and use its button image: https://trustedrouter.com/sign-in-as-ycombinatorOne sign-in flow. Extra company context.

- Register your app- Sign in to TrustedRouter and register your app through OAuth registration and protocol reference- POST /v1/oauth/appswith its name, app ID, and exact callback URL. Registration uses your console session, not a provider API key.

- Request profile access- Use the authorization-code flow with PKCE S256 and state validation. Request - profile; add- inferenceonly if your app also calls models. The user approves access.

- Read the current identity- Exchange the code and fetch - /v1/auth/userinfoserver-side with the returned access token. Use- data.subas the stable user ID. Do not trust profile JSON sent by the browser.

- Match the organization- Require a verified email and an exact - funding_organizationmatch. Show the company and its source. Recheck current claims before granting company-only benefits.

// Server-side, after the OAuth code exchange.

// accessToken comes from TrustedRouter, not a browser claim.

const response = await fetch(

"https://trustedrouter.com/v1/auth/userinfo",

{

headers: { Authorization: `Bearer ${accessToken}` },

cache: "no-store",

},

);

if (!response.ok) throw new Error("TrustedRouter profile unavailable");

const { data } = await response.json();

const company = data.email_verified === true

&& Array.isArray(data.company_affiliations)

? data.company_affiliations.find((claim) =>

claim.funding_organization === "Y Combinator"

&& claim.match_method === "verified_email_domain")

: undefined;

// No match does not prevent ordinary sign-in.

const userId = data.sub;

const companyContext = company ?? null;What your app receives

- Company + domain

- The listed company name and exact verified email domain.

- Organization

- funding_organization: "Y Combinator", with the directory relationship.

- Founding year

- A sourced year when known. nullmeans unknown, not zero.

- Evidence

- A source listing, check timestamp, and verified_email_domainmatch method.

View the response shape

Illustrative values below, not a real company record. Userinfo wraps the identity in data; the OAuth token exchange includes profile metadata under trustedrouter.

{

"data": {

"sub": "usr_example",

"email": "person@example.com",

"email_verified": true,

"company_affiliations": [

{

"company_name": "Example Company",

"funding_organization": "Y Combinator",

"relationship": "accelerator",

"domain": "example.com",

"founding_year": null,

"source_url": "https://www.ycombinator.com/companies",

"checked_at": "2026-09-12T00:00:00+00:00",

"match_method": "verified_email_domain"

}

]

}

}A useful signal, not an employment check.

A match means the verified email domain matches a reviewed company listing. It does not prove employment, investor endorsement, funding eligibility, or ownership of the company.

Personal email, an unlisted domain, or stale or unavailable evidence can produce no match. Keep ordinary sign-in working. Offer retry or manual review for company-only benefits rather than treating missing data as proof that someone is ineligible.

The Sign in with Y Combinator artwork identifies a company-affiliation sign-in flow, not official authentication operated by Y Combinator. Keep the backing line visible and explain that TrustedRouter checks the company email domain.