Connect your app
An admin creates your app and lists your websites. Then pick the popup, the API, or both.
1. "Log in with Loop Wallet" popup
<script src="https://YOUR-HUB/sdk/loop-wallet.js"></script>
<script>
const lw = LoopWallet.init({ appId: "YOUR_APP_ID" });
loginButton.onclick = async () => {
const { address, session_token, verified } = await lw.login();
};
signButton.onclick = async () => {
const { signature, message_hash } = await lw.signTypedData(typedData); // SNIP-12
};
sendButton.onclick = async () => {
const { transaction_hash } = await lw.execute([{ contractAddress, entrypoint, calldata }]); // gas-free
};
</script>2. Partner API (server to server)
POST /api/public/v1/wallet/get-or-create { email }
POST /api/public/v1/wallet/verify-otp { email, code }
POST /api/public/v1/wallet/resend-otp { email }
GET /api/public/v1/wallet/:address/assets
POST /api/public/v1/wallet/sign { session_token, typed_data }
POST /api/public/v1/wallet/execute { session_token, calls: [{ contractAddress, entrypoint, calldata }] }
Header on every call: X-App-Key: lwk_...Keep your app key on your server. Browser calls are only accepted from your registered websites.
3. Tokens & NFTs API (Loop Do, Loop Fans, PressChain)
Base: /api/public/v1 Headers: Authorization: Bearer lwk_... Idempotency-Key: <uuid> (all writes)
Amounts are decimal strings ("12.5"). Errors: { error: { code, message, details } }
POST /wallets { externalId, kind?: user|collection_owner|treasury, label?, email? }
GET /wallets?externalId=… · /wallets/:id · /wallets/:id/balances · /wallets/:id/nfts
POST /tokens { name, symbol, initialSupply, swappable? }
POST /tokens/:id/mint { amount }
POST /tokens/:id/distribute { toWalletId | toAddress, amount }
POST /transfers { fromWalletId, toWalletId | toAddress, tokenId, amount }
POST /returns { walletId, tokenId, amount }
POST /swaps { walletId, fromTokenId, toTokenId, amount }
POST /collections { name, symbol, ownerWalletId, royaltyReceiver?, royaltyBps? }
PATCH /collections/:id/royalties { receiver, bps }
POST /collections/:id/freeze { confirm: true } (permanent)
POST /collections/:id/minters { address } DELETE /collections/:id/minters/:address
POST /collections/:id/nfts { toWalletId | toAddress, tokenUri, attributes?, media? }
GET|PATCH /collections/:id/nfts/:tokenId { tokenUri?, attributes?, media? }
POST /collections/:id/nfts/:tokenId/freeze { confirm: true }
POST /nft-transfers { collectionId, tokenId, fromWalletId, toWalletId | toAddress }
GET /transactions/:id · /transactions?status=&type=&walletId= · POST /transactions/:id/cancelWrites return 202 with a transaction (queued → submitted → confirmed/failed). Add ?wait=true to wait up to 45 s. Set a webhook address on the Dashboard to get signed transaction.confirmed / transaction.failed events (X-Signature: sha256=HMAC).
Wallets
Starknet accounts using the SNIP-9 class 0x02b486…ba1f. Their address is known up front and they deploy on first use, with gas paid by a paymaster.