Skip to content
Developers · Embed

Player sign-in

Watching needs nobody to sign in. Joining and playing do, and there are three ways, chosen per tournament. The first two need nothing from you.

Three ways

WayFor whomWhat you do
Email codeAnyone. They type their email and the 6-digit code we send: no password, no new tab.Nothing. It's the default.
GoogleAnyone with a Google account, in a small popup, once Google sign-in is switched on for Ocheso. Hidden inside apps, where Google refuses webviews.Nothing.
Your loginYour own users, already signed in to your site or app. They're never asked anything.One endpoint on your server and one call on your pages. Below.

Each tournament has an identity setting: accounts (email code, and Google when switched on; the default), platform (your users only) or any (both). It is set when the tournament is made and frozen once anyone has entered.

Players who sign in with an email code or Google have an Ocheso account: it works in every tournament, on your site and anywhere else. When you add players by email in Studio, they're entered the first time they sign in with that address.

Your login, step by step

Your server vouches for the user; Ocheso trusts it for ten minutes. The widget never sees your secret key, and your pages never see anything but a short-lived token.

  1. 1. A player presses Join in the widget.
  2. 2. The loader calls your fetchToken(), which asks your server.
  3. 3. Your server: POST /v1/platform/player-tokens with ochs_… → ochp_…
  4. 4. The loader hands ochp_… to the widget by postMessage, never in a URL.
  5. 5. The widget trades it for its own session and joins.
  1. Make a secret key

    In Studio, Developers → Keys → New key, with the Players scope. It starts ochs_ and is shown once. Store it on your server as OCHESO_SECRET_KEY, never in a page or an app: the API refuses it from a browser.

  2. Add an endpoint that hands out player tokens

    For whoever is signed in to your site. external_id is your id for them and must never change: the same id is the same Ocheso player, with their rating and history. Answer 401 when nobody is signed in.

    // Your server. The secret key stays in your environment - never in a page or an app.
    // Ocheso.identify() on your pages calls this for whoever is signed in to YOUR site.
    app.get("/ocheso-token", async (req, res) => {
      if (!req.user) return res.status(401).end(); // not signed in here: Ocheso shows your login link
    
      const r = await fetch("https://api.ocheso.com/v1/platform/player-tokens", {
        method: "POST",
        headers: {
          Authorization: `Bearer ${process.env.OCHESO_SECRET_KEY}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          external_id: String(req.user.id), // your id for them; it never changes
          name: req.user.displayName,
        }),
      });
      if (!r.ok) return res.status(502).json({ error: (await r.json()).detail });
    
      const { token } = await r.json(); // ochp_…, good for 10 minutes
      res.set("Cache-Control", "no-store").json({ token });
    });
  3. Tell the widget where to ask

    On pages where your users can be signed in. The loader asks only when someone joins or opens their game, and one token serves every widget on the page. loginUrlis where the widget's Sign in button sends people your endpoint doesn't know.

    HTML
    <script>!function(w){var o=w.Ocheso=w.Ocheso||{q:[]};["ready","mount","identify","logout","setTheme","on","scan"].forEach(function(m){o[m]=o[m]||function(){o.q.push([m,arguments])}})}(window)</script>
    <script>
      Ocheso.identify(async function () {
        // Your endpoint (the server snippet): a token for whoever is signed in to your site.
        const res = await fetch("/ocheso-token", { credentials: "same-origin" });
        if (!res.ok) return null; // not signed in: Ocheso offers your sign-in page
        return (await res.json()).token;
      }, { loginUrl: "/login" });
    </script>
    <script async src="https://www.ocheso.com/embed/v1.js"></script>
  4. Test it

    Studio's Developerspage has a box to paste a token from your endpoint: it checks the token and throws it away. Then set a tournament's sign-in to Your platform's login and press Join on your own page.

Tokens and how long they last

TokenLivesWhere
ochs_…until revokedYour server only. Mints player tokens and calls the platform API.
ochp_…10 minutesYour page, briefly. Reusable until it expires, so one fetch serves every widget.
oche_…12 h (your users) · 7 days (accounts)Inside the widget. Ocheso's own session; you never handle it.
  • The loader keeps a token for 8 minutes, so it is never used with less than two left. If the widget is refused anyway, it asks again with reason expired and the loader skips its copy.
  • Return null (or a 401 from your endpoint) when nobody is signed in. The widget then offers Sign in, which goes to your loginUrl, and an identityRequired event fires in case your page would rather open its own sign-in.
  • When your user signs out, call Ocheso.logout() so the widget forgets them too.
  • Serve tokens with Cache-Control: no-store. A token cached by a CDN would sign the next visitor in as the last one.

Your users on Ocheso

Each user you sign in becomes a player that belongs to your organisation only. They have no Ocheso password, their ratings count inside your organisation, and they appear only in your tournaments. What you send is what we keep:

FieldNotes
external_idRequired, 1–128 characters. Your stable id for them.
nameRequired, up to 60 characters. Shown on boards and tables; send the current one with each token.
emailOptional. Shown to your admins only. Never used to send mail or to match an Ocheso account.
avatar_url · country · ratingOptional. https URL, two-letter country code, and a starting rating (100–3500).
tournament · enterOptional. Limit the token to one tournament, and enter the player at the same time.

To erase someone, call DELETE /v1/platform/players/{external_id}: their name becomes "Deleted player" in past results and the link to your id is gone. See the HTTP API.

Sign-in and allowed domains

A widget checks which page it is on before it accepts anyone. On a domain that isn't in your allowed list it still shows the tournament, but read-only, with a link to join on the hosted page. That keeps a copied snippet on someone else's site from signing your users in.

Not working?

Most sign-in problems are a domain missing from the list (www versus the bare domain, a port on a test server) or a cached token. Troubleshooting has both.