# Account
Source: https://docs.rownd.io/administration/account
Your account is created when you sign into Rownd for the first time.
Your account information can be found in the "Account and Billing" section of
the platform. This includes your account name, Rownd subscription plan, and
billing information.
Your account name will be included in the invite email for teammates you invite
to your account.
We recommend that your account name matches the name of your company or product.
**Updating your account information**
1. In the [Rownd platform](https://app.rownd.io) open the top right corner menu under your username.
2. From the menu select **Account and billing.**
3. In the account and billing page, update your account name in the **Account
name** field, then press **Save**.
# Teams
Source: https://docs.rownd.io/administration/teams
Give team members access to co-manage aspects of your Rownd account.
#### Inviting new team members
First, sign into your Rownd account, click on the dropdown menu on the top right
and select **Manage team**.
On the **Team** page, click **Invite team member**.
Enter the new team member's **email** **address** and choose the **level of
access** to grant. There are three different **permission** levels:
* **Editor:** Can add and edit applicationsbut cannot invite team members or
modify account settings.
* **Admin:** Full account control over apps, team members, billing, etc.
* **View-only:** Can view most aspects of the platform but cannot make any
changes.
Click **Save** to send the invitation. Your team member will receive an email
containing a link that will automatically sign them into Rownd and prompt them
to accept or decline the invitation to join your account.
Once the invitation is sent, the new team member will show as **pending** until
they've accepted the invitation.
Once they've accepted the invitation, the pending status will be removed.
#### Editing a team member's access
Click **Edit** next to the team member whose access you want to modify.
Choose an updated **permission** level for the team member. Then click **save**
to update.
#### Removing a team member
Click **Delete** next to the team member who you want to remove
On the resulting confirmation dialog, click **Delete** to confirm the action.
The team member will be removed from your account.
# Create a magic link
Source: https://docs.rownd.io/api-reference/authentication/create-magic-link
POST /hub/auth/magic
Generate a magic link
# Create a magic link
Source: https://docs.rownd.io/api-reference/authentication/create-user-magic-link
POST /me/auth/magic
Enables the user identified by their access token to create a magic link for themselves. Useful for signing in to a new device via QR code, among other things.
# Overview
Source: https://docs.rownd.io/api-reference/authentication/overview
Rownd's API leverages two authentication mechanisms depending on which operation you're invoking. **User-scoped** APIs enable your users to manage their profile information, register passkeys, set preferences, and so on. **App-scoped** APIs allow you to manage aspects of your app, read and update user profiles, add or remove users, and fetch keys necessary for validating a user's bearer token.
Rownd leverages API keys for app-scoped authentication. You'll see these referred to as "app keys" throughout the platform and documentation.
To generate a new app key/secret pair, see this [reference guide](/configuration/app-credentials).
### App-scoped authentication
When making calls to the Rownd REST API, you must include your app key/secret pair in the request headers. The app key is used to identify the app making the request, and the secret is used to authenticate the request.
Ensure the following headers are present:
* `X-Rownd-App-Key: `
* `X-Rownd-App-Secret: `
User-initiated requests leverage bearer token authentication, which is generated when a user signs in. You'll usually leverage this token from one of our SDKs in order to call user-based Rownd APIs in addition to your own API stack.
### User-scoped authentication
In most cases, Rownd's SDKs and the Rownd Hub call Rownd APIs on behalf of a user. In these cases, the user's bearer token is included in the request headers. The bearer token is used to identify the user making the request, and to authenticate the request.
We recommend that you use Rownd bearer tokens to authenticate users against your own API or service. Since Rownd's tokens are signed asymmetrically, you can use our public JWK set to validate a token's signature.
If you're using a Rownd server SDK (e.g., Node.js), convenience methods or middleware are provided to automatically validate a bearer token and attach the user's profile to the request object.
Use these endpoints to fetch our OIDC and/or JWK configurations:
* [OIDC configuration](/api-reference/authentication/retrieve-oidc)
* [JWK set](/api-reference/authentication/retrieve-jwk)
# Retrieve Rownd JWK set
Source: https://docs.rownd.io/api-reference/authentication/retrieve-jwk
GET /hub/auth/keys
Retrieve the current JWK set that validates Rownd-issued tokens
# Retrieve OIDC configuration
Source: https://docs.rownd.io/api-reference/authentication/retrieve-oidc
GET /hub/auth/.well-known/oauth-authorization-server
# Groups overview
Source: https://docs.rownd.io/api-reference/groups/overview
Groups API documentation
With Rownd groups, you can segment your application users into logical segments. Each segment contains group members
which are tied back to application users via their `user_id`. With the group APIs, you can add a group member
directly or by creating a group invite. Group invites result in a one-time-use link that you can send to a
user that when visited adds them to the group with specific roles. Each group member is assigned to roles,
which are an array of strings like `"admin"` or `"editor"`. You can specify member roles via member creation
or updates, or during an invite creation.
The groups APIs are split into two sets that differ slighly on imlementation: [Platform](#platform) and
[User-Facing](#userfacing)
## Platform
The [platform](/api-reference/groups/platform/group-create) APIs accept Rownd application credentials for authentication. They are intended for use by an
application administrator. You should use these APIs on your backend server or equivalent to manage groups,
members, and invites
## User-Facing
The [user-facing](/api-reference/groups/user/group-create) APIs accept an authenticated user's Rownd access token (JWT) for authentication. This set of APIs is intended for use in frontend applications when you want to give your
users the ability to manage their own groups, members, and invites.
### User-Facing Distinctions
The user-facing APIs differ slightly in implementation. Here are the main differences:
#### Authorization
Group members and invites can only be managed by group owners. A group owner is a group member that has the
`"owner"` role.
#### Group Owners
The creator of a group is always given the `"owner"` role.
## Getting Started
Here are a few key endpoints to help you get started integrating Groups into your app:
Platform API for creating a group
Platform API for creating a group invite
Platform API for updating a group member
Platform API for deleting a group member
# Create a group
Source: https://docs.rownd.io/api-reference/groups/platform/group-create
POST /applications/{app}/groups
Platform API for creating a new group
# Delete a group
Source: https://docs.rownd.io/api-reference/groups/platform/group-delete
DELETE /applications/{app}/groups/{group}
Platform API for deleting a group
# List groups
Source: https://docs.rownd.io/api-reference/groups/platform/group-list
GET /applications/{app}/groups
Platform API for listing all groups belonging to an app
# Retrieve a group
Source: https://docs.rownd.io/api-reference/groups/platform/group-read
GET /applications/{app}/groups/{group}
Platform API for retrieving a group
# Update a group
Source: https://docs.rownd.io/api-reference/groups/platform/group-update
PUT /applications/{app}/groups/{group}
Platform API for updating a group
# Create a group invite
Source: https://docs.rownd.io/api-reference/groups/platform/invites/invite-create
POST /applications/{app}/groups/{group}/invites
Platform API for creating a group invite
# Delete a group invite
Source: https://docs.rownd.io/api-reference/groups/platform/invites/invite-delete
DELETE /applications/{app}/groups/{group}/invites/{invite}
Platform API for deleting a group invite
# List group invites
Source: https://docs.rownd.io/api-reference/groups/platform/invites/invite-list
GET /applications/{app}/groups/{group}/invites
Platform API for listing group invites
# Retrieve a group invite
Source: https://docs.rownd.io/api-reference/groups/platform/invites/invite-read
GET /applications/{app}/groups/{group}/invites/{invite}
Platform API for retrieving a group invite
# Update a group invite
Source: https://docs.rownd.io/api-reference/groups/platform/invites/invite-update
PUT /applications/{app}/groups/{group}/invites/{invite}
Platform API for updating a group invite
# Create a group member
Source: https://docs.rownd.io/api-reference/groups/platform/members/member-create
POST /applications/{app}/groups/{group}/members
Platform API for creating a member within the group. You can create a member by providing a user
ID or a user lookup value like an email address or phone number. The first member created within
a group will automatically be assigned the `'owner'` role.
# Delete a group member
Source: https://docs.rownd.io/api-reference/groups/platform/members/member-delete
DELETE /applications/{app}/groups/{group}/members/{member}
Platform API for deleting a group member
# List group member
Source: https://docs.rownd.io/api-reference/groups/platform/members/member-list
GET /applications/{app}/groups/{group}/members
Platform API for listing group members
# Retrieve a group member
Source: https://docs.rownd.io/api-reference/groups/platform/members/member-read
GET /applications/{app}/groups/{group}/members/{member}
Platform API for retrieving a group member
# Update a group member
Source: https://docs.rownd.io/api-reference/groups/platform/members/member-update
PUT /applications/{app}/groups/{group}/members/{member}
Platform API for updating a group member
# Create a group
Source: https://docs.rownd.io/api-reference/groups/user/group-create
POST /me/groups
User-facing API for creating a new group. The callee is automatically added with the `"owner"` role.
# Delete a group
Source: https://docs.rownd.io/api-reference/groups/user/group-delete
DELETE /me/groups/{group}
User-facing API for deleting a group
# List groups
Source: https://docs.rownd.io/api-reference/groups/user/group-list
GET /me/groups
User-facing API for listing groups
# Retrieve a group
Source: https://docs.rownd.io/api-reference/groups/user/group-read
GET /me/groups/{group}
User-facing API for retrieving a group
# Update a group
Source: https://docs.rownd.io/api-reference/groups/user/group-update
PUT /me/groups/{group}
User-facing API for updating a group
# Create a group invite
Source: https://docs.rownd.io/api-reference/groups/user/invites/invite-create
POST /me/groups/{group}/invites
User-facing API for creating a group invite. An invite can be created for a user by providing
their `user_id`, `email`, or `phone`. Once accepted, the user will be added as a member within
the group and be assigned the roles specified in the invite.
# Delete a group invite
Source: https://docs.rownd.io/api-reference/groups/user/invites/invite-delete
DELETE /me/groups/{group}/invites/{invite}
User-facing API for deleting a group invite
# List group invites
Source: https://docs.rownd.io/api-reference/groups/user/invites/invite-list
GET /me/groups/{group}/invites
User-facing API for listing group invites
# Retrieve a group invite
Source: https://docs.rownd.io/api-reference/groups/user/invites/invite-read
GET /me/groups/{group}/invites/{invite}
User-facing API for retrieving a group invite
# Update a group invite
Source: https://docs.rownd.io/api-reference/groups/user/invites/invite-update
PUT /me/groups/{group}/invites/{invite}
User-facing API for updating a group invite
# Create a group member
Source: https://docs.rownd.io/api-reference/groups/user/members/member-create
POST /me/groups/{group}/members
User-facing API for creating a group member
# Delete a group member
Source: https://docs.rownd.io/api-reference/groups/user/members/member-delete
DELETE /me/groups/{group}/members/{member}
User-facing API for deleting a group member
# List group members
Source: https://docs.rownd.io/api-reference/groups/user/members/member-list
GET /me/groups/{group}/members
User-facing API for listing group members
# Retrieve a group member
Source: https://docs.rownd.io/api-reference/groups/user/members/member-read
GET /me/groups/{group}/members/{member}
User-facing API for retrieving a group member
# Update a group member
Source: https://docs.rownd.io/api-reference/groups/user/members/member-update
PUT /me/groups/{group}/members/{member}
User-facing API for updating a group member
# Create an OpenID Connect client
Source: https://docs.rownd.io/api-reference/oidc/clients/create
POST /applications/{app}/oidc-clients
Platform API for creating an OIDC client for an application
# Delete an OpenID Connect client
Source: https://docs.rownd.io/api-reference/oidc/clients/delete
DELETE /applications/{app}/oidc-clients/{client}
Platform API for deleting an OIDC client for an application
# List OpenID Connect clients
Source: https://docs.rownd.io/api-reference/oidc/clients/list
GET /applications/{app}/oidc-clients
Platform API for retrieving OIDC clients for an application
# Retrieve an OpenID Connect client
Source: https://docs.rownd.io/api-reference/oidc/clients/read
GET /applications/{app}/oidc-clients/{client}
Platform API for retrieving an OIDC client for an application
# Update an OpenID Connect client
Source: https://docs.rownd.io/api-reference/oidc/clients/update
PUT /applications/{app}/oidc-clients/{client}
Platform API for updating an OIDC client for an application
# Delete a user profile
Source: https://docs.rownd.io/api-reference/user-profiles/app/delete
DELETE /applications/{app}/users/{user}/data
Delete a user profile
# Get sample user profile data
Source: https://docs.rownd.io/api-reference/user-profiles/app/get-sample-data
GET /applications/{app}/users/__sample__/data
Retrieve sample user data
# Retrieve a user profile
Source: https://docs.rownd.io/api-reference/user-profiles/app/get-user-data
GET /applications/{app}/users/{user}/data
Retrieve a user profile
# Insert or update user profile data
Source: https://docs.rownd.io/api-reference/user-profiles/app/insert-update
PUT /applications/{app}/users/{user}/data
Insert or update user profile data
# List user profiles
Source: https://docs.rownd.io/api-reference/user-profiles/app/list-user-profiles
GET /applications/{app}/users/data
# Retrieve one field from a user profile
Source: https://docs.rownd.io/api-reference/user-profiles/app/retrieve-field
GET /applications/{app}/users/{user}/data/fields/{field}
Retrieve the value of one field in a user profile
# Update one field in a user profile
Source: https://docs.rownd.io/api-reference/user-profiles/app/update-field
PUT /applications/{app}/users/{user}/data/fields/{field}
Update the value of one field in a user profile
# Update / patch user profile data
Source: https://docs.rownd.io/api-reference/user-profiles/app/update-patch
PATCH /applications/{app}/users/{user}/data
Updates user profile data
# Retrieve a user profile
Source: https://docs.rownd.io/api-reference/user-profiles/user/get-user-data
GET /me/applications/{app}/data
Retrieve user profile
# Retrieve one field from a user profile
Source: https://docs.rownd.io/api-reference/user-profiles/user/retrieve-field
GET /me/applications/{app}/data/fields/{field}
Retrieve the value of one field in a user profile
# Update one field in a user profile
Source: https://docs.rownd.io/api-reference/user-profiles/user/update-field
PUT /me/applications/{app}/data/fields/{field}
Update the value of one field in a user profile
# Update user profile data
Source: https://docs.rownd.io/api-reference/user-profiles/user/update-put
PUT /me/applications/{app}/data
Update user profile
# Revoke all user tokens/sessions
Source: https://docs.rownd.io/api-reference/user-sessions/app/revoke-user-sessions
POST /applications/{app}/users/{user}/signout
Revokes all tokens for the specified user causing them to be signed out on all devices.
# App credentials
Source: https://docs.rownd.io/configuration/app-credentials
Learn how app keys work with Rownd code snippets, SDKs, and APIs.
When your code interacts with Rownd through an SDK, JavaScript code snippet, or directly with our REST API, you'll need a set of credentials to authenticate your access to the Rownd platform. At Rownd, we call these "app keys" and "app secrets." Every application provides a default app key, but you can create as many additional keys as you need.
The app key is a *publishable* value, meaning it isn't intended to be private. You'll use an app key in all of your user-facing code, such as React or Vue apps, websites, mobile apps, etc.
Each app key has an associated app secret that will be visible to you only once. App secrets are *private* values, meaning you should limit the number of people who have access to them. You should also take care to ensure they are not included in publicly visible configuration files, mobile app binaries, website deployments, and so on. They should exist only within your backend server environments or secrets manager.
You can revoke an app key and its associated secret at any time through the [Rownd dashboard](https://app.rownd.io). Be careful, though! Revoking a key that's still in use will likely result in downtime for your app. Ensure you generate new app keys and update your deployments with them before revoking existing keys.
##### What's the difference?
**App keys** help identify your application, enable the retrieval of certain application metadata, and initiate authentication from web or mobile.
**App secrets** authenticate machine-to-machine communication with Rownd to retrieve and update any user profile, generate sign-in (magic) links for any user, and support other more sensitive/restricted functions.
#### Working with app keys
From the Rownd dashboard, select the application for which you want to generate an app key, then select **App keys** from the side navigation.
#### Creating a new app key
Press the **Add app key** button on the top-right side of the screen. A new app key and secret are generated, then the **Edit app key** dialog is displayed, which contains the name of the app key, the key itself, and its associated secret.
Be sure to copy and store the app secret in a safe location, since it will be shown only once! Opening the "edit app key" dialog again will show a masked version of the secret.
You can rename the app key to something that makes sense to you, then press **Save** to save it.
#### Updating an app key
1. Click on the three dots beneath the **Action** column on the right side of the app keys table.
2. From the resulting menu, select **Edit** to modify the name of the key (the key and secret are immutable).
3. Make the desired modifications and press **Save** to finish.
#### Deleting / revoking an app key
1. Click on the three dots beneath the **Action** column on the right side of the app keys table.
2. Press **Delete** to initiate the deletion process. A confirmation dialog will appear.
3. Press **Delete** within the dialog to permanently revoke the key. It will immediately stop working.
# Applications
Source: https://docs.rownd.io/configuration/applications
Rownd applications connect to your product(s) to provide Rownd authentication to your users.
A Rownd application contains a unique code snippet that, when injected across
your product, provides user authentication to your platform. Within your Rownd
application, you can define and customize authentication methods, data types,
and more. You can also connect a Rownd application to your existing tools with
Integrations. It is likely that one Rownd application is enough to span all
aspects of your product, but you can create multiple Rownd apps in your account
as needed. However, a user session cannot span multiple applications.
Your application name is used in all verification messages used to authenticate
your users. We recommend using the name of your company or product for your
application name.
### Edit an application
Rownd creates a sample application during initial account setup. You can edit it to suit your needs.
Modify the name, description, and logo of your existing application from
the **Settings** tab.
1. On the Settings tab, set the **Application name** and **Application description** as desired.
2. Drag and drop a logo (PNG or SVG) into the **Application logo** area, or click within it to display a file picker.
3. Press **Save edits** when finished.
#### Create a new application
You may want to create additional applications for separate products or for dev/test environments.
To create a new application:
1. Click the application dropdown in the top left corner, and select **Create new
application** from the list.
2. In the next screen, enter an application name. Optionally, provide a description and logo.
3. Press **Create**.
4. Your newly created app will open to its Home tab.
#### Switch to another application
If you have multiple Rownd applications, you can switch between them using the application switcher.
1. Press the application switcher in the top left corner of the sidebar.
2. Select a different application from the list of applications.
Not seeing the application you're looking for?
* Try selecting **switch account** in the top right dropdown menu to see if the
application you are looking for is associated with a different account.
* Are you signed in with the correct user identifier (e.g., email address)? It's possible that the application
you are looking for is associated with an account your current user doesn't have access to. Try signing out and
signing back in with a different email address or social provider.
#### Delete an application
If you wish to delete an application, you can delete it from the **Settings** tab.
1. From the Settings tab, scroll to the bottom and press **Delete application**.
2. In the modal that appears, confirm you want to delete the app by pressing **Delete**.
Deleting your Rownd application completely removes all application data from
Rownd. If the application is being used to authenticate users in your product,
deleting it will prevent any further registrations or authentications.
# Sign in with Apple
Source: https://docs.rownd.io/configuration/authentication-methods/apple
Sign in with Apple offers a fast, secure, and privacy-focused method for users to sign in to their accounts on your website and mobile apps. By leveraging the Apple ecosystem, this feature enables users to authenticate using their existing Apple ID without having to create a new account or remember an additional password.
When enabled, users can take advantage of the strong security and privacy features provided by the Apple platform, including two-factor authentication and email private relay. By offering this sign-in method, you can streamline the authentication process for your users and reduce barriers to entry, resulting in an improved user experience.
In addition to its ease of use and enhanced security, Sign in with Apple complies with various privacy regulations, helping you maintain compliance and protect your users' data. By providing a trustworthy and user-friendly authentication option, you can attract more users to your platform and foster trust in your services.
## Configuring Sign in with Apple
Using Rownd to add "Sign in with Apple" to your app is quick and easy, usually requiring no code changes. Our implementation supports iOS, Android, and web clients so no matter how your users are accessing your app or service, they can always sign in with their method of choice.
To enable Sign-in with Apple, complete the following steps.
#### Configuring Xcode and an Apple Services ID
1. If you're developing an iOS or macOS app, enable the **Sign in with Apple** capability in Xcode. [See Apple's documentation for more information.](https://developer.apple.com/documentation/xcode/adding-capabilities-to-your-app)
2. Create an [Apple Services ID](https://developer.apple.com/account/resources/identifiers/list/serviceId) for your app. Note the identifier for use in the next step. Ensure that this Callback URL is set within the Services ID: `https://api.rownd.io/hub/auth/apple/callback`
#### Configuring Rownd
Now, open your app in the [Rownd platform](https://app.rownd.io/applications). Then click on the **Sign-in methods** tab on the left to adjust your flow.
1. Locate the **Sign in with Apple** authentication method and press **Enable**.
2. Enter the Services ID that you created in the previous section.
3. Ensure the **Allow for authentication** switch is turned on.
4. Press **Save.**
That's it! Your app and/or website is now ready to handle sign-in requests for users with an Apple ID.
# Email sign-in
Source: https://docs.rownd.io/configuration/authentication-methods/email
Email-based Authentication with Rownd Sign-in Links offers a secure and user-friendly way for users to access their accounts on your website and mobile apps.
Email-based authentication using Rownd Sign-in Links provides a secure and user-friendly method for users to sign in to their accounts on your website and mobile apps. With this approach, users don't need to remember complex passwords or create new accounts. Instead, they simply enter their email address and receive a unique sign-in link directly within their inbox, which they can use to securely access their account.
**Improve Email Deliverability with Custom Domains**
Using a custom domain for your authentication emails can significantly improve deliverability rates and enhance your brand's credibility. When your sign-in links come from your own domain instead of a third-party one, email providers are less likely to flag them as suspicious.
Learn more about setting up [Custom Domains](/configuration/custom-domains/overview) to enhance your authentication experience.
This method of authentication is especially convenient for users, as it eliminates the need for password management and reduces the risk of password-related security breaches. By sending a one-time-use sign-in link to the user's email address, you can ensure that only the account owner can access the account.
Rownd Sign-in Links are designed to be straightforward for both developers and users. Integration is seamless, and the process is intuitive for users, streamlining the authentication experience on your platform.
Incorporating email-based authentication with Rownd Sign-in Links not only improves the user experience but also enhances the security of your platform, helping you build trust with your users and maintain a secure environment for their data.
#### Enabling email authentication
1. Navigate to **Sign-in methods** in the [Rownd dashboard](https://app.rownd.io).
2. Toggle the switch for **Email** to the "on" position.
3. Click **Save**.
#### Browser Fingerprinting and Reverification for Returning Users
Rownd uses browser fingerprinting to enhance the sign-in experience for returning users. When a user signs in with email authentication, Rownd securely associates their session with device metadata to form a private, temporary fingerprint. This allows returning users to sign back in—within a configurable time window—without going through the full email verification process again.
Additionally, Rownd remembers the last sign-in method used. If a user has multiple authentication options, we’ll surface the one they last used to simplify the experience.
Browser fingerprinting in Rownd is privacy-conscious and session-bound. It doesn’t track users across websites—it simply reduces friction for repeat visits on personal devices.
#### Customizing email messages
Rownd allows you to change portions of the email to better match your brand. See our [email customization article](/configuration/customizations/email-customization) for more information.
# Validating third-party authenticators
Source: https://docs.rownd.io/configuration/authentication-methods/existing-authentication
Rownd's token validator allows you to authenticate a token issued by another authentication provider and exchange it for a Rownd token. This feature is useful when migrating to Rownd from another authentication provider and you want to prevent existing users from being signed-out during the transition. It can also be used when moving between contexts, such as when your code is embedded in an implementation that you don't directly control (e.g., a webview inside someone else's mobile app).
Use Rownd's [token validator integration](/configuration/integrations/token-validator) to configure this feature.
# Sign in with Google
Source: https://docs.rownd.io/configuration/authentication-methods/google
Turn on the Google authentication method to allow users to sign in with their Google accounts on your website and mobile apps.
Sign in with Google is a widely-used, secure authentication method that allows users to quickly sign in to their accounts on your website and mobile apps using their existing Google accounts. By offering this option, you can simplify the authentication process for your users, eliminating the need for them to create a new account or remember an additional password.
Integrating Sign in with Google streamlines the user experience, as millions of people worldwide already have Google accounts for services like Gmail, Google Drive, and YouTube. By leveraging the familiar Google ecosystem, you can lower the barrier to entry for your platform and potentially increase user engagement.
In terms of security, Google provides robust measures such as two-factor authentication, helping protect users' accounts from unauthorized access. Furthermore, integrating Sign in with Google can help you comply with various privacy regulations and safeguard your users' data.
By incorporating Sign in with Google into your authentication options, you can enhance user convenience, improve security, and foster trust in your platform.
**New Feature: Google One Tap**
As the name implies, Google One Tap is a streamlined authentication option that allows users to sign in to websites and apps with just one tap on their device if they're already signed-in to a Google account. With One Tap, users can sign in quickly and easily, without having to remember a password, manually enter any credentials, or leave your product. Our customers typically see an instant increase in sign-ups when Google One Tap is enabled.
## Prerequisites
Before you turn on Google Sign-in, you'll need to do a few things in the Google
Cloud Platform.
#### OAuth Web Client ID
Use
[these instructions](https://support.google.com/workspacemigrate/answer/9222992?hl=en)
from Google to create an OAuth web client ID. You'll need this client ID to
configure Rownd for all deployments regardless of web or mobile app.
The OAuth client ID's **Authorized JavaScript Origins** should contain any sites
on which you will embed Rownd and support Google Sign-in. If you are only using
Rownd on your mobile apps, you can leave this list empty
#### OAuth iOS Client ID (optional)
If you are adding Rownd to an iOS app, you'll need to create another OAuth
client ID. In the Google Cloud Platform you can create one just like before, but
this time, set the application type to "iOS". You'll be asked to provide your
app's bundle ID, App Store ID, and team ID.
When you finish creating the client ID, take note of the **iOS URL Scheme**
value. You will need this later when adding a custom URL scheme to your iOS app.
This value will be the reversed client ID value and look something like this:
```
com.googleusercontent.apps.224565757208-05divavgck1qgqg9b58piodfhqb55h90
```
For detailed instructions check out this
[documentation](https://support.google.com/cloud/answer/6158849?hl=en#zippy=%2Cnative-applications%2Cios)
#### OAuth Android Client ID (optional)
If you are adding Rownd to an Android app, you'll need one more OAuth client ID.
Use an existing one or create a new one in the Google Cloud Platform just the
same as before with your web or iOS client ID. When creating, make sure to
select the "Android" application type. Provide your app's package name and SHA-1
fingerprint.
For detailed instructions check out this
[documentation](https://support.google.com/cloud/answer/6158849?hl=en#zippy=%2Cnative-applications%2Candroid)
### Enabling Google Sign-in
Once you have completed the prerequisites, you can configure Rownd to enable
Google Sign-in.
1. Navigate to the [Rownd Platform](https://app.rownd.io), and select your
desired application is from the application switcher.
2. Select the **Sign-in methods** option on the left to adjust your flow.
3. Scroll down to view the authentication methods, and click **Enable** next to
**Google**.
4. On the configuration screen, enter the following information:
* **Google OAuth Client ID** - Enter your OAuth web client ID that you created as the first prerequisite step
* **Google OAuth Client Secret -** Enter the client secret associated with your OAuth web client ID
* **Google iOS OAuth Client ID** - Enter your OAuth iOS client ID that you created as a prerequisite
* **Google OAuth Scopes** - (Optional) Enter additional OAuth scopes that you would like to request from the user during authentication. By default Rownd will request `email` and `profile`. Most of the time, you don't need to provide a value in this field.
If you are using Rownd on an Android app, you do not need to configure your
Android Client ID in the Rownd platform. Google uses the package name and SHA-1
fingerprint that you provided when creating the OAuth client ID to authenticate
your app.
## Enabling Google One Tap
Google One Tap is a streamlined authentication system that allows users to sign in to websites and apps with just one tap on their device. With One Tap, users can sign in quickly and easily, without having to remember a password or manually enter any credentials. One Tap is designed to simplify the sign-in process and improve the user experience, while also providing strong security features such as two-factor authentication and anti-phishing protections.
### Set up:
1. Pre-requisite: Ensure Google is configured as described above.
2. Click the Google One Tap checkbox
3. If desired, adjust the **Prompt after** field to indicate how long the user should be on the page before being prompted to sign in. This may require some experimentation, since prompting too quickly might be bothersome, while delaying too long might cause the prompt to seem random or out of place. The default of seven seconds works well for many use cases, but your particular website or app may require different settings.
4. Presss **Update**, then press **Save** in the top left corner.
Google One Tap has a cooldown period that is enforced by Google. If the end-user clicks the close button, the dialog will not appear for between 7 and 60 minutes. When testing this feature, be aware that if intentionally close the Google One Tap dialog, the popup will not appear again until the cooldown period ends.
#### One last thing for iOS Apps
When Google finishes signing in a user, it calls back into your app on a custom
URL scheme. You'll need to define this inside your XCode project settings.
1. Click on your project in Xcode, and then select your app under **TARGETS**
2. Next, go to the **Info** tab and scroll down to the bottom of the view where
you see **URL Types**
3. Expand **URL Types** and click the **+** icon to add a new value
4. Set the **URL Schemes** value to the URL Scheme (reversed iOS Client ID)
value that you noted when creating the OAuth iOS client ID earlier. Again,
this value will look something like:
`com.googleusercontent.apps.422565757208-05dqvvigck1qgqg9b58piodfhqb55h90`
That's it!
Your iOS app with the above changes needs to be published to the App Store *before* enabling Sign in with Google in the Rownd platform. If you want to enable Sign in with Google on Android and web before your app update has been reviewed by Apple, remove the **iOS Client ID** from the Rownd platform configuration. When your app update goes live, restore the **iOS Client ID** in the Rownd platform.
### Finishing up
At this point, you're all done! Make sure you save the Google configuration
inside of the Rownd Platform. When you are ready to turn it on, click the toggle
to enable Google Sign-in. Your users will then see a new option in the Rownd
sign-in dialog to continue with Google.
# Sign in as guest
Source: https://docs.rownd.io/configuration/authentication-methods/guests
Authentication should often be a gradual process. Users may not want to provide identifiable information when trying your product for the first time. Or, if your product uses sensitive information like health data, users may not want to link that data to their identity at all.
For these and other use cases, Rownd offers *guest authentication*, which provides a mechanism for users to onboard your product anonymously—-no email address, phone number, or other contact information is required.
## How it works
After enabling the **Guests** sign-in method, Rownd will display the option **Continue as guest** in the sign-in modal. Or, if you're writing custom code, you can trigger a guest sign-in automatically on behalf of a visitor who has not yet signed in.
Rownd doesn't request any identifiers for this user, but simply generates a unique ID for their account. Any profile information that's collected will be associated with this unique ID.
Traditionally, using a guest account presented difficulty when signing into that same account on other devices or after signing out. To prevent this issue, Rownd supports [Passkeys](./passkeys) so that even anonymous users can sign into their account across multiple devices that have access to the Passkey.
Passkeys for guests identify a user only by their random unique identifier. No personal information is associated with a Passkey.
### Progressive profiles
Once a user has tried your product, they may feel more confident in sharing personal details in order to preserve their account, receive customer service, and so on. Leveraging [Automations](), you can prompt these users to add identifiable information at strategic points within a user journey.
### Detecting guests
While you might allow guests to use certain aspects of your product, you may want to limit their access to specific features. Whether as a means of upselling or because a specific feature relies on identifiable information, you can detect guests in one of two ways.
1. **Inspect the user's access token:** When a user signs in anonymously, their JWT (access token) is annotated to indicate that they are a guest. The JWT claim looks like this: `https://auth.rownd.io/is_anonymous: true`.
2. **Inspect the user's profile:** Users who originally signed in as a guest will have an `anonymous_id` field populated within their profile. Check if this is present without any other identifiers like email, phone number, wallet address, etc.
## Enabling guest sign-in
1. Navigate to the [Rownd dashboard](https://app.rownd.io/)
2. Select **Sign-in methods** from the sidebar
3. Press **Enable** within the **Guests** sign-in chip.
4. Press **Save** to publish your changes.
# Instant Users
Source: https://docs.rownd.io/configuration/authentication-methods/instant-users
Turn every visitor into a user, instantly
Instant Users captures visitors as users when they land on your website, web app, or mobile app. Are your users seeing the value in your product before they are forced to sign up? With Instant Users, you don't have to worry about this. Our Instant users feature ensures users can explore and experience your app without barriers, making it easier for them to see the value and commit to signing up when they're ready.
## Enabling Instant Users
Enabling Instant Users is easy and does not require any additional code. Simply follow the steps below to enable Instant Users for your application.
1. Open your app in the [Rownd platform](https://app.rownd.io). Click on the **Settings** tab on the left to adjust your flow and then select the "User Settings" tab.
.
2. Toggle on "Instant Users" and the cleanup timeline. This is how long of inactivity before instant users are "cleaned up". Every use-case is different and our default i 30 days.
3. To confirm your changes, press **Save** in the upper right-hand corner of the page.
## The User Spectrum
Instant users is the first step along the Rownd User Spectrum. An instant user gets granted a JWT, that JWT has a normal lifecycle and security, and the goal is to show your user enough of your app and get them comfortable aenough to either login as a guest, enter a piece of verifiable data, or login with a verifiable email or phone number (either manually or through a social sign-in)
### The Spectrum:
1. **Instant user**: Upon initial visit, a new visitor receives a user ID as they move through your app, starting as a partial profile.
2. **Guest user**: Visitors can continue as guests, maintaining progress and exploring your app without immediate sign-up.
3. **Unverified user**: Users can provide an email without verification, reducing friction and allowing continued app use.
4. **Verified user**: Eventually, users provide verifiable information, like an email or Google account, to fully sign up and re-access their account.
.
# OpenID Connect (OIDC) and OAuth2
Source: https://docs.rownd.io/configuration/authentication-methods/oauth
Leverage existing OAuth-compliant identity providers
While Rownd provides a superior authentication experience for most users, there may be occasions where end-users need to authenticate with a third-party system.
This can be especially important when dealing with corporate SSO requirements. CISO policy may require that all users sign in through an in-house identity provider or an enterprise cloud provider like Microsoft or Google. (If you're looking for Google authentication, we highly recommend using our [built-in Google authentication method.](./google))
Follow the steps below to configure Rownd to interoperate with your target OpenID or OAuth2 server.
If you require a SAML authentication flow, please [get in touch](mailto:support@rownd.io).
## Supported flows
Rownd supports the following authentication flows:
* Authorization code flow
* Authorization code flow with proof key for code exchange (PKCE)
* Authorization code flow with JWT-secured authorization requests
## Configuring an OpenID or OAuth2 client
Before getting started, be sure you obtain a valid client ID and--if required--client secret or private key from your OAuth provider.
1. From the [Rownd platform](https://app.rownd.io), navigate to the **Sign-in methods** sidebar tab.
2. In the *Additional sign-in methods* section, select **Enable additional methods**.
3. From the *Add additional sign-in methods* dialog, locate the **Custom** option and select **Add**.
4. Enter a name for the authentication method (e.g., My SSO provider) and optionally upload light and dark mode icons that will represent this authentication method.
5. Select the type of authentication flow: OpenID or OAuth2.
6. *(Required for OpenID)* Provide the issuer's base URL which hosts the `/.well-known/openid-configuration` endpoint (e.g., `https://auth.mycorp.com`).
7. Provide the default scopes that should be included in every authentication request. You can conditionally include additional scopes at authentication time.
8. Click **Next** to continue to the next step.
9. Enter your **Client ID**
10. If applicable, select the type of *client authentication* your provider requires and then paste the authentication secret in the provided input.
11. *(OAuth2 only)* Provide applicable values for the various authorization server endpoints (e.g., authorization endpoint, token endpoint, JWK endpoint, etc).
12. Press **Enable** at the bottom of the dialog to add the sign-in method to your available authentication options. The dialog will close.
13. Press **Save** at the top-right of the window to persist your changes.
## Need something else?
If you require assistance setting up a custom authentication provider or need an option not currently covered, please [contact us](mailto:support@rownd.io).
# Authentication methods
Source: https://docs.rownd.io/configuration/authentication-methods/overview
Configure what sign-in methods are used in your app and websites
Authentication should not be a tax on your growth. With Rownd's adaptive authenication and wide range of authentication options, we help maximize both product flexibility and increase user growth.
## Navigating to authentication methods
Open your app in the [Rownd platform](https://app.rownd.io/applications). Then click on the **Sign-in methods** tab on the left to adjust your flow.
## Available authentication methods
You can use any combination of the following authentication methods:
Passwordless sign-in with a passkey (biometrics)
Passwordless email sign-in
One tap sign-in with a Google account
Fast sign-in with Apple ID
Passwordless SMS-based sign-in
}
href="./guests"
>
Anonymous sign-in for unidentified users
When detected, sign in using Metamask, Coinbase, etc.
Get in touch to discuss your needs!
## Adaptive sign-in with Rownd
Rownd's adaptive sign-in feature offers a tailored authentication experience for users by adapting the sign-in method depending on the user's device. This versatile approach ensures the most convenient and secure authentication option is presented, enhancing the user experience and promoting increased user engagement.
### Device-specific sign-in methods
Rownd's adaptive sign-in can detect the user's device and adjust the available authentication options accordingly. This ensures that the user is presented with the most appropriate sign-in method for their device, resulting in a seamless and intuitive experience. Some device-specific sign-in methods include:
* **Biometric authentication:** Rownd utilizes passkey technology to automatically utilize whatever biometric featuers a device has. For devices with biometric capabilities, such as fingerprint or facial recognition, Rownd can offer these secure and convenient methods as authentication options.
* **Device-based authentication:** For users with device-specific accounts (e.g., Apple ID or Google accounts), Rownd can present the option to sign in using these platform-specific accounts.
* **SMS or email authentication:** For devices without biometric or device-based options, Rownd can provide authentication via SMS or email, sending a unique, one-time-use login link to the user's mobile device or email address.
### Customizing sign in methods by device on the Rownd platform
1. **Navigate to the Sign in methods tab:** After installing Rownd with a code snippet or SDK, navigate to the sign in methods tab in the Rownd Platform.
2. **Configure [mobile app settings](configuration/mobile.mdx):** If you have a mobile app, configure your Google, Apple and mobile settings to get started. This will ensure proper deep linking to your mobile apps with your new customizations.
3. **Customize sign in method orders by device:** Select the device type at the top (Desktop, iOS, Android), drag, drop, prioritize, and hide methods until you’re liking your customizations for each device type. We recommend prioritizing Apple sign in on iOS devices and prioritizing Google sign in on Android devices.
4. **Test it out:** Save and try out your new customizations in your app! Continue to iterate based on on the way your users are signing in.
### Benefits of adaptive sign-in
Implementing Rownd's adaptive sign-in feature in your mobile app provides several advantages:
1. **Improved user experience:** By offering device-specific sign-in methods, you can cater to users' preferences and provide a more convenient and intuitive authentication process.
2. **Increased security:** Adaptive sign-in ensures that the most secure method available on the user's device is presented, helping to safeguard user accounts and protect sensitive data.
3. **Higher engagement and retention:** A tailored authentication experience can lead to higher user engagement and retention, as users are more likely to continue using an app that offers a seamless and convenient sign-in process.
## Unverified Users
See more details on [Unverified Users](/configuration/authentication-methods/unverified)
# Sign in with Passkeys
Source: https://docs.rownd.io/configuration/authentication-methods/passkeys
Enable passkey authentication to provide a secure and seamless sign-in experience for users with passkey-enabled devices.
Passkeys offer a secure and convenient method for users to sign in to their accounts on your website and mobile apps. By enabling passkeys, users with passkey-enabled devices can save their passkeys to their account. Once a passkey is saved, users can quickly sign in using their passkeys, providing a seamless and efficient experience.
## Enabling passkeys
Enabling passkeys is easy and does not require any additional code. Simply follow the steps below to enable passkeys for your application.
1. Open your app in the [Rownd platform](https://app.rownd.io/applications). Then click on the **Sign-in methods** tab on the left to adjust your flow.
2. Scroll down to view the authentication methods, and press **Enable** next to **Passkeys**.
At this time, passkey cannot be the only form of sign-in enabled. Users can add passkeys after signing up with
another method. After the first sign-in, they can use their passkeys to sign in to their account. This ensures
account access across different devices.
3. To confirm your changes, press **Save** in the upper right-hand corner of the page.
With passkeys enabled, users with passkey-enabled devices can now enjoy a seamless and secure sign-in experience on your website and mobile apps.
1. Configure iOS "Mobile app settings" in the [Rownd Platform](https://app.rownd.io/methods) with a subdomain, bundle ID, and a team ID. Instructions can be found [here](/configuration/mobile/ios).
2. In Xcode ensure "Associated Domains" for applinks and webcredentials are configured with your Rownd subdomain
applinks:your\_set\_subdomain.rownd.link
webcredentials:your\_set\_subdomain.rownd.link
See image below
1. Configure iOS "Mobile app settings" in the [Rownd Platform](https://app.rownd.io/methods) with a subdomain, package name, and a SHA 256 cert fingerprint. Instructions can be found [here](/configuration/mobile/android).
# Sign in with SMS / Phone Number
Source: https://docs.rownd.io/configuration/authentication-methods/phone-sms
Passwordless SMS authentication
SMS-based authentication using Rownd Sign-in Links is a secure and convenient method for users to sign in to their accounts on your website and mobile apps. This approach eliminates the need for passwords, instead sending a unique, one-time-use sign-in link directly to users' mobile devices via SMS. By simply clicking on the link, users can securely access their accounts without having to remember any passwords.
**Enhance SMS Link Trust with Custom Domains**
Using a custom domain for your SMS authentication links can significantly improve user trust and click-through rates. When users receive links that contain your own domain rather than a generic one, they're more likely to perceive them as legitimate and click through.
Learn more about setting up [Custom Domains](/configuration/custom-domains/overview) to create a more cohesive branded experience.
This authentication method offers several advantages, including ease of use for users and enhanced security. By leveraging users' mobile devices for authentication, you can reduce the risk of password-related security breaches and ensure that only the authorized account holder has access to the account.
Integrating SMS-based authentication with Rownd Sign-in Links is straightforward for developers, and the process is intuitive for users. This results in a streamlined authentication experience on your platform and a reduced barrier to entry for your users.
By incorporating SMS-based authentication with Rownd Sign-in Links, you can offer a user-friendly and secure authentication option that promotes trust in your platform and safeguards user data.
#### When to use phone sign-in
There are few more powerful ways to bridge the computer-to-mobile gap than with SMS sign-in. Rownd utilizes powerful sign-up links that make it easy to verify a phone number without having to copy down annoying 4-8 digit passcodes.
When paired with Rownd's mobile download links, users can leverage SMS to download and sign-in to your mobile app in just a few taps.
#### Enabling SMS authentication
1. Navigate to **Sign-in methods** in the [Rownd dashboard](https://app.rownd.io).
2. Toggle the switch for **Phone number** to the "on" position.
3. Click **Save**.
There is an incremental cost to send SMS text messages. Most Rownd plans include a set number of messages per-month and a small surcharge for each message thereafter. Surcharges may vary based on the destination country / carrier.
SMS is disabled for free accounts by default. [Get in touch](https://rownd.io/contact) with us if you'd like to enable it.
# Unverified Users
Source: https://docs.rownd.io/configuration/authentication-methods/unverified
Allow first-time users to sign up without immediate verification. On subsequent visits, they will be prompted to verify their email or phone number.
## Enabling Delayed Verification for unverified Users
Enabling delayed verification for unverified users allows first-time users to sign up without needing to verify their email immediately. This feature reduces friction during the sign-up process, providing a smoother user experience, especially for new users.
On the user’s second visit, they will be prompted to verify their account to continue accessing the app. This ensures that your app maintains security while allowing users to try it out with minimal barriers.
This feature is particularly useful for applications where quick sign-up is critical, and you want to prioritize user experience without compromising security for returning users.
### Benefits of Delayed Verification
* **Lower Friction:** First-time users can sign up quickly without needing to verify their email immediately.
* **User Experience:** Reduces the likelihood of sign-up abandonment by making the process faster and more seamless.
* **Improved Security:** Users will still be required to verify their account on subsequent visits, ensuring that only legitimate users can access the app long-term.
* **Flexible Integration:** Does not require any additional code beyond enabling the setting on your Rownd platform.
### Enabling Delayed Verification
Enabling delayed verification for unverified users is simple and does not require coding changes. Just follow the steps below:
1. **Open your application in Rownd**\
Open your app in the [Rownd platform](https://app.rownd.io/applications). In the left-hand navigation panel, click on the **Settings** tab and navigate to the **User Settings** tab.
2. **Enable Delayed Verification**\
Scroll down to the part of the page where you'll find the toggle next to **Allow delayed verification**. Flip the toggle to enable the feature for your application.
3. **Save Changes**\
After enabling delayed verification, click **Save** in the upper right-hand corner to confirm your changes.
### How It Works for Users
Once enabled, users can sign up without immediate verification by entering their email in the email sign-in field if enabled. They will be able to access the app and use its features, but when they return to the app on a later visit, they will be prompted to verify their email to continue using the app.
For users who have a recognized device (via browser fingerprinting), the verification prompt may be skipped on future visits as long as the device is recognized.
### Use Cases
* **E-commerce apps**: Users can quickly browse and explore products without immediate verification but will need to verify their account for checkout.
* **Social apps**: New users can sign up and explore the app, and on their second visit, they can verify their email or phone for account recovery and security.
* **Service-based apps**: Let users try out basic features first without verification, and later require verification for accessing premium or restricted features.
### Next Steps
Once delayed verification is enabled, consider reviewing your sign-in flows and customizing the user experience even further. Rownd’s platform offers additional customization options, such as customizing the verification prompt and setting different requirements for different user groups.
***
If you have any further questions about this feature or need help with troubleshooting, feel free to reach out to Rownd’s support team at [support@rownd.io](mailto:support@rownd.io)
# Automations overview
Source: https://docs.rownd.io/configuration/automations/overview
Streamline your sign up experience with Rownd automaitions.
#### What are automations?
In Rownd, Automations are tools that empower you to enhance and optimize your app's sign-up process without any coding. You can configure automations to add functions to your app like prompting users to sign in, collecting additional information, or triggering specific Rownd actions when users interact with certain elements. Automations help improve your app's sign in and user flows without the need for extensive technical expertise.
Note: Rownd must be installed on your app in order for automations to work properly.
#### Why use automations?
* **Fast iteration and testing**: With Automations, you can experiment with new elements in your sign-up flow and iterate rapidly.
* **No-code server side changes**: Rownd operates server-side, ensuring that your changes and Automations are instantly applied to your app when you save them on the platform. There's no need to involve engineering for minor adjustments or updates.
* **Easy customization**: One significant advantage of Automations is the ability to tailor the wording and style for each one. For instance, you can easily adjust the title of a sign-in prompt to better match your content.
#### How It Works
1. Browse the Automations catalog in the Automations tab and select the automation that best matches what you are trying to do.
2. Configure your automation, including naming it and specifying the type of prompt it will be, among other options.
3. Customize the style and wording of your automation, which may vary depending on the type.
4. Save and publish to immediately implement your automation in your app.
5. Iterate over time by making adjustments and refinements until your automation operates optimally for you users.
#### Current and coming soon Rownd automations
While this feature is still in Beta, we are still building new automations every week! Below are a few of our existing and in progress automations and what they will help you accomplish.
* **Sign-In Prompt**: Encourage users to sign in based on clicks, time duration, sessions, or an entire page. Connect this prompt to a sign-in button or an app feature requiring authentication.
* **Sign-Out Event**: Enable users to end their current session with a "Sign-out" button or any other element you choose.
* **Request Additional Information**: Enable this automation to easily gather extra user information. Once activated, it prompts users to provide additional details, making it applicable in various scenarios such as age verification, collecting usernames, and requesting secondary email or address information.
* **Collect Form Data (Coming Soon!)**: Connect Rownd data fields to a form in your application to passively add information to a user's Rownd profile while they use your app.
* **Open Profile (Coming Soon!)**: Launch the Rownd profile from a button or element within your app, allowing users to update their data and connected accounts.
* **Google One Tap (Coming Soon!)**: Prompt users to sign in using a Google account. Configure when this prompt appears, whether on click, based on time, session, or an entire page. Use it to re-prompt users if they initially ignore the one-tap prompt.
* **Passkey prompt (Coming Soon!)** The passkey prompt automation allows you to prompt users to add a passkey to their account based on clicks, time duration, sessions, or an entire page. You can connect this prompt to a button or element within your app to prompt users to add a passkey.
* **Promotional Opt in (Coming Soon!)**: This automation enables you to request email or text message marketing opt-ins from your users with ease. When enabled, you can customize and automate the opt-in process according to your preferences. You have the flexibility to determine the frequency, timing, and mode of communication that works best for your users.
# Sign in prompts
Source: https://docs.rownd.io/configuration/automations/sign-in-prompt
Encourage user sign in with customized prompts.
The sign in prompt automation allows you to encourage users to sign in based on clicks, time duration, sessions, or an entire page. Connect this prompt to a sign-in button or an app feature requiring authentication.
#### Sign in prompt use cases
* **Content Gating**: Enhance user engagement by implementing click-triggered sign-in prompts within your application. These prompts allow users to explore your app freely, only requesting sign-in when specific elements are clicked. For example, if you wish to restrict access to certain features for unauthenticated users, seamlessly integrate a Rownd sign-in prompt to the corresponding tab or element in your app. This process takes just minutes to implement, encouraging users to sign in to access exclusive content.
* **Free Trials**: Provide prospective users with the opportunity to experience your product through free trials without the initial sign-up requirement. Utilize time-based sign-in prompts to prompt users to sign in after a defined period, whether it's 5 minutes, 24 hours, or 4 days—flexibility tailored to your needs. Time-based prompts allow users ample time to familiarize themselves with your product, generating excitement and increasing the likelihood of conversion when prompted to sign up.
* **Simple Buttons**: Simplify the process of integrating sign-in functionality into your website, even when your development team has limited availability. Sign-in prompts empower you to connect sign-in actions to any button or element seamlessly. Additionally, you can redirect users to specific destinations after they sign in, providing complete control over their post-login journey.
#### How does it work?
1. **Create a New Sign-In Prompt Automation**
Begin by adding a new Sign-In Prompt Automation from the "Automations" tab.
2. **Configure Your Automation**
Tailor your automation to fit your use case. Determine the type of prompt you require, whether it's click-triggered, time-based, page-scoped, or immediately after sign-in. Define any specific requirements and redirect links.
For click-triggered prompts on websites and web apps, you'll need to provide an element selector to connect to your Rownd automation. Refer to the video below for guidance on finding and copying an element selector.
3. **Customize Your Prompt**
Personalize your prompt by adjusting the wording and content that will be displayed to your users for this particular prompt.
4. **Finish creating Your Automation**
Once you've configured and customized your prompt, click 'Create' to officially add your new automation to your app.
5. **Ongoing Optimization**
Continuously refine, modify, and iterate on your automations to align with user behaviors and preferences.
Automations are currently a Beta feature, and we highly value user feedback. Please feel free to share your feedback and ideas with us by sending an email to [support@rownd.io](mailto:support@rownd.io).
# Implementation
Source: https://docs.rownd.io/configuration/cross-domain/implementation
Get cross-domain authentication added to your product
## Getting Started
1. **Locate your subdomain from the Rownd dashboard's** [settings](/configuration/mobile)
2. **Create or use an existing** [**app key**](/configuration/app-credentials)
3. **Form your root origin URL using the following template**
```
https://REPLACE_WITH_YOUR_SUBDOMAIN.rownd.link/root/
```
4. Add the root origin URL to your implementation of the Rownd SDK (see [examples](#implementation-examples) below)
5. Test to ensure everything is working. You should be able to visit one of your domains, sign in successfully, and then visit another of your domains and remain signed in.
### Implementation Examples
If you're using our WordPress, Shopify, or similar integrations, look for a "Root Origin URL" setting the the plugin or app's configuration page.
Below are some examples of how to enable cross-origin authentication across various Rownd SDKs.
#### Next.js / React / Remix
```jsx theme={null}
return (
{children}
);
```
#### JavaScript
For websites using the standard snippet:
```javascript theme={null}
_rphConfig.push(['setRootOrigin', yourRootOriginUrl]);
```
## Best Practices
1. Maintain consistent configuration across all properties
2. Use trusted SSL certificates for all domains
3. Test authentication flow in development environment before implementing in production
4. Test user flows across different domains
## Troubleshooting
If the authentication state isn't syncing, make sure you:
1. Verify that the root origin configuration is the same across all web properties
2. Be sure SSL certificates are valid
3. Confirm the app key is correct
If you're still facing difficulty, please reach out to [Rownd support](mailto:support@rownd.io?subject=Cross-domain%20auth%20not%20working).
# Adding cross-domain authentication
Source: https://docs.rownd.io/configuration/cross-domain/overview
Keep users signed in across all of your web properties
Rownd's cross-domain authentication provides a seamless user experience across multiple domains and subdomains without third-party cookies. This modern approach maintains secure user sessions across your entire digital ecosystem.
## How It Works
Rownd uses a novel authentication method that:
* Operates independently of third-party cookies
* Maintains sessions across different domains
* Synchronizes user state automatically
* Preserves security while improving user experience
## Benefits
* **Seamless User Experience**: Users stay signed in across all your properties
* **Cookie-Independent**: Future-proof against browser privacy changes
* **Flexible Implementation**: Works across web apps, mobile apps, and websites
* **Improved Conversion**: Reduces friction in user journeys
* **Enhanced Security**: Maintains secure sessions without compromising user privacy
## Common Use Cases
### Landing Page to Application
1. Add Rownd to your marketing site
2. Enable passive authentication (e.g., Google One Tap)
3. Users automatically sign in when accessing your main application
4. Increases conversion by removing authentication barriers
### Documentation Portal Integration
1. Implement Rownd across your documentation site
2. Provide personalized help based on user context
3. Track documentation usage patterns
4. Deliver customized content based on user preferences
### Multi-App Ecosystem
1. Deploy Rownd across multiple applications
2. Maintain consistent authentication state
3. Works seamlessly with [sub-brands](https://docs.rownd.io/configuration/customizations/sub-brands)
4. Create branded experiences for different user segments
To implement cross-domain authentication within your product, follow our[ implementation steps.](/configuration/cross-domain/implementation)
## SDK References
For detailed implementation guidelines, refer to:
* [Web SDK Documentation](https://docs.rownd.io/sdk-reference/web)
* [Mobile SDK Documentation](https://docs.rownd.io/sdk-reference/mobile)
* [Sub-brands Configuration](https://docs.rownd.io/configuration/customizations/sub-brands)
# How to set custom domains in DNS providers
Source: https://docs.rownd.io/configuration/custom-domains/dns-records
These docs shows how to add the **CNAME** and **TXT** records required to configure a custom authentication domain (e.g., for magic‑link emails, smart links, etc.) with Rownd. Each example uses:
* **CNAME**: points `` to your Rownd subdomain (``).
* **TXT**: creates a verification record at `` with the token ``.
Click the links for your DNS provider’s official docs for more details.
***
## Table of Contents
1. [Cloudflare](#1-cloudflare)
2. [GoDaddy](#2-godaddy)
3. [Google Cloud DNS](#3-google-cloud-dns)
4. [AWS Route 53](#4-aws-route-53)
5. [Azure DNS](#5-azure-dns)
6. [Namecheap](#6-namecheap)
7. [DigitalOcean DNS](#7-digitalocean-dns)
8. [Hover](#8-hover)
9. [DNS Made Easy](#9-dns-made-easy)
10. [Dyn Managed DNS](#10-dyn-managed-dns)
11. [Squarespace](#11-squarespace)
***
## 1. Cloudflare
* **Official Docs**: [Manage DNS Records – Cloudflare](https://developers.cloudflare.com/dns/manage-dns-records/)
### Add a CNAME Record
| Field | Value |
| ------ | ------------------------------ |
| Type | CNAME |
| Name | `` |
| Target | `` |
| TTL | Auto (or your preferred value) |
### Add a TXT Record
| Field | Value |
| ------- | ------------------------------ |
| Type | TXT |
| Name | `` |
| Content | `` |
| TTL | Auto (or your preferred value) |
***
## 2. GoDaddy
* **Official Docs**:
* [Add CNAME Records](https://support.godaddy.com/help/add-cname-records-19238)
* [Add TXT Records](https://support.godaddy.com/help/add-a-txt-record-19236)
### Add a CNAME Record
| Field | Value |
| --------- | ---------------------- |
| Type | CNAME |
| Host | `` |
| Points to | `` |
| TTL | 600 sec (or default) |
### Add a TXT Record
| Field | Value |
| --------- | ----------------------- |
| Type | TXT |
| Host | `` |
| TXT Value | `` |
| TTL | 600 sec (or default) |
***
## 3. Google Cloud DNS
* **Official Docs**: [Resource Record Types – Cloud DNS](https://cloud.google.com/dns/docs/records)
### Add a CNAME Record
| Field | Value |
| -------------------- | ---------------------------- |
| DNS Name | `.` |
| Resource Record Type | CNAME |
| Canonical name | `.` |
| TTL | 300 sec (or your preference) |
### Add a TXT Record
| Field | Value |
| -------------------- | ---------------------------- |
| DNS Name | `` |
| Resource Record Type | TXT |
| TTL | 300 sec (or your preference) |
| TXT data | `""` |
***
## 4. AWS Route 53
* **Official Docs**: [Creating Records – Route 53](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resource-record-sets-creating.html)
### Add a CNAME Record
| Field | Value |
| ----------- | ---------------------- |
| Record name | `` |
| Record type | CNAME |
| Value | `` |
| TTL (sec) | 300 |
### Add a TXT Record
| Field | Value |
| ----------- | ------------------------ |
| Record name | `` |
| Record type | TXT |
| Value | `""` |
| TTL (sec) | 300 |
***
## 5. Azure DNS
* **Official Docs**: [Add Records to DNS Zones – Azure DNS](https://learn.microsoft.com/azure/dns/dns-zones-records)
### Add a CNAME Record
| Field | Value |
| ----- | ---------------------- |
| Name | `` |
| Type | CNAME |
| Alias | `` |
| TTL | 3600 sec |
### Add a TXT Record
| Field | Value |
| ----- | ----------------------- |
| Name | `` |
| Type | TXT |
| Value | `` |
| TTL | 3600 sec |
***
## 6. Namecheap
* **Official Docs**: [How to Add DNS Records – Namecheap](https://www.namecheap.com/support/knowledgebase/article.aspx/9756/2237/how-to-add-dns-records-for-a-domain)
### Add a CNAME Record
| Field | Value |
| ----- | ---------------------- |
| Type | CNAME |
| Host | `` |
| Value | `` |
| TTL | Automatic |
### Add a TXT Record
| Field | Value |
| ----- | ----------------------- |
| Type | TXT |
| Host | `` |
| Value | `` |
| TTL | Automatic |
***
## 7. DigitalOcean DNS
* **Official Docs**: [Add DNS Records – DigitalOcean](https://docs.digitalocean.com/products/networking/dns/how-to/add-records/)
### Add a CNAME Record
| Field | Value |
| -------------- | ---------------------- |
| Host name | `` |
| Will direct to | `` |
| Record type | CNAME |
### Add a TXT Record
| Field | Value |
| ----- | ----------------------- |
| Host | `` |
| Value | `` |
| Type | TXT |
***
## 8. Hover
* **Official Docs**: [Adding a DNS Record – Hover Help](https://help.hover.com/hc/en-us/articles/203729334-Adding-a-DNS-record)
### Add a CNAME Record
| Field | Value |
| --------- | ---------------------- |
| Type | CNAME |
| Host name | `` |
| Points to | `` |
### Add a TXT Record
| Field | Value |
| --------- | ----------------------- |
| Type | TXT |
| Host name | `` |
| Value | `` |
***
## 9. DNS Made Easy
* **Official Docs**: [Adding Records – DNS Made Easy](https://support.dnsmadeeasy.com/hc/en-us/articles/115005531225-Adding-Records)
### Add a CNAME Record
| Field | Value |
| ----- | ---------------------- |
| Type | CNAME |
| Host | `` |
| Value | `` |
### Add a TXT Record
| Field | Value |
| ----- | ----------------------- |
| Type | TXT |
| Host | `` |
| Value | `` |
***
## 10. Dyn Managed DNS
* **Official Docs**: [Using the DNS Manager – Dyn](https://help.dyn.com/using-dns-manager/)
### Add a CNAME Record
| Field | Value |
| -------- | ---------------------- |
| Type | CNAME |
| Hostname | `` |
| Target | `` |
### Add a TXT Record
| Field | Value |
| -------- | ----------------------- |
| Type | TXT |
| Hostname | `` |
| TXT Data | `` |
***
## 11. Squarespace
* **Official Docs**:
* [Adding DNS records to your domain – Squarespace](https://support.squarespace.com/hc/en-us/articles/360002101888-Adding-DNS-records-to-your-domain)
* [DNS records for connecting third-party domains – Squarespace](https://support.squarespace.com/hc/en-us/articles/360035485391-DNS-records-for-connecting-third-party-domains)
### Add a CNAME Record
| Field | Value |
| ----- | ---------------------- |
| Type | CNAME |
| Host | `` |
| Data | `` |
### Add a TXT Record
| Field | Value |
| ----- | ----------------------- |
| Type | TXT |
| Host | `` |
| Data | `` |
***
Follow these steps to configure your custom authentication domain for Rownd smart links and magic‑link flows.
# Custom Domain Configuration
Source: https://docs.rownd.io/configuration/custom-domains/overview
Custom domains allow you to maintain a consistent brand experience throughout your users' authentication journey. By configuring a custom domain, all authentication flows, magic links, and auth-related emails will use your domain instead of Rownd's default domains.
## Benefits of Custom Domains
* **Enhanced Brand Trust**: Users see only your domain throughout the entire authentication process
* **Improved Deliverability**: Email providers often trust established domains more than third-party services
* **Consistent User Experience**: Seamless transitions between your application and authentication flows
* **HIPAA and Compliance**: Help meet regulatory requirements for sensitive industries
## Setting Up Custom Domains
### Step 1: Access Domain Settings
Navigate to the Settings section in the left sidebar of your Rownd dashboard.
### Step 2: Add Your Custom Domain
Under the "Primary authentication domain" section, you'll see your current authentication domain. To add a custom domain:
1. Type your domain (e.g., auth.acme.com)
2. The domain will show as "Pending" until verified
### Step 3: Configure DNS Records
To verify ownership of your domain, you need to add two DNS records:
1. **CNAME Record**: Points your domain to Rownd's authentication servers
* Name: Your custom domain (e.g., auth.acme.com)
* Value: The provided Rownd endpoint (e.g., eijl7ms.auth.rownd.com)
2. **TXT Record**: Verifies your ownership of the domain
* Name: \_cf-custom-hostname.your-domain (e.g., \_cf-custom-hostname.auth.com)
* Value: The provided verification string (e.g., 5edk2cd9-030da-453d-8450-8221b2aasdfasf)
Add these records through your DNS provider's management console:
#### DNS Provider Instructions
We provide step-by-step instructions for configuring DNS records with popular providers:
* [Cloudflare](/configuration/custom-domains/dns-records#1-cloudflare)
* [GoDaddy](/configuration/custom-domains/dns-records#2-godaddy)
* [Google Cloud DNS](/configuration/custom-domains/dns-records#3-google-cloud-dns)
* [AWS Route 53](/configuration/custom-domains/dns-records#4-aws-route-53)
* [Azure DNS](/configuration/custom-domains/dns-records#5-azure-dns)
* [Namecheap](/configuration/custom-domains/dns-records#6-namecheap)
* [DigitalOcean DNS](/configuration/custom-domains/dns-records#7-digitalocean-dns)
* [Hover](/configuration/custom-domains/dns-records#8-hover)
* [DNS Made Easy](/configuration/custom-domains/dns-records#9-dns-made-easy)
* [Dyn Managed DNS](/configuration/custom-domains/dns-records#10-dyn-managed-dns)
* [Squarespace](/configuration/custom-domains/dns-records#11-squarespace)
For detailed instructions on setting up DNS records with your specific provider, see our [DNS Provider Steps](/configuration/custom-domains/dns-records).
### Step 4: Wait for Verification
After adding the DNS records, Rownd will automatically verify your domain. This process typically takes 5-10 minutes but can sometimes take up to 24-48 hours, depending on your DNS provider's propagation time.
Once verified, your domain will show as "Verified - Inactive":
### Step 5: Activate Your Custom Domain
Click the "Activate" button to start using your custom domain for authentication. Once activated, all authentication flows, emails, and links will use your custom domain.
## Link Domains
In addition to your primary authentication domain, you can also configure link domains for Smart Links. These domains are used when creating deep links to your application for authentication flows, app installs, and user onboarding.
To add a link domain, navigate to the "Link domains" section below your primary authentication domain settings.
### Smart Links with Custom Domains
[Smart Links](/magic-links/overview) can be used with your custom domains to create a seamless branded experience for your users. These links function similarly to Branch links, providing powerful attribution and deep linking capabilities, but with full customization under your own domain.
Smart Links can be used in various scenarios:
* **[Authenticated Experiences](/magic-links/authenticated)**: Send authenticated deep links that maintain user context and session state
* **[Unauthenticated Experiences](/magic-links/unauthenticated)**: Create public links for app installs, onboarding flows, or marketing campaigns
* **[Cross-Platform Experiences](/magic-links/platform)**: Direct users to the appropriate experience based on their device and context
By using a custom domain for your Smart Links, you enhance brand trust and recognition while maintaining all the functionality of Rownd's link management system.
## Troubleshooting
If your domain verification fails to complete:
1. **Check DNS Configuration**: Ensure both CNAME and TXT records are correctly configured
2. **Wait for Propagation**: DNS changes can take time to propagate globally
3. **Verify Domain Format**: Ensure your domain format matches exactly what's specified in the Rownd dashboard
4. **Contact Support**: If issues persist, contact Rownd support for assistance
## Notes and Limitations
* Each Rownd application can have one active authentication domain at a time
* You can have multiple verified domains but only one can be active
* Custom domains require proper SSL/TLS certificate configuration, which Rownd handles automatically
* Custom domain email deliverability may require additional SPF/DKIM configuration for optimal results
# Pre-built UI
Source: https://docs.rownd.io/configuration/customizations/email-customization
Rownd provides a comprehensive set of pre-built UI components that are fully customizable to align with your company's branding and user experience requirements. These components are optimized for both web and mobile platforms, reducing development effort while maintaining flexibility.
## UI Components
Each of the following sections outlines a specific UI element, its purpose, and customization options.
You can modify these UI components in the Design tab within the Rownd platform:
* In the **Design tab**
* **Theme tab:** Apply global branding, including colors, typography, and logos.
* **Customize UI tab:** Adjust content, wording, and visibility settings.
* **Sign-in Methods tab:** Configure authentication method order and visibility.
### Sign-in Modal
This modal appears when a user attempts to sign in. It provides authentication options based on the methods configured in your Rownd platform.
**Customizable elements:**
* Order and visibility of sign-in methods (Sign-in Methods tab)
* Content and wording (Customize UI tab)
* Branding, including logos and colors (Theme tab)
### Profile
The Rownd Profile enables users to manage their account information without requiring custom development. It consists of the following sections:
* **Account Information**: Displays enabled sign-in methods, allowing users to update their email, phone number, or connect accounts like Google.
* **Personal Information**: Stores non-authentication data, such as names and addresses. Fields can be customized from the Profile Data tab. Users can edit data unless marked as app-owned.
* **Preferences**: Displays the account ID (for support), a "Sign out of all sessions" option (which signs users out of all devices), and an "Account deletion" feature.
*Future updates will include session management, passkey management, and more.*
**Customizable elements:**
* Fields in Account Information (Sign-in Methods tab)
* Fields in Personal Information (Profile Data tab)
* Branding and styling (Theme tab)
### Verification Modal
This modal appears when users need to verify their email or phone number during sign-in.
**Customizable elements:**
* Title and failure messages (Customize UI tab)
* Branding and visual elements (Theme tab)
### Verification Screen
After users verify their phone number or email, they briefly see this screen before being redirected to your app or website.
**Customizable elements:**
* Currently, this screen inherits Theme settings.
* Future updates will allow content customization in the Customize UI tab.
### Rownd Verification Email
Users receive this email to verify their email address during sign-in.
**Customizable elements:**
* Language and wording (Customize UI tab)
* Company logo. colors,and corner radius (Theme tab)
> **Note:** If you prefer to have Rownd verification emails sent from an email address on your own domain (e.g., [hello@mycompany.com](mailto:hello@mycompany.com)), we can configure that for you. Send an email to [support@rownd.io](mailto:support@rownd.io) with the subject line From email address change. We’ll process your request in about one business day and reply with further instructions to finalize the setup.
### Mobile Redirect Screen
When a user without your mobile app clicks a sign-in link on a mobile device, this screen directs them to download the app.
**Customizable elements:**
* App store logo and branding (Theme tab)
* Content and wording (Customize UI tab)
### Rownd Hub Widget
The Rownd Hub is an optional widget that provides a quick-access entry point for authentication and profile management.
**Customizable elements:**
* Visibility (Customize UI tab)
* Branding and design (Theme tab)
*The Hub can be useful for testing on web apps and websites.*
### Automations UI
Certain UI elements are triggered through Automations in Rownd. These include:
* Passkey modals
* Prompts for additional user information
**Customizable elements:**
* Wording adjustments
* Ordering of fields
* Branding (Theme tab)
***
Rownd’s pre-built UI components provide a powerful, flexible solution for authentication and user account management, saving significant development time. With extensive customization options, businesses can maintain brand consistency while leveraging secure, optimized UI elements across web and mobile platforms.
# Global style
Source: https://docs.rownd.io/configuration/customizations/global-style
Customize Rownd UI elements to match your brand and style
Rownd offers a range of style customizations to best match your brand look and feel.
#### Elements you can customize
* **Appearance.** Depending on your application, you can decide if you want your styles to **1. Automatically sync with user OS settings**, 2. Always appear in **light mode** or 3. Always appear in **dark mode**. The default setting is to automatically sync to user OS setting.
* **Primary color.** Rownd's default primary color is Purple `#5B13DF`. You can
change this color to match your brand color. Additionally, if you are using dark mode or syncing to user OS settings, you can add a primary color for dark mode. Use the **Dark mode** toggle in the preview on the right to see your dark mode color in the preview.
* **Overlay blurring.** By default, overlays (behind modals) blur the background. You can leave this on or turn it off.
* **Visual elements.** Most Rownd dialogs include "visual swoops" at the bottom that match the primary color you select. You can choose to remove these for your application. Rownd also includes default illustrations that appear on varying modals. You can choose to remove these as well.
* **Corner radiuses.** By default, Rownd modal and hub corners have rounded edges; you can choose between rounded and square corners on UI elements.
* **Logos.** Logos can be added to sign in modals by checking the box to "Include app logo in Rownd modals." You may add separate logos for light and dark mode or upload the same logo for both appearances.
#### How to customize
1. In the Rownd dashboard, navigate to the **Design** tab from the left navigation.
2. Edit and change dark mode options, the primary color, corners, background blur, and visual
elements with the options on the left side of the screen.
3. Preview your changes in an example UI dialog on the right side of the screen.
4. Press **Save** in the top-right corner before leaving the page. Your updates will be applied to the websites and apps where you've installed the Rownd code snippet.
#### Additional UI customizations
Global styles will span across all Rownd UI elements, but you have additional customization options for the content and appearances of Rownd emails, modals, and screens.
* **[Email customizations](configuration/customizations/email-customization.mdx).** Customize the language and logo that appear in user verification emails for email sign in.
* **Sign in modal.** From the "Modals" tab, you can update the content, visuals, and links on your Rownd sign in modal.
* **Verification modal.** From the "Modals" tab, you can update the content and visuals on your Rownd verification modal.
* **App download screen.** From the "Emails and screens" tab, you can update the content and visuals on the Rownd App download screen. This screen appears if your user is attempting mobile app sign in and does not yet have the app on their device. Be sure to configure your [mobile app settings](configuration/mobile.mdx) for this to work properly.
If your app is already in production, you may want to create a second Rownd app in order to test your changes before applying them to your live environment.
You can use the **Reset to default settings** option on the right side of the page
to reset the style to the Rownd defaults.
# Sub-brands
Source: https://docs.rownd.io/configuration/customizations/sub-brands
Sub-brands allow you to manage users across all your varying apps, websites and products
Introducing sub-brands, one of Rownd’s latest and greatest features focused on allowing you to expand your portfolio without partitioning where you manage your users. Sub-brands are extremely unique, easy to use, and can save you and your development team so much time.
#### What are sub-brands?
A sub-brand is a variation of your Rownd application. Sub-brands can have their own theme, customizations, and even associated automations. All sub-brands share users with the base app, which means that users maintain their account and profile information across the sub-brands they are signed into. Sub-brands allow you to see which apps and brands your users have interacted with, without having to use multiple Rownd apps.
When you add a user to a sub-brand or they sign into one of your apps that uses a specific sub-brand, an attribute called `rownd:app_variants` is added to their profile with a list of any sub-brands with which the user has interacted. You can also manage these attributes to add or remove a user from a sub-brand.
Additionally, when the user signs in or out of a sub-branded app, their profile metadata will include a map of each sub-brand containing the sign-in method used and the last time they signed in.
#### Why might you enable sub-brands?
Sub-brands are most often used when customers have multiple brands or style considerations for different environments like their web app, mobile app, or blog site. Here are a few examples and use cases:
* League or collection of apps: For example, a sports league wants sign-ins for their rewards program, but each team has its own application and requirements. In this scenario, the base Rownd app would represent the league, and each team would be its own sub-brand. This way, each team could still have its logo and branding colors, as well as its sign-in method configuration, while at the base app level, the league can see which users have interacted with each team (sub-brand), and users can easily sign in across team apps.
* Parent brand scenario: When one company owns multiple brands (Example: Walt Disney Company owning ESPN, Hulu, Disney +, ABC, etc.), they’d want to know which customers are interacting with which apps, without those users having a separate account for each app. By using sub-brands, the parent brand can better understand their users in seeing where they are visiting.
* Testing scenario: You can also use sub-brands as a way of testing your Rownd flow without impacting production users. Since you can attach a specific app key to a sub-brand, you can create a sub-brand with changes that you'd like to change and use its app key in a separate testing environment to validate the changes.
#### How to enable and use sub-brands:
1. From the Rownd platform, navigate to the design tab.
2. In the design tab, you’ll see a sub-brands tab (with “Beta” tag).
3. From that tab, you can add your first sub-brand. Give it a name and an optional description, and press create!
4. From here, you can use the drop-down and change the design theme.
5. To install in your app, grab the app key either from the app key tab or from the sub-brands tab. Include it in the Rownd SDK configuration or add it to the Javascript snippet.
6. Once users start signing into your apps, you’ll be able to see the sub-brands they have interacted with from the users table. The really cool thing here too is that their profile and account information will persist across sub-brands and the base app!
#### Base brands vs. Sub-brands
Your base brand is the original branding and style you configured for your Rownd app. When you add a sub-brand, the sub-brand will initially take on the same styling as your base brand (colors, logos, styles, etc.) until you change them. If you don't customize a style aspect of a sub-brand, and later change that aspect in the base brand, the sub-brand will adopt the base brand's change. For example, if you haven't updated the corner radius of a sub-brand from the base brand's 3px radius, and then change the base brand's corner radius to 10px, all sub-brands that weren't already customizing the corner radius will now adopt a 10px corner radius.
We love feedback! If you try out this feature, please reach out and let us know what you think and any feedback or questions you have at [Support@rownd.io](mailto:Support@rownd.io).
# Airtable
Source: https://docs.rownd.io/configuration/integrations/airtable
The Rownd integration for Airtable lets you sync personal information between
Rownd and a single Airtable Table. When configured, PII stored in the Table will
be discoverable and manageable by the data owners.
#### Creating the integration
1. From the **Integrations** tab in the sidebar, click on the **Add
Integration** button. If this is your first time creating an integration,
you'll already be in the Connector Catalog and don't need to click the
button.
2. Choose the **Airtable** connector from the Connector Catalog
3. Enter a name for your new Integration.
After you've entered a descriptive name, click **Next**
1. Authenticate with Airtable
Enter an API key that Rownd can use for reading and writing to Airtable. You can
create or retrieve your API key from the Airtable
[account settings](https://airtable.com/account) under the **API** heading.
Click the **Next** button after entering your API key.
1. Airtable Settings
Select the Airtable Base and Table
When done, click **Next**
1. Last Modified Time Field
In this step, Rownd will check for the existence of a `lastModifiedTime` Field
within your chosen Table. This is a special field type that Airtable uses to
record the last time an entry in the Table was updated. if necessary, please add
this Field (with any name) to your Table and click the **Retry** button.
Otherwise, click **Create** to finish.
For more inormation on adding a `lastModifiedTime` Field, please check out the
[Airtable Documentation](https://support.airtable.com/hc/en-us/articles/360022745493-Last-modified-time-field)
Click the **Create** button to finish creating your Integration
**Attach your Integration to a Rownd Application**
After creating your Integration, you must attach it to an existing Rownd
application.
1. From the Integrations table, click the overflow icon on your new Integration
and select **Attach to application**
2. Choose the application from the selector and click **Next**
3. Map data between the Rownd application and your new Integration
You will see a list of all fields that exist in your chosen application's
schema. Choose the corresponding Field within your Airtable Table.
For instance, you could have a field in your Rownd application called
`first_name` and a corresponding Field in your Table called `firstName`. Choose
the `firstName` options in the dropdown next to `first_name`.
A mapping for the `email` field is required. Rownd uses this field to identify
and search for users.
Rownd can only manage fields for which you have provided a mapping. Therefore,
define as many mappings as possible to get the most value from Rownd.
Once you complete the mapping, click **Save**.
# Auth0
Source: https://docs.rownd.io/configuration/integrations/auth0
The Auth0 integration helps you migrate your user authentication from Auth0 to Rownd. The migration can be done in one sync operation or on-demand as users sign-in. Existing Auth0 users will maintain their user IDs in Rownd.
#### Creating the integration
1. From the **Integrations** tab in the sidebar, click on the **Add Integration** button.
2. Choose the **Auth0** connector from the Connector Catalog
3. Enter a name for your new integration. After you've entered a descriptive name, click **Next**
4. Enter your client credentials and environment domain
The client credentials that you provide must be for a "Machine-to-Machine" application. Rownd uses these credentials to make calls to the Auth0 Management API to lookup user info. Find out more about creating the client credentials [here.](https://auth0.com/docs/get-started/auth0-overview/create-applications/machine-to-machine-apps)
When the connection is ready, you can use the three-dots menu on the far right of the row to attach the connection to your app.
Once these steps are completed, you should be able to use Rownd to sign in as an existing Auth0 user, receiving the same ID that you had previously.
# Firebase Authentication
Source: https://docs.rownd.io/configuration/integrations/firebase/authentication
The Firebase Authentication integration helps you migrate your user authentication flow from Firebase to Rownd. It also provides the means to use Rownd and Firebase Firestore together.
Before you begin, check out the Google Cloud [prerequisites](/configuration/integrations/firebase/google-cloud-platform-requirements)
to ensure your GCP account and Project are ready to integrate with Rownd.
#### Creating the integration
1. From the **Integrations** tab in the sidebar, click on the **Add
Integration** button.
2. Choose the **Firebase - Authentication** connector from the Connector
Catalog
3. Enter a name for your new integration.
After you've entered a descriptive name, click **Next**
4. Click the **Begin authentication** button to sign in to your Google Account and grant Rownd access to your Firebase project.
Firebase Authentication runs on Google Cloud. Rownd leverages the Google
Cloud Platform to receive updates from Firebase as any users are created, modified, or deleted. Rownd will need permission to read Google Cloud Projects, read and write Firebase resources, and create
Cloud Functions. For a full list of access that Rownd
needs, click
[here](/rownd/guides/configuration/integrations/firebase/google-cloud-platform-requirements#access-requirements).
Grant Rownd the access to your Google Account, and then click the **Next**
button when authentication is complete.
5. Select the Firebase Project and Application that you'd like to link with Rownd.
When finished, click **Create**
Initialization of the integration may take a few minutes while Rownd creates the required links with your Firebase project. You can track its progress in the **Connections** tab of the Integrations area.
When the connection is ready, you can use the three-dots menu on the far right of the row to attach the connection to your app.
Once these steps are completed, you should be able to use Rownd to sign in as an existing Firebase user, receiving the same ID that you had previously.
# Hubspot
Source: https://docs.rownd.io/configuration/integrations/hubspot
The Rownd integration for Hubspot makes it easy to keep your contact list in sync. The integration will automatically create a new contact or update an existing one in your Hubspot account.
#### Setup
The Hubspot integration can be enabled from the [Rownd dashboard.](https://app.rownd.io)
1. From the menu, select **Integrations.**
2. Select the **Connector catalog** tab.
3. From the list of available connectors, click on the **Hubspot**
entry. The connector setup dialog will appear.
4. Enter a descriptive name and click **Next**.
#### Authenticate
1. Click **Begin authenticate** and log in to your Hubspot account
2. Grant Rownd access to your Hubspot account, and then click **Next**
### Optional setting
To manage email subscriptions, specify the subscription id and the data field to map.
4. Click **Create** to create the connection.
The dialog should indicate that the integration was created successfully. Now that the connection exists, we need to attach it to an application.
#### Attach to an application
1. From the Integrations table, click the overflow icon on your new Integration
and select **Attach to application**
2. Choose the application from the selector and click **Next**
3. Map data between the Rownd application and your new Integration
A mapping for the `email` field is required. Rownd uses this field to identify
and search for existing subscribers in your Hubspot account. Rownd can only manage fields for which you have provided a mapping.
4. Click **Save.**
After a moment, the attached application should appear in the row next to the
connection. Once this occurs, data updates should begin flowing through the
integration.
# MailerLite
Source: https://docs.rownd.io/configuration/integrations/mailerlite
The Rownd integration for MailerLite makes it easy to keep your subscriber list in sync. The integration will automatically create a new subscriber or update an existing one in your MailerLite account.
#### Setup
The MailerLite integration can be enabled from the [Rownd dashboard.](https://app.rownd.io)
1. From the menu, select **Integrations.**
2. Select the **Connector catalog** tab.
3. From the list of available connectors, click on the **MailerLite**
entry. The connector setup dialog will appear.
4. Enter a descriptive name and click **Next**.
#### Authenticate
Enter your MailerLite API key. You can create or retrieve your API key from your MailerLite account.
1. In your MailerLite account, navigate to the [Integrations](https://dashboard.mailerlite.com/integrations) page.
2. Under MailerLite API click **Use**.
3. Click **Generate new token**.
4. Name your new token and copy/paste it into the field in the Rownd dialog.
5. Click **Create** to create the connection.
The dialog should indicate that the integration was created successfully. Now that the connection exists, we need to attach it to an application.
#### Attach to an application
1. From the Integrations table, click the overflow icon on your new Integration
and select **Attach to application**
2. Choose the application from the selector and click **Next**
3. Map data between the Rownd application and your new Integration
A mapping for the `email` field is required. Rownd uses this field to identify
and search for existing subscribers in your MailerLite account. Rownd can only manage fields for which you have provided a mapping.
4. Click **Save.**
After a moment, the attached application should appear in the row next to the
connection. Once this occurs, data updates should begin flowing through the
integration.
# Overview
Source: https://docs.rownd.io/configuration/integrations/overview
Rownd offers a growing list of integrations with other cloud services, CRMs, and more. Here's a list of the integrations we currently support.
We can seamlessly synchronize data between Rownd and connected
services, keeping all of your user account information in sync across
all of the tools you use. For example, when you add a potential lead to HubSpot,
Rownd will automatically be aware of that contact and can attach their metadata
to their account when they sign in with their email address or phone number. If
the user corrects information in their profile (e.g., fixing a typo in their
last name), Rownd will propagate that change back to HubSpot.
Not all of our integrations are currently user-configurable, so
[get in touch](https://rownd.io/contact) with us if you want to use one of the
ones that aren't yet self-service. We're happy to help!
Integrations are a beta feature, so you may not see them in your account yet. As a result, there may be bugs and documentation may lag the available connectors. Contact us if you need them to be enabled in your account.
| Integration | Self-service? |
| ------------------------------------------------------ | ------------- |
| [Airtable](./airtable) | Yes |
| [Auth0](./auth0) | Yes |
| [Firebase (Authentication)](./firebase/authentication) | Yes |
| [HubSpot](./hubspot) | Yes |
| Mailchimp | Yes |
| [MailerLite](./mailerlite) | Yes |
| [Token validator](./token-validator) | Yes |
| [Webhooks](./webhooks) | Yes |
| WooCommerce | Yes |
| Zapier | Yes |
# Token validator
Source: https://docs.rownd.io/configuration/integrations/token-validator
Validating third-party tokens
Rownd's token validator allows you to authenticate a token issued by another authentication provider and exchange it for a Rownd token. This feature is useful when migrating to Rownd from another authentication provider and you want to prevent existing users from being signed-out during the transition. It can also be used when moving between contexts, such as when your code is embedded in an implementation that you don't directly control (e.g., a webview inside someone else's mobile app).
## Why it's important
### Keeping users signed-in
When transitioning to Rownd's adaptive authenitcation, it's often important to keep your existing users signed-in once you deploy Rownd. The token validator enables Rownd to accept and validate your users' existing tokens. That way, users won't be forced to sign in again due to the authentication provider upgrade.
### Moving between apps or contexts
If your app is embedded in one of your customers' apps, the "parent" app may have previously created its own user session. If the customer can pass you a token or similar data that can be validated either via a JWKset or a REST API, Rownd's token validator will validate the existing token and extract a user ID from the response so that a user can continue using your app without any friction.
## How to set it up
To set up the token validator, you'll need to configure your authentication provider to issue a token that Rownd can validate.
**Note:** If you do not see **Integrations** in the Rownd left-hand sidebar, please contact the Rownd support team at [support@rownd.io](mailto:support@rownd.io) for assistance.
### Configuring the token validator
To set up the token validator with a generic authentication provider, follow these steps:
1. Navigate to **Integrations** in the Rownd platform sidebar.
2. Enter the API endpoint to be used for token validation.
3. Provide information enabling Rownd to extract a user ID
4. Attach it to an application
#### Coming soon:
In the near future, we'll also support the following configurations:
1. Adding an OpenID Configuration endpoint or a direct URL to a JWK endpoint that Rownd can use to verify an asymmetrically-signed JWT.
2. Adding an HMAC secret that can be used to verify a symmetrically-signed JWT.
If none of the above configurations match your specific use case, please let us know.
#### Reponding to requests from the token validator
When implementing an API for the token validator to call, the response should be a flat JSON object with properties
that match the configuration you supplied to the token validator setup above. For example, if you configured the token validator to extract a `userId` and `email` from the response, the response should look like this:
```json theme={null}
{
"userId": "1234567890",
"email": "juliet@rose.com"
}
```
You can also include additional properties in the response, which will be stored in the user's profile in Rownd if they match the profile schema configured within Rownd.
Providing a user ID in your API response is optional. If none is provided, Rownd will generate a new user ID. If the user ID is present, Rownd will use it instead, which may be helpful if you're trying to map users to an existing system.
#### Handling cases where the token is invalid or the user isn't found
If the token Rownd passes to your API does not match an existing user, you should return either a 400 or a 404 status code, which will cause Rownd to abort the token exchange.
### Firebase setup
If you're using Firebase as your authentication provider, Rownd provides a separate integration. Follow these steps:
1. Navigate to **Integrations**
2. Click on the **Firebase - Authenticaiton** card from the **Connector catalog** tab.
3. Authenticate with Firebase, providing Rownd scoped access for validation.
4. Select the desired **Project** and **App** (if applicable).
5. Save the integration, then attach it to your Rownd application to enable it.
When existing users sign in via Rownd, we'll automatically preserve their Firebase ID and basic user information, which is especially useful if you're referencing users in a separate datastore via this ID.
Once Rownd is fully implemented, your users will not have to "re-sign in" and Rownd will automatically create users inside of Rownd for them.
For additional assistance setting up the token validator, please reach out to [support@rownd.io](mailto:support@rownd.io).
# Webhooks
Source: https://docs.rownd.io/configuration/integrations/webhooks
Run your own logic when data changes within Rownd
Often, multiple sources can create or update profile and account information for
your users. For example, sometimes your app might update profile fields for a
user, but other times the user might update other information from their
browser. In either case, some component of your system might need to know about
those changes as they occur.
Rownd provides a webhook integration that can communicate with essentially any
HTTP-based system, letting you know when new data is created or when existing
data has changed.
### Setup
To enable one or more webhooks, you'll need to configure them through the
[Rownd dashboard.](https://app.rownd.io)
1. From the menu, select **Integrations.**
2. Select the **Connector catalog** tab.
3. From the list of available connectors, click on the **Generic webhook**
entry. The connector setup dialog will appear.
4. Enter a descriptive name for your webhook and click **Next**.
5. Select your desired **HTTP method** and enter the URL of your webhook. (If
you're just testing, you might want to use something like
[webhook.site](https://webhook.site))
6. Click **Create** to create the connection.
The dialog should indicate that the webhook was created successfully. Now that
the connection exists, we need to attach it to an application, which will
dispatch updates to the webhook as data changes occur.
1. Select the **Configured connections** tab at the top of the page.
2. Locate the webhook connection you just created and click the three-dots menu
on the right-hand side of the row.
3. From the menu, select **Attach to application**. The **Attach connection**
dialog will appear.
4. From the **Select an application** menu, select the application to which the
connection should be attached. Click **Next**.
5. By default, the webhook will contain the field names as they appear within
Rownd. If you want to change any field names, you may do so by typing the
desired field name(s) into the **Map fields** page.
6. Click **Save.**
After a moment, the attached application should appear in the row next to the
connection. Once this occurs, data updates should begin flowing through the
webhook.
### Payload reference
Overall, the payload for the webhooks will be similar for creates, updates, and
deletes; however the payload will always include a lookup value (such as email
address or phone number) and meta indicating what triggered the webhook.
Below are example payloads of each type of trigger. The main payload fields will
differ based on the fields you defined within Rownd.
Remember, the HTTP method will match the value configured during connector
setup, regardless of the represented action.
#### Data created
```json theme={null}
{
"data": {
"email": "jrose@acme.com",
"first_name": "Juliet",
"last_name": "Rose",
"user_id": "0e223bd4-1324-49ff-b948-122eeaaa42d1"
},
"redacted": [],
"meta": {
"operation": "data_insert",
"lookup_values": [
{
"field": "email",
"value": "jrose@acme.com"
}
]
}
}
```
#### Data updated
```json theme={null}
{
"data": {
"email": "jrose@acme.com",
"first_name": "Juliet",
"last_name": "Rose",
"country": "United States",
"user_id": "0e223bd4-1324-49ff-b948-122eeaaa42d1"
},
"redacted": [],
"meta": {
"operation": "data_update",
"lookup_values": [
{
"field": "email",
"value": "jrose@acme.com"
}
]
}
}
```
#### Data visibly changed
```json theme={null}
{
"data": {
"email": "jrose@acme.com",
"first_name": "Juliet",
"last_name": "Rose",
"country": "<>",
"user_id": "0e223bd4-1324-49ff-b948-122eeaaa42d1"
},
"redacted": ["country"],
"meta": {
"operation": "visibility_update",
"lookup_values": [
{
"field": "email",
"value": "jrose@acme.com"
}
]
}
}
```
#### Data deleted
```json theme={null}
{
"data": {
"user_id": "0e223bd4-1324-49ff-b948-122eeaaa42d1"
},
"meta": {
"operation": "delete",
"lookup_values": [
{
"field": "email",
"value": "jrose@acme.com"
}
]
}
}
```
# Android configuration
Source: https://docs.rownd.io/configuration/mobile/android
Preparing Rownd to work with your Android app
Configure Rownd for Android mobile devices including ([React Native](/sdk-reference/mobile/react-native) and [Flutter](/sdk-reference/mobile/flutter)). This configuration will allow multiple Rownd services to work in the Android operating system like [App Links](/configuration/mobile/overview#what-are-universal-links) and [Passkeys](/configuration/authentication-methods/passkeys).
## Android App Links
### 1. Configure the Rownd Platform
1. Select **Sign-in methods** from the left navigation menu.
2. In the Sign-in preferences section, locate [**Mobile app settings**](/configuration/mobile/mobile-app-settings)
3. Fill out mobile app settings for Android
* Subdomain (e.g., myapp for myapp.rownd.link - the .rownd.link portion is added automatically).
* Play store URL - The direct link to your app in the Google Play Store
* Package name - The package name for your app as shown in the Google Play Console (e.g., `com.example.myapp`)
* SHA256 certificate fingerprints - For dev/test apps signed locally or manually, obtain the SHA256 hash from your keystore. For apps distributed through the Google Play Store that use automatic signing, obtain the SHA256 hash from the [Google Play Console](https://play.google.com/console/developers).
4. Ensure Android is **enabled** and hit **save**
### 2. Configure your Android project
Configure the `AndroidManifest.xml` file with an intent filter containing your `subdomain`
```xml theme={null}
```
# Using Android Instant Apps
Source: https://docs.rownd.io/configuration/mobile/android-instant
100% conversion from web to native mobile app
Android Instant Apps allow users to experience your app without installing it from the Play Store — reducing friction and improving conversion. You can use this to deliver a fast, native authentication experience that gets users signed in before ever asking them to install your app.
> ✅ **Best for**: High-intent flows like authentication, referral links, and onboarding.
***
## How it works
When users tap a link — from a website, ad, QR code, or elsewhere — they launch a lightweight version of your Android app instantly. No Play Store. No install step. Just instant access.
This allows you to:
* Authenticate users quickly, using Rownd
* Capture user intent with minimal drop-off
* Seamlessly transition users to the full app after sign-in
***
## Project structure
To build an Instant App, your Android project must use a **modular** structure.
### 🔹 Base module (`:base`)
The base module includes shared code and resources used across your app, including your instant and installable experiences. This includes:
* Shared layouts and assets
* Common logic/utilities
* The Rownd SDK (💡Keep it lean!)
### 🔹 Feature modules
Split your app into **feature modules** for each experience:
| Module type | Purpose | Notes |
| ---------------- | ---------------------------------------- | ------------------------------- |
| `:instant-login` | The minimal experience for Rownd login | Must stay under 15MB total size |
| `:full-app` | The installable full version of your app | Can include everything |
> ⚠️ **Google Play size limit**: Instant app experiences must be ≤15MB total (including the base module). Strip unused assets, fonts, and libraries.
***
## Getting started
### 1. Enable Instant Apps in your project
Follow [Google’s official guide](https://developer.android.com/topic/google-play-instant) to set up:
* Instant app support in your manifest
* `base`, `feature`, and `instant` module structure
* Instant app build variants
### 2. Add Rownd to your instant feature
Include the Rownd SDK in your `:base` module (or `:instant-login` if you want more separation). Follow the [Android SDK integration guide](/sdk-reference/mobile/android) to configure Rownd for sign-in.
#### `settings.gradle`
```groovy theme={null}
include ':base', ':instant-login', ':full-app'
```
**base/build.gradle.kts**
```kotlin theme={null}
dependencies {
implementation("io.rownd:android:")
// other shared deps
}
```
```kotlin theme={null}
class MainApplication : Application() {
override fun onCreate() {
super.onCreate()
Rownd.configure(
this,
"REPLACE_WITH_YOUR_APP_KEY"
)
}
}
```
#### `instant-login/build.gradle.kts`
```kotlin theme={null}
dependencies {
implementation(project(":base"))
implementation("io.rownd:android:")
// other instant app deps
}
```
```kotlin theme={null}
class InstantLoginActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Your instant app logic here
setContent {
InstantLoginScreen(onSignIn = {
Rownd.requestSignIn()
}) // Your instant app UI
}
}
}
```
### 3. Link to your instant experience
You can generate smart links or deep links to launch your instant app directly from:
* Your website
* QR codes
* Marketing emails and campaigns
Rownd can generate these links automatically, or you can create them manually using App Links.
***
### Example use case
A referral campaign sends users a personalized link. Instead of going to the Play Store, the user:
1. Launches your Instant App directly
2. Authenticates via Rownd (email, passkey, social, etc.)
3. Is optionally prompted to install the full app
4. Their session persists into the full app after install
***
### Benefits
* Higher conversion: Fewer steps = more users signing in
* Lower bounce rate: No detour to the Play Store
* Seamless onboarding: Get users started before asking them to install
***
Need help?
If you’re planning to implement Instant Apps with Rownd, reach out to us — we’d love to help you get started or provide feedback on your module structure.
# iOS configuration
Source: https://docs.rownd.io/configuration/mobile/ios
Preparing your iOS app to work with Rownd
Configure Rownd for iOS mobile devices including ([React Native](/sdk-reference/mobile/react-native) and [Flutter](/sdk-reference/mobile/flutter)). This configuration will allow multiple Rownd services to work in the iOS operating system like [Universal Links](/configuration/mobile/overview#what-are-universal-links) and [Passkeys](/configuration/authentication-methods/passkeys).
### 1. Configure in Rownd Platform
1. Select **Sign-in methods** from the left navigation menu.
2. In the Sign-in preferences section, locate [**Mobile app settings**](/configuration/mobile/mobile-app-settings)
3. Fill out mobile app settings for iOS
* Subdomain (e.g., myapp for myapp.rownd.link - the .rownd.link portion is added automatically).
* App store URL - The direct link to your app in the Apple App Store
* Bundle IDs - A comma-separated list of bundle IDs for your app (e.g., `com.example.myapp`)
* Team ID - The team ID for your app as shown in the [Apple Developer Portal](https://developer.apple.com/account) (e.g., `15GKOXA3H6`)
4. Ensure iOS is **enabled** and hit **save**
### 2. Configure in project (Xcode or entitlements file)
#### Using Xcode
1. In your Xcode project, select your app from the left, then navigate to Targets > Signing & Capabilities
2. Add Associated Domains as a capability
3. Add the subdomain to the applinks entitlement. `applinks:.rownd.link`
#### Using entitlements file
file: `ios/[appName]/[appName].entitlement`
```xml theme={null}
...
com.apple.developer.associated-domains
...
subdomain.rownd.link
```
# Using iOS App Clips
Source: https://docs.rownd.io/configuration/mobile/ios-app-clip
100% conversion from web to native mobile app
You can use Rownd's iOS SDK with its built-in understanding of App Groups to get users from web, to App Clip, to mobile app without losing users during conversion. Simply have users sign in from the App Clip. After they download the full app, they will already be signed in.
This seamless authentication flow solves one of the biggest friction points in mobile user acquisition - requiring users to create new accounts or re-authenticate when transitioning between experiences. With Rownd:
* Users can authenticate on your website
* Continue their journey in an App Clip with the same authenticated session
* Install the full app and find themselves already signed in and ready to go
This creates a frictionless conversion funnel that significantly improves user retention and engagement by eliminating authentication barriers between platforms.
You can reference an example using App Clips with Rownd in the official [Rownd iOS SDK GitHub repo](https://github.com/rownd/ios/tree/main/example/LandmarksAppClip).
## How it works
Rownd leverages Apple's App Groups technology to securely share authentication state between your App Clip and full application. This document provides clear, step-by-step guidance for integrating and configuring Rownd authentication within your App Clips and ensuring continuity to your main iOS application.
The following steps assume you have already set up your App Clip; if you haven't done this yet, please skip to the [setting up app clips](#%F0%9F%93%B1-setting-up-app-clips) section below before proceeding with the Rownd integration.
***
## 📦 Step 1: Add Rownd SDK dependencies
Before configuring Rownd in your app and App Clip, you need to add the Rownd SDK as a dependency to both targets:
### Using Swift Package Manager (Recommended)
1. In Xcode, select **File → Add Packages...**
2. Enter the Rownd iOS SDK repository URL: `https://github.com/rownd/ios`
3. Select "Up to Next Major Version" for dependency rule
4. **Important:** Make sure to select BOTH your main app target AND your App Clip target:
* Your main app target (e.g., `YourApp`)
* Your App Clip target (e.g., `YourApp Clip`)
### Using CocoaPods
Alternatively, if your project uses CocoaPods, add Rownd to your Pod file:
```ruby theme={null}
# Your main app target
target 'YourApp' do
pod 'Rownd'
end
# Your App Clip target
target 'YourApp Clip' do
pod 'Rownd'
end
```
Then run `pod install` in your terminal to install the dependencies.
For more detailed information on installing and configuring the Rownd iOS SDK, refer to the [Rownd iOS SDK Documentation](https://docs.rownd.io/sdk-reference/mobile/ios).
***
## 🔧 Step 2: Create separate AppDelegates
Ensure both your **main app** and **App Clip** targets have separate, clearly linked `AppDelegate.swift` files.
### Example: `AppDelegate.swift`
Both your App Clip and Main App should initialize Rownd like this:
```swift theme={null}
import UIKit
import Rownd
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
Task {
Rownd.config.appGroupPrefix = "com.example" // Replace with your app group prefix
await Rownd.configure(
launchOptions: launchOptions,
appKey: "REPLACE_WITH_YOUR_ROWND_APP_KEY"
)
}
return true
}
}
```
### Common mistake: When using SwiftUI, be sure to link your `AppDelegate` in your main app's `App` struct:
Ensure the following line explicitly links your AppDelegate:
```swift theme={null}
import SwiftUI
@main
struct YourApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
```
***
## 🔗 Step 3: Configure App Groups
Both your main app and App Clip must share the **exact same App Group identifier** for Rownd authentication continuity:
### MUST USE the Rownd preset App Group identifier format:
```
group..io.rownd.sdk
```
Example:
```
group.com.your-app.io.rownd.sdk
```
Explicitly set this App Group in both:
* **Main App → Signing & Capabilities → App Groups**
* **App Clip → Signing & Capabilities → App Groups**
***
## 📦 Step 4: Configure Rownd Dashboard
Rownd explicitly relies on your **bundle identifiers**. You must explicitly list both your App Clip and Main App bundle identifiers in the Rownd Dashboard:
**Example:**
* Main app: `com.yourapp.ios-demo`
* App Clip: `com.yourapp.ios-demo.Clip`
Explicitly add both bundle IDs under your Rownd Dashboard **App Settings → Bundle IDs**.
***
## 📋 Step 5: Set required capabilities and entitlements
Explicitly ensure the following capabilities and entitlements are correctly configured:
* ✅ **App Groups** (same identifier as above)
* ✅ **Associated Domains** (for universal linking)
```
applinks:your-domain.com
```
* ✅ **Parent Application Identifiers** (for App Clip → Main App linking)
Manually set the [Parent Application Identifiers](https://developer.apple.com/documentation/bundleresources/entitlements/com.apple.developer.parent-application-identifiers) if missing:
### Example (`.entitlements` file XML):
```xml theme={null}
com.apple.developer.parent-application-identifierscom.yourapp.ios-demo
```
***
## 🛠️ Step 6: Debugging & Common Issues
### Issue: `x-rownd-app-key header is required`
Indicates the Rownd SDK is not properly initialized. Confirm:
* Explicit AppDelegate linking (Step 2).
* Proper App Groups set up (Step 3).
* Correct app keys and bundle IDs in Rownd Dashboard (Step 4).
### Issue: Rownd Hub not loading
* Ensure ATS (`App Transport Security`) settings temporarily allow arbitrary loads (testing only):
```xml theme={null}
NSAppTransportSecurityNSAllowsArbitraryLoads
```
***
## 🚀 Final Checklist
✅ **Separate AppDelegates explicitly linked**\
✅ **App Groups correctly shared**\
✅ **Bundle IDs registered explicitly on Rownd dashboard**\
✅ **Capabilities and Entitlements correctly set**
This structured configuration ensures seamless Rownd authentication across your main app and App Clips.
***
## ✨ Best practices for App Clips with Rownd
### 1. Use Smart Links for auto sign-in
For a truly seamless experience, you can automatically sign in users using Smart Links that direct users to your App Clip. When transitioning an authenticated user from your website, redirect them using an authenticated Smart Link. Or, use Smart Links in directed communications to users to ensure they're signed in when they open your App Clip (and ultimately, your full app).
### 2. Use explicit sign-up buttons
Rather than forcing authentication immediately upon launch, provide a clear call-to-action that allows users to sign up when they're ready:
```swift theme={null}
Button("Sign up") {
Rownd.requestSignIn()
}
.buttonStyle(.borderedProminent)
.padding()
```
This approach respects user agency and creates a better first-time experience.
### 3. Maintain UI consistency between your App Clip and main app
Make your App Clip feel like a natural extension of your main app. Use the same:
* Color schemes and branding
* UI components and patterns
* Typography and visual language
* Terminology and navigation patterns
This creates a seamless transition when users move from the App Clip to your full app, reinforcing that they're already familiar with your product.
### 4. Focus on a single, core task
App Clips should concentrate on delivering one specific feature quickly:
* Identify the most valuable single action for new users
* Remove all UI elements not directly supporting this core action
* Keep the App Clip under 10MB (smaller is better for faster loading)
* Design the authentication flow to support this core task with minimal friction
### 5. Design strategic, full app installation prompts
Time your prompts for installing the full app strategically:
* Wait until after users complete their core task
* Highlight additional features available in the full app
* Emphasize that they'll remain signed in when transitioning
* Use Apple's App Clip API to show the installation card:
```swift theme={null}
// UIKit: After user completes primary task
guard let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene else { return }
let config = SKOverlay.AppClipConfiguration(position: .bottom)
let overlay = SKOverlay(configuration: config)
overlay.present(in: scene)
```
For SwiftUI, you can also use the [`.appStoreOverlay` modifier](https://developer.apple.com/documentation/swiftui/view/appstoreoverlay\(ispresented:configuration:\)) to present the App Clip card:
***
## 📱 Setting up App Clips
Before integrating Rownd authentication with your App Clip, you'll need to properly set up the App Clip itself. This process requires configuration across multiple platforms:
### Xcode Configuration
* Create an App Clip target in your existing iOS app project
* Configure the App Clip's `Info.plist` with required entries
* Set up App Clip experience metadata
### Parent-child relationship configuration
A critical aspect of App Clips is establishing the proper parent-child relationship between your main app and App Clip:
#### For the App Clip (child):
Add the parent application identifier entitlement to your App Clip's `entitlements` file:
```xml theme={null}
com.apple.developer.parent-application-identifiers$(AppIdentifierPrefix)com.yourcompany.yourapp
```
#### For the main app (parent):
Add the associated App Clip identifier entitlement to your main app's `entitlements` file:
```xml theme={null}
com.apple.developer.associated-appclip-app-identifiers$(AppIdentifierPrefix)com.yourcompany.yourapp.Clip
```
This bidirectional relationship is essential for:
* Proper App Store presentation
* Authentication state transfer
* App Clip to full app conversion tracking
### App Clip Codes & Launch Experience
App Clip Codes provide an intuitive way for users to discover and launch your App Clip in the physical world:
* **App Clip Codes**: Custom-designed scannable codes that can be placed on physical materials
* **NFC tags**: For contactless launch of your App Clip
* **QR codes**: For camera-based scanning and launch
* **Safari App Banner**: Present an App Clip card when users visit your website
* **Maps integration**: Allow discovery through Apple Maps (if applicable)
The launch experience is critically important - when a user activates an App Clip:
1. A lightweight App Clip card appears with basic app information
2. User taps "Open" to launch without installation
3. App Clip loads with contextual data from the invocation method
4. Rownd authentication can happen seamlessly at this point
### Apple Developer Portal Configuration
* Configure App ID for your App Clip
* Set up appropriate provisioning profiles
* Enable necessary entitlements
### App Store Connect Configuration
* Set up App Clip card metadata
* Configure invocation methods (QR codes, NFC tags, links)
* Submit for review alongside your main app
Setting up App Clips properly requires significant effort and attention to detail across all these platforms. We recommend thoroughly reviewing Apple's official documentation before proceeding with the Rownd integration steps outlined in this guide.
For complete details on setting up App Clips, refer to:
* [Apple's App Clip documentation](https://developer.apple.com/documentation/appclip)
* [Associated App Clip App Identifiers documentation](https://developer.apple.com/documentation/bundleresources/entitlements/com.apple.developer.associated-appclip-app-identifiers)
* [App Clip Codes documentation](https://developer.apple.com/documentation/app_clips/creating_app_clip_codes)
***
## 📖 References
* [Rownd SDK iOS documentation](https://docs.rownd.io/sdk-reference/mobile/ios#usage-within-app-extensions)
* [Apple App Clip documentation](https://developer.apple.com/documentation/appclip)
* [Associated App Clip App Identifiers documentation](https://developer.apple.com/documentation/bundleresources/entitlements/com.apple.developer.associated-appclip-app-identifiers)
* [Creating App Clip Codes documentation](https://developer.apple.com/documentation/app_clips/creating_app_clip_codes)
# Mobile app settings
Source: https://docs.rownd.io/configuration/mobile/mobile-app-settings
Configuring your mobile app
Configure mobile app settings to enable a prompt for mobile users to download the app or take them to their existing app.
### Configure iOS mobile app settings
1. App store URL
1. Log in to [Apple App Store Connect](https://appstoreconnect.apple.com/apps).
2. Go to My Apps and click on you app.
3. Click App Information in the General section.
4. Click View on App Store in the Additional Information section.
5. Copy the URL of the page.
2. Bundle IDs
1. Enter a comma-separated list of bundle IDs for your app (e.g., `com.example.myapp`)
3. Team ID
1. Log in to Apple [Apple Developer Portal](https://developer.apple.com/account)
2. Scroll down to Membership details
3. Copy the Team ID
### Configure Android mobile app settings
1. Play store URL
1. Log in to [Google Play Console](https://play.google.com/console)
2. Select your app from the dashboard.
3. Click on View on Google Play.
4. Copy the URL of the page.
2. Package name
1. Log in to [Google Play Console](https://play.google.com/console)
2. Select your app from the dashboard.
3. Copy package name from the app dashboard
3. SHA-256 Cert Fingerprints
1. Log in to [Google Play Console](https://play.google.com/console)
2. Select your app from the dashboard.
3. Click App Integrity under the Release section then click Settings in the Play app signing section.
4.Copy SHA-256 certificate fingerprint in the App signing key certificate section
# Mobile app configuration
Source: https://docs.rownd.io/configuration/mobile/overview
Configure mobile apps in Rownd with ease.
## On this page
* [Introduction to Mobile App Configuration](#introduction-to-mobile-app-configuration)
* [What Are Universal Links?](#what-are-universal-links%3F)
* [Submitting Your App for Review](#submitting-your-app-for-review)
* [Configure by Platform](#configure-by-platform)
* [iOS Configuration](/configuration/mobile/ios)
* [Android Configuration](/configuration/mobile/android)
## Introduction to Mobile App Configuration
Rownd makes it easy to add secure, seamless sign-in to your mobile app. Whether you're building with [React Native](/sdk-reference/mobile/react-native), [Flutter](/sdk-reference/mobile/flutter), or [native iOS](/sdk-reference/mobile/ios)/[Android](/sdk-reference/mobile/android), our mobile SDKs allow you to integrate modern authentication experiences without the complexity.
Once the SDK is set up, you can enable features like universal Sign-in Links — which automatically direct users to your app and sign them in without needing a password.
This guide will walk you through how Rownd works with mobile platforms, how to prepare your app for App Store review, and how to configure your mobile SDK for iOS and Android.
### What are universal links?
Universal links are a type of deep link that allows users to open your mobile app directly from a URL. If the app is installed, the link takes the user straight to the app. If not, it redirects them to the appropriate app store (Apple App Store or Google Play).
Rownd uses universal links as part of its Sign-in flow, helping users sign in seamlessly with a single tap — no password required.
* **Simplified user experience** - By directing users to the relevant content or app store, universal links create a more streamlined and intuitive user journey, which can lead to increased user engagement and retention.
* **Improved conversion rates** - By reducing friction in the user experience and lowering the barriers to entry, universal links can help boost conversion rates for app installations that lead to user sign-ups.
* **Enhanced security** - Universal links are more secure than legacy custom URL schemes, as they rely on the app's domain and can only be used by the associated app, thus reducing the risk of phishing attacks or unauthorized access.
Universal links reduce friction and improve conversion by making sign-in feel like magic — no extra steps, no lost users.
A [Rownd Mobile SDK](/sdk-reference/mobile) must be installed in your app to use this feature.
### Submitting Your App for Review
When submitting your app to the App Store or Google Play Store, reviewers will need a way to access and test the app. If you're using Rownd for authentication, you can streamline this process by setting up simple test accounts.
**Recommended Setup**
Use a disposable email inbox service like [Mailinator](https://www.mailinator.com) to create one or more test accounts.
**Example:**
* Test email address: [my-app-review-1@mailinator.com](mailto:my-app-review-1@mailinator.com)
* Instruct reviewers to:
1. Enter the test email in your app’s sign-in screen
2. Visit the corresponding Mailinator inbox at:
```
https://www.mailinator.com/v4/public/inboxes.jsp?to=my-app-review-1
```
You can create multiple test accounts by incrementing the address (e.g., `my-app-review-2@mailinator.com`, etc.).
> Be sure the inbox name matches the email address\
> (e.g., `my-app-review-1@mailinator.com` → `my-app-review-1` inbox on Mailinator).
**Optional Enhancements**
* Preload test data into the accounts
* Use conditional logic in your app to streamline or skip onboarding for known test users
This approach works for both iOS (App Store) and Android (Google Play), and is commonly accepted during the review process.
### Configure by platform
See our step-by-step configuration guides for [iOS](/configuration/mobile/ios) and [Android](/configuration/mobile/android) for assistance in filling out this section.
Configure mobile for iOS including React Native and Flutter
Configure mobile for Android including React Native and Flutter
# OpenID Connect Setup
Source: https://docs.rownd.io/configuration/oidc/overview
## Table of Contents
1. [Set up using the platform](#using-the-rownd-platform)
2. [Setup using the API](#using-the-api)
* [Required headers](#required-headers)
* [API endpoints](#api-endpoints)
* [OIDC configuration discovery](#oidc-configuration-discovery)
* [OIDC endpoints](#oidc-endpoints)
* [Response format](#response-format)
* [Logo management](#uploading-oidc-client-logos)
* [Upload requirements](#required-headers-1)
* [Logo parameters](#parameters)
* [Advanced configuration](#advanced-configuration)
* [Custom interaction endpoint](#custom-interaction-endpoint)
* [User flow example](#user-flow-example)
### Using the Rownd Platform
You can set up an OIDC client directly through the [Rownd platform](https://app.rownd.io):
**1. Navigate to your application**
**2. Open the "App Keys" page on the left menu and click on the "OIDC Clients" tab**
**3. Click "Create New OIDC Client"**
**4. Set your OIDC client details**
#### Fields
* **Name**: A display name for your OIDC client (required)
* **Redirect URIs**: Where users will be redirected after authentication (required). You can add more than one.
* Example: `https://example.com/callback`
* **Allowed Scopes**: The scopes that the OIDC client is allowed to request. You can add more than one.
* Example: `openid profile email` ; note; you can add additional date fields to Rownd for more finite scopes.
Click "Next"
**5. Retrieve client credentials and OpenID endpoints**
You can now retrieve your client credentials and use them to configure your OIDC client. You can also see the OIDC endpoints.
Make sure to save your client credentials (client\_id and secret) after creation, as the secret cannot be retrieved later.
**6. OIDC customizations**
Click on "Customizations" to customize sign-in and consent modals with a call to action and logos that help your users stay in context.
### Using the API
To create or update an OIDC client configuration via the API, you'll need your Rownd application credentials.
#### Required headers
| Header | Description |
| -------------------- | ----------------------------- |
| `x-rownd-app-key` | Your Rownd application key |
| `x-rownd-app-secret` | Your Rownd application secret |
#### API endpoints
* Create: `POST https://api.rownd.io/applications/{app-id}/oidc-clients`
* Update: `PUT https://api.rownd.io/applications/{app-id}/oidc-clients/{client-id}`
#### cURL Example
```bash theme={null}
# Create new OIDC client
curl -X POST 'https://api.rownd.io/applications/{app-id}/oidc-clients' \
-H 'x-rownd-app-key: YOUR_APP_KEY' \
-H 'x-rownd-app-secret: YOUR_APP_SECRET' \
-H 'Content-Type: application/json' \
-d '{
"name": "Example OIDC Provider",
"description": "Example OIDC Provider",
"config": {
"allowed_origins": [
"https://example.com"
],
"redirect_uris": [
"https://example.com/callback"
],
"post_logout_uris": [
"https://example.com/logout"
],
"logo_uri": "https://storage.rownd.io/logo-example.png",
"logo_dark_mode_uri": "https://storage.rownd.io/logo-dark-example.png"
}
}'
# Update existing OIDC client
curl -X PUT 'https://api.rownd.io/applications/{app-id}/oidc-clients/{client-id}' \
-H 'x-rownd-app-key: YOUR_APP_KEY' \
-H 'x-rownd-app-secret: YOUR_APP_SECRET' \
-H 'Content-Type: application/json' \
-d '{
"name": "Updated OIDC Provider",
"description": "Updated OIDC Provider",
"config": {
"allowed_origins": [
"https://example.com"
],
"redirect_uris": [
"https://example.com/callback"
],
"post_logout_uris": [
"https://example.com/logout"
],
"logo_uri": "https://storage.rownd.io/logo-example.png",
"logo_dark_mode_uri": "https://storage.rownd.io/logo-dark-example.png"
}
}'
```
Replace `YOUR_APP_KEY`, `YOUR_APP_SECRET`, and `{app-id}` with your actual Rownd application credentials and ID. For the update request, also replace `{client-id}` with your OIDC client ID.
## Configuration
Refer to the [Rownd OpenID Connect API documentation](/api-reference/oidc/clients) for detailed information on creating and managing OpenID clients.
To create a new OIDC client configuration, send a POST request to `api.rownd.io/applications/{app-id}/oidc-clients` with the following body parameters:
### Request Body Parameters
| Parameter | Description |
| --------------------------- | ----------------------------------------------------------------------- |
| `name` | The display name of your OIDC client |
| `description` | A brief description of your OIDC client |
| `config.allowed_origins` | Array of allowed origins that can make requests to the OIDC server |
| `config.redirect_uris` | Array of valid URIs where users will be redirected after authentication |
| `config.post_logout_uris` | Array of valid URIs where users will be redirected after logging out |
| `config.logo_uri` | URL to the logo image used in light mode |
| `config.logo_dark_mode_uri` | URL to the logo image used in dark mode |
### Example Request
```json theme={null}
{
"name": "Example OIDC Provider",
"description": "Example OIDC Provider",
"config": {
"allowed_origins": [
"https://example.com"
],
"redirect_uris": [
"https://example.com/callback"
],
"post_logout_uris": [
"https://example.com/logout"
],
"logo_uri": "https://storage.rownd.io/logo-oidc-client-app_1234_oidcc_5667-filename.png",
"logo_dark_mode_uri": "https://storage.rownd.io/logo-oidc-client-app_1234_oidcc_5667-filename.png"
}
}
```
### Response Format
Both POST and PUT requests will return a response with the following structure:
```json theme={null}
{
"id": "oidc_client_ck9c1glf0100001l2f7z8z9z9",
"app_id": "app_ckl8bcf1g000001l2f7z8z9z9",
"name": "Example OIDC Provider",
"description": "Example OIDC Provider",
"config": {
"allowed_origins": [
"https://example.com"
],
"redirect_uris": [
"https://example.com/callback"
],
"post_logout_uris": [
"https://example.com/logout"
],
"logo_uri": "https://storage.rownd.io/logo-oidc-client-app_1234_oidcc_5667-filename.png",
"logo_dark_mode_uri": "https://storage.rownd.io/logo-oidc-client-app_1234_oidcc_5667-filename.png"
},
"created_at": "2024-12-05T23:34:05.709Z",
"updated_at": "2024-12-05T23:34:05.709Z",
"credentials": [
{
"name": "Production API Key",
"client_id": "string",
"secret": "string",
"expires": "2024-12-31T23:59:59Z",
"application": "app_k3y1qwerty12345",
"app_variant_id": "variant_fgy1qw367fty121lm",
"oidc_client_configuration_id": "oidcc_k3y1qwerty12345",
"created_at": "2024-12-05T23:34:05.709Z",
"updated_at": "2024-12-05T23:34:05.709Z"
}
]
}
```
### Response Fields
| Field | Description |
| ------------- | ------------------------------------------------------------- |
| `id` | Unique identifier for the OIDC client configuration |
| `app_id` | The Rownd application ID this configuration belongs to |
| `name` | Display name of the OIDC client |
| `description` | Description of the OIDC client |
| `config` | Configuration object containing origins, URIs, and logos |
| `created_at` | Timestamp of when the configuration was created |
| `updated_at` | Timestamp of the last update |
| `credentials` | Array of credential objects containing authentication details |
#### Credentials Object
| Field | Description |
| ------------------------------ | ---------------------------------------------- |
| `name` | Name of the credential |
| `client_id` | The OIDC client ID to use for authentication |
| `secret` | The client secret to use for authentication |
| `expires` | Expiration date of the credentials |
| `application` | Associated Rownd application ID |
| `app_variant_id` | Variant ID if applicable |
| `oidc_client_configuration_id` | ID of the OIDC client configuration |
| `created_at` | Timestamp of when the credentials were created |
| `updated_at` | Timestamp of the last credentials update |
Store the `client_id` and `secret` securely as they will be needed for all subsequent OIDC operations.
## OpenID Configuration Discovery
Rownd provides a standard OpenID Configuration discovery endpoint that returns a complete list of OIDC specifications and endpoints for your application.
### Discovery Endpoint
```http theme={null}
GET api.rownd.io/oidc/{app_id}/.well-known/openid-configuration
```
Replace `{app_id}` with your Rownd application ID to get the complete OIDC configuration for your app. For example:
```
https://api.rownd.io/oidc/app_wj43asd4ywn790plclbhux6a/.well-known/openid-configuration
```
This endpoint returns a JSON document containing all supported OIDC features, endpoints, and capabilities of your Rownd OIDC server, following the OpenID Connect Discovery specification.
The discovery endpoint is publicly accessible and does not require authentication. It's commonly used by OIDC clients to automatically configure themselves.
## OpenID Endpoints
Rownd provides three main OIDC endpoints, all accessible at `https://api.rownd.io/oidc/{app-id}/`:
### 1. Authorization Endpoint (`/auth`)
* Used to authenticate users and obtain authorization
* Initiates the authentication flow
* Returns an authorization code that can be exchanged for tokens
* Supports standard OIDC parameters like `scope`, `response_type`, and `redirect_uri`
### 2. Token Endpoint (`/token`)
* Exchanges authorization codes for access and ID tokens
* Supports refresh token requests
* Requires client authentication using client\_id and client\_secret
* Returns JWT tokens containing user information and access rights
### 3. UserInfo Endpoint (`/me`)
* Provides detailed information about the authenticated user
* Requires a valid access token
* Returns user profile data based on the granted scopes
* Supports standard OIDC claims
## Credentials
After creating an OIDC client configuration, you'll receive credentials in the response:
* `client_id`: Your unique client identifier
* `client_secret`: Your client secret for secure communication
Store your client\_secret securely! It cannot be recovered if lost and would require generating new credentials.
## Implementation Flow
1. Configure your OpenID client using the configuration endpoint
2. Store the returned client\_id and client\_secret securely
3. Implement the authorization flow:
* Direct users to the `/auth` endpoint for authentication
* Handle the callback with the authorization code
* Exchange the code for tokens at the `/token` endpoint
* Fetch user information from the `/me` endpoint as needed
## Example Implementation
```javascript theme={null}
// Example authorization request
const authUrl = `https://api.rownd.io/oidc/${appId}/auth?` +
`client_id=${clientId}&` +
`redirect_uri=${encodeURIComponent(redirectUri)}&` +
`response_type=code&` +
`scope=openid profile email`;
// Redirect user to authUrl
// After receiving the authorization code in your callback:
async function exchangeCode(code) {
const response = await fetch(`https://api.rownd.io/oidc/${appId}/token`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'authorization_code',
code,
client_id: clientId,
client_secret: clientSecret,
redirect_uri: redirectUri,
}),
});
return await response.json();
}
```
## Best Practices
1. Always use HTTPS for redirect URIs
2. Implement proper token storage and refresh mechanisms
3. Validate all tokens on your backend
4. Keep your client\_secret secure and never expose it in client-side code
5. Implement proper error handling for all OIDC endpoints
Need help? Contact our [support team](mailto:support@rownd.io) for assistance with your OIDC implementation.
### Uploading OpenID Client Logos
You can upload custom logos for your OIDC client that will be displayed in light and dark modes. Logos can be uploaded using the following API endpoint.
#### Logo Upload Endpoint
```http theme={null}
PUT /application/{app-id}/oidc_clients/{client-id}/logo/{type}
```
#### Parameters
| Parameter | Description |
| --------- | --------------------------------------------------------- |
| `app` | Your Rownd application ID |
| `client` | Your OIDC client ID |
| `type` | Either 'light' or 'dark' for the respective display modes |
#### Required Headers
| Header | Description |
| -------------------- | ----------------------------- |
| `x-rownd-app-key` | Your Rownd application key |
| `x-rownd-app-secret` | Your Rownd application secret |
| `x-rownd-filename` | The filename of your logo |
Only PNG and SVG file formats are supported for logo uploads.
#### cURL Example
```bash theme={null}
# Upload light mode logo
curl -X PUT 'https://api.rownd.io/application/{app-id}/oidc_clients/{client-id}/logo/light' \
-H 'x-rownd-app-key: YOUR_APP_KEY' \
-H 'x-rownd-app-secret: YOUR_APP_SECRET' \
-H 'x-rownd-filename: logo.png' \
-H 'Content-Type: image/png' \
--data-binary '@/path/to/your/logo.png'
# Upload dark mode logo
curl -X PUT 'https://api.rownd.io/application/{app-id}/oidc_clients/{client-id}/logo/dark' \
-H 'x-rownd-app-key: YOUR_APP_KEY' \
-H 'x-rownd-app-secret: YOUR_APP_SECRET' \
-H 'x-rownd-filename: logo-dark.svg' \
-H 'Content-Type: image/svg+xml' \
--data-binary '@/path/to/your/logo-dark.svg'
```
Ensure your logo files meet the following requirements:
* File format: PNG or SVG only
* Recommended dimensions: At least 512x512 pixels for optimal display
* File size: Keep files under 5MB for best performance
### Advanced configuration
#### Custom interaction endpoint
By default, OpenID authentication flows direct users to a Rownd-hosted URL for sign-in. However, if you have Rownd integrated into your website or application, you can provide a custom interaction endpoint for a more streamlined experience.
When configured, users will be directed to your site/app instead of the default Rownd URL. This provides several benefits:
* Maintains your branded experience
* Leverages existing user sessions
* Reduces authentication steps when users are already logged in
* Provides a more seamless OIDC consent flow
##### Configuration
Add the `interaction_endpoint` to your OIDC client configuration under the `config` object:
```json theme={null}
{
"name": "Example OIDC Provider",
"description": "Example OIDC Provider",
"config": {
"allowed_origins": [
"https://example.com"
],
"redirect_uris": [
"https://example.com/callback"
],
"post_logout_uris": [
"https://example.com/logout"
],
"interaction_endpoint": "https://example.com/auth",
"logo_uri": "https://storage.rownd.io/logo-example.png",
"logo_dark_mode_uri": "https://storage.rownd.io/logo-dark-example.png"
}
}
```
The interaction endpoint must be a page where the Rownd JavaScript snippet is properly installed and configured (a single-page app like React will also work). This ensures the authentication flow can properly handle the OpenID consent process.
##### User flow example
1. User initiates OIDC sign-in from a third-party application
2. Instead of going to `hub.rownd.io`, they are redirected to your custom endpoint (e.g., `https://example.com/auth`)
3. If the user is already signed in on your site:
* They only need to approve the OIDC consent
* No additional authentication is required
4. If the user is not signed in:
* They'll see your normal Rownd authentication flow
* After signing in, they'll be prompted for OIDC consent
5. After consent, they are redirected back to the original application
This approach can significantly reduce friction in the authentication process, especially for users who frequently interact with your platform.
# Configuration
Source: https://docs.rownd.io/configuration/overview
The Rownd platform gives everything you need to add customizable authentication to your product
Rownd provides an out-of-the-box configuration allowing you to deploy frictionless authentication into your product in minutes. However, we know that your users have unique expectations that affect how they think about authentication. Some are technically-minded and will consciously pick a specific sign-in method while others will simply press the default or select whatever seems simplest.
Rownd makes it easy to adjust your sign-in experience for what best fits your user-base. Rownd also dynamically tweaks the sign-in flow per user based on the their device, browser, and behaviors.
You can adjust your product's sign-in experience in the following ways:
# User groups
Source: https://docs.rownd.io/configuration/user-accounts/groups
## What are Groups?
Groups allow you to segment users within your application. You can manage groups as an administrator through the Rownd
Platform or programmatically through the [Group APIs](/api-reference/groups/overview). You can even allow users to create and manage their own groups. Once added to a group, users can be assigned roles to give them certain permissions
within the group.
## Why Use Groups?
* **Collaborations**: Suitable for apps promoting user collaboration or shared account spaces. Users can invite others or create new groups within your app.
* **Role-Based Access**: Add users to a group and assign them specific roles. Check their role withini a group to enforce role-based access control.
## How it works
1. From the "Users" tab in the Rownd platform, go to the "Groups" tab to view, manage, and add groups.
2. Add a group: Use the "add" dropdown button from the groups tab and click "add new group." Name your group and determine whether an invitation is required to join. Open groups are suitable for public roles, while invitation-required groups are better for private roles.
4. After adding a group, click "view" to see its contents and members.
5. Add users manually or use Rownd APIs to integrate the invite flow into your app. Provide an email or phone number, select the member's role, and include a redirect URL for the user.
Currently, you can only add one user at a time from the Rownd platform.
6. After adding a member, copy the provided invite link. For now, you'll need to send this link to users via email, SMS, or some other means yourself. We will soon send this invite automatically for you.
7. Manage members from the group’s page. All users in all groups will appear in the "users" table in the users tab on the platform. Once a user becomes part of a group, that group will appear in their Rownd account.
8. To delete a group from the platform, either use the trash icon in the group line item in the groups table or press “Delete this group” from the specific group’s page.
9. Edit a group name by clikcing on the 'Edit' icon on the card under your Group's name in a group page.
## Rownd Groups API Commands
Go check out the [Group APIs](/api-reference/groups/overview) to get started integrating groups into your app
## Coming Soon
**Groups UI**
We will soon add support for managing groups, members, and invites through Rownd-provided user interfaces available in all of our SDKs.
**Groups SDK Support**
Full support for group management is rolling out soon for all of our SDKs.
Note: The Groups feature is currently in beta. Your feedback at [support@rownd.io](mailto:support@rownd.io) is highly appreciated.
# User Accounts
Source: https://docs.rownd.io/configuration/user-accounts/overview
The Rownd platform gives everything you need to add instant sign in and profiles to your app
Rownd offers instant user profiles through the Rownd Hub, as well as comprehensive [user management](./platform-user-table) in the **Users** tab within the platform. Additionally, with Rownd's [progressive profiles](./progressive-profiles), your users can explore your platform without the need for immediate sign-in, enhancing their experience.
Discover more about user account options below:
# Platform users table
Source: https://docs.rownd.io/configuration/user-accounts/platform-user-table
Unlike other authentication platforms, Rownd provides an intelligent, customizable user profile system. This allows you to collect information about your users, and use it to personalize their experience. It also enables Rownd to handle more of the personalization for you, integrate with other tools you might use, and enforce rules about who can access or update profile data.
We provide a number of built-in fields, but you can also create your own custom fields. You can also customize whether fields are "owned" by the end-user or by your app, which limits who can modify data in the field.
### Managing the profile schema
Rownd configures some commonly used profile fields when an app is first created, but you can add to them, modify them, or remove them as needed.
To manage the profile schema, open the [Rownd dashboard](https://app.rownd.io) and select **Data types** from the side navigation.
#### Schema field options
When adding or editing a field, the following options are available:
* **Data type** - This is the name for the field that will be returned in programmatic operations (e.g., REST API responses). This is also used as the display name if one is not explicitly specified. This should be primarily machine-friendly (e.g., `first_name`)
* **Display name** - This is the name that will be displayed to end-users. If not specified, the "data type" will be used.
* **Type** - This is the data type for the field. The following types are available:
* **String** - Accepts any text.
* **Number** - A numeric value.
* **Boolean** - A `true/false` value.
* **Image** - A binary blob representing an image. Represented as a URL in API responses.
* **Document** - A binary blob representing a document (e.g., PDF, DOC, etc). Represented as a URL in API responses.
* **Date** - A date value.
* **Object** - A flexible, schema-less JSON object (e.g., `{ "foo": "bar" }`).
* **Any** - Makes no assumptions about the data stored--could be anything.
* **Required retention** - Sets the amount of time that data in the field must be retained. This is useful for fields that are required by law (e.g., GDPR requires that data be retained for 6 years). If not specified, data can be removed by the user at any time. \_(Note: It is recommended to use this field only when absolutely necessary.)
* **Data owner** - Specifies who owns the data in the field. If set to **User**, the end-user can modify the data in the field. If set to **Application**, the end-user can only view the data in the field, and the app is responsible for updating it.
* **Visibility** (only applicable when "Data owner" is set to "Application") - Specifies who can view the data in the field. **Visible to users** indicates that the data is visible to the end-user in their profile. **Hidden from users** indicates that the data is only visible to the app when making server-to-server API requests (i.e., the app secret is present).
#### Adding a new field
1. On the data types page, press **Add data type**.
2. From the **Data type** dropdown, select a built-in field or begin typing. If the field you want isn't in the list, you can create a custom field by typing in the desired name.
3. Complete the rest of the form as desired (see [schema field options](#schema-field-options) for details).
4. Press **Add** to save the new field.
#### Editing an existing field
1. On the data types page, locate the field you want to edit and click the three-dots icon on the right side of the table. Select **Edit** from the menu.
2. Make any desired changes to the field (see [schema field options](#schema-field-options) for details) on the available options.
3. Press **Save** to persist the changes and close the dialog.
#### Deleting a field
1. On the data types page, locate the field you want to edit and click the three-dots icon on the right side of the table. Select **Delete** from the menu.
2. In the resulting dialog, verify that you are deleting the correct field, then press **Delete** to confirm.
Deleting a field from the schema does not automatically remove data for that field in each user's profile; however, it will be missing from any API responses.
Regardless, be careful that you don't have code that depends on the presence of this field.
#### Managing users
In the **Users** area of the platform, you have complete control over your users' profile information. Each time a user signs in, they are listed in the Users table. This table allows you to easily locate users, provide support, and manually edit their accounts. It provides information about the sign-in methods they have used and the profile information they have added. Additionally, you can utilize the filtering and sorting tools--located in the top right icons of the table--to efficiently navigate and organize the table.
#### User editor
Clicking on a user in the platform opens the **user editor** modal. It lets you view and manage individual user data like sign-in methods, activity history, profile fields, sessions, and more.
In the user editor, you'll find:
* **USER ID**: At the top, you'll find the user’s **Rownd ID** used to identify this unique user in your app.
* The ability to **delete or disable** the user account from the bottom of the modal.
* **Sign-in information**: This section shows how the user has signed in. You might see a phone number, email address, Apple ID, Google ID, anonymous ID, or wallet address—depending on what’s been used.
* **User metadata**: Displays activity-related info for the user: when they were last active, which method they used to sign in last, when their profile was created, and when they last signed in. You can also view the full user JSON if needed.
* **Profile data**: Shows additional data collected for the user, such as their name, age, address, job role, nickname, username, and any custom claims. If the user has a NEAR wallet, you’ll see that info too. Only fields with values will appear.
* **Sessions & sub-brands**: Here, you can sign the user out of all active sessions. If you're using sub-brands, this section also lets you add or remove the user from sub-brands and see when they were last active in each.
* **Email logs**: If the user has tried to sign in with email, this tab will show a list of sent email events, including recipient address, delivery status, and timestamp. It's helpful for checking deliverability and open rates.
Want more from the user editor? If there’s something you’d like to see added to the user editor, let us know by [contacting us](mailto:support@rownd.io) or reaching out through the in-app chat.
# Progressive profiles
Source: https://docs.rownd.io/configuration/user-accounts/progressive-profiles
Progressive profiles gradually capture new or returning users as they advance through your app experience. Instead of immediately requesting an email, Rownd's progressive profiles allow you to seamlessly transition simple visitors into verified users through thoughtful prompts.
By enabling guest users and associated automations, you can allow users to explore your product until they are ready to complete the full sign-up process without losing any of their app progress.
#### Progressive profile milestones
As users progress through your product's expereince, the goal is for them to eventually become a verified user. Below are the various levels of user interaction with your app and what each means.
* **Visitor**. A visitor is simply a user that has just arrived. They have no Rownd ID or captured session at this time.
* **Guest / Anonymous user**. When a visitor takes an action or spends a certain amount of time in your product (this is customizable) they are considered a Guest (or anonymous user). At this point the user has a Rownd ID associated with their browser or app session.
The benefit of guest users is that their progress will be saved as long as they are accessing your app from the same device or session when they return; think about it like a saved cart on an ecommerce site. The **risk** of guest users is the potential of losing progress if they return on a difference device or browser or after a significant amount of time.
Using Passkeys, it is possible to preserve a guest's anonymity while allowing them to sign in repeatedly or from other devices.
You can enable guest users as a sign-in method from the sign-in methods page.We recommend prompting guest users to add a sign-in method as quickly as makes sense for your use case in order to prevent them from losing any account data. You can do this by assigning automated prompts at specific moments in your app.
* **Unverified user**. Unverified users have provided a piece of verifiable information but have not yet verified it. For example, a user has provided an email address in your app, but has not claimed or verified as their own yet. At this point the user no longer runs the risk of losing account data. If they are signed out or access your app on another device, they can sign in simply by verifying their email address via the normal sign-in process.
To enable Unverified users, navigate to the **Sign-in methods** tab and scroll down to **Sign in preferences.** Here, you can enable unverified users via the toggle. After enabling, new users that provide an email address can sign in without verifying their information on their first visit. On return visits, they will be asked to verify their account.
* **Verified user**. A verified user has verified their account by either verifying their email or phone number, signing in with Google or Apple, or connecting a passkey to a session. Verified users are now fully authenticated and should be able to access their account information after being signed out.
#### Automations for capturing users at the right moment
The following automations are available to help you capture users at the right moment in your app experience:
1. Sign in prompt
2. Passkey prompt (coming soon!)
3. Google one tap prompt (coming soon!)
4. Capture user (coming soon!)
5. Prompt for additional information (coming soon!)
#### Deleting users
According to Rownd's pricing model, you are billed based on the number of active users on your app, specifically those with associated Rownd IDs. In the case of users who remain as "Guest" or "anonymous" without any further progression, you have the option to configure your app to automatically delete their accounts after a specified period of time.
# User Profiles
Source: https://docs.rownd.io/configuration/user-accounts/user-profiles
Understand the anatomy of a Rownd user profile, including user data, attributes, and metadata.
## Anatomy of a Rownd User Profile
A Rownd user profile is a comprehensive collection of user data, attributes, and metadata that allows you to manage and understand your users effectively. This document provides an overview of the key components of a Rownd user profile.
### User data
User data includes fields matching your app's profile data schema. This typically includes fields like:
* **User ID**: A unique identifier for the user.
* **Email**: The user's email address.
* **Phone Number**: The user's phone number.
* **Name**: The user's full name.
Rownd facilitates a strongly-defined user profile schema to ensure consistency and compatibility across your app. You can add as many custom fields as needed to capture additional user information. Each field specifies a data type, such as string, number, boolean, array, object, document, image, and so on.
By default, a user can update any of their profile data (other than their user ID) through Rownd's provided UI components or APIs. You can change a field's visibility or editability settings to restrict user access to specific data.
Rownd profiles can store file objects like images and documnets so that you don't need additional systems for user avatars and other small artifacts.
### Attributes
Attributes are custom data points that you can define and attach to a user profile. These are technically visible to the user, but they are only editable with your application credentials. Rownd's pre-built UI components won't display this data to the user, but savvy users could still view by looking at API responses in their browser (for example).
Attribute names follow the format `namespace:key` and store an array of string values like `["value1", "value2"]`.
You can store any attribute you want; however, note the following namespaces are reserved by Rownd, so you won't be able to create custom attributes in these namespaces. See the section on pre-defined attributes below for a list of writable reserved attributes.
* `rownd:`
* `system:`
#### Pre-defined attributes
The following table lists all of the pre-defined attributes that Rownd uses. You can modify these attributes through Rownd's REST API or through the Rownd Platform. Invalid values within these attributes are typically ignored.
| Attribute Name | Description | Example value |
| -------------------- | -------------------------------------------------- | ---------------------- |
| `rownd:app_variants` | A list of sub-brands the user has interacted with. | `["id1234", "id5678"]` |
#### Custom Attributes
You might decide to include your own custom attributes within a user's profile. Here are some common use cases:
* **Custom fields**: Any additional information you want to store about the user, such as preferences, subscription status, or loyalty points.
* **Tags**: Labels that help categorize and segment users for targeted actions or communications.
Examples:
```json theme={null}
{
"attributes": {
"myapp:loyalty_points": ["100"],
"myapp:tags": ["premium", "vip"]
}
}
```
### Metadata
Metadata provides additional context about the user's interactions and status within your application. This includes:
* **Sign-in Methods**: Information about how the user signed in (e.g., email, social login).
* **Last Sign-in Time**: The last time the user signed into your application.
* **Sub-brands**: A map of sub-brands the user has interacted with, including the sign-in method used and the last sign-in time for each sub-brand.
Most metadata is read-only and is managed by Rownd on your behalf. You can access this information through the Rownd API or the Rownd Platform.
### Example user profile structure
Here is an example structure of a Rownd user profile. The `data` attribute will differ based on your app's profile schema.
```json theme={null}
{
"data": {
"user_id": "user_a3vc29gjsaf0h",
"email": "juliet@example.com",
"phone_number": "+1234567890",
"first_name": "Juliet",
"last_name": "Rose",
"profile_picture": "https://storage.rownd.io/profile.jpg",
},
"attributes": {
"rownd:app_variants": ["id1234", "id5678"],
"myapp:loyalty_points": ["100"],
},
"groups": [{
"group": {
"id": "group_dvbfjkxkvetrr0d45oa7xaoo",
"name": "My app's group",
"member_count": 0,
"app_id": "290167281732813315",
"admission_policy": "invite_only",
"created_at": "2024-07-09T15:35:31.553Z",
"updated_at": "2024-07-09T15:35:31.524Z",
},
"member": {
"user_id": "71f6ceeb-ee0a-4437-9b44-e6229defbab8",
"roles": [
"admin",
"owner"
],
"id": "member_n73ophaa4ksb5dab5bnj4kfv",
"state": "active",
"invited_by": "user_1234",
"added_by": "user_1234",
"group_id": "group_dvbfjkxkvetrr0d45oa7xaoo"
}
}],
"metadata": {
"modified": "2025-01-27T16:44:05.191Z",
"first_sign_in": "2023-09-01T15:41:05.725Z",
"first_sign_in_method": "email",
"last_sign_in": "2025-01-27T16:44:05.160Z",
"last_sign_in_method": "email",
"last_active": "2025-01-27T16:44:05.160Z",
"last_token_refresh": "2023-01-25T18:09:42.248Z",
"app_variants": {
"base": {
"last_sign_in": "2025-01-27T16:44:05.160Z",
"last_sign_in_method": "email"
}
},
"verified_date": "2024-06-05T16:43:45.510Z",
"auth_level": "verified"
},
"state": "enabled"
}
```
### Managing User Profiles
To manage user profiles, you can use the Rownd platform's user management features. This includes viewing and editing user profiles, managing sub-brands, and viewing user activity and metadata.
For more detailed information on managing user profiles, refer to the [API reference](/api-reference/user-profiles/app/insert-update).
By understanding the anatomy of a Rownd user profile, you can better manage your users and provide a personalized experience across your applications.
# Examples
Source: https://docs.rownd.io/configuration/web3/near-examples
Integrate Rownd with NEAR blockchain to provide secure wallet management and user-friendly wallet interactions for your users.
This is a limited beta feature. Please [contact us](mailto:support@rownd.io?subject=Please%20enable%20NEAR) if you're interested in using it.
The Rownd NEAR integration ensures that all of your users have a NEAR account either automatically or on-dmand.
## NEAR Examples
Here are some basic examples of using the Rownd SDK and APIs to interact with NEAR. See the [JavaScript API Reference](/sdk-reference/web/javascript--api-reference#near) for more details
### Trigger an implicit account creation
If you wish to control when NEAR implicit accounts are created for your users, you can opt for the "on-demand" creation
strategy. This improves sign-up time since Rownd does not have to wait for the execution of on-chain contract calls to
complete. You will need to manually ensure that an implicit account exists for a user.
You can execute the following SDK call to ensure an implicit account exists
```javascript Javascript theme={null}
// accountId = "12a734486c485767d02a4747487573e69889a92618c4890328b0a18c6320898cd2"
const accountId = await rownd.near.ensureImplicitAccount();
```
```sh cURL theme={null}
# Invoke the 'near.ensure-implicit-account` with the user's Rownd access token
curl 'https://api.rownd.io/hub/connection_action' \
-H 'authorization: Bearer ' \
-H 'content-type: application/json' \
--data-raw '{"action_type":"near.ensure-implicit-account"}'
# Result:
# {
# "action_type": "ensure-implicit-account",
# "result": "success",
# "data": {
# "near_implicit_account_id": "3df96ef4be51736d4d76f23c801954f72e8421a7751d4e2c44bc7cee35576a70"
# }
# }
```
## Prompt a user for named account creation
This call will open a dialog prompting the user to enter a name prior to creating the NEAR account. This name will end
with `.rownd.near` by default. For instance, if a user specifies `my-account-1`, the full account name will be
`my-account-1.rownd.near`. Work with the Rownd support team if you would like to change this account name suffix to
another value.
```javascript Javascript theme={null}
rownd.near.createNamedAccount();
```
## Prompt a user to connect an account
This call will open a dialog prompting the user to connect a NEAR account. They will be presented with a list of supported wallet providers. Clicking on one of the providers will initiate a NEAR wallet sign-in, after which the NEAR account and wallet ID will be added to the Rownd user's profile data.
```javascript Javascript theme={null}
rownd.near.connectAccount();
```
# Rownd Integration with NEAR
Source: https://docs.rownd.io/configuration/web3/near-overview
Integrate Rownd with NEAR blockchain to provide secure wallet management and user-friendly wallet interactions for your users.
This is a limited feature. Please [contact us](mailto:support@rownd.io?subject=Please%20enable%20NEAR) if you're interested in using it.
The NEAR Protocol is a scalable and user-friendly blockchain platform designed to power the next generation of decentralized applications. With its focus on simplifying the developer and user experience, NEAR is poised to drive mass-adoption of web3 technologies.
Rownd's integration with NEAR addresses one of the most significant barriers to entry for new web3 users - the onboarding process. By automating wallet generation, securely storing private keys, and enabling seamless wallet management through each person's Rownd profile, users can easily interact with NEAR-based applications. This streamlined approach accelerates user onboarding, reduces friction, and fosters a more inclusive web3 ecosystem, empowering a wider audience to participate in the decentralized revolution.
The integration offers the following features:
* **Automatic wallet creation**
When the integration is configured, Rownd will automatically create a NEAR wallet for each user. This eliminates the need for users to manually create a wallet, streamlining the onboarding process and making it more user-friendly.
* **On-Demand wallet creation**
The integration can be configured so that a NEAR wallet is not created automatically upon user sign-in. In this
configuration, you can manually trigger the creation of the NEAR wallet at any point. See our [examples page](/configuration/web3/near-examples).
* **Secure private key storage**
Rownd securely stores the private key associated with each user's NEAR wallet using double encryption. This ensures that the private key remains safe from unauthorized access, providing a high level of security for users' assets.
* **User wallet access**
Users can view their NEAR wallet balance and transaction history through the Rownd profile. This provides a convenient way for users to keep track of their wallet without needing to use a separate interface.
* **Named wallet creation**
With Rownd, users have the option to create a named wallet for their NEAR account. This makes it easy for users to remember their wallet addresses and share them with others for transactions.
* **Easy wallet attachment**
Users can easily attach a NEAR wallet to their Rownd account, making it simple to manage their blockchain assets alongside their other authentication methods.
## Configuring NEAR
This is a limited feature. Please [contact us](mailto:support@rownd.io?subject=Please%20enable%20NEAR) if you're interested in using it.
To set up the Rownd NEAR integration, follow these steps:
1. Create a Rownd NEAR integration in the Rownd platform.
2. Choose between "Testnet" or "Mainnet" based on your requirements.
3. Enter your NEAR wallet and private key to create accounts and fund them (optional).
Now, your Rownd NEAR integration is set up and ready to be used by your users.
## Data Type Updates
After attachhing the NEAR integration to your application, Rownd will add the following fields to your application
data types. Fields marked "Encrypted" are stored encrypted in the Rownd database and only visible to the users.
The implicit NEAR account ID
The implicit private key
The implicit seed phrase
The named NEAR account ID
The named NEAR private key
The named NEAR seed phrase
The personal NEAR account ID
The personal NEAR private key
# Authenticated links
Source: https://docs.rownd.io/magic-links/authenticated
Authenticated magic links are a powerful tool for securely granting users access to your app or website. These links contain an embedded authentication payload that verifies the user's identity, allowing them to bypass the traditional login process. This not only enhances the user experience by providing a seamless entry point but also ensures that access is restricted to authorized users.
When a user clicks on an authenticated magic link, they are automatically signed in and redirected to the specified destination within your app or site. This can be particularly useful for re-engaging users, onboarding new users, or directing users to specific content or features.
To create authenticated magic links, you can use the Rownd API, which allows you to customize the link's behavior and target destination. This flexibility ensures that you can tailor the user experience to meet your specific needs while maintaining a high level of security.
Overall, authenticated magic links offer a convenient and secure way to manage user access, making them an essential component of modern authentication strategies.
## Creating authenticated magic links
Authenticated magic links can only be created via the Rownd API. Since these links contain sensitive authentication information, it's essential to follow best practices for handling and distributing them securely.
Magic links can be created via our REST API or through our SDKs. Backend SDKs can be used to create magic links for any user, while frontend SDKs can be used to create magic links for the currently authenticated user, which are useful for device-transition scenarios.
Here's an example creating an authenticated magic link using the Rownd API. In this example, we're using an email address as the primary user identifier, setting some profile information, and specifying a redirect URL for the user. If the user exists, they will be signed in and redirected to the specified URL. If the user doesn't exist, an account will be created automatically during sign-in.
**Request**
```bash theme={null}
POST https://api.rownd.io/hub/auth/magic
Content-Type: application/json
X-Rownd-App-Key: YOUR_APP_KEY
X-Rownd-App-Secret: YOUR_APP_SECRET
{
"purpose": "auth",
"verification_method": "email",
"data": {
"email": "juliet@rose.com",
"first_name": "Juliet",
"last_name": "Rose"
},
"redirect_url": "https://yourapp.com/welcome",
"expiration": "1h"
}
```
**Response**
```json theme={null}
{
"link": "https://rownd.link/YOUR_UNIQUE_MAGIC_LINK",
"app_user_id": "user_a1b2c3d4"
}
```
# Overview
Source: https://docs.rownd.io/magic-links/overview
Magic links provide a seamless authentication method for getting users into your app or website without requiring them to explicitly sign in. However, you can also use magic links for other purposes, such as re-engaging users, onboarding new users, or directing users to specific app screens. While magic links usually include an authentication payload identifying the user, they can also be used for non-authentication purposes.
In many cases, you can replace Branch or Firebase Dynamic Links with Rownd magic links, as they provide similar functionality at no additional cost with the added benefit of integrated authentication.
### What makes Rownd magic links unique?
* **Integrated authentication**: Unlike standard Magic links, Rownd's Magic Links also manage user sign-in and verification, providing a streamlined login experience across devices and platforms.
* **Security first**: Each link is dynamically generated to verify user identity and restrict unauthorized access.
* **Cross-platform**: Rownd magic links are optimized for use across web, iOS, and Android, ensuring a consistent experience.
* **Unauthenticated / bulk links**: Create reusable links for bulk distribution with a customized call-to-action. Deep link into your app or website or trigger app downloads from the correct app store. This allows users to directly access the download link without requiring authentication.
### Elevate Your Brand with Custom Domains
One of the most powerful features of Rownd Smart Links is the ability to use your own custom domain:
* **Enhanced Brand Trust**: Links displaying your domain instead of a third-party one significantly improve click-through rates
* **Improved Deliverability**: Email and SMS providers are less likely to flag links from established domains
* **Seamless Brand Experience**: Maintain your brand identity throughout the entire user journey
* **Professional Appearance**: Custom domains create a more polished, professional impression
To set up custom domains for your Smart Links, visit our [Custom Domains](/configuration/custom-domains/overview) documentation. Once configured, all your Smart Links will use your branded domain, creating a cohesive experience from email or SMS all the way through to your application.
## Creating and using smart links
Rownd offers two powerful ways to create Smart Links, each designed for different use cases and workflow preferences:
### Platform-Based Creation
You can now create and manage Smart Links directly through the Rownd dashboard without writing any code. Our user-friendly interface allows you to:
* Create reusable Smart Links for marketing campaigns, user onboarding, or app downloads
* Customize link behavior with redirects based on device type
* Add analytics tags to track link performance
* Control how your links appear when shared on social media
* Manage all your links from a central dashboard
The platform approach is perfect for marketing teams, content managers, and anyone who needs to create and manage links without developer involvement. Within minutes, you can create a Smart Link that delivers a tailored experience to your users.
For detailed instructions on creating Smart Links through the platform, see our [Platform Guide](/magic-links/platform).
### API-Based Creation
For developers and automated workflows, Rownd offers a powerful API for programmatically creating Smart Links. This approach enables:
* **Dynamic link generation** based on user actions or events
* **Seamless integration** with existing marketing automation platforms
* **Bulk creation** of personalized links for email campaigns
* **Custom authentication flows** tailored to your specific business needs
* **Web hooks and callbacks** for advanced tracking and user journey orchestration
During email or SMS sign-in, Rownd automatically generates smart links on your behalf and sends them to the user. However, you can also programmatically create smart links using the Rownd API. This allows you to customize the link's behavior, such as redirecting users to specific app screens or triggering custom actions.
To create a magic link, see our [API documentation](/api-reference/authentication/create-magic-link).
#### Example Request
Here’s a basic example of how to create a Magic Link using Rownd's API:
```bash theme={null}
POST https://api.rownd.io/hub/auth/magic
Content-Type: application/json
X-Rownd-App-Key: YOUR_APP_KEY
X-Rownd-App-Secret: YOUR_APP_SECRET
{
"data": {
"email": "user@example.com"
},
"redirect_url": "https://yourapp.com/welcome"
}
```
This request will create a Magic Link that authenticates the user when accessed and redirects them to the specified URL.
### Example Response
```json theme={null}
{
"link": "https://rownd.link/YOUR_UNIQUE_MAGIC_LINK"
}
```
You can then send this link to the user.
### Using magic links
If you're only using magic links on a web platform, then no additional setup is required. However, if you're using Rownd on a mobile platform like iOS or Android, you'll need to add some configuration to your app and the Rownd dashboard to get everything working properly.
#### iOS setup
Apple requires several changes to your app's configuration to handle magic links. They also require an Apple App Site Association (AASA) file to be properly configured; however, Rownd builds and hosts this file for you.
To complete the required setup, follow the [iOS configuration steps](/configuration/mobile/ios).
After setup, test your links on a physical device to confirm they redirect correctly into the app.
#### Android setup
Android apps require an intent filter in the `AndroidManifest.xml` file to handle magic links. Android also requires a Digital Asset Links JSON file to be properly configured; however, Rownd builds and hosts this file for you.
To complete the required setup, follow the [Android configuration steps](/configuration/mobile/android).
After setup, test your links on a physical device to confirm they redirect correctly into the app.
### App download links
After you've configured and tested your mobile apps to handle magic links, you can also direct your mobile users to a special magic link endpoint that will automatically launch your app if it's installed or otherwise direct the user to your app listing on the appropriate app store for their device.
To use this link, simply append `/download` to your Rownd subdomain (configured in Mobile settings). For example, if your subdomain is `myapp`, then the download link would be `https://myapp.rownd.link/download`.
If the user is not on iOS or Android when they activate this link, it'll simply redirect them to your Rownd app's default URL
***
## Additional Resources
For more details on configuring and customizing Magic Links in Rownd, refer to the following:
* [Rownd iOS Configuration Documentation](https://docs.rownd.io/configuration/mobile/ios)
* [Rownd Android Configuration Documentation](https://docs.rownd.io/configuration/mobile/android)
* [Create Magic Link API Reference](https://docs.rownd.io/api-reference/authentication/create-magic-link)
***
This setup should help you get started with implementing Magic Links in Rownd. For any additional questions, feel free to reach out to our support team or consult the API reference.
# Unauthenticated links
Source: https://docs.rownd.io/magic-links/unauthenticated
Unauthenticated magic links are a powerful tool for directing users to specific content or features within your app or website. These links can be shared publicly and do not require the user to sign in, making them ideal for marketing campaigns, promotions, or general content sharing.
When a user clicks on an unauthenticated magic link, they are directed to the specified destination within your app or site. This can be particularly useful for driving traffic to specific pages, promoting new features, or sharing content with a wider audience.
To create unauthenticated magic links, you can use the Rownd API, which allows you to customize the link's behavior and target destination. This flexibility ensures that you can tailor the user experience to meet your specific needs while maintaining a high level of security.
## Creating unauthenticated magic links
Here's an example of creating an unauthenticated magic link using the Rownd API. In this example, we're specifying a redirect URL. When someone accesses the link, they'll be directed to the specified URL without an authentication payload attached. If they've previously authenticated and still have a valid session, that session will continue.
**Request**
```bash theme={null}
POST https://api.rownd.io/hub/auth/magic
Content-Type: application/json
X-Rownd-App-Key: YOUR_APP_KEY
X-Rownd-App-Secret: YOUR_APP_SECRET
{
"purpose": "shorten",
"redirect_url": "https://yourapp.com/promo?code=discount"
}
```
**Response**
```json theme={null}
{
"link": "https://rownd.link/YOUR_UNIQUE_MAGIC_LINK"
}
```
# Migrating from Auth0
Source: https://docs.rownd.io/migration/auth0
Migrating from Auth0 to Rownd is fast and easy. In most cases, you'll probably be able to remove a lot of unnecessary code and configuration from your product in exchange for Rownd's turnkey solution. Let's get started!
## Overview
In this guide, we'll help you plan your migration from Auth0 to Rownd so that you can think through the process and avoid any pitfalls. We'll also provide some code snippets to help you get started.
Here's what you'll work through as part of this migration:
1. Creating a Rownd account and setting up your test and production apps.
2. Updating your code to leverage Rownd instead of Auth0.
3. Migrating your existing users to Rownd.
We've prepared a [sample repository](https://github.com/rownd/migration-auth0#auth0-migration-to-rownd) that demonstrates the migration process from a code perspective.
## Set up Rownd
5. [Create an Auth0 integration](/configuration/integrations/auth0) and attach it to your app. This will allow Rownd to migrate your existing users automatically.
## Update back-end code
You'll need to update your backend APIs to accept Rownd-signed JWTs instead of Auth0 JWTs. Use the Rownd SDK corresponding to the framework or language of your backend API server. Check out a full list of our [backend SDKs](https://docs.rownd.io/sdk-reference/backend/overview).
Our SDKs provide functions to validate Rownd tokens, fetch user data, and in some cases middleware that you can plug directly into your request handlers to authenticate usurs automatically. Here's an example of using the Node.js SDK's Express middleware:
```typescript theme={null}
import { createInstance } from '@rownd/node';
const rownd = createInstance({
app_key: 'YOUR_APP_KEY',
app_secret: 'YOUR_APP_SECRET',
});
const { authenticate } = rownd.express;
app.get('/api/*', authenticate({ fetchUserInfo: true }));
app.get('/api/profile', (req, res) => {
res.send({
profile: req.user
});
});
```
Notice the use of the `authenticate` middleware function from `rownd.express` which validates a JWT in the `Authorization` header and fetches profile data from Rownd, making it available on the request object for other request handlers. You can also build a middlware yourself or use one-off instances of `rownd.validateToken(token);` and `rownd.fetchUserInfo(token);`.
## Update front-end code
Next, you'll need to replace Auth0 with Rownd in your frontend. The exact steps will vary depending on the frontend framework you're using and the authentication features of Auth0 that you are utilizing. We'll use React as an example to demonstrate the steps below.
1. Install the `@rownd/react` dependency with your preferred package manager
2. Add the `RowndProvider` context provider.
In your app's entrypoint file, add the `RowndProvider` context provider. You should already have an `Auth0Provider` somewhere in your app, which can help you find where you need to add this.
To keep existing users signed in during the migration, leave the existing `Auth0Provider` in place for now. Find out more about [keeping users signed in](#keep-existing-users-signed-in) during the migration.
```tsx RowndProvider theme={null}
import { RowndProvider } from '@rownd/react';
const root = createRoot(document.getElementById('root'));
root.render(
,
);
```
3. Replace Auth0 hook with Rownd
Auth0 provides a React hook named `useAuth0()` that you'll need to replace with Rownd. Rownd exposes similar properties and functions through the `useRownd()` hook. It should be pretty straightforward to swap out the Auth0 hook to use Rownd's, and to adapt your code to use the Rownd properties.
```typescript useRownd() hook theme={null}
// const { isAuthenticated, user } = useAuth0();
const { is_authenticated, user } = useRownd();
if (is_authenticated) {
return user.data.email;
}
```
**Notable Differences**
***Enforcing authentication for protected components***
If you have components protected with Auth0's `withAuthenticationRequired` component, you'll need to add the some equivalent Rownd code to enforce authentication. Use the `useRownd()` hook to enforce authentication upon rendering of certain components
```typescript Example theme={null}
const { is_initializing, is_authenticated, requestSignIn } = useRownd();
if (!is_initializing && !is_authenticated) {
requestSignIn({ prevent_closing: true });
}
```
***Audiences and APIs***
Rownd backend SDKs automatically validate the audience claim in Rownd-issued JWTs. Unlike Auth0, you do not need to explicitly set the audience and API configuration parameters in the SDK itself. You can remove any code present in your React app that configures or depends on audiences. If you want to set additional audience values, you can do so in the Rownd Platform under Application Settings.
***OAuth redirects***
The Rownd React SDK and Javascript snippet itself handle all redirects associated with authentication flows. If you have frontend code that handles callbacks or redirects from Auth0, you can safely remove these. They are no longer needed with Rownd.
## Keep existing users signed-in
Migrating your authentication to Rownd will help convert more users as they move through your funnel; however, what about the users you already have? They'll quickly become frustrated if they get signed out as a result of the migration.
To keep existing users signed in, you can pass their old Auth0 access token to Rownd for validation. Rownd will then issue a new token to the user so they'll be able to continue using your product without interruption. Once the new token is issued, the auth0 token can be permanently discarded.
Here's a full example using the Rownd React SDK. We'll break down the details below:
```typescript Example theme={null}
const { is_initializing, is_authenticated, getAccessToken } = useRownd();
const auth0 = useAuth0();
useEffect(() => {
if (is_authenticated) {
return;
}
if (!is_initializing && !auth0.isLoading && auth0.isAuthenticated) {
auth0.getAccessTokenSilently().then((auth0Token) => {
getAccessToken({ token: auth0Token })
});
}
}, [getAccessToken, is_authenticated, is_initializing, auth0])
```
1. In your front-end code, at the top-level component, check if the user is already signed in to Rownd. If they are, you're done!
```typescript theme={null}
if (is_authenticated) {
return;
}
```
2. If they aren't, check if they're currently authenticated via Auth0. If they are, retrieve their ID token.
```typescript theme={null}
if (!is_initializing && !auth0.isLoading && auth0.isAuthenticated) {
auth0.getAccessTokenSilently().then((auth0Token) => {
getAccessToken({ token: auth0Token })
});
}
```
3. Pass the token to Rownd for validation. If the token is valid, Rownd will issue a new token to the user.
```typescript theme={null}
getAccessToken({ token: auth0Token })
```
4. `is_authenticated` should now be `true` and the user can continue using your product normally.
## Sync user profiles (optional)
Rownd supports multiple ways to sync your user data from Auth0. If you created and attached the [Auth0 integration](/configuration/integrations/auth0) to your app, Rownd will begin migrating users "just in time," meaning that as users sign in, their data will automatically be imported into Rownd (matched on email address, phone number, etc).
However, pre-loading user data into Rownd will speed up the initial authentication handshake. You can use the Auth0 connector's "sync" option to do a bulk import of all users from your Auth0 app to Rownd. Any users that sign-in after the sync begins will be auto-migrated using the "just in time" method.
# Migrating from AWS Cognito
Source: https://docs.rownd.io/migration/cognito
## Overview
Here's what you'll work through as part of this migration:
1. Creating a Rownd account and setting up your test and production apps.
2. Updating your code to leverage Rownd instead of Cognito for authentication.
3. Migrating your existing users to Rownd.
We've prepared a [sample repository](https://github.com/rownd/migration-cognito#cognito-migration-to-rownd) that demonstrates the migration process from a code perspective.
## Set up Rownd
## Update back-end code
You'll need to update your backend APIs to accept Rownd-signed JWTs instead of AWS Cognito JWTs.
1. Install the Rownd SDK for your [back-end language or framework](/sdk-reference/backend).
2. Locate code that uses the AWS Cognito to manage users, validate tokens, and so on. Remove this code.
Our SDKs provide functions to validate Rownd tokens, fetch user data, and in some cases middleware that you can plug directly into your request handlers to authenticate users automatically.
Here's an example using Express middleware in Node.js:
Notice the use of the `authenticate` middleware function from `rownd.express` which validates a JWT in the `Authorization` header and fetches profile data from Rownd, making it available on the request object for other request handlers. You can also build a middleware yourself or use one-off instances of `rownd.validateToken(token)` and `rownd.fetchUserInfo(token)`.
```typescript theme={null}
import { createInstance } from '@rownd/node';
const rownd = createInstance({
app_key: 'YOUR_APP_KEY',
app_secret: 'YOUR_APP_SECRET',
});
const { authenticate } = rownd.express;
app.get('/api/*', authenticate({ fetchUserInfo: true }));
app.get('/api/profile', (req, res) => {
res.send({
profile: req.user
});
});
```
## Update front-end code
1. Install the `@rownd/react` dependency with your preferred package manager
```
npm install @rownd/react
```
2. Add the `` to the app's main entry.
```typescript React .tsx theme={null}
import React from 'react',
import ReactDOM from 'react-dom';
import { RowndProvider } from '@rownd/react';
import App from './App';
ReactDOM.render(
,
document.getElementById('root')
```
3. Replace all sign up and sign in buttons to trigger the `requestSignIn` flow for new or existing users.
```typescript theme={null}
const { requestSignIn } = useRownd();
```
4. Replace ConfirmSignUp with is\_authenticated API request
```typescript theme={null}
const { is_authenticated } = useRownd();
return (
<>
{is_authenticated && }
{!is_authenticated && }
>
);
```
5. Replace InitiateAuth with getAccessToken API request
```typescript theme={null}
const { getAccessToken } = useRownd();
let accessToken = await getAccessToken({
waitForToken: false,
});
```
6. Replace sign out buttons to send a signOut API request
```typescript theme={null}
const { signOut } = useRownd();
```
## Sync user profiles (optional)
Export user data, then import it
1. To do a bulk import of all users from your Cognito to Rownd see our [GitHub repo](https://github.com/rownd/csv-exporter) to export user data and transform your user data to the correct schema
2. Then use the following script to import your users into Rownd.
```
const axios = require('axios');
let data = JSON.stringify({
"users": [
{
"user_id": "__default__",
"data": {
"email": "romeo@gmail.com",
"sub": "41dbf550-1031-70e1-cc01-ce0106007d33"
}
},
{
"user_id": "__default__",
"data": {
"email": "johndoe@mailinator.com",
"sub": "518b35f0-9081-707d-5814-54cb79d27cc6"
}
},
{
"user_id": "__default__",
"data": {
"email": "janedoe@gmail.com",
"sub": "910b8560-c071-70a3-09e3-ef0bd61a8168"
}
}
]
});
let config = {
method: 'put',
maxBodyLength: Infinity,
url: 'https://api.rownd.io/applications//users/data',
headers: {
'x-rownd-app-key': '',
'x-rownd-app-secret': '',
'Content-Type': 'application/json',
},
data : data
};
axios.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});
```
# Migrating from Firebase Authentication
Source: https://docs.rownd.io/migration/firebase
Migrating from Firebase Authentication to Rownd is fast and easy. In most cases, you'll probably be able to remove a lot of unnecessary code and configuration from your product in exchange for Rownd's turnkey solution. Let's get started!
## Overview
In this guide, we'll help you plan your migration from Firebase to Rownd so that you can think through the process and avoid any pitfalls. We'll also provide some code snippets to help you get started.
Here's what you'll work through as part of this migration:
1. Creating a Rownd account and setting up your test and production apps.
2. Updating your code to leverage Rownd instead of Firebase for authentication.
3. Migrating your existing users to Rownd.
We've prepared a [sample repository](https://github.com/rownd/migration-firebase#firebase-migration-to-rownd) that demonstrates the migration process from a code perspective.
## Set up Rownd
5. [Create a Firebase Authentication integration](/configuration/integrations/firebase/authentication) and attach it to your app. This will allow Rownd to migrate your existing users automatically.
## Update back-end code
Some Firebase apps don't have a back-end component. If that's the case for you, you can skip this section!
In most cases, you should be able to remove all Firebase Authentication-related code from any backend servers or functions you're using. Take the following steps to migrate your back-end from Firebase Authentication to Rownd.
1. If you're only using Firebase Authentication, uninstall Firebase SDKs from your back-end project.
2. Install the Rownd SDK for your [back-end language or framework](/sdk-reference/backend).
3. Locate code that uses the Firebase SDK to manage users, validate tokens, and so on. Remove this code.
4. Replace the previous Firebase code with Rownd code. See our [GitHub repo](https://github.com/rownd/migration-firebase) for an example of this code migration.
## Update front-end code
Firebase provides a limited amount of pre-built UI, so it's likely you've created some custom UI to handle sign-in and sign-up. Rownd provides a fully customizable UI that you can use to replace your existing UI. Take the following steps to migrate your front-end from Firebase Authentication to Rownd.
If you plan to keep existing users signed-in (and you should!), keep your Firebase SDKs installed until you've migrated all of your active users to Rownd. This usually takes a month or two depending on your users' behavior patterns.
1. Remove existing authentication code, authentication screens, and so on. (If you're migrating a mobile app, you may want to keep the splash screen, although Rownd can help you let users into your app before they fully authenticate).
2. Install a [front-end web SDK](/sdk-reference/web) or [mobile SDK](/sdk-reference/mobile) for your platform or framework.
3. Add the required bits of Rownd code to authenticate users and protect your front-end.
Here's an example where we'll update the front-end and replace Firebase authentication with Rownd. React code examples are provided for demonstration purposes.
1. Remove all code related to Firebase. If you'd like to keep existing users signed in during migration, a `getAuth(app)` instance from Firebase will still be required.
2. Install Rownd.
```
npm install @rownd/react
```
3. Add the RowndProvider to the app's main entry.
```typescript React .tsx theme={null}
import React from 'react',
import ReactDOM from 'react-dom';
import { RowndProvider } from '@rownd/react';
import App from './App';
ReactDOM.render(
,
document.getElementById('root')
```
4. Add a sign-in trigger to all protected pages:
```typescript React .tsx theme={null}
import { useRownd } from '@rownd/react';
export default function MyProtectedComponent(props) {
const { is_authenticated, requestSignIn, is_initializing } = useRownd();
useEffect(() => {
if (!is_authenticated && !is_initializing) {
requestSignIn()
}
}, [is_authenticated, is_initializing, requestSignIn]);
}
```
## Keep existing users signed-in
Migrating your authentication to Rownd will help convert more users as they move through your funnel; however, what about the users you already have? They'll quickly become frustrated if they get signed out as a result of the migration.
To keep existing users signed in, you can pass their old access token to Rownd for validation. Rownd will then issue a new token to the user, so they'll be able to continue using your product without interruption. Once the new token is issued, the old provider's token can be permanently discarded.
1. In your front-end code, check if the user is already signed in to Rownd (e.g., `rownd.isAuthenticated`). If they are, you're done!
2. If they aren't, check if they're currently authenticated via Firebase. If they are, retrieve their ID token.
```typescript theme={null}
import { getAuth } from "firebase/auth";
const firebaseConfig = { ... };
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
if (auth.currentUser) {
const token = await auth.currentUser.getIdToken();
}
```
3. Pass the token to Rownd for validation. If the token is valid, Rownd will issue a new token to the user.
```typescript theme={null}
const token = await rownd.getAccessToken(token);
```
4. `rownd.isAuthenticated` should now be `true` and the user can continue using your product normally.
## Sync user profiles (optional)
Rownd supports multiple ways to sync your user data from Firebase. Once the Firebase integration is created and attached to your app, Rownd will begin migrating users "just in time," meaning that as users sign in, their data will automatically be imported into Rownd (matched on email address, phone number, etc).
However, pre-loading user data into Rownd will speed up the initial authentication handshake. You can use the Firebase connector's "sync" option to do a bulk import of all users from your Firebase app to Rownd. Any users that sign-in after the sync begins will be auto-migrated using the "just in time" method.
# Overview
Source: https://docs.rownd.io/migration/overview
Flee static sign-in and move to Rownd with ease
Whether you use Auth0, Stytch, Cognito, Firebase, or you built a custom solution, moving to something new can seem like an overwhelming task. However, with Rownd, it's not hard or overwhelming. We've made it super easy for you to migrate.
A few things to consider when leaving your current auth provider:
1. The easiest part is moving the data. User profiles, emails, phone numbers, even Google IDs can be imported into Rownd. In many cases, this can even happen automatically.
2. Consider keeping users signed-in through the migration--your users will love you for it. This means you'll temporarily run two auth providers in parallel.
Let's dig in.
## Set up Rownd
The first step is to confgiure Rownd in your dev enviornment. We have a plethora of SDKs and code snippets to make this straight-forward.
### Considerations when setting up Rownd
1. **No sign-in page:** Rownd is different. You won't need a sign-in page. Simply trigger the Rownd sign-in flow from existing buttons or trigger sign-in dynamically. It's your choice.
2. **No difficult coding:** Rownd provides all of the authentication UI out of the box, so you won't need to build anything yourself. Applying branding, authenticaton options, and more can be configured dynamically through the Rownd platform.
3. **Move auth where you need it:** Although some customers simply replace their existing sign-in flows with Rownd, we recommend moving authentication deeper into your offering. Letting your customers experience some of your product prior to requesting registration is a great way to boost your conversion rate.
## Keeping users signed-in
Rownd provides a [token validator](/configuration/integrations/token-validator) integration that can take an existing authentication token and validate it against another provider's API or JWK endpoint. This allows users that are already signed-in to stay signed-in while Rownd issues them a new token.
### Considerations for token validaiton
1. The API or JWK endpoint needs to be public so Rownd can validate the token.
2. Each auth provider has their own methods for validating tokens. Reach out to [support@rownd.io](mailto:support@rownd.io) and we'll help you configure the provider to validate tokens to keep your users signed-in.
## Setting up Google and/or Apple sign-in
If you already had [Google](/configuration/authentication-methods/google) or [Apple](/configuration/authentication-methods/apple) sign-in options, you can set them up quickly in Rownd as well.
### Considerations for setting up Google and/or Apple sign-in
1. Use the same Google Client ID that you used to set up the authentication prior to migration. This ensures the Google ID remains the same. If that's not possible for some reason, Rownd can still automatically users based on their Google account's email address.
2. Use the same Apple App ID for both.
## Migrating data
Migrating existing user profiles is the easiest part. If you're migrating from another auth provider, Rownd can automatically migrate your users for you. See our provider-specific migration guides for more information.
If you're migrating from an auth provider that Rownd doesn't support natively, or if you're coming from your own auth solution, [reach out to us](mailto:migration@rownd.io?subject=Migrating%20to%20Rownd%20from%20another%20provider) a few days before deploying to production. We'll provide hands-on assistance to ensure your migration is smooth.
### Considerations for migrating data
1. Consider what data you want to transfer to Rownd. Most sign-in methods should be migrated. Rownd can also manage other profile information (names, addresses, etc).
2. You may choose to migrate data from two or more sources. For example, you may move profile data from Auth0 and personal information (PII) from your own database. Let us know!
## Start a migration
Choose your migration path below to get started!
>} href="/migration/auth0">
Reduce expenses and improve your user experience
Say goodbye to AWS's frustrating auth tools
>} href="/migration/firebase">
Use Rownd with your existing Firebase project
Another auth provider or your own custom solution
# Rownd Subscriptions Integration Guide
Source: https://docs.rownd.io/payments/app-setup
This guide provides a complete overview of integrating Rownd Subscriptions into your React application.
## Table of Contents
* [Overview](#overview)
* [Prerequisites](#prerequisites)
* [API Methods](#api-methods)
* [Response Structures](#response-structures)
* [Implementation Examples](#implementation-examples)
* [Best Practices](#best-practices)
* [Quick-Start Implementation Prompt](#quick-start-implementation-prompt)
* [Understanding the API Methods and IDs](#understanding-the-api-methods-and-ids)
* [Finding and Using Subscription IDs](#finding-and-using-subscription-ids)
* [API Methods in Detail](#api-methods-in-detail)
* [Common Patterns and Gotchas](#common-patterns-and-gotchas)
## Overview
Rownd Subscriptions provides a simple API to manage subscription plans and user subscriptions in your application. The API is accessible through the global `window.rownd` object.
## Prerequisites
1. Rownd SDK must be installed and configured in your application
2. User must be authenticated to access subscription features
3. Subscription plans must be configured in your Rownd dashboard
## API Methods
### 1. Get Available Subscription Plans
```javascript theme={null}
await window.rownd.subscriptions.available()
```
**Description:** Fetches all available subscription plans for the current application.
**Returns:** Promise that resolves to an object containing available subscription plans.
### 2. Subscribe to a Plan
```javascript theme={null}
await window.rownd.subscriptions.subscribe(subscriptionId, planId)
```
**Parameters:**
* `subscriptionId` (string): The subscription ID from the available plans response
* `planId` (string): The specific plan/price ID to subscribe to (format: `prod_XXX__price_YYY`)
**Returns:** Promise that resolves when subscription is successful (status 200).
### 3. List User's Subscriptions
```javascript theme={null}
await window.rownd.subscriptions.list()
```
**Description:** Fetches all active subscriptions for the authenticated user.
**Returns:** Promise that resolves to an object containing the user's subscriptions.
## Response Structures
### Available Plans Response
```javascript theme={null}
{
results: [
{
created_at: "2025-06-03T01:01:15.708Z",
id: "sub_r7i3j3hf7nliv0somxl99d08", // This is the subscriptionId
presentation: {
options: [
{
active: true,
billing_scheme: "per_unit",
created: 1748912473,
currency: "usd",
description: "Starter plan",
hub_visible: true,
id: "prod_SQaOuPZleHnMXY__price_1RVjE5FKMLRRRtblfOWelt8y", // This is the planId
livemode: true,
name: "Starter",
nickname: "Free trial",
object: "price",
product: {
id: 'prod_SQaOuPZleHnMXY',
object: 'product',
active: true,
// ... additional product details
},
recurring: {
interval: 'month',
interval_count: 1,
trial_period_days: null,
usage_type: 'licensed'
},
unit_amount: 0, // Price in cents
unit_amount_decimal: "0"
},
{
// ... additional plan options
}
]
},
provider: "stripe",
provider_connection_id: "cmbftbsvv01cffg3rg3qwhsdl",
updated_at: "2025-06-03T01:26:37.563Z"
}
],
total_results: 1
}
```
### User Subscriptions Response
```javascript theme={null}
{
results: [
{
app_subscription_id: "sub_r7i3j3hf7nliv0somxl99d08",
billing_cycle_anchor: 1749155826,
cancel_at_period_end: false,
created: 1749155826,
created_at: "2025-06-05T20:37:06.000Z",
currency: "usd",
customer: "cus_SRdicauykfzG8Z",
id: "stripe|sub_1RWkX8FKMLRRRtbl01wU54sW",
livemode: true,
plan: {
id: 'price_1RVjE5FKMLRRRtblfOWelt8y',
object: 'plan',
active: true,
amount: 0,
amount_decimal: '0',
// ... additional plan details
},
status: "active", // Can be: active, trialing, canceled, etc.
updated_at: "2025-06-05T20:37:13.966Z"
}
],
total_results: 1
}
```
## Implementation Examples
### Example 1: Fetching and Displaying Available Plans
```javascript theme={null}
import { useState, useEffect } from 'react'
function SubscriptionPlans() {
const [plans, setPlans] = useState([])
const [loading, setLoading] = useState(false)
const fetchAvailablePlans = async () => {
setLoading(true)
try {
const response = await window.rownd.subscriptions.available()
if (response.results && response.results.length > 0) {
// Extract plans from the first result's presentation options
setPlans(response.results[0].presentation.options || [])
}
} catch (error) {
console.error('Error fetching plans:', error)
} finally {
setLoading(false)
}
}
useEffect(() => {
fetchAvailablePlans()
}, [])
const formatPrice = (amount, currency) => {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: currency.toUpperCase()
}).format(amount / 100) // Convert cents to dollars
}
return (
)
}
```
### Example 2: Subscribing to a Plan
```javascript theme={null}
const handleSubscribe = async (subscriptionId, planId) => {
try {
const response = await window.rownd.subscriptions.subscribe(subscriptionId, planId)
if (response.status === 200 || response.ok) {
console.log('Successfully subscribed!')
// Handle success (e.g., show success message, refresh subscriptions)
}
} catch (error) {
console.error('Subscription failed:', error)
// Handle error (e.g., show error message)
}
}
// Usage example:
// subscriptionId comes from available() response: response.results[0].id
// planId comes from the specific plan: plan.id
handleSubscribe("sub_r7i3j3hf7nliv0somxl99d08", "prod_SQaOuPZleHnMXY__price_1RVjE5FKMLRRRtblfOWelt8y")
```
### Example 3: Displaying User's Subscriptions
```javascript theme={null}
import { useState, useEffect } from 'react'
function MySubscriptions() {
const [subscriptions, setSubscriptions] = useState([])
const [loading, setLoading] = useState(false)
const fetchMySubscriptions = async () => {
setLoading(true)
try {
const response = await window.rownd.subscriptions.list()
if (response.results) {
setSubscriptions(response.results)
}
} catch (error) {
console.error('Error fetching subscriptions:', error)
} finally {
setLoading(false)
}
}
useEffect(() => {
fetchMySubscriptions()
}, [])
const formatDate = (dateString) => {
return new Date(dateString).toLocaleDateString('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric'
})
}
return (
{loading ? (
Loading subscriptions...
) : subscriptions.length === 0 ? (
No active subscriptions
) : (
{subscriptions.map((sub) => (
{sub.plan?.name || 'Subscription'}
Status: {sub.status}
Started: {formatDate(sub.created_at)}
Next billing: {formatDate(new Date(sub.billing_cycle_anchor * 1000))}
))}
)}
)
}
```
## Best Practices
### 1. Error Handling
Always wrap API calls in try-catch blocks to handle potential errors gracefully:
```javascript theme={null}
try {
const response = await window.rownd.subscriptions.available()
// Handle success
} catch (error) {
console.error('Error:', error)
// Show user-friendly error message
}
```
### 2. Loading States
Provide visual feedback during API calls:
```javascript theme={null}
const [loading, setLoading] = useState(false)
const fetchData = async () => {
setLoading(true)
try {
// API call
} finally {
setLoading(false)
}
}
```
### 3. Authentication Check
Ensure user is authenticated before showing subscription features:
```javascript theme={null}
import { useRownd } from '@rownd/react'
function SubscriptionFeature() {
const { is_authenticated } = useRownd()
if (!is_authenticated) {
return
Please sign in to view subscriptions
}
// Show subscription content
}
```
### 4. Price Formatting
Always format prices for display (Stripe stores amounts in cents):
```javascript theme={null}
const formatPrice = (amount, currency) => {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: currency.toUpperCase()
}).format(amount / 100)
}
```
### 5. Date Formatting
Convert Unix timestamps to readable dates:
```javascript theme={null}
const formatDate = (timestamp) => {
return new Date(timestamp * 1000).toLocaleDateString('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric'
})
}
```
## Common Use Cases
### 1. Subscription Selection Modal
Create a modal that displays available plans and allows users to subscribe.
### 2. Subscription Management Page
Show users their current subscriptions with details like billing dates and status.
### 3. Upgrade/Downgrade Flow
Allow users to change their subscription plan by showing available options.
### 4. Trial Period Handling
Display trial information and countdown for plans with trial periods.
### 5. Celebration Modal for Successful Subscriptions
Create a delightful upgrade experience to celebrate when users successfully subscribe to a plan.
#### Implementation Example:
```javascript theme={null}
import { useState } from 'react'
function SubscriptionWithCelebration() {
const [showSuccess, setShowSuccess] = useState(false)
const [fadeOut, setFadeOut] = useState(false)
const [planName, setPlanName] = useState('')
const handleSubscribe = async (subscriptionId, planId, planName) => {
try {
const response = await window.rownd.subscriptions.subscribe(subscriptionId, planId)
if (response) {
// Show celebration
setPlanName(planName)
setShowSuccess(true)
setFadeOut(false)
// Start fade out after 4 seconds
setTimeout(() => setFadeOut(true), 4000)
// Remove celebration after fade completes
setTimeout(() => {
setShowSuccess(false)
setFadeOut(false)
}, 4800)
}
} catch (error) {
console.error('Subscription failed:', error)
}
}
if (showSuccess) {
return (
Congrats on upgrading to {planName}!
{/* Your celebration animation here */}
)
}
// ... rest of your component
}
```
#### CSS for Celebration Animation:
```css theme={null}
.celebration-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(102, 51, 153, 0.8); /* Purple overlay */
display: flex;
align-items: center;
justify-content: center;
z-index: 2000;
animation: fadeIn 0.8s cubic-bezier(0.4, 0, 0.2, 1);
}
.celebration-overlay.fade-out {
animation: fadeOut 0.8s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}
.celebration-content h1 {
color: white;
font-size: 48px;
font-weight: 700;
animation: slideDownFadeIn 1s cubic-bezier(0.34, 1.56, 0.64, 1);
}
/* Circular wipe animation example */
.celebration-animation {
width: 200px;
height: 200px;
border-radius: 50%;
position: relative;
overflow: hidden;
animation: scaleInRotate 1s cubic-bezier(0.34, 1.56, 0.64, 1) 0.3s both;
}
.celebration-animation::before {
content: '';
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: conic-gradient(
from 0deg,
transparent 0deg,
rgba(255, 255, 255, 0.4) 30deg,
transparent 90deg
);
animation: circularWipe 2.5s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes fadeOut {
from { opacity: 1; }
to { opacity: 0; }
}
@keyframes slideDownFadeIn {
from {
opacity: 0;
transform: translateY(-50px) scale(0.9);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}
@keyframes scaleInRotate {
from {
opacity: 0;
transform: scale(0.3) rotate(-180deg);
}
to {
opacity: 1;
transform: scale(1) rotate(0deg);
}
}
@keyframes circularWipe {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
```
#### Best Practices for Celebration Modals:
1. **Timing**: Show celebration for 4-5 seconds total
2. **Smooth Transitions**: Use cubic-bezier easing for natural motion
3. **Fade Out**: Always fade out before removing to avoid jarring transitions
4. **Accessibility**: Ensure celebration doesn't interfere with screen readers
5. **Performance**: Use CSS animations instead of JavaScript for better performance
6. **Customization**: Match celebration colors to your brand
## Troubleshooting
### Issue: "Cannot read properties of undefined"
**Solution:** Ensure `window.rownd` is available before making API calls. The Rownd SDK must be fully initialized.
### Issue: Subscription fails silently
**Solution:** Check the response object and console for error details. Ensure the user has valid payment methods if required.
### Issue: Empty subscription list
**Solution:** Verify that subscription plans are properly configured in your Rownd dashboard and that the user is authenticated.
## Additional Notes
* All subscription amounts are in cents (multiply by 100 when saving, divide by 100 when displaying)
* The `subscriptionId` is different from the `planId` - use the correct one for each API call
* Subscription status can be: active, trialing, canceled, past\_due, etc.
* Always handle the case where a user has no active subscriptions
## Quick-Start Implementation Prompt
> **Copy and paste this prompt into Cursor to implement Rownd Subscriptions in your app:**
```prompt theme={null}
I need to implement Rownd Subscriptions in my React application. Please help me create the following components and functionality:
1. Create a SubscriptionPlans component that:
- Uses the Rownd SDK to fetch available plans
- Displays plans in a grid with pricing, descriptions, and trial periods
- Handles loading states and errors
- Uses proper price formatting (cents to dollars)
2. Create a SubscribeButton component that:
- Takes subscriptionId and planId as props
- Handles the subscription process using window.rownd.subscriptions.subscribe()
- Shows loading state during subscription
- Displays success/error messages
- Includes a celebration animation on successful subscription
3. Create a MySubscriptions component that:
- Lists the user's active subscriptions
- Shows subscription status, start date, and next billing date
- Handles the case of no active subscriptions
- Includes proper date formatting
4. Add proper error handling and loading states throughout
- Use try/catch blocks for all API calls
- Show loading spinners during API calls
- Display user-friendly error messages
5. Implement authentication checks:
- Use useRownd() hook to check authentication status
- Show appropriate messages for unauthenticated users
Please use the following API methods:
- window.rownd.subscriptions.available()
- window.rownd.subscriptions.subscribe(subscriptionId, planId)
- window.rownd.subscriptions.list()
Include proper TypeScript types, error handling, and loading states. Follow the best practices from the Rownd documentation for subscription management.
```
> **Note:** This prompt is designed to work with Cursor's AI capabilities to generate a complete implementation based on the Rownd Subscriptions documentation. The generated code will include proper error handling, loading states, and TypeScript types.
## Understanding the API Methods and IDs
### Finding and Using Subscription IDs
When working with Rownd Subscriptions, you'll need to understand two important IDs:
1. **subscriptionId**: This is the ID of the subscription configuration in your Rownd dashboard. You can find this by:
* Calling `window.rownd.subscriptions.available()`
* Looking at the `id` field in the response (e.g., `"sub_r7i3j3hf7nliv0somxl99d08"`)
* This ID represents the subscription configuration, not a user's subscription
2. **planId**: This is the specific plan/price ID within a subscription. You can find this by:
* Looking at the `presentation.options[].id` field in the available plans response
* Format is typically `prod_XXX__price_YYY`
* This ID represents the specific plan a user can subscribe to
### API Methods in Detail
#### 1. Fetching Available Plans
```javascript theme={null}
const response = await window.rownd.subscriptions.available()
```
* Returns all subscription plans configured in your Rownd dashboard
* Response structure:
```javascript theme={null}
{
results: [{
id: "sub_r7i3j3hf7nliv0somxl99d08", // This is your subscriptionId
presentation: {
options: [{
id: "prod_XXX__price_YYY", // This is your planId
name: "Starter",
description: "Starter plan",
unit_amount: 0, // Price in cents
recurring: {
interval: 'month',
trial_period_days: null
}
}]
}
}]
}
```
#### 2. Subscribing to a Plan
```javascript theme={null}
await window.rownd.subscriptions.subscribe(subscriptionId, planId)
```
* Parameters:
* `subscriptionId`: From the available() response (e.g., `"sub_r7i3j3hf7nliv0somxl99d08"`)
* `planId`: From the plan options (e.g., `"prod_XXX__price_YYY"`)
* Returns: Promise that resolves on successful subscription
* Status codes:
* 200: Success
* 400: Invalid parameters
* 401: Unauthenticated
* 402: Payment required
* 403: Forbidden
#### 3. Listing User's Subscriptions
```javascript theme={null}
const response = await window.rownd.subscriptions.list()
```
* Returns all active subscriptions for the authenticated user
* Response structure:
```javascript theme={null}
{
results: [{
id: "stripe|sub_1RWkX8FKMLRRRtbl01wU54sW",
status: "active", // active, trialing, canceled, etc.
created_at: "2025-06-05T20:37:06.000Z",
billing_cycle_anchor: 1749155826,
plan: {
id: 'price_1RVjE5FKMLRRRtblfOWelt8y',
amount: 0,
// ... additional plan details
}
}]
}
```
### Common Patterns and Gotchas
1. **Finding the Right IDs**:
```javascript theme={null}
// Example of extracting IDs from available plans
const availablePlans = await window.rownd.subscriptions.available()
const subscriptionId = availablePlans.results[0].id
const planId = availablePlans.results[0].presentation.options[0].id
```
2. **Handling Multiple Plans**:
```javascript theme={null}
// Example of mapping through multiple plans
const plans = availablePlans.results[0].presentation.options.map(plan => ({
id: plan.id,
name: plan.name,
price: plan.unit_amount / 100, // Convert cents to dollars
interval: plan.recurring.interval
}))
```
3. **Checking Subscription Status**:
```javascript theme={null}
const subscriptions = await window.rownd.subscriptions.list()
const hasActiveSubscription = subscriptions.results.some(
sub => sub.status === 'active' || sub.status === 'trialing'
)
```
4. **Error Handling**:
```javascript theme={null}
try {
const response = await window.rownd.subscriptions.subscribe(subscriptionId, planId)
// Handle success
} catch (error) {
if (error.status === 402) {
// Handle payment required
} else if (error.status === 401) {
// Handle authentication error
}
// Handle other errors
}
```
Remember:
* Always handle the case where a user has no active subscriptions
* Convert price amounts from cents to dollars for display
* Check authentication status before making API calls
* Handle loading states during API calls
* Provide clear error messages to users
# Rownd Payments Overview
Source: https://docs.rownd.io/payments/overview
Start accepting payments in your app within minutes, not months. Rownd Payments eliminates the complexity of payment processing, letting you focus on growing your business while we handle the technical and compliance details.
## What You Get
### Start Making Money in Seconds
* **Instant Setup**: Your payment account is created automatically - no lengthy applications or waiting periods
* **Zero Integration Hassle**: Skip months of payment provider documentation and complex API integrations
* **Ready-Made UI**: Beautiful payment components appear right in your app through the Rownd Hub
### Everything Managed for You
* **One Dashboard**: View all your revenue, payouts, and customer payments in one place
* **Automatic Payouts**: Your money arrives in your bank account automatically - no manual transfers needed
* **Real-time Insights**: See exactly how your business is performing at any moment
### Built for Your Success
* **Simple Integration**: Add payments to your app with just a few lines of code
* **Professional Checkout**: Your customers enjoy a seamless, branded payment experience
* **Flexible Products**: Create any type of product or subscription plan you need - we handle the complexity
## Payment Providers Available to You
Currently, you can process payments through:
* **Stripe**: Industry-leading payment processing with global reach
* **More Coming Soon**: We're adding new providers based on your needs
:::note
You pay just 1% on transactions. We cover all payment provider fees (including Stripe's processing fees) for transfers and payouts, so you keep more of what you earn.
:::
## How to Get Started
Getting paid is simple:
1. Click "Enable Payments" in your Rownd dashboard
2. Add your business and bank details
3. Drop our payment components into your app
4. Start accepting payments immediately!
## Perfect For
### Subscription Businesses
* Monthly or annual billing for your SaaS
* Membership sites and communities
* Premium content subscriptions
### Direct Sales
* Sell digital downloads
* Process one-time purchases
* Book appointments and services
### Advanced Models
* Set up trial periods
* Offer promotional pricing
* Create custom billing cycles
## Your Security is Handled
We take care of all the complex security requirements:
* **PCI Compliance**: We maintain it so you don't have to
* **Data Protection**: Your customers' payment information is always encrypted and secure
* **Fraud Prevention**: Built-in protection keeps your business safe
* **Full Compliance**: We handle all regulatory requirements for you
## Your Next Steps
* [Connect your Stripe account](/payments/stripe)
* [View detailed integration guide](/payments/app-setup)
# Stripe Integration
Source: https://docs.rownd.io/payments/stripe
When you enable Rownd Payments, we automatically create and manage a Stripe Express account for you. This means you can start accepting payments immediately without dealing with Stripe's complex setup process or technical requirements.
## Your Stripe Express Account
Stripe Express is your gateway to accepting payments professionally. Here's what you get:
* **Instant Activation**: Your account is ready to accept payments as soon as you enable it
* **Your Own Dashboard**: Access a clean, simple interface to manage your business
* **Daily Payouts**: Your earnings automatically transfer to your bank account every day
* **Full Control**: You own your customer relationships and set your own prices
## What's Included
### Automatic Setup - Done for You
* We create and configure your Stripe account instantly
* No forms to fill out or verification delays
* Start accepting payments right away
### Everything in One Place
* See all your transactions in your Rownd dashboard
* Track payouts to your bank account
* View customer payment history and details
### Professional Payment Experience
* Your customers see your brand, not ours
* Mobile-optimized checkout that works everywhere
* Secure payment processing they can trust
### Simple Product Creation
* Create products and subscription plans in seconds
* Set any price or billing schedule you want
* We handle all the technical complexity
## Getting Started
1. **Turn on Payments**
* Go to the Payments section in your dashboard
* Click "Enable Stripe Payments"
* Complete a quick verification (takes 2 minutes)
2. **Add Your Details**
* Enter your business information
* Connect your bank account for payouts
* Add your tax details (we'll help you)
3. **Create Your First Product**
* Click "New Product" and follow the wizard
* Set your price and billing type
* Add a description your customers will see
4. **Start Accepting Payments**
* Add our payment components to your app
* Customize how checkout looks
* Test everything before going live
## Managing Your Money
### Getting Paid
* Money arrives in your bank account daily
* See exactly when each payout will arrive
* Track every payment in real-time
### Your Customers
* View complete payment history for each customer
* Process refunds with one click
* Handle any disputes that arise
### Business Insights
* See your revenue growth over time
* Track which products perform best
* Understand your customer behavior
## Tips for Success
1. **Test Everything First**
* Use test mode to try different scenarios
* Make sure payments work smoothly
* Verify web hook connections are working
2. **Stay on Top of Things**
* Check your dashboard regularly
* Address failed payments quickly
* Respond to customer questions promptly
3. **Keep Everything Current**
* Update your business info when it changes
* Keep your bank details accurate
* Ensure tax information stays current
## Common Questions
### Payment Issues
* **Card Declined**: The customer needs to check their card details or try another card
* **Payout Delayed**: Verify your bank information is correct (payouts typically take 2-3 business days)
* **Integration Problems**: Make sure you're using the latest Rownd components
## Need Help?
If you run into any issues:
1. Check our [documentation](/docs) for answers
2. Reach out to our support team - we're here to help
3. Check [Stripe's status](https://status.stripe.com) if payments aren't working
## What's Next
* [Set up your products](/payments/configuration)
* [Create subscription plans](/payments/products)
* [Customize your checkout](/payments/integration)
* [View your earnings](/payments/payouts)
* [View detailed integration guide](/payments/app-setup)
# Convex
Source: https://docs.rownd.io/sdk-reference/backend/convex
Convex SDK reference
## Installation
Install the required dependencies:
```bash theme={null}
npm install convex @rownd/react
```
***
## Configuration
1. **Get your Rownd App Key:**
* Sign up or log in at [Rownd Dashboard](https://app.rownd.io)
* Create/select your application
* Copy your **App Key** (e.g., `key_xxxxxxxx`)
* Copy your **App ID** This is used to verify the audience.
2. **Set up Convex:**
* Follow the [Convex Getting Started guide](https://docs.convex.dev/quickstart/) to initialize your backend and get your deployment URL.
***
## RowndProvider Setup
Wrap your app with `RowndProvider` from `@rownd/react/convex` and pass both your Convex client and Rownd app key:
```tsx theme={null}
import { createRoot } from "react-dom/client";
import { ConvexReactClient } from "convex/react";
import { RowndProvider } from "@rownd/react/convex";
import App from "./App";
const convex = new ConvexReactClient(import.meta.env.VITE_CONVEX_URL as string);
createRoot(document.getElementById("root")!).render(
);
```
## Server-side Usage
### Add Rownd to your auth.config.js file.
Add these to your convex/auth.config.js file:
```ts theme={null}
//convex/auth.config.js
export default {
providers: [
{
domain: "https://api.rownd.io",
applicationID: "app:your-rownd-app-id"
},
],
```
> \[! NOTE]
> Ensure you have the `app:` in addition to your app-id.
> For example, applicationID: "app:app\_alksdjflakjvlkeja"
### Mapping Rownd IDs in Convex
**It is critical to keep a mapping of the Rownd user ID in your Convex `users` table.**\
This allows you to associate Rownd-authenticated users with your app's data.
**Schema example:**
```ts theme={null}
// convex/schema.ts
import { defineSchema, defineTable } from "convex/server";
import { v } from "convex/values";
export default defineSchema({
users: defineTable({
rowndId: v.string(),
email: v.optional(v.string()),
})
.index("by_rowndId", ["rowndId"]),
// ...other tables
});
```
**Storing and looking up users by Rownd ID:**
This example mutation ensures the existence of a user record in your database for the currently authenticated
user. `ctx.auth.getUserIdentity()` will return all of the claim data included in the user's JWT. You can use the
`subject` value to map your internal users to Rownd user's.
```ts theme={null}
// convex/users.ts
import { mutation } from "./_generated/server";
export const store = mutation({
args: {},
handler: async (ctx) => {
const identity = await ctx.auth.getUserIdentity();
if (!identity) {
throw new Error("Called storeUser without authentication present");
}
// Check if we've already stored this identity before.
const user = await ctx.db
.query("users")
.withIndex("by_rowndId", (q) =>
q.eq("rowndId", identity.subject),
)
.unique();
if (user !== null) {
return user._id;
}
// If it's a new identity, create a new `User`.
const dbUser = await ctx.db.insert("users", {
rowndId: identity.subject,
email: identity.email,
});
return dbUser;
},
});
```
### Accessing the Current User
To get the current authenticated user in any Convex function, always look up by the Rownd ID:
```ts theme={null}
// convex/auth.ts
import { query } from "./_generated/server";
export const loggedInUser = query({
handler: async (ctx) => {
const identity = await ctx.auth.getUserIdentity();
if (!identity) {
return null;
}
const user = await ctx.db
.query("users")
.withIndex("by_rowndId", (q) =>
q.eq("rowndId", identity.subject),
)
.unique();
return user;
},
});
```
### Protecting Convex Functions
Always check for authentication and use the Rownd ID mapping to associate data with users:
```ts theme={null}
import { mutation } from "./_generated/server";
import { v } from "convex/values";
export const createPost = mutation({
args: {
title: v.string(),
content: v.string(),
category: v.string(),
},
handler: async (ctx, args) => {
const identity = await ctx.auth.getUserIdentity();
if (!identity) throw new Error("Please log in");
const user = await ctx.db
.query("users")
.withIndex("by_rowndId", (q) =>
q.eq("rowndId", identity.subject),
)
.unique();
if (!user?._id) throw new Error("User not found");
return await ctx.db.insert("posts", {
authorId: user._id,
title: args.title,
content: args.content,
category: args.category,
likes: 0,
});
},
});
```
***
## Client-side Usage
### Using Rownd React SDK Features
After setting up the `RowndProvider`, you can use all other features of the [`@rownd/react`](https://docs.rownd.io/sdk-reference/web/react) SDK in your app as documented in the official Rownd docs.
The Rownd React SDK only handles client-side authentication state. For proper integration with Convex, you should use Convex's authentication hooks and utilities to ensure server-side state is properly synchronized.
Create a custom hook like `useStoreUserEffect` to handle the authentication flow as outlined in these [Convex docs](https://docs.convex.dev/auth/database-auth)
**Example:**
```tsx theme={null}
import { useRownd } from "@rownd/react";
import { useStoreUserEffect } from "./useStoreUserEffect.js";
function Profile() {
const { requestSignIn, signOut, user: rowndUser } = useRownd();
const { isAuthenticated } = useStoreUserEffect();
if (!isAuthenticated) {
return ;
}
return (
Welcome, {rowndUser?.first_name}!
);
}
```
For more details and advanced usage, see the [Rownd React SDK documentation](https://docs.rownd.io/sdk-reference/web/react).
***
## Best Practices & Tips
* **Always map Rownd IDs:**\
Store the Rownd user ID (`identity.subject`) in your `users` table and use it as the primary lookup for all user-specific data.
* **Use indexes for efficient lookups:**\
Index your `users` table by `rowndId` for fast queries.
* **Optionally include additional profile data in JWT claims**
You can use the Rownd Platform to setup profile data fields for inclusion in additional JWT claims. This makes them avaiable on the `ctx.auth.getUserIdentity()`
# Backend SDK Overview
Source: https://docs.rownd.io/sdk-reference/backend/overview
## Rownd Backend SDK Features
Rownd's Backend SDKs provide powerful tools for secure and efficient server-side authentication and user management.
### Robust Token Management
Ensure secure access to your backend resources with comprehensive token management:
* **Token Verification**: Easily verify user tokens to authenticate requests
* **Token Refresh**: Automatically handle token expiration and renewal
* **Custom Claims**: Add and manage custom claims for user tokens
### Understanding Rownd Tokens
Rownd uses JWT (JSON Web Tokens) for authentication. Here's an example token payload:
```json theme={null}
json
{
"jti": "e5aded8f-4950-4215-9a45-dc3e7x8575e90",
"aud": [
"app:app_v8q15ahdmpx3wqnbm6j19grlx",
"app_variant:cm4swjkos008x5bfc8x48d70xu"
],
"sub": "user_o7jyzlzbga2uhly698ba8a1s",
"iat": 1734467046,
"exp": 1734470646,
"iss": "https://api.rownd.io",
"https://auth.rownd.io/app_user_id": "user_o7jyzlzbga2uhly698ba8a1s",
"https://auth.rownd.io/is_verified_user": true,
"https://auth.rownd.io/auth_level": "verified"
}
```
Standard JWT claims:
* **jti**: Unique identifier for this token
* **aud**: Array of audiences this token is intended for (includes Rownd app ID and app variant ID if applicable);
* **sub**: Subject identifier (Rownd user ID)
* **iat**: Timestamp when the token was issued
* **exp**: Timestamp when the token expires
* **iss**: Token issuer (Rownd API)
Rownd-specific claims:
* **[https://auth.rownd.io/app\_user\_id](https://auth.rownd.io/app_user_id)**: User's unique identifier in Rownd
* **[https://auth.rownd.io/is\_verified\_user](https://auth.rownd.io/is_verified_user)**: Boolean indicating if the user is verified
* **[https://auth.rownd.io/auth\_level](https://auth.rownd.io/auth_level)**: User's authentication level (e.g., "verified")
### Seamless Integration
Integrate Rownd's backend capabilities with your existing infrastructure:
* **Framework Compatibility**: Support for popular server-side frameworks like Node.js, Django, and .NET
* **API Integration**: Effortlessly call Rownd's backend services
* **Server-Side Rendering Support**: Compatible with frameworks like Next.js and Remix for efficient SSR
### Advanced User Management
Manage user data and authentication flows with ease:
* **User Profiles**: Access and update user profiles programmatically
* **Role-Based Access Control**: Implement fine-grained access control for different user roles
* **Event Hooks**: Trigger custom logic on authentication events
### Developer-Friendly Tools
Streamline backend development with comprehensive tools and support:
* **Detailed Documentation**: In-depth guides and API references
* **Versioning and Compatibility**: Clear upgrade paths and backward compatibility
* **Technical Support**: Access to expert engineering support
## Steps for getting started:
1. [Set up your Rownd account](/welcome/getting-started) (only takes a minute).
2. Create an [app key](/configuration/app-credentials).
3. Install Rownd using an SDK.
4. [Configure customizations](/configuration/overview) and sign-in methods from the Rownd platform.
## Rownd Backend SDKs:
JavaScript and TypeScript
Python
Python
C#
}
href="/sdk-reference/backend/ruby-on-rails"
/>
}
href="/sdk-reference/backend/convex"
>
Convex
# Android
Source: https://docs.rownd.io/sdk-reference/mobile/android
Rownd bindings for Android
The Rownd SDK for Android provides authentication, account and user profile management, deep linking, and more for native Android applications.
Using the Rownd platform, you can easily bring the same authentication that's on your website to your mobile apps. Or if you only authenticate users on your mobile apps, you can streamline the authentication process using Rownd's passwordless sign-in links, enabling you to seamlessly authenticate users from an app link sent to their email or phone number.
Once a user is authenticated, you can retrieve and update their profile information on the fly using native APIs. Leverage Rownd's pre-built mobile app components to give users profile management tools.
## Installation
In Android Studio, open your app's module-level `build.gradle` file and add the following dependency:
```
implementation 'io.rownd:android:3.0.2'
```
After adding, run a Gradle sync and the Rownd SDK/API should be available within your IDE.
### ProGuard config
Rownd's Android SDK includes a `consumer-rules.pro` file, which should automatically augment your app's own proguard/r2 config.
If you're using ProGuard to shrink, obfuscate, and/or optimize your app ([and you should!](https://developer.android.com/studio/build/shrink-code)), and you're noticing minification or runtime errors after installing Rownd, you may need to add the following rules to your `proguard-rules.pro` file.
```proguard theme={null}
-if @kotlinx.serialization.Serializable class **
-keepclassmembers class <1> {
static <1>$Companion Companion;
}
# Keep `serializer()` on companion objects (both default and named) of serializable classes.
-if @kotlinx.serialization.Serializable class ** {
static **$* *;
}
-keepclassmembers class <2>$<3> {
kotlinx.serialization.KSerializer serializer(...);
}
# Keep `INSTANCE.serializer()` of serializable objects.
-if @kotlinx.serialization.Serializable class ** {
public static ** INSTANCE;
}
-keepclassmembers class <1> {
public static <1> INSTANCE;
kotlinx.serialization.KSerializer serializer(...);
}
# @Serializable and @Polymorphic are used at runtime for polymorphic serialization.
-keepattributes RuntimeVisibleAnnotations,AnnotationDefault,Annotation,InnerClasses
# Suppress warnings about missing AWT classes (which aren't used in Android)
-dontwarn java.awt.*
# libsodium uses jna
-keep class com.sun.jna.* { *; }
-keepclassmembers class * extends com.sun.jna.* { public *; }
# ViewModel names are used at runtime
-keep public class * extends androidx.lifecycle.ViewModel {*;}
```
## Usage
### Initializing the Rownd SDK
The Rownd SDK needs access to your application's and current activity's context in order to properly manage state, display UI components, and so on.
The most straightforward way of doing this is to subclass the Android `Application` class and pass the app's primary context.
To initialize Rownd, call the configure method like this:
```kotlin theme={null}
Rownd.configure(application, "REPLACE_WITH_YOUR_APP_KEY")
```
Here's an example of what that might look like in the initial `Application` class:
```kotlin theme={null}
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
Rownd.configure(this, "REPLACE_WITH_YOUR_APP_KEY")
}
}
```
After initialization, your app should typically call `Rownd.requestSignIn()` at some point, if the user is not already authenticated. This will display the Rownd interface for authenticating the user. Once they complete the sign-in process, an access token and the user's profile information will be available to your app.
### Handling authentication
Rownd leverages an observable architecture to expose data to your app using [StateFlow](https://developer.android.com/kotlin/flow/stateflow-and-sharedflow). This means that as the Rownd state changes, an app can dynamically update without complicated logic. For example, a view can display different information based on the user's authentication status.
You can use this StateFlow in both older-style XML layouts as well as Android Jetpack's newer Composable views.
### Using state in XML layout
```xml theme={null}
```
```kotlin theme={null}
// my_activity.kt
class MyActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding: ActivityMainBinding =
DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.lifecycleOwner = this
binding.rownd = Rownd
}
}
```
### Using state in a Composable
```kotlin theme={null}
// some_activity_or_component.kt
class MyActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val state = Rownd.state.collectAsState()
val signInButtonText = if (state.value.auth.isAuthenticated) "Sign out" else "Sign in"
Button(
onClick = {
if (state.value.auth.isAuthenticated) Rownd.signOut()
else Rownd.requestSignIn()
}
) {
Text(signInButtonText)
}
}
}
}
```
Once you subscribe to the Rownd state via `Rownd.state.collectAsState()`, you can use the various parts of the state tree as needed.
Access the state like this:
```kotlin theme={null}
val rowndState = Rownd.state.collectAsState()
val isAuthenticated = rowndState.value.auth.isAuthenticated
```
The following classes/properties are available:
#### .auth
```kotlin theme={null}
data class AuthState(
val accessToken: String?, // Current, valid access token for the user (valid for one hour)
val isVerifiedUser: Boolean, // Whether the current user has verified at least one identifier (e.g., email)
val isAuthenticated: Boolean // Whether the current user is signed in
)
```
#### .user
```kotlin theme={null}
data class User(
val id: String?, // The user's ID as known to Rownd
val data: Map = HashMap(),
val redacted: PersistentList // A list of any profile fields that a user has restricted your app from accessing
)
```
## Customizing the UI
While most customizations are handled via the [Rownd dashboard](https://app.rownd.io), there are a few things that have to be customized directly in the SDK.
The `RowndCustomizations` class exists to facilitate these customizations. It provides the following properties that may be subclassed or overridden.
* `sheetBackgroundColor: Color?` (default: `null`) - Allows setting a single color for Rownd-provided bottom sheet interfaces regardless of system theme. Use this or `dynamicSheetBackgroundColor`, but not both.
* `dynamicSheetBackgroundColor: Color` (default: `light: #ffffff`, `dark: #1c1c1e`; requires subclassing) - Allows changing the background color underlying the bottom sheet that appears when signing in, managing the user account, etc. Based on the system color scheme.
* `sheetCornerBorderRadius: Dp` (default: `25.dp`) - Modifies the curvature radius of the bottom sheet's top corners.
* `loadingAnimation: Int` (default: null) - Replace Rownd's use of the system default loading spinner (i.e., `ProgressBar`) with a custom animation. Any animation resource compatible with [Lottie](https://airbnb.design/lottie/) should work, but will be scaled to fit a 1:1 aspect ratio (usually with a frame width/height of `100 Dp`) This should be a value like `R.raw.my_animation`
To apply customizations, we recommend subclassing the `RowndCustomizations` class. Here's an example:
```kotlin theme={null}
class AppCustomizations(app: Application) : RowndCustomizations() {
private var app: Application
init {
this.app = app
}
override val dynamicSheetBackgroundColor: Color
get() {
val uiMode = AppCompatDelegate.getDefaultNightMode()
return if (uiMode == AppCompatDelegate.MODE_NIGHT_YES) {
Color(0xff123456)
} else {
Color(0xfffedcba)
}
}
override var sheetCornerBorderRadius: Dp = 25.dp
override var loadingAnimation: Int? = R.raw.loading
}
// MyApplication.kt
import android.app.Application
import android.content.res.Configuration
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import io.rownd.android.Rownd
import io.rownd.android.models.RowndCustomizations
class MyApplication: Application() {
override fun onCreate() {
super.onCreate()
Rownd.configure(this, "b60bc454-c45f-47a2-8f8a-12b2062f5a77")
Rownd.config.customizations = AppCustomizations(this)
}
}
```
## API reference
In addition to the StateFlow APIs, Rownd provides imperative APIs that you can call to request sign in, get and retrieve user profile information, retrieve a current access token, or encrypt user data with the user's local key.
### Rownd.requestSignIn(): Unit
Opens the Rownd sign-in dialog for authentication.
### Rownd.requestSignIn(with = RowndSignInHint)
Initiates a sign-in using the method specified by the `with` argument, bypassing the authentication method selector. For example, this could be used to steer a new user toward a specific sign-in method.
Supported options:
* `RowndSignInHint.Google` - Prompt user to sign in with their Google account
* `RowndSignInHint.OneTap` - Prompt user to sign into their account with Google One Tap
* `RowndSignInHint.Passkey` - Prompt user to sign in with a passkey if they've previously set one up
* `RowndSignInHint.Guest` - Sign in the user anonymously as a guest.
Example:
```kotlin theme={null}
Rownd.requestSignIn(with = RowndSignInHint.Google)
```
### Rownd.requestSignIn(RowndSignInOpts(...)): Unit
Opens the Rownd sign-in dialog for authentication, as before, but allows passing additional context options as shown below.
* `intent: RowndSignInIntent` - This option applies only when you have opted to split the sign-up/sign-in flow via the Rownd dashboard. Valid values are `.SignIn` or `.SignUp`. If you don’t set this value, the user will be presented with the unified sign-in/sign-up flow. Please reach out to [support@rownd.io](mailto:support@rownd.io) to enable.
* `postSignInRedirect: String` (Not recommended) - If you've followed the steps to enable Android App Links, the redirect will be handled automatically. When the user completes the authentication challenge via email or SMS, they'll be redirected to the URL set for postSignInRedirect. If this is an [Android App Link](https://developer.android.com/training/app-links), it will redirect the user back to your app.
Example:
```kotlin theme={null}
Rownd.requestSignIn(RowndSignInOpts(
intent = RowndSignInIntent.SignUp
))
```
### Rownd.signOut(): Void
Clears the user's access token, removes the user's profile data, and returns the user to a completely unauthenticated state.
### Rownd.signOut(scope = RowndSignOutScope): Void
Revokes all tokens for the specified user causing them to be signed out on all devices.
Supported options:
* `RowndSignOutScope.all`
\- All devices
The following user profile APIs technically accept `Any` as the value of a field. However, that value **must** be serializable using [Kotlin's Serialization](https://kotlinlang.org/docs/serialization.html) library. If the value is not serializable out of the box, you'll need to provide your own serializer implementation as described in the Kotlin documentation.
### suspend Rownd.getAccessToken(throwIfMissing: Boolean = false): String?
Assuming a user is signed-in, returns a valid access token, refreshing the current one if needed.
By default, this function will return `null` if an access token cannot be returned, either because the user is not signed in or because the refresh token is invalid.
If an access token cannot be returned due to a temporary condition (e.g., inaccessible network), this function will throw a `RowndException` indicating the failure reason (e.g., server or network error).
You may also set `throwIfMissing` to `true` to force an error to be thrown if an access token cannot be returned. This will provide more granular reasons for the failure. The possible error subtypes for `RowndException` in this case are:
* `NoAccessTokenPresentException(message: String)` - the user is not signed in
* `InvalidRefreshTokenException(message: String)` - the refresh token was invalid (e.g., the token was expired, revoked, or a previous exchange failed to complete successfully). The user will be signed out.
* `NetworkConnectionFailureException(details: String)` - a network condition prevented the token from being refreshed, even after several retries and should be re-attempted later. The user can remain signed-in.
* `ServerException(details: String)` - an error occurred on the server and you should try again later. The user can remain signed-in.
Example:
```kotlin theme={null}
try {
val accessToken = Rownd.getAccessToken(throwIfMissing = true)
} catch (e: RowndException) {
when (e) {
is NoAccessTokenPresentException -> { /* User is not signed in. do nothing. */ }
is InvalidRefreshTokenException -> { /* Refresh token is invalid. User was signed out. Show splash page and error dialog */ }
else -> { /* Something else went wrong. Ignore if possible, otherwise ask user to retry their action, connect to a network, close/reopen the app, etc. */ }
}
}
```
### suspend Rownd.getAccessToken(token: String): String?
When possible, exchanges a non-Rownd access token for a Rownd access token. This is primarily used in scenarios
where an app is migrating from some other authentication mechanism to Rownd. Using Rownd integrations,
the system will accept a third-party token. If it successfully validates, Rownd will sign-in the user and
return a fresh Rownd access token to the caller.
This API returns `null` if the token could not be validated and exchanged. If that occurs, it's likely
that the user should sign-in normally via `Rownd.requestSignIn()`.
> NOTE: This API is typically used once. After a Rownd token is available, other tokens should be discarded.
Example:
```kotlin theme={null}
// Assume `oldToken` was retrieved from some prior authenticator.
val accessToken = Rownd.getAccessToken(oldToken)
if (accessToken != null) {
// Navigate to the UI that a user should typically see
} else {
Rownd.requestSignIn()
}
```
### Rownd.user.get(): Map\
Returns the entire user profile as a Map
### Rownd.user.get\(field: String): T?
Returns the value of a specific field in the user's data Map. `"id"` is a special case that will return the user's ID, even though it's technically not in the Map itself.
Your application code is responsible for knowing which type the value should cast to. If the cast fails or the entry doesn't exist, a `null` value will be returned.
### Rownd.user.set(data: Map\): Void
Replaces the user's data with that contained in the Map. This may overwrite existing values, but must match the schema you defined within your Rownd application dashboard. Any fields that are flagged as `encrypted` will be encrypted on-device prior to storing in Rownd's platform.
### Rownd.user.set(field: String, value: Any): Void
Sets a specific user profile field to the provided value, overwriting if a value already exists. If the field is flagged as `encrypted`, it will be encrypted on-device prior to storing in Rownd's platform.
## Data encryption
As indicated previously, Rownd can automatically assist you in protecting sensitive user data by encrypting it on-device with a user's unique encryption key prior to saving it in Rownd's own platform storage.
When you configure your app within the Rownd platform, you can indicate that it supports on-device encryption. When this flag is set, Rownd will automatically generate a cryptographically secure, unrecoverable encryption key on the user's device after they sign in. The key is stored using Android's native KeyStore mechanisms and all encryption is handled on the device. The key is never transmitted to Rownd's servers and the Rownd SDK does not provide any APIs to for your code to programmatically retrieve the encryption key.
Only fields that you designate `encrypted` are encrypted on-device prior to storing within Rownd. Some identifying fields like email and phone number do not support on-device encryption at this time, since they are frequently used for indexing purposes.
Of course, all data within the Rownd platform is encrypted at rest on disk and in transit, but this does not afford the same privacy guarantees as data encrypted on a user's local device. For especially sensitive data, we recommend enabling field-level encryption.
Data encrypted on-device will not be accessible by you, the app developer, outside of the context of your app. In other words, your app can use encrypted data in its plaintext (decrypted) form while the user is signed in, but you won't be able to retrieve that data from the Rownd servers in a decrypted form. For data that you choose to encrypt, you should never transmit the plain text value across a network.
In some cases, you may want to encrypt data on-device that you'll send to your own servers for storage. Rownd provides convenience methods to encrypt and decrypt that data with the same user-owned key.
### Rownd.user.encrypt(plaintext: String): String
Encrypts the provided String `data` using the user's symmetric encryption key and returns the ciphertext as a string. You can encrypt anything that can be represented as a string (e.g., Int, Dictionary, Array, etc), but it's currently up to you to get it into a string format first.
If the encryption fails, an `EncryptionException` will be thrown with a message explaining the failure.
### Rownd.user.decrypt(ciphertext: String): String
Attempts to decrypt the provided String `data`, returning the plaintext as a string. If the data originated as some other type (e.g., Map), you'll need to decode the data back into its original type.
If the decryption fails, an `EncryptionException` will be thrown with a message explaining the failure.
Encryption is only possible once a user has authenticated. Rownd supports multiple levels of authentication (e.g., guest, unverified, and verified), but the lowest level of authentication must be achieved prior to encrypting or decrypting data. If you need to explicitly check whether encryption is possible at a specific point in time, call `Rownd.user.isEncryptionPossible(): Boolean` prior to calling `encrypt()` or `decrypt()`.
## Events
The Rownd SDK emits lifecycle events that you can listen to within your app. These events are primarily useful for detecting more granular aspects of a user's session (e.g., starting to sign in, completing sign-in, updated profile, etc.).
To listen to events, pass a function or closure that accepts a `RowndEvent` object to `Rownd.addEventListener()`. It might look something like this:
```kotlin theme={null}
class MyApp: Application() {
override fun onCreate() {
super.onCreate()
Rownd.addEventListener {
when (it.event) {
RowndEventType.SignInStarted -> {
// Do stuff
}
RowndEventType.SignInCompleted -> {
it.data?.get("user_type")?.let { it1 -> Log.d("App", it1.toString()) }
}
else -> {
// no-op
}
}
}
}
}
```
This registers the event listener with the Rownd SDK. You can also unregister the listener by calling `Rownd.removeEventListener()` with the same function or closure if you assign it to a variable.
Once the event handler is registered, it will receive events as they occur. The `RowndEvent` object contains the event type and any associated data. The event types are defined in the `RowndEventType` enum.
> NOTE: You'll need `implementation "org.jetbrains.kotlinx:kotlinx-serialization-json"` listed as a dependency in your `build.gradle` file in order to access the `data` `JsonObject` in the `RowndEvent` object.
#### List of events
Here's a list of events that the Rownd SDK emits and the corresponding data that should be present in the event data dictionary. Remember to write your code defensively, as the data dictionary may be missing keys in some cases.
# Expo
Source: https://docs.rownd.io/sdk-reference/mobile/expo
Rownd bindings for Expo
### Prerequisites
You must be using React Native v0.64 or higher.
Must be an ejected Expo app which can be bare React Native or use an Expo development build. Instructions for bare React Native app can be found [here](/sdk-reference/mobile/react-native).
### Installation
First, install the Rownd SDK for Expo.
```bash theme={null}
npm install @rownd/react-native
```
### Expo development
1. Add `@rownd/react-native` as a plugin to your `app.json` file.
```json theme={null}
{
"expo": {
"plugins": ["@rownd/react-native"]
}
}
```
2. Install [Expo BuildProperties](https://docs.expo.dev/versions/latest/sdk/build-properties/) to set iOS/Android versions
```sh theme={null}
npx expo install expo-build-properties
```
3. Add `expo-build-properties` as a plugin to your `app.json` file. Ensure the Sdk versions match or are above provided iOS/Android versions.
```json theme={null}
{
"expo": {
"plugins": [
"@rownd/react-native",
[
"expo-build-properties",
{
"android": {
"minSdkVersion": 26
},
"ios": {
"deploymentTarget": "14.0"
}
}
]
]
}
}
```
4. (optional) Enable Apple sign-in for iOS in your `app.json` file.
```json theme={null}
{
"expo": {
"ios": {
"usesAppleSignIn": true
}
}
}
```
5. (optional) Enable Google sign-in for iOS. Add your Google IOS Client ID client as a URL Scheme in your `app.json` file.
```json theme={null}
{
"expo": {
"infoPlist": {
"CFBundleURLTypes": [
{
"CFBundleURLSchemes": [
"com.googleusercontent.apps.xxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxx"
]
}
]
}
}
}
```
#### Enable deep linking
Rownd supports automatically signing-in users when they initially install your
app or when they click a sign-in link when the app is already installed. Follow instructions below to setup.
1. Visit the Rownd platform and go to the [Sign-in methods](https://app.rownd.io) page. Open the Mobile app settings modal and (1) create a subdomain and (2) fill out the iOS/Android settings.
2. Enable deep linking for Expo using `app.json` and `` created in the Rownd platform.
These settings might only apply at the time the native projects were generated. Try deleting the ios/android folders and rebuilding the project.
File: `app.json`
```json theme={null}
{
"expo": {
"ios": {
...
"associatedDomains": ["applinks:.rownd.link"]
},
"android": {
...
"intentFilters": [
{
"action": "VIEW",
"autoVerify": true,
"data": [
{
"scheme": "https",
"host": ".rownd.link"
}
],
"category": ["BROWSABLE", "DEFAULT"]
}
]
}
}
}
```
# Flutter
Source: https://docs.rownd.io/sdk-reference/mobile/flutter
Rownd bindings for Flutter
## Getting Started
This SDK leverages Rownd's web and native iOS and Android SDKs to provide a simple interface for Flutter developers to add Rownd to their apps.
### Installation
Begin by depending on `rownd_flutter_plugin` and `provider` in your `pubspec.yaml`:
```yaml theme={null}
name: my_app
---
dependencies:
rownd_flutter_plugin: ^1.3.2
provider: ^6.1.2
```
If you don't have one already, be sure to obtain an app key from the [Rownd dashboard](https://app.rownd.io) for use in the next step.
## Platform-specific configuration
There are a couple of configuration settings that must be applied to the platform-specific code for your app in order for Rownd to work properly.
### Android
1. Set your app's `targetSdkVersion` to 32 or higher in your app's `build.gradle` file.
2. Set your app's `minSdkVersion` to 26 or higher in your app's `build.gradle` file. Rownd currently does not support an API version lower than 26.
3. Ensure any Android activities (like `MainActivity`) subclass `FlutterFragmentActivity` instead of `FlutterActivity`. If you're using the default `MainActivity` generated by Flutter, you can simply change the superclass to `FlutterFragmentActivity` like this:
```kotlin theme={null}
class MainActivity: FlutterFragmentActivity() {}
```
4. Check and update your ProGuard config using [the rules from our Android SDK](https://github.com/rownd/android/blob/main/README.md#proguard-config).
## Usage
Initialize the Rownd plugin and call `rowndPlugin.configure(RowndConfig(appKey: 'YOUR_APP_KEY'));` within your application wherever you do most of your app's initialization.
Now you're ready to use Rownd in your app. The plugin provides a `RowndCubit` class that can be used to manage the Rownd state.
A basic sign-in example might look like this:
```dart theme={null}
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import 'package:rownd_flutter_plugin/rownd.dart';
import 'package:rownd_flutter_plugin/rownd_platform_interface.dart';
import 'package:rownd_flutter_plugin/state/global_state.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State createState() => _MyAppState();
}
class _MyAppState extends State {
final rowndPlugin = RowndPlugin(); // Initialize the Rownd plugin
@override
void initState() {
super.initState();
rowndPlugin.configure(RowndConfig(appKey: 'YOUR_APP_KEY'));// Configure the Rownd plugin with your app key
}
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => RowndCubit(rowndPlugin), // Create a RowndCubit with the Rownd plugin
child: MaterialApp(
title: 'Example App',
theme: ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(seedColor: Colors.green),
),
home: BlocBuilder(
builder: (context, state) {
// Use the RowndCubit to build the UI based on the current authentication state
if (state == AuthState.authenticated) {
return const MyHomePage();
} else {
return const LoginPage();
}
},
),
routes: {
'/home': (context) => const MyHomePage(),
},
),
);
}
}
```
In this example, the `home` for the BlocProvider is determined by the `RowndCubit`'s authentication state. If the user is authenticated, the `MyHomePage` widget is displayed. If the user is not authenticated, the `LoginPage` widget is displayed.
There are many ways to define the UI based on the authentication state, but this is a simple and effective approach.
To learn more about Bloc and Cubit, see the [flutter\_bloc documentation](https://pub.dev/packages/flutter_bloc).
### RowndCubit
The `RowndCubit` class is a `Cubit` that manages the Rownd state. It provides a simple interface for checking the current user's authentication status, signing in and out, and getting the current user's profile.
```dart theme={null}
class LoginPage extends StatelessWidget {
const LoginPage({super.key});
@override
Widget build(BuildContext context) {
var authCubit = context.watch(); // Get the RowndCubit from the context
return Scaffold(
appBar: AppBar(
title: const Text('My example app'),
),
body: Column(children: [
const Center(child: Text('Welcome to my example app!')),
ElevatedButton(
onPressed: () async {
authCubit.signIn(); // Sign the user in
},
child: const Text('Sign in')),
]),
);
}
}
```
## API
### `signIn(RowndSignInOptions? options)`
Signs the user in. The `options` parameter is optional and can be used to specify additional options for the sign-in process.
```dart theme={null}
class LoginPage extends StatelessWidget {
const LoginPage({super.key});
@override
Widget build(BuildContext context) {
var authCubit = context.watch();
return Scaffold(
body: Column([
const Center(child: Text('Welcome to my example app!')),
ElevatedButton(
onPressed: () async {
authCubit.signIn(); // Sign the user in
},
child: const Text('Sign in')),
]),
);
}
}
```
#### `RowndSignInOptions`
| Property | Type | Description |
| -------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `postSignInRedirect` (not recommended) | `String` | If you've followed the steps to enable Android App Links, the redirect will be handled automatically. When the user completes the authentication challenge via email or SMS, they'll be redirected to the URL set for postSignInRedirect. If this is an [Android App Link](https://developer.android.com/training/app-links), it will redirect the user back to your app. |
| `intent` | `String` | This option applies only when you have opted to split the sign-up/sign-in flow via the Rownd dashboard. Valid values are `.SignIn` or `.SignUp`. If you don’t set this value, the user will be presented with the unified sign-in/sign-up flow. Please reach out to [support@rownd.io](mailto:support@rownd.io) to enable. |
### `signOut()`
Signs the user out.
```dart theme={null}
var authCubit = context.watch();
...
ElevatedButton(
onPressed: () async {
authCubit.signOut(); // Sign the user out
Navigator.pushReplacementNamed(context, '/');
},
child: const Text("Sign out"),
)
```
### `isAuthenticated()`
Returns a boolean indicating whether the user is authenticated.
```dart theme={null}
var authCubit = context.watch();
bool isAuthenticated = authCubit.isAuthenticated(); // Check if the user is authenticated
```
### `manageAccount()`
Displays the current user's profile information, allowing them to update it.
```dart theme={null}
var authCubit = context.watch();
...
ElevatedButton(
onPressed: () {
authCubit.manageAccount(); // Display the user's profile information
},
child: const Text("Manage Account"),
),
```
### `registerPasskey()`
Registers a passkey for the user. A user must have successfully authenticated at least once before they can register a passkey.
```dart theme={null}
var authCubit = context.watch();
...
ElevatedButton(
onPressed: () {
authCubit.registerPasskey(); // Register a passkey for the user
},
child: const Text("Register Passkey"),
),
```
### `user`
Returns the current user's profile as a `Map`.
```dart theme={null}
var authCubit = context.watch();
Map user = authCubit.user; // Get the user's profile
```
# iOS
Source: https://docs.rownd.io/sdk-reference/mobile/ios
Rownd bindings for native iOS apps
The Rownd SDK for iOS provides authentication, account and user profile management, deep linking, and more for native iPhone, iPad, and even macOS applications.
Using the Rownd platform, you can easily bring the same authentication that's on your website to your mobile apps. Or if you only authenticate users on your mobile apps, you can streamline the authentication process using Rownd's passwordless sign-in links, enabling you to seamlessly authenticate users from an app link sent to their email or phone number.
Once a user is authenticated, you can retrieve and update their profile information on the fly using native APIs. Leverage Rownd's pre-built mobile app components to give users profile management tools.
## Installation
In Xcode, select your project file, select the main target, then scroll down to the "frameworks" section to add a package dependency to your project. See the [official documentation](https://developer.apple.com/documentation/xcode/adding-package-dependencies-to-your-app) for specific steps.
Enter this as the package repository url:
```
https://github.com/rownd/ios.git
```
## Usage
### Initializing the Rownd SDK
In your `AppDelegate` file, call the `Rownd.configure()` method during application launch:
```swift theme={null}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
Task {
await Rownd.configure(launchOptions: launchOptions, appKey: "YOUR_API_KEY")
}
return true
}
// Optionally, ensure any incoming URL requests are passed to Rownd for authentication
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
Rownd.handleSmartLink(url: url)
return true
}
func application(_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
// Get URL components from the incoming user activity.
guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
let incomingURL = userActivity.webpageURL,
let components = NSURLComponents(url: incomingURL, resolvingAgainstBaseURL: true) else {
return false
}
return Rownd.handleSmartLink(url: incomingURL)
}
func scene(_ scene: UIScene, willConnectTo
session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions) {
// Get URL components from the incoming user activity.
guard let userActivity = connectionOptions.userActivities.first,
userActivity.activityType == NSUserActivityTypeBrowsingWeb,
let incomingURL = userActivity.webpageURL,
let components = NSURLComponents(url: incomingURL, resolvingAgainstBaseURL: true) else {
return
}
Rownd.handleSmartLink(url: incomingURL)
}
```
After initialization, your app will typically call `Rownd.requestSignIn()` at some point, if the user is not already authenticated. This will display the Rownd interface for authenticating the user. Once they complete the sign-in process, an access token and the user's profile information will be available to your app.
### Handling authentication
Rownd leverages an observeable architecture to expose data to your app. This means that as the Rownd state changes, an app can dynamically update without complicated logic. For example, a view can display different information based on the user's authentication status.
Here's an example SwiftUI view that displays different messages depending on the user's authenticated status:
```swift theme={null}
import SwiftUI
import Rownd
struct MyView: View {
@StateObject var authState = Rownd.getInstance().state().subscribe { $0.auth }
@StateObject var user = Rownd.getInstance().state().subscribe { $0.user.data }
var body: some View {
VStack {
HStack {
Button(action: {
if authState.current.isAuthenticated {
Rownd.signOut()
} else {
Rownd.requestSignIn()
}
},
label: {
Text(!authState.current.isAuthenticated ? "Sign in" : "Sign out")
})
Spacer()
if authState.current.isAuthenticated {
Button(action: {
}, label: {
Text(user.current?["first_name"]?.value as? String)
})
}
}
.padding(.horizontal)
}
}
}
struct MyView_Previews: PreviewProvider {
static var previews: some View {
MyView()
}
}
```
#### Example usage outside of SwiftUI
```swift theme={null}
class Auth {
private var authState = Rownd.getInstance().state().subscribe { $0.auth }
private var cancellables = Set()
init() {
self.authState.$current
.sink { [weak self] state in
// Called whenever the auth state changes
guard !state.isLoading else { return }
guard state.auth.isAuthenticated else {
return
}
// User is authenticated. Change app state accordingly.
// This is also a good time to get the latest access token.
let accessToken = await Rownd.getAccessToken()
}
.store(in: &cancellables)
}
}
```
You can subscribe to any state object that Rownd supports. Here's a list of available states and their structures:
#### .auth
```swift theme={null}
public struct AuthState {
public var accessToken: String? // Current, valid access token for the user (valid for one hour)
public var isAuthenticated: Bool // Whether the user is currently authenticated
public var isAccessTokenValid: Bool // Whether the current access token is valid
public var isVerifiedUser: Bool? // Whether the current user has verified at least one identifier (e.g., email)
public var hasPreviouslySignedIn: Bool // Whether the app has been previously signed in before
}
```
#### .user
```swift theme={null}
public struct UserState {
public var id: String? // The user's ID as known to Rownd
public var data: Dictionary // Contains key/value pairs for the current user based on your Rownd's app config
}
```
### Getting an access token
Whenever your app needs to make an authenticated request to your backend, you'll need to get an access token. You can do this by calling `await Rownd.getAccessToken(throwIfMissing: true)`. If the user is not authenticated, this function will throw an `AuthenticationError.noAccessTokenPresent` error.
If there is an issue fetching the access token (e.g., during a token refresh), an `AuthenticationError.serverError` or `AuthenticationError.networkConnectionFailure` error will be thrown. Server and network failures are automatically retried before throwing an error.
If the user is signed in, but the refresh token is expired, invalidated, or has been used previously, the user will be signed out and the function will throw an `AuthenticationError.invalidRefreshToken` error.
See the [API reference](#rownd-getaccesstoken-token-string-async-string) for more information.
### Customizing the UI
While most customizations are handled via the [Rownd dashboard](https://app.rownd.io), there are a few things that have to be customized directly in the SDK.
The `RowndCustomizations` class exists to facilitate these customizations. It provides the following properties that may be subclassed or overridden.
* `sheetBackgroundColor: UIColor` (default: light: .white, dark: .systemGray6; requires subclassing) - Allows changing the background color underlaying the bottom sheet that appears when signing in, managing the user account, etc.
* `sheetCornerBorderRadius: CGFloat` (default: `25.0`) - Modifies the curvature radius of the bottom sheet corners.
* `loadingAnimation: Lottie.Animation` (default: nil) - Replace Rownd's use of the system default loading spinner (i.e., `UIActivityIndicatorView` or `ProgressView`) with a custom animation. Any animation compatible with [Lottie](https://airbnb.design/lottie/) should work, but will be scaled to fit a 1:1 aspect ratio (usually with a `CGRect` frame width/height of `100`)
To apply customizations, we recommend subclassing the `RowndCustomizations` class. Here's an example:
```swift theme={null}
class AppCustomizations : RowndCustomizations {
override var sheetBackgroundColor: UIColor {
return UIColor(red: 31/255, green: 37/255, blue: 80/255, alpha: 1.0)
}
}
// AppDelegate.swift
import Rownd
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
Rownd.config.customizations = AppCustomizations() // Apply the customizations
Task {
await Rownd.configure(launchOptions: launchOptions, appKey: "YOUR_API_KEY")
}
return true
}
}
```
### Usage within app extensions
It's possible to access the Rownd state from within an app extension, like a widget. You'll need to include the Rownd package in the extension's dependencies and set up an app group for data sharing between the app and the extension. Without the app group, extensions will not be able to sync with your app's authentication state.
Follow these steps to configure your app and extension to work with Rownd:
1. Add an [app group](https://developer.apple.com/documentation/xcode/configuring-app-groups) entitlement to both your app and any extensions that will use Rownd. This app group **must** be named like this: `.io.rownd.sdk`. For example, if you work at a company with the acme.com domain, your app group might look like this: `com.acme.app.io.rownd.sdk`. Rownd will store its data in this app group. Your app should store data in a separate app group to prevent any collisions.
2. In your app's `AppDelegate` file as well as your extension's entry point, set the app group prefix you defined above via `Rownd.config.appGroupPrefix = ""` (e.g., `Rownd.config.appGroupPrefix = "com.acme.app"`)
3. In your extension, call `Rownd.configure()` prior to accessing authentication state. Here's an example:
```swift theme={null}
Task {
Rownd.config.appGroupPrefix = "group.rowndexample"
let rowndState = await Rownd.configure(appKey: "key_pko8eul59xz33hr21jgxvx6s")
var authStatus: String = "You are not authenticated. ☹️"
if rowndState.auth.isAuthenticated == true {
authStatus = "You are authenticated! 😁"
}
}
```
If you're building widgets that need access to Rownd auth state, you should listen for Rownd auth events and notify `WidgetCenter` that widgets may need updating any time the state changes. That way, they'll re-render while your app is in the foreground and will show an accurate state. Here's a simple example:
```swift theme={null}
import Foundation
import Combine
import WidgetKit
import Rownd
class SomeClass {
private var authState = Rownd.getInstance().state().subscribe { $0.auth }
private var cancellables = Set()
init() {
self.authState
.$current
.sink { [weak self] state in
WidgetCenter.shared.reloadAllTimelines()
}
.store(in: &cancellables)
}
}
```
### Configuration options
Rownd provides a number of configuration options that can be set before calling `Rownd.configure()`. These options are available via the `Rownd.config` object.
* `enableSmartLinkPasteBehavior: Bool` (default: `true`) - Attempts to access the clipboard for smart link pasting behavior if it contains a URL. This *will* trigger a system alert asking for permission to access the clipboard. If you don't want this behavior, set this to `false`.
### Events
The Rownd SDK emits lifecycle events that you can listen to within your app. These events are primarily useful for detecting more granular aspects of a user's session (e.g., starting to sign in, completing sign-in, updated profile, etc.).
To listen to events, first create a class that conforms to the `RowndEventHandlerDelegate` protocol. It looks something like this:
```swift theme={null}
import Foundation
import Rownd
class RowndEventHandler: RowndEventHandlerDelegate {
func handleRowndEvent(_ event: RowndEvent) {
switch event.event {
case .signInCompleted:
let userType = event.data?["user_type"]
let appVariantUserType = event.data?["app_variant_user_type"]
break
default:
break
}
}
}
```
Next, register the event handler delegate with the Rownd SDK:
```swift theme={null}
Rownd.addEventHandler(RowndEventHandler())
```
Once the event handler is registered, it will receive events as they occur. The `RowndEvent` object contains the event type and any associated data. The event types are defined in the `RowndEventType` enum.
#### List of events
Here's a list of events that the Rownd SDK emits and the corresponding data that should be present in the event data dictionary. Remember to write your code defensively, as the data dictionary may be missing keys in some cases.
### API reference
In addition to the state observable APIs, Rownd provides imperative APIs that you can call to request sign in, get and retrieve user profile information, retrieve a current access token, or encrypt user data with the user's local key.
#### `Rownd.requestSignIn() -> Void`
Opens the Rownd sign-in dialog for authentication.
#### `Rownd.requestSignIn(RowndSignInOptions(postSignInRedirect: "https://my-domain.com")) -> Void`
#### `Rownd.requestSignIn(RowndSignInOptions(postSignInRedirect: "https://my-domain.com", intent: .signIn)) -> Void`
Opens the Rownd sign-in dialog for authentication, as above. When the user completes the authentication challenge via email or SMS, they'll be redirected to the URL set for `postSignInRedirect`. If this is a [Universal Link](https://developer.apple.com/ios/universal-links/), it will redirect the user back to your app.
#### `Rownd.requestSignIn(with: RowndSignInHint) -> Void`
#### `Rownd.requestSignIn(with: RowndSignInHint, signInOptions: RowndSignInOptions?) -> Void`
Requests a sign-in, but with a specific authentication provider (e.g., Sign in with Apple). Rownd treats this information as a hint. If the specified authentication provider is enabled within your Rownd app configuration, it will be honored. If not, Rownd will fall back to the default flow.
Supported values:
* `.appleId` - Prompt user to sign in with their Apple ID
* `.google` - Prompt user to sign in with their Google account
* `.passkey` - Prompt user to sign in with a passkey if they've previously set one up
* `.guest` - Sign in the user anonymously as a guest.
#### `RowndSignInOptions`
Some of the `requestSignIn()` methods accept an optional `RowndSignInOptions` parameter. This class contains the following properties:
* `postSignInRedirect: String?` (not recommended) - When the user completes the authentication challenge via email or SMS, they'll be redirected to the URL set for `postSignInRedirect`. If this is a [Universal Link](https://developer.apple.com/ios/universal-links/), it will redirect the user back to your app. If you don't set this value, the user will be redirected to your app's subdomain as configured in the Rownd dashboard.
* `intent: RowndSignInIntent?` - This option applies only when you have opted to split the sign-up/sign-in flow via the Rownd dashboard. Valid values are `.signIn` or `.signUp`. If you don't set this value, the user will be presented with the unified sign-in/sign-up flow. If you don't set this value, the user will be presented with the unified sign-in/sign-up flow.
### `Rownd.signOut() -> Void`
Clears the user's access token, removes the user's profile data, and returns the user to a completely unauthenticated state.
### `Rownd.signOut(scope: RowndSignoutScope) -> Void`
Revokes all tokens for the specified user causing them to be signed out on all devices.
Supported values:
* `.all` - All devices
### `Rownd.getAccessToken(throwIfMissing: Bool = false) async throws -> String?`
Assuming a user is signed-in, returns a valid access token, refreshing the current one if needed.
By default, this function will return `nil` if an access token cannot be returned, either because the user is not signed in or because the refresh token is invalid.
If an access token cannot be returned due to a temporary condition (e.g., inaccessible network), this function will throw an `AuthenticationError` indicating the failure reason (e.g., server or network error).
You may also set `throwIfMissing` to `true` to force an error to be thrown if an access token cannot be returned. This will provide more granular reasons for the failure. The possible error cases for `AuthenticationError` are:
* `.noAccessTokenPresent` - the user is not signed in
* `.invalidRefreshToken(details: String)` - the refresh token was invalid (e.g., the token was expired, revoked, or a previous exchange failed to complete successfully). The user will be signed out.
* `.networkConnectionFailure(details: String)` - a network condition prevented the token from being refreshed, even after several retries and should be re-attempted later
* `.serverError(details: String)` - an error occurred on the server and you should try again later
Example:
```swift theme={null}
do {
let accessToken = try await Rownd.getAccessToken(throwIfMissing: true)
} catch {
switch error {
case AuthenticationError.noAccessTokenPresent:
// The user is not signed in
case AuthenticationError.invalidRefreshToken(let details):
// The refresh token was invalid. Request that the user sign in again.
case AuthenticationError.networkConnectionFailure(let details),
AuthenticationError.serverError(let details):
// Alert the user that they should try again due to some recoverable error
print("Server error occurred: \(details)")
}
}
```
#### Rownd.getAccessToken(\_ token: String) async -> String?
When possible, exchanges a non-Rownd access token for a Rownd access token. This is primarily used in scenarios
where an app is migrating from some other authentication mechanism to Rownd. Using Rownd integrations,
the system will accept a third-party token. If it successfully validates, Rownd will sign-in the user and
return a fresh Rownd access token to the caller.
This API returns `nil` if the token could not be validated and exchanged. If that occurs, it's likely
that the user should sign-in normally via `Rownd.requestSignIn()`.
> NOTE: This API is typically used once. After a Rownd token is available, other tokens should be discarded.
> Example:
```swift theme={null}
// Assume `oldToken` was retrieved from some prior authenticator.
let accessToken = await Rownd.getAccessToken(oldToken)
if (accessToken != nil) {
// Navigate to the UI that a user should typically see
} else {
Rownd.requestSignIn()
}
```
#### Rownd.user.get() -> Dictionary\
Returns the entire user profile as a dictionary object
#### Rownd.user.get\(field: String) -> T?
Returns the value of a specific field in the user's data dictionary. You can use `user_id` to obtain the user's unique ID, which is always a string.
Your application code is responsible for knowing which type the value should cast to. If the cast fails or the entry doesn't exist, a `nil` value will be returned.
#### Rownd.user.set(data: Dictionary\) -> void
Replaces the user's data with that contained in the dictionary. This may overwrite existing values, but must match the schema you defined within your Rownd application dashboard.
Hint: use `AnyCodable.init(value)` to conform your values to the required type.
#### Rownd.user.set(field: String, value: AnyCodable) -> void
Sets a specific user profile field to the provided value, overwriting if a value already exists. If the field is flagged as `encrypted`, it will be encrypted on-device prior to storing in Rownd's platform.
Hint: use `AnyCodable.init(value)` to conform your values to the required type.
# Mobile SDK Overview
Source: https://docs.rownd.io/sdk-reference/mobile/overview
## Rownd Mobile SDK Features
Rownd's Mobile SDKs deliver enterprise-grade authentication with native performance and delightful user experiences across iOS and Android platforms.
### Deep Platform Integration
Native integration with platform-specific features provides the best possible user experience:
* **iOS Integration**:
* Native Apple Sign-in
* Passkey/Face ID/Touch ID support
* Universal links for seamless deep linking
* SwiftUI and UIKit support
* **Android Integration**:
* Google One-Tap sign-in
* Native Passkey / Biometric authentication
* App links and deep linking
* Kotlin and Java support
### Mobile-Optimized UI Components
Pre-built, native UI elements that feel at home on each platform:
* **Native Bottom Sheets**: Platform-specific design and behavior
* **Adaptive Layouts**: Responsive to different screen sizes and orientations
* **Custom Animations**: Smooth, native-feeling transitions
* **Accessibility Support**: Built-in support for VoiceOver and TalkBack
### No-Code Configuration
Empower your team to make changes without app updates:
* **Dynamic Authentication Flow**: Modify sign-in methods and flows instantly
* **Visual Customization**: Update colors, text, and branding from the dashboard
* **Feature Flags**: Enable/disable features without code changes
* **A/B Testing**: Test different flows without deploying new versions
### Automated User Journeys
Create sophisticated onboarding experiences without code:
* **Trigger Controls**: Choose when and where to prompt users
* **Progressive Profiling**: Gradually collect user information
* **Conditional Flows**: Create different paths based on user attributes
* **Cross-Platform Consistency**: Maintain unified experiences across devices
### Easy Implementation
Quick integration process that respects developer workflows:
* **Comprehensive Documentation**: Clear setup guides and API references
* **Sample Applications**: Working examples for common use cases
* **Version Management**: Backward compatibility and clear upgrade paths
* **Technical Support**: Direct access to engineering support
## Steps for getting started:
1. [Set up your Rownd account](/welcome/getting-started) (only takes a minute).
2. Create an [app key](/configuration/app-credentials).
3. Install Rownd using an SDK.
4. [Configure customizations](/configuration/overview) and sign-in methods from the Rownd platform.
## Rownd Mobile SDKs:
Kotlin or Java
Swift
}
href="/sdk-reference/mobile/flutter"
/>
}
href="/sdk-reference/mobile/expo"
/>
# React Native
Source: https://docs.rownd.io/sdk-reference/mobile/react-native
Rownd bindings for React Native
### Prerequisites
You must be using React Native v0.64 or higher.
### Installation
First, install the Rownd SDK for React Native.
```bash theme={null}
npm install @rownd/react-native
```
### Expo
You can find specific Expo installation instructions [here](/sdk-reference/mobile/expo).
#### Android
1. Ensure the Sdk versions match or are above provided versions. File:
*android/build.gradle*
```jsx theme={null}
ext {
...
minSdkVersion = 26
compileSdkVersion = 32
targetSdkVersion = 31
...
}
```
2. Install the Rownd library and dependencies.
```bash theme={null}
cd android && ./gradlew build
```
3. Check and update your ProGuard config using [the rules from our Android SDK](https://github.com/rownd/android/blob/main/README.md#proguard-config).
4. Only required for Google Sign-in: Add a Rownd plugin initializer to your MainActivity file. File: \*android/app/src/main/java/.../MainActivity.java
```java theme={null}
import android.os.Bundle;
import com.reactnativerowndplugin.RowndPluginPackage;
public class MainActivity extends ReactActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
RowndPluginPackage.preInit(this);
}
}
```
#### iOS
1. Ensure iOS version is at least 14. File: *ios/Podfile*
```jsx theme={null}
platform: ios, "14.0";
```
2. Install the Rownd pod and it's dependencies
```bash theme={null}
cd ios && pod install
```
#### Enable deep linking
Rownd supports automatically signing-in users when they initially install your
app or when they click a sign-in link when the app is already installed.
Instructions for: [iOS](/configuration/mobile/ios) and [Android](/configuration/mobile/android)
# Rownd SDK Overview
Source: https://docs.rownd.io/sdk-reference/overview
Whether you've got a website, blog, single-page app, traditional web app, or mobile app, Rownd has you covered.
Rownd's SDKs have dozens of visual elements, including the sign-up and sign-in screens, automations, and the user-profile sections, which can save developers days of design and front-end work.
Looking for an SDK you don't see? Reach out to us at [support@rownd.io](mailto:support@rownd.io). Odds are we're already working on it.
### Choose your applicaiton type
Mobile app that runs on a device (Flutter, Swift, etc)
Webapp that runs in a browser (React, Next.js, etc)
A hosted or custom website (Wordpress, Webflow, etc)
Backend side of the app (Node.js, Django, etc)
## Jump directly to your SDK
### Rownd Webapp / Website SDKs
}
href="/sdk-reference/web/react"
/>
}
href="/sdk-reference/web/nextjs"
/>
}
href="/sdk-reference/web/remix"
/>
}
href="/sdk-reference/web/ruby-on-rails"
/>
### Rownd Mobile SDKs
Kotlin or Java
Swift
}
href="/sdk-reference/mobile/flutter"
/>
### Backend / Server-side SDKs
}
href="/sdk-reference/web/ruby-on-rails"
/>
# Angular
Source: https://docs.rownd.io/sdk-reference/web/angular
Angular SDK reference
#### Installation
Run `npm install @rownd/angular` or `yarn add @rownd/angular`
### Usage
The library provides an Angular Module and Service for dependency injection.
In the main app.module.ts file, add the Rownd module. You'll also need to
include the `@ngrx/store` module as well, as Rownd will drive state updates
through it.
```jsx theme={null}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { StoreModule } from '@ngrx/store';
import { RowndModule, RowndService } from '@rownd/angular';
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
StoreModule.forRoot({}),
RowndModule.forRoot({ appKey: '' }),
],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {
// Load the Rownd Service into your app
constructor(private rownd: RowndService) {}
}
```
#### Module params
```jsx theme={null}
import { Component } from '@angular/core';
import { RowndService } from '@rownd/angular';
@Component({
selector: 'protected-component',
templateUrl: 'protected.component.html',
styleUrls: ['protected.component.scss'],
})
export class ProtectedComponent {
constructor(private rownd: RowndService) {
// Subscribe to Rownd isAuthenticated observable
this.rownd.isAuthenticated$.subscribe({
next(auth) {
console.log("is Authenticated: ", auth)
}
});
// Subscribe to Rownd User Data observable
this.rownd.user$.subscribe({
next(user) {
console.log("user: ", user)
}
});
}
signIn() {
this.rownd.requestSignIn();
}
signOut() {
this.rownd.signOut();
}
}
```
#### API Reference
**requestSignIn()**
Trigger the Rownd sign-in dialog. This accepts an optional parameter with
options to control the behavior of the sign in. See our
[SDK Docs](/sdk-reference/web/javascript--api-reference)
for a full list of supported options.
```jsx theme={null}
import { Component } from '@angular/core';
import { RowndService } from '@rownd/angular';
@Component({
selector: 'my-component',
template: ``,
})
export class MyComponent {
constructor(private rownd: RowndService) {}
requestSignIn() {
this.rownd.requestSignIn({
auto_sign_in: true,
identifier: '+19199998181',
post_login_redirect: '/dashboard'
});
}
}
```
* `auto_sign_in`: boolean - when true, automatically trigger a sign-in attempt
if identifier is included or an email address or phone number has already been
set in the user data.
* `identifier`: string - an email address or phone number (in E164 format) to
which a verification message may be sent. If the Rownd app is configured to
allow unverified users, then sign-in will complete without verification if the
user has not signed in previously.
* `post_login_redirect`: string - at the conclusion of a successful sign in,
Rownd will redirect the user here. This can be a path on the current domain or
a full URL.
**signOut()**
Signs out the current user and clears their profile, returning them to a
completely unauthenticated state.
```jsx theme={null}
import { Component } from '@angular/core';
import { RowndService } from '@rownd/angular';
@Component({
selector: 'my-component',
template: ``,
})
export class MyComponent {
constructor(private rownd: RowndService) {}
signOut() {
this.rownd.signOut()
}
}
```
**getAccessToken()**
Get the current user's access token.
```jsx theme={null}
await this.rownd.getAccessToken({ waitForToken: true });
```
* `waitForToken`: boolean - when true, if no access token is present or if it's
expired, the promise will not be resolved until a valid token is available.
While unlikely, this could result in waiting forever.
**isAuthenticated\$**
An observable boolean that indicates whether the user is currently signed in.
```jsx theme={null}
import { Component } from '@angular/core';
import { RowndService } from '@rownd/angular';
@Component({
selector: 'my-component',
template: 'You're signed in!
})
export class MyComponent {
constructor(private rownd: RowndService) { }
}
```
**user\$**
An observable object that represents information about the current user,
specifically their profile information. The schema will match whatever you
define in the Rownd Platform. See our
[documentation](https://docs.rownd.io/rownd/guides/configuration/user-profiles)
for more information on configuring this schema.
```jsx theme={null}
import { Component } from '@angular/core';
import { RowndService } from '@rownd/angular';
Component({
selector: 'my-component',
template: '
Hello, {{(this.rownd.user$ | async)?.first_name}}
})
export class MyComponent {
constructor(private rownd: RowndService) { }
}
```
**isInitializing\$**
An observable boolean that will be `true` until Rownd has fully loaded and
resolved the current user's authentication status. This usually takes only a few
milliseconds, but if you make decisions that depend on the `isAuthenticated$`
value while `isInitializing$` is still `true`, your code/logic may not work as
you expect.
```jsx theme={null}
import { Component } from '@angular/core';
import { RowndService } from '@rownd/angular';
Component({
selector: 'my-component'
})
export class MyComponent {
constructor(private rownd: RowndService) { }
// isInitializing$ is an observable
this.rownd.isInitializing$
}
```
# Django (Python)
Source: https://docs.rownd.io/sdk-reference/web/django--python
Integrate Rownd instant accounts and authentication into your Django-backed project.
### Installation
Install via pip:
```bash theme={null}
pip install rownd-django
```
Or, add the `rownd-django` package to your dependencies. In `requirements.txt`,
this would look like:
```txt theme={null}
rownd-django>=1.0.0
```
This plugin only works with Django v3 and above. We strongly recommend
upgrading if you're using something older. If you can't for some reason,
please [get in
touch](mailto:support@rownd.io?subject=Django%soSDK:%20Request%20for%20older%20version%20support).
Next, add the Rownd app and authentication backend to your Django `settings.py`
file.
```py theme={null}
INSTALLED_APPS = [
...
'rownd_django',
]
AUTHENTICATION_BACKENDS = [
'rownd_django.auth.backend.RowndAuthenticationBackend',
'django.contrib.auth.backends.ModelBackend'
]
```
If you're using Django REST Framework, then add the Rownd authentication class
to your `REST_FRAMEWORK` settings.
```py theme={null}
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rownd_django.auth.backend.RowndApiAuthentication',
]
}
```
Finally, add your Rownd app credentials to your Django `settings.py` file. You
can obtain these from the [Rownd dashboard](https://app.rownd.io). These
credentials enable the Rownd authentication backend to communicate with the
Rownd API.
```py theme={null}
ROWND = {
'APP_KEY': '',
'APP_SECRET': '',
}
```
#### A note on Google Sign-in
If you plan to use Google sign-in, you'll need to add or update one last configuration item in your
`settings.py` while developing locally without HTTPS connections enabled. Without this setting, the
Google One Tap iframe will not load correctly due to a missing Referrer header.
```
SECURE_REFERRER_POLICY = "no-referrer-when-downgrade"
```
#### Configure the Rownd Hub (required)
Rownd authentication requires a small code snippet to be embedded within your
app, present on all HTML pages. Setup for the Hub/snippet itself is outside the
scope of this document, but you can find the relevant setup guides for either
[single page apps](https://docs.rownd.io/rownd/sdk-reference/web/react-next.js)
or
[traditional web apps via vanilla js](https://docs.rownd.io/rownd/sdk-reference/web/javascript-browser).
Use our SDKs to embed the Hub/snippet in your SPA or use the vanilla JS SDK to
add the snippet in your main Django template HTML.
Now that everything is set up, you can add Rownd authentication to your APIs or
views.
### Usage
The Rownd Django SDK provides support for both "traditional" Django apps where
you have an authentication session that follows a user across page loads, as
well as "single-page" (SPA) Django apps using frameworks like React, Vue, etc.
#### Single-page apps (SPA) / API-based
When using an SPA framework like React, Vue, or similar, you'll likely want to
leverage the specific Rownd SDK for those frameworks. You can find a list of
supported frameworks in
[our documentation](https://docs.rownd.io/rownd/sdk-reference/web).
Typically, an SPA will use an API-driven request/response flow which makes
typical sessions unnecessary (though Rownd supports them if you need them). We
highly recommend the
[Django REST framework](https://www.django-rest-framework.org/) for this
purpose. Rownd provides plug-and-play support for the REST framework's
authentication API.
Here's an example of how you might configure an API to leverage Rownd's
authenticator, given the installation instructions above:
```py theme={null}
from rownd_django.auth.backend import RowndApiAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
class ExampleView(APIView):
authentication_classes = [RowndApiAuthentication]
permission_classes = [IsAuthenticated]
def get(self, request, format=None):
content = {
'user': str(request.user), # `django.contrib.auth.User` instance.
'auth': str(request.auth), # None
}
return Response(content)
```
#### Traditional (non-SPA) apps / session-based
In this flow, once a user has been authenticated with the Rownd Hub, the Hub
will make a request to your app's backend to set up a session for the user.
First, ensure your project has session middleware enabled.
```py theme={null}
MIDDLEWARE = [
...
'django.contrib.sessions.middleware.SessionMiddleware',
...
]
```
Next, include the Rownd `session_authenticator` in your `urls.py` file.
```py theme={null}
urlpatterns = [
...
path('rownd/', include('rownd_django.auth.urls', namespace='rownd')),
...
]
```
Finally, update your Rownd Hub code snippet to fire post-authenticate and post-sign-out API requests
to the session authenticator we just enabled.
```js theme={null}
```
The session authenticator will establish an authenticated session if one doesn't
already exist and will return a response indicating that the Rownd Hub should
trigger a page refresh. This is usually necessary for your app views to display
the desired authenticated context. In the event that an authenticated session
already exists, the Hub will not trigger further page refreshes.
#### CSRF Protection
By default CSRF protection is disabled on the two sign-in and sign-out routes provided by Rownd. If
you would like to enable it on those endpoints, you must ensure all of your sites views contain the
`csrftoken` cookie and update your settings to enable the CSRF protection. You can find more information
on the `csrftoken` cookie [here](https://docs.djangoproject.com/en/4.2/ref/csrf/).
```python theme={null}
ROWND = {
'APP_KEY': '',
'APP_SECRET': '',
'CSRF_PROTECT_ROUTES': True
}
```
# Go
Source: https://docs.rownd.io/sdk-reference/web/go
A comprehensive Go SDK for integrating Rownd authentication, user management, and group management into your applications.
## Installation
```bash theme={null}
go get github.com/rownd/client-go/pkg/rownd
```
## Features
* Token validation and management with EdDSA support
* User authentication and profile management
* Group management with member roles and invites
* HTTP middleware for authentication
* Comprehensive error handling
* Configurable caching for JWKs and WKC
## Quick start
```go theme={null}
package main
import (
"context"
"log"
"github.com/rownd/client-go/pkg/rownd"
)
func main() {
// Initialize client with options
client, err := rownd.NewClient(
rownd.WithAppKey("YOUR_APP_KEY"),
rownd.WithAppSecret("YOUR_APP_SECRET"),
rownd.WithBaseURL("https://api.rownd.io"),
)
if err != nil {
log.Fatal(err)
}
ctx := context.Background()
// Create or update a user
user, err := client.Users.CreateOrUpdate(ctx, rownd.CreateOrUpdateUserRequest{
Data: map[string]interface{}{
"email": "user@example.com",
"first_name": "John",
"last_name": "Doe",
},
})
if err != nil {
log.Fatal(err)
}
log.Printf("User ID: %s", user.GetID())
}
```
## Quick start with examples
### Creating users
```go theme={null}
// Let Rownd generate an ID
user, err := client.Users.CreateOrUpdate(ctx, rownd.CreateOrUpdateUserRequest{
UserID: "__default__", // Special value that tells Rownd to generate a user ID. Can be `__rowndid__`, `__uuid__`, `__objectid__`, or `__default__` for your app's configured default behavior.
Data: map[string]interface{}{
"email": "user@example.com",
"first_name": "John",
"last_name": "Doe",
},
})
// Response:
// user = {
// ID: "user_a7b53gwdaml5jt7t71442nt7",
// State: "enabled",
// AuthLevel: "unverified",
// Data: {
// "email": "user@example.com",
// "first_name": "John",
// "last_name": "Doe",
// "user_id": "user_a7b53gwdaml5jt7t71442nt7"
// }
// }
// Use your own ID
user, err := client.Users.CreateOrUpdate(ctx, rownd.CreateOrUpdateUserRequest{
UserID: "custom_id_12345",
Data: map[string]interface{}{
"email": "user@example.com",
},
})
```
### Searching for users
```go theme={null}
// Lookup by email
users, err := client.Users.List(ctx, rownd.ListUsersRequest{
Fields: []string{"email", "first_name", "last_name", "user_id"}, // Specify fields to return
LookupFilter: []string{"user@example.com"},
})
// Response:
// users = {
// TotalResults: 1,
// Results: [{
// ID: "user_a7b53gwdaml5jt7t71442nt7",
// State: "enabled",
// AuthLevel: "verified",
// Data: {
// "email": "user@example.com",
// "first_name": "John",
// "last_name": "Doe"
// },
// VerifiedData: {
// "email": "user@example.com"
// }
// }]
// }
// Pagination example
users, err := client.Users.List(ctx, rownd.ListUsersRequest{
PageSize: ToPtr(10), // Get 10 results per page
After: ToPtr("user_lastid"), // Start after this user ID
})
```
### Group management examples
```go theme={null}
// Create a group
group, err := client.Groups.Create(ctx, rownd.CreateGroupRequest{
Name: "Engineering Team",
AdmissionPolicy: rownd.AdmissionPolicyInviteOnly,
Meta: map[string]any{
"department": "Engineering",
"cost_center": "ENG-123",
},
})
// Response:
// group = {
// ID: "group_a3l1n2lsnb3q0xbul9enjnh7",
// Name: "Engineering Team",
// AdmissionPolicy: "invite_only",
// Meta: {
// "department": "Engineering",
// "cost_center": "ENG-123"
// },
// CreatedAt: "2024-03-01T12:00:00Z",
// UpdatedAt: "2024-03-01T12:00:00Z"
// }
// Create an invite
invite, err := client.GroupInvites.Create(ctx, rownd.CreateGroupInviteRequest{
GroupID: group.ID,
Email: "new@example.com",
Roles: []string{"member"},
RedirectURL: "/welcome",
})
// Response:
// invite = {
// Link: "https://app.rownd.io/invite/abc123...",
// Invitation: {
// ID: "invite_xyz789",
// GroupID: "group_a3l1n2lsnb3q0xbul9enjnh7",
// Email: "new@example.com",
// Roles: ["member"],
// State: "pending",
// CreatedAt: "2024-03-01T12:01:00Z"
// }
// }
```
### Token validation with claims
```go theme={null}
token, err := client.ValidateToken(ctx, "your-jwt-token")
// Response:
// token = {
// UserID: "user_a7b53gwdaml5jt7t71442nt7",
// AccessToken: "original-jwt-token",
// Claims: {
// Sub: "user_a7b53gwdaml5jt7t71442nt7",
// Iss: "https://api.rownd.io",
// Aud: ["app:app_xyz123"],
// Exp: 1709312400,
// Iat: 1709308800,
// AppUserID: "user_a7b53gwdaml5jt7t71442nt7",
// IsUserVerified: true,
// IsAnonymous: false,
// AuthLevel: "verified"
// }
// }
```
### Helpful utilities
```go theme={null}
// Convert values to pointers (useful for optional fields)
pageSize := rownd.ToPtr(10)
after := rownd.ToPtr("some_id")
// Get value from pointer with fallback
value := rownd.ToValue(optionalPtr) // Returns actual value or zero value if nil
// Extract token from context (in HTTP handlers)
token := rownd.TokenFromCtx(r.Context())
if token != nil {
userID := token.UserID
authLevel := token.Claims.AuthLevel
}
```
## Authentication & token validation
### Token validation
```go theme={null}
// Validate a token
token, err := client.ValidateToken(ctx, "your-jwt-token")
if err != nil {
log.Fatal(err)
}
// Access token claims
log.Printf("User ID: %s", token.UserID)
log.Printf("Auth Level: %s", token.Claims.AuthLevel)
```
### HTTP middleware
```go theme={null}
import "github.com/rownd/client-go/pkg/rownd/middleware"
// Create middleware handler
handler, err := rowndmiddleware.NewHandler(client,
rowndmiddleware.WithErrorHandler(func(w http.ResponseWriter, r *http.Request, err error) {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
}),
)
// Use middleware
router.Use(rowndmiddleware.WithAuthentication(handler))
```
## User management
### User operations (CRUD)
```go theme={null}
// Get user
user, err := client.Users.Get(ctx, rownd.GetUserRequest{
UserID: "user_id",
})
// List/lookup users
users, err := client.Users.List(ctx, rownd.ListUsersRequest{
Fields: []string{"email", "first_name", "last_name"},
LookupFilter: []string{"user@example.com"},
})
// Delete user
err := client.Users.Delete(ctx, rownd.DeleteUserRequest{
UserID: "user_id",
})
```
## Group management
### Groups
```go theme={null}
// Create group
group, err := client.Groups.Create(ctx, rownd.CreateGroupRequest{
Name: "Engineering Team",
AdmissionPolicy: rownd.AdmissionPolicyInviteOnly,
Meta: map[string]any{
"department": "Engineering",
},
})
// List groups
groups, err := client.Groups.List(ctx, rownd.ListGroupsRequest{})
// Delete group
err := client.Groups.Delete(ctx, rownd.DeleteGroupRequest{
GroupID: "group_id",
})
```
### Group invites
```go theme={null}
// Create invite
invite, err := client.GroupInvites.Create(ctx, rownd.CreateGroupInviteRequest{
GroupID: "group_id",
Email: "new@example.com",
Roles: []string{"member"},
RedirectURL: "/welcome",
})
// List invites
invites, err := client.GroupInvites.List(ctx, rownd.ListGroupInvitesRequest{
GroupID: "group_id",
})
// Delete invite
err := client.GroupInvites.Delete(ctx, rownd.DeleteGroupInviteRequest{
GroupID: "group_id",
InviteID: "invite_id",
})
```
## Group membership management
### The difference between Group IDs and User IDs
In Rownd's group system, there are two important identifiers:
* `user_id`: The unique identifier for a Rownd user (e.g., "user\_a7b53gwdaml5jt7t71442ng7")
* `member_id`: The unique identifier for a user's membership in a specific group (e.g., "member\_dnn5g4e3q5aptail2gr43kpj")
A single user can be a member of multiple groups, with a different `member_id` for each group membership.
```go theme={null}
// Example group member structure
type GroupMember struct {
ID string `json:"id"` // This is the member_id
UserID string `json:"user_id"` // This is the user_id
Roles []string `json:"roles"`
State string `json:"state"`
Profile map[string]interface{} `json:"profile"`
GroupID string `json:"group_id"`
}
```
### Managing group members
```go theme={null}
// Add a user to a group
member, err := client.GroupMembers.Create(ctx, rownd.CreateGroupMemberRequest{
GroupID: "group_a3l1n2lsnb3q0xbul9enjnh7",
UserID: "user_a7b53gwdaml5jt7t71442nt7",
Roles: []string{"editor", "viewer"},
})
// Response:
// member = {
// ID: "member_dnn5g4e3q6aptail2gr43kpj", // The member_id
// UserID: "user_a7b53gwdaml5jt7t71442nt7", // The user_id
// Roles: ["editor", "viewer"],
// State: "active",
// Profile: {
// "email": "user@example.com",
// "first_name": "John"
// },
// GroupID: "group_a3l1n2lsnb3q0xbul9enjnh7"
// }
// Update a member's roles using member_id
updatedMember, err := client.GroupMembers.Update(ctx, rownd.UpdateGroupMemberRequest{
GroupID: "group_a3l1n2lsnb3q0xbul9enjnh7",
MemberID: "member_dnn5g4e3q6aptail2gr43kpj", // Use member_id, not user_id
Roles: []string{"admin"},
})
// List group members
members, err := client.GroupMembers.List(ctx, rownd.ListGroupMembersRequest{
GroupID: "group_a3l1n2lsnb3q0xbul9enjnh7",
})
// Response:
// members = {
// TotalResults: 2,
// Results: [{
// ID: "member_dnn5g4e3q6aptail2gr43kpj",
// UserID: "user_a7b53gwdaml5jt7t71442nt7",
// Roles: ["admin"],
// State: "active",
// Profile: {
// "email": "user@example.com"
// }
// }, {
// ID: "member_kll8h7g2p9qbxyzw4m5njth8",
// UserID: "user_b8c64hwdaml5kt8u82553ou8",
// Roles: ["viewer"],
// State: "active",
// Profile: {
// "email": "another@example.com"
// }
// }]
// }
// Remove a member from a group using member_id
err := client.GroupMembers.Delete(ctx, rownd.DeleteGroupMemberRequest{
GroupID: "group_a3l1n2lsnb3q0xbul9enjnh7",
MemberID: "member_dnn5g4e3q6aptail2gr43kpj", // Use member_id, not user_id
})
```
### Important notes about group membership
1. **Member ID vs User ID**
* Use `member_id` when managing a specific membership (updating roles, removing from group)
* Use `user_id` when adding a new member to a group
* A user (`user_id`) can have multiple memberships (`member_id`s) across different groups
2. **Group Ownership**
* Groups must always have at least one owner
* When removing the last owner, transfer ownership first
* Example of transferring ownership:
```go theme={null}
// Transfer ownership before removing the last owner
_, err = client.GroupMembers.Update(ctx, rownd.UpdateGroupMemberRequest{
GroupID: "group_id",
MemberID: "new_owner_member_id",
Roles: []string{"owner", "member"},
})
```
3. **Member States**
* `active`: Normal membership
* `suspended`: Temporarily restricted access
* `invited`: Pending acceptance of invitation
4. **Common Role Types**
* `owner`: Full administrative control
* `admin`: Can manage members and content
* `editor`: Can modify content
* `viewer`: Read-only access
* Custom roles can be defined as needed
## Group ownership and member management rules
### Group ownership rules
1. **Automatic owner assignment**
* The first member added to a group automatically receives the "owner" role
* Example of first member creation:
```go theme={null}
// First member automatically becomes owner
member, err := client.GroupMembers.Create(ctx, rownd.CreateGroupMemberRequest{
GroupID: "group_id",
UserID: "user_id",
Roles: []string{"member"}, // "owner" will be automatically added
})
// Response:
// member = {
// ID: "member_abc123",
// UserID: "user_id",
// Roles: ["owner", "member"], // Note: "owner" was automatically added
// State: "active"
// }
```
2. **Owner requirements**
* Every group must maintain at least one owner at all times
* Attempting to remove the last owner will result in an error
```go theme={null}
// This will fail if it's the last owner
err := client.GroupMembers.Delete(ctx, rownd.DeleteGroupMemberRequest{
GroupID: "group_id",
MemberID: "last_owner_member_id", // Will return error if last owner
})
```
3. **Group deletion requirements**
* A group must have at least one member. To remove all members, delete the group.
* Correct order of operations:
```go theme={null}
// Correct order: Delete group first, which removes all members
err := client.Groups.Delete(ctx, rownd.DeleteGroupRequest{
GroupID: "group_id",
})
// Incorrect: Will fail if trying to remove last member while group exists
err := client.GroupMembers.Delete(ctx, rownd.DeleteGroupMemberRequest{
GroupID: "group_id",
MemberID: "last_member_id", // Will return error
})
```
## Error handling
The SDK provides structured error types for better error handling:
```go theme={null}
if err != nil {
switch e := err.(type) {
case *rownd.Error:
switch e.Kind {
case rownd.ErrAuthentication:
log.Printf("Authentication error: %v", e)
case rownd.ErrValidation:
log.Printf("Validation error: %v", e)
case rownd.ErrAPI:
log.Printf("API error: %v", e)
case rownd.ErrNetwork:
log.Printf("Network error: %v", e)
case rownd.ErrNotFound:
log.Printf("Not found error: %v", e)
}
case *rownd.MultiError:
log.Printf("Multiple errors occurred: %v", e)
default:
log.Printf("Unknown error: %v", err)
}
}
```
## Configuration options
### Client options
```go theme={null}
client, err := rownd.NewClient(
rownd.WithAppKey("key"),
rownd.WithAppSecret("secret"),
rownd.WithBaseURL("https://api.rownd.io"),
rownd.WithWKCCacheDuration(time.Hour),
rownd.WithJWKsCacheDuration(time.Hour),
)
```
### Request options
```go theme={null}
client.Users.Get(ctx, request,
rownd.RequestWithHeader("X-Custom-Header", "value"),
)
```
## Testing
Run all tests:
```bash theme={null}
go test ./...
```
Run specific tests:
```bash theme={null}
go test -v ./... -run TestRowndUsers
```
Run with timeout:
```bash theme={null}
go test -v ./... -timeout 30s
```
## Types reference
### Auth levels
```go theme={null}
const (
AuthLevelInstant AuthLevel = "instant"
AuthLevelUnverified AuthLevel = "unverified"
AuthLevelGuest AuthLevel = "guest"
AuthLevelVerified AuthLevel = "verified"
)
```
### Group admission policies
```go theme={null}
const (
AdmissionPolicyInviteOnly AdmissionPolicy = "invite_only"
AdmissionPolicyOpen AdmissionPolicy = "open"
)
```
## Environment setup
### Using environment variables
Create a `.env` file in your project root:
```env theme={null}
# .env
ROWND_APP_KEY=key_bd81v4usfn4c9wh6i83c13ak
ROWND_APP_SECRET=ras_32769e81.0.002bc537079f78d4bc890214fd85c63b313c0
ROWND_APP_ID=app_xkbuml48qs3tyxxjjpaxeemv
ROWND_BASE_URL=https://api.rownd.io
```
Load environment variables in your code:
```go theme={null}
package main
import (
"github.com/joho/godotenv"
"github.com/rownd/client-go/pkg/rownd"
"log"
"os"
)
func main() {
// Load .env file
if err := godotenv.Load(); err != nil {
log.Printf("Warning: .env file not found")
}
// Initialize client with environment variables
client, err := rownd.NewClient(
rownd.WithAppKey(os.Getenv("ROWND_APP_KEY")),
rownd.WithAppSecret(os.Getenv("ROWND_APP_SECRET")),
rownd.WithBaseURL(os.Getenv("ROWND_BASE_URL")),
)
if err != nil {
log.Fatal(err)
}
}
```
### Environment Files
1. Add `.env` to your `.gitignore`:
```gitignore theme={null}
# .gitignore
.env
```
2. For testing, create a separate `.env.test`:
```env theme={null}
# .env.test
ROWND_TEST_APP_KEY=test_key_here
ROWND_TEST_APP_SECRET=test_secret_here
ROWND_TEST_APP_ID=test_app_id_here
ROWND_TEST_BASE_URL=https://api.rownd.io
```
3. Load different env files based on environment:
```go theme={null}
func loadEnv() {
env := os.Getenv("GO_ENV")
if env == "test" {
godotenv.Load(".env.test")
}
}
```
## License
This project is licensed under the MIT License - see the LICENSE file for details.
# HTML Hooks
Source: https://docs.rownd.io/sdk-reference/web/html
## Installation
Please reference one of Rownd's other [Web SDKs](/sdk-reference/web/overview) for instructions on installing Rownd onto your site or web app. The HTML Hooks functionality is available with any or our web SDKs.
## HTML Hooks
The Rownd Hub supports various hooks that can be used to modify the behavior of
content on a page. These are controlled by
[HTML data attributes](https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use%5Fdata%5Fattributes).
The following attribute hooks are supported.
## Sign in / sign up buttons / triggers
### `data-rownd-sign-in-trigger`
Attach to a clickable control (e.g., `` or `