LOCKET docs, for developers
The signing route (api/mint-auth.js) shares one library, api/_snag-mint-lib.js, with the same authorisation code a keeper would use elsewhere in the family. For LOCKET, that authorisation is only half the job. The route answers a wallet that asks for its own piece over HTTP, proving the buy happened; it never mints anything by itself. LOCKET has no funded keeper submitting mints on a buyer's behalf, because the contract only accepts the credited buyer as the transaction's sender, and only that buyer's own wallet can produce the sealed commitment and ciphertext a mint now carries. Finishing the mint, and later requesting a holder check, is the holder's own action, from their own connected wallet, paying their own gas.
POST { "txHash": "0x..." } to api/mint-auth.js. It refuses at the first failure, in this order, each with its own status code:
| Step | Status | Message |
|---|---|---|
| Method and JSON shape | 405 / 400 | POST only / Send a JSON object |
| txHash shape | 400 | txHash must be 0x and 64 hex characters |
| Config present | 503 | minting not connected |
| Per-IP budget | 503 / 429 | busy, try again shortly / too many authorisations from this address, wait a few minutes |
| Receipt reachable | 502 | chain not reachable |
| Transaction exists | 404 | transaction not found |
| Transaction succeeded | 400 | that transaction failed |
| Two confirmations | 409 | buy is too new, try again in a moment |
| Collection readable, not paused, right chain | 502 / 503 | collection not readable / minting is paused / wrong chain |
| A qualifying pool-to-buyer transfer | 400 | buy under the minimum / no buy from the pool in that transaction |
| Not already used | 409 | that buy already has its piece |
| Domain and digest match the contract | 502 | collection domain mismatch |
| Success | 200 | buyer, buyRef, amountIn, deadline, signature, collection |
Nothing is cleaned up on the caller's behalf. A malformed field is refused, never guessed at.
Six authorisations per client per ten minutes, counted by the first of x-vercel-forwarded-for, x-forwarded-for or x-real-ip. The store is bounded: expired windows are dropped first, and when every slot is held by a live caller a new caller is told the service is busy rather than evicting someone else's window.
Anyone holding SIGNER_KEY can authorise a mint for any address. That is the honest shape of this design: the chain proves the buy, but a server attests to it. The contract can rotate the signer (setSigner) and can be paused, and the owner is a two-step transfer that cannot be renounced, so a leaked key is recoverable. It is still a key, and it should live nowhere but the Vercel environment and the keeper's own shell.
There is no node scripts/snag-keeper.mjs run for LOCKET the way a plain buy-and-relay collection in this family would use one. Once the signing route answers, the holder's own wallet does the rest: build the encrypted commitment and ciphertext client-side after direct Lit identity discovery, then call mintForBuy directly, attaching the server's authorisation alongside that seal. The buyer's wallet pays the gas for that call, the same as any other on-chain action they take.
Opening later requires Lit TEE execution and a fresh read from pinned Robinhood Chain RPC. The Lit action sends an encrypted response to the holder browser. This is unverified live and stays disabled.
mintForBuy call fails or is never sent, the buy reference stays unused and the wallet stays unclaimed, so the same holder can simply try again with a fresh authorisation.