Creating OAuth Endpoints

How to create a Seam-Compatible OAuth endpoint.

This guide will you implement the two endpoints required for OAuth 2.0 with the Authorization Code Flow, /authorize and /oauth/token. We'll also go over some OAuth concepts to make it as easy as possible.


  • Resource Owner (Door Locks Account Owner): The person, installer, company or end-user who owns the door locks or can grant access to a building. This person will sign in to your server.

  • Resource/Authorization Server (Your Server): The server granting access to the door locks, that's what we're creating here!

  • Client (Seam): Application requesting access to the door locks on behalf of the Door Locks Account Owner. This is Seam! We're a client requesting access on behalf of the door locks owner, so that the door locks owner can get delivery services.

If you use an external authorization provider like Auth0 or Clerk, you'll have a separate Resource and Authorization server. We can handle this! Contact



  • /authorize - This endpoint provides a web page for the Door Locks Account Owner to sign into

  • /oauth/token - Client (Seam) calls this after the user signs in

GET /authorize

This endpoint can return the HTML for a webpage for a user to sign into (expand this box to see an example!). You can use your own internal endpoints to validate the user, then, using your database, create an authorization code that we'll use in a later step. The authorization code just represents that a user successfully logged in. It can be a UUID or a random string. To avoid storing codes in your database, you may consider using a signed JWT for the authorization code. It is very important that you validate that the redirect_uri goes to *, or a malicious actor could gain access to your system by redirecting the Door Locks Account Owner to their domain.

Provide a webpage for the Door Locks Account Owner to sign into


Query Parameters




URL to redirect Intercom Owner to after they sign in

<!-- Just an example, this page will look ugly! --!>
    email: <input type="text" id="email" /><br/>
    password: <input type="text" id="password" /><br/>
    <button id="submit">submit</button>
    <script src=""></script>
      // When the user hits submit, we 
      $("#submit").on("click", async () => {
        const res = await fetch("/yourinternalapi/login", {
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            email: $("#email").val(),
            password: $("#password").val()
        }).then(r => r.json())
        // Our login response contains the OAuth Authorization Code
        window.location.href = redirect_uri + "&code=" + res.authorization_code

POST /oauth/token

Seam sends you an Authorization code it got from /authorize, as well as a Client ID of "seam" and Client Secret, which we will provide you. While testing your login flow, you can use "seamsecret" as your Client Secret.

You should return an Access Token, which can be a long random string, UUID, or signed JWT. You'll use this access token to allow seam to access Devices and Access Codes.

Seam will attach the access token in it's Authorization header like so: Authorization: Bearer <access_token>

Exchange an Authorization Code for an Access Token


Request Body




Authorization code from /authorize



The client_id should be "seam"



A secret provided to you by Seam.

  "access_token": "MODojXFjngsV8Z2xAymEi5CdCTo9ZpQf4tXTLO2L061ae"


Last updated


Š Seam Labs, Inc. All rights reserved.