docs
Get startedTroubleshootingPaymentsWebhooksAgent paymentsSwop MCPOviIdentity (swop.id)SwivyRPC (preview)API reference

Sign in with Swop

Let users log in to your app with their Swop account, using standard OpenID Connect, and give them the same wallet they have in Swop.

Preview: Swivy is not generally available

Swivy is in staging. It is not in production and Swop's own apps don't run on it yet. The SDK packages aren't published to npm; preview partners get access along with their credentials. Everything on this page can change. Request early access.

Sign in with Swop is a login button for your app, like "Sign in with Google". The difference: after login, your app can also reach the user's same Swop wallet: the same EVM and Solana addresses they have in the Swop app.

It's built on OpenID Connect (OIDC), the standard behind most "Sign in with…" buttons. If you've integrated Google or Apple login, you already know the flow: redirect, consent, code, tokens.

What your app gets

  • An id_token (a signed JWT) with who the user is, and an access_token.
  • With the wallets.read scope: access to the user's wallets once you exchange the token for a Swivy session.
  • A refresh_token that rotates on every use.

Sensitive wallet actions still need the user's passkey. A login token alone can't move money.

The flow

  1. Your app redirects the user to Swop's authorize URL with your client_id, redirect_uri, scopes and a PKCE challenge.
  2. Swop signs them in (or skips this if they're already signed in) with an email code or a wallet, and shows a consent screen the first time.
  3. Swop redirects back to your redirect_uri with a one-time code.
  4. Your app exchanges the code at the token endpoint for id_token, access_token and refresh_token. Verify the JWT with the issuer's JWKS like any OIDC provider.
  5. Exchange the token for a Swivy session in your own environment. Now you can show the user's wallets and submit intents.

Endpoints

Everything hangs off the issuer's discovery document:

GET {issuer}/oidc/{appId}/.well-known/openid-configuration
GET {issuer}/oidc/{appId}/jwks
GET {issuer}/oidc/{appId}/authorize
POST {issuer}/oidc/{appId}/token
GET {issuer}/oidc/{appId}/logout      (end_session_endpoint)

Discovery also returns the userinfo_endpoint, supported scopes and token auth methods. Use a standard OIDC client library and point it at discovery rather than hard-coding paths.

Scopes

ScopeGives you
openidRequired. The id_token.
profileBasic profile.
emailThe user's email.
wallets.readAccess to the user's wallets after the session exchange.

Scopes control what you can see. What a wallet can do still comes from your environment's policy.

Exchange the code for tokens

Browser and mobile apps are public clients: no client secret, PKCE required. Servers can be confidential clients with a secret.

curl -X POST "{issuer}/oidc/{appId}/token" \
  -H "content-type: application/json" \
  -d '{
    "grant_type": "authorization_code",
    "code": "ocd_...",
    "redirect_uri": "https://yourapp.example/auth/swop/callback",
    "client_id": "scid_...",
    "code_verifier": "your-pkce-verifier"
  }'

Refresh with "grant_type": "refresh_token". Each refresh returns a new refresh token; reusing an old one is rejected.

Turn the login into wallet access

Call the session exchange with your app's credentials and the token from Swop:

curl -X POST "{swivy-api}/v1/runtime/auth/oidc/exchange" \
  -H "content-type: application/json" \
  -H "x-swivy-app-id: app_..." \
  -H "x-swivy-publishable-key: pk_swivy_..." \
  -d '{ "token": "eyJ..." }'

The response has the same shape as an email login: sessionToken, identity, managedAccounts and linkedWallets. In the SDKs:

await swivy.authenticate({ method: 'oidc', token: idToken });

Why it's the same wallet: apps that sign in with Swop live in the same Swivy project as Swop. Inside one project, Swivy reuses the same wallet owner for each user, so the addresses match. Each app still keeps its own session, audit log and policy.

Logging out

Send the user to the end_session_endpoint with your client_id and a post_logout_redirect_uri that's registered on your client. Swop clears its session, revokes the matching refresh tokens and redirects back.

Who will use it

El Dorado, Chalk, Game Film AI and Decentrabet are planned to sign in with Swop once Swivy is in production.

Step up before wallet actions

Signing in proves who the user is. Before anything that moves money, your app still asks for a passkey approval in its own environment and attaches the challengeId to the intent:

// Browser (@swivy/web). In React, use useSwivyPasskeys().approveWithPasskey.
const approval = await swivy.approveWithPasskey(passkeyAuthMethodId, 'intent_approval');

const intent = await swivy.createTransactionIntentAndWait({
  accountId: wallet.id,
  chain: 'evm',
  challengeId: approval.challenge.challengeId,
  payload: { network: 'base-mainnet', transaction: { to: '0x1111111111111111111111111111111111111111', value: '0x0', data: '0x' } },
});

Under the hood that's createChallenge(authMethodId, purpose) then verifyChallenge(challengeId, response), which map to POST /v1/runtime/mfa/challenges and POST /v1/runtime/mfa/challenges/verify in the API reference.

On this page