{"id":13454538,"url":"https://github.com/seamapi/prefixed-api-key","last_synced_at":"2025-05-15T16:01:49.412Z","repository":{"id":39884952,"uuid":"490874689","full_name":"seamapi/prefixed-api-key","owner":"seamapi","description":"Module for generating a prefixed API Key","archived":false,"fork":false,"pushed_at":"2025-02-10T20:03:13.000Z","size":112,"stargazers_count":297,"open_issues_count":10,"forks_count":13,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-05-11T15:46:54.812Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/seamapi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-05-10T22:08:18.000Z","updated_at":"2025-04-15T12:01:01.000Z","dependencies_parsed_at":"2024-01-14T07:17:21.142Z","dependency_job_id":"980eb655-9e02-4c6d-bac8-38042df92822","html_url":"https://github.com/seamapi/prefixed-api-key","commit_stats":{"total_commits":17,"total_committers":3,"mean_commits":5.666666666666667,"dds":"0.23529411764705888","last_synced_commit":"b599ea1e9715940ee5146f6111726a00bd3938b8"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seamapi%2Fprefixed-api-key","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seamapi%2Fprefixed-api-key/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seamapi%2Fprefixed-api-key/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seamapi%2Fprefixed-api-key/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/seamapi","download_url":"https://codeload.github.com/seamapi/prefixed-api-key/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254374388,"owners_count":22060609,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T08:00:55.128Z","updated_at":"2025-05-15T16:01:49.361Z","avatar_url":"https://github.com/seamapi.png","language":"TypeScript","readme":"# Prefixed API Key (Seam-style)\n\n\u003e Example key: `mycompany_BRTRKFsL_51FwqftsmMDHHbJAMEXXHCgG`\n\u003e\n\u003e [Discussion on Hacker News](https://news.ycombinator.com/item?id=31333933#31336542) \u0026middot; [Awesome Seam Open-Source](https://github.com/seamapi/awesome-seam)\n\nSeam-style API Keys have many advantages:\n\n- Double clicking the api key selects the entire api key\n- The alphabet is standard across languages thanks [to the base58 RFC](https://datatracker.ietf.org/doc/html/draft-msporny-base58) and its usage in cryptocurrencies\n- They are shorter than hex and base32 api keys\n- They have prefixes [allowing secret scanning by github](https://docs.github.com/en/code-security/secret-scanning/about-secret-scanning)\n- They have a hashed component so the server doesn't need to store the api key (reducing attack surface)\n- They have unhashed short tokens which can be mutually used by the server and key bearer/customer to identify the api key\n- They default to roughly the same number of entropy bits as UUIDv4\n\n## The Format\n\nSeam-style api keys look like this:\n\n```\nmycompany_BRTRKFsL_51FwqftsmMDHHbJAMEXXHCgG\n```\n\nLet's break down each component of the API key...\n\n```\nmycompany ..._...  BRTRKFsL ..._...  51FwqftsmMDHHbJAMEXXHCgG\n^                  ^                 ^\nPrefix             Short Token       Long Token\n```\n\n- The Prefix is used to identify the company or service creating the API Key.\n  This is very helpful in secret scanning.\n- The Short Token is stored by both the server and the key bearer/customer, it\n  can be used to identify an API key in logs or displayed on a customer's\n  dashboard. A token can be blocklisted by its short token.\n- The Long Token is how we authenticate this key. The long token is never stored\n  on the server, but a hash of it is stored on the server. When we receive an\n  incoming request, we search our database for `short_token` and `hash(long_token)`.\n\n## Getting Started\n\n```ts\nimport { generateAPIKey } from \"prefixed-api-key\"\n\nconst key = await generateAPIKey({ keyPrefix: 'mycompany' })\n\n// Store the key.longTokenHash and key.shortToken in your database and give\n// key.token to your customer.\n\nconsole.log(key)\n/*\n{\n  shortToken: 'BRTRKFsL',\n  longToken: '51FwqftsmMDHHbJAMEXXHCgG',\n  longTokenHash: 'd70d981d87b449c107327c2a2afbf00d4b58070d6ba571aac35d7ea3e7c79f37',\n  token: 'mycompany_BRTRKFsL_51FwqftsmMDHHbJAMEXXHCgG'\n}\n*/\n```\n\n## Utility Methods\n\n```ts\nimport {\n  hashLongToken,\n  extractLongToken,\n  extractShortToken,\n  checkAPIKey,\n  getTokenComponents,\n} from \"prefixed-api-key\"\n\nhashLongToken(\"51FwqftsmMDHHbJAMEXXHCgG\")\n// \"d70d981d87b449c107327c2a2afbf00d4b58070d6ba571aac35d7ea3e7c79f37\"\n\nextractLongToken(\"mycompany_BRTRKFsL_51FwqftsmMDHHbJAMEXXHCgG\")\n// \"51FwqftsmMDHHbJAMEXXHCgG\"\n})\n\nextractShortToken(\"mycompany_BRTRKFsL_51FwqftsmMDHHbJAMEXXHCgG\")\n// \"BRTRKFsL\"\n\ngetTokenComponents(\"mycompany_BRTRKFsL_51FwqftsmMDHHbJAMEXXHCgG\")\n/*\n{\n  shortToken: 'BRTRKFsL',\n  longToken: '51FwqftsmMDHHbJAMEXXHCgG',\n  longTokenHash: 'd70d981d87b449c107327c2a2afbf00d4b58070d6ba571aac35d7ea3e7c79f37',\n  token: 'mycompany_BRTRKFsL_51FwqftsmMDHHbJAMEXXHCgG'\n}\n*/\n\nawait checkAPIKey(\n  \"mycompany_BRTRKFsL_51FwqftsmMDHHbJAMEXXHCgG\",\n  \"d70d981d87b449c107327c2a2afbf00d4b58070d6ba571aac35d7ea3e7c79f37\"\n)\n// true\n```\n","funding_links":[],"categories":["TypeScript","Official Projects"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseamapi%2Fprefixed-api-key","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fseamapi%2Fprefixed-api-key","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseamapi%2Fprefixed-api-key/lists"}