# Moov Documentation (full) > Complete documentation content for LLM consumption. > Source: https://docs.moov.io --- URL: https://docs.moov.io/404/ --- # Page not found --- URL: https://docs.moov.io/api/authentication/access-tokens/create/ --- # Create an access token --- URL: https://docs.moov.io/api/authentication/access-tokens/ --- # Access tokens --- URL: https://docs.moov.io/api/authentication/access-tokens/revoke/ --- # Revoke an access token --- URL: https://docs.moov.io/api/authentication/api-authentication/ --- # Authentication options With a server-side integration, you are responsible for directly handling and storing sensitive user information. With a client-side integration, you can use Moov.js and server-generated access tokens to transmit data from your user directly to Moov. ## [Server-side: Basic authentication](#server-side-basic-authentication) You can use your API key's public and private keys with Basic authentication. Set the `Authorization` header to `Basic `, where credentials is the Base64 encoding of public key and private key joined by a single colon `:`. Only use this method if you are developing a server-side integration. If you are developing a client-side integration, use [OAuth](#client-side-oauth-with-jwt) instead. * * * ## [Client-side: OAuth with JWT](#client-side-oauth-with-jwt) You can set up authentication with [OAuth](/api/authentication/access-tokens) and initialize [Moov.js](/moovjs/) in your application. When making requests to Moov from a browser, you can use OAuth with JSON Web Tokens (JWT). ### [Understand scopes](#understand-scopes) A scope is a permission that limits how a specific account can interact with another account. The rest of this guide will reference various scopes that are required for specific actions via Moov.js or any client-side integration. | Scope | Description | |----------------------------------------------|--------------------------------------------------------------------------| | `/accounts.write` | Allows a new Moov account to be created, and view all connected accounts | | `/accounts/{accountID}/bank-accounts.write` | Access to view or add a linked bank account to a Moov account | | `/accounts/{accountID}/cards.write` | Access to view or add a linked cards to a Moov account | | `/accounts/{accountID}/payment-methods.read` | Access to view payment methods for the account specified | For the full list of scopes, read the [scopes](/api/authentication/scopes/) documentation. ### [Create an access token](#create-an-access-token) Within your server-side application, you’ll generate a single-use access token containing information needed to communicate with your Moov account securely. Once you’ve generated this token, you can send it back to your client to use with Moov.js. For each action you take you will need a unique short lived access token. The example below generates a token that can create a new account. Moov.js requires the `/accounts.write` scope. [cURL](#tab-549368721-2-0) ```zsh curl -X POST "https://api.moov.io/oauth2/token" \ -u "PUBLIC_KEY:PRIVATE_KEY" \ --data '{ "grant_type":"client_credentials", "client_id":"5clTR_MdVrrkgxw2", "client_secret":"dNC-hg7sVm22jc3g_Eogtyu0_1Mqh_4-", "scope":"/accounts.write", "refresh_token":"i1qxz68gu50zp4i8ceyxqogmq7y0yienm52351c6..." }'\ ``` --- URL: https://docs.moov.io/api/authentication/e2ee/create/ --- # Generate a public key --- URL: https://docs.moov.io/api/authentication/e2ee/ --- # End-to-end encryption --- URL: https://docs.moov.io/api/authentication/e2ee/test/ --- # Test JWE token --- URL: https://docs.moov.io/api/authentication/ --- # Authentication --- URL: https://docs.moov.io/api/authentication/scopes/ --- # Scopes Moov follows the OAuth2 protocol authentication flow. This guide provides the complete list of scopes and guidance for using them. If you're using Moov.js or any client-side integration, you'll need to set scopes. Scopes specify what actions an account can take. When generating an OAuth2 access token, you'll include the name of the scope that covers the type of access needed. You will then use a generated token for each API call you make. ![](https://fast.wistia.com/embed/medias/erk98x51xc/swatch) ## [Account-restricted scopes](#account-restricted-scopes) Some scopes are not restricted to a single account: - `/ping.read`: lets you call `GET /ping` to make sure the API is responding - `/accounts.write`: lets you call `POST /accounts` to create a new user account Other scopes are restricted to a single account, meaning you'll need the account ID *before* you generate the token: - `/accounts/{accountID}/profile.write`: lets you call `PUT /accounts/{accountID}` to update that account's profile, metadata, or other properties - `/accounts/{accountID}/wallets.read`: lets you call `GET /accounts/{accountID}/wallets/{walletID}` to see the balance in that wallet ## [Generating multiple tokens](#generating-multiple-tokens) If you already have an account ID and have a simple task to accomplish, you can generate a single OAuth token with a space-delimited list of the required scopes. For example, if you need to read an account's profile for display, update some of its properties, and create a transfer, you'll generate a single OAuth token with these scopes: - `/accounts/{accountID}/profile.read` - `/accounts/{accountID}/profile.write` - `/accounts/{accountID}/transfers.write` If haven't retrieved an account ID, or have a more complex task to accomplish, then you'll need to generate more than one OAuth token. If you're trying to accomplish the same set of tasks as above, but you need to create the account first, you'll generate two OAuth tokens with these scopes: - First token - `/accounts.write` - Second token - `/accounts/{accountID}/profile.read` - `/accounts/{accountID}/profile.write` - `/accounts/{accountID}/transfers.write` You'll use the first token to call `POST /account`, which will return the ID of the new account. Use that account ID to construct the scopes for the second token. ## [Available scopes](#available-scopes) The account ID for transfers related scopes should be the **platform** account ID. The account ID for all other scopes will be the **user's** account ID. | Scope | Description | |---------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------| | `/accounts.write`, `/accounts.read` | Allows a new Moov account to be created, and view all connected user accounts | | `/accounts/{accountID}/bank-accounts.read`, `/accounts/{accountID}/bank-accounts.write` | Access to view or add a linked bank account to a Moov account | | `/accounts/{accountID}/cards.read`, `/accounts/{accountID}/cards.write` | Access to view or add a linked cards to a Moov account | | `/accounts/{accountID}/capabilities.read`, `/accounts/{accountID}/capabilities.write` | Access to request or view capabilities, determining what actions the account can do | | `/accounts/{accountID}/documents.read`, `/accounts/{accountID}/documents.write` | Access to view or upload documents (like I-9s, W-4s) associated with a Moov account | | `/accounts/{accountID}/files.read`, `/accounts/{accountID}/files.write` | Access to view or upload files associated with a Moov account | | `/accounts/{accountID}/payment-methods.read` | Access to view payment methods for the account specified | | `/accounts/{accountID}/profile-enrichment.read` | Access to view a Moov account's profile image | | `/accounts/{accountID}/profile.read`, `/accounts/{accountID}/profile.write` | Access to view or edit details associated with a Moov account | | `/accounts/{accountID}/representatives.read`, `/accounts/{accountID}/representatives.write` | Access to view or add details on business representatives for a Moov account | | `/accounts/{accountID}/transfers.write`, `/accounts/{accountID}/transfers.read` | Access to move money by creating transfers | | `/accounts/{accountID}/wallets.read` | Access to view the balance on an account's Moov wallet | | `/accounts/{accountID}/wallets.write` | Access to manage an account's Moov wallet | | `/accounts/{accountID}/apple-pay.write` | Allows a developer to add or remove an Apple Pay domain | | `/accounts/{accountID}/apple-pay.read` | Allows a developer to retrieve registered Apple Pay domains | | `/fed.read` | Allows a developer to use the institutions lookup service to look up a bank name by routing number | | `/ping.read` | Allows a developer to test and confirm they are able to hit one of Moov's services | --- URL: https://docs.moov.io/api/enrichment/branding/create/ --- # Create brand --- URL: https://docs.moov.io/api/enrichment/branding/get/ --- # Get brand --- URL: https://docs.moov.io/api/enrichment/branding/ --- # Branding Get and set brand colors for light and dark modes. Used in Moov hosted UIs. --- URL: https://docs.moov.io/api/enrichment/branding/patch/ --- # Update brand --- URL: https://docs.moov.io/api/enrichment/branding/put/ --- # Create or replace brand --- URL: https://docs.moov.io/api/enrichment/form-shortening/address/get/ --- # Address autocomplete --- URL: https://docs.moov.io/api/enrichment/form-shortening/avatars/get/ --- # Get avatar --- URL: https://docs.moov.io/api/enrichment/form-shortening/business/get/ --- # Enrich a business profile --- URL: https://docs.moov.io/api/enrichment/form-shortening/ --- # Form shortening Find publicly available information to autofill form fields based on an email address. If available, the response includes details about the individual and/or business tied to the email address. The following utilities require less input from your users and reduce mistakes. --- URL: https://docs.moov.io/api/enrichment/form-shortening/industries/get/ --- # List industries --- URL: https://docs.moov.io/api/enrichment/form-shortening/institutions/get-ach/ --- # Look up bank by routing number --- URL: https://docs.moov.io/api/enrichment/ --- # Enrichment --- URL: https://docs.moov.io/api/enrichment/institutions/get/ --- # Look up financial institutions --- URL: https://docs.moov.io/api/enrichment/institutions/ --- # Institutions Validate a financial institution before initiating payment activity, or check which payment rails are available for a given routing number. Use this information to autofill form fields. --- URL: https://docs.moov.io/api/errors/ --- # Error handling After you submit an API call to Moov, you receive an HTTP response indicating whether or not the call was successful. This guide summarizes the various error codes you may see for transfers, capabilities, card acceptance, and bank accounts. Across all endpoints, you'll typically see the following response statuses: - `2xx` responses for successful API calls - `4xx` responses for errors with the input - `5xx` Moov is in a degraded state; extremely rare ## [Transfers](#transfers) | HTTP status code | HTTP status message | Description | Error handling guidance | |------------------|-----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 201 | Created | Transfer was successfully created but an error occurred while getting the synchronous response. The asynchronous response object will be returned. | Moov's internal services are in a degraded state and are unable to return the full transfer object as a response. The transfer was created but we aren't able to generate a synch response so we return the async response here. You can attempt GET the transfer using the ID that's returned. Note that if Moov's services are still degraded, you will not be able to get the response if you attempted to use the transfer `GET` [endpoint](/api/money-movement/transfers/get/) right after creating the transfer. | | 202 | Accepted | A transfer or refund was successfully created but a timeout occurred while waiting for a synchronous response. Rail-specific details may be missing from the response object. | A timeout occurred with the payment network. To retrieve full rail-specific details at a later time, use the transfer GET endpoint. | | 400 | Bad request | Invalid request, an error message will be available in the response body. | There was a problem with the request payload. The error message will provide specific details on what needs to be fixed. | | 409 | Conflict | Attempted to create a transfer using duplicate X-Idempotency-Key header | Retry the request with a different X-Idempotency-Key header. | | 422 | Unprocessable content | The request body could not be processed | The error message will let you know how long to wait (in milliseconds) before you can retry | | 429 | Too many requests | Request was refused due to rate limiting | The error message will let you know how long to wait (in milliseconds) before you can retry | ## [Accounts](#accounts) | HTTP status code | HTTP status messsage | Description | Error handling guidance | |------------------|-----------------------|----------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 404 | Not found | No account with the specified account ID was found | Double check the account ID and retry | | 422 | Unprocessable content | The request body could not be processed | There was a problem with the request payload. Check for required headers, whether or not you're using a duplicate ID, and that you're using a valid account type. The error message will provide specific details on what needs to be fixed. | | 429 | Too many requests | Request was refused due to rate limiting | The error message will let you know how long to wait (in milliseconds) before you can retry | ## [Capabilities](#capabilities) | HTTP status code | HTTP status messsage | Description | Error handling guidance | |------------------|----------------------|-------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 404 | Not found | No account with the specified account ID was found | Double check the account ID and retry. | | 409 | Conflict | The request could not be completed due to a state conflict with the target resource | There are [capability requirements](/guides/accounts/capabilities/requirements/) that have not yet been met or incomplete KYC [verification](/guides/accounts/requirements/identity-verification/). The error message will provide specific details about which requirements have not yet been met. | | 429 | Too many requests | Request was refused due to rate limiting | The error message will let you know how long to wait (in milliseconds) before you can retry. | ## [Card acceptance](#card-acceptance) | HTTP status code | HTTP status message | Description | Error handling guidance | |------------------|-----------------------|------------------------------------------------------------------|---------------------------------------------------------------------------------------------| | 404 | Not found | No account with the specified account ID was found | Double check the account ID and retry | | 409 | Conflict | Attempted to link card that already exists on the account | Double check the card number you were trying to link | | 422 | Unprocessable content | The supplied card appeared invalid or was declined by the issuer | Double check the card number you were trying to link or get in contact with the card issuer | | 429 | Too many requests | Request was refused due to rate limiting | The error message will let you know how long to wait (in milliseconds) before you can retry | ## [Bank accounts](#bank-accounts) | HTTP status code | HTTP status message | Description | Error handling guidance | |------------------|-----------------------|----------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------| | 404 | Not found | No account with the specified account ID was found | Double check the account ID and retry | | 409 | Conflict | Unable to get bank name for routing number or duplicate bank account | Double check the routing number provided | | 422 | Unprocessable content | The request body could not be processed | There was a problem with the request payload. The error message will provide specific details on what needs to be fixed | | 429 | Too many requests | Request was refused due to rate limiting | The error message will let you know how long to wait (in milliseconds) before you can retry | * * * [Rate limits](/api/rate-limits) --- URL: https://docs.moov.io/api/ --- # API reference API version `latest` will no longer be updated and is removed from our public documentation. If you are using `latest`, update immediately. Moov suggest all users move to `2026.01.00` at this time. Moov is a platform that enables developers to integrate all aspects of money movement with ease and speed. The Moov API makes it simple for platforms to send, receive, and store money. Our API is based upon REST principles, returns JSON responses, and uses standard HTTP response codes. Base URL https://api.moov.io To integrate it into your application, you can use the JSON HTTP API or one of the Moov libraries (depending on your programming language or framework). Use the dropdown menu to select the version of the API you would like to view. Send the API version you want to use in the header with your request. For example: ```zsh curl -X POST "https://api.moov.io/accounts/" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version": "v2026.01.00" \ ``` Moov suggests all new users start with `v2026.01.00`. If you don't include a version header in your request, Moov defaults to `v2024.01.00`. ## [Server-side SDKs](#server-side-sdks) [moovfinancial/ \ moov-dotnet](/sdks/dotnet/) [moovfinancial/ \ moov-go](/sdks/go/) [moovfinancial/ \ moov-java](/sdks/java/) [moovfinancial/ \ moov-php](/sdks/php/) [moovfinancial/ \ moov-python](/sdks/python/) [moovfinancial/ \ moov-ruby](/sdks/ruby/) [moovfinancial/ \ moov-android](/sdks/tap-to-pay-android/) [moovfinancial/ \ moov-ios](/sdks/tap-to-pay-iphone/) [moovfinancial/ \ moov-typescript](/sdks/typescript/) [**Postman collection** \ Explore a Postman collection with example calls to our API.](/guides/developer-tools/postman-collection/) [**Breaking changes** \ How Moov treats changes to the API.](/guides/developer-tools/breaking-changes-api/) --- URL: https://docs.moov.io/api/money-movement/disputes/delete/ --- # Delete dispute evidence --- URL: https://docs.moov.io/api/money-movement/disputes/get-evidence-data/ --- # Get dispute evidence data --- URL: https://docs.moov.io/api/money-movement/disputes/get-evidence/ --- # Get dispute evidence --- URL: https://docs.moov.io/api/money-movement/disputes/get/ --- # Retrieve a dispute --- URL: https://docs.moov.io/api/money-movement/disputes/ --- # Disputes --- URL: https://docs.moov.io/api/money-movement/disputes/list-evidence/ --- # List dispute evidence --- URL: https://docs.moov.io/api/money-movement/disputes/list/ --- # List disputes --- URL: https://docs.moov.io/api/money-movement/disputes/patch/ --- # Update dispute evidence --- URL: https://docs.moov.io/api/money-movement/disputes/post-evidence/ --- # Submit dispute evidence --- URL: https://docs.moov.io/api/money-movement/disputes/post-file/ --- # Upload evidence file --- URL: https://docs.moov.io/api/money-movement/disputes/post/ --- # Accept dispute --- URL: https://docs.moov.io/api/money-movement/disputes/post-text/ --- # Upload evidence text --- URL: https://docs.moov.io/api/money-movement/ --- # Money movement --- URL: https://docs.moov.io/api/money-movement/issuing/create/ --- # Create a spending card --- URL: https://docs.moov.io/api/money-movement/issuing/get-authorization/ --- # Get authorization --- URL: https://docs.moov.io/api/money-movement/issuing/get-card-transaction/ --- # Get card transaction --- URL: https://docs.moov.io/api/money-movement/issuing/get-details/ --- # Get PCI details for a spending card --- URL: https://docs.moov.io/api/money-movement/issuing/get/ --- # Retrieve a spending card --- URL: https://docs.moov.io/api/money-movement/issuing/ --- # Card issuing --- URL: https://docs.moov.io/api/money-movement/issuing/list-authorization-events/ --- # List authorization events --- URL: https://docs.moov.io/api/money-movement/issuing/list-authorizations/ --- # List authorizations --- URL: https://docs.moov.io/api/money-movement/issuing/list-card-transactions/ --- # List card transactions --- URL: https://docs.moov.io/api/money-movement/issuing/list/ --- # List spending cards --- URL: https://docs.moov.io/api/money-movement/issuing/update/ --- # Update a spending card --- URL: https://docs.moov.io/api/money-movement/payment-links/create/ --- # Create payment link --- URL: https://docs.moov.io/api/money-movement/payment-links/delete/ --- # Disable payment link --- URL: https://docs.moov.io/api/money-movement/payment-links/get/ --- # Get payment link --- URL: https://docs.moov.io/api/money-movement/payment-links/get-qrcode/ --- # Get payment link QR code --- URL: https://docs.moov.io/api/money-movement/payment-links/ --- # Payment links Payment links offer a no-code way to accept or send payments online. You can create a payment link and share it with your customers via email, SMS, or social media. When your customers click on the link, they can accept or pay using a credit card, debit card, or bank account. --- URL: https://docs.moov.io/api/money-movement/payment-links/list/ --- # List payment links --- URL: https://docs.moov.io/api/money-movement/payment-links/update/ --- # Update payment link --- URL: https://docs.moov.io/api/money-movement/receipts/create/ --- # Create receipts --- URL: https://docs.moov.io/api/money-movement/receipts/ --- # Receipts --- URL: https://docs.moov.io/api/money-movement/receipts/list/ --- # List receipts --- URL: https://docs.moov.io/api/money-movement/refunds/cancel/ --- # Cancel or refund a card transfer --- URL: https://docs.moov.io/api/money-movement/refunds/create/ --- # Create a refund --- URL: https://docs.moov.io/api/money-movement/refunds/get/ --- # Retrieve refund --- URL: https://docs.moov.io/api/money-movement/refunds/ --- # Refunds --- URL: https://docs.moov.io/api/money-movement/refunds/list/ --- # List refunds --- URL: https://docs.moov.io/api/money-movement/schedules/create/ --- # Create a schedule --- URL: https://docs.moov.io/api/money-movement/schedules/delete/ --- # Cancel schedule --- URL: https://docs.moov.io/api/money-movement/schedules/get/ --- # Get a schedule --- URL: https://docs.moov.io/api/money-movement/schedules/get-occurence/ --- # Get an occurrence --- URL: https://docs.moov.io/api/money-movement/schedules/ --- # Scheduled transfers --- URL: https://docs.moov.io/api/money-movement/schedules/list/ --- # List schedules --- URL: https://docs.moov.io/api/money-movement/schedules/update/ --- # Update a schedule --- URL: https://docs.moov.io/api/money-movement/sweeps/create-config/ --- # Create a sweep config --- URL: https://docs.moov.io/api/money-movement/sweeps/get-config/ --- # Get a sweep config --- URL: https://docs.moov.io/api/money-movement/sweeps/get/ --- # Get a sweep --- URL: https://docs.moov.io/api/money-movement/sweeps/ --- # Sweeps Use the API or the [Moov Dashboard](https://dashboard.moov.io/signin) to configure sweeps. A sweep automatically initiates daily transfers to external bank accounts on a set schedule. Enabling sweeps will either payout funds from a wallet or pull funds to cover fees and chargebacks. You have the option to choose which payment method to use for processing sweeps - standard ACH, same-day ACH, or RTP. | Push payment method | Receive funds by | |-----------------------|---------------------| | `ach-credit-same-day` | 6 pm ET | | `ach-credit-standard` | 10 am ET (next day) | | `rtp-credit` | Instant | See our [sweeps](/guides/money-movement/wallets/sweeps/) documentation for more details. --- URL: https://docs.moov.io/api/money-movement/sweeps/list-configs/ --- # List sweep configs --- URL: https://docs.moov.io/api/money-movement/sweeps/list/ --- # List sweeps --- URL: https://docs.moov.io/api/money-movement/sweeps/patch-config/ --- # Update a sweep config --- URL: https://docs.moov.io/api/money-movement/transfers/cancel-details/ --- # Get cancellation details --- URL: https://docs.moov.io/api/money-movement/transfers/cancel/ --- # Cancel a transfer --- URL: https://docs.moov.io/api/money-movement/transfers/create/ --- # Create a transfer --- URL: https://docs.moov.io/api/money-movement/transfers/create-receipts/ --- # Create receipts --- URL: https://docs.moov.io/api/money-movement/transfers/get/ --- # Retrieve a transfer --- URL: https://docs.moov.io/api/money-movement/transfers/ --- # Transfers --- URL: https://docs.moov.io/api/money-movement/transfers/list/ --- # List transfers --- URL: https://docs.moov.io/api/money-movement/transfers/list-receipts/ --- # List receipts --- URL: https://docs.moov.io/api/money-movement/transfers/options/ --- # Retrieve transfer options --- URL: https://docs.moov.io/api/money-movement/transfers/patch/ --- # Update transfer metadata --- URL: https://docs.moov.io/api/moov-accounts/accounts/create/ --- # Create an account --- URL: https://docs.moov.io/api/moov-accounts/accounts/delete/ --- # Delete an account --- URL: https://docs.moov.io/api/moov-accounts/accounts/get/ --- # Retrieve an account --- URL: https://docs.moov.io/api/moov-accounts/accounts/get-tos/ --- # Generate a terms of service token --- URL: https://docs.moov.io/api/moov-accounts/accounts/ --- # Accounts --- URL: https://docs.moov.io/api/moov-accounts/accounts/list-connections/ --- # List connected accounts --- URL: https://docs.moov.io/api/moov-accounts/accounts/list/ --- # List accounts --- URL: https://docs.moov.io/api/moov-accounts/accounts/patch/ --- # Update an account --- URL: https://docs.moov.io/api/moov-accounts/accounts/share-connection/ --- # Share account connection --- URL: https://docs.moov.io/api/moov-accounts/billing/create-agreement/ --- # Create fee plan agreement --- URL: https://docs.moov.io/api/moov-accounts/billing/get-fees/ --- # Retrieve fees for an account --- URL: https://docs.moov.io/api/moov-accounts/billing/get-statement/ --- # Get statement --- URL: https://docs.moov.io/api/moov-accounts/billing/ --- # Billing --- URL: https://docs.moov.io/api/moov-accounts/billing/list-agreements/ --- # List fee agreements for an account --- URL: https://docs.moov.io/api/moov-accounts/billing/list-fees/ --- # List fees for an account --- URL: https://docs.moov.io/api/moov-accounts/billing/list-plans/ --- # List fees plans --- URL: https://docs.moov.io/api/moov-accounts/billing/list-statements/ --- # List statements --- URL: https://docs.moov.io/api/moov-accounts/capabilities/delete/ --- # Disable a capability --- URL: https://docs.moov.io/api/moov-accounts/capabilities/get/ --- # Retrieve a capability --- URL: https://docs.moov.io/api/moov-accounts/capabilities/ --- # Capabilities --- URL: https://docs.moov.io/api/moov-accounts/capabilities/list/ --- # List capabilities for an account --- URL: https://docs.moov.io/api/moov-accounts/capabilities/post/ --- # Request capabilities --- URL: https://docs.moov.io/api/moov-accounts/files/get/ --- # Retrieve file details --- URL: https://docs.moov.io/api/moov-accounts/files/ --- # Files --- URL: https://docs.moov.io/api/moov-accounts/files/list/ --- # List files --- URL: https://docs.moov.io/api/moov-accounts/files/post/ --- # Upload file --- URL: https://docs.moov.io/api/moov-accounts/ --- # Moov accounts --- URL: https://docs.moov.io/api/moov-accounts/onboarding/delete/ --- # Revoke onboarding invite --- URL: https://docs.moov.io/api/moov-accounts/onboarding/get/ --- # Get onboarding invite --- URL: https://docs.moov.io/api/moov-accounts/onboarding/ --- # Onboarding --- URL: https://docs.moov.io/api/moov-accounts/onboarding/list/ --- # List onboarding invites --- URL: https://docs.moov.io/api/moov-accounts/onboarding/post/ --- # Create onboarding invite --- URL: https://docs.moov.io/api/moov-accounts/partner-billing/get-residuals/ --- # Get residuals --- URL: https://docs.moov.io/api/moov-accounts/partner-billing/ --- # Partner billing A partner is a contracted business entity that uses Moov's platform to facilitate transfer solutions for merchants and connected accounts. Partner accounts are typically platforms, SaaS providers, or marketplaces which integrate with Moov’s API. The partner billing endpoints can only be used with a partner's `accountID`. To find your partner account ID, navigate to **Settings** in the Dashboard - your account ID is located below your account name and logo. --- URL: https://docs.moov.io/api/moov-accounts/partner-billing/list-fee-revenue/ --- # List fee revenue --- URL: https://docs.moov.io/api/moov-accounts/partner-billing/list-partner-agreements/ --- # List partner pricing agreements --- URL: https://docs.moov.io/api/moov-accounts/partner-billing/list-residual-fees/ --- # List residual fees --- URL: https://docs.moov.io/api/moov-accounts/partner-billing/list-residuals/ --- # List residuals --- URL: https://docs.moov.io/api/moov-accounts/representatives/create/ --- # Add a representative --- URL: https://docs.moov.io/api/moov-accounts/representatives/delete/ --- # Remove a representative --- URL: https://docs.moov.io/api/moov-accounts/representatives/get/ --- # Retrieve a representative --- URL: https://docs.moov.io/api/moov-accounts/representatives/ --- # Business representatives --- URL: https://docs.moov.io/api/moov-accounts/representatives/list/ --- # List representatives --- URL: https://docs.moov.io/api/moov-accounts/representatives/update/ --- # Update a representative --- URL: https://docs.moov.io/api/moov-accounts/support/create/ --- # Create a support ticket --- URL: https://docs.moov.io/api/moov-accounts/support/get/ --- # Retrieve a support ticket --- URL: https://docs.moov.io/api/moov-accounts/support/get-messages/ --- # List support messages --- URL: https://docs.moov.io/api/moov-accounts/support/ --- # Connected account support tickets You can hand off support tickets for your connected accounts to Moov. Moov will respond directly to the connected account, though you'll be able to see the messages. --- URL: https://docs.moov.io/api/moov-accounts/support/list/ --- # List support tickets --- URL: https://docs.moov.io/api/moov-accounts/support/update/ --- # Update a support ticket --- URL: https://docs.moov.io/api/moov-accounts/underwriting/get/ --- # Retrieve underwriting details --- URL: https://docs.moov.io/api/moov-accounts/underwriting/ --- # Underwriting --- URL: https://docs.moov.io/api/moov-accounts/underwriting/post/ --- # Create or update underwriting details --- URL: https://docs.moov.io/api/moov-accounts/underwriting/put/ --- # Update underwriting details (sunsetting) --- URL: https://docs.moov.io/api/rate-limits/ --- # Rate limiting Moov implements rate limiting for security and performance optimization. Use this guide to learn how Moov uses rate limiting. By limiting the number of requests hitting our API, we can manage request volume at scale, keeping Moov's platform reliable for the many developers and platforms interacting with our services. ## [How we use rate limits](#how-we-use-rate-limits) We currently limit the number of requests by any given IP address to 40 requests per second per account ID. If you exceed the request limit for our API, all endpoints will respond with a `429` status code, indicating you have made too many requests. Test accounts are limited to 10 requests per second per account ID. ## [What to do when you get a `429` response](#what-to-do-when-you-get-a-429-response) The 429 response header will note how much time you have until you can retry the request. ## [How to increase rate limits](#how-to-increase-rate-limits) If you need to increase your rate limit for your account, [contact Moov](https://support.moov.io/) with details about your use case and we're happy to raise the limit. --- URL: https://docs.moov.io/api/sources/apple-pay/get/ --- # Get domains Apple Pay --- URL: https://docs.moov.io/api/sources/apple-pay/ --- # Apple Pay --- URL: https://docs.moov.io/api/sources/apple-pay/register/ --- # Register domains for Apple Pay --- URL: https://docs.moov.io/api/sources/apple-pay/session/ --- # Create Apple Pay session --- URL: https://docs.moov.io/api/sources/apple-pay/token/ --- # Create Apple Pay token --- URL: https://docs.moov.io/api/sources/apple-pay/update/ --- # Update domains for Apple Pay --- URL: https://docs.moov.io/api/sources/bank-accounts/complete-bank-account-verification/ --- # Complete bank account verification --- URL: https://docs.moov.io/api/sources/bank-accounts/complete-micro-deposits/ --- # Complete micro-deposits --- URL: https://docs.moov.io/api/sources/bank-accounts/create/ --- # Link a bank account --- URL: https://docs.moov.io/api/sources/bank-accounts/delete/ --- # Delete a bank account --- URL: https://docs.moov.io/api/sources/bank-accounts/get-bank-account-verification/ --- # Get bank account verification --- URL: https://docs.moov.io/api/sources/bank-accounts/get/ --- # Retrieve a bank account --- URL: https://docs.moov.io/api/sources/bank-accounts/ --- # Bank accounts --- URL: https://docs.moov.io/api/sources/bank-accounts/initiate-bank-account-verification/ --- # Initiate bank account verification --- URL: https://docs.moov.io/api/sources/bank-accounts/initiate-micro-deposits/ --- # Initiate micro-deposits --- URL: https://docs.moov.io/api/sources/bank-accounts/list/ --- # List bank accounts --- URL: https://docs.moov.io/api/sources/cards/create/ --- # Link a card --- URL: https://docs.moov.io/api/sources/cards/delete/ --- # Disable a card --- URL: https://docs.moov.io/api/sources/cards/get/ --- # Retrieve a card --- URL: https://docs.moov.io/api/sources/cards/ --- # Cards --- URL: https://docs.moov.io/api/sources/cards/list/ --- # List cards --- URL: https://docs.moov.io/api/sources/cards/update/ --- # Update a card --- URL: https://docs.moov.io/api/sources/ --- # Sources --- URL: https://docs.moov.io/api/sources/payment-methods/get/ --- # Retrieve a payment method --- URL: https://docs.moov.io/api/sources/payment-methods/ --- # Payment methods --- URL: https://docs.moov.io/api/sources/payment-methods/list/ --- # List payment methods --- URL: https://docs.moov.io/api/sources/terminal-applications/create/ --- # Create a terminal application --- URL: https://docs.moov.io/api/sources/terminal-applications/create-versions/ --- # Register terminal application version --- URL: https://docs.moov.io/api/sources/terminal-applications/delete/ --- # Delete a terminal application --- URL: https://docs.moov.io/api/sources/terminal-applications/get-configuration/ --- # Get terminal application configuration --- URL: https://docs.moov.io/api/sources/terminal-applications/get/ --- # Get a terminal application --- URL: https://docs.moov.io/api/sources/terminal-applications/get-link/ --- # Get linked terminal application --- URL: https://docs.moov.io/api/sources/terminal-applications/ --- # Terminal applications --- URL: https://docs.moov.io/api/sources/terminal-applications/link/ --- # Link a terminal application --- URL: https://docs.moov.io/api/sources/terminal-applications/list/ --- # List terminal applications --- URL: https://docs.moov.io/api/sources/terminal-applications/list-links/ --- # List linked terminal applications --- URL: https://docs.moov.io/api/sources/wallets/create/ --- # Create a wallet --- URL: https://docs.moov.io/api/sources/wallets/get-adjustment/ --- # Get adjustment --- URL: https://docs.moov.io/api/sources/wallets/get/ --- # Retrieve a wallet --- URL: https://docs.moov.io/api/sources/wallets/get-transaction/ --- # Retrieve a wallet transaction --- URL: https://docs.moov.io/api/sources/wallets/ --- # Wallets --- URL: https://docs.moov.io/api/sources/wallets/list-adjustments/ --- # List adjustments --- URL: https://docs.moov.io/api/sources/wallets/list/ --- # List wallets --- URL: https://docs.moov.io/api/sources/wallets/list-transactions/ --- # List wallet transactions --- URL: https://docs.moov.io/api/sources/wallets/update/ --- # Update a wallet --- URL: https://docs.moov.io/api/tools/images/delete/ --- # Delete image --- URL: https://docs.moov.io/api/tools/images/get/ --- # Get image metadata --- URL: https://docs.moov.io/api/tools/images/ --- # Image library Images can be used to enhance the merchant experience by adding images to transfer line items and products in your product catalog. Upload and store images - up to 16MB in PNG, JPG, or WebP format. Images larger than 16MB and duplicate images will be rejected. --- URL: https://docs.moov.io/api/tools/images/list/ --- # List image metadata --- URL: https://docs.moov.io/api/tools/images/post/ --- # Upload image --- URL: https://docs.moov.io/api/tools/images/put-image/ --- # Replace image or image metadata --- URL: https://docs.moov.io/api/tools/images/put-metadata/ --- # Update image metadata --- URL: https://docs.moov.io/api/tools/ --- # Account tools --- URL: https://docs.moov.io/api/tools/products/delete/ --- # Disable a product --- URL: https://docs.moov.io/api/tools/products/get/ --- # Retrieve a product --- URL: https://docs.moov.io/api/tools/products/ --- # Product catalog Create a product catalog for merchants. Product can have a title, base price, description, associated image, and additional options like price modifiers. Map products to line items in transfers and payment links. --- URL: https://docs.moov.io/api/tools/products/list/ --- # List active products --- URL: https://docs.moov.io/api/tools/products/post/ --- # Create new product --- URL: https://docs.moov.io/api/tools/products/put/ --- # Update a product and options --- URL: https://docs.moov.io/api/version-reference/ --- # API version reference Moov's API versioning follows the format `vYYYY.QQ.BB`, where - `YYYY` is the year - `QQ` is the two-digit month for the first month of the quarter (e.g., `01`, `04`, `07`, `10`) - `BB` is the build number, starting at `.00`, for subsequent builds in the same quarter. For example, `v2025.01.00` is the initial release of the first quarter of 2025. ## [Lifecycle](#lifecycle) Each quarter's API version is released at the start of that quarter. For example, `v2026.04.00` will be released in April 2026. Once released, a version is considered stable and will only receive non-breaking changes. When a new version is released, work begins on the next quarter's version, which is considered in development. The in development version receives new features, breaking changes, and non-breaking changes throughout the quarter. For example, once `v2026.04.00` is officially released in April, `v2026.07.00` enters *in development* and is available for early access. Note - if no changes are made to the *in development* API version, that version will be skipped for an official release and will disappear from our public documentation. If no API version is passed in your header request, Moov will default to `v2024.01.00`. ## [Available versions](#available-versions) - `v2026.04.00` (in development) - `v2026.01.00` (current) - `v2025.07.00` - `v2025.04.00` - `v2025.01.00` - `v2024.01.00` (default) The *in development* version of the API always represents the next quarter's API. ## [Setting the API version](#setting-the-api-version) To use a specific API version, set the `X-Moov-Version` header on every request: ```fallback X-Moov-Version: v2026.01.00 ``` ### [Moov SDKs](#moov-sdks) Moov's official SDKs set the `X-Moov-Version` header automatically. Each SDK release is pinned to a specific API version — you don't need to set the header yourself. ### [Custom SDKs and direct API integrations](#custom-sdks-and-direct-api-integrations) If you generate your own SDK from our [OpenAPI specification](https://spec.speakeasy.com/moov/moov/api-v2026.01.00), or call the API directly, you are responsible for setting the `X-Moov-Version` header. Each OpenAPI spec includes the version it corresponds to in the `info.version` field. Configure your HTTP client or generated SDK to send this value as the `X-Moov-Version` header with every request. For example, if `info.version` is `v2026.01.00`, every request should include: ```fallback X-Moov-Version: v2026.01.00 ``` Most OpenAPI generators do not automatically set header defaults, so you will likely need to configure this in a request interceptor, middleware, or client constructor — depending on your HTTP client or generated SDK. ## [2026.01.00](#20260100) Added the `instant-bank-credit` payment method for real-time payments via RTP or FedNow. While `rtp-credit` will continue to be supported, Moov strongly suggests moving to the `instant-bank-credit` payment method. ## [2025.07.00](#20250700) - New support tickets allow you to hand off connected account support to Moov, and Moov will respond - Granular capabilities allow you to only request the capabilities you need, shortening onboarding time - Underwriting dynamically generates based on an account's business profile and requested capabilities - New enriched industry taxonomies model - Allows Moov to create guest accounts for Tap to Pay processing ## [2025.04.00](#20250400) - Added support for a `terminalCard` source and the `card-present-payment` payment method type for in-person payments. ## [2025.01.00](#20250100) - Updated error response status codes. ## [Breaking changes](#breaking-changes) - Non-breaking changes may be added to a release even after it becomes stable. - Minor breaking changes may be added to a release while it's in beta. Moov attempts to minimize this as much as possible. - Brand new features or major breaking changes will be in API version `latest`. Moov may release new features or major breaking changes for customers who are in specific beta programs or testing various features with us. See the [breaking changes](/guides/developer-tools/breaking-changes-api/) guide for more details. ## [SDK versioning](#sdk-versioning) SDKs are generated from each API version. SDK versioning will have the following format: | API version | SDK version | |---------------|----------------| | `v2025.07.00` | `25.7.x` | | `v2026.01.00` | `26.1.x` | | `v2026.04.00` | `26.4.0-dev.x` | For example, API `v2026.04.00` is *in development*, so the corresponding `-dev.x` SDK version indicates an *in development* version of the SDK and should be used with caution. --- URL: https://docs.moov.io/changelog/2021-08-13/ --- # Our first public changelog ## Payments - ACH transfers for multi-party payouts, collecting funds, and account-to-account transfers - Bank account linking with micro-deposits and Plaid support - Opting in to capabilities for informing on data requirements - Every transfer is captured in a ledger and broken down into the primitive money movement, with transparent details - Listen for key Moov events by creating and managing webhooks in the dashboard - [Wallets](/guides/sources/wallets/) for storing funds or use as a payment source ## Administrative - Moov Dashboard (including dark mode) - Mobile friendly version of the Moov Dashboard - Inviting others to your account in the Moov Dashboard - Multi-factor authentication for Moov Dashboard sign-ins - Fast customer onboarding - OFAC/sanctions checks - Profile photos magically appear - Business information magically appears letting you change it or simply confirm it ## Developer - Create and manage API keys restricted to your domains - Moov.js SDK for interacting with the Moov API in a browser - Restrict access of people with roles and access tokens based on OAuth - Webhook signature signing example project ## Documentation - New [quick start](/guides/quick-start/) guide - Dive deeper into Moov by reading through the new [Glossary](/guides/get-started/glossary/) section - Dive deep into our API with a fully documented [API reference](/api) - Get started quickly with a fully documented front end library, [Moov.js](/moovjs) --- URL: https://docs.moov.io/changelog/2021-10-14/ --- # OSS Slack app, Dashboard authentiation, and developer tooling ## Slack application Real-time insights into money movement activity are vital to help prevent fraud and resolve errors quickly. We launched a new open-source project that allows you to host a Slack app and get updates when transactions are created and completed. You can find the open source project on the [Moov Financial Github](https://github.com/moovfinancial/slack-integration). The Readme includes a guide for getting it up and running. ## Authentication - After a period of inactivity, you are automatically signed out. When you sign back in after you are automatically signed out, you'll now return to the last page you were on in. - You will now see a notice on the login page letting you know you have been signed out automatically. - Invite, two factor, and signup emails will now be sent from you from "Moov" instead of "noreply" - New users who sign up on the dashboard who are not part of the beta will now be giving a chance to request early access right from the dashboard. - We now prevent you from removing the last Admin on the account, ensuring you don't accidentally lose access to your account. - We updated the member's invite page to include the role, email address, and when they were invited. - If you get an error when signing in, those messages will now appear inline. - Redesigned the look of all our automated emails to ensure they have a consitent look. ## Developer tools - On the edit API key modal, when you submit the form by pressing enter, it will now save your updates instead of prompting you to delete. - Added the ability to restrict which domains you can call our API for each API key. - Our scope list now includes `transfers.read`, which is needed to read the information about a specific transfer via our API. - Added the scope for `/profile-enrichment.read` to allow you to autofill information about companies that sign up for your platform. - We added the ability to [revoke an access token](/api/authentication/access-tokens/revoke/) that you no longer need. A token that has been revoke will cause any follow up requests signed with that access token to fail. - When creating a new access token, you will receive a refresh token which you can use to generate a new token with the same scopes. ## Improvements Adjusted our sanctions screening to reduce the possibility of false positives. --- URL: https://docs.moov.io/changelog/2021-10-27/ --- # Introducing wallets ## Wallets Moov Wallets are now available. Every application has wallet provisioned for its account, and you can request the `wallet` capability for any Moov account. ## Faster transfers Moov now processes all ACH debits with same-day processing by default. This means your bank-to-bank or bank-to-wallet transfers will happen a day faster if we receive the request before the 4:15 pm ET cutoff window. ## Authentication - You can now generate an OAuth2 token by passing data as `application/json` in addition to passing as `application/x-www-form-urlencoded` when making a request to `oauth2/token` endpoint. - Added a confirmation when requesting a new two-factor code be sent to your email. - If you are inactive for a period of time, you will be warned a minute prior to being signed out. - Added `cards.read` and `cards.write` to the list of allowed scopes in preparation for allowing card transfers. - After a period of time, you will be signed out. We added the ability to reenter your password to stay signed in. ## Webhooks - Updated the Webhook keys to use a consistent camel case format. `TransferID` → `transferID`. - Added the `accountID` and `status` to the `capability.updated` webhook event. This will allow you to get additional information about the capability that was updated. - Added the `status` to the `transfer.updated` webhook. ## Member management - You can now search for Members that have access to your account on the members page. - You will now be notified if you try to send an invite to someone who is already a member of that account. - If a member invitation has expired you will now see that the status of that invitation in the member list. ## Account verification Moov account verification is now automated. When you request capabilities like `send-funds.ach` that require verification, the process will kick off as soon as all the data requirements outlined in the capability are satisfied for the individual or business. For any account that isn't instantly verified, you can view outstanding requirement errors or the overall status from the API and from the Moov Dashboard. ## Plaid integration We updated our Plaid processor integration to not require Plaid's identity product. ## Transfer statuses There are two new transfer statuses: `failed` and `reversed`. Receiving an ACH return will update the transfer status and send a `transfer.updated` event based on the transfer status: - `failed` - transfer returned/failed during clearing period or before funds movement - `reversed` - transfer returned/failed after clearing period or marked `completed` ## Improvements - Improved the experience of using the Moov app from a phone, particularly phones with notches. - The account ID for your account is now included on the Business Details page to help with troubleshooting and creating tokens. ## Bug fixes - Some Moov Dashboard users experienced aggressive caching that caused them to see an older version of the app. We implemented new cache-busting to keep the app as fast as ever while serving new updates. - Resolved an issue that was preventing the `capability.updated` event when it should have been. - We fixed some typos and updated the wording for sign-in error messages to increase clarity. - Resolved an issue that prevented you from sending an invite to a member who had been previously removed from your account. - We updated our open source Slack application to properly format numbers and removed some typos. --- URL: https://docs.moov.io/changelog/2021-11-17/ --- # Plaid integration ### Plaid integration Moov-managed Plaid integration allows our customers to offer instant account verification and launch the Plaid experience from [Moov.js](/moovjs). ### Webhooks - We finished a project this cycle to ensure all the required information is included on all the webhooks so developers can pull the information that is needed. We also updated our [documentation](/guides/webhooks/webhook-events/) to include a list of the schemas for all the webhook events. - Added the `accountID` and `status` to the `bankAccount.created`, `.updated`, and `.disabled` events. - The `transfer.created` and `transfer.updated` now include the `accountID` for the account facilitating the transfer along with the `status` of the transfer. - We are now sending events for the `transfer.updated` event when a transfer `fails` or is `reversed`, since sometimes things don't go as planned. - We added the `accountID` to the `balance.updated` webhook to allow developers to get additional information about the wallet if needed. - The `paymentMethod` webhook events now include the `accountID` and the `sourceID` to allow developers to more quickly get information about that payment method. - The `representative.created` and `representative.updated` webhooks now include the `accountID` for the account the representative belongs to. ### Permissions For users with "Developer," "Support," or "View only" permissions, the dashboard will now reflect what actions they can or cannot perform instead of getting an error message when they attempt to perform that action. If the user isn't able to perform an action, the button will be disabled, hidden, and in some cases, the entire section won't be visible. ### Dashboard - We added verification status to the accounts list and account details. - Improved usability of date of birth, tax ID, and phone number fields. ### Bug fixes - We resolved an issue where a warning banner was being shown when it wasn't supposed to be when trying to add a new member. - We resolved a bug that was temporarily preventing you from switching the role of a user in the dashboard. --- URL: https://docs.moov.io/changelog/2021-12-08/ --- # Test mode ### Test mode - We've enabled [test accounts](/guides/get-started/test-mode/) so you can interact with Moov's platform without sending real money or waiting on account verification. - API key creation for test accounts - Simulate micro-deposits by inputting `$0.00` - Simulate successful transfers ### Transfers metadata We now allow our customers to store free-form data on transfers. As a customer, you can store any type of data that suits your needs, for example: invoice numbers, correlation IDs, SKU data, etc. ### Bug fixes We resolved a bug that was preventing 2FA codes from being emailed out for a brief period of time. ### Improvements - We made small text updates to improve the consistency of member role names (for example, "Administrator" instead of "Administrators"). - We improved internal logging across session refreshes to continue to monitor, track, and prevent fraudulent activity. - We updated the UX for adding multiple domains on an API key. --- URL: https://docs.moov.io/changelog/2022-01-19/ --- # Dashboard metrics ### Dashboard We’ve released Dashboard metrics. You can now view new accounts (by type and overall), transfer count (by status and overall), and transfer volume over time on the Moov Dashboard. See our [Dashboard overview guide](/guides/dashboard/) for more information. ### Collect-funds capability In preparation for the release of our card acquiring beta program, we wanted to simplify the onboarding process for our customers that intend to accept card payments. Part of this preparation is to only allow businesses to have the `collect-funds` capability. ### Wallets Utilizing a [Moov wallet](/guides/wallets) can be a great way to simplify and expedite many payment use cases. Starting now, any Moov account with the `send-funds.ach` or `collect-funds.ach` capabilities enabled will automatically get a wallet. This wallet may be used for payment exception use cases. ### MX Integration Moov has partnered with MX to offer our clients another seamless way to perform instant account verification. Our clients that have an existing MX relationship can now connect their MX account directly to their Moov account so their clients have the ability to link their bank accounts instantly. See our [MX integration guide](/guides/sources/bank-accounts/verification/mx/) for more information. ### Transfer status webhooks The `transfer.updated` webhook event now includes the rail-specific statuses that correspond to each leg of the transfer. The breakdown of statuses can be found [here](/guides/webhooks/webhook-events/#granular-transfer-event-statuses). This provides a more granular level of transparency on a transfer and will notify you (if subscribed) of transaction completion or any rail-specific issues that arise when we hear about them. --- URL: https://docs.moov.io/changelog/2022-02-16/ --- # Refunds and other improvements ### Cards - You can now refund card payments in the Moov Dashboard. You can issue a full refund from a transfer with `card-payment` as the source. - We now include card type and issuer information on linked cards in the Dashboard. - We added a new `cardDetails` object for setting a dynamic statement descriptor and recurring flag for card payments. - Fees will be shown in the Dashboard. Fee support in the API will be generally available soon. ### Listing industries We added a new endpoint for [listing accepted industries](/api/enrichment/form-shortening/industries/get/), including their name, MCC, NAICS, and SIC codes. Use the API or Moov.js to list industries. ### Autocompleting addresses We have a new endpoint for auto-completing addresses, creating a better user experience with less timing and better accuracy for KYC verifications. ### Improvements - Plaid customers using the Moov processor token will now receive a canned response when using a Moov test account. - We improved the display of bank accounts, cards, and their payment methods in the Dashboard. --- URL: https://docs.moov.io/changelog/2022-02-23/ --- # Introducing Moov Drops ### Moov Drops We’ve released three pre-built user interfaces for embedding payments quickly and securely. - [Onboarding](/moovjs/drops/onboarding/): implements a flow for onboarding and verifying customers - [Payment methods](/moovjs/drops/payment-methods/): an interface for helping users set up and manage their linked bank accounts and cards - [Card Link](/moovjs/drops/card-link/): a web component for adding credit card information securely All Moov Drops: - Leverage [Moov.js](/moovjs/), ensuring that sensitive data never hits your servers - Optimize for a seamless user experience through form-shortening, error handling, and accessibility features - Are customizable to match your brand (see our [theming guide](/moovjs/drops/theming/)) --- URL: https://docs.moov.io/changelog/2022-03-02/ --- # Transfer groups ### Transfer groups [Transfer groups](/guides/money-movement/transfer-groups/) are now available via the Moov API. Transfer groups provide a way to associate multiple transfers together by a shared ID of the parent transfer. Use the `transferID` of a to-wallet transfer as the `source` of a transfer to group them. The subsequent transfer will be `queued` until its parent completes, and you can choose to make it visible to the recipient. Support for transfer groups will be coming soon to the Moov Dashboard. ### Bug fixes - We fixed an issue with Dashboard metrics being incorrectly calculated. - We have consolidated the [Moov Onboarding Drop](/moovjs/drops/onboarding) to further streamline the client experience. ### Improvements - For all new accounts, we will auto-populate your test account data so you can start exploring and learning right away. - We clarified business requirements in our docs and the Moov Dashboard. - We updated our SSN requirements to toggle between requiring only the last four of a client’s SSN or requiring their full SSN. --- URL: https://docs.moov.io/changelog/2022-03-23/ --- # Facilitator fees ## Dashboard - We streamlined our onboarding process to help prospects start learning what Moov can do for them as quickly as possible. - We edited [test mode](/guides/get-started/test-mode/) so that there is no need to spend any time adding business data or creating accounts and payment methods before you’ve decided to use Moov. Test mode now pre-populates sample business information so you can focus on exploring the platform. ## Transfers - You can now monetize your transfers with [facilitator fees](/guides/money-movement/fees/). When you set a facilitator fee on a transfer the amount of the fee will be moved to your Moov wallet. - [Transfer groups](/guides/money-movement/transfer-groups/) can now include wallet-to-bank transfers to end the chain. --- URL: https://docs.moov.io/changelog/2022-04-13/ --- # Transfer groups in timeline and synchronous transfer responses ### Dashboard We made a handful of dashboard improvements to improve how we communicate the status of your account. - [Transfer groups](/guides/money-movement/transfer-groups) are now visible in the Moov Dashboard so you know exactly where your funds are at all times. - We made it easier to find and fix [capability](/guides/accounts/capabilities/troubleshoot/) errors so you know exactly what needs to be fixed before a transfer can be processed. - After creating a new account or payment method in the Dashboard, you’ll see sample code snippets that give context on how you can perform those same actions more efficiently using our API. ### Transfers - We have introduced the `X-Wait-For` header for use when making a transfer. When you make a transfer today you get an immediate response containing only the `transferID` to indicate the transfer instructions have been received. With the new `X-Wait-For` header, you can pass a value of `rail-response` to tell the service that you want the full transfer payload back after the request has gone out to the payment rail and back. This is useful for handling client-side errors and retries for card transactions that communicate with the card networks in real time. ### Test mode Things don’t always go according to plan—we’ve added a new test card in [test mode](/guides/get-started/test-mode/#card-acceptance) to help you simulate what happens when a card payment is declined. --- URL: https://docs.moov.io/changelog/2022-05-05/ --- # Locked accounts ## Improvements - We made it quicker and easier to request capabilities for new accounts by allowing you to create an account and request capabilities in the same API call. - In an effort to reduce confusion and accidental overwrites of existing data, we have added PATCH methods and have removed the PUT methods for updating Accounts and Representatives. PUT updates to Accounts and Representatives will no longer be supported. ## Account locking Once a Moov account has been verified, you will be unable to edit most of the business or individual identity details as additional verification may need to take place. If you need to update verified information, requests should be sent to our support team. --- URL: https://docs.moov.io/changelog/2022-05-19/ --- # Basic authentication ## API authentication You can now use basic authentication to authenticate with the Moov API! It's important that you only use this for server-to-server communication and not in a browser. Once you've created an API key, within your server-side app set the Authorization header to `Basic ` where credentials is the Base64 encoding of public key and private key joined by a single colon `:`. When using this authentication method you don't need to set scopes, but keep in mind that your API key will have read and write access to every Moov endpoint within your account. OAuth 2.0 based authentication with scopes remains the most secure way to communicate with the Moov API from a browser and can still be used to create restricted access tokens for server-to-server communication. ## Account capabilities You no longer need to request the `transfers` capability after creating an account because it will automatically be requested and enabled upon account creation. This change simplifies the process of creating accounts that will be charged or sent a payout that don't require verification. --- URL: https://docs.moov.io/changelog/2022-06-15/ --- # Simpler onobarding ### Onboarding We rebuilt our entire sign-up and onboarding process to remove as much friction as possible before folks start building. Specifically, we: - Rebuilt our test environment and removed all of the hoops customers previously had to jump through before building. This includes filling out a test business profile, adding test business representatives, and even creating connected accounts and payment methods. All you have to do after signing up is generate test mode API keys and start building. More to come! - Streamlined how we collect required information about your business to get you to production. This historically cumbersome process of inputting data is now seamless. Ensuring that we have all of the necessary information to verify your business up front can shave days off the onboarding timeline. ### Dashboard We improved how we communicate with our clients through their Moov Dashboard by clarifying action items and statuses for your accounts. This includes showing when an account has been verified and therefore can no longer be updated, as well as communicating any verification issues with your accounts and what needs to be corrected to proceed. --- URL: https://docs.moov.io/changelog/2022-07-06/ --- # Card acquiring improvements ## Moov Drops If you need to limit which card brands you accept, you can now toggle which brands you support using the `allowCardBrands` option in the [Card link](/moovjs/Drops/card-link), [payment methods](/moovjs/Drops/payment-methods), and [onboarding](/moovjs/Drops/onboarding) Moov Drops. ## Cards - To improve fraud detection and prevention, we integrated with Mastercard’s MATCH service. - `transactionSource` for transfers using a card is now supported on all card brands. ## Improvements - Improvements and bug fixes relating to missing account requirements and locking down fields after verification. - For clarity, we renamed the “Profile” navigation link within an Account to “Settings”. - We now show all fields under your account’s Business details section. - Improved our tracking of when a customer has moved to production to prevent multiple employees from having to fill out the same form. ## Bug fixes - We resolved an error where previous transfers in a transfer group wouldn’t show if they had been refunded. - We fixed an issue where some users weren’t able to advance past the initial loading screen. - We fixed an issue where the `markup` fee set on a transfer could be incorrectly calculated. --- URL: https://docs.moov.io/changelog/2022-07-27/ --- # Dashboard and API experience improvements ## Dashboard - You can now quickly find an account by pasting an account ID into the search field on the accounts list. - Have a transfer ID that you need to debug? Paste it into the new search bar on the transfers list. - You can now filter the transfer list by refunded state. - The Dashboard overview now includes your Moov wallet balance. ## Cards - If you’re PCI level 1 and have been using the API to link cards directly, you can now use the base path of the API instead of `cards.moov.io`. The latter is now deprecated and will be removed in the future. This keeps consistency with all other Moov endpoints. ## Improvements - We made it easier to identify and fix requirements that need attention. - We hardened our capabilities service by reprocessing failures if the account mode was missing. - We enhanced our verification service by streamlining manual reviews - We added an additional security and fraud prevention measure by running all card acquiring merchants through the Mastercard MATCH database. ## Bug fixes - We addressed a few issues around account creation and updating: - We only require a phone number OR email address but not both. - Fixed our process for updating an SSN or ITIN. - We addressed an issue with our support contact section that required all of the fields or none of them. --- URL: https://docs.moov.io/changelog/2022-08-04/ --- # ACH statement descriptors, disputes, and more ## Custom ACH statement descriptors You can now set a customized ACH statement descriptor when [creating a transfer](/api/money-movement/transfers/create/). We’ve introduced two new optional fields you can use to adjust the default Nacha file entry: - `achDetails.companyEntryDescription` - `achDetails.originatingCompanyName` This provides you the opportunity to add more context about what the payment was for, allowing recipients to more easily recognize the transaction. ## Verification We made some bug fixes for our verification flow and streamlined the process to account for a few edge cases. We also improved our manual review process by removing errors from client dashboards after a manual review is required. ## Capabilities We now automatically enable the `wallet` capability if you have the `card-issuing` capability. Note that our card issuing functionality is currently in a closed beta. ## Failure reason codes We shipped failure reason codes that explain why a card transfer was unsuccessful. You can now see a human-readable code for why the transfer failed in the Moov Dashboard. We’ve also implemented machine-readable `failurecode`, which you can view when you [get a transfer](/api/money-movement/transfers/get/) in the API. ## Disputes We’ve shipped and documented [dispute handling for card transfers](/guides/money-movement/accept-payments/card-acceptance/disputes/). You can view dispute information on the [transfer object](/api/money-movement/transfers/get/)in the API and in the Dashboard via transfer status. Support for Mastercard is in progress. --- URL: https://docs.moov.io/changelog/2022-08-18/ --- # Faster searching in Moov Dashboard ## Dashboard improvements We've made several improvements to the Moov Dashboard for a cleaner, faster user experience: - Improved the loading and search speed for accounts - Simplified verification statuses (so it’s easier to tell whether any action is needed on your part) - Enhanced our autofill address input field by adding support for apartments and suites ## Disputes We are continuing to improve how Moov handles [disputes](/guides/money-movement/accept-payments/card-acceptance/disputes/), with the most recent changes being: - [GET transfer](/api/money-movement/transfers/get/) model now returns the `disputedAmount` - Support for MasterCard disputes ## Card statement descriptors You can now include more information in statement descriptors and receive descriptor information from the transfers API. Specifically: - `dynamicDescriptor` and `statementDescriptor` character limit increased to 22 characters - [GET transfer](/api/money-movement/transfers/get/) response now returns the `dynamicDescriptor` ## Transfer errors We investigated and addressed a bug on transfer error responses. --- URL: https://docs.moov.io/changelog/2022-09-01/ --- # Partial refunds ## Partial refunds We now support [partial refunds](/guides/money-movement/accept-payments/card-acceptance/reversals/) on card payments. Use the API or dashboard to process any number of partial refunds summing up to the amount of the original transfer. ## Transfer updates The deprecated fields, `createdAt` and `ach`, have been removed from the transfer model. We've switched the names of these fields to `createdOn` and `achDetails` for clarity. ## Fraud prevention We improved fraud prevention and detection by adding Captcha to the Moov Dashboard. ## Onboarding We made it easier for new clients to complete their business profile in production and ask for help from a team member if necessary. ## Verification statuses We finished adding the new verification statuses to the Dashboard and [Moov Drops](/moovjs/drops/). --- URL: https://docs.moov.io/changelog/2022-09-15/ --- # Document uploading ## Dashboard improvements We got rid of the "load more" button and replaced it with infinite scrolling for a more seamless user experience experience. This update applies to all tables that display entries loaded from the API. In addition, we improved our address field by adding support for suite and apartment numbers. ## Document upload We’ve added a new service that allows clients to upload documents to their own dashboard via API. To learn more, see our [files](/api/moov-accounts/files/post/) endpoint. ## Business verification We simplified how we define business owners. Previously, business owners had to own 25% or more of the business in order to communicate they are an owner. That limit still exists to technically be counted as a beneficial owner, but we accept any percentage now. ## Instant account verification with Plaid We've updated our documentation to clarify a few common sticking points on using [Plaid Link with Moov.js](/moovjs/sources/bank-accounts/plaid-link/). --- URL: https://docs.moov.io/changelog/2022-09-29/ --- # Card issuing ## Card issuing Behind the scenes, we’ve been working hard on [card issuing](/use-cases/card-issuing/). Our program is still in a closed beta, so stay tuned for more updates! ## Dashboard The issuing view in the Moov Dashboard includes pagination on the list of issued cards and transaction history. You'll only see this view if you're one of our card issuing beta customers. ## Cards We added a new `clear()` method to the [Moov Drop for linking a card](/moovjs/drops/card-link/#properties) to clear all user input. This allows you add multiple cards quickly: if you want, you can set up their code to submit card info, then clear out the form to get it ready for the next card. ## Refund webhooks We have renamed two fields in the `refund.created`and `refund.updated` webhook events to match the field naming with our platform. Note that `originalTransferID` is now `transferID` and `refundTransferID` is now `refundID`. We’ll support the old fields for 1 month before deprecating. ## Dispute webhooks The `dispute.created` webhook now supports `transferID` vs. `transactionID` that previously did not link back to anything in our system. ## Bug fixes - We resolved an issue where patching an account could unexpectedly fail - We fixed a bug where Moov Drops could throw an error in certain situations where a valid JWT was used --- URL: https://docs.moov.io/changelog/2022-10-13/ --- # File uploads in Moov Dashboard ## File upload We’ve updated the Moov Dashboard so you can now upload documents for a connected account under the “Documents” section of the Moov account. If you need to upload a file for your platform partner (facilitator) account (vs. connected accounts), you can do this in the “settings” section of the Dashboard. Feel free to refer to our [dashboard guide](/guides/dashboard/accounts/#documents) for further guidance. ## Account protection We added and started enforcing password rules for more rigorous account protection. ## Onboarding We consolidated and clarified information about capability requirements for Moov accounts in our documentation. To read more see: - [Verification](/guides/accounts/requirements/identity-verification/) - [Business representatives](/guides/accounts/requirements/business-representatives/) - [Capabilities](/guides/accounts/capabilities/) ## Changelog email newsletter There’s now a way to subscribe to Moov’s changelog updates and receive them in your email inbox. If you’d like to receive a newsletter with our changelog, feel free to hit the subscribe button. --- URL: https://docs.moov.io/changelog/2022-11-10/ --- # Wallet transaction and Apple Pay ## Wallet transactions We now provide insight into funds that move in and out of an account’s wallet at a granular level. Every Moov transfer that involves a wallet will also have a corresponding transaction representing how the wallet is impacted. This creates greater visibility into things like fees earned, disputes, and refunds. This record of wallet transactions also enables historical balance tracking. To learn more about this feature and the different transaction types, read our [wallet transactions guide](/guides/wallet/transactions/). ## Apple Pay Moov now supports Apple Pay as a way to accept card payments. Read our guide on [accepting cards with Apple Pay](/guides/sources/cards/apple-pay/) to learn more. ## Dashboard We gave the interface a fresh coat of paint. New colors help shine a light on your accounts and transfers. Reminder that light and dark mode are available and that the Dashboard is a progressive web app that can be used on your phone or nearly any modern web-enabled device. ## Onboarding In order to accommodate longer addresses, we’ve increased the maximum length of an address to 60 characters. ## API docs To help give more context and guidance, we’ve added links to our guides in our [API reference](/api) endpoint descriptions. ## Bug fixes - We resolved a bug where an invalid wallet `balance.updated` webhook events were being generated for some accounts. - We’ve updated our platform to fix incorrect reporting of disputes received on pending transfers. - Hidden whitespace characters were preventing some micro-deposits from working properly. This has been resolved. --- URL: https://docs.moov.io/changelog/2022-11-23/ --- # Transfer peek previews, bank holiday notices, and more ## Transfer peek previews We’ve added [transfer peek previews](/guides/dashboard/peek-preview/) to allow faster access to transfer details from any list of transfers in the Dashboard. Toggle the preview on and off by tapping `Space` while on the transfers list. You can also dismiss the preview with the `Esc` key. ## Bank holiday notices We now have a notice that shows up on in the Dashboard whenever a bank holiday or observed bank holiday is coming up in a few days and stays until the day after. This update lets you know that the upcoming bank holidays may cause delays on pending transfers. ## Synchronous refund responses You can now use the `x-wait-for` header to wait for the payment rail response on refunds. Stay posted for updates to our documentation that includes detailed information on the responses. ## NOCs and returns update bank accounts A Notification of Change (NOC) is a notification provided by the ACH Network that something about a bank account we are interacting with has changed (i.e., a new account number or routing number). Moov now consumes data from ACH Network’s NOC and automatically revises transfer and bank account records accordingly. The `bankAccount.updated` webhook will reflect when an NOC change has been made on a bank account. --- URL: https://docs.moov.io/changelog/2022-12-08/ --- # ACH transfer timing in test mode ## ACH transfer timing in test mode Previously, ACH transfers in test mode followed the same processing windows as production mode, taking up to 48 hours to process. However, we’ve updated our platform so that ACH transfers in test mode now complete much faster (within about an hour), since no real money movement is happening. ## Changelog style If you haven’t noticed already, our changelog got a new look. We now include titles in addition to the date timeline so you can get a quick sense of Moov’s latest product updates. ## Synchronous transfer creation response We added a 201 response for synchronous transfer creation. If Moov is unable to get transfer details that are returned in the 200 synchronous response, we’ll return a 201 confirming the transfer was created with the transferID. ## Card acceptance We reduced the potential for latency during periods of high traffic by adding rate limiting to some of our asynchronous processes. ## Bug fixes We resolved a bug in the Dashboard where the list of members were sorted in reverse alphabetical order by last name. We revised this so the list of members are sorted in alphabetical order. Styling was broken for the card link iframe within the [Payment method Drop](/moovjs/drops/payment-methods/). The styling has been updated and now works correctly. --- URL: https://docs.moov.io/changelog/2022-12-22/ --- # Card dispute resolution, failure reasons, and webhook updates ## Card disputes We have updated the `status` field on disputes objects. Pre-disputes resolved by Visa’s rapid dispute resolution will have the `resolved` status, while all other disputes have status `response-needed` status. We have added the `respondBy` field added to disputes object. The date in the `respondBy` field should be must be presented to the merchant as the last day they are able to submit evidence to fight a chargeback. See our [disputes](/guides/money-movement/accept-payments/card-acceptance/disputes/) guide for more information. The `networkReasonCode` field for a dispute in the transfers endpoint will now return an empty string, and will be fully deprecated on January 21, 2023. The network code is still available via the [GET dispute](/api/money-movement/disputes/get/) endpoint. ## Failure reasons When a transfer fails, we will now communicate the reason for the failure through the `failureReason` field in API response for a [**GET transfer**](/api/money-movement/transfers/get/). The `failureReason` field provides context so our platform partners can understand why a transfer failure happened and determine what next steps to take. See our [failures](/guides/money-movement/events-and-statuses/#failure-reasons) guide for more information on the reasons and their corresponding descriptions. Please note, card and ACH specific failure codes are still available under the source and destination objects. ## Webhook events The `availableBalance` field on the `balance.updated` webhook event is deprecated. If you need to retrieve the available balance for a wallet, you can use the [GET wallet](/api/sources/wallets/get/) endpoint. We’ve made some updates that allow us to send webhook events faster. However, because we are prioritizing speed, we can no longer guarantee ordering on the `walletTransaction.updated` webhook event. --- URL: https://docs.moov.io/changelog/2023-01-19/ --- # Issued card Moov Drop ## Issued card Moov Drop The new [issued card Moov Drop](/moovjs/drops/issued-card/) enables customers to display a previously issued virtual card within a secure, Moov-hosted iframe. ## Underwriting We have added a new underwriting requirement for certain capabilities. See our [underwriting](/guides/accounts/requirements/underwriting/) guide for more context on when we need to underwrite an account and what we require. A section for underwriting will be added to the Moov Dashboard in the near future. ## Bug fixes and improvements We resolved an issue that was causing some ACH test mode transfers not to complete as scheduled. We’ve improved visibility by surfacing reasons for failed bank account validation attempts. For example, when micro-deposits expire, the `statusReason` will be `ErrMicroDepositExpired`. --- URL: https://docs.moov.io/changelog/2023-02-02/ --- # Underwriting updates ## Underwriting As a part of our [underwriting process](/guides/accounts/requirements/underwriting/), you can now provide underwriting data in the Moov Dashboard. When creating a new account via the Dashboard, you can input the required information depending on the capabilities the account needs. You can also edit these fields when viewing an account’s profile and clicking on transaction details. ## Bug fixes We resolved an issue that was causing some ACH transactions initiated during weekends to not complete as scheduled. --- URL: https://docs.moov.io/changelog/2023-02-17/ --- # Faster wallet transactions, secure file uploads in Moov.js ## Faster wallet transactions list We have optimized the [LIST wallet transactions endpoint](/api/sources/wallets/list-transactions/) so that paginated and filtered transactions load faster than ever. If you're not already benefiting from wallet transactions, they make it easy to track all the money moving through your platform. You can use them to present detailed transaction history and for real-time reconciliation. See our [wallet transactions](/guides/sources/wallets/transactions/) guide to learn more. ## File uploads in Moov.js In addition to the Dashboard and Moov API, you can now [upload files](/moovjs/accounts/files) related to an account using Moov.js. This means you can stay out of the flow of sensitive documents and allow them to be passed directly from your user to Moov. To read more on file upload specifications, see our [file uploading](/guides/dashboard/accounts/#documents) guide. ## Business verification We optimized our verification logic to improve business verification speed and consistency. ## Transfer failure reasons We’ve added transfer failure reasons to the Moov Dashboard for greater transparency and understanding for why a transfer did not succeed. See our [transfer failures](/guides/money-movement/events-and-statuses/#failure-reasons) guide for more context on failure reasons. --- URL: https://docs.moov.io/changelog/2023-03-02/ --- # File upload Moov Drop ## File upload Moov Drop We shipped a pre-built UI component that allows users to upload important documents to their Moov account. With this Moov Drop, your users pass documents directly to Moov and you stay out of the flow of sensitive data collection. --- URL: https://docs.moov.io/changelog/2023-04-14/ --- # Enhanced account search ## Enhanced account search We've optimized our account search endpoints to be exceedingly quick. You can search by term, status, account type, or any combination of the three to retrieve your account list in as little as half a second. With broader search criteria, you will now be able to see more than just exact matches in your search results. ## Bug fixes and improvements There was a problem in the Dashboard where the “Review” button was not functional. We’ve updated the "Review" button so it should work for accounts with capability errors. --- URL: https://docs.moov.io/changelog/2023-04-28/ --- # Faster ACH ## Faster ACH Moov can now approve accounts for default [faster ACH processing](/guides/money-movement/accept-payments/ach/ach-processing-speeds/#faster-same-day-processing). Faster ACH processing allows you to bypass the standard two-day debit hold period, kicking off the credit process soon after the transfer is initiated. Based on processing cutoff times, bank-to-bank and bank-to-wallet transfers can fully complete in one day. Faster ACH approved accounts will also have the ability to add the two-day hold period to a transfer if desired. ## Account disconnect You can now permanently disconnect accounts from your Moov account. This action does *not* delete the account or any associated data with the account. Disconnected accounts cannot be interacted with, and you will no longer be able to edit the profile, upload documents, or create new transfers or payment methods. Disconnected accounts will also no longer appear in your list views, however, you can still view them using a filter. When disconnecting accounts, please take note this action cannot be undone. ## Dashboard enhancements The Capabilities tab in the Moov Dashboard now shows when an account requires a review from Moov. In this scenario, capabilities will show as pending with no requirement errors. --- URL: https://docs.moov.io/changelog/2023-05-16/ --- # A new way to refund ## A new way to refund Moov now provides the option to send a card reversal request. A reversal will either cancel a transfer or refund a transfer depending on the settlement status. If a transfer can be canceled, this reduces processing costs for the merchant and returns funds to cardholders quicker. Read more in our [Reversals](/guides/money-movement/accept-payments/card-acceptance/reversals/) documentation. ## Apple Pay Payment methods for [Apple Pay](/guides/sources/cards/apple-pay/) now include unique fingerprint detection, expiration date, and dynamic last four of the device-specific card number. ## Micro-deposit update Moov has updated the [micro-deposit](/guides/sources/bank-accounts/verification/micro-deposits/) process. In addition to sending two micro-deposit credits, Moov initiates a debit to re-coup the credit amount. Each micro-deposit now has a range of up to .49¢. ## Relaxed character restrictions You have the ability to use more characters in account names, for example, characters like ñ are now accepted. The characters are converted before sending them off to certain payment rails with character restrictions. To see all accepted characters, you can view the name object in an individual’s profile in the [create an account endpoint](/api/moov-accounts/accounts/create/). ## Bug fixes An issue in the [Payment methods Drop](/moovjs/drops/payment-methods/) was resolved where the `onResourceCreated` event wasn't firing when adding a bank account or card. An issue with the way the `foreignID` and the `created` date was displayed in the business accounts’ Dashboard view has been corrected. --- URL: https://docs.moov.io/changelog/2023-05-30/ --- # Card re-verification ## Card re-verification You can now update the expiration date and address details for a card, as well as re-verify a card's CVV, using Moov’s new Update card PATCH [endpoint](/api/sources/cards/update/). With the new endpoint, when a CVV is provided, immediate re-verification is initiated. If no CVV is provided, the updated details are saved for the card’s next use. Visit Moov's [Card payments](/guides/sources/cards/#reverify-a-card) documentation for more information. --- URL: https://docs.moov.io/changelog/2023-06-14/ --- # Card linking merchant parameter ## Card linking merchant parameter A new `merchantAccountID` parameter can be used to pass merchant information with the $0 authorization transaction Moov creates when a card is linked. While these $0 transactions don't typically show on a statement, they can show up in a cardholder's fraud alerts. If you don't supply a `merchantAccountID`, your platform's account information will be used. The `merchantAccountID` can also signify which merchant the cardholder has consented to save their information, which allows you to save a card for future use. See our [documentation](/guides/sources/cards/#link-a-card) for more information. ## New Apple Pay payment methods dialog There is a new dialog box when adding Apple Pay payment method details in the Dashboard. ## Bug fixes Fixed an issue with transfer list query parameters. When the `reversed` status is applied, the date range filters now work. Fixed an issue with the **View transfer** link in the Dashboard. --- URL: https://docs.moov.io/changelog/2023-07-11/ --- # Wallet transaction history ## Wallet transaction history If an account’s wallet capability is disabled, the wallet’s transaction history will still be accessible through the Dashboard. ## Bug fixes - Fixed a timeout issue on card payment reversals in test mode. - Fixed a timeout on listing wallet transactions when filtering by source ID. - Fixed a bug in the Dashboard where the last four numbers of Apple Pay payment methods were inconsistently displaying. - Fixed a bug in the Dashboard where account search criteria was removed when going from an account back to the list. - Fixed a bug in the Dashboard where the wrong account ID was copied from the destination transfer. --- URL: https://docs.moov.io/changelog/2023-07-25/ --- # Rail status for refunds Refunds now include a rail specific status in the `cardDetails` object, allowing further visibility into refund timing. You will be able to see whether a refund has been initiated, confirmed, settled, completed, or failed. See our [documentation](/guides/money-movement/accept-payments/card-acceptance/reversals/#settlement-status) for an example. --- URL: https://docs.moov.io/changelog/2023-08-08/ --- # Composable Drops ## Composable Drops New Moov Drops allow users to add and update card information through your application, with data sent directly and securely to Moov. The new composable Drops make it easier to embed and style form fields to match your brand. We're also introducing low-level components for securely capturing any information that gets sent to Moov, not just card data. See our [Moov.js Drops](/moovjs/drops/composable-drops/) documentation for more information. --- URL: https://docs.moov.io/changelog/2023-08-22/ --- # Card account updater ## Card account updater With Moov’s card account updater, you can set up cards to automatically receive updates. Sensitive card information is securely sent to Moov and updated on your behalf, eliminating the need for you to contact cardholders for card updates. See our [documentation](/guides/sources/cards/card-account-updater/) for more information. ## ACH returns in test mode You now have the ability to simulate various ACH return scenarios in test mode. You can initiate test returns occurring at different transfer stages to gain better insight into cashflow management. See our [documentation](/guides/get-started/test-mode/#ach-returns) for more information. --- URL: https://docs.moov.io/changelog/2023-09-26/ --- # Improvements and bug fixes ## Improvements We’ve enhanced our Apple Pay solution to obtain the cardholder’s billing address so that it can be submitted for an AVS check. AVS (Address Verification System) is a fraud prevention tool that verifies that the billing address matches the address of the cardholder. See our [Apple Pay docs](/guides/sources/cards/apple-pay/) for more information. For those looking to implement this update, please note: - We made a new `billingContact` object available within Moov’s [Link Apple Pay token request](/api/sources/apple-pay/token/) - We strongly recommended setting `postalAddress` as a required billing contact field in the Apple Pay client-side implementation so that the cardholder’s information is sent to your app. Read the [Apple documentation](https://developer.apple.com/documentation/apple_pay_on_the_web/applepayrequestbase/2951608-requiredbillingcontactfields) on `requiredBillingContactFields` for more details. ## Bug fixes We fixed a few minor bugs in the Moov Dashboard: - When a card on file is activated in the payment methods list, the new status now appears immediately rather than after a user refreshes - The [documents](/guides/dashboard/accounts/#documents) page communicates the correct maximum number of documents you can upload for an account --- URL: https://docs.moov.io/changelog/2023-10-10/ --- # Platform improvements ## Speed and stability Moov engineers are always working to make our system both fast and stable. We shipped a series of backend enhancements that reduced the mean response time of all API endpoints, particularly while under heavy loads. ## Dashboard We improved the process for creating and updating accounts and representatives. You can now enter the information you have on hand and come back to input more information later. ## Alphanumeric character support for bank accounts We now support alphanumeric characters for bank account numbers over ACH. --- URL: https://docs.moov.io/changelog/2023-10-24/ --- # Higher precision, account creation, and more ## Higher precision We’ve updated transfers, wallet transactions, and wallet endpoints with new decimal fields that support up to 9 decimal places. You can now also input facilitator fees with higher precision. In the `POST` create transfer [endpoint](/api/money-movement/transfers/create/), you'll find two new optional fields: `totalDecimal` and `markupDecimal`. We will still support the pre-existing fields (`total` and `markup`), but only one field is required in the payload. We have updated the `GET` transfer [endpoint](/api/money-movement/transfers/get/) to include `moovFeeDetails` showing each category of fees charged, with the existing total `moovFee` that sums all line items. `moovFeeDecimal` will be the precise fee charged, where the pre-existing `moovFee` will round to the nearest cent. We will continue to support the pre-existing fields and will display rounded values to the nearest cent. Moov will apply standard rounding on all existing amount fields with the exception of the wallet and wallet transactions `availableBalance`, which will round **down** to the nearest cent. This will prevent transfers being created from a wallet where the amounts may exceed the precise balance available. The `walletTransaction.updated` webhook event has been updated with a new `valueDecimal` field to support the same level of precision. ## Creating accounts We've refreshed the account creation flow in the Moov Dashboard for greater speed and clarity. When creating accounts in the Dashboard, you will now go through a customized flow based on the capabilities you've requested. ## ToS acceptance for server-side integrations For those developing server-side integrations, Moov now lets you manually pass the required terms of service information to us via the account `POST` and `PATCH` [endpoints](/api/moov-accounts/accounts/create/). ## Closed cards Cards that have received an `account-closed` update will have `card_on_file` set to `false` and no longer receive updates. Merchants should disable these closed cards. --- URL: https://docs.moov.io/changelog/2023-11-01/ --- # Interchange qualification and passthrough fees * * * ## Interchange qualification For greater transparency, `GET` and `LIST` transfer endpoint responses now include the `interchangeQualification` field under `cardDetails`, surfacing the card network program that determines the interchange rate. ## Passthrough network fees Moov now provides additional granularity on the `moovFee` in the API. You can now view the various passthrough network fees charged once a transfer moves to a completed status. The `moovFee` will be broken out into three buckets: - `interchange` - `cardScheme` - `moovProcessing` You can read more about the breakdown of card processing fees in our [passthrough fees](/guides/money-movement/accept-payments/card-acceptance/passthrough-fees/) guide. --- URL: https://docs.moov.io/changelog/2023-11-09/ --- # Transfer timestamps Moov has updated transfer timestamps to appear under the new `railDetails` object. The `statusUpdates` object is now deprecated. ## Transfer timestamps Moov now provides an additional layer of transparency on transfer status changes to provide customers with as much data as possible on where funds are at any given moment. Transfer timestamps are now available in the API and are coming to the Dashboard soon. These timestamps are helpful for those looking to: - Automate money movement flows based on when a transfer is originated - Know when a transfer completed to understand when the destination received the funds When you use the transfer `GET` [endpoint](/api/money-movement/transfers/get/), we now provide a `statusUpdates` object where you can view a transfer's status. Specifically: `source.cardDetails.statusUpdates` now contains the following timestamps: - initiated - confirmed - settled - completed - canceled - failed `source.achDetails.statusUpdates` and `destination.achDetails.statusUpdates` now contain the following timestamps: - initiated - originated - completed - corrected - returned If a transfer has completed, the top-level response on the transfer `GET` [endpoint](/api/money-movement/transfers/get/) will include a `completedOn` timestamp field. If the transfer has not completed, the `completedOn` timestamp will not appear. --- URL: https://docs.moov.io/changelog/2023-11-21/ --- # Improvements and bug fixes ## Improvements - For account onboarding and adding a representative, we have updated the address fields to show the full zip code in the Dashboard. - When providing a website for a business profile in the Dashboard, you are no longer limited to sites that start with `https://`. ## Bug fixes - Previously, our warning copy would incorrectly mark a failed verification as missing information in the Dashboard. We've updated the warning copy to indicate an error could be due to missing information or failed verification. - We also fixed an issue in the Dashboard where the account list was not properly filtering by verification state. - We updated the [underwriting](/api/moov-accounts/underwriting/) endpoint so that when you pass an invalid dollar amount with decimals, you receive a `422` response (indicating unprocessable content) rather than a generic `500` internal server error response. --- URL: https://docs.moov.io/changelog/2023-12-05/ --- # New transfer creation flow and more ## New transfer creation flow We’ve released a new transfer creation flow in the Moov Dashboard to simplify the end-to-end experience. You will now see a dedicated page to create a transfer versus the previous modal. More features for this flow are coming soon. ## Interchange qualification We have deprecated the `interchangeQualification` field on the `GET` and `LIST` transfers [endpoints](/api/money-movement/transfers/get/). We will now surface the card network program that determines the interchange rate in the `feeProgram` field. ## Transfer timestamps The timestamps in the transfers `statusUpdates` object have moved to the existing objects `achDetails` and `cardDetails` on the transfers and refunds `GET` endpoints. The `statusUpdates` object will be deprecated. Along with this change, we've updated transfer details to include an improved timeline in the Dashboard. You will now see progress bars with clickable steps to view the timestamps associated with each stage of the transfer. --- URL: https://docs.moov.io/changelog/2023-12-19/ --- # API reference redesign and more ## API reference redesign We’ve redesigned the [Moov API reference](/api) so that it’s now easier to read and understand each endpoint. Every endpoint now has its own page for enhanced clarity. ## Mobile search for Moov docs We have improved the mobile experience for interacting with Moov's docs. You can now search [docs.moov.io](https://docs.moov.io/) on mobile browsers. ## American Express network discount fee property The transfer response model now contains a new `discount` property within the `moovFeeDetails` object. The value represents the network discount fee for American Express transactions only. Note the `interchange` property within `moovFeeDetails` applies to fees for Visa, Mastercard, and Discover transactions. ## Document requirements for capabilities The retrieve capability `GET` [endpoint](/api/moov-accounts/capabilities/get/) and list capabilities `GET` [endpoint](/api/moov-accounts/capabilities/list/) now communicate when Moov requires a document to complete verification and enable capabilities for an account. The same information is also communicated via the Moov Dashboard. We recommend subscribing to the [capabilities webhook](/guides/webhooks/webhook-events/#capabilities) for any changes to account requirements, then using the list capabilities `GET` [endpoint](/api/moov-accounts/capabilities/list/) to determine what documentation is needed. ## Outstanding pending capabilities We started cleaning up old requested capabilities for accounts. If a capability is pending and has missing requirements for 90 days, we will automatically un-request it. Capabilities that are un-requested can be re-requested at any time. ## Bug fix We resolved a bug in the Dashboard where acceptable websites were previously flagged as invalid. --- URL: https://docs.moov.io/changelog/2024-01-09/ --- # Ask Moov, bank account statuses, & more ## Ask Moov Ask Moov is a new generative AI search tool within [docs.moov.io](/) that makes searching for answers easy. Use the search field at the top of the page to type your question, and press return. You'll get a summarized answer, plus links to sources within Moov documentation with more information. ## Updated bank account response The bank account response model now includes a new `statusReason`, which explains why a status has changed. If the change was caused by an ACH return, you will also now see `achReturnCode` and `exceptionDetails` fields. We’ve also added a new `updatedOn` field to show when a status update occurred. This field has been retroactively added to all updates, however, all updates prior to 2024 should expect to see a timestamp in December of 2023. The new fields are viewable within the `bankAccount.updated` webhook, the bank account `GET` [endpoints](/api/sources/bank-accounts/), and within the Moov Dashboard. ## Business representative requirements As of January 8th, we'll be requiring the full social security number for business representatives and individuals that need to be verified. We'll be reaching out and asking for this information if it's missing from current representatives. ## Payment method IDs in the Dashboard It’s now easier to find payment method IDs in the Dashboard. These IDs can easily be copied when viewing any wallet, and on the bank account and card detail views. ## Design We gave the Dashboard a fresh coat of paint for the new year, but don't worry, your workflow is not impacted. We improved the contrast on buttons, made better use of available space, and added other design-related improvements. Moov is a progressive web app, so we're constantly looking at how we can improve the look and functionality on every device. Our [documentation](/) now supports both light mode and dark mode. The site will update per your OS settings. --- URL: https://docs.moov.io/changelog/2024-01-23/ --- # New payment methods query parameter ## Payment methods query parameter The list payment methods [endpoint](/api/sources/payment-methods/list/) includes a new query parameter, `paymentMethodType`, which fetches payment methods by type. In practice, this means you could combine `paymentMethodType` with the existing `sourceID` parameter to find the `push-to-card` payment method for a particular card ID, or the `rtp-credit` payment method for a particular bank account. ## Moov fees on completed transfers Moov fees (`moovFeeDetails`, `moovFee`, `moovFeeDecimal`) will now populate once when a transfer completes with final fee amounts. Previously, fees would be populated after authorization and then updated with final amounts on transfer completion. ## Facilitator fees in the Dashboard You can now add a facilitator fee when creating a transfer in the Dashboard. --- URL: https://docs.moov.io/changelog/2024-02-21/ --- # Instant disbursements with push to card and RTP ## Instant disbursements with push to card and RTP Moov has enabled immediate payouts to linked debit cards and bank accounts via Visa Direct, Mastercard Send, and RTP. This feature is now fully available in [test mode](/guides/get-started/test-mode/) and to early adopters in production, with use cases for loan disbursements, gig payouts, and ecommerce settlements. ### Instant disbursements unlocked - **Around-the-clock availability**: Execute payments to debit cards or bank accounts any time, including weekends and holidays. - **Create new revenue streams**: Offer end users the option for faster payments and leverage facilitator fees to unlock new revenue opportunities. ### Push-to-card: Quick funds for debit card users For enabled [push to card](/guides/money-movement/send-payments/push-to-card/) customers, a new **`push-to-card`** payment method is automatically generated when an eligible debit card is linked to a Moov account. Transfer funds between a **`moov-wallet`** and **`push-to-card`** payment method and see them credited within 30 minutes or less. ### RTP: Real-time bank transfers With [RTP](/guides/money-movement/send-payments/rtp/), you can instantly transfer funds from a Moov wallet to eligible bank accounts. The **`rtp-credit`** payment method is automatically generated for eligible bank accounts and will automatically update as additional banks join the RTP network. ### Available in test mode View the [push to card](/guides/get-started/test-mode/#push-to-card--pull-from-card) and [RTP](/guides/get-started/test-mode/#rtp) test mode guides to see how you can experience the full capabilities of instant disbursements on test accounts with pre-populated sample data. ### Enable in production To use instant disbursements in a production environment, [contact us](https://moov.io/contact/). ## Terms of service Moov Drop Our new, pre-built [terms of service Drop](/moovjs/drops/terms-of-service/) provides users links to our privacy policy and terms of service agreement. We’ll generate a token in the background that you can use to update the account to be compliant with Moov’s terms of service. ## Disconnect accounts with the API We’ve added a new `DEL` endpoint in the `/accounts` API. Provide the account and bank account IDs to disconnect an account. See the [API reference](/api/sources/bank-accounts/delete/) for more information. ## Updated link card response We’ve updated the link a card `POST` [endpoint](/api/sources/cards/create/) to save you time by including the payment method IDs for the card in the response. You’ll no longer need to make a separate call to retrieve them when immediately making a transfer after linking a card. ## Failed transfer status update If money fails to reach the destination in a wallet-to-bank transfer, the status will now appear as `failed` to align with our status definitions (previously, the status would appear as `reversed`). Historical transfer statuses will not be changed. --- URL: https://docs.moov.io/changelog/2024-03-05/ --- # Debt repayment transfers ## Debt repayment transfers Merchants that service loans or other debt payments may be eligible for lower interchange fees by enabling debt repayment for their account. See our [debt repayment](/guides/money-movement/card-acceptance/debt-repayment/) guide for more information, or [contact us](https://moov.io/contact/) if you have a debt repayment use case. ## American Express Moov now supports American Express card processing. If you're interested in processing Amex, please [contact support](https://support.moov.io/). ## SEC codes You now have the option of specifying an SEC code in certain ACH transfer request scenarios. The following SEC codes are available to set: `CCD`, `PPD`, `WEB`, and `TEL`. See our [ACH transfer](/guides/money-movement/ach/#sec-codes) guide for more information. ## API updates **Deprecation notice** The following two fields related to accounts have been deprecated: - [Account](/api/moov-accounts/accounts/) `verificationStatus` - [Underwriting](/api/moov-accounts/underwriting/) `status` To determine if an account is able to perform a given action, look for changes in the status of the [requested capabilities](/api/moov-accounts/capabilities/list/) for an account. **New capability status** The new `in-review` capability status communicates when Moov is manually reviewing account details to enable a capability - you don't need to take any further action. The existing `pending` status will notify you if further action is needed, for example, providing any missing capability requirements. Please review your app to determine if you’re making use of the deprecated fields, or if the addition of the new `in-review` capability status will negatively impact your system. --- URL: https://docs.moov.io/changelog/2024-03-20/ --- # Pull from card & disputes in test mode ## Pull from card available in test mode You can now use test card numbers for both `pull-from-card` and `push-to-card` payment methods. You can use these payment methods in test mode to simulate completed and failed Visa and Mastercard transfers. To use these payment methods in test mode, you'll need to remove existing test card numbers. This includes `4111111111111111` for transfers and/or `4000020000000000` for declines. Find more information and instructions in the [test mode](/guides/get-started/test-mode/#push-to-card--pull-from-card) guide. ## Disputes available in test mode Test card numbers are also now available to simulate disputes for Visa, Mastercard, Discover, and American Express. You can simulate chargebacks, as well as American Express inquiry disputes. Find more information and instructions in the [test mode](/get-started/test-mode/#disputes) guide. ## Reminder: API field updates Last week, we announced new deprecated fields: - [Account](/api/moov-accounts/accounts/) `verificationStatus` - [Underwriting](/api/moov-accounts/underwriting/) `status` Review your app to determine if you’re still using the deprecated fields. We also announced a new `in-review` capability status. The `in-review` status communicates when Moov is manually reviewing account details to enable a capability — you don't need to take any further action. The existing `pending` status will notify you if further action is needed, for example, providing any missing capability requirements. Review your app to determine if the new `in-review` capability status will negatively impact your system. --- URL: https://docs.moov.io/changelog/2024-04-02/ --- # Disputes response endpoint and more ## Disputes updates When a merchant receives a dispute, they can now accept or challenge the dispute through the disputes response endpoint in the API. We’ve also added a new `dispute.updated` [webhook](/guides/webhooks/webhook-events/#disputes) that will generate if there is a change to a dispute’s `status` or `phase` . [Disputes guide](/guides/money-movement/accept-payments/card-acceptance/disputes/#respond-to-disputes) [Disputes endpoints](/api/money-movement/disputes/) ## Dashboard bug fix We resolved an issue in the Dashboard where business address details weren’t carried over from the autofill form field to the manual address entry fields. ## Reminder: API field updates This is a final reminder to review your app to determine if you’re still using the deprecated fields listed below, or if the new `in-review` capability status will negatively impact your system. Read more for context below. A few weeks ago, we announced new deprecated fields: - [Account](/api/moov-accounts/accounts/) `verificationStatus` - [Underwriting](/api/moov-accounts/underwriting/) `status` We also announced the `in-review` capability status, which communicates when Moov is manually reviewing account details to enable a capability — you don’t need to take any further action. The existing `pending` status will notify you if further action is needed, for example, providing any missing capability requirements. --- URL: https://docs.moov.io/changelog/2024-04-16/ --- # Data sync, test mode updates, & more ## Data sync [Data sync](/guides/developer-tools/data-sync/) is a new no-code feature that sends your Moov account data to Google BigQuery, allowing you to access your payment data with tools you use to run your business, like Looker and Tableau. ## Test mode updates - Winning and losing disputes: You can now simulate winning or losing disputes by entering the text evidence specified in the [test mode guide](/guides/get-started/test-mode/#disputes). - RTP failures: We also added the ability to simulate various failure scenarios with RTP in test mode. See the [test mode guide](/guides/get-started/test-mode/#rtp) for the list of failure cases. ## ACH micro-deposit return code update An R29 return code for ACH micro-deposits will now result in the bank account status `verificationFailed` and you will need to re-verify the account. See our [documentation on ACH return codes](/guides/money-movement/accept-payments/ach/returns/#return-codes) for more information. Note that some return codes will result in a different status for ACH micro-deposits and ACH transfers. --- URL: https://docs.moov.io/changelog/2024-04-30/ --- # Dashboard updates We’ve made a variety of small improvements to the accounts section of the Dashboard. Keep reading for more details on what's changed. ## Peek preview for accounts lists We’ve added [peek preview](/guides/dashboard/accounts/#peek-preview) functionality to the accounts list view in the Dashboard. Press the `space` key to toggle the preview on and off. You can move your cursor up and down the accounts list and the preview will update with the corresponding account information. The `esc` key will also dismiss the preview. ## Capability requirements We removed **verification status** and replaced the status with an indicator that reflects if any capabilities have requirements pending for a particular account. Read our [Dashboard accounts guide](/guides/dashboard/accounts/#view-errors-and-actions) for more details. ## Filter accounts by capability & capability status You can now [filter accounts by capability](/guides/dashboard/accounts/#filter-accounts-by-capability) or capability status, allowing you to quickly surface specific account lists by capability-specific criteria. --- URL: https://docs.moov.io/changelog/2024-05-14/ --- # Optional Visa name verification field ## Visa name verification field For Visa cards, we support Visa’s Account Name Inquiry (ANI) for enhanced cardholder verification. ANI is an optional tool that ensures the name provided on the linked card matches the name held on file with the issuer. There is a new optional `verifyName` field in the [link a card](/api/sources/cards/create/)`POST` and [update card](/api/sources/cards/update/) `PATCH` endpoints for requesting this name verification. Results of the verification request are returned in the `cardVerification.accountName` as shown in the sample response object below: ```jsx { "cardVerification": { "accountName": { "fullName": "match", // Options: noMatch, match, partialMatch, notChecked "firstName": "match", // Options: noMatch, match, partialMatch, notChecked "middleName": "noMatch", // Options: noMatch, match, partialMatch, notChecked "lastName": "match" // Options: noMatch, match, partialMatch, notChecked } } } ``` --- URL: https://docs.moov.io/changelog/2024-05-29/ --- # Moov.js version update and API docs ## Moov.js version update We identified a long-standing issue with Moov's client-side JavaScript SDK, Moov.js. Due to a misconfiguration, it was possible for users to cache outdated versions of Moov.js in their local browsers and experience page-breaking `404` errors following the release of a new version of Moov.js. Users would then have to manually clear their local browser cache to resolve the issue. We resolved this issue with the release of Moov.js v0.6.12 on May 14, 2024. If your website used Moov.js prior to that date, some of your users may have outdated versions of Moov.js stored in their browser cache. If your codebase used Moov.js prior to May 14, 2024, please review your codebase for the url `https://js.moov.io/v1`, and update the url to `https://js.moov.io/v1?min=v0.6.12`. ## Cards endpoints documentation Our API docs now reflect previously undocumented fields already present in our cards endpoints. In the update a card `PATCH` [endpoint](/api/sources/cards/update/) documentation, we now include the `merchantAccountID` as an optional field in the request body. We also now document the following fields returned in `200` responses for the link a card `POST` [endpoint](/api/sources/cards/create/) as well as the update a card `PATCH` [endpoint](/api/sources/cards/update/): - `issuerPhone` - `issuerURL` - `cardCategory` --- URL: https://docs.moov.io/changelog/2024-07-09/ --- # Hosted onboarding ## Hosted onboarding (coming soon) Soon you'll be able to use Moov's hosted onboarding forms to cut down the time it takes to onboard users. You'll create an invite and send a secure form link from the Moov Dashboard. Users will move through the onboarding flow and provide data necessary to fulfill capability requirements, agree to pricing, and accept Moov's terms. Once users complete the onboarding form, you'll be notified in the Dashboard that they're ready to move money. You can start building for this new flow now. See our [hosted onboarding](/guides/accounts/hosted-onboarding/) guide and our [API reference](/api/moov-accounts/onboarding/) for details. ## Disputes in the Dashboard You can now fully manage disputes in the [Dashboard](https://dashboard.moov.io/signin). You can view, accept, delete, and update disputes, as well as view, upload, and update dispute evidence. ## Updates to dynamicDescriptor Accounts must now be approved by Moov to use the `dynamicDescriptor` field - an optional field to override the default card statement descriptor on a transfer. View our [documentation](/guides/money-movement/accept-payments/card-acceptance/statement-descriptors/#transfer-level-statement-descriptor) for more details. ## Changes to capability requirements Capability requirements have updated to reflect financial institution exemptions and additional underwriting requirements. ### Financial institution exemptions US state and/or federally regulated financial institutions are exempt from [beneficial ownership](/guides/accounts/requirements/business-representatives/#owner) requirements. Our account onboarding process will conditionally require a financial institution to provide their primary regulator during signup, which will be communicated through capability requirements. Additionally, providing [business representatives](/guides/accounts/requirements/business-representatives/) is not a requirement for these financial institutions. ### Underwriting requirements Additional fields have been added for account underwriting that detail fulfillment, return policies, and the type of volume expected by merchants. If you aren't already, ensure you're providing these fields. See the [underwriting API](/api/moov-accounts/underwriting/put/) for more details. --- URL: https://docs.moov.io/changelog/2024-08-01/ --- # Instant micro-deposit verification ## Instant micro-deposit verification Instant micro-deposit verification introduces a faster and easier way to verify bank account ownership. This feature enables instant account verification for RTP-enabled bank accounts, allowing users to complete the process in seconds — an improvement over the traditional, multi-day, micro-deposit method. For accounts not yet RTP-enabled, the code is sent via same-day ACH. Use instant micro-deposit verification to: - Instantly verify accounts for RTP-enabled banks in a single session - Ensure broad compatibility with automatic fallback to same-day ACH for other institutions - Meet Nacha account validation requirements - Enhance user experience with a quick, easy verification process How it works: 1. Moov sends a $0.01 credit to the user's bank account 2. This credit contains a unique verification code 3. Users retrieve and enter the code to verify their account instantly (for RTP) or later that day (for same-day ACH) See our [documentation](/guides/sources/bank-accounts/verification/instant-micro-deposit/) for more information. ## Cards API response updates New fields, `commercial` and `regulated`, will now be included in successful responses for the link a card, update a card, retrieve a card, and list cards [endpoints](/api/sources/cards/). Both of these fields provide additional details for a card: - `commercial` indicates whether the card is for commercial or personal use - `regulated` indicates whether the card's issuing bank is subject to capped debit interchange rates under the Durbin Amendment. This is determined by the asset size of the issuing bank. A value of `true` means the issuing bank’s asset size qualifies for the cap on interchange fees. --- URL: https://docs.moov.io/changelog/2024-09-04/ --- # Sweeps & scheduling betas ## Sweeps (beta) You can now set up sweeps, which work on autopilot, sending daily transfers to external bank accounts. A sweep will payout funds from a wallet, or pull funds to cover fees and chargebacks. [Contact us](https://moov.io/contact/) if you'd like to try out sweeps. See our [sweeps](/guides/money-movement/wallets/sweeps/) guide and [API](/api/money-movement/sweeps/) documentation for more information. ## Scheduled transfers (beta) We're making it easier to create future-dated transfers through scheduling. Moov is looking for early adopters to test scheduling in beta and provide feedback. View our new guide on [scheduling transfers](/guides/money-movement/scheduling/) for more information, or [contact our team](https://moov.io/contact/) if you're interested in participating. ## End-to-end encryption You can now use our API to generate a public key for passing secure authentication data through non-PCI compliant intermediaries, or create a JWE test token to ensure it’s acceptable by Moov. See our [API](/api/authentication/e2ee/) documentation for more information. ## Drops pseudo-class support & bug fix All input [pseudo-classes](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes#input_pseudo-classes) are now supported on Moov's composable Drops. You can style Drops based on form validity, user input interaction, and input value. Visit our [Drops documentation](/moovjs/drops/composable-drops/) for more information. An issue with input validity has been fixed. --- URL: https://docs.moov.io/changelog/2024-09-17/ --- # Additional linked bank account types ## Additional linked bank account types Moov now supports general ledger and loan linked bank account types. Loan accounts allow sending credits to external loan accounts for repayment. General ledger accounts allow financial institution users to link their general ledger accounts. See our [bank account](/guides/sources/bank-accounts/#account-types) guide for more information. ## Test card updates The data for `cardCategory`, `regulated`, and `commercial` has been updated for test mode cards. For the test card starting with number 411111: - `cardCategory` is "PERSONAL" - `regulated` is **true** For the test card starting with number 601111: - `cardCategory` is "TRADITIONAL REWARDS" - `commercial` is **true** --- URL: https://docs.moov.io/changelog/2024-10-01/ --- # Updates to test mode, API, Go SDK, Dashboard & more ## Account name inquiry in test mode Test mode now supports name verification with Visa's ANI verification. You can test various results by entering in different name combinations. View our [test mode](/guides/get-started/test-mode/#name-verification) guide for more information. ## New transfer history endpoints Two new endpoints have been added to the accounts API: - `/accounts/{accountID}/transfers/{transferID}` - `/accounts/{accountID}/transfers` These endpoints allow you to [retrieve an account transfer](/api/moov-accounts/accounts/get-transfers/) or [list account transfers](/api/moov-accounts/accounts/list-transfers/) using query parameters. Moving forward, we suggest using the new list account transfers endpoint over the existing [list transfers](/api/money-movement/transfers/list/) endpoint. ## Go SDK updates [Webhook](/guides/webhooks/webhook-events/#wallet-transactions) support for sweeps has been added to the Go SDK. Additionally, the `verifyName` field has been added on `POST /cards` and the `verifyName` and `holderName` fields have been added on `PATCH /cards/{cardID}` to support ANI verification. ## API updates We've relaxed the validation for the `website` field within a [business profile](/api/moov-accounts/accounts/create/) to allow paths. ## Dashboard updates We added the ability to search by `sweepID` in the wallet view of the Moov Dashboard (previously this was only available via the API). ## Bug fix We fixed a bug where an account's capabilities could show a `pending` status with no listed requirements. --- URL: https://docs.moov.io/changelog/2024-10-15/ --- # Moov Drop enhancements, sweep statement descriptor, & more ## Moov Drops We freshened up the design of the onboarding, payment method, and file upload Moov Drops, improving behavior on small screens and increasing color contrast and legibility. You can now customize the border radius of elements within the onboarding, payment method, and file upload Moov Drops. Use `--moov-radius-large` and `--moov-radius-small` in your theme to change them from the default. Show your business' avatar on the start page of the onboarding Drop by adding the `showLogo` property to the component or setting the `show-logo` attribute to `true`. ```html ``` - Financial institutions will be asked for their primary regulator from the onboarding Drop. - Loan linked bank account type can be added from the payment method and onboarding Drops. ## Wallets Now by default, transfers created by sweeps include a short, unique identifier used in company entry descriptions which appear on the recipient’s bank statement. On each sweep, you can view this descriptor in the `statementDescriptor` field. ## Accounts The transfers capability no longer requires a website or description for businesses. ## Bug fixes - Improved error handling for the add funds flow. - Fixed a bug in which disabled payment options were being returned as transfer options. - Fixed a bug where the status reason for RTP credit failure was not appearing. - Fixed a bug where transfer details stopped loading when viewing multiple transfers back to back. - Fixed a bug where RTP transactions were showing `0000` as the `transactionID` instead of `MOOV`. - Fixed a bug where the account selector in the Dashboard eventually stops working. - Fixed a bug where ACH credit failures were not producing the correct failure response. - Fixed a bug where accounts were receiving a message that a website or description was missing even though the requirement has been removed. - Fixed misspelling of "website" in an error message in the onboarding Drop. - Fixed an issue that prevented Moov Drop dialogs from scrolling vertically on small screens. - Fixed an issue where the representative avatar was loading the main Moov account avatar instead in the onboarding Drop. --- URL: https://docs.moov.io/changelog/2024-10-29/ --- # Transfer, Dashboard & card brand updates ## Transfer updates The following IDs have all been added to the transfer model: - `sweepID` - `occurrenceID` - `scheduleID` The sweep ID is present when the transfer represents a sweep generated by Moov from the wallet. The schedule ID provides a reference to the schedule the transfer was automatically created from. The occurrence ID provides a reference to the specific occurrence of that schedule. Moov recently released a [scheduled transfers](/guides/money-movement/scheduling/) beta. The new schedule ID and occurrence ID make it easier to filter and find scheduled transfers. See our [scheduling API](/api/money-movement/schedules/create/) for more details. In addition, the default statement descriptor on a sweep is now in the following format: `swp_6d72dh`. The default sweep statement descriptor can be overwritten by setting your own statement descriptor when initiating a sweep. See the [API reference](/api/money-movement/sweeps/create-config/) for details. ## Mastercard settlement timing Mastercard has updated their cutoff time for processing card payments. The cutoff is now 2 AM ET instead of 6 PM ET. Transfers created before the cutoff time are typically credited to a merchant’s Moov wallet the next banking day. See our [settlement timing](/guides/money-movement/accept-payments/card-acceptance/timing/) guide for more information. ## Dashboard bug fixes - Fixed an issue where the capability status would be shown as "In Review" instead of "Pending" in certain situations. - Fixed an issue where the search bar would be hidden if the search request by ID had no results. - Fixed an issue where an error would appear instead of an empty result when searching for accounts. ## Card brand updates We've implemented the standard fall updates for card brands, including new interchange calculation tables. ### American Express We've implemented American Express's new discount fees for utility merchants: | Pricing | Threshold | Discount fees | |---------|-----------------------|---------------| | Tier 1 | ≤$1,000.00 | 0.00% + $0.75 | | Tier 2 | $1,000.01 - $5,000.00 | 0.00% + $1.50 | | Tier 3 | >$5,000.01 | 2.30% | ### Visa We've implemented Visa's interchange changes for the following programs: New installment credential standard credit product for AP region: | Interchange program | Fee | |-------------------------|-------| | Premium Card - Base Fee | 1.85% | Changes for corporate & purchasing fee programs for transactions from fleet & fuel merchants: | Interchange program | Fee | |------------------------------|---------------| | Commercial Fuel Level 2 Data | 2.20% + $0.10 | | Commercial Fuel Level 3 Data | 1.90% + $0.10 | Two fee programs will **no longer** be supported: | Interchange program | Fee | |--------------------------------|---------------| | X Corporate Card Fuel Level 2 | 2.20% + $0.10 | | X Purchasing Card Fuel Level 2 | 2.20% + $0.10 | --- URL: https://docs.moov.io/changelog/2024-11-12/ --- # Updates to branding options, Moov.js & more ## Branding options Business accounts now have the ability to set brand colors for light and dark modes. You can choose and set brand colors in the Dashboard settings or with the enrichment [API](/api/enrichment/branding/). Brand colors help your customers identify your brand throughout Moov's hosted onboarding process. ## Moov.js Linking a bank account will now send a request with the `x-wait-for: payment-method` header, allowing for client apps to use the `paymentMethodID` that comes back in the response. Moov.js now includes methods for using Moov’s new \[instant bank account verification](moov.accounts.bankAccounts.startMicroDepositVerification({accountID, bankAccountID})) flow. - `moov.accounts.bankAccounts.startVerification({accountID, bankAccountID})` - `moov.accounts.bankAccounts.getVerification({accountID, bankAccountID})` - `moov.accounts.bankAccounts.completeVerification({accountID, bankccountID, code})` See the [Moov.js docs](/moovjs/sources/bank-accounts/) for more information. ## General improvements - Improved the success rate of auto-fetching images for Moov accounts and financial institutions on linked bank accounts. - Added `EIN` as an available field for use with Data Sync. - Dashboard sign in verification codes are delivered faster. ## Bug fixes - Fixed a bug with card fee assessments. - Fixed a bug with American Express chargeback inquiry processing. - Fixed a bug preventing date of birth from being entered in the Dashboard onboarding process. - Fixed an issue where Moov account capabilities could be in a `pending` status without requirements. --- URL: https://docs.moov.io/changelog/2024-11-26/ --- # Drops improvements ## Onboarding Drop We've improved the [onboarding Drop](/moovjs/drops/onboarding/) experience. The business representative steps will now be skipped if only the transfer capability is requested. ## Card link Drop bug fix We've fixed an issue in the [card link Drop](/moovjs/drops/card-link/) where the error icon was not honoring the fill opacity. --- URL: https://docs.moov.io/changelog/2024-12-09/ --- # Cards, wallets, disputes & more ## International card acquiring support To support international card acquiring, a card's billing address now supports postal codes up to 10 characters. Additionally, the card's issuing country will be included when retrieving information about card transactions. ## Wallet adjustments Scenarios occur where Moov may make an immediate adjustment to a wallet’s balance, such as partial chargebacks, fee adjustments, or corrections from transaction processing. Upon adjustment, you’ll get a `walletTransaction.updated` webhook notification and can find the adjustment reason in the wallet transaction memo. Two endpoints have been added to retrieve further details about wallet adjustments: - [Retrieve a wallet adjustment](/api/sources/wallets/get-adjustment/) - Gets a specific wallet adjustment - [List wallet adjustments](/api/sources/wallets/list-adjustments/) - Lists all adjustments associated with a wallet See our [wallet documentation](/guides/sources/wallets/transactions/#adjustments) for more information. ## Updated dispute paths The paths for all dispute endpoints have been prefixed with `/accounts/{accountID}` to scope permissions to the specified account. For example, to retrieve a list of all disputes: `/disputes` has become `/accounts/{accountID}/disputes` We suggest updating all endpoints in your application as soon as possible. See our [disputes API](/api/money-movement/disputes/) for more information. ## Updated velocity limits Velocity limits for Visa and Mastercard push to card transactions are now the following: | Limit type | Maximum limit | |-----------------|------------------------------| | Amount | $25,000 | | 1-day velocity | 150 transactions or $100,000 | | 7-day velocity | 250 transactions or $250,000 | | 30-day velocity | 750 transactions or 500,000 | ## Updated Apple Pay scopes Apple Pay scopes have been updated from apple-pay.write and apple-pay.read to the following: - apple-pay-merchant.write - apple-pay-merchant.write ## Bug fixes - Fixed an account linking bug in the payment method Drop - Added missing `400` responses to the cards and accounts endpoint documentation --- URL: https://docs.moov.io/changelog/2025-01-09/ --- # Wallet fund timing & bug fixes If you're subscribed to our changelog emails, we will now be sending from hello@moov.io. If you haven't already, please add this domain to your safe list so you don't miss any changelog emails. ## Wallet fund timing For card payments, wallets are now funded by 1PM ET instead of 6PM ET. See our [documentation](/guides/money-movement/accept-payments/card-acceptance/timing/) for more details on settlement timing. ## Bug fixes - Fixed an issue where network fees were not being estimated. - Fixed a bug where memos were not appearing on moov-fee wallet transactions. - Fixed a bug where the facilitator view button in the Dashboard was not switching account views. ## Product release roundup 2024 Read our newest [product release](https://moov.io/blog/product/2024-recap/) blog post for a roundup of Moov's most exciting launches of 2024. --- URL: https://docs.moov.io/changelog/2025-01-23/ --- # Payment links & more ## Payment links You can now create payment links to accept payments. A payment link authenticates a session that lets your customers securely create a Moov account and link payment methods before submitting payment through a generated link or QR code. A payment link can accept the following payment methods: - Apple Pay - Card - ACH debit collect View our [payment links](/guides/money-movement/payment-links/) documentation and [API](/api/money-movement/payment-links/) for more information. Payout payment links coming soon. ## Pull from card dispute testing In test mode, we've added one Mastercard and one Visa card number to simulate disputes for pull from card transfers. See our [test mode](/guides/get-started/test-mode/#disputes) guide for more information. ## Fixes & updates - Added missing documentation and error responses to the [access token](/api/authentication/access-tokens/) endpoints - `ACHStatus` now includes `canceled` ### Upload evidence dispute endpoint The following updates have been made to the [upload evidence file](/api/money-movement/disputes/post-file/) endpoint: - Specifies what types of dispute files can be uploaded: - `image/jpeg` - `image/tiff` - `application/pdf` - Additional `201` response has been added with the following fields: - `evidenceID` - `disputeID` - `evidenceType` - `createdOn` --- URL: https://docs.moov.io/changelog/2025-02-04/ --- # Bug fixes & updates ## Bug fixes - Fixed a Dashboard issue where the **Fix now** button for capability requirements was not working - Fixed a test mode disputes issue where `chargebackReversed` was not receiving the full `chargeback` amount - Fixed the [evidence text](/api/money-movement/disputes/post-text/) response body, which was not showing all fields ## Updates - Added missing `409` response to the [create brand](/api/enrichment/branding/create/) endpoint - Added missing `4XX` response codes to [delete dispute evidence](/api/money-movement/disputes/delete/) endpoint - Added an undocumented `text` field to the [list dispute](/api/money-movement/disputes/list/) evidence endpoint - Added missing query parameter `walletID` to the [list adjustments](/api/sources/wallets/list-adjustments/) endpoint - Added missing scope documentation for [sweeps](/api/money-movement/sweeps/) and [adjustments](/api/sources/wallets/) endpoints --- URL: https://docs.moov.io/changelog/2025-02-20/ --- # Pricing fee plans ## Fee plans When you onboard merchants, you'll now have the ability to create and assign fee plans. Moov is introducing flexible pricing plans that let you have more control over interchange, card network, and Moov fee. When you create a fee template, you can assign it to one or many merchants. Flat rate plans lump fees together and can be customized per merchant, whereas cost plus plans pass interchange and Moov fees along to the merchant. Moov suggests onboarding merchants and selecting fee plans through our [hosted onboarding](/guides/accounts/hosted-onboarding/) process. You can view a list of billable events that incur fees in our [pricing](/guides/fee-plans/plan-options/#billable-events) guide. --- URL: https://docs.moov.io/changelog/2025-03-06/ --- # Cancellations & new SDKs ## Cancellations You can now cancel ACH and card transfers through the API or the Dashboard. There is a limited window where you are able to initiate a cancellation. See following resources for more information: - [ACH cancellations](/guides/money-movement/accept-payments/ach/cancellations/) - [Card cancellations](/guides/money-movement/accept-payments/card-acceptance/reversals/#initiate-a-cancellation) - [Transfers API](/api/money-movement/transfers/) ## New SDKs We've updated and expanded our [server-side SDKs](/sdks/)! Moov now offers the following new SDKs: - [Typescript](/sdks/typescript/) - [PHP](/sdks/php/) - [Java](/sdks/java/) - [Python](/sdks/python/) Moov's Node SDK is no longer supported. To receive support or access to new features, migrate to the [Typescript SDK](https://github.com/moovfinancial/moov-typescript) (or any of the new SDKs listed above). ## Updated transfer & refund paths The paths for all transfer and refund endpoints have been prefixed with `/accounts/{accountID}` to scope permissions to the specified account. For example, to retrieve a list of all transfers: `/transfers` has become `/accounts/{accountID}/transfers`. We suggest updating all endpoints in your application as soon as possible. See our [transfers API](/api/money-movement/transfers/) and [refunds API](/api/money-movement/refunds/) for more information. --- URL: https://docs.moov.io/changelog/2025-03-18/ --- # Dashboard updates & bug fixes ## Dashboard updates - More linked card details are now available in the Dashboard. If you've performed account name verification on a linked card, the results will be visible. Additionally, the card category will now show whether a card is consumer/commercial, or regulated/non-regulated - From the transfer details screen, you can now copy the `accountID` and the `paymentMethodID` from the source and destination cards. - You can now apply multiple transaction type filters for wallet transactions. ## Bug fixes - Fixed a bug where multiple wallets were appearing for an account search. When assessing fees, you can now filter wallets based on the account facilitating the transfer. - Fixed a bug with synchronous cancellation response. - Fixed a bug where ACH and card status were not updating properly after a void. - Fixed a bug where not all transfers were appearing in the list transfers response. --- URL: https://docs.moov.io/changelog/2025-04-03/ --- # Branded receipts, sales tax & more ## Branded receipts Moov has added branded receipts to the [Dashboard](https://dashboard.moov.io/signin) and [API](/api/money-movement/transfers/create-receipts/) which can be sent to buyers/payees once a transfer has initiated or completed. You'll identify which transfer the receipt is for and choose the account's email address on file, or enter an email manually. For scheduled transfers, you can create the receipt with the `scheduleID` and Moov will automatically create and send a receipt for every occurrence in that schedule. View our [receipts](/guides/money-movement/receipts/) guide for more information. ## Sales tax We’ve added a new, optional `salesTaxAmount` field when creating a transfer to specify the total sales tax for the transfer. This value is informational and is included in receipts when set. Entering a sales tax amount does not change the total transfer amount. The `salesTaxAmount` field is omitted from the response if not set, so if you don't need or want to use it, there’s nothing you need to update. ## Schedules in the Dashboard The [scheduling API](/api/money-movement/schedules/) has been integrated into Moov's [Dashboard](https://dashboard.moov.io/signin). Recurring and future dated transfers can now be created and managed right in the Dashboard. ## Updates & bug fixes - Increased upload file size for accounts to 20 MB per file - Increased upload file size for disputes to 4 MB per file - `foreignID` is now included on webhook events for accounts - Improved capability error codes in the Dashboard - Fixed a bug with sweep filters in the Dashboard --- URL: https://docs.moov.io/changelog/2025-04-17/ --- # Updates & bug fixes ## Webhooks Please note that if webhook servers return a `404` after the final retry, the webhook will become disabled. For information on webhooks, visit our [documentation](/guides/webhooks/). ## Updates We've updated the error responses for fee plan agreements. View the fee plan [API](/api/moov-accounts/billing/create-agreement/) for details. In the Dashboard, any member with `profile.write` access can now update *Card statement descriptor* and *ACH company name*. ## Bug fixes We've fixed a bug in which account information would get stuck and not complete when updating. --- URL: https://docs.moov.io/changelog/2025-05-29/ --- # Sweep subtotals & more ## Sweep subtotals We've added `subtotals` to the [get sweep](/api/money-movement/sweeps/get/) and [list sweep](/api/money-movement/sweeps/list/) responses. The subtotal provides a breakdown of the `accruedAmount`, such as push, pull, dispute, refund, and fee amounts. ## Deep linking in the Dashboard We've improved deep linking support in the Dashboard. The current selected account (visible in the top left of the Dashboard) now appears within the URL. ## SDK examples Our [API](/api/) now includes request examples for our new PHP, Python, TypeScript, and Java SDKs. ## Moov Model Context Protocol You can now use our TypeScript SDK as an installable MCP server. Use the MCP to enable AI assistants to perform Moov operations on your behalf. See our [documentation](/guides/developer-tools/mcp-ai/mcp/) for more information and instructions. ## Bug fixes - Improved response time when searching for accounts with an email address - Fixed a bug with the [initiate micro-deposit](/api/sources/bank-accounts/initiate-micro-deposits/) response body - Fixed a bug in which the [wallet transaction list](/api/sources/wallets/list-transactions/) was out of order - Fixed a bug that prevented verification codes being sent during the RTP [instant verification](/api/sources/bank-accounts/initiate-bank-account-verification/) process - Fixed a bug that prevented updating accounts in the Dashboard even though the verification process had not started --- URL: https://docs.moov.io/changelog/2025-06-11/ --- # API updates & more ## New institution search A new institution enrichment [endpoint](/api/enrichment/form-shortening/institutions/get/) has been added, which allows you search for financial institutions by name or routing number. The response now includes support for RTP, ACH, and Wire accounts. The previous enrichment [endpoint](/api/enrichment/form-shortening/institutions-ach/), which only supports ACH, will continue to be supported for now. Be advised this endpoint may be deprecated in the future. ## New industry response The enrichment [endpoint](/api/enrichment/form-shortening/industries/get/) which returns a list of MCC industries has an updated response format. The response now includes all the following formats: URL safe, display name, human readable category label, and the MCC code. This response format is returned with the `X-Moov-Version: v2025.07.00` header. ## Payment link code A `paymentLinkCode` is now returned with the transfers API. A `paymentLinkCode` can be used as a query parameter in the [list transfers](/api/money-movement/transfers/list/) request. Note that `paymentLinkCode` is the same as `code` returned via the [payment links API](/api/money-movement/payment-links/create/). ## Scheduling in the Dashboard You can now view scheduled transfers in the Dashboard. Navigate to **Transfers > Schedules** to see a list of all scheduled transfer details, including the amount, next scheduled transfer date, and when the schedule cycle ends. ## Bug fixes - Fixed a bug in the Onboarding Drop when MCC codes are omitted - Fixed a bug with business representative validation in the Dashboard - Fixed a bug loading data when switching between accounts in the Dashboard --- URL: https://docs.moov.io/changelog/2025-06-26/ --- # Payment link receipts, test mode data, & transfer options ## Payment link receipts [Payment links](/guides/money-movement/payment-links/) will now automatically create and send a [receipt](/guides/money-movement/receipts/) via email with every successful submission. Additionally, the payment link title is passed along in the transfer description and will appear on receipts. ## Postal & CVV verification We've updated test card data with postal and CVV codes which correspond to specific verification scenarios. You can now test linking cards with the following postal and CVV verification outcomes, depending on card brand: `match`, `noMatch`, `notChecked`, `unavailable`. See the [test mode](/guides/get-started/test-mode/#link-cards-for-card-acceptance) guide for more information. ## Transfer options endpoint We've added a new transfer options [endpoint](/api/money-movement/transfers/transfer-options/) - `/accounts/{accountID}/transfer-options`. The previous endpoint, `/transfer-options`, is still currently still supported; however, we strongly suggest switching to the new endpoint as soon as possible to prepare for deprecation of `/transfer-options` in the future. ## Bug fixes - Fixed a bug on the onboarding links Dashboard view where the list would not scroll - Fixed a bug in which submitting an empty country code was causing an error. Submitting an empty country code will default to the `US` country code. --- URL: https://docs.moov.io/changelog/2025-07-08/ --- # Deprecation notice & Dashboard sweeps update ## Endpoint deprecation notice We've recently created two new endpoints to replace existing ones. The following endpoints will be removed from our public documentation and will be fully deprecated in the future: - [/transfer-options](/api/money-movement/transfers/options/) - [/institutions/ach/search](/api/enrichment/form-shortening/institutions-ach/get/) Please switch to the following new endpoints: - [/accounts/{accountID}/transfer-options](/api/money-movement/transfers/transfer-options/) - [/institutions](/api/enrichment/form-shortening/institutions/get/) ## Sweep transaction details Coming soon in the Dashboard, the sweep transaction summary will show a chart of all wallet transaction types. You can select **Amount** or **Count** to see specific details. ## Bug fixes - Fixed a bug where incorrect customer support information was being shown to cardholders - Fixed a bug where providing the monthly volume requirement moved the status to pending review instead of fulfilled --- URL: https://docs.moov.io/changelog/2025-07-31/ --- # Support tickets & RTP sweeps ## Connected account support tickets Connected accounts can now open issues with Moov support. You can create a support ticket integration with our [API](/api/moov-accounts/support/), and coming soon, users who are signed in will be able to open an issue directly in the Dashboard. For your connected accounts, you have the ability to: - Allow a user to create an issue - View issues - Retrieve messages associated with issues - Close issues View our [support ticket API](/api/moov-accounts/support/) and our [documentation](/guides/account-tools/support-tickets/) for more information. ## RTP sweep support Sweeps now support the `rtp-credit` push payment method, disbursing funds instantly. View the [Sweeps API](/api/money-movement/sweeps/) for details. ## Bug fixes & updates - Fixed a bug where an error screen would load while trying to view disputes - Fixed a bug where the onboarding Drop showed a capability requirement for sole proprietorship that was not necessary - Fixed pagination issues --- URL: https://docs.moov.io/changelog/2025-08-28/ --- # Passkey authorization & Ruby SDK ## Passkey authorization We've added the ability to use a passkey to log in to the Moov Dashboard through your browser, password manager, a phone or tablet, or a USB security key. Use the secure **Sign in with passkey** option on the [Dashboard](https://dashboard.moov.io/) login screen. ## Ruby SDK (beta) We've added a Ruby SDK to our lineup. View the [documentation](https://github.com/moovfinancial/moov-ruby) on GitHub, or visit our [SDK](/sdks/) page. Note, the Ruby SDK is in beta. ## Bug fixes We've fixed a Dashboard bug with maximum character limits when submitting text based dispute evidence. --- URL: https://docs.moov.io/changelog/2025-09-18/ --- # Merchant statements & API versioning ## Merchant statements Moov now provides monthly statements to help you understand and reconcile your merchant processing costs. Within your monthly statements you'll receive a summary of the following: - Fee names - Transaction processing fees for all rails - Count of instances of the fee assessed - Total fee amount assessed - Network passthrough fees - card network fees - Interchange report (cost-plus plans only) See our [API](/api/moov-accounts/billing/) and [documentation](/guides/fee-plans/merchant-statements/) for more information. ## API versioning Use the [new dropdown](/api/) on our API docs to view different versions of Moov's API. Currently, you can view the following versions: - v2025.04.00 (stable) - Latest (beta) - v2025.01.00 - v2024.01.00 (default) For every request to the API, you can send a version header. Moov suggests `v2025.04.00` for all new users. If no version is sent with your request, Moov will default to `v2024.01.00`. Note, our API documentation previously displayed `latest` by default. If you are looking for endpoints or features which no longer appear in the side navigation, switch the dropdown to **Latest (beta)**. ## Dashboard transfer improvements When creating a transfer, you can now search for an account by name, email, or account ID, as well as filter by type, capabilities, or capability status. Additionally, you should notice a faster experience overall when creating a transfer in the Dashboard. ## Drops improvements We've improved autocompletion behavior and timing on firing field validation. ## Bug fixes - Fixed a bug where some domains were not being successfully added to the API key allow list - Fixed a Dashboard bug where capability status badges were not selectable - Improvements and bug fixes within the Dashboard UI --- URL: https://docs.moov.io/changelog/2025-10-09/ --- # Multiple wallets & more ## Multiple wallets You can now create multiple wallets for each Moov account. Moov will generate one default wallet per account, and now an additional 10 general wallets can be added to each account. Every wallet maintains its own independent balance and transaction history, giving you greater flexibility in fund management and reconciliation. See our [multiple wallets](/guides/sources/wallets/multiple-wallets/) guide and [API](/api/sources/wallets/) for more information. ## Customer support in Dashboard We previously announced our [support tickets API](/api/moov-accounts/support/). Customer support tickets are now available in the Dashboard. Users who are signed in to the Dashboard will be able to directly open an issue. See the [support ticket](/guides/account-tools/support-tickets/) guide for more information. ## API quarterly release Since this changelog, we have updated our API release cadence. Visit our [version reference](/api/version-reference) guide for the most up to date information. We've released API version `2025.07.00`, which includes the following updates and features from the previous version of `latest`: - Granular capabilities - Dynamic underwriting - Enriched industry taxonomies model - Support tickets Note - while some features are now available in our quarterly, stable API release, some features are still considered in beta. When you visit Moov's [API documentation](/api/), `v2025.07.00` is now the main view. See our new [version reference](/api/version-reference) guide for the list of updates per API version. ## Test cards We've added more CVV and AVS verification test cases to the push & pull test cards. See the [test mode](/guides/get-started/test-mode/#transfers) guide for more information. ## Bug fixes - Fixed an issue where the support tickets list on an account wasn’t correctly paginated in the Dashboard - Improved idempotency checks for Tap to Pay payments created via the Android and iOS SDKs - Improved the display of "guest" accounts created via contactless Tap to Pay payments - Enhanced some validation error responses --- URL: https://docs.moov.io/changelog/2025-11-06/ --- # Wallet balances & Moov link ## Balances in the Dashboard We've made some UI changes in the Dashboard. In the Dashboard sidebar, navigate to **Balances** to find your total available wallet balance, your default wallet, and any additional general wallets that have been created. Click on a wallet to view all wallet transactions. ## moov.link We've updated the Moov URL for [payment links](/guides/money-movement/payment-links/). When you generate a payment link code, the URL is now `https://moov.link/p/{code}`. The old URL, `moov.money` will automatically redirect to `moov.link`. ## Bug fixes We've fixed a number of bugs in the Dashboard: - The secret key did not appear after creating an API key - The clear (X) button was not clearing wallet transactions - Sweep configs were not appearing in the settings - *Pending review* underwriting task was not loading - Verification documents were not showing on individual account verification review - The incorrect month was appearing on billing statements - `verification-expired` status was missing from instant bank verification Additionally, we fixed a bug where bank accounts that have been disabled and re-enabled were unable to be verified. --- URL: https://docs.moov.io/changelog/2025-11-20/ --- # Payout links, line items & products API ## Payout links You can now send payout links and generate QR codes for payouts with the Dashboard and API. Payment links support the push to card, RTP credit, ACH credit same day, and ACH credit standard payment methods. Navigate to **Transfers > Payment links** in the Dashboard to [send a payout](/guides/dashboard/transfers/payment-links/) or accept a payment. Use the POST `/accounts/{accountID}/payment-links` endpoint to [send a payout](/api/money-movement/payment-links/create/) or accept a payment with the API. View our [payment links](/guides/money-movement/payment-links/) guide for more information. ## Line items A `lineItems` field has been added to the transfer and payment links APIs. Line items allow you to create items when initiating a transfer or payment link. Each item can specify a name, description, image, options, and price modifiers. Visit the [transfers API](/api/money-movement/transfers/create/) and [payment links API](/api/money-movement/payment-links/create/) for more details. Coming soon: line items on receipts. ## Products and images API Create a product catalog with the products and images APIs. Give each product a title, base price, description, associated image, and additional options like price modifiers. You can map products to line items in transfers and payment links. Visit the [products guide](/guides/account-tools/product-catalog/) & [API](/api/tools/products/) and the [images guide](/guides/account-tools/image-collection/) & [API](/api/tools/images/) for more details. ## .NET SDK (beta) We've added a beta .NET SDK to our lineup. View the [documentation](https://github.com/moovfinancial/moov-dotnet), or visit our [API](/api/) for examples. ## Dashboard updates In the payment link detail view, we've added the list of transfers created by payment links. This view can also be accessed from the main transfer details view. ## Bug fixes - Moov now explicitly blocks HSA cards from being eligible for push and pull transactions - The terms of service field for POST `/accounts` was incorrectly listed as a `oneOf` and has been fixed with the proper nesting pattern - The last four numbers of the card were missing from certain transaction memos - In the Go SDK, `Capability_NameWalletBalance` has been updated to `CapabilityName_WalletBalance` - Account metadata was not always appearing in the Dashboard - Terms of service could not be accepted via the Dashboard hosted onboarding flow --- URL: https://docs.moov.io/changelog/2025-12-19/ --- # Granular capabilities & more ## Granular capabilities We've expanded our capabilities to make them available on a more granular level. For example, `send-funds` has been expanded with the following options: - `send-funds.ach` - `send-funds.instant-bank` - `send-funds.push-to-card` In addition to having more control over capabilities, this allows for a dynamic underwriting process. Accounts will only have to provide information relevant for the specific capabilities requested, resulting in faster verification and capability enablement. View the [capabilities](/guides/accounts/capabilities/reference/) guide for the full list of granular capabilities, and view the [underwriting](/guides/accounts/requirements/underwriting/) guide for additional information. Granular capabilities are available with [Moov API](/api/moov-accounts/capabilities/post/) `v2025.07.00` and later. Earlier versions of the API support our legacy capabilities (`send-funds`, `collect-funds`, and `wallet`). ## Merchant reference guide We've published a [merchant reference](https://support.moov.io/collections/5692997986-merchant_reference) section on our [support site](https://support.moov.io/). The merchant reference guide provides information for merchants outside the context of our main developer and product documentation. This section of our support site will be updated on a regular basis as we update and release new features. ## Institutions endpoint We've deprecated the `/institutions/ach/search` [endpoint](/api/enrichment/form-shortening/institutions/get-ach/) and it will be removed in a future release. We've replaced the deprecated endpoint with the new `/institutions` [endpoint](/api/enrichment/institutions/get/). The new `/institutions` endpoint returns basic identifying metadata, including ACH, RTP, Wire, and FedNow payment support. ## Dashboard navigation We updated the ordering and presentation of the sidebar navigation in the Moov Dashboard. Payment links, Products, and Image library are now at the top level, and the account switcher has been redesigned, making it easier to differentiate test accounts from production accounts. Lastly, the user menu was also redesigned. ## Bug fixes & updates - Added support for a comma-separated list of statuses for query on pricing and fee endpoints - Updated handling of `dispute.updated` webhook event in test mode for evidence handling - Fixed an issue with the Android API linking to sandbox mode - Fixed an issue with password manager auto-logins for the Dashboard - Fixed payment validation issues within the Dashboard payment link form - Added missing RTP option for sweeps in the Dashboard --- URL: https://docs.moov.io/changelog/2026-01-13/ --- # ACH addenda & more ## ACH addenda You can now include a single ACH addenda record when [creating transfers](/api/money-movement/transfers/create/) for supported SEC codes (CCD, PPD, WEB). This enables use cases like TXP addenda for tax payments, allowing compliant ACH credits for IRS and state tax agencies. Addenda data is validated against Nacha rules and safely masked in API responses to protect sensitive information. View our [documentation](/guides/money-movement/accept-payments/ach/ach-overview/#addenda) for more information. ## Idempotency guidance Previously, our guidance was to use a UUID v4 idempotency key in the `X-Idempotency-Key` header. Our current guidance is to use a deterministic idempotency key such as a unique ID from your system (up to 36 characters), or a UUID comprised of unique identifiers for the action. Moov now supports UUID v5. ## Dashboard updates - You can now select a product or create free-form line items when creating a transfer or payment link. - Dropdowns and tooltips across the Dashboard are now native popovers and intelligently change their position to prevent colliding with viewport constraints. - The payment links list now supports [peek preview](/guides/dashboard/transfers/payment-links/#peek-preview) which gives you quick access to view details of each payment link without navigating away from the list. Toggle peek preview on and off by hitting the **space** key. --- URL: https://docs.moov.io/changelog/2026-01-22/ --- # Tap to Pay on iPhone & Android ## Tap to Pay on iPhone With Tap to Pay on iPhone, merchants can seamlessly and securely accept contactless payments using only an iPhone and a supporting iOS app — with no additional hardware needed. Tap to Pay on iPhone accepts all forms of contactless payments, including Apple Pay, contactless credit and debit cards and other digital wallets. Moov has a new [MoovKit](https://moovfinancial.github.io/moov-ios/documentation/moovkit) Swift SDK for Tap to Pay on iPhone functionality. View our [Tap to Pay for iPhone](/guides/money-movement/accept-payments/card-acceptance/tap-to-pay-iphone/) guide for more information. Tap to Pay on iPhone accept and decline functionality is also available to test in [test mode](/guides/get-started/test-mode/#tap-to-pay-on-mobile). ## Tap to Pay on Android With Tap to Pay on Android, merchants can seamlessly and securely accept contactless payments using an Android device's built-in NFC capabilities. Customers can tap their contactless card or mobile wallet against the merchant's phone to securely complete transactions. Moov has a new [Android SDK](https://moovfinancial.github.io/moov-android/moov-android/io.moov.sdk/index.html) for Tap to Pay on Android functionality. View our [Tap to Pay on Android](/guides/money-movement/accept-payments/card-acceptance/tap-to-pay-android/) guide for more information. Tap to Pay on Android accept and decline functionality is also available to test in [test mode](/guides/get-started/test-mode/#tap-to-pay-on-mobile). ## Payment link updates If set, payment links will now display line items for Apple Pay. Additionally, the initial load time for payments links has decreased. ## Bug fixes - Fixed a missing field issue with the TypeScript SDK `202` responses - Fixed an issue with calculating debt repayment interchange rates - Fixed a race condition when selecting capabilities for merchants who have previously been disabled --- URL: https://docs.moov.io/changelog/2026-02-25/ --- # Partner billing, invoicing, API & SDK versioning ## Partner billing Our new [partner billing API](/api/moov-accounts/partner-billing/) provides more insight into fees, residuals, and revenue. You can now retrieve information about your partner costs and merchant-generated revenue to reconcile costs and residuals. On the first day of each month, Moov will generate a statement for your account. Partner statements will include a summary of the following: - Merchant fees collected for each fee category - Partner fees assessed for each fee category - Net income for each fee category - Residual payment (for revenue-share partners) - Monthly partner platform fees (if applicable) - Interchange report You can access your statements with the [list statements endpoint](/api/moov-accounts/billing/list-statements/). View the new [billing](/guides/billing/) guides for more information. ## Invoicing Use the [invoices API](/api/v2026.04.00/money-movement/invoices/) or the [Dashboard](/guides/dashboard/invoices/) to send professional, branded invoices to your customers and accept payments without relying on third‑party tools. When you send an invoice, Moov automatically creates a single-use, secure payment link scoped to that invoice and customer. See our [invoices](/guides/account-tools/invoices/) guide for more information. ![Invoice receipt](../../guides/dashboard/invoices/images/invoice-receipt-email.png) ## API & SDK versioning Moov API [v2026.01.00](/api/) is officially released. API [v2026.04.00](/api/v2026.04.00/) is available as an *in development* API and should be used with caution as breaking changes may occur without notice. Moov is no longer updating the `latest` API version and it will be removed from our documentation. This version of our API used to be in continuous release as a beta version. Those using `latest` should update to a different version of our API immediately - Moov suggests `v2026.01.00` at this time. Visit our API [version reference](/api/version-reference/) for details on major releases per version. * * * SDK versioning will follow the following format: | API version | SDK version | |---------------|----------------| | `v2025.07.00` | `25.7.x` | | `v2026.01.00` | `26.1.x` | | `v2026.04.00` | `26.4.0-dev.x` | Currently API `v2026.04.00` is *in development*, so the corresponding `-dev.x` SDK version indicates an *in development* version of the SDK and should be used with caution. ## Bug fixes - Fixed a webhooks bug when fetching an accounts `metadata` and `foreignID` - Fixed a bug where transfers were getting stuck in sandbox mode - Fixed a bug in which `createTransfer` was being duplicated for sweeps --- URL: https://docs.moov.io/changelog/2026-04-03/ --- # New onboarding Drop and docs MCP server ## Onboarding Drop Our onboarding Drop has undergone a makeover with a more streamlined look. Additionally, the onboarding Drop now supports [granular capabilities](/guides/accounts/capabilities/reference/) and [dynamic underwriting](/guides/accounts/requirements/underwriting/). Visit the [onboarding Drop](/moovjs/drops/onboarding/) guide for more information. ## Docs MCP server You can now use Moov's MCP server in conjunction with our new [docs MCP server](/guides/developer-tools/mcp-ai/docs-mcp/). The docs MCP server allows you and your AI agent to parse Moov's documentation and ask questions about how to set up integrations. Visit our [MCP & AI](https://docs.moov.io/guides/developer-tools/mcp-ai/) section for more information. ## General updates - Credit cards can now be used for approved [pull-from-card](/guides/money-movement/accept-payments/pull-from-card/) (AFT) use cases - OpenID Connect providers can now be configured in the Dashboard, allowing new members of your team to sign in with your company-provisioned credentials - [Hosted onboarding](/guides/dashboard/accounts/onboarding-links/) now shows your brand colors and makes your logo more prominent - Added `imageID` validation error field to invoice line item models - Added a title filter for [list products](/api/tools/products/list/) API ## Bug fixes - Fixed a bug in sandbox mode where underwriting was stuck in pending after approval - Fixed a bug in which query params were not being validated on some card transactions queries - Added pattern to `TerminalApplication.packageName` - Made all fields in rail details models optional --- URL: https://docs.moov.io/guides/accounts/account-types/ --- # Account types Learn about the different types of Moov accounts and the basic requirements to start moving money. Moov accounts fall into three categories based on how they interact with Moov’s platform and money movement flows: partner, merchant, and individual. Moov’s API doesn't always assign explicit account types when requesting IDs, for example. Use this guide to understand Moov's three account types and how to identify various ID use cases. | Account type | Common role | Example | |--------------|------------------------------|----------------------------| | Partner | Integrator | SaaS payment platform | | Merchant | Business, accepting payments | Online store or restaurant | | Individual | End-user, consumer | Cardholder or payee | Throughout our documentation, you may see the phrase **connected account**. A connected account is any account that is linked to another Moov account. A connected account can be a merchant/business or individual account. ## [Partner account](#partner-account) Partners are Moov’s direct customers—the platforms, SaaS providers, or marketplaces integrating with Moov’s API. Partners are responsible for initiating API calls, managing webhooks, and facilitating the overall user experience for their downstream users. An example of a partner account is a **gig platform** using Moov to pay their drivers and accept payments from customers. As a partner, when you sign up for Moov, we'll create an account for you. Your partner account has different access to Moov's platform than other types of Moov accounts. A partner account: - Holds Moov API keys and acts as the technical integrator - Undergoes full underwriting and has a commercial agreement with Moov - Controls onboarding, compliance flows, and payment initiation for users - Provides embedded payments for users - Functions as merchants if directly processing payments Our API might explicitly ask for a `partnerAccountID`, or it might just ask for an `accountID`. For example, when interacting with `POST /accounts/{accountID}/transfers`, you must specify *your (partner)* `accountID`. This is also true for [scopes](/api/authentication/scopes/), your (partner) `accountID` is required: - `/accounts/{accountID}/transfers.write` - `/accounts/{accountID}/transfers.read` ## [Merchant accounts](#merchant-accounts) The partner account creates and onboards Moov accounts for each end user (i.e., customers, merchants). An example of a merchant account is a **restaurant** using a food delivery platform that runs on Moov to accept card payments. A merchant is typically the business end of the transaction, accepting payments or sending payouts. The partner account is responsible for onboarding all merchant accounts. If a merchant account requires anything beyond the `transfers` capability, they must: - Accept Moov's [platform terms of service agreement](#platform-terms-of-service-agreement) - Undergo the underwriting process - Undergo Know Your Customer (KYC) verification Merchant accounts may pay for processing directly, depending on their corresponding platform agreement with you (the partner) and Moov. You can set different [processing fees](/guides/billing/fee-plans/) per merchant. ## [Individual accounts](#individual-accounts) An individual account is an end-user or consumer who receives a payout or pays for goods and services. An example of an individual account is a **delivery driver** receiving payouts or a **customer** paying for a good or service through a merchant checkout flow. Individual accounts: - Represent the final party in a transaction flow - Do not directly hold API credentials or control money movement - May be charged processing fees (surcharges or transaction fees) depending on the partner or merchant’s configuration ## [Capabilities](#capabilities) You'll request access to [capabilities](/guides/accounts/capabilities/) when creating an account. Each capability has different requirements depending on if the account is an individual or business account. Familiarize yourself with capabilities requirements before creating an account (you can also request capabilities after account creation). Click on the capability to view the requirements for each account type. | Capability | Account type | |------------------------------------------------------------------------------|----------------------| | [Transfers](/guides/accounts/capabilities/reference/#transfers) | Individual, business | | [Wallet](/guides/accounts/capabilities/reference/#wallet) | Business | | [Send funds](/guides/accounts/capabilities/reference/#send-funds) | Business | | [Collect funds](/guides/accounts/capabilities/reference/#collect-funds) | Business | | [Card issuing](/guides/accounts/capabilities/reference/#card-issuing) (beta) | Business | Depending on the capabilities requested for merchant Moov accounts, you may need to provide additional information about the account in order for Moov to start the automatic verification process. For more information, read our [verification](/guides/accounts/requirements/identity-verification/) guide. ### [Platform terms of service agreement](#platform-terms-of-service-agreement) If an account requests a capability that requires acceptance of Moov's terms of service, you must display a link to the [Moov platform agreement](https://moov.io/legal/platform-agreement/) in your application. Use the terms of service Drop to collect user agreements. See the [platform terms of service agreement](/guides/accounts/requirements/platform-agreement/) guide for more information and implementation instructions. ## [Beneficial ownership](#beneficial-ownership) US state and federally regulated financial institutions are exempt from beneficial ownership requirements. Moov must verify beneficial ownership before a business account can send or collect funds. Owners are individuals who own 25% or more of the business. Moov also requires at least one control officer: someone with significant responsibility to manage the business, like an executive officer or director. Moov refers to these individuals collectively as [business representatives](/guides/accounts/requirements/business-representatives/). Representatives can be created via the Dashboard or the API. ### [Dashboard](#dashboard) The [Dashboard](/guides/dashboard/accounts/) will bring you through the entire owner flow, which incudes creating owners and providing ownership percentage. Once you finish the process, if any information is missing, you'll receive a notification in the Dashboard. Once all owners have been created, and all required information is entered, Moov can begin account verification. ### [API](#api) Use the representatives `POST` [endpoint](/api/moov-accounts/representatives/create/) to create each owner. For each owner, set `isOwner` to **true**, as well as provide the `ownershipPercentage`. If a representative does not own ≥25% of the company, they are not considered a beneficial owner. You can set `isOwner` to **false** and leave the `ownershipPercentage` field blank. After you've created all the owners, patch the profile's `business` object by setting `ownersProvided` to **true** using the accounts `PATCH` [endpoint](/api/moov-accounts/accounts/patch/). This indicates to Moov the profile is complete, and verification can begin. If *no one* owns ≥25%, you don't need to create any owners. However, even if no owners are created, you'll still need to set `ownersProvided` to **true** using the `PATCH` [endpoint](/api/moov-accounts/accounts/patch/). ## [Next steps](#next-steps) Familiarize yourself with Moov's [capabilities](/guides/accounts/capabilities/) and [account requirements](/guides/accounts/requirements/). When you're ready to create user accounts, see our [create accounts](/guides/accounts/create-accounts/) or [hosted onboarding](/guides/accounts/hosted-onboarding/) guide. --- URL: https://docs.moov.io/guides/accounts/capabilities/enablement/ --- # Enable capabilities Request capabilities for accounts, fulfill requirements, and track the enablement lifecycle. Capabilities move through a lifecycle from `pending` to `enabled`. Each capability has requirements that must be fulfilled before it can be enabled. These include account profile data, [identity verification](/guides/accounts/requirements/identity-verification/), and [underwriting](/guides/accounts/requirements/underwriting/). Every payment method requires certain capabilities. Visit the [payment methods](/guides/money-movement/payment-methods/) guide for details. ## [Request capabilities](#request-capabilities) You can request capabilities when creating an account or at any point after. The [capabilities reference](/guides/accounts/capabilities/reference/) lists all available capabilities and their use cases. ### [Request via API](#request-via-api) The following examples demonstrate how to request capabilities after an account has been created. [cURL](#tab-974231568-2-0) [Go SDK](#tab-974231568-2-1) [Moov.js](#tab-974231568-2-2) ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/capabilities" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "capabilities": [ "transfers", "send-funds.ach", "collect-funds.ach", "wallet.balance" ] }'\ ``` ```go mc, _ := moov.NewClient() var accountID string mc.RequestCapabilities(ctx, accountID, []moov.CapabilityName{ moov.CapabilityName_Transfers, moov.CapabilityName_SendFundsACH, moov.CapabilityName_CollectFundsACH, moov.Capability_NameWalletBalance, }, ) ``` ```javascript const moov = Moov(token); const accountID = "accountID"; const capabilities = [ "send-funds.ach", "collect-funds.ach" ]; moov.accounts.capabilities.request({accountID, capabilities}); ``` ## [Requirements](#requirements) After requesting a capability, Moov determines what requirements must be fulfilled based on the capability type and whether the account is an individual or business. Requirements fall into two categories: - **Verification:** Confirms the account holder's identity. This includes basic account data (name, address, tax ID) and may require document uploads. See the [identity verification](/guides/accounts/requirements/identity-verification/) guide. - **Underwriting:** Assesses the account's risk profile and expected transaction volume. Required for most payment capabilities. See the [underwriting](/guides/accounts/requirements/underwriting/) guide. The `transfers` capability is automatically enabled with no additional requirements. The `wallet.balance` capability only requires verification. ## [Capability lifecycle](#capability-lifecycle) Each capability moves through statuses based on whether its requirements have been fulfilled and verified. | Status | Description | |-------------|----------------------------------------------------------------------------------------------------------------| | `pending` | Capability requested but requirements not yet met. Required information may be missing or verification failed. | | `in-review` | All requirements fulfilled. Moov is verifying the information through compliance checks. | | `enabled` | All requirements satisfied and verified. The capability is active and can be used in production. | | `disabled` | Capability turned off. May be due to a Moov compliance action or disabled via API/Dashboard. | ## [Manage capabilities](#manage-capabilities) Track the status of each capability and its requirements with the [capabilities API](/api/moov-accounts/capabilities/) or Dashboard. ### [Get capability details](#get-capability-details) Use the capabilities `GET` [endpoint](/api/moov-accounts/capabilities/list/) to retrieve capabilities for an account. | Field | Description | |----------------------------------------|----------------------------------------------------------------| | `capability` | The capability key (for example, `collect-funds.ach`) | | `status` | Current status (`pending`, `in-review`, `enabled`, `disabled`) | | `requirements.currentlyDue` | List of outstanding requirements | | `requirements.errors` | Array of errors encountered during verification | | `disabledReason` | If disabled, the reason (for example, `risk action`) | | `createdOn`, `updatedOn`, `disabledOn` | Lifecycle timestamps | ```json { "capability": "collect-funds.ach", "accountID": "670356c4-bd3c-414b-9709-c4dc84752902", "status": "pending", "requirements": { "currentlyDue": [ "document.business.verification" ], "errors": [ { "requirement": "business.legalname", "errorCode": "failed-automatic-verification" } ] }, "createdOn": "2025-05-13T19:46:53Z", "updatedOn": "2025-05-13T19:50:58Z" } ``` After requesting capabilities, certain business types must provide Moov with a list of [beneficial owners](/guides/accounts/account-types/#beneficial-ownership). ## [Webhooks](#webhooks) Set up a `capability.updated` [webhook](/guides/webhooks/webhook-events/#capabilities) to listen for capability status changes. Webhooks enable real-time UI updates or automated handling, such as prompting users to provide missing information. The Dashboard also displays notices when an account has outstanding requirements. --- URL: https://docs.moov.io/guides/accounts/capabilities/ --- # Capabilities Capabilities define what payment functionality is available to a Moov account. Capabilities give you granular control over your users' payment functionality while ensuring compliance with financial regulations and payment network requirements. Each capability unlocks a specific payment functionality, for example, collecting card payments or sending instant bank transfers. Capabilities come with [verification](/guides/accounts/requirements/identity-verification/) and [underwriting](/guides/accounts/requirements/underwriting/) requirements that must pass before they're enabled. When enabled, capabilities allow accounts to: - **Collect funds:** Pull customer payments via cards, digital wallets, or ACH - **Send funds:** Push payouts via ACH, instant bank transfers (RTP/FedNow), or card networks - **Money transfer:** Move funds between cards for account funding, me-to-me, or P2P use cases - **Wallet:** Store funds on the Moov platform - **Card issuing:** Issue and manage virtual prepaid cards The `transfers` capability is automatically enabled for all Moov accounts. The `wallet.balance` capability is automatically requested when any collect, send, money transfer, or card issuing capability is enabled. --- URL: https://docs.moov.io/guides/accounts/capabilities/reference/ --- # Capabilities reference Explore available capabilities, what they enable, and common use cases. Capabilities define which payment functions a Moov account can use. Enabling a capability on Moov account unlocks a specific payment function (for example, collecting card payments or sending ACH credits). They ensure compliance with financial regulations and payment network rules while giving you granular control over the functionality available to your users. The capabilities below are available with Moov API `v2025.07.00` and later. Earlier versions of our API support legacy capabilities (`send-funds`, `collect-funds`, and `wallet`). API `v2025.07.00` allows you to request capabilities on a more granular level, speeding up verification and enablement. | Capability | Description | Auto-enabled | Requirements | |---------------------------------|------------------------------------------------------------------------------|--------------|---------------------------------| | `transfers` | Enables participation in any Moov transfer | Yes | None | | `wallet.balance` | Enables holding funds in a Moov wallet and allows wallet-to-wallet transfers | Conditional | Verification | | `collect-funds.card-payments` | Accepts payments via credit/debit cards and digital wallets | No | Verification & Underwriting | | `collect-funds.ach` | Accept ACH debit payments from bank accounts | No | Verification & Underwriting | | `send-funds.ach` | Send ACH credit transfers (standard or same-day) | No | Verification & Underwriting | | `send-funds.instant-bank` | Send instant bank transfers via RTP & FedNow | No | Verification & Underwriting | | `send-funds.push-to-card` | Push funds to cards via Visa Direct or Mastercard Send | No | Verification & Underwriting | | `money-transfer.pull-from-card` | Pull funds from debit/prepaid cards for account funding or P2P | No | Verification & Underwriting | | `money-transfer.push-to-card` | Push funds to debit/prepaid cards for withdrawals or P2P | No | Verification & Underwriting | | `card-issuing` | Create and manage virtual prepaid cards funded by a Moov wallet | No | Verification & Underwriting | ## [Transfers](#transfers) The `transfers` capability is automatically requested and enabled for all Moov accounts that meet minimum data requirements for account creation. When this capability is disabled, the account cannot move money in or out. | Key | Enables | Auto-enabled | |-------------|------------------------------------|--------------| | `transfers` | Participation in any Moov transfer | Yes | ## [Wallet](#wallet) Moov wallets are required to accept or disburse funds on the platform. The `wallet.balance` capability is automatically requested when an account enables any **collect-funds**, **send-funds**, **money-transfer**, or **card-issuing** capability. | Key | Enables | Auto-enabled | |------------------|------------------------------------------------------------------------|------------------------------------------------------------------------------| | `wallet.balance` | Hold funds in a Moov wallet; participate in wallet-to-wallet transfers | Yes, when any collect/send/money-transfer/card-issuing capability is enabled | ## [Collect funds](#collect-funds) Collect funds capabilities allow accounts to pull money into Moov by charging customers’ payment methods. | Key | Enables | Use cases | |-------------------------------|-----------------------------------------|------------------------------------------------| | `collect-funds.card-payments` | Accept card and digital wallet payments | Online checkout, subscriptions, tap-to-pay POS | | `collect-funds.ach` | Accept ACH debit payments | Recurring billing, invoicing, B2B payments | ## [Send funds](#send-funds) Send funds capabilities allow accounts to push money out for payouts and disbursements. | Key | Enables | Use cases | |---------------------------|----------------------------------------------------------|-------------------------------------------| | `send-funds.ach` | ACH credits (standard and same-day) | Vendor payments, loan disbursements | | `send-funds.instant-bank` | Real-time payouts via RTP and FedNow (coming soon) | Insurance claims, instant disbursements | | `send-funds.push-to-card` | Instant card payouts (Visa Direct & Mastercard Send) | Gig economy payouts, same-day withdrawals | You may see `send-funds.rtp` in the API. This will be deprecated in favor of `send-funds.instant-bank`, which supports RTP (and will support FedNow in the future). ## [Money transfer](#money-transfer) Money transfer capabilities allow eligible financial institutions and platforms to move funds to and from debit or prepaid cards. Common use cases include funding external accounts, me-to-me transfers (moving money between a user’s own accounts), and peer-to-peer (P2P) payments. These capabilities are limited to approved and specialized use cases. To determine whether your organization qualifies, please contact Moov. | Key | Enables | Use cases | |---------------------------------|-----------------------------------------------------------|--------------------------------| | `money-transfer.pull-from-card` | Pull funds from cards (Visa Direct & Mastercard Send) | Account funding, me-to-me, P2P | | `money-transfer.push-to-card` | Push funds to cards (Visa Direct & Mastercard Send) | Withdrawals, me-to-me, P2P | ## [Card issuing](#card-issuing) The card issuing capability allows businesses to issue virtual prepaid cards, funded from a Moov wallet, for embedded spending, expense management, and other controlled-spend use cases. The card issuing capability is in beta - [contact Moov](https://moov.io/contact/) if you have a use case. | Key | Enables | Use cases | |----------------|-----------------------------------------|------------------------------------------------| | `card-issuing` | Create and manage virtual prepaid cards | Expense management, controlled vendor payments | ## [Use cases](#use-cases) Use the following sections to explore common capability use cases. ### [Source and destination accounts](#source-and-destination-accounts) In a Moov transfer, **source** and **destination** accounts may require different capabilities: - **Collect funds:** The destination account (your user) pulls money from a customer (source). - Destination: requires a collect-funds capability - Source: requires only `transfers` - **Send funds:** The source account (your user) pushes money to a recipient (destination). - Source: requires a send-funds capability - Destination: requires only `transfers` ### [Combined flows](#combined-flows) Some business models require both collecting payments and sending payouts—for example, platforms with integrated billing and disbursement, or lenders that collect repayments and disburse loan proceeds. These flows are supported by enabling both **collect funds** and **send funds** capabilities. Examples: - **Lending platforms:** Collect repayments via `collect-funds.ach` or `collect-funds.card-payments`, Disburse loan proceeds via `send-funds.ach`. - **SaaS billing platforms:** Collect customer payments via `collect-funds.ach`, Pay vendors via `send-funds.instant-bank`. ### [Common business models](#common-business-models) | Business model | Party | Capabilities | Flow | |------------------|--------------|---------------------------------------------------------|---------------------------------------------------------| | **Ecommerce** | Merchant | `collect-funds.card-payments`, `wallet.balance` | Customer pays → Funds settle to merchant wallet | | | Customer | `transfers` | | | **Lending** | Lender | `collect-funds.ach`, `send-funds.ach`, `wallet.balance` | Lender disburses loan → Borrower repays over time | | | Borrower | `transfers` | | | **SaaS billing** | Biller | `collect-funds.ach`, `send-funds.ach`, `wallet.balance` | Business pays invoice → Biller collects and pays vendor | | | Business | `transfers` | | | | Vendor | `transfers` | | | **Insurance** | Insurer | `send-funds.instant-bank`, `wallet.balance` | Claim approved → Real-time payout to policyholder | | | Policyholder | `transfers` | | --- URL: https://docs.moov.io/guides/accounts/capabilities/troubleshoot/ --- # Troubleshoot capabilities Learn about capability requirement errors, what they mean, and how to address them in the Moov API or Dashboard. Use this guide to identify, troubleshoot, and solve issues related to requesting capabilities and the verification and underwriting process. ## [Identify requirement errors](#identify-requirement-errors) If Moov is unable to verify account information, we will communicate the errors, or ask for documentation. Outstanding capability requirements and errors will prevent a capability from being enabled. The easiest way to see errors is in the Dashboard, however, you can also use the capabilities `GET` [endpoint](/api/moov-accounts/capabilities/get/). ### [View errors via API](#view-errors-via-api) Pass the `accountID` to the list capabilities `GET` [endpoint](/api/moov-accounts/capabilities/list/) to list outstanding requirements for *all* capabilities [cURL](#tab-658243917-1-0) [Go SDK](#tab-658243917-1-1) ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/capabilities/" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ ``` ```go mc, _ := moov.NewClient() var accountID string mc.ListCapabilities(ctx, accountID) ``` The response will communicate: - Outstanding requirements - Errors on requirements that were previously submitted For example, the following response communicates that there was an error on the business EIN requirement. ```JSON { "capability": "transfers", "accountID": "3dfff852-927d-47e8-822c-2fffc57ff6b9", "status": "enabled", "requirements": { "currentlyDue": [ "account.tos-acceptance" ], "errors": [ { "requirement": "business.ein", "errorCode": "failed-automatic-verification" } ] }, "disabledReason": "string", "createdOn": "2024-08-24T14:15:22Z", "updatedOn": "2024-08-24T14:15:22Z", "disabledOn": "2024-08-24T14:15:22Z" } ``` You can also find any outstanding requirements for a *single* capability using the capability `GET` [endpoint](/api/moov-accounts/capabilities/get/). Provide both the `accountID` and `capabilityID` in the path. ## [Address requirement errors](#address-requirement-errors) See the table below for more details on possible requirement errors and the steps for resolving them. | Error | Description | Next steps | |-----------------------------------|------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------| | `failed-automatic-verification` | The data provided could not be verified | Correct the errored field via API or Dashboard | | `tax-id-mismatch` | There was an issue verifying the SSN or TIN | Submit a document to Moov with the SSN or TIN. See below for a [list of acceptable documents](#acceptable-documents) | | `invalid-address` | The address could not be verified | Correct the errored field via API or Dashboard | | `address-restricted` | The address provided is not an acceptable residential address | Correct the errored field via API or Dashboard | | `document-id-mismatch` | The uploaded ID does not match information provided | Upload an updated ID or correct the errored field via API or dashboard | | `document-date-of-birth-mismatch` | The date of birth listed on the document does not match the date of birth provided | Upload an updated document | | `document-name-mismatch` | The name listed on the document does not match the name provided | Upload an updated document | | `document-number-mismatch` | A number listed on the document does not match the number provided | Upload an updated document | | `document-incomplete` | The document provided has incomplete information | Upload a document with complete information | | `document-failed-risk` | The document failed to meet a Moov requirement | [Contact Moov](https://support.moov.io/) to resolve the issue | | `document-illegible` | The uploaded document is not legible | Upload a legible version of the document | | `document-unsupported` | The document type is not supported | Upload one of the following supported document types: CSV, PNG, JPEG, PDF | | `document-not-uploaded` | A document was required, but not uploaded | Upload a document for the corresponding requirement | | `document-corrupt` | The document was corrupt | Upload an uncorrupted version of the document | | `document-expired` | The document was expired | Upload a non-expired version of the document | ## [Satisfy document requirements](#satisfy-document-requirements) Moov may require documentation to verify account data and enable capabilities. Document requirements and data requirements are communicated in both the capabilities [response](/api/moov-accounts/capabilities/get/), or in the Dashboard. ### [Acceptable documents](#acceptable-documents) Document requirement(s) Acceptable documents `business.document.verification` - Articles of Incorporation or Certificate of Formation \- DBA Registration \- Government-issued business license or registration \- EIN confirmation letter or SS4 \- `individual.document.verification` \- `representative.{rep-uuid}.document.verification` - Unexpired government issued ID with a photo \- Utility bill from the last 60 days \- Bank statement from the last 60 days \- Residential lease or mortgage statement \- `individual.document.tin` \- `representative.{rep-uuid}.document.tin` \- Tax return statement \- SSN/ITIN card \- W2 ### [Uploading documents via Moov API](#uploading-documents-via-moov-api) You can address document requirements by uploading a file using the files `POST` [endpoint](/api/moov-accounts/files/post/). When uploading a file, include a `filePurpose` to communicate what the document is for. A file can have the following purposes: | `filePurpose` | Description | |-------------------------------|--------------------------------------------------------------------------------------------------------------------------------------| | `business_verification` | Use for documents addressing business verification requirements | | `representative_verification` | Use for documents addressing representative verification requirements. Must also include the representativeID in the metadata field. | | `individual_verification` | Use for documents addressing individual verification requirements | You can upload a file via API as shown below: ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/files" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --form \ -F "file=@/path/to/your/file.txt" \ -F "filePurpose=business_verification" \ -F "metadata={\"representative_id\":\"string\"}" ``` You can also upload documents via the [Dashboard](/guides/dashboard/accounts/all-accounts/#documents). --- URL: https://docs.moov.io/guides/accounts/create-accounts/ --- # Create accounts Follow this step by step guide to create accounts with our API, SDKs, and Moov.js. The easiest way to create accounts will be through our [hosted onboarding](/guides/accounts/hosted-onboarding/) process. You can create business or individual accounts, pre-fill data, and send a form link directly to merchants to complete. The examples on this page show the flow of creating both business and individual accounts with our API, SDKs, and Moov.js, including the use of Moov's pre-built onboarding Drop. We strongly recommend using Moov.js's pre-built [onboarding Drop](/moovjs/drops/onboarding/). As part of the verification process, an address is required for business accounts requesting wallet, send funds, collect funds, or card issuing capabilities. The following address types **cannot** be the main address provided for a Moov account: - ❌ PO Box - ❌ Commercial mailing receiving agency - ❌ Registered agent Before you create an account, familiarize yourself with [capabilities](/guides/accounts/capabilities/) and [requirements](/guides/accounts/requirements/). A full example is provided at the end of each section. ## [Get access token](#get-access-token) *This initial step is only required if you're going to use Moov's onboarding Drop.* Create an access token, which you’ll later include as the `onboarding.token` when onboarding accounts with Drops. [cURL](#tab-574618923-2-0) ```zsh curl -X POST "https://api.moov.io/oauth2/token" \ -u "PUBLIC_KEY:PRIVATE_KEY" \ --data '{ "grant_type":"client_credentials", "client_id":"5clTR_MdVrrkgxw2", "client_secret":"dNC-hg7sVm22jc3g_Eogtyu0_1Mqh_4-", "scope":"/accounts.write", "refresh_token":"i1qxz68gu50zp4i8ceyxqogmq7y0yienm52351c6..." }'\ ``` ## [Business account](#business-account) The examples below have been broken up into all the small tasks needed to create a business Moov account. However, when using the API, SDKs, or Moov.js, steps 2-4 *can* be consolidated into one step. See the [full example](/guides/accounts/create-accounts/#create-business-account-full-example) for details. ### [Create business account](#create-business-account) You can provide a variety of information when creating an account. The example below only includes the minium required fields. The response object will include the newly created `accountID` which you will need to update the account. Sole proprietors must be created via the business profile with `businessType.soleProprietorship`. [cURL](#tab-287316954-0-0) [Go SDK](#tab-287316954-0-1) [Moov.js](#tab-287316954-0-2) [Onboarding Drop](#tab-287316954-0-3) Create account [reference](/api/moov-accounts/accounts/create/) ```zsh curl -X POST "https://api.moov.io/accounts" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "accountType": "business", "profile": { "business": { "legalBusinessName": "Whole Body Fitness LLC", "businessType": "llc", "website": "wbfllc.com" } }, "foreignId": "unique-correlation-id" }'\ ``` Create account [reference](/api/moov-accounts/accounts/create/) ```go mc, _ := moov.NewClient() mc.CreateAccount(ctx, moov.CreateAccount{ Type: moov.AccountType_Business, Profile: moov.CreateProfile{ Business: &moov.CreateBusinessProfile{ Name: "Whole Body Fitness LLC", Type: "llc", Website: "wbfllc.com", }, }, }) ``` Create account [reference](/api/moov-accounts/accounts/create/) ```javascript const moov = Moov(token); const accountPayload = { accountType: "business", profile: { business: { legalBusinessName: "Whole Body Fitness LLC", businessType: "llc", website: "wbfllc.com" } }, foreignId: "unique-correlation-id" }; const account = await moov.accounts.create({accountPayload}); ``` Onboarding Drop [reference](/moovjs/drops/onboarding/) With the onboarding Drop, you request capabilities when creating an account. After this step, you can jump ahead to [step 4](#send-platform-agreement-to-business). ```html ``` ```javascript // Get the onboarding Drop const onboarding = document.querySelector("moov-onboarding"); // After generating a token, set it on the onboarding element onboarding.token = "some-generated-token"; // Include your accountID, which can be found in the Dashboard onboarding.facilitatorAccountID = "your-account-id"; // Request capabilities onboarding.capabilities = ["send-funds.ach", "collect-funds.ach"]; // Open the onboarding flow when ready onboarding.open = true; ``` ### [Request capabilities for business](#request-capabilities-for-business) Request capabilities for the account you've created by passing the `accountID`. You can find the account ID in the create account response, or you can find it by using the list accounts `GET` [endpoint](/api/moov-accounts/accounts/list/). [cURL](#tab-175234869-0-0) [Go SDK](#tab-175234869-0-1) [Moov.js](#tab-175234869-0-2) Request capabilities [reference](/api/moov-accounts/capabilities/post/) ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/capabilities" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "capabilities": [ "transfers", "send-funds.ach", "collect-funds.ach", "wallet.balance" ] }'\ ``` Request capabilities [reference](/api/moov-accounts/capabilities/post/) ```go mc, _ := moov.NewClient() var accountID string mc.RequestCapabilities(ctx, accountID, []moov.CapabilityName{ moov.CapabilityName_Transfers, moov.CapabilityName_SendFundsACH, moov.CapabilityName_CollectFundsACH, moov.Capability_NameWalletBalance, }, ) ``` Request capabilities [reference](/api/moov-accounts/capabilities/post/) ```javascript const moov = Moov(token); const accountID = "accountID"; const capabilities = [ "send-funds.ach", "collect-funds.ach" ]; moov.accounts.capabilities.request({accountID, capabilities}); ``` ### [Send platform agreement to business](#send-platform-agreement-to-business) The platform agreement is sent via a token. To send a token, you must generate the token and then update the account with that token. Terms of service tokens must be created on the client-side for the user to accept. You can then pass the token to your server when creating or updating the account. The easiest way to do this is with the Moov [TOS Drop](/moovjs/drops/terms-of-service/). Note in addition to the Drop, the tabs below show the API methods to generate and pass a token. **The API implementations outlined below are not available to everyone.** If you are not authorized by Moov to use the API flows, you will receive a `400` error. [Terms of service Drop](#tab-473159268-0-0) [Token](#tab-473159268-0-1) [Manual](#tab-473159268-0-2) Terms of Service Drop [reference](/moovjs/drops/terms-of-service/) ```html ``` ```javascript // Get the terms of service Drop const termsOfService = document.querySelector("moov-terms-of-service"); // Provide the token termsOfService.token = "eyjh..."; ``` Generate token [reference](/api/moov-accounts/accounts/get-tos/) and update account [reference](/api/moov-accounts/accounts/patch/) ```zsh # Get the terms of service token curl -X GET "https://api.moov.io/tos-token" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ ``` ```zsh # Send the token when patching the account curl -X PATCH "https://api.moov.io/accounts/{accountID}" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "termsOfService": { "token": "terms-of-service-token" }, "foreignID": "unique-correlation-id" }'\ ``` Update account [reference](/api/moov-accounts/accounts/patch/) ```zsh curl -X PATCH "https://api.moov.io/accounts/{accountID}" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "termsOfService": { "manual": { "acceptedDate": "accepted-date", "acceptedIP": "accepted-ip", "acceptedUserAgent": "accepted-user-agent", "acceptedDomain": "accepted-domain" } }, "foreignID": "unique-correlation-id" }'\ ``` ### [Create representatives](#create-representatives) Moov must verify business representatives before a business account send funds or collect funds from other accounts. A beneficial owner is any individual with ≥25% ownership of the business (owner), or someone with significant responsibility to control or manage the business (controller). An account is not required to have an owner, but must have at least one controller. An account can have a maximum of 7 representatives. [cURL](#tab-354921867-0-0) [Go SDK](#tab-354921867-0-1) [Moov.js](#tab-354921867-0-2) Add a representative [reference](/api/moov-accounts/representatives/create/) ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/representatives" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "address": { "addressLine1": "12 Main Street", "city": "Cabot Cove", "stateOrProvince": "ME", "postalCode": "04103", "country": "US" }, "birthDate": { "day": 10, "month": 11, "year": 1985 }, "email": "amanda@classbooker.dev", "governmentID": { "ssn": { "full":"111111111", "lastFour":"1111" } }, "name": { "firstName": "Amanda", "lastName": "Yang" }, "phone": { "number": "8185551212", "countryCode": "1" }, "responsibilities": { "isController": false, "isOwner": true, "ownershipPercentage": 38, "jobTitle": "CEO" } }' ``` Add a representative [reference](/api/moov-accounts/representatives/create/) ```go mc, _ := moov.NewClient() var accountID string mc.CreateRepresentative(ctx, accountID, moov.CreateRepresentative{ Address: &moov.Address{ AddressLine1: "12 Main Street", City: "Cabot Cove", StateOrProvince: "ME", PostalCode: "04103", Country: "US", }, BirthDate: &moov.Date{ Day: 10, Month: 11, Year: 1985, }, Email: "amanda@classbooker.dev", GovernmentID: &moov.GovernmentID{ SSN: &moov.SSN{ Full: "111111111", LastFour: "1111", }, }, Name: moov.Name{ FirstName: "Amanda", LastName: "Yang", }, Phone: &moov.Phone{ Number: "8185551212", CountryCode: "1", }, Responsibilities: &moov.Responsibilities{ IsController: false, IsOwner: true, OwnershipPercentage: 38, JobTitle: "CEO", }, }) ``` Add a representative [reference](/api/moov-accounts/representatives/create/) ```javascript const moov = Moov(token); const accountID = "accountID"; const representativePayload = { address: { addressLine1: "12 Main Street", city: "Cabot Cove", stateOrProvince: "ME", postalCode: "04103", country: "US" }, birthDate: { day: 10, month: 11, year: 1985 }, email: "amanda@classbooker.dev", governmentID: { ssn: { full: "111111111", lastFour: "1111" } }, name: { firstName: "Amanda", lastName: "Yang" }, phone: { number: "8185551212", countryCode: "1" }, responsibilities: { isController: false, isOwner: true, ownershipPercentage: 38, jobTitle: "CEO" } }; const account = await moov.representatives.create(accountID, representativePayload); ``` ### [Update account with beneficial owners](#update-account-with-beneficial-owners) Update the account to alert Moov that you have finished creating representatives. At least one controller should have been created in step 4. [cURL](#tab-269471835-0-0) [Go SDK](#tab-269471835-0-1) [Moov.js](#tab-269471835-0-2) Update account [reference](/api/moov-accounts/accounts/patch/) ```zsh curl -X PATCH "https://api.moov.io/accounts/{accountID}" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "profile": { "business": { "ownersProvided": true } }, "foreignId": "unique-correlation-id" }'\ ``` Update account [reference](/api/moov-accounts/accounts/patch/) ```go mc, _ := moov.NewClient() account := moov.Account{ AccountID: "accountID", AccountType: moov.AccountType_Business, Profile: moov.Profile{ Business: &moov.Business{ OwnersProvided: true, }, }, } mc.UpdateAccount(ctx, account) ``` Update account [reference](/api/moov-accounts/accounts/patch/) ```javascript const moov = Moov(token); const accountID = "accountID" const updatedAccount = { profile: { business: { ownersProvided: true, } } }; moov.accounts.update(accountID, updatedAccount); ``` ### [Additional underwriting and verification](#additional-underwriting-and-verification) Depending on the account and capabilities requested, Moov might require additional [verification](/guides/accounts/requirements/identity-verification/) and [underwriting](/guides/accounts/requirements/underwriting/). You will receive alerts for any missing data in the [Dashboard](https://dashboard.moov.io/signin). ### [Create business account full example](#create-business-account-full-example) You can consolidate steps 2 through 4 using the create account `POST` [endpoint](/api/moov-accounts/accounts/create/). The below example includes all the fields you can send to Moov in one step when creating a business account. After creating an account, you would still need to add representatives and provide beneficial owner confirmation (starting at steps 5 and 6). Any additional [verification](/guides/accounts/requirements/identity-verification/) and [underwriting](/guides/accounts/requirements/underwriting/) requirements will be listed in the [Dashboard](https://dashboard.moov.io/signin). [cURL](#tab-193685472-4-0) [Go SDK](#tab-193685472-4-1) [Moov.js](#tab-193685472-4-2) Create account [reference](/api/moov-accounts/accounts/create/) ```zsh curl -X POST "https://api.moov.io/accounts" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ -H "X-Wait-For: connection" \ --data-raw '{ "accountType": "business", "profile": { "business": { "address": { "addressLine1": "123 Main Street", "addressLine2": "Unit 302", "city": "Boulder", "stateOrProvince": "CO", "postalCode": "80301", "country": "US" }, "businessType": "llc", "description": "Local fitness center paying out instructors", "doingBusinessAs": "Whole Body Fitness", "email": "amanda@classbooker.dev", "industryCodes": { "naics": "713940", "sic": "7991", "mcc": "7997" }, "legalBusinessName": "Whole Body Fitness LLC", "phone": { "number": "8185551212", "countryCode": "1" }, "taxID": { "ein": { "number": "123-45-6789" } }, "website": "www.wholebodyfitnessgym.com", } }, "capabilities": [ "send-funds.ach", "collect-funds.ach" ], "customerSupport": { "address": { "addressLine1": "123 Main Street", "addressLine2": "Unit 302", "city": "Boulder", "stateOrProvince": "CO", "postalCode": "80301", "country": "US" }, "email": "amanda@classbooker.dev", "phone": { "number": "8185551212", "countryCode": "1" }, "website": "www.wholebodyfitnessgym.com" }, "foreignId": "unique-correlation-id", "metadata": { "property1": "string", "property2": "string" }, "mode": "production", "settings": { "cardPayment": { "statementDescriptor": "Whole Body Fitness" } }, "termsOfService": { "token": "kgT1uxoMAk7QKuyJcmQE8nqW_HjpyuXBabiXPi6T83fUKRJkA3dsFID6fzitMpm2qrOh4" } }'\ ``` Create account [reference](/api/moov-accounts/accounts/create/) ```go mc, _ := moov.NewClient() thirdPartyID := "" // your system identifier mc.CreateAccount(ctx, moov.CreateAccount{ Type: moov.AccountType_Business, Profile: moov.CreateProfile{ Business: &moov.CreateBusinessProfile{ Address: &moov.Address{ AddressLine1: "123 Main Street", AddressLine2: "Apt 302", City: "Boulder", StateOrProvince: "CO", PostalCode: "80301", Country: "US", }, Type: moov.BusinessType_Llc, Description: "Local fitness center paying out instructors", DBA: "Whole Body Fitness", Email: "julesj@classbooker.dev", IndustryCodes: &moov.IndustryCodes{ Naics: "713940", Sic: "7991", Mcc: "7997", }, Name: "Whole Body Fitness LLC", Phone: &moov.Phone{ Number: "8185551212", CountryCode: "1", }, TaxID: &moov.TaxID{ EIN: moov.EIN{ Number: "123456789", }, }, Website: "www.wholebodyfitnessgym.com", }, }, RequestedCapabilities: []moov.CapabilityName{ moov.CapabilityName_SendFundsACH, moov.CapabilityName_CollectFundsACH, }, CustomerSupport: &moov.CustomerSupport{ Address: &moov.Address{ AddressLine1: "123 Main Street", AddressLine2: "Unit 302", City: "Boulder", StateOrProvince: "CO", PostalCode: "80301", Country: "US", }, Email: "julesj@classbooker.dev", Phone: &moov.Phone{ Number: "8185551212", CountryCode: "1", }, }, ForeignID: thirdPartyID, Metadata: map[string]string{ "Property1": "string", "Property2": "string", }, AccountSettings: &moov.AccountSettings{ CardPayment: &moov.CardPaymentSettings{ StatementDescriptor: "Jules Jackson", }, }, }) ``` Create account [reference](/api/moov-accounts/accounts/create/) ```javascript const moov = Moov(token); const accountPayload = { accountType: "business", profile: { business: { address: { addressLine1: "123 Main Street", addressLine2: "Unit 302", city: "Boulder", stateOrProvince: "CO", postalCode: "80301", country: "US" }, businessType: "llc", description: "Local fitness center paying out instructors", doingBusinessAs: "Whole Body Fitness", email: "amanda@classbooker.dev", industryCodes: { naics: "713940", sic: "7991", mcc: "7997" }, legalBusinessName: "Whole Body Fitness LLC", phone: { number: "8185551212", countryCode: "1" }, taxID: { ein: { number: "123-45-6789" } }, website: "www.wholebodyfitnessgym.com", } }, capabilities: [ "send-funds.ach", "collect-funds.ach" ], customerSupport: { address: { addressLine1: "123 Main Street", addressLine2: "Unit 302", city: "Boulder", stateOrProvince: "CO", postalCode: "80301", country: "US" }, email: "amanda@classbooker.dev", phone: { number: "8185551212", countryCode: "1" }, website: "www.wholebodyfitnessgym.com" }, foreignId: "unique-correlation-id", metadata: { property1: "string", property2: "string" }, mode: "production", settings: { cardPayment: { statementDescriptor: "Whole Body Fitness" } }, termsOfService: { token: "kgT1uxoMAk7QKuyJcmQE8nqW_HjpyuXBabiXPi6T83fUQoxsyWYPcYzuHQTqrt7YRp4gCwyDQvb6U5REM9Pgl2EloCe35t-eiMAbUWGo3Kerxme6aqNcKrP_6-v0MTXViOEJ96IBxPFTvMV7EROI2dq3u4e-x4BbGSCedAX-ViAQND6hcreCDXwrO6sHuzh5Xi2IzSqZHxaovnWEboaxuZKRJkA3dsFID6fzitMpm2qrOh4" }, }; const account = await moov.accounts.create({accountPayload}); ``` ## [Individual account](#individual-account) The examples below have been broken up into all the small tasks needed to create an individual Moov account. However, when using the API, SDKs, or Moov.js, steps 2-4 *can* be consolidated into one step. See the [full example](/guides/accounts/create-accounts/#create-individual-account-full-example) for details. Sole proprietors need to be created with a [business account](#business-account). ### [Create individual account](#create-individual-account) You can provide a variety of information when creating an account. The example below only includes the minium required fields. The response object will include the newly created `accountID` which you will need to update the account. [cURL](#tab-695428317-0-0) [Go SDK](#tab-695428317-0-1) [Moov.js](#tab-695428317-0-2) [Onboarding Drop](#tab-695428317-0-3) Create account [reference](/api/moov-accounts/accounts/create/) ```zsh curl -X POST "https://api.moov.io/accounts" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "accountType": "individual", "profile": { "individual": { "email": "julesjacksonyoga@moov.io", "name": { "firstName": "Jules", "lastName": "Jackson" } } }, "foreignID": "unique-correlation-id" }'\ ``` Create account [reference](/api/moov-accounts/accounts/create/) ```go mc, _ := moov.NewClient() mc.CreateAccount(ctx, moov.CreateAccount{ Type: moov.AccountType_Individual, Profile: moov.CreateProfile{ Individual: &moov.CreateIndividualProfile{ Name: moov.Name{ FirstName: "Jules", LastName: "Jackson", }, Email: "julesjacksonyoga@moov.io", }, }, }) ``` Create account [reference](/api/moov-accounts/accounts/create/) ```javascript const moov = Moov(token); const accountPayload = { accountType: "individual", profile: { individual: { email: "julesjacksonyoga@moov.io", name: { firstName: "Jules", lastName: "Jackson" } } }, foreignID: "unique-correlation-id" }; const account = await moov.accounts.create({accountPayload}); ``` Onboarding Drop [reference](/moovjs/drops/onboarding/) With the onboarding Drop, you request capabilities when creating an account. After this step, you can jump ahead to [step 3](#send-platform-agreement-to-individual). ```html ``` ```javascript // Get the onboarding Drop const onboarding = document.querySelector("moov-onboarding"); // After generating a token, set it on the onboarding element onboarding.token = "some-generated-token"; // Include your accountID, which can be found in the Dashboard onboarding.facilitatorAccountID = "your-account-id"; // Request capabilities onboarding.capabilities = ["send-funds.ach"]; // Open the onboarding flow when ready onboarding.open = true; ``` ### [Request capabilities for individual](#request-capabilities-for-individual) Request capabilities for the account you've created by passing the `accountID`. You can find the account ID in the create account response, or you can find it by using the list accounts `GET` [endpoint](/api/moov-accounts/accounts/list/). [cURL](#tab-136427985-0-0) [Go SDK](#tab-136427985-0-1) [Moov.js](#tab-136427985-0-2) Request capabilities [reference](/api/moov-accounts/capabilities/post/) ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/capabilities" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "capabilities": [ "send-funds.ach" ] }'\ ``` Request capabilities [reference](/api/moov-accounts/capabilities/post/) ```go mc, _ := moov.NewClient() var accountID string mc.RequestCapabilities(ctx, accountID, []moov.CapabilityName{ moov.CapabilityName_Transfers, moov.CapabilityName_SendFundsACH, moov.Capability_NameWalletBalance, }, ) ``` Request capabilities [reference](/api/moov-accounts/capabilities/post/) ```javascript const moov = Moov(token); const accountID = "accountID"; const capabilities = [ "send-funds.ach" ]; moov.accounts.capabilities.request({accountID, capabilities}); ``` ### [Send platform agreement to individual](#send-platform-agreement-to-individual) You can send the platform agreement via a token, or manually using the `accountID`. To send a token, you must generate the token and then update the account with that token. To send Moov the acceptance manually, you must capture the information from the customer and send it to Moov. Moov recommends anyone using a server integration update the terms of service using the **manual method**. [Token](#tab-162589734-0-0) [Manual](#tab-162589734-0-1) [Terms of service Drop](#tab-162589734-0-2) Generate token [reference](/api/moov-accounts/accounts/get-tos/) and update account [reference](/api/moov-accounts/accounts/patch/) ```zsh # Get the terms of service token curl -X GET "https://api.moov.io/tos-token" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ ``` ```zsh # Send the token when patching the account curl -X PATCH "https://api.moov.io/accounts/{accountID}" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "termsOfService": { "token": "terms-of-service-token" }, "foreignID": "unique-correlation-id" }'\ ``` Update account [reference](/api/moov-accounts/accounts/patch/) ```zsh curl -X PATCH "https://api.moov.io/accounts/{accountID}" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "termsOfService": { "manual": { "acceptedDate": "accepted-date", "acceptedIP": "accepted-ip", "acceptedUserAgent": "accepted-user-agent", "acceptedDomain": "accepted-domain" } }, "foreignID": "unique-correlation-id" }'\ ``` Terms of Service Drop [reference](/moovjs/drops/terms-of-service/) ```html ``` ```javascript // Get the terms of service Drop const termsOfService = document.querySelector("moov-terms-of-service"); // Provide the token termsOfService.token = "eyjh..."; ``` ### [Create individual account full example](#create-individual-account-full-example) You can consolidate steps 1 through 3 using the create account `POST` [endpoint](/api/moov-accounts/accounts/create/). The below example includes all the fields you can send to Moov in one step when creating an individual account. Any additional [verification](/guides/accounts/requirements/identity-verification/) and [underwriting](/guides/accounts/requirements/underwriting/) requirements will be listed in the [Dashboard](https://dashboard.moov.io/signin). [cURL](#tab-237614589-6-0) [Go SDK](#tab-237614589-6-1) [Moov.js](#tab-237614589-6-2) Create account [reference](/api/moov-accounts/accounts/create/) ```zsh curl -X POST "https://api.moov.io/accounts" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ -H "X-Wait-For: connection" \ --data-raw '{ "accountType": "individual", "profile": { "individual": { "address": { "addressLine1": "123 Main Street", "addressLine2": "Apt 302", "city": "Boulder", "stateOrProvince": "CO", "postalCode": "80301", "country": "US" }, "birthDate": { "day": "09", "month": "05", "year": "1985" }, "email": "julesjacksonyoga@moov.io", "governmentID": { "ssn": { "full": "111111111", "lastFour": "1111" } }, "name": { "firstName": "Jules", "lastName": "Jackson" }, "phone": { "number": "8185551212", "countryCode": "1" }, } }, "capabilities": [ "transfers", "send-funds", "wallet" ], "foreignId": "unique-correlation-id", "metadata": { "property1": "string", "property2": "string" }, "mode": "production", "settings": { "cardPayment": { "statementDescriptor": "Jules Jackson" } }, "termsOfService": { "token": "kgT1uxoMAk7QKuyJcmQE8nqW_HjpyuXBabiXPi6T83fUKRJkA3dsFID6fzitMpm2qrOh4" } }'\ ``` Create account [reference](/api/moov-accounts/accounts/create/) ```go mc, _ := moov.NewClient() mc.CreateAccount(ctx, moov.CreateAccount{ Type: moov.AccountType_Individual, Profile: moov.CreateProfile{ Individual: &moov.CreateIndividualProfile{ Address: &moov.Address{ AddressLine1: "123 Main Street", AddressLine2: "Apt 302", City: "Boulder", StateOrProvince: "CO", PostalCode: "80301", Country: "US", }, BirthDate: &moov.Date{ Day: 9, Month: 5, Year: 1985, }, Email: "julesjacksonyoga@moov.io", GovernmentID: &moov.GovernmentID{ SSN: &moov.SSN{ Full: "111111111", LastFour: "1111", }, }, Name: moov.Name{ FirstName: "Jules", LastName: "Jackson", }, Phone: &moov.Phone{ Number: "8185551212", CountryCode: "1", }, }, }, RequestedCapabilities: []moov.CapabilityName{ moov.CapabilityName_Transfers, moov.CapabilityName_SendFunds, moov.CapabilityName_Wallet, }, ForeignID: "unique-correlation-id", Metadata: map[string]string{ "Property1": "string", "Property2": "string", }, AccountSettings: &moov.AccountSettings{ CardPayment: &moov.CardPaymentSettings{ StatementDescriptor: "Jules Jackson", }, }, TermsOfService: &moov.TermsOfServicePayload{ Token: "kgT1uxoMAk7QKuyJcmQE8nqW_HjpyuXBabiXPi6T83fUQoxsyWYPcYzuHQTqrt7YRp4gCwyDQvb6U5REM9Pgl2EloCe35t-eiMAbUWGo3Kerxme6aqNcKrP_6-v0MTXViOEJ96IBxPFTvMV7EROI2dq3u4e-x4BbGSCedAX-ViAQND6hcreCDXwrO6sHuzh5Xi2IzSqZHxaovnWEboaxuZKRJkA3dsFID6fzitMpm2qrOh4", }, }) ``` Create account [reference](/api/moov-accounts/accounts/create/) ```javascript const moov = Moov(token); const accountPayload = { accountType: "individual", profile: { individual: { address: { addressLine1: "123 Main Street", addressLine2: "Apt 302", city: "Boulder", stateOrProvince: "CO", postalCode: "80301", country: "US" }, birthDate: { day: "09", month: "05", year: "1985" }, email: "julesjacksonyoga@moov.io", governmentID: { ssn: { full: "111111111", lastFour: "1111" } }, name: { firstName: "Jules", lastName: "Jackson" }, phone: { number: "8185551212", countryCode: "1" }, } }, capabilities: [ "transfers", "send-funds", "wallet" ], foreignId: "unique-correlation-id", metadata: { property1: "string", property2: "string" }, mode: "production", settings: { cardPayment: { statementDescriptor: "Jules Jackson" } }, termsOfService: { token: "kgT1uxoMAk7QKuyJcmQE8nqW_HjpyuXBabiXPi6T83fUQoxsyWYPcYzuHQTqrt7YRp4gCwyDQvb6U5REM9Pgl2EloCe35t-eiMAbUWGo3Kerxme6aqNcKrP_6-v0MTXViOEJ96IBxPFTvMV7EROI2dq3u4e-x4BbGSCedAX-ViAQND6hcreCDXwrO6sHuzh5Xi2IzSqZHxaovnWEboaxuZKRJkA3dsFID6fzitMpm2qrOh4" }, }; const account = await moov.accounts.create({accountPayload}); ``` ## [Next steps](#next-steps) After you've successfully created accounts, the next step is to link a funding source like a card or bank account so you can start moving money. [Funding sources](/guides/sources/) [Move money](/guides/money-movement/) --- URL: https://docs.moov.io/guides/accounts/hosted-onboarding/ --- # Hosted onboarding This tutorial will show you how to create an onboarding link to a co-branded form through our secure hosted onboarding process. Send the link to merchants to complete their accounts. Generate a link to a co-branded onboarding application from the [Dashboard](https://dashboard.moov.io/) or our [API](/api/moov-accounts/onboarding/). Any existing information you have for merchants, such as names and addresses, can be pre-filled. When you send a link, a secure session is created and merchants are prompted to complete the form and sign up for access to Moov. Merchants can be redirected to your app upon completion. We strongly suggest using the Dashboard's hosted onboarding process to create onboarding links for your merchants. Visit our [Dashboard documentation](/guides/dashboard/accounts/onboarding-links/) for more information. ## [Merchant experience](#merchant-experience) Merchants will need to create an account with Moov to access the form. During this process, they'll give permission for you to move money and perform actions on behalf of their account, and they'll view and agree to the pricing disclosure for the plan you've selected. Once an account has been created, they can start and pause the session, filling out the form at their convenience. Merchants need to double check any pre-filled information for accuracy. In addition to basic information, business accounts will be required to provide owners and control officers. The onboarding form supports uploading documents for this purpose. ![Onboard link in Dashboard](../../shared-images/onboarding-form.png) ### [Your branding](#your-branding) Hosted onboarding contains several references to your own brand, including: - Your logo and company name displayed throughout the onboarding flow - Page title and meta description includes your company name - Social share image includes your logo - Accent colors for both light and dark mode - If set, the `returnURL` will redirect the user to your app upon completion of the form - If set, `termsOfServiceURL` will reference your terms of service within the hosted onboarding flow alongside Moov's platform agreement and privacy policy Brand accent colors can be set by navigating to **Settings** in the Dashboard or with the [enrichment](/api/enrichment/branding/create/) API. The return URL and terms of service URL can be set when creating an onboarding link in the Dashboard or with the [onboarding](/api/moov-accounts/onboarding/post/) API. ## [Create a link](#create-a-link) Create a link and send a form to merchants to fill out at their convenience. Form links will expire upon completion and attempts by a merchant to access a completed form will result in a `404` error. When you create a link you'll need to provide the desired account type, capabilities, and fee plan. Sole proprietors must be created via the business profile with `businessType.soleProprietorship`. Read the [capabilities](/guides/accounts/capabilities/) and [fee plan](/guides/fee-plans/) guides for details. You'll also need to provide the list of [scopes](/api/authentication/scopes/#available-scopes) you want to use on the account. Use the onboarding `POST` [endpoint](/api/moov-accounts/onboarding/post/) to create an onboarding link. You're required to send the following with your request: - Capabilities - Fee plan codes for the account - Scopes Additionally, you can choose to send a custom return URL, your terms of service URL, and prefill any merchant data. ### [Choose capabilities](#choose-capabilities) Select a business or individual account type and choose the capabilities for the account. Capabilities allow Moov accounts to receive transfers or send money to other accounts. Each capability will have a set of [requirements](/guides/accounts/capabilities/reference/) that need to be met before it can be enabled. Capabilities allow you to accomplish the following: - Authorize debit transfers - Store funds with Moov - Send funds to another account - Collect funds from another account (business accounts only) - Provide a virtual card to a merchant (business accounts only) You can request the following capabilities depending on use case and need: - `wallet.balance` - `collect-funds.ach` - `collect-funds.card-payments` - `send-funds.ach` - `send-funds.instant-bank` - `send-funds.push-to-card` - `card-issuing` - `money-transfer.pull-from-card` - `money-transfer.push-to-card` ### [Select fee plan](#select-fee-plan) Use the [fee plan](/api/moov-accounts/billing/list-plans/) API to retrieve what fee plans are available to use with an account. Familiarize yourself with [billable events](/guides/billing/fee-plans/#billable-events) before creating or selecting a fee plan. Select a standard plan, which has a $500 monthly transaction minimum, or set up a custom interchange plan. For some fees, you have the option of choosing an all-in model, or you can also assign specific fees based on fee types. Once you create a plan, you can assign it to one merchant or reuse it for many merchants. Merchants must agree to and accept the fee plan before it can go into effect. **Cost plus:** With a cost plus plan, card networks’ interchange fees and Moov’s processing markup are passed along to the merchant. Cost plus plans are beneficial for merchants with a high and varied transaction volume that prefer to have more control over fees. Fees are broken down into a more digestible and transparent format. **Flat rate:** With a flat rate plan, you can lump all the processing fees together with a flat rate customized for each merchant. Flat plans are beneficial for merchants with a low transaction volume that prefer a predictable solution over lowering cost as much as possible. When you set up a merchant with a fee plan, they will receive a pricing disclosure they need to accept. The pricing disclosure shows the rates for the following: - ACH - Card acquiring - Instant payments (RTP) - Transaction management fees - Platform fees - Network fees ### [Prefill data](#prefill-data) At this time you'll also decide whether or not to prefill any existing merchant data or configure client-side authorization through scopes. If you selected to prefill data, enter in basic information for the merchant, such as company name, industry, and address. ### [Send request](#send-request) The following is a sample request with prefilled data, including a terms of service token. Any merchant that requires wallet, collect funds, send funds, or card issuing capabilities must accept Moov's [platform agreement](/guides/accounts/requirements/platform-agreement/). Before you create an onboarding link with the [onboarding API](/api/moov-accounts/onboarding/post/), you can use the [accounts API](/api/moov-accounts/accounts/get-tos/) to generate a terms of service token to send along with the onboarding link request. ```zsh curl --X POST "https://api.moov.io/onboarding-invites" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "returnURL": "https://mycompany.com/account", "termsOfServiceURL": "https://mycompany.com/terms-of-service", "scopes": [ "accounts.read" ], "capabilities": [ "transfers" ], "feePlanCodes": [ "merchant-direct" ], "prefill": { "mode": "production", "accountType": "business", "profile": { "business": { "legalBusinessName": "Whole Body Fitness LLC", "doingBusinessAs": "Whole Body Fitness", "businessType": "llc", "address": { "addressLine1": "123 Main Street", "addressLine2": "Apt 302", "city": "Boulder", "stateOrProvince": "CO", "postalCode": "80301", "country": "US" }, "phone": { "number": "8185551212", "countryCode": "1" }, "email": "amanda@classbooker.dev", "website": "www.wholebodyfitnessgym.com", "description": "Local fitness center paying out instructors", "taxID": { "ein": { "number": "123-45-6789" } }, "industryCodes": { "naics": "713940", "sic": "7991", "mcc": "7997" }, "primaryRegulator": "FDIC" } }, "metadata": { "property1": "string", "property2": "string" }, "termsOfService": { "token": "kgT1uxoMAk7QKuyJcmQE8nqW_HjpyuXBabiXPi6T83fUKRJkA3dsFID6fzitMpm2qrOh4" }, "foreignID": "4528aba-b9a1-11eb-8529-0242ac13003", "customerSupport": { "phone": { "number": "8185551212", "countryCode": "1" }, "email": "amanda@classbooker.dev", "address": { "addressLine1": "123 Main Street", "addressLine2": "Apt 302", "city": "Boulder", "stateOrProvince": "CO", "postalCode": "80301", "country": "US" }, "website": "www.wholebodyfitnessgym.com" }, "settings": { "cardPayment": { "statementDescriptor": "Whole Body Fitness" }, "achPayment": { "companyName": "Whole Body Fitness" } } } }'\ ``` ## [Manage onboarding invites](#manage-onboarding-invites) [List all invites](/api/moov-accounts/onboarding/list/) using the API. The response will have the `code` for each invite. The onboarding link code is required to [retrieve](/api/moov-accounts/onboarding/get/) an individual invite or [revoke](/api/moov-accounts/onboarding/delete/) an invite. Revoking an invite renders the link unusable. ## [Status](#status) The easiest way to track an onboarding link's status through the Dashboard, under **Accounts > Onboarding links**. You can track whether a merchant has created an account and started to complete the form. The Dashboard will also alert you if newly created accounts have any outstanding [capability requirements](/guides/accounts/capabilities/reference/). --- URL: https://docs.moov.io/guides/accounts/ --- # Moov accounts Learn how to create, connect, and update accounts on Moov's platform. Before you can move real money with a production account, you'll need to sign a contract and set up a fee plan with Moov. [Contact us](https://moov.io/contact/) to select a fee plan and get the verification process started. Your Moov account is different from other Moov accounts. Your account: - Facilitates money movement - Is hidden in your list of accounts - Can be used as a source or destination in a transfer - Can be updated through the settings page in the Dashboard When interacting with [transfers](/api/money-movement/transfers/) via Moov.js or any client-side integration, you must specify your `accountID` for the following [scopes](/api/authentication/scopes/): - `/accounts/{accountID}/transfers.write` - `/accounts/{accountID}/transfers.read` After your account has been created, you can then create individual or business accounts for each of your users. Every account requires a profile with information describing the legal entity associated with it, including information for verification and underwriting purposes. Additionally, every account requesting capabilities to process payments must agree to Moov's platform terms of service agreement. To create merchant accounts with payment processing abilities, use one of the following: - [Hosted onboarding](/guides/accounts/hosted-onboarding/) - [Onboarding Drop](/moovjs/drops/onboarding/) - [Accounts API](/guides/accounts/create-accounts/) Bank accounts, payment cards, and transfer activity are all associated with singular Moov accounts and can be monitored on your platform. For example, if someone changes their linked bank account, all past activity remains associated with their Moov account. Explore the pages in this section for more information on account creation, verification, and management. Your agreement with Moov may include a cost per active verified Moov account. Verified Moov accounts have gone through [KYC checks](/guides/accounts/requirements/identity-verification/) which are initiated by opting into certain [capabilities](/guides/accounts/capabilities/). The capabilities that have been selected may impact the price of each verified account. --- URL: https://docs.moov.io/guides/accounts/requirements/business-representatives/ --- # Business representatives Business representatives are individuals with significant control or beneficial ownership of a business entity. Moov must verify these individuals before enabling payment capabilities. ## [Quick start](#quick-start) 1. **Create at least one control officer** using the representatives [POST endpoint](/api/moov-accounts/representatives/create/) with `isController: true` 2. **Create all beneficial owners** (individuals with ≥25% ownership) with `isOwner: true` and `ownershipPercentage` 3. **Confirm ownership** by setting `ownersProvided: true` on the account using the [PATCH endpoint](/api/moov-accounts/accounts/patch/) Step 3 is required even if no one owns ≥25% of the business. The Moov Dashboard handles this flow automatically. ## [Why this is required](#why-this-is-required) Under FinCEN's [Customer Due Diligence (CDD) rule](https://www.fincen.gov/resources/statutes-and-regulations/cdd-final-rule), financial institutions must identify and verify the identity of beneficial owners who own 25% or more of a legal entity, as well as at least one individual with significant management responsibility. This helps prevent money laundering and financial crimes. Moov collects this information through two categories of business representatives: | Type | Description | Required | |----------------|-------------------------------------------------------------------------------------------|-----------------| | **Controller** | An individual with significant management responsibility (CEO, CFO, COO, President, etc.) | At least one | | **Owner** | An individual who owns ≥25% of the business | All who qualify | If one person is both a control officer and beneficial owner, set both `isController` and `isOwner` to **true**. Moov allows a maximum of 7 representatives per account. ## [Control officer](#control-officer) A control officer is someone with significant management responsibilities and the authority to make decisions within the business. Examples include: - CEO, COO, CFO, or other C-suite executives - President or Vice President - Treasurer or Secretary - Managing Partner or General Partner Create a control officer using the representatives [POST endpoint](/api/moov-accounts/representatives/create/) with `isController: true` and include a `jobTitle`. Regardless of how many control officers the business has, you only need to create **one**. ## [Owner](#owner) US state and federally regulated financial institutions are exempt from beneficial ownership requirements. A beneficial owner is an individual who owns 25% or more of the business. All beneficial owners must be verified by Moov before payment capabilities can be enabled. Create each beneficial owner using the representatives [POST endpoint](/api/moov-accounts/representatives/create/) with: - `isOwner: true` - `ownershipPercentage` (the percentage they own) If no individual owns ≥25% of the business, you don't need to create any owners, but you still must set `ownersProvided: true` on the account to confirm that no individuals meet the 25% threshold. ## [Data requirements](#data-requirements) The table below shows what information is required for each representative type. | Required information | Control officer | Beneficial owner | |-----------------------|-----------------|------------------| | Legal name | **✓** | **✓** | | Personal address | **✓** | **✓** | | Email or phone | **✓** | **✓** | | Date of birth | **✓** | **✓** | | Full SSN | **✓** | **✓** | | `isController: true` | **✓** | | | Job title | **✓** | | | `isOwner: true` | | **✓** | | `ownershipPercentage` | | **✓** | The personal address must be a residential address. The following address types **cannot** be used: - PO Box - Commercial mailing receiving agency - Registered agent address ## [Verification timing](#verification-timing) Most representative verifications complete automatically within seconds. If Moov cannot verify a representative automatically, you may need to upload supporting documents. Common scenarios requiring documents: - Name, address, or date of birth could not be matched - SSN could not be verified See [troubleshooting verification](/guides/accounts/capabilities/troubleshoot/) for document requirements and resolution steps. ## [Troubleshoot verification](#troubleshoot-verification) The individual or business representative’s name could not be verified. Moov requires an unexpired government issued ID that shows the full name. Acceptable documents include an unexpired drivers license or ID card. In certain situations where an ID is not available, a residential lease or mortgage document may suffice. The address provided cannot be a commercial address. The individual or business representative’s residential address could not be verified. Moov requires an unexpired government issued ID that shows the residential address. Acceptable documents include an unexpired drivers license or ID card. In certain situations where an ID is not available, a residential lease or mortgage document may suffice. The address provided cannot be a commercial address. The individual or business representative's date of birth could not be verified. Moov requires an unexpired government issued ID that shows the date of birth. Acceptable documents include a drivers license, passport, or ID card. The individual or business representative’s SSN could not be verified. Moov requires a government issued document that shows the individual’s SSN. Acceptable documents include a SSN or ITIN card, a tax return statement, or a W2. --- URL: https://docs.moov.io/guides/accounts/requirements/identity-verification/ --- # Verification Moov verifies the identity of individuals and businesses before enabling payment capabilities. This page explains the verification process and data requirements. ## [Overview](#overview) Banking regulations require financial institutions to verify customer identities before enabling certain capabilities. This includes: - **Know Your Customer (KYC):** Verifying individual identity - **Know Your Business (KYB):** Verifying business identity and [beneficial ownership](/guides/accounts/requirements/business-representatives/) All Moov accounts are checked against [OFAC](https://ofac.treasury.gov/) and sanctions lists to ensure they are not prohibited from conducting business in the United States. Moov simplifies this process: request [capabilities](/guides/accounts/capabilities/reference/) for an account, collect the required data, and Moov automatically starts verification. ## [When verification is required](#when-verification-is-required) | Scenario | Verification required? | Capability | |---------------------------------------|------------------------|-------------------------------------------------------------------------| | Storing money in a Moov wallet | ✓ | [wallet.balance](/guides/accounts/capabilities/reference/#wallet) | | Collecting money from another account | ✓ | [collect-funds](/guides/accounts/capabilities/reference/#collect-funds) | | Sending money to another account | ✓ | [send-funds](/guides/accounts/capabilities/reference/#send-funds) | | Receiving payouts | | [transfers](/guides/accounts/capabilities/reference/#transfers) | | Paying with a card or bank account | | [transfers](/guides/accounts/capabilities/reference/#transfers) | ## [Beneficial ownership](#beneficial-ownership) For business accounts, Moov must verify both the business entity and its [business representatives](/guides/accounts/requirements/business-representatives/) (control officers and beneficial owners). US state and federally regulated financial institutions are exempt from beneficial ownership requirements. Under FinCEN's Customer Due Diligence rule, Moov must verify all individuals who own 25% or more of the business (beneficial owners) and at least one control officer. See the [business representatives](/guides/accounts/requirements/business-representatives/) guide for complete requirements. **Before verification can start:** 1. Create all required [business representatives](/guides/accounts/requirements/business-representatives/) 2. Set `ownersProvided: true` on the account using the [PATCH endpoint](/api/moov-accounts/accounts/patch/) ## [Verification timing](#verification-timing) Verification is performed asynchronously and typically completes within a minute. However, some businesses may take multiple minutes. Most verifications complete automatically. If Moov cannot verify information automatically, you'll receive requirements for additional documentation through the capabilities API or Dashboard. Subscribe to [capability webhooks](/guides/webhooks/webhook-events/#capabilities) to receive real-time updates on verification status: | Event | Description | |------------------------|---------------------------------------------------------------------------------| | `capability.requested` | Capability has been requested | | `capability.updated` | Capability status changed (e.g., requirements fulfilled, verification complete) | ## [Required verification data](#required-verification-data) The tables below list all verification data fields and their API paths. Moov may request additional documents to complete verification—these will appear in the Dashboard and the [capabilities API](/api/moov-accounts/capabilities/list/). ### Business profile Set on `profile.business` via the [accounts API](/api/moov-accounts/accounts/) | Field | API path | Status | Notes | |---------------------|---------------------|-------------|--------------------------------------------------------------------------------------------------------| | Legal business name | `legalBusinessName` | Required | | | Doing business as | `doingBusinessAs` | Optional | | | Business type | `businessType` | Required | | | Address | `address` | Required | Must be a physical location; no PO boxes or registered agents | | Phone | `phone` | Required | | | EIN | `taxID.ein.number` | Required | SSN can be used for sole proprietors | | Description | `description` | Conditional | Required if `website` not provided | | Website | `website` | Conditional | Required if `description` not provided | | Industry | `industry` | Required | See [industries endpoint](/api/enrichment/form-shortening/industries/get/); or use `industryCodes.mcc` | | MCC code | `industryCodes.mcc` | Conditional | Required if `industry` not provided | | Owners provided | `ownersProvided` | Conditional | Required for corporations, partnerships, and LLCs | | Terms of Service | `termsOfService` | Required | Set on the account object | View requirement IDs for capabilities API | Field | Requirement ID | |---------------------|-------------------------------------| | Legal business name | `business.legalname` | | Doing business as | `business.dba` | | Business type | `business.business-type` | | Address | `business.address` | | Phone | `business.phone` | | EIN | `business.ein` | | Description | `business.description` | | Website | `business.description-or-website` | | Industry | `business.industry` | | MCC code | `business.industry-code-mcc` | | Owners provided | `business.indicate-owners-provided` | | Terms of Service | `account.tos-acceptance` | ### Representative(s) Set via the [representatives API](/api/moov-accounts/representatives/) For details on control officers vs beneficial owners, see [Business representatives](/guides/accounts/requirements/business-representatives/). | Field | API path | Status | Notes | |----------------------|----------------------------------------|-------------|--------------------------------------------------------------------| | First name | `name.firstName` | Required | | | Last name | `name.lastName` | Required | | | Email | `email` | Required | | | Phone | `phone` | Required | | | Address | `address` | Required | Must be a residential address; no PO boxes or commercial addresses | | Date of birth | `birthDate` | Required | | | Full SSN | `governmentID.ssn.full` | Required | | | Is controller | `responsibilities.isController` | Required | At least one representative must be a controller | | Job title | `responsibilities.jobTitle` | Conditional | Required if `isController` is `true` | | Is owner | `responsibilities.isOwner` | Conditional | Required if ownership ≥25% | | Ownership percentage | `responsibilities.ownershipPercentage` | Conditional | Required if `isOwner` is `true` | View requirement IDs for capabilities API | Field | Requirement ID | |----------------------|---------------------------------------| | First name | `representative.{uuid}.firstname` | | Last name | `representative.{uuid}.lastname` | | Email | `representative.{uuid}.email` | | Phone | `representative.{uuid}.mobile` | | Address | `representative.{uuid}.address` | | Date of birth | `representative.{uuid}.birthdate` | | Full SSN | `representative.{uuid}.ssn` | | Is controller | `representative.{uuid}.is-controller` | | Job title | `representative.{uuid}.job-title` | | Is owner | `representative.{uuid}.is-owner` | | Ownership percentage | `representative.{uuid}.ownership` | For additional requirements beyond verification, see our [underwriting](/guides/accounts/requirements/underwriting/) guide. ## [Troubleshoot verification](#troubleshoot-verification) The business name could not be verified. Double check that the provided name is the full legal business name and there are no typos. If everything is accurate, but the name cannot be verified, Moov will require one of the following: EIN letter from the IRS or Articles of Incorporation. The documents provided must list the name as entered into Moov's system. The business address could not be verified. Double check the address was entered correctly and that the business representative's residential address was not used as the commercial business address. Commercial addresses cannot be a PO box, commercial mailing receiving agency, or registered agent. The business has a PO box, commercial mailing receiving agency, or registered agent listed as the commercial address. Commercial business addresses cannot be a PO box, commercial mailing receiving agency, or registered agent. The address must be a valid, physical location where the business operates. Moov can't verify the TIN or EIN. Double check the EIN is correct and the legal business name exactly matches IRS records (including punctuation and abbreviations). If everything is accurate, and Moov returns a tax ID mismatch, you will need to upload one of the following documents showing the EIN and legal name: EIN confirmation letter from the IRS or a tax document (for example, a 1099). The business does not have past processing statements. Moov needs to understand the volume of transactions the business intends to process. You will need to provide the average number and dollar volume of transactions you will be processing monthly and the average dollar amount of individual transactions. Do I need to run my users through KYC again if I am switching to Moov? Yes. KYC requirements pertain to each relationship an account holder has with the sponsor bank, so we are required to perform these checks again. How long does verification take? It depends. Automatic verification can take less than a second but if there is an error or the data requires manual review, the process may involve additional information or documentation and take up to several days. Are there special requirements for business representatives? Yes. See our [business representative](/guides/accounts/requirements/business-representatives/) guide for more information. --- URL: https://docs.moov.io/guides/accounts/requirements/ --- # Account requirements Learn about the information Moov requires for verifying account holders and enabling capabilities. Every Moov account is subject to certain requirements. These requirements vary depending on the account type (business vs. individual) as well as what [capabilities](/guides/accounts/capabilities/) you're looking to request for the account. Your application will need to be [authenticated](/api/authentication/api-authentication/#client-side-oauth-with-jwt) to interact with Moov's platform when collecting terms of service acceptance for accounts. Use the guides in this section to learn more about account requirements. --- URL: https://docs.moov.io/guides/accounts/requirements/platform-agreement/ --- # Platform terms of service agreement Learn how to implement Moov's platform terms of service agreement with our API or Moov.js. Accounts that require any capability in addition to `transfer` must agree to Moov's platform terms of service agreement before a transfer can be created with that account. You must display a link to both the [privacy policy](https://moov.io/legal/privacy-policy/) and [platform agreement](https://moov.io/legal/platform-agreement/) in your application, and the terms must be accepted by the user. A user's platform agreement acceptance needs to be sent to Moov in the form of a token. Terms of service tokens must be created on the client-side for the user to accept. You can then pass the token to your server when creating or updating the account. You'll need to [authenticate](/api/authentication/api-authentication/#client-side-oauth-with-jwt) your application before you generate a terms of service token. The Moov.js [Drop](#terms-of-service-drop) is the best way to securely capture a user's platform agreement acceptance and send it to Moov - the terms of service API is not available to everyone. ## [Terms of service Drop](#terms-of-service-drop) [Moov.js](/moovjs/) is a browser client that collects PII data so you don’t have to be responsible for handling and storing sensitive customer information. Moov.js provides a pre-built [terms of service Drop](/moovjs/drops/terms-of-service/). With the pre-built user interface, you can integrate our privacy policy and terms of service while simultaneously generating a token in the background. The token can be patched to an account using the accounts `PATCH` [endpoint](/api/moov-accounts/accounts/patch/). ### [Alternate Moov.js implementation](#alternate-moovjs-implementation) To confirm the platform terms of service agreement acceptance via Moov.js, pass the `accountID` into the following method. This will generate a terms of service token and update the account in one step. | Name | Type | |-------------|--------| | `accountID` | string | ```javascript moov.accounts.acceptTermsOfService({ accountID: "account-id" }); ``` Separately, if you need to generate a terms of service token to pass to the Moov API, you can call the following method. ```javascript moov.accounts.getTermsOfServiceToken(); ``` Visit the [Moov.js](/moovjs/accounts/accounts/) documentation for more information on creating accounts with Moov.js. ## [API implementation](#api-implementation) **The API implementations outlined below are not available to everyone.** If you are not authorized by Moov to use these flows, you will receive a `400` error. To confirm the platform terms of service agreement acceptance via the API, you must send either a token, or enter the acceptance manually. You can provide this information when creating an account, or by updating an existing account. ### [Terms of service token](#terms-of-service-token) You can retrieve and send the token when creating an account, or you can update the account after it's been created. To send Moov the terms of service token, retrieve the token with the terms of service `GET` [endpoint](/api/moov-accounts/accounts/get-tos/). Use the account `POST` [endpoint](/api/moov-accounts/accounts/create/) to send the token when creating an account, or use the `PATCH` [endpoint](/api/moov-accounts/accounts/patch/) when updating an account.. [Create account with token](#tab-267145398-3-0) [Update account with token](#tab-267145398-3-1) ```zsh # Get the terms of service token curl -X GET "https://api.moov.io/tos-token" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ ``` ```zsh # Send the token when creating an account curl -X POST "https://api.moov.io/accounts" \ # ... --data-raw '{ "accountType": "account-type", "profile": {...}, "termsOfService": { "token": "terms-of-service-token" }, "foreignID": "unique-correlation-id" }'\ ``` ```zsh # Get the terms of service token curl -X GET "https://api.moov.io/tos-token" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ ``` ```zsh # Send the token when patching the account curl -X PATCH "https://api.moov.io/accounts/{accountID}" \ # ... --data-raw '{ "termsOfService": { "token": "terms-of-service-token" }, "foreignID": "unique-correlation-id" }'\ ``` ### [Manual entry](#manual-entry) You'll need to capture a date-time, IP address, user agent and domain to manually enter a terms of service agreement. For manual entry when creating an account, use the create account `POST` [endpoint](/api/moov-accounts/accounts/create/). For manual entry when updating an account, use the patch account `PATCH` [endpoint](/api/moov-accounts/accounts/patch/). [Create account manually](#tab-725641983-4-0) [Update account manually](#tab-725641983-4-1) ```zsh curl -X POST "https://api.moov.io/accounts" \ # ... --data-raw '{ "accountType": "your-account-type", "profile": {...}, "termsOfService": { "manual": { "acceptedDate": "accepted-date", "acceptedIP": "accepted-ip", "acceptedUserAgent": "accepted-user-agent", "acceptedDomain": "accepted-domain" } }, "foreignID": "unique-correlation-id" }'\ ``` ```zsh curl -X PATCH "https://api.moov.io/accounts/{accountID}" \ # ... --data-raw '{ "termsOfService": { "manual": { "acceptedDate": "accepted-date", "acceptedIP": "accepted-ip", "acceptedUserAgent": "accepted-user-agent", "acceptedDomain": "accepted-domain" } }, "foreignID": "unique-correlation-id" }'\ ``` --- URL: https://docs.moov.io/guides/accounts/requirements/underwriting/ --- # Underwriting Underwriting is Moov's risk assessment process that lets us safely enable payment capabilities for accounts on your platform. As a payment processor, Moov is required to do due diligence and understand an account's business model, transaction patterns, and risk profile before enabling money movement capabilities. Through underwriting, we can understand and prevent unnecessary financial risk while ensuring high-volume established businesses have adequate processing thresholds. ## [Quick start](#quick-start) Underwriting is required for all capabilities except `transfers`. Here's what you need to know: 1. **Request capabilities** → Moov returns the baseline required underwriting fields 2. **Submit underwriting data** → Use the [underwriting API](/api/moov-accounts/underwriting/post/) 3. **Re-check capabilities** → Additional requirements may appear based on the submitted values 4. **Repeat until no requirements remain** → Once all requirements are met, capabilities are enabled Most approvals are instant. Some high-volume or high-risk profiles may take up to two business days. ## [How requirements work](#how-requirements-work) Underwriting requirements are **tiered** based on the account's business profile. This means low-volume, US-only businesses have minimal requirements, while higher-volume or international businesses need to provide more detail. ### [Baseline requirements (all capabilities)](#baseline-requirements-all-capabilities) Every capability requires these two fields: | Field | Description | Values | |----------------------|---------------------------------------------------------|---------------------------------------------------------| | `geographicReach` | Where are the account's customers located? | `us-only`, `us-and-international`, `international-only` | | `monthlyVolumeRange` | Estimated monthly transaction volume for the capability | See [volume ranges](#volume-ranges) | **Fast path:** If `geographicReach` is `us-only` AND `monthlyVolumeRange` is `under-10k`, these are the only fields required for most capabilities. ### [Extended requirements](#extended-requirements) These fields are required when **either** of the following is true: - `monthlyVolumeRange` is greater than `under-10k` - `geographicReach` is `us-and-international` or `international-only` | Field | Description | Format | |-----------------------------|-------------------------------------------------------|------------------------------------------------------------| | `businessPresence` | How does the business operate? | See [business presence types](#business-presence-types) | | `volumeShareByCustomerType` | Percentage of transactions that are B2B vs B2C vs P2P | Object with `business`, `consumer`, `p2p` (must total 100) | | `pendingLitigation` | Current or pending legal matters | See [pending litigation](#pending-litigation) | | `averageTransactionAmount` | Average transaction size in USD | Integer (per capability) | | `maximumTransactionAmount` | Maximum transaction size in USD | Integer (per capability) | ### [Card payment requirements](#card-payment-requirements) The `collect-funds.card-payments` capability has additional requirements: | Condition | Additional fields required | |------------------------------------------------------------|--------------------------------------------------------------------------------------------------| | All card merchants | [`currentlyAcceptsCards`](#card-acceptance), [`cardAcceptanceMethods`](#card-acceptance-methods) | | Card-not-present merchants (`inPersonPercentage` < 80%) | [`fulfillment`](#fulfillment), [`refundPolicy`](#refund-policy-options) | | Currently accepts cards (`currentlyAcceptsCards` = true) | Upload processing statements via [files API](/api/moov-accounts/files/post/) | ## [Capabilities reference](#capabilities-reference) All capabilities follow the same tiered requirement structure. The table below shows available capabilities: | Capability | Description | |---------------------------------|--------------------------------------------------------------------------------------| | **Collect funds** | | | `collect-funds.ach` | Pull funds via ACH debit | | `collect-funds.card-payments` | Accept cards and digital wallets (e.g. Apple/Google Pay) | | **Send funds** | | | `send-funds.ach` | Push funds via ACH credit (standard or same-day) | | `send-funds.push-to-card` | Instant disbursement via Visa Direct or Mastercard Send | | `send-funds.instant-bank` | Instant bank transfers via RTP & FedNow | | **Money transfer** | | | `money-transfer.pull-from-card` | Pull funds from debit/prepaid cards for me-to-me account funding or person-to-person | | `money-transfer.push-to-card` | Push funds to debit/prepaid cards for me-to-me transfers or person-to-person | ## [API workflow](#api-workflow) ### [Check requirements](#check-requirements) Use the [capabilities API](/api/moov-accounts/capabilities/list/) to see what's required. Underwriting fields are prefixed with `underwriting.`: ```json { "capability": "collect-funds.card-payments", "status": "pending", "requirements": { "currentlyDue": [ "underwriting.geographicReach", "underwriting.collectFunds.cardPayments.estimatedActivity.monthlyVolumeRange" ] } } ``` ### [Submit underwriting data](#submit-underwriting-data) Use the [underwriting POST endpoint](/api/moov-accounts/underwriting/post/) to submit data: ```json { "geographicReach": "us-only", "collectFunds": { "cardPayments": { "estimatedActivity": { "monthlyVolumeRange": "under-10k" } } } } ``` The POST endpoint is required for API versions v2025.07.00 and later. ### [Check for additional requirements](#check-for-additional-requirements) Re-query capabilities after each submission. New requirements may appear based on the submitted values: ```json { "capability": "collect-funds.card-payments", "status": "pending", "requirements": { "currentlyDue": [ "underwriting.pendingLitigation", "underwriting.businessPresence", "underwriting.volumeShareByCustomerType", "underwriting.collectFunds.cardPayments.estimatedActivity.averageTransactionAmount", "underwriting.collectFunds.cardPayments.estimatedActivity.maximumTransactionAmount" ] } } ``` ### [Repeat until complete](#repeat-until-complete) Continue submitting data until `currentlyDue` is empty and `status` changes to `enabled`. ## [Full example](#full-example) This example onboards a merchant requesting `collect-funds.ach` and `collect-funds.card-payments`. ### [Request capabilities](#request-capabilities) ```bash curl -X POST "https://api.moov.io/accounts/{accountID}/capabilities" \ -H "Authorization: Bearer {token}" \ -H "Content-Type: application/json" \ -d '{ "capabilities": [ "collect-funds.ach", "collect-funds.card-payments" ] }' ``` **Response:** Initial requirements for both capabilities: ```json [ { "capability": "collect-funds.ach", "status": "pending", "requirements": { "currentlyDue": [ "underwriting.geographicReach", "underwriting.collectFunds.ach.estimatedActivity.monthlyVolumeRange" ] } }, { "capability": "collect-funds.card-payments", "status": "pending", "requirements": { "currentlyDue": [ "underwriting.geographicReach", "underwriting.collectFunds.cardPayments.estimatedActivity.monthlyVolumeRange" ] } } ] ``` ### [Submit baseline underwriting](#submit-baseline-underwriting) Submit geographic reach and volume estimates: ```json { "geographicReach": "us-only", "collectFunds": { "ach": { "estimatedActivity": { "monthlyVolumeRange": "under-10k" } }, "cardPayments": { "estimatedActivity": { "monthlyVolumeRange": "10k-50k" } } } } ``` **Result:** ACH is approved (low volume, US-only). Card payments triggers extended requirements because volume exceeds `under-10k`: ```json [ { "capability": "collect-funds.ach", "status": "enabled", "requirements": {} }, { "capability": "collect-funds.card-payments", "status": "pending", "requirements": { "currentlyDue": [ "underwriting.pendingLitigation", "underwriting.businessPresence", "underwriting.volumeShareByCustomerType", "underwriting.collectFunds.cardPayments.estimatedActivity.averageTransactionAmount", "underwriting.collectFunds.cardPayments.estimatedActivity.maximumTransactionAmount", "underwriting.collectFunds.cardPayments.currentlyAcceptsCards", "underwriting.collectFunds.cardPayments.cardAcceptanceMethods" ] } } ] ``` ### [Submit extended requirements](#submit-extended-requirements) Complete all remaining requirements: ```json { "pendingLitigation": "none", "businessPresence": "online-only", "volumeShareByCustomerType": { "business": 80, "consumer": 20, "p2p": 0 }, "collectFunds": { "cardPayments": { "estimatedActivity": { "averageTransactionAmount": 150, "maximumTransactionAmount": 1000 }, "currentlyAcceptsCards": true, "cardAcceptanceMethods": { "inPersonPercentage": 10, "onlinePercentage": 90, "mailOrPhonePercentage": 0 }, "fulfillment": { "method": "shipped-physical-goods", "timeframe": "within-7-days" }, "refundPolicy": "full-refund-within-30-days" } } } ``` ### [Upload documents (if required)](#upload-documents-if-required) If the merchant currently accepts cards, upload processing statements: ```bash curl -X POST "https://api.moov.io/accounts/{accountID}/files" \ -H "Authorization: Bearer {token}" \ -F "file=@/path/to/processing-statement.pdf" \ -F "filePurpose=underwriting" ``` ## [Reference](#reference) Use the following sections as a reference for various parts of the underwriting process. ### [Volume ranges](#volume-ranges) Select the range that matches the account's expected monthly transaction volume for `monthlyVolumeRange`: | Value | Range | |-------------|-------------------------| | `under-10k` | Less than $10,000 | | `10k-50k` | $10,000 – $50,000 | | `50k-100k` | $50,000 – $100,000 | | `100k-250k` | $100,000 – $250,000 | | `250k-500k` | $250,000 – $500,000 | | `500k-1m` | $500,000 – $1,000,000 | | `1m-5m` | $1,000,000 – $5,000,000 | | `over-5m` | Over $5,000,000 | ### [Business presence types](#business-presence-types) Select the option that best describes how the business operates for `businessPresence`: | Value | Description | |---------------------|--------------------------------------------| | `commercial-office` | Traditional office space | | `retail-storefront` | Physical retail location | | `home-based` | Operated from residential address | | `online-only` | No physical customer interaction | | `mobile-business` | Service provider that travels to customers | | `mixed-presence` | Combination of physical and online | ### [Pending litigation](#pending-litigation) Select the option that applies to current or pending legal matters for `pendingLitigation`: | Value | Description | |-------------------------------------------|--------------------------------------------------| | `none` | No current or pending litigation | | `government-enforcement-or-investigation` | Regulatory investigations or enforcement actions | | `fraud-or-financial-crime` | Allegations of fraud or financial misconduct | | `consumer-protection-or-class-action` | Consumer complaints or class action suits | | `data-breach-or-privacy` | Data security or privacy violations | | `bankruptcy-or-insolvency` | Financial distress proceedings | | `employment-or-workplace-disputes` | Employee-related legal issues | | `personal-injury-or-medical` | Injury or medical malpractice claims | | `intellectual-property` | Patent, trademark, or copyright disputes | | `other` | Other significant legal matters | ### [Card acceptance](#card-acceptance) Indicate whether the business currently accepts card payments for `currentlyAcceptsCards`: | Value | Description | |---------|-------------------------------------------------------------------------------------| | `true` | Business currently accepts card payments (requires uploading processing statements) | | `false` | Business does not currently accept card payments | ### [Card acceptance methods](#card-acceptance-methods) Describe the distribution of card transactions by payment channel for `cardAcceptanceMethods`. All three percentages must total 100: | Field | Description | |-------------------------|------------------------------------------------------------------------| | `inPersonPercentage` | Percentage of transactions where the card is present (POS, tap-to-pay) | | `onlinePercentage` | Percentage of transactions from online/ecommerce channels | | `mailOrPhonePercentage` | Percentage of transactions via mail order or phone order (MOTO) | **Example:** ```json { "cardAcceptanceMethods": { "inPersonPercentage": 10, "onlinePercentage": 85, "mailOrPhonePercentage": 5 } } ``` If `inPersonPercentage` is less than 80%, [`fulfillment`](#fulfillment) and [`refundPolicy`](#refund-policy-options) details are also required. ### [Fulfillment](#fulfillment) For card-not-present merchants, provide details on how goods or services are delivered. The `fulfillment` object contains two fields: | Field | Description | |-------------|-----------------------------------------------------------------------------------------------------------------------| | `method` | How the account's customers receive their purchase — see [method values](#fulfillment-methods) below | | `timeframe` | When the account's customers typically receive their purchase — see [timeframe values](#fulfillment-timeframes) below | **Example:** ```json { "fulfillment": { "method": "shipped-physical-goods", "timeframe": "within-7-days" } } ``` ### [Fulfillment methods](#fulfillment-methods) Select how the account's customers receive goods or services for `fulfillment.method`: | Value | Description | |------------------------------|----------------------------------------| | `shipped-physical-goods` | Items shipped via carrier | | `local-pickup-or-delivery` | Customer pickup or local delivery | | `digital-content` | Downloads, streaming, digital products | | `in-person-service` | Service provided at business location | | `remote-service` | Service provided remotely/virtually | | `donation` | Charitable contributions | | `bill-or-debt-payment` | Utility bills, loan payments, etc. | | `subscription-or-membership` | Recurring access or services | | `other` | Custom fulfillment method | ### [Fulfillment timeframes](#fulfillment-timeframes) Select when the account's customers typically receive their purchase for `fulfillment.timeframe`: | Value | Description | |----------------------|------------------------------------------------------| | `immediate` | Instant delivery (digital goods, in-person services) | | `within-7-days` | Standard shipping timeframe | | `within-30-days` | Extended delivery window | | `over-30-days` | Long-term delivery (custom orders, pre-orders) | | `scheduled-event` | Delivery tied to specific event date | | `recurring-schedule` | Ongoing subscription deliveries | | `pre-order` | Payment before product availability | | `other` | Custom timeframe | ### [Refund policy options](#refund-policy-options) Select the option that describes the business's refund policy for `refundPolicy`: | Value | Description | |-------------------------------|-------------------------------------------------| | `no-refunds` | All sales final | | `full-refund-within-30-days` | Standard 30-day return window | | `full-refund-extended-window` | Returns accepted beyond 30 days | | `partial-refund` | Reduced refund amount (restocking fees, etc.) | | `store-credit-only` | Refunds as store credit/gift cards only | | `prorated-refund` | Refund amount based on usage/time | | `conditional-refund` | Refunds under specific conditions only | | `event-based-policy` | Refunds tied to event cancellation/rescheduling | | `custom-policy` | Unique refund terms | --- URL: https://docs.moov.io/guides/accounts/resolution-links/ --- # Resolution links Resolution links are temporary, secure links you can send to businesses to resolve requirement errors surfaced during verification. A business account must have fulfilled initial data requirements (via the [onboarding API](/api/moov-accounts/onboarding/), [hosted onboarding](/guides/dashboard/accounts/onboarding-links/), or the [Moov Drop](/moovjs/drops/onboarding/)) before verification can begin. When Moov cannot verify certain elements of the data provided, requirement errors and document requirements may be returned. Resolution links let end users self-serve by correcting or providing the additional information needed to resolve these errors and enable the capability. ![Resolution link notice](./resolution-link.png) Requirement errors may involve [KYC-related](/guides/accounts/requirements/identity-verification/) information such as the business profile details and the identities of all business representatives. Resolution links automatically expire after 30 days, or you can manually [disable](#disable-resolution-links) them at any time. An account can only have one active resolution link at a time. ## [Check for requirement errors](#check-for-requirement-errors) Once an account has fulfilled its initial currently due requirements for a capability, Moov attempts to verify the data provided. If verification is unsuccessful, requirement errors will be returned. You can check for requirement errors in the Moov Dashboard or with the API. In the Dashboard, an action required alert displays in the account row. When you open the account's page, a list of what needs to be resolved appears under the account name. ![Alert for due items in Dashboard](../../shared-images/dashboard-resolution-alert.png) Additionally, you can use the [retrieve a capability](/api/moov-accounts/capabilities/get/) or [list capabilities](/api/moov-accounts/capabilities/list/) endpoints to get `requirements.currentlyDue`. ### [Get requirement errors](#get-requirement-errors) Log in to the Dashboard to view an account, or use the API to get requirement errors. ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/capabilities/" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2026.04.00" \ ``` ``` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ``` ```json [ { "capability": "transfers", "accountID": "string", "status": "enabled", "requirements": { "currentlyDue": [ "account.tos-acceptance" ], "errors": [ { "requirement": "account.tos-acceptance", "errorCode": "invalid-value" } ] }, "disabledReason": "string", "createdOn": "2019-08-24T14:15:22Z", "updatedOn": "2019-08-24T14:15:22Z", "disabledOn": "2019-08-24T14:15:22Z" } ] ``` ### [Create a resolution link](#create-a-resolution-link) Create a resolution link to send to the end user resolve verification exceptions. The response includes the URL and the expiration date, which is automatically set to 30 days. Once the link is sent, Moov will send the user an MFA code to access the link. [Request](#tab-854316927-0-0) [Response](#tab-854316927-0-1) ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/resolution-links" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2026.04.00" \ --data-raw '{ "recipient": { "phone": { "number": "5555555555", "countryCode": "1" } } }' ``` ``` 1 2 3 4 5 6 7 8 9 ``` ```json { "accountID": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "code": "bwebMOhZ85", "createdOn": "2026-07-01T12:00:00Z", "expiresOn": "2026-07-30T12:00:00Z", "partnerAccountID": "0d8e0d6e-e4a2-4f1b-8c3d-1b9e0f5a7c2d", "recipient": "15555555555", "url": "https://moov.link/r/bwebMOhZ85" } ``` ### [Get resolution links](#get-resolution-links) Retrieve a specific resolution link or get a list of all resolution links. [Get resolution link](#tab-891753264-0-0) [List resolution links](#tab-891753264-0-1) ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/resolution-links/{resolutionLinkCode}" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2026.04.00" \ ``` ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/resolution-links" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2026.04.00" \ ``` ### [Disable a resolution link](#disable-a-resolution-link) If needed, you can disable a resolution link. Once a link has been disabled, the recipient will no longer be able to access it. ```zsh curl -X DELETE "https://api.moov.io/accounts/{accountID}/resolution-links/{resolutionLinkCode}" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2026.04.00" \ ``` --- URL: https://docs.moov.io/guides/accounts/updating-accounts/ --- # Update accounts Learn how and when to update certain information in Moov accounts. You can update a newly created account during certain verification and capability status windows. Profile and underwriting data must also be submitted for the account before you have the ability to edit it. Certain fields like `accountType`, can't be updated once an account has been created. ## [Update windows](#update-windows) Moov uses the capability status to determine when profile and onboarding information can be edited. - `pending` status: Update or provide missing required information, or data that triggers a verification error - `in-review` & `enabled`: Update or provide missing required information When an account is `in-review` or `pending`, most submitted underwriting data is locked, and cannot be edited or removed. If you need to change locked data for a capability that is already in use, [contact support](https://support.moov.io/). Fields like `metadata`, `foreignID`, and `settings` can always be updated, regardless of capability status. ## [Capability status & editable fields](#capability-status--editable-fields) Existing data refers to fields that have already been provided and accepted. These fields are locked once the capability moves to `in-review` or `enabled`. | **Status** | **Edit existing data** | **Edit incomplete data** | **Provide missing data** | |-------------|------------------------|--------------------------|--------------------------| | `disabled` | **✓** | **✓** | **✓** | | `pending` | | **✓** | **✓** | | `in-review` | | | **✓** | | `enabled` | | | **✓** | ## [Update accounts via API](#update-accounts-via-api) To update an account via the Moov API, use the accounts `PATCH` [endpoint](/api/moov-accounts/accounts/patch/). You can also update an account with [Moov.js](/moovjs/). Some business accounts require the [additional step](/guides/accounts/account-types/#api) of setting `ownersProvided` to **true** before Moov can verify an account. The examples below update a business account with this information. [cURL](#tab-328796451-2-0) [Go SDK](#tab-328796451-2-1) [Moov.js](#tab-328796451-2-2) ```zsh curl -X PATCH "https://api.moov.io/accounts/{accountID}" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "profile": { "business": { "ownersProvided": true } }, "foreignId": "unique-correlation-id" }'\ ``` ```go mc, _ := moov.NewClient() account := moov.Account{ AccountID: "accountID", AccountType: moov.AccountType_Business, Profile: moov.Profile{ Business: &moov.Business{ OwnersProvided: true, }, }, } mc.UpdateAccount(ctx, account) ``` ```javascript const moov = Moov(token); const accountID = "accountID" const updatedAccount = { profile: { business: { ownersProvided: true, } } }; moov.accounts.update(accountID, updatedAccount); ``` ## [Update accounts via Dashboard](#update-accounts-via-dashboard) See the [Dashboard](/guides/dashboard/accounts/#edit-account-information) docs for information and instructions. If a certain field is locked and you can't update it, this is due to the verification or underwriting status of the account. ## [Disconnect accounts](#disconnect-accounts) Once you disconnect an account, the action cannot be undone. Disconnecting an account removes the ability to interact with it. You'll continue to have read-only access to the account for reporting purposes. The following actions will no longer be available: - Edit profile - Edit past transfers - Upload documents - Create new transfer - Create new payment method Disconnecting an account **does not** delete the account, its Moov wallet, or account history. You can disconnect an account through the [Dashboard](/guides/dashboard/accounts/#disconnect-accounts) or by providing the `accountID` in the path when making a request to the accounts `DEL` [endpoint](/api/moov-accounts/accounts/delete/). If you want to include disconnected accounts when using the list accounts `GET` [endpoint](/api/moov-accounts/accounts/list/), make sure you set `includeDisconnected` to **true**. --- URL: https://docs.moov.io/guides/account-tools/image-collection/ --- # Image library Upload and store images with Moov to create an image library. Link images to products in your product catalog. Use the [images API](/api/tools/images/) to upload an image up to 16MB in PNG, JPG, or WebP format. Every image will be given a unique `imageID`, which can be linked to products in your product catalog, enhancing your transfer UI. Each Moov account has a starting limit of 300 images. View the [product catalog](/guides/accounts/product-catalog/) guide for more information on how to use images with products. ## [Upload image](#upload-image) In addition to the image itself, you can supply alt-text through the `metadata` field. Duplicate images and images larger than 16MB will be rejected. [cURL](#tab-438976251-1-0) ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/images" \ -H "Authorization: Bearer {token}" \ --data '{ "image": "00010101011111000101010110", "metadata": { "altText": "Blue oat milk carton by Fancy Brand" } }'\ ``` The response will include an `imageID` which can be used to get metadata, replace, or delete an image. The `link` is the public URL to access the image. You can add a `size={width}x{height}` parameter to the public URL to resize the image. Additionally, the `publicID` is a unique identifier which is used in the URL and can also be used in public endpoints. ```json { "imageID": "bbdcb050-2e05-43cb-812a-e1296cd0c01a", "publicID": "string", "altText": "string", "link": "https://api.moov.io/images/qJRAaAwwF5hmfeAFdHjIb", "createdOn": "2019-08-24T14:15:22Z", "updatedOn": "2019-08-24T14:15:22Z" } ``` ## [Manage images](#manage-images) Once an image has been uploaded, you can retrieve a list of all image metadata, or get a singular image's metadata. You can also update an image's metadata, or replace an existing image, including its metadata. Deleting an image permanently removes it from Moov. ### [Retrieve metadata](#retrieve-metadata) Retrieve a list of all image metadata, or get metadata for a specific image. [List all image metadata](#tab-981376542-2-0) [Get image metadata](#tab-981376542-2-1) ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/images/" \ -H "Authorization: Bearer {token}" \ ``` ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/images/{imageID}" \ -H "Authorization: Bearer {token}" \ ``` ### [Update an image](#update-an-image) You can replace an image and, optionally, its metadata, or you can just update its metadata. [cURL - Replace image](#tab-721956834-3-0) [cURL - Update metadata](#tab-721956834-3-1) ```zsh curl -X PUT "https://api.moov.io/accounts/{accountID}/images/{imageID}" \ -H "Authorization: Bearer {token}" \ --data '{ "image": "00010101011111001111000101010", "metadata": { "altText": "Red soy milk carton by Fancy Brand" } }'\ ``` ```zsh curl -X PUT "https://api.moov.io/accounts/{accountID}/images/{imageID}/metadata" \ -H "Authorization: Bearer {token}" \ --data '{ "metadata": { "altText": "New! Updated recipe, blue oat milk by Fancy Brand" } }'\ ``` ### [Delete an image](#delete-an-image) Deleting an image permanently removes it from your collection stored with Moov. [cURL](#tab-175638492-4-0) ```zsh curl -X DELETE "https://api.moov.io/accounts/{accountID}/images/{imageID}" \ -H "Authorization: Bearer {token}" \ ``` --- URL: https://docs.moov.io/guides/account-tools/ --- # Account tools Use account tools to enhance the merchant experience. Allow end users to connect with Moov directly for support and set up a product catalog to enhance the merchant experience. With Moov's account tools, you can enhance the merchant and end user experience. Use our support API to set up a solution to send support tickets for connected accounts directly to Moov. Moov will work with merchants and end users to solve issues, while you'll still have viewable access to the support messages. The products and images APIs lets you create a product catalog to map directly to transfers and payment link as line items. Products can be customized with images, size and color options, as well as price modifiers. --- URL: https://docs.moov.io/guides/account-tools/invoices/ --- # Invoices Generate an invoice to send to customers - request payments, track invoice status, and get paid all from one place. Invoices are built directly into Moov's platform, so you can send professional, branded invoices to your customers and accept payments without relying on third‑party tools. With invoicing you can: - Create detailed line items - Automatically generate secure payment links - Send directly to customers via email - Accept one-time payments via bank transfer or card - Manually mark invoices as paid for off-platform payments When using the [invoice API](/api/v2026.04.00/money-movement/invoices/), provide the `customerAccountID` in the request to create an invoice. When a customer pays an invoice, funds are collected and deposited directly into the merchant's Moov wallet. To create an invoice, use the `POST` create invoice [endpoint](/api/v2026.04.00/money-movement/invoices/post/). To send an invoice, use the `PATCH` update invoice [endpoint](/api/v2026.04.00/money-movement/invoices/patch/) and set the status to `unpaid`. ## [Invoice details](#invoice-details) In addition to amount due, an invoice contains the following details: | Component | Description | |----------------|-----------------------------------------------------------------------------------------------------| | Invoice number | Automatically generated and sequential per account, for example, **INV‑1001**. | | Invoice date | The date the service or sale occurred. This can differ from when the invoice is sent. | | Due date | When the payment is due to the merchant. | | Description | Optional notes shown to the customer, for example, job numbers or description of services provided. | ### [Line items](#line-items) Each invoice includes one or more line items that describe what's being charged. Line items can be products from the account’s [product catalog](/guides/account-tools/product-catalog/), or free-from line items that support custom names, prices, and quantities. When you use a `productID`, Moov attaches the associated product image from your catalog to the line item. You must still specify the `basePrice` for the line item, as the price from the product catalog is not used. You can also use the `productID` for your own reporting and tracking. ## [Invoice status](#invoice-status) An invoice can be in any of the following stages: `draft`, `unpaid`, `payment-pending`, `paid`, `overdue`, or `canceled`. When an invoice is created but not sent, it becomes a draft. While in draft status, all fields in the invoice can be edited. An invoice must be explicitly sent to trigger the payment link and email notification. Once the invoice is sent, it is marked as unpaid. Upon successful payment, a receipt will be sent to the customer and the merchant will be notified of payment via email. Additionally, a webhook notification is sent. A failed payment will result in the invoice being re-sent to the payer via the same payment link to retry. The original failed payment is logged and shown to the payer in the invoice and the merchant is notified of the failed payment via email. If an invoice is not paid by the due date and becomes overdue, Moov will notify the merchant via email. If an invoice is canceled, the payment link will be disabled and will throw an error if interacted with: `This invoice has already been paid or is no longer valid.` ## [Payment links & transfer status](#payment-links--transfer-status) When an invoice is sent, Moov automatically creates a secure payment link scoped to that invoice and customer. The payment link is a unique, **single-use payment link** which displays: - Your business name and logo - The [invoice details](#invoice-details) - Total amount due A transfer is created for record keeping. The `transferID` can be found in `invoicePayments.transfer` within the [create an invoice](/api/v2026.04.00/money-movement/invoices/post/) response. The table below shows the mapping of invoice status to payment link and transfer status. | Invoice status | Payment link status | Transfer status | |-------------------|---------------------|-----------------| | `draft` | N/A | N/A | | `unpaid` | `active` | N/A | | `payment-pending` | `disabled` | `pending` | | `paid` | `disabled` | `completed` | | `overdue` | `active` | N/A | | `canceled` | `disabled` | N/A | ## [Email notifications](#email-notifications) Invoices are attached to an email in PDF format and are sent in a variety of scenarios. Moov sends an email to the payer when the invoice status is updated to one of the following: - Unpaid - Paid (receipt) - Overdue - Payment failed - Canceled Additionally, an email is sent if the transaction has been refunded. Moov sends an email to the merchant when an invoice status is updated to paid, or if it's manually marked as paid. Moov also notifies merchants if the invoice is overdue, or the payment transaction is disputed. If a logo has been added to the merchant's settings, the logo will be automatically added to the email. Below is an example of an email someone will receive for a payment request. ![Invoice email](../images/invoice_due_email.png) ## [Create and manage invoices](#create-and-manage-invoices) Follow the steps below to create and manage invoices via the [invoice API](/api/v2026.04.00/money-movement/invoices/). Most of the endpoints in the invoice API will require you to pass the `invoiceID` which is returned in the [create an invoice](/api/v2026.04.00/money-movement/invoices/post/) response. ### [Create invoice](#create-invoice) Use the `POST` create invoice [endpoint](/api/v2026.04.00/money-movement/invoices/post/) to create an invoice. You'll need to send the `customerAccountID` in the request body as well as create at least one line item. ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/invoices" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2026.04.00" \ --data '{ "customerAccountID": "d8b40343-5784-4096-8d40-9f3b4a834066", "description": "string", "lineItems": { "items": [ { "name": "string", "basePrice": { "currency": "USD", "valueDecimal": "12.987654321" }, "quantity": 1, "options": [ { "name": "string", "quantity": 1, "priceModifier": { "currency": "USD", "valueDecimal": "12.987654321" }, "group": "string" } ], "productID": "dbb08e34-cbbb-47d7-824b-bc71f5b00e6c" } ] }, "dueDate": "2025-08-24T14:15:22Z", "invoiceDate": "2025-08-24T14:15:22Z", "taxAmount": { "currency": "USD", "valueDecimal": "12.987654321" } }'\ ``` ### [Optional: Update invoice](#optional-update-invoice) Use the `PATCH` update invoice [endpoint](/api/v2026.04.00/money-movement/invoices/patch/) to update an invoice's line items, tax amount, due date, invoice date, description, or status. Only invoices in the `draft`, `unpaid` or `overdue` status can be updated and the `dueDate` can only be updated if the invoice status is `draft`. Note that setting an invoice's status to `unpaid` finalizes the invoice and sends an email with a payment link to the customer. ```zsh curl -X PATCH "https://api.moov.io/accounts/{accountID}/invoices/{invoiceID}" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2026.04.00" \ --data '{ "description": "string", "lineItems": { "items": [ { "name": "string", "basePrice": { "currency": "USD", "valueDecimal": "13.987654321" }, "quantity": 2, "options": [ { "name": "string", "quantity": 1, "priceModifier": { "currency": "USD", "valueDecimal": "1.00" }, "group": "string" } ], "productID": "dbb08e34-cbbb-47d7-824b-bc71f5b00e6c" } ] }, "dueDate": "2025-08-24T14:15:22Z", "invoiceDate": "2025-08-24T14:15:22Z", "status": "draft", "taxAmount": { "currency": "USD", "valueDecimal": "12.987654321" } }'\ ``` ### [Send invoice](#send-invoice) To send an invoice, you'll use the same `PATCH` update invoice [endpoint](/api/v2026.04.00/money-movement/invoices/patch/) as mentioned in the previous step. To send an invoice, set the status to `unpaid`. Setting an invoice's status to `unpaid` finalizes the invoice and sends an email with a payment link to the customer. ``` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 ``` ```zsh curl -X PATCH "https://api.moov.io/accounts/{accountID}/invoices/{invoiceID}" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2026.04.00" \ --data '{ "description": "string", "lineItems": { "items": [ { "name": "string", "basePrice": { "currency": "USD", "valueDecimal": "13.987654321" }, "quantity": 1, "productID": "dbb08e34-cbbb-47d7-824b-bc71f5b00e6c" } ] }, "dueDate": "2025-08-24T14:15:22Z", "invoiceDate": "2025-08-24T14:15:22Z", "status": "unpaid", "taxAmount": { "currency": "USD", "valueDecimal": "12.987654321" } }' ``` ### [Get invoices](#get-invoices) Use the `invoiceID` to view a specific invoice, or retrieve a list of all invoices. [Get invoice](#tab-137892645-0-0) [List invoices](#tab-137892645-0-1) Use the `GET` retrieve invoice [endpoint](/api/v2026.04.00/money-movement/invoices/get/) and pass the `invoiceID`. ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/invoices/{invoiceID}" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2026.04.00" \ ``` Use the `GET` list invoices [endpoint](/api/v2026.04.00/money-movement/invoices/list/). ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/invoices" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2026.04.00" \ ``` ### [Optional: Manually mark as paid](#optional-manually-mark-as-paid) Create an external payment invoice resource and mark an invoice as paid outside of Moov's system with the payment resource [endpoint](/api/v2026.04.00/money-movement/invoices/post-payments/). ```zsh curl -X POST "/accounts/{accountID}/invoices/{invoiceID}/payments" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2026.04.00" \ --data '{ "amount": { "currency": "USD", "valueDecimal": "12.987654321" }, "description": "string", "foreignID": "d8b40343-5784-4096-8d40-9f3b4a834066", "paymentDate": "2025-08-24T14:15:22Z" }'\ ``` Note - invoices that are paid via payment link will be automatically marked as paid. ### [List payments](#list-payments) Pass the `invoiceID` to retrieve all payments made toward an invoice with the `GET` payments [endpoint](/api/v2026.04.00/money-movement/invoices/get-payments/). ```zsh curl -X GET "/accounts/{accountID}/invoices/{invoiceID}/payments" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2026.04.00" \ ``` ## [Receive funds](#receive-funds) Once the transfer completes, the invoice is marked as paid and the funds are available in the senders wallet. ### [Manually mark as paid](#manually-mark-as-paid) Invoices that are paid via payment link will be automatically marked as paid, however, you can manually mark an invoice as paid with the `POST` payment resource [endpoint](/api/v2026.04.00/money-movement/invoices/post-payments/). Manually marking an invoice as paid notifies the merchant via email, sends a receipt to the customer, and cancels the corresponding payment link. Additionally, a webhook event is sent and a `foreignID` is added to the invoice. You can only mark an invoice as paid if the status is `unpaid` or `overdue`. ```zsh curl -X POST "/accounts/{accountID}/invoices/{invoiceID}/payments" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2026.04.00" \ --data '{ "amount": { "currency": "USD", "valueDecimal": "12.987654321" }, "description": "string", "foreignID": "d8b40343-5784-4096-8d40-9f3b4a834066", "paymentDate": "2025-08-24T14:15:22Z" }'\ ``` ## [Payment failures & refunds](#payment-failures--refunds) If a payment attempt fails, the invoice will automatically return to an `unpaid` status. The original payment link remains active, allowing the customer to retry the payment using the same link. If a payment is refunded or disputed, the invoice will continue to show a `paid` status. Any refunded or disputed amounts are reflected directly on the invoice so you can see how much has been returned. [Refunds](/guides/money-movement/accept-payments/card-acceptance/reversals/) and [disputes](/guides/money-movement/accept-payments/card-acceptance/disputes/) follow Moov’s standard payment flow, meaning the refunded or disputed amount is deducted from the account’s wallet. ## [Delete an invoice](#delete-an-invoice) In a scenario where an invoice was accidentally or mistakenly created, you can delete it using the delete invoice [endpoint](/api/v2026.04.00/money-movement/invoices/delete/). Deleted invoices will be hidden from results lists by default, but can still be retrieved through the get invoice [endpoint](/api/v2026.04.00/money-movement/invoices/get/). If you need to void an invoice that was already sent or recorded, cancel it instead by updating its status to `canceled` with the update invoice [endpoint](/api/v2026.04.00/money-movement/invoices/patch/). Only invoices in a `draft` status can be deleted. ## [Webhooks](#webhooks) Subscribe to the following [webhook events](/guides/webhooks/webhook-events/#invoices), which will provide you with relevant invoice updates: - `invoice.created` notifies you when an invoice was successfully created - `invoice.updated` notifies you when an invoice was updated --- URL: https://docs.moov.io/guides/account-tools/product-catalog/ --- # Product catalog Build a product catalog to use across transfers and payment links. Use the [product API](/api/tools/products/) to create a product catalog for transfers and payment links. For each product, you can specify an image, title, description, and base price. You can also set additional option groups like size and color, each with their own images and additional price modifiers. For example, a cafe has a product catalog that contains each of the drinks on their menu. Each drink product has an option group set up for alternative milk choices which adds a price modifier to the overall cost. ## [Create a product](#create-a-product) To create a new product for the catalog, pass the `accountID` and specify a title and base price. Additionally, you can specify a description, an image, and option groups. The example below creates a lunch special with an option group that has price modifications for alternative milks. You can [upload and store](#upload-and-store-images) images with Moov. [cURL](#tab-738541692-1-0) ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/products" \ -H "Authorization: Bearer {token}" \ --data '{ "basePrice": { "currency": "USD", "valueDecimal": "14.95" }, "title": "Monday lunch special 1", "description": "Sandwich, chips, latte", "images": [ { "imageID": "bbdcb050-2e05-43cb-812a-e1296cd0c01a" } ], "optionGroups": [ { "description": "Alternative milk options", "name": "Milk options", "options": [ { "description": "Fancy brand oat milk", "images": [ { "imageID": "bbdcb050-2e05-43cb-812a-e1296cd0c01a" } ], "name": "Oat milk", "priceModifier": { "currency": "USD", "valueDecimal": "1.00" } }, { "description": "Fancy brand almond milk", "images": [ { "imageID": "bbdcb050-2e05-43cb-812a-e1296cd0c01b" } ], "name": "Almond milk", "priceModifier": { "currency": "USD", "valueDecimal": "1.00" } } ] } ] }'\ ``` If you want to use a product you've created, you'll need to use the [product API](/api/tools/products/) to retrieve product data and map it to `lineItems` when creating transfers and payment links. You can, however, create freeform line items when initiating a transfer or payment link. ## [Manage products](#manage-products) Once a product catalog has been created, you can retrieve, update, and disable products. ### [List products](#list-products) You can list all active products, or retrieve a single active or disabled product. [cURL - Get active product list](#tab-671394852-2-0) [cURL - Get a product](#tab-671394852-2-1) This endpoint will only return active products. ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/products" \ -H "Authorization: Bearer {token}" \ ``` This endpoint will retrieve an active or disabled product. ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/products/{productID}" \ -H "Authorization: Bearer {token}" \ ``` ### [Update a product](#update-a-product) Every part of a product and its options can be updated. Updating a product initiates a complete replacement of the product model, so while only the title and base price are required, any omitted fields will be removed from the model if not included in the update request. ```zsh curl -X PUT "https://api.moov.io/accounts/{accountID}/products/{productID}" \ -H "Authorization: Bearer {token}" \ --data '{ "basePrice": { "currency": "USD", "valueDecimal": "15.05" }, "title": "Monday lunch special 1", "description": "Sandwich, chips, latte", "images": [ { "imageID": "bbdcb050-2e05-43cb-812a-e1296cd0c01a" } ], "optionGroups": [ { "description": "Alternative milk options", "name": "Milk options", "options": [ { "description": "Fancy brand soy milk", "images": [ { "imageID": "bbdcb050-2e05-43cb-812a-e1296cd0c01a" } ], "name": "Oat milk", "priceModifier": { "currency": "USD", "valueDecimal": "1.05" } }, { "description": "Fancy brand coffee milk", "images": [ { "imageID": "bbdcb050-2e05-43cb-812a-e1296cd0c01b" } ], "name": "Almond milk", "priceModifier": { "currency": "USD", "valueDecimal": "1.05" } } ] } ] }'\ ``` ### [Disable a product](#disable-a-product) A disabled product remains in the system for historical and reporting purposes. To disable a product, pass the `accountID` and `productID`. [cURL](#tab-469853217-4-0) ```zsh curl -X DELETE "https://api.moov.io/accounts/{accountID}/products/{productID}" \ -H "Authorization: Bearer {token}" \ ``` ## [Upload and store images](#upload-and-store-images) Use the [images API](/api/tools/images/) to upload a PNG, JPG, or WebP image. You can supply alt-text through the `metadata` field. Duplicate images and images larger than 16MB will be rejected. When you upload an image, you'll receive a `imageID`, which can be used to point to the image when you create or update a product. [cURL](#tab-241986753-5-0) ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/images" \ -H "Authorization: Bearer {token}" \ --data '{ "image": "00010101011111000101010110", "metadata": { "altText": "Blue oat milk carton by Fancy Brand" } }'\ ``` View the [images](/guides/accounts/image-collection) guide for more information. --- URL: https://docs.moov.io/guides/account-tools/support-tickets/ --- # Support tickets You can create tickets for customers via Moov's API, or customers can directly access support when they are signed in to Moov's Dashboard. Customers can access Moov support two ways: through an integration built with our [support ticket API](/api/moov-accounts/support/) or, if users are signed in to the Dashboard, they can open an issue through the Dashboard support widget. Note: Only merchants who were onboarded via [hosted onboarding](/guides/accounts/hosted-onboarding/) have access to the Dashboard. When a support ticket is opened, it creates an issue tied to the Moov account that requests it. You are able to view and track all issues for your connected accounts through the Dashboard. Note, only production accounts will be able to access customer support. This guide details the API integration. ### [Create a new issue](#create-a-new-issue) You can use the `POST` support ticket [endpoint](/api/moov-accounts/support/create/) to allow a customer to send Moov a titled message along with their contact info. ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/tickets" \ -H "Authorization: Bearer {token}" \ --data '{ "body": "Message body", "title": "Message title", "contact": { "email": "melany.roberts@yahoo.com", "name": "Melany Roberts" }'\ ``` ### [Retrieve a support ticket](#retrieve-a-support-ticket) Once the issue has been created, you can retrieve the issue with the `GET` support ticket [endpoint](/api/moov-accounts/support/get/). ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/tickets/{ticketID}" \ -H "Authorization: Bearer {token}" \ ``` The response will include the original support message as well as other relevant data. ```json { "ticketID": "string", "number": 1, "title": "string", "contact": { "email": "melany.roberts@yahoo.com", "name": "Melany Roberts" }, "status": "new", "createdOn": "2025-08-24T14:15:22Z", "updatedOn": "2025-08-25T11:00:00Z", "latestMessageOn": "2025-08-25T11:00:00Z" } ``` ### [List support ticket messages](#list-support-ticket-messages) You can retrieve the messages between the customer and Moov support using the list support ticket messages [endpoint](/api/moov-accounts/support/get-messages/). ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/tickets/{ticketID}/messages" \ -H "Authorization: Bearer {token}" \ ``` You'll receive a response with all messages associated with the support ticket. ```json [ { "author": "Melany Roberts", "body": "First message", "sentOn": "2025-08-24T14:15:22Z" }, { "author": "Melany Roberts", "body": "Follow up message", "sentOn": "2025-08-25T11:00:00Z" } ] ``` ### [Update support ticket](#update-support-ticket) You can update the support ticket's status to `closed` when the issue has been resolved using the `PATCH` support ticket [endpoint](/api/moov-accounts/support/update/). ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/tickets/{ticketID}" \ -H "Authorization: Bearer {token}" \ --data '{ "status": "closed" }'\ ``` --- URL: https://docs.moov.io/guides/billing/facilitator-fees/ --- # Facilitator fees (legacy billing) Facilitator fees are no longer generally available and require Moov's approval before use. If you have a use case that does not fit our regular fee plan model, please [contact us](https://moov.io/contact/). Under this structure, Moov charges your platform a processing fee for each successful payment, which you can pass on to your customers on a per-transfer basis. Failed transfers and additional items that are not supported in this flow are invoiced to your account on a monthly basis. When you set a facilitator fee, the fee amount is deducted from the transfer, so the destination receives the net amount. Your wallet is credited with the fee once the transfer completes. No fees are incurred if a transfer fails. Moov supports two fee structures: - **Total**: A flat percentage fee charged to the destination, for example, 4.00% per transfer - **Markup**: An amount added on top of Moov's fee, for example, Interchange + 1.90% & $0.10 When creating transfers, specify your fee using either `total`/`totalDecimal` or `markup`/`markupDecimal`. The decimal versions support up to nine decimal places. Only one of `total` or `totalDecimal`, or `markup` or `markupDecimal` can be used. ## [Guidelines](#guidelines) Below is a summary of general guidelines for facilitator fees: - To pass through exact processing costs with no markup, set `markup` to `0` - Anything above your cost must be calculated in your system and the markup must be sent to Moov as a dollar amount in the transfer - Your fee cannot exceed the maximum limits: - For **total** fees: Must be less than the transfer amount - For **markup** fees: Depends on transfer type: - `card-acquiring`: Total (markup + Moov fees + estimated interchange) must be less than transfer amount - `rtp` or `push-to-card`: Total (markup + Moov fees) must be less than transfer amount - If no facilitator fee is specified, your wallet is debited to cover your processing fees ## [Charges & reconciliation](#charges--reconciliation) Card payments include Moov fees with interchange and other costs finalized at completion. Fee breakdowns appear in `moovFeeDetails` on each transfer: - `interchange`: Determined at the time of settlement and charged upon completion for Visa, Mastercard, and Discover - `discount`: Determined at the time of settlement and charged upon completion for American Express - `cardScheme`: Network fees charged at completion - `moovProcessing`: Your agreed-upon processing rate with Moov Your platform receives the facilitator fee and is debited the `moovProcessing` fee, visible in the `facilitator-fee` transaction in your wallet. --- URL: https://docs.moov.io/guides/billing/ --- # Billing Moov supports flexible fee structures based on your needs and processing flows. Key components in the Moov billing structure include: - **Fee plans**: allows you to monetize payment processing costs by passing them on to your Merchants. Each Merchant can have their own fee structure based on their payment volume and needs - **Merchant fees (your revenue)**: fees you collect from your Merchants under your own pricing model. These fees are calculated and assessed based on the fee plans assigned to your Merchant accounts - **Partner costs**: fees charged to you or processing costs based on your Moov agreement (Schedule A) - **Partner residuals (if applicable)**: if you have a revenue share structure, residuals are calculated using Merchant fee revenue and your Partner costs and distributed after each billing cycle Use the guides in this section to learn about billing, reconciliation, and residuals. --- URL: https://docs.moov.io/guides/billing/merchant-billling/ --- # Merchant billing Learn about merchant fees, reconciliation, and statements. Each merchant account must be configured with a custom fee plan during onboarding. When a billable event is triggered, the corresponding fee, calculated based on the account's fee plan, is debited from the Moov wallet. Moov provides you with monthly statements so you can reconcile your merchant processing costs. This guide will walk you through accessing and understanding merchant billing and statements. To configure and assign fee plans, see the [fee plan](/guides/billing/fee-plans/) guide. In order to pass through exact costs, [standard rounding](/guides/billing/fee-plans/#rounding) is applied on all fees with the exception of network fees (interchange, scheme fees, etc.). ## [Charges and reconciliation](#charges-and-reconciliation) Fees are assessed in real time and deducted from the account's wallet immediately after a transfer reaches its final state. For plans with monthly charges, fees are billed on the first of each month for the prior billing cycle. You can list fees for a specific merchant account and list all assessed fee transactions in a merchant's wallet. [List fees](#tab-963127548-1-0) [List assessed fee transactions](#tab-963127548-1-1) Use the list fees [endpoint](/api/moov-accounts/billing/list-fees/). ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/fees" \ -H "Authorization: Bearer {token}" \ ``` Use the `GET` wallet transaction [endpoint](/api/sources/wallets/list-transactions/). You can query by `transactionType=moov-fee`. ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/wallets/{walletID}/transactions?transactionType=moov-fee" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ ``` ### [Reconciliation](#reconciliation) Each [wallet transaction](/api/sources/wallets/get-transaction/) includes key details to help you understand the charges: - `transactionType`: Always set to `moov-fee` - `source`: Indicates the origin of the fee: `transfer`, `dispute`, or `fee` - `memo`: A human-readable description of the charge (for example, `Fee for card payment`) Moov aggregates all fees associated with the same source into a single wallet charge. For cost-plus pricing plans, this aggregated amount may include interchange, dues and assessments, and processing fees combined into one transaction. When you retrieve or list [transfers](/api/money-movement/transfers/list/), each `moov-fee` transaction response contains a `moovFees` array that references the individual fees contributing to the total charge (query parameters allow you to filter by time range or transfer ID): ```json { "moovFees": [ { "accountID": "7e4b26c2-b399-49ef-8390-50e1ea44d550", "feeIDs": [ "9d957d33-1a9a-47aa-9460-fe1a90f003dd" ], "totalAmount": { "currency": "USD", "valueDecimal": "0.1" }, "transferParty": "source" } ], } ``` Also included in the response are the `feeIDs`. You can send `feeIDs` in the body of the `POST` list fees [endpoint](/api/moov-accounts/billing/list-fees/) to retrieve a granular breakdown of each fee: ```json { "feeID": "ec7e1848-dc80-4ab0-8827-dd7fc0737b43", "accountID": "ec7e1848-dc80-4ab0-8827-dd7fc0737b43", "walletID": "ec7e1848-dc80-4ab0-8827-dd7fc0737b43", "createdOn": "2019-08-24T14:15:22Z", "feeName": "string", "amount": { "currency": "USD", "valueDecimal": "12.987654321" }, "generatedBy": { "transferID": "ec7e1848-dc80-4ab0-8827-dd7fc0737b43" } } ``` ## [Merchant statements](#merchant-statements) Moov generates monthly statements for each merchant account. Statements are made available on the first day of the following month for the previous month's activity. Merchant statements will include a summary of the following: - Fee names - Transaction processing fees for all rails - Count of instances of the fee assessed - Total fee amount assessed - Network passthrough fees - card network fees - Interchange report (cost-plus plans only) For merchants on a cost-plus fee plan, you'll also receive a detailed interchange report that breaks down charges by interchange or discount program and rate. ### [Access statements](#access-statements) Partners are responsible for delivering billing statements to their merchants. Use the list statements [endpoint](/api/moov-accounts/billing/list-statements/) to list all statements. You can filter by `billingPeriodStartDate` and `billingPeriodEndDate` to specify the time period. [Query billing period start date](#tab-756243198-2-0) ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/statements?billingPeriodStartDate=2025-06-10T23:00:00Z" \ -H "Authorization: Bearer {token}" ``` To download a specific statement in your preferred format (PDF or JSON), use the `GET` statements [endpoint](/api/moov-accounts/billing/get-statement/) with an `accept` header. [Download PDF](#tab-586247319-3-0) ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/statements/{statementID}" \ -H "Authorization: Bearer {token}" \ -H "Accept: application/pdf" ``` Statements are available in the [Dashboard](/guides/dashboard/settings/documents/#merchant-statements) and [API](/api/moov-accounts/billing/). You can subscribe to the `statement.created` [webhook](/guides/webhooks/webhook-events/#billing) to receive real-time notifications on availability. In the Dashboard, statements can be accessed by navigating **Settings > Documents** and clicking on the **Statements** tab. Statement availability via email is coming soon. --- URL: https://docs.moov.io/guides/billing/partner/ --- # Partner billing Learn about partner fees, residuals, and reconciliation. During the onboarding process, you'll enter into a partner agreement with Moov. Your buy rate is configured as a fee plan and assigned to your partner account. You can view your active partner pricing agreement using the `GET` partner pricing [endpoint](/api/moov-accounts/partner-billing/list-partner-agreements/). ## [Fees and revenue](#fees-and-revenue) You can retrieve information about fees, including partner costs and merchant-generated revenue, using the `GET` fees [endpoint](/api/moov-accounts/billing/get-fees/). Use this endpoint for partner fees by passing in your partner `accountID` and for merchant fees passing in the merchant's `accountID`. [Partner fees](#tab-926438715-2-0) [Merchant fees](#tab-926438715-2-1) List all partner fees. Partner fees include all the fees charged to you, per your buy-rate. Use your partner `accountID` in the route. To find your partner account ID, navigate to **Settings** in the side navigation. Your partner account ID is located below your account name and logo. ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/fees" \ -H "Authorization: Bearer {token}" \ ``` Response: ```json [ { "feeID": "9dae7250-d128-4dbb-bc2c-3c2e8a2fb42d", "accountID": "3dfff852-927d-47e8-822c-2fffc57ff6b9", "walletID": "0eb7d670-c252-422a-892d-002136c358e0", "createdOn": "2019-08-24T14:15:22Z", "feeName": "string", "amount": { "currency": "USD", "valueDecimal": "12.987654321" }, "generatedBy": { "transferID": "e23de6dd-5168-4e1d-894d-807fa691dc80", "cardID": "f159b73e-e9c6-4dce-9609-2274bb1f8396", "disputeID": "5720fd8c-f7a6-4c10-a19a-d345b5f89bec", "accountID": "3dfff852-927d-47e8-822c-2fffc57ff6b9", "bankAccountID": "5b03c365-bcf1-4c70-aeec-29a06f15faf2" }, "feeGroup": "string", "residualID": "8df0a983-e21b-44af-a8c4-c35403236f69" } ] ``` List all fees for a specific merchant account. Use a merchant's `accountID` in the route. To find a merchant's account ID, navigate to **Accounts** in the Dashboard and select or search for a merchant's account. Their merchant account ID is located below their name and logo. You can also find a merchant account ID using the [accounts API](/api/moov-accounts/accounts/list/). ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/fees" \ -H "Authorization: Bearer {token}" \ ``` Response: ```json [ { "feeID": "9dae7250-d128-4dbb-bc2c-3c2e8a2fb42d", "accountID": "3dfff852-927d-47e8-822c-2fffc57ff6b9", "walletID": "0eb7d670-c252-422a-892d-002136c358e0", "createdOn": "2019-08-24T14:15:22Z", "feeName": "Card decline fee", "amount": { "currency": "USD", "valueDecimal": "15.987444321" }, "generatedBy": { "transferID": "e23de6dd-5168-4e1d-894d-807fa691dc80", "cardID": "f159b73e-e9c6-4dce-9609-2274bb1f8396", "disputeID": "5720fd8c-f7a6-4c10-a19a-d345b5f89bec", "accountID": "3dfff852-927d-47e8-822c-2fffc57ff6b9", "bankAccountID": "5b03c365-bcf1-4c70-aeec-29a06f15faf2" }, "feeGroup": "string", "residualID": "8df0a983-e21b-44af-a8c4-c35403236f69" } ] ``` ## [Reconcile costs and revenue](#reconcile-costs-and-revenue) Reconcile your costs and revenue *without revenue share.* Partner processing costs are debited from your wallet in real time as the billable events occur and fees are created. Merchant fees collected are credited to your wallet in real time. To reconcile costs for a specific period, use the `GET` fees [endpoint](/api/moov-accounts/billing/get-fees/) and query by the date range. The `amount` and `feeGroup` are included in the response. You can use these fields to filter fees. ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/fees?startDateTime=2025-12-24T14:15:22Z?endDateTime=2026-02-24T14:15:22Z" \ -H "Authorization: Bearer {token}" \ ``` Response: ```json [ { "feeID": "9dae7250-d128-4dbb-bc2c-3c2e8a2fb42d", "accountID": "3dfff852-927d-47e8-822c-2fffc57ff6b9", "walletID": "0eb7d670-c252-422a-892d-002136c358e0", "createdOn": "2026-01-24T14:15:22Z", "feeName": "string", "amount": { "currency": "USD", "valueDecimal": "12.987654321" }, "generatedBy": { "transferID": "e23de6dd-5168-4e1d-894d-807fa691dc80", "cardID": "f159b73e-e9c6-4dce-9609-2274bb1f8396", "accountID": "3dfff852-927d-47e8-822c-2fffc57ff6b9", }, "feeGroup": "string", "residualID": "8df0a983-e21b-44af-a8c4-c35403236f69" } ] ``` ## [Reconcile revenue share residuals](#reconcile-revenue-share-residuals) While partner fees and merchant fee revenue are recorded throughout the period for reporting purposes, Moov generates a single residual settlement transaction one business day after the billing period closes with one of the following outcomes: - Positive residual: wallet is credited - Negative residual: wallet is debited The wallet transaction's `sourceID` corresponds to the `residualID`, which you can use to reconcile the settlement. ### [Calculations](#calculations) A residual represents your share of net income: `netIncome` = `merchantFees` − `partnerCost` Fee revenue is the `merchantFees` on the residual. Fee revenue can also be retrieved using the `GET` fee revenue [endpoint](/api/moov-accounts/partner-billing/list-fee-revenue/). Your `residualAmount` = `netIncome` x `revenueShare` ## [Calculate](#calculate) ### [Retrieve the residual summary](#retrieve-the-residual-summary) Use the `residualID` to retrieve the residual record with the `GET` residuals [endpoint](/api/moov-accounts/partner-billing/get-residuals/). ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/residuals/{residualID}" \ -H "Authorization: Bearer {token}" \ ``` The response provides the totals used in the calculation: ```json { "residualID": "8df0a983-e21b-44af-a8c4-c35403236f69", "partnerAccountID": "c197cd40-7745-4413-8f3b-ec962d1b5225", "periodStart": "2019-08-24T14:15:22Z", "periodEnd": "2019-08-24T14:15:22Z", "merchantFees": { "currency": "USD", "valueDecimal": "12.987654321" }, "partnerCost": { "currency": "USD", "valueDecimal": "12.987654321" }, "netIncome": { "currency": "USD", "valueDecimal": "12.987654321" }, "revenueShare": "2.25", "residualAmount": { "currency": "USD", "valueDecimal": "12.987654321" }, "moovShare": { "currency": "USD", "valueDecimal": "12.987654321" }, "createdOn": "2019-08-24T14:15:22Z" } ``` ### [Reconcile fee revenue](#reconcile-fee-revenue) To view the merchant fee revenue entries included in the residual calculation, use your partner `accountID` with the `GET` fee revenues [endpoint](/api/moov-accounts/partner-billing/list-fee-revenue/) and query the `residualID`. ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/fee-revenue?residualID={residualID}" \ -H "Authorization: Bearer {token}" \ ``` This returns all fee revenue items applied to the residual. Optionally, you can group results by `feeGroup` to review the revenue breakdown. The total should match `merchantFees` from [step one](#calculate). ```json [ { "feeID": "9dae7250-d128-4dbb-bc2c-3c2e8a2fb42d", "accountID": "3dfff852-927d-47e8-822c-2fffc57ff6b9", "walletID": "0eb7d670-c252-422a-892d-002136c358e0", "createdOn": "2019-08-24T14:15:22Z", "feeName": "string", "amount": { "currency": "USD", "valueDecimal": "12.987654321" }, "generatedBy": { "transferID": "e23de6dd-5168-4e1d-894d-807fa691dc80", "cardID": "f159b73e-e9c6-4dce-9609-2274bb1f8396", "accountID": "3dfff852-927d-47e8-822c-2fffc57ff6b9", }, "feeGroup": "string", "residualID": "8df0a983-e21b-44af-a8c4-c35403236f69" } ] ``` ### [Reconcile partner costs](#reconcile-partner-costs) To view the partner fees included in the residual calculation, use your partner accountID with the `GET` fees [endpoint](/api/moov-accounts/billing/get-fees/) and query the `residualID`. ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/fees?residualID={residualID}" \ -H "Authorization: Bearer {token}" \ ``` This returns all partner cost entries applied to the residual. You may optionally group results by `feeGroup` to review the cost breakdown. The total should match `partnerCosts` from [step one](#calculate). ```json [ { "feeID": "9dae7250-d128-4dbb-bc2c-3c2e8a2fb42d", "accountID": "3dfff852-927d-47e8-822c-2fffc57ff6b9", "walletID": "0eb7d670-c252-422a-892d-002136c358e0", "createdOn": "2019-08-24T14:15:22Z", "feeName": "string", "amount": { "currency": "USD", "valueDecimal": "12.987654321" }, "generatedBy": { "transferID": "e23de6dd-5168-4e1d-894d-807fa691dc80", "cardID": "f159b73e-e9c6-4dce-9609-2274bb1f8396", "accountID": "3dfff852-927d-47e8-822c-2fffc57ff6b9", }, "feeGroup": "string", "residualID": "8df0a983-e21b-44af-a8c4-c35403236f69" } ] ``` ### [Confirm result match](#confirm-result-match) Look at the `residualAmount` from [step one](#calculate) and confirm the calculations and the `residualAmount` match. ## [Partner statements](#partner-statements) Moov generates monthly statements for each partner account. Statements are made available on the first day of the following month for the previous month's activity. Partner statements will include a summary of the following: - Merchant fees collected for each fee category - Partner fees assessed for each fee category - Net income for each fee category - Residual payment (for revenue-share partners) - Monthly partner platform fees (if applicable) - Interchange report Use the `GET` list statements [endpoint](/api/moov-accounts/billing/list-statements/) to list all statements. You can filter by `billingPeriodStartDate` and `billingPeriodEndDate` to specify the time period. To download a specific statement in your preferred format (PDF or JSON), use the `GET` statements [endpoint](/api/moov-accounts/billing/get-statement/) with an `accept` header. Statements are available in the [Dashboard](/guides/dashboard/settings/documents/#merchant-statements) and [API](/api/moov-accounts/billing/). You can subscribe to the `statement.created` [webhook](/guides/webhooks/webhook-events/#billing) to receive real-time notifications on availability. ### [Access statements](#access-statements) Use the list statements [endpoint](/api/moov-accounts/billing/list-statements/) to list all statements. You can filter by `billingPeriodStartDate` and `billingPeriodEndDate` to specify the time period. [Query billing period start date](#tab-381749625-5-0) ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/statements?billingPeriodStartDate=2025-06-10T23:00:00Z" \ -H "Authorization: Bearer {token}" ``` To download a specific statement in your preferred format (PDF or JSON), use the `GET` statements [endpoint](/api/moov-accounts/billing/get-statement/) with an `accept` header. [Download PDF](#tab-526813479-6-0) ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/statements/{statementID}" \ -H "Authorization: Bearer {token}" \ -H "Accept: application/pdf" ``` In the Dashboard, statements can be accessed by navigating **Settings > Documents** and clicking on the **Statements** tab. Statement availability via email is coming soon. --- URL: https://docs.moov.io/guides/billing/plan-options/ --- # Fee plans Fee plans define how you bill merchants on the Moov platform, allowing you to recover underlying processing costs, apply consistent pricing, and monetize payments. Choose a pricing model, which determines how fees are structured and presented. Within your chosen model, fees are assessed when specific billable events occur. Clearly defined fee assessments and transparent pricing during the merchant onboarding process helps build sustainable revenue while giving merchants confidence in how they are billed. ## [Pricing models](#pricing-models) Fee plans can be assigned to a single merchant or reused across many merchants. Moov supports two pricing models: - **Flat rate pricing** - **Interchange cost-plus pricing** Both models offer the same processing capabilities and reliability. The difference is how fees are structured and presented. Each fee plan defines the fee type and the amount charged when a billable event occurs. ### [Flat rate pricing](#flat-rate-pricing) Flat rate pricing offers a simplified and predictable pricing structure by consolidating processing costs into a single rate. Flat rate pricing is well suited for: - Businesses with lower transaction volumes - Businesses that prioritize predictable fees over cost optimization - Merchants who prefer simple pricing with minimal fee breakdowns ### [Interchange cost-plus pricing](#interchange-cost-plus-pricing) Interchange cost-plus pricing provides an itemized fee structure that passes through card network fees and interchange—while allowing you to apply a markup for additional processing costs. This model gives merchants greater visibility into their true processing costs. Interchange cost-plus pricing is ideal for: - Businesses with higher transaction volumes - Merchants focused on minimizing processing costs - Businesses that value detailed fee transparency - Merchants who want to optimize payment strategies using fee-level insights ## [Billable events](#billable-events) A billable event is an action on Moov's platform that triggers a fee assessment. The fees that are charged to your customers are determined by their fee plan agreement. Fees are applied whenever the billable events occur and match the configured conditions. Multiple fee conditions can apply to the same event, and all matching rules are assessed. Supported billable events include: - Transaction volume such as ACH, RTP, Push & Pull transaction volume, and card settlement & authorizations - Exceptions and services including ACH returns and notices of change, disputes and value added card services - Recurring monthly account fees such as wallet fees and payment acceptance fees Full list of billable events: Billable event Description Fee condition ACH volume Individual ACH debit and credit transactions originated on the platform. `ach-credit-same-day` `ach-credit-standard` `ach-debit-collect` `ach-debit-fund` ACH return NOC ACH exceptions, including returns and notices of change (NOC). `unauthorized` `authorized` `noc` RTP volume Completed, successful Real-Time Payments (RTP) disbursement transfers. Push volume Push-to-card disbursement transfers. `approval` `decline` Pull volume Pull-from-card instant funding transfers, including sales, refunds, and declines. `approval` `decline` `refund` Card settled volume Completed, successful card acquiring payment transfers. `cardBrand` `cardType` Card auth volume Card acquiring payment authorizations, regardless of outcome, including sales, refunds, and voids. `decline` `refund` `void` Dispute count Initiated or received dispute. Card verification count Verifying a cardholder’s account details when linking a card. Card update count Details of a card on file are updated through Moov's card account updater service. Instant verification count Instant micro-deposit verification. Wallet fee Charged monthly per merchant for maintaining access to the platform. Payment acceptance fee Charged monthly per merchant with any of the `collect-funds` and/or `send-funds` capabilities. PCI fee A monthly maintenance fee for PCI compliance and monitoring all merchants. ## [Create and assign fee plans](#create-and-assign-fee-plans) Moov recommends creating accounts and assigning fee plans during onboarding, either through the Dashboard or the API. Using the onboarding flow ensures merchants are presented with both the applicable [terms of service](/guides/accounts/requirements/platform-agreement/) and the selected fee plan, and are able to review and accept them as part of account creation. For new merchants, fee plans are assigned as part of onboarding. When assigning a fee plan to a merchant, you can choose between the pricing models outlined above: - [Standard flat rate plans](#flat-rate-pricing) - [Interchange cost-plus plans](#interchange-cost-plus-pricing) Fee plans are configured by Moov. If you need to create a new fee plan or modify an existing plan (for example, to support a new pricing structure or business model), contact [Moov support](https://support.moov.io/). Once created, fee plans can be assigned during merchant onboarding though the [Dashboard](/guides/dashboard/accounts/onboarding-links/) or via the [API](/api/moov-accounts/onboarding/). You can preview each plan's pricing disclosure in the Dashboard before assigning it. Existing accounts cannot currently be assigned a fee plan directly in the Dashboard. To assign or update a fee plan for an existing account, use the API or contact [Moov support](https://support.moov.io/). ### [Hosted onboarding in the Dashboard](#hosted-onboarding-in-the-dashboard) In the Dashboard, you can create a hosted onboarding link to set up a merchant account. During this process, you'll be prompted to select the following: - Account type - Capabilities - Pricing plan Under **Pricing**, select either a standard flat rate plan or an interchange cost-plus plan. See the [Dashboard onboarding](/guides/dashboard/accounts/onboarding-links/) guide for step-by-step instructions. ### [Onboard via API](#onboard-via-api) Create onboarding links and assign fee plans programmatically using the [onboarding API](/api/moov-accounts/onboarding/). In addition to capabilities and account details, you'll specify one or more fee plan codes. ```zsh curl --X POST "https://api.moov.io/onboarding-invites" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "scopes": [ "accounts.read" ], "capabilities": [ "transfers" ], "feePlanCodes": [ "b6134307-8922-4a72-bf3c-d0297bbe8a35" ], "prefill": { "mode": "production", "accountType": "individual", "termsOfService": { "token": "UUID" } } }' ``` You can also prefill merchant information such as account type, name, and address. For more details, see the [hosted onboarding](/guides/accounts/hosted-onboarding/) guide. To view a merchant's current fee plan agreement either navigate to **Accounts > Pricing** in the Dashboard, or use the `GET` fee agreements [endpoint](/api/moov-accounts/billing/list-agreements/). If you need to update a pricing model, such as increasing fees, changing billing frequency, or modifying plan structure, contact [Moov support](https://support.moov.io/). ## [Pricing disclosures](#pricing-disclosures) You are responsible for merchant-facing communications regarding pricing. Any changes or updates to a fee plan must be communicated to and accepted by merchants. If you use Moov's [hosted onboarding](/guides/accounts/hosted-onboarding/) process, Moov presents the pricing disclosure with the onboarding link. The disclosure lists the rates in the plan you selected. All fee plans must be accepted by the merchant before processing. Any changes to existing fee plans must go through a Moov representative, and must be communicated and accepted by merchants before they can be implemented. You can preview detailed pricing disclosures for both plan types in the [Dashboard](/guides/dashboard/accounts/onboarding-links/#pricing-plans--disclosure). ## [Resources](#resources) To create accounts and assign fee plans, use the following resources: - [Onboarding links](/guides/dashboard/accounts/onboarding-links/) in the Dashboard (suggested) - [Hosted onboarding](/guides/accounts/hosted-onboarding/) API overview - Onboarding [API](/api/moov-accounts/onboarding/) - Merchant billing [API](/api/moov-accounts/billing/) - Partner billing [API](/api/moov-accounts/partner-billing/) --- URL: https://docs.moov.io/guides/dashboard/accounts/all-accounts/ --- # All accounts View account information and manage accounts you've created. When you enter an account's page, you have the ability to view and manage information, files, and data. ## [Create accounts](#create-accounts) You can create a new account by clicking the `New account` button. Select `Onboarding link` to use Moov's [hosted onboarding](/guides/dashboard/accounts/onboarding-links/) process. You also have the option of manually creating an account. ![Create accounts in the Dashboard](../images/create-accounts.png) Sole proprietors must be created via the business profile with **Business type > Sole proprietorship**. ### [Underwriting](#underwriting) When creating a new account in the Dashboard, you can submit the required underwriting information as a part of the process. Check the [underwriting](/guides/accounts/requirements/underwriting/#underwriting-statuses) guide to view the various underwriting statuses. ## [Filter accounts](#filter-accounts) You can filter accounts by capability and/or capability status. Combine the two filters to view a variety of account list combinations, such as all accounts with the send funds capability enabled. You can also filter by accounts that require action. If you see an `!` indicator in an account row, you can click on the indicator to find details about what action is needed, such as missing documents. You can also open the filter menu to filter all accounts by `Action needed`. ## [Account view](#account-view) Click into an account to see details. On the **Overview** tab, you'll see all the data you've collected about the legal entity, its transfer activity, and its available payment methods. This is also where you can view information about business representatives for a business account. We require all business accounts to have business representatives on file, including at least one control officer. For certain business types, we need information on everyone who owns 25% or more of the company. See our [business representatives](/guides/accounts/requirements/business-representatives/) guide for more details. ![Account overview in the Dashboard](../images/account-overview.png) You can update an account profile via the Moov Dashboard overview tab. Select the individual or business account you'd like to update and click `Edit` on the field you want to update. If a certain field is locked and you can't update it, this is due to the verification or underwriting [status](/guides/accounts/updating-accounts/#updating-account-profiles-and-transaction-data) of the account. We surface an orange banner at the top of the overview tab for accounts with errors or missing capability requirements. Click `View details` or other instructions next to any listed error to address the issue. ![Account error in the Dashboard](../images/account-error.png) ### [Wallet](#wallet) In the **Wallet** tab, you can view a wallet's balance, cash out or add funds, and view transaction details. Additionally, you can filter and search wallet transactions. ![Wallet view in Moov Dashboard](../images/account-wallet-tab.png) ### [Transfers](#transfers) Under the **Transfers** tab, you can view all transfers associated with an account. Search by transfer or group ID, or use the filters to search for transfers within a specific date range or by status. ![Transfer view in Moov Dashboard](../images/account-transfer-tab.png) ### [Capabilities](#capabilities) Under the **Capabilities** tab, you can view capability requests along with the outstanding data requirements and the status of each capability. You also have the ability to manually request or unrequest a capability. See our [capabilities](/guides/accounts/capabilities/) guide for details about each capability and its corresponding information requirements. ![Account capabilities view in Moov Dashboard](../images/account-capabilities.png) If a requested capability is `pending` due to missing information, you’ll be notified of this on the capabilities page. When you click `View missing requirements`, you’ll receive guidance on what kind of information you need to provide before the capability is enabled. ### [Documents](#documents) Under the **Documents** tab, you can find the file upload feature. File upload covers a number of use cases including but not limited to, individual identity verification and business underwriting. You may need to provide certain documents in order to enable capabilities. Below are the parameters for uploading files: - Max size: 20 MB - Max number of files per account: 50 - Acceptable file types: CSV, JPG, PDF, PNG Once a file has been uploaded, it will have a status of `pending` until Moov has reviewed the document. Depending on the requirements the document was intended to satisfy, Moov will review the file and either approve or reject the file, and its status will change to `approved` or `rejected` accordingly. Note that only team members with administrator roles can view uploaded documents. If you need to delete a document, or upload more than 50 files for an account, please [contact Moov](https://support.moov.io/). For security purposes, after a document has been uploaded, account holders can no longer view that document (only Moov admins can view uploaded files). If you need to upload documents to *your* account, navigate to **Settings > Documents** in the Dashboard. Visit the setting's [documents](/guides/dashboard/settings/documents/) guide for more information. You can also upload files with the files `POST` [endpoint](/api/moov-accounts/files/post/). ### [Settings](#settings) Under the **Settings** tab, you can view and edit contact, transfer, and metadata details. Additionally, you can: - Set [brand colors](#brand-settings) - Set up automatic sweeps/payouts - Register domains with [Apple Pay](/guides/sources/cards/apple-pay/) - [Disconnect accounts](#disconnect-accounts) ![Settings view in the Moov Dashboard](../images/account-settings-tab.png) #### [Brand settings](#brand-settings) Moov offers light and dark mode brand settings. Colors you select for light and dark modes will be used as accent colors throughout the customer's user experience, including the payment link UI. #### [Disconnect accounts](#disconnect-accounts) Once you disconnect an account, the action cannot be undone. Disconnecting an account removes the ability to interact with it. You'll continue to have read-only access to the account for reporting purposes. The following actions will no longer be available: - Edit profile - Edit past transfers - Upload documents - Create new transfer - Create new payment method Disconnecting an account **does not** delete the account, its Moov wallet, or account history. To disconnect an account, navigate to **Accounts > Settings** within the account you want to disconnect. You will see a section labeled `Disconnect Account`. Disconnected accounts will no longer appear in your list views, but you can still view them using the filter in the `Account status` section of the filters. ### [Pricing](#pricing) Under the **Pricing** tab, set up or view details of an account's fee plan. The easiest way to add a fee plan to an account is through the [hosted onboarding](/guides/dashboard/accounts/onboarding-links/) process. When adding a new account, you can create an onboarding link that will detail the fee plan you've chosen for the account. The merchant is required to view and agree to the plan before it can go into affect. View our [pricing and fee plan](/guides/fee-plans/) guides for more information. ![Pricing view in the Moov Dashboard](../../../shared-images/account-pricing-tab.png) --- URL: https://docs.moov.io/guides/dashboard/accounts/ --- # Accounts View, filter, and manage the accounts you've created. The **Accounts** section of the Dashboard offers a variety of information about the Moov accounts you're connected to. View all accounts and their transfers, filter by account type, search by name, email, or account ID. You can manage manage capabilities and associated account files, and if needed, disconnect accounts. Use the peek preview shortcut to quickly access transfer status and details. ![Accounts view in the Dashboard](./images/accounts-table-view.png) ## [Peek preview](#peek-preview) The peek preview shortcut gives you fast access to details in the Dashboard. Press the `space` key to toggle the preview on and off. You can move your cursor up and down the account list and the preview will update with the corresponding account details. The `esc` key will also dismiss the preview. Press `c` while the preview is open to copy the `accountID` to your clipboard. --- URL: https://docs.moov.io/guides/dashboard/accounts/onboarding-links/ --- # Onboarding links Create, send, and view account onboarding links in the Dashboard. Use Moov's hosted onboarding process to create business or individual accounts right in the Dashboard. Pre-fill data, then select capabilities and a pricing fee plan. Send the form directly to merchants to complete on their computer or phone. ![Onboarding link in the Dashboard](../images/onboarding-links.png) ## [Onboard form](#onboard-form) Navigate to **Accounts > Onboarding links** to create a new onboarding link or view the status of links you've sent out for completion. The onboarding form allows to create business or individual accounts. You can prefill existing customer data like names and contact info. You'll select capabilities for the account, as well as a pricing plan. You can provide an optional return URL and terms of service URL under **Advanced options**. A return URL is where you would like to send users after they've completed the form. If you need users to agree to your own terms of service, you can provide the URL in that field. If you've set up brand colors, the onboarding flow will reflect your branding when you send the link to a merchant. The merchant can finish the onboarding process on their own device. ![Merchant onboarding flow](../../../shared-images/onboarding-form.png) ### [Capabilities](#capabilities) Select a business or individual account type and choose the capabilities for the account. Capabilities allow Moov accounts to receive transfers or send money to other accounts. Each capability will have a set of [requirements](/guides/accounts/capabilities/reference/) that need to be met before it can be enabled. Capabilities allow you to accomplish the following: - Authorize debit transfers - Store funds with Moov - Send funds to another account - Collect funds from another account (business accounts only) - Provide a virtual card to a merchant (business accounts only) You can request the following capabilities depending on use case and need: - `wallet.balance` - `collect-funds.ach` - `collect-funds.card-payments` - `send-funds.ach` - `send-funds.instant-bank` - `send-funds.push-to-card` - `card-issuing` - `money-transfer.pull-from-card` - `money-transfer.push-to-card` Visit the [capabilities](/guides/accounts/capabilities/) section for details about functions and requirements. ### [Pricing plans & disclosure](#pricing-plans--disclosure) Select a standard plan, which has a $500 monthly transaction minimum, or set up a custom interchange plan. For some fees, you have the option of choosing an all-in model, or you can also assign specific fees based on fee types. Once you create a plan, you can assign it to one merchant or reuse it for many merchants. Merchants must agree to and accept the fee plan before it can go into effect. **Cost plus:** With a cost plus plan, card networks’ interchange fees and Moov’s processing markup are passed along to the merchant. Cost plus plans are beneficial for merchants with a high and varied transaction volume that prefer to have more control over fees. Fees are broken down into a more digestible and transparent format. **Flat rate:** With a flat rate plan, you can lump all the processing fees together with a flat rate customized for each merchant. Flat plans are beneficial for merchants with a low transaction volume that prefer a predictable solution over lowering cost as much as possible. When you set up a merchant with a fee plan, they will receive a pricing disclosure they need to accept. The pricing disclosure shows the rates for the following: - ACH - Card acquiring - Instant payments (RTP) - Transaction management fees - Platform fees - Network fees ![Pricing plan disclosure](../images/pricing-disclosure.png) Familiarize yourself with billable events. A billable event is an action on Moov's platform which triggers a fee assessment. Fees from billable events are assessed in real time and charged to the merchant's wallet. The debit transaction from the merchant's wallet contains the following properties. - `Transaction type`: `Moov fee` - `Source`: Can be one of `Transfer`, `Dispute`, or `Fee` - `Memo`: Describes the fee charged. For example, `Fee for card payment`. Moov will roll up fees related to the same source. For example, a card payment transfer's `Moov fee` will be the sum of all the fees that were charged for a successful card transfer. Typically, the `Moov fee` wallet transaction will be completed immediately after the source is in its final state. Billable event Description Fee condition ACH volume Individual ACH debit and credit transactions originated on the platform. `ach-credit-same-day` `ach-credit-standard` `ach-debit-collect` `ach-debit-fund` ACH return NOC ACH exceptions, including returns and notices of change (NOC). `unauthorized` `authorized` `noc` RTP volume Completed, successful Real-Time Payments (RTP) disbursement transfers. Push volume Push-to-card disbursement transfers. `approval` `decline` Pull volume Pull-from-card instant funding transfers, including sales, refunds, and declines. `approval` `decline` `refund` Card settled volume Completed, successful card acquiring payment transfers. `cardBrand` `cardType` Card auth volume Card acquiring payment authorizations, regardless of outcome, including sales, refunds, and voids. `decline` `refund` `void` Dispute count Initiated or received dispute. Card verification count Verifying a cardholder’s account details when linking a card. Card update count Details of a card on file are updated through Moov's card account updater service. Instant verification count Instant micro-deposit verification. Wallet fee Charged monthly per merchant for maintaining access to the platform. Payment acceptance fee Charged monthly per merchant with any of the `collect-funds` and/or `send-funds` capabilities. PCI fee A monthly maintenance fee for PCI compliance and monitoring all merchants. View our [pricing and fee plan](/guides/fee-plans/) guides for more information. ## [Merchant communication](#merchant-communication) When you're ready to send the link to a merchant, simply copy the link and send it via email or SMS. A merchant must accept the pricing fee plan and agree to the pricing disclosure before the plan can go into affect. You are responsible to your merchants for communication regarding pricing models. Any changes or updates to a fee plan must be communicated to and accepted by merchants. --- URL: https://docs.moov.io/guides/dashboard/accounts/resolution-links/ --- # Resolution links Use the Dashboard to send businesses temporary, secure links to resolve requirement errors surfaced during verification. During [hosted onboarding](/guides/dashboard/accounts/onboarding-links/), business accounts must fulfill initial data requirements before verification can begin. When Moov cannot verify certain elements of the data provided, such as [KYC-related](/guides/accounts/requirements/identity-verification/) information, the Dashboard will alert you to requirement errors and document requirements. Resolution links let end users self-serve by correcting or providing the additional information needed to resolve these errors and enable the capability. ## [Check for requirement errors](#check-for-requirement-errors) If a business is missing data for verification, you'll see an alert in their row on the main accounts view. Enter the account's page to view the specific requirement errors. ![Resolution link notice](../../../shared-images/dashboard-resolution-alert.png) ## [Create resolution link](#create-resolution-link) Click the **Create resolution link** and enter the email address of the recipient, or click **Use SMS** to enter their phone number instead. Once the resolution link is created, send it via your chosen method. Resolution links automatically expire after 30 days, or you can manually [disable](#view--disable-resolution-links) them at any time. An account can only have one active resolution link at a time. ## [Recipient experience](#recipient-experience) Moov sends the recipient a security code to the email address or phone number entered when you created the link. The recipient will need to enter the code to access the resolution link. ![Resolution link auth](../images/res-link-auth.png) Once the business receives the link, they'll be able to fill out any missing information or upload any missing documents. ![Resolution link notice](../images/res-link-notice.png) ## [View & disable resolution links](#view--disable-resolution-links) In the account view, you can view the resolution link to see the expiration date, or disable the resolution link. Once a link has been disabled, the recipient will no longer be able to access it. --- URL: https://docs.moov.io/guides/dashboard/developers/ --- # Developers Use the developer tab to view and manage API keys and webhooks. Navigate to the **Developers** section of the Dashboard to create and manage webhooks and API keys. Only developer and admin roles have permissions set to both view and update webhooks and API keys. See our [roles](/guides/dashboard/settings/members/#roles) guide for more information. ![Developers section of the Dashboard](../images/developer-overview.png) ## [API keys](#api-keys) The **API Keys** page will list all existing API keys. Use the **New API key** button to create a new API key or click on an existing key in the list to view or edit details. You have the ability to update API keys in the following ways: - Edit the name - Add a note - Add or remove domains - Delete the key View the [get started](/guides/dashboard/get-started/#create-a-new-api-key) guide for step by step instructions on how to set up API keys. ## [Webhooks](#webhooks) The **Webhooks** page will list all existing webhooks. Use the **New webhook** button to create a new webhook, or click on an existing webhook in the list or the **Action** button to view event types or manage details. You have the ability to update a webhook in the following ways: - Add a description - Reveal the secret - Disable or enable - Update the endpoint URL - Update events The following webhooks are available. View the main [webhooks](/guides/webhooks/) documentation for more details. | Event identifier | Description | |-----------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------| | `account.created` | A new account was created in Moov | | `account.updated` | One of the fields for an existing Moov account was updated | | `account.deleted` | An account was deleted | | `representative.created` | A representative was added to an account | | `representative.updated` | A representative was updated | | `representative.deleted` | A representative was deleted | | `capability.requested` | A capability was requested for a Moov account | | `capability.updated` | A capability was updated for a Moov account | | `bankAccount.created` | A bank account was created for a Moov account | | `bankAccount.updated` | A bank account was updated for a Moov account | | `bankAccount.deleted` | A bank account was deleted for a Moov account | | `transfer.created` | A transfer was created to send money from one account to another | | `transfer.updated` | The status of a transfer is pending, completed, failed, or reversed. Granular rail-specific updates on the source and destination also trigger this event. | | `walletTransaction.updated` | A wallet transaction's status has been changed to pending, completed, canceled, or failed | | `dispute.created` | A dispute has been created for a particular transfer. | | `paymentMethod.enabled` | A payment method for account has been enabled | | `paymentMethod.disabled` | A payment method for account has been disabled | | `balance.updated` | The balance of a Moov wallet has been updated | | `cancellation.created` | A cancellation has been created | | `cancellation.updated` | A cancellation's status has changed to pending, completed, or failed | | `refund.created` | A card payment refund has been created | | `refund.updated` | A card payment refund's status has changed to pending, completed, or failed | | `networkID.updated` | The network ID of a merchant with an issued card has been updated | --- URL: https://docs.moov.io/guides/dashboard/get-started/ --- # Sign up for Moov Sign up for a Moov account through the Dashboard to access test mode and move real money in production mode. When you create an acount with Moov, you'll get instant access to test mode where you can simulate a variety of transfer flows with sample data. To be approved for production mode, you'll need to work with Moov directly and provide the necessary onboarding documentation. ## [Create account](#create-account) Visit the [Moov Dashboard](https://dashboard.moov.io/signup) to create an account. Creating an account gives you access to test mode. If you're interested in a production account, Moov will work with you to gather the necessary data. Test mode and production each require their own API keys. Moov uses API keys to generate tokens that authenticate your API requests. If your request does not include a valid token, you will receive an error. See the next section for details. Once you've created an account, you have the option to log in to Moov using a passkey through your browser, password manager, phone or tablet, or USB security key. ![Sign in to the Moov Dashboard with passkey](../images/passkey-signin.png) ## [Create a new API key](#create-a-new-api-key) To create a new API key, navigate to **Developers** in the Dashboard. Select **API keys**, where you can create new API keys, or view and edit existing ones. Test mode and production mode each require their own API keys. Only accounts with `admin` and `developer` permissions will be able to create and view API keys. For more on permissions, see [managing teams](/guides/dashboard/managing-teams). 1. Set a name for the API key. This field is customizable so you can remember the purpose of the API key you're creating. 2. Copy your secret key and save it in a confidential, secure place. 3. Add any domains you will use for testing and production to the domain list. 4. Optional: After creating a key, you can include a note to remind yourself where the key is stored (for example, "Stored as an environment variable in the payments service"). ## [Find your API keys](#find-your-api-keys) If you need to locate your API key, you can always find it in the [Moov Dashboard](https://dashboard.moov.io/developers/api). However, if your account doesn't have `admin` or `developer` permissions, you won't have access to view or create API keys. If you're unable to find your API key, you may want to request access from an administrator on your Moov account. API keys contain a public key and a secret key. The secret key cannot be viewed in Moov after the API key is created, so we recommend immediately storing it in a safe place. If you have lost your secret key, you should delete that API key and create a new one. ## [Deactivate API keys](#deactivate-api-keys) If your API key is compromised, delete it from the list of API keys in Moov. This will immediately ensure that the key cannot be used. You can then create a new key. ## [Mode switching](#mode-switching) Switch between production and test mode in the Moov Dashboard by using the account dropdown in the upper left hand corner. ![Toggle for test account in Moov Dashboard](../../shared-images/mode-toggle.png) ### [Test mode](#test-mode) Once you have an account, you can use your test account with your test API keys to view sample data and transfer fake money. Try out the following in test mode: - Add a bank account - Initiate verification - Initiate a transfer - Initiate a return View the full Dashboard [test mode](/guides/dashboard/test-mode/) guide to see what else you can do in test mode. ### [Production mode](#production-mode) After you’ve completed your business profile and Moov has approved your production account, you can switch to production mode. Before you start using production mode, make sure to: - Have your production API key - Switch out the account ID anywhere it's hard coded - Set up new webhook URLs if you used any in test mode Read the main [production mode](/guides/get-started/production-mode/) guide for more details. --- URL: https://docs.moov.io/guides/dashboard/image-library/ --- # Image library Upload and store images in the Dashboard to create an image library. Link images to products in your product catalog. Navigate to **Image library** in the Dashboard. Images uploaded to the library must be in PNG, JPG, or WebP format, and cannot exceed 16MB. Every image will be given a unique image ID, which can be linked to products in your product catalog, enhancing your transfer UI. Each Moov account has a starting limit of 300 images. ![Image library in the Dashboard](./images/image-library-view.png) After you upload an image, you can select it to view the public URL and the image ID. Additionally, you can add alt text or append the public URL with a width and height parameter (`?size=[width]x[height]`) to scale and crop the image to a specific size. ![Edit image in the Dashboard](./images/edit-image-library.png) Delete an image by hovering over it and selecting the trash icon, or by hitting the **Delete** button inside the editing modal. --- URL: https://docs.moov.io/guides/dashboard/ --- # Dashboard The Moov Dashboard is an online portal where you can create and manage Moov accounts, transfers, and settings. The Dashboard is an online portal that allows you to manage your account and the accounts you're connected with. Use the Dashboard to view and manage brand identity, teams, capabilities, webhooks, and transfers. 📲 The onboarding links workflow let's you create accounts, choose capabilities, and select a fee plan for each merchant. Send onboarding links to merchants to provide additional information and review agreements and disclosures. 💳 Use payment links to send a URL or QR code to collect funds from cards, bank accounts, or Apple Pay. View and manage payment links right in the Dashboard. 🔔 Moov's Dashboard notification system will alert you to any issues that need resolving on your or your merchants' accounts, such as missing documents or actions required to resolve disputes. Before you dive into the Dashboard guides, make sure you familiarize yourself with the Moov [glossary](/guides/get-started/glossary/). ![Business detail setting view in Moov Dashboard](./images/dashboard-main.png) --- URL: https://docs.moov.io/guides/dashboard/invoices/ --- # Invoices Create an invoice to send to customers - request payments, track invoice status, and get paid all from the Dashboard. Navigate to **Invoices** in the Dashboard to create a new invoice. Within invoices, you'll also have access to brand settings so you can set brand colors before sending an invoice. ![Invoice Dashboard view](./images/invoice-table.png) ## [Create an invoice](#create-an-invoice) To create an invoice, search for the account you want to bill. To add line items, you can search your product catalog for existing products, or enter custom amounts to bill. You'll have the option to adjust the quantity per item once it's added to the invoice. Select an invoice date and the due date - they do not have to be the same date, and include a memo for the description if desired. Once the form is filled out, you can save the invoice as a draft, or review it to send out. ![Create invoice in the Dashboard](./images/create-invoice.png) Use the switcher to view a preview of the invoice PDF and the associated payment link. ### [Invoice numbers & details](#invoice-numbers--details) Invoice numbers are automatically generated and sequential per account. For example, the first invoice for an account will be **INV‑1** and the following will be **INV‑2** and so on. ## [Review & send](#review--send) In addition to the amount due, an invoice will have the following information: - **Invoice number:** Automatically generated and sequential per account, for example, **INV‑103** - **Invoice date:** The date the service or sale occurred - this can differ from when the invoice is sent - **Due date:** When the payment is due to the merchant - **Invoice description:** Optional notes shown to the customer, for example, job numbers or description of services provided You can send the invoice, or save it as a draft. When an invoice is sent, Moov automatically creates a secure, single-use payment link scoped to that invoice and customer. ![Review & send invoice](./images/review-invoice.png) ## [Email notifications](#email-notifications) Invoices are attached to an email in PDF format and are sent to customers in a variety of scenarios. If you have branding colors set, they will display in the email. Invoices are sent to the payer when the status is updated to one of the following: - Unpaid - Paid (receipt) - Overdue - Payment failed - Canceled - Additionally, an email is sent if the transaction has been refunded Moov also sends an email to the merchant when an invoice status updates to paid, or if it's manually marked as paid via the payment resource [endpoint](/api/v2026.04.00/money-movement/invoices/post-payments/) in the API. Moov also notifies merchants if the invoice is overdue, or the payment is disputed. Example of an invoice attached to an **unpaid** email notification: ![Invoice due email](./images/invoice-due-email.png) Example of an invoice attached to a **paid** email notification: ![Invoice receipt email](./images/invoice-receipt-email.png) ## [Manage invoices](#manage-invoices) On the main **Invoices** view, you can filter invoices by status, created on date, and due date. Once the payment link transfer completes, the invoice is marked as paid and the funds are available in the senders wallet. The table below shows the mapping of invoice status to payment link and transfer status. | Invoice status | Payment link status | Transfer status | |-------------------|---------------------|-----------------| | `draft` | N/A | N/A | | `unpaid` | `active` | N/A | | `payment-pending` | `disabled` | `pending` | | `paid` | `disabled` | `completed` | | `overdue` | `active` | N/A | | `canceled` | `disabled` | N/A | ### [Edit an invoice](#edit-an-invoice) Only invoices in the draft, unpaid, or overdue status can be updated. The due date can only be updated if the invoice is in a draft status. ## [Delete an invoice](#delete-an-invoice) An invoice in a draft status can be deleted if it was accidentally or mistakenly created. Deleted invoices will be hidden from results lists by default, but can still be retrieved through the get invoice [endpoint](/api/v2026.04.00/money-movement/invoices/get/). If you need to void an invoice that was already sent or recorded, cancel it instead by updating its status to `canceled`. ## [Payment failures & refunds](#payment-failures--refunds) If a payment attempt fails, the invoice will automatically return to an unpaid status. The original payment link remains active, allowing the customer to retry the payment using the same link. If a payment is refunded or disputed, the invoice will continue to show a paid status. Any refunded or disputed amounts are reflected directly on the invoice so you can see how much has been returned. [Refunds](/guides/money-movement/accept-payments/card-acceptance/reversals/) and [disputes](/guides/money-movement/accept-payments/card-acceptance/disputes/) follow Moov’s standard payment flow, meaning the refunded or disputed amount is deducted from the account’s wallet. --- URL: https://docs.moov.io/guides/dashboard/overview/ --- # Overview This page details the information that's available on the main overview page of the Moov Dashboard. When you log in to the Dashboard, you'll land on the the **Overview** page. This page provides useful, at-a-glance information about activity on your account. Onboarding tasks may appear at the top of the page if you have not yet completed them. ![Overview view in Moov Dashboard](../images/overview-view.png) ## [Wallet balance](#wallet-balance) The wallet balance gives you fast insight into your current balance. Within the wallet balance snapshot, there are also buttons to **Add funds** to, or **Cash out** the wallet. Click the menu expansion to find **Sweep settings** or copy relevant IDs. Use the sweep settings to set up or manage [sweeps](/guides/money-movement/wallets/sweeps/) for automated payouts. The **View transactions** link will take you to the wallet transaction overview page. ## [Metrics](#metrics) By default, the Dashboard will show you the last 30 days of activity. You can change the date range to see more or less activity. - **Total transfers:** This is a snapshot of the total number of transfers created within your account within the selected date range. The transfer count is then broken down by status. - **Transfer volume:** This is a snapshot of the total value of transfers created within the selected date range. For durations less than seven days, the volume is broken down by hour. Otherwise, the volume is broken down by day. - **New accounts:** This is a snapshot of the number of accounts that have been created within the selected date range broken down by type (individual or business). ## [Test mode](#test-mode) If you're still in test mode, the overview page will suggest actions to take, such as setting up test bank accounts and creating test transfers. --- URL: https://docs.moov.io/guides/dashboard/payment-links/ --- # Payment links Create payment links from the Dashboard. Accept or send funds from cards, bank accounts, or Apple Pay. Navigate to **Payment links** in the Dashboard. You can view your payment link history or create a new payment link. Before you send your first payment link, you have the option to set up brand colors. Click on the **Brand settings** button to set light and dark mode colors for your payment links. ![Payment link Dashboard view](./images/payment-link-view.png) ## [Create a payment](#create-a-payment) Click the **New payment link** button and choose either the **Accept payment** or **Send payout** tab to create a link. Choose the amount and provide a title and description. If you're sending a payout, you'll also need to provide a phone number or email address for the recipient. The recipient will receive a verification code to the chosen contact method. Select the payment methods you would like to allow. By default, all payment methods are selected: | Accept methods | Send methods | |----------------|---------------------| | Card payments | Push to card | | Apple Pay | RTP credit | | ACH debit | ACH credit same day | | | ACH credit standard | Then select the wallet you would like to accept or payout the funds to. Additionally, when accepting a payment, you can specify one of the following calls to action: - Pay - Subscribe - Book - Donate ## [Sharable link & QR code](#sharable-link--qr-code) After you create a payment link, you'll be presented with a sharable link and QR code that can be scanned in-person. ![Sharable link and QR code](../../shared-images/payment-link-qr.png) ## [Receipts](#receipts) When a payment link is successfully submitted, a receipt will automatically be created and sent via email using the transfer ID and the email/email accountID ID. The payment link's title is passed along in the transfer description and will appear on receipts. ![Receipt email](./images/receipt-example.png) ## [View & edit payment links](#view--edit-payment-links) When you select a payment link, you can view details, copy the link, and view the QR code. Selecting **More actions** will allow you to edit the details or delete the payment link. Only the account that creates the payment link can update the payment link, if needed. For example, if a merchant creates a payment link, only the merchant account has access to update that payment link. ## [Peek preview](#peek-preview) The peek preview shortcut gives you fast access to details in the Dashboard. Press the `space` key to toggle the preview on and off. You can move your cursor up and down the list and the preview will update with the corresponding payment link details. The `esc` key will also dismiss the preview. Press `c` while the preview is open to copy the `accountID` to your clipboard. --- URL: https://docs.moov.io/guides/dashboard/product-catalog/ --- # Product catalog Build a detailed product catalog with images, amounts, and descriptions to use across transfers and payment links. Navigate to **Products** in the Dashboard to create a product catalog for transfers and payment links. For each product, you can specify an image, title, description, and base price. You can also set additional option groups like size and color, each with their own images and additional price modifiers. ## [Create a product](#create-a-product) Click the **New product** button and fill out the information in the product modal. A product title and base price are required. A description, image, and group are optional. Images can be in PNG, JPG, or WebP format. Duplicate images and images larger than 16MB will be rejected. ![Add a product to the catalog in the Dashboard](./images/create-product.png) ## [Manage products](#manage-products) Once you've created products, they'll appear on the main product catalog view. All elements of a product can be edited. Click on a product to view, and click the **...** menu button to edit or delete the product. ![Product list in the Dashboard](./images/products-table.png) When you view or edit a product, your [image library](/guides/dashboard/image-library/) will be available. Any images you add while editing a product will also be added to your image library. ## [Payment links](#payment-links) Use the product catalog in combination with [payment links](/guides/dashboard/payment-links/). When you create a payment link you are required to either select an existing product or enter a custom amount. You can search for a specific product, or scroll through all your products. --- URL: https://docs.moov.io/guides/dashboard/settings/business-settings/ --- # Business details Use this guide to learn how to manage business details and settings. Navigate to **Business details** to find your account profile in the Dashboard. This is where you'll be able to manage your business details such as brand settings and business representatives, as well as manage transfer, Apple Pay, and sweeps settings. ![Business detail setting view in Moov Dashboard](../images/business-details.png) ## [Business details](#business-details) Business accounts have the option to include support contact information, such as an email or phone number, that can be displayed on credit card transactions in case customers need to contact a customer support team. ### [Brand settings](#brand-settings) In the **Brand settings** section of the settings, you can set light and dark mode brand colors. Brand colors you select for light and dark modes will be used as accent colors throughout the customer's user experience, including the payment link UI. ![Brand settings in Moov Dashboard](../images/brand-settings.png) ### [Representatives](#representatives) In the **Business representative** section of the settings, you can add, view, and edit representatives on your account. In order to meet federal regulations, Moov is required to collect and verify information about business representatives, who are control officers or owners of a business. Before account verification is initiated, one control officer and all owners with ≥25% ownership need to be created. To learn more about business representatives and the information we require, see our main [business representatives](/guides/accounts/requirements/business-representatives/) guide. ### [Transfer settings](#transfer-settings) You are able to view your transfer settings, such as statement descriptor and ACH company name, which is what other accounts will see as the origin of your transactions. If you need to update your account's transfer settings, you'll need to use the [accounts API](/api/moov-accounts/accounts/patch/). ### [Expected activity](#expected-activity) Moov provides an overview of the following expected activity: - Average monthly volume - Maximum transaction amount - Average transaction amount - Business description / use case ## [Apple Pay](#apple-pay) In the **Apple Pay** section, you can register your domains to start using Apple Pay. Before you can get started with Apple Pay, your website needs to follow Apple's guidelines and your server needs to be set up accordingly. - [Apple Pay website guidelines](https://developer.apple.com/apple-pay/acceptable-use-guidelines-for-websites/) - [Apple Pay server requirements](https://developer.apple.com/documentation/apple_pay_on_the_web/setting_up_your_server) - All pages that include Apple Pay must be served over HTTPS - Your domain must have a valid SSL certificate - Your server must support the Transport Layer Security (TLS) protocol version 1.2 or later, and one of the [cipher suites](https://support.apple.com/guide/security/tls-security-sec100a75d12/web) listed See our main [Apple Pay](/guides/sources/cards/apple-pay/) guide for detailed instructions and information. ## [Sweeps](#sweeps) A sweep automatically initiates daily transfers to external bank accounts on a set schedule, allowing you to maintain a daily balance if desired. Enabling sweeps will either payout funds from a wallet or pull funds to cover fees and chargebacks. When you enable sweeps, you'll select a bank account and a speed, such as `ACH same day`. By default, your daily minimum balance will be set to `$0` and your statement descriptor will be a 10-character ID. You can update your minimum balance as needed and set a customized statement descriptor for easier reference. See our main [sweeps](/guides/money-movement/wallets/sweeps/) guide for more details. --- URL: https://docs.moov.io/guides/dashboard/settings/documents/ --- # Documents Upload documents for verification purposes. Moov is required to verify your account before you can use production mode. Navigate to **Settings > Documents** to view or upload documents needed to verify your account. ![Document list in Moov Dashboard](../images/documents-table.png) ## [Upload documents](#upload-documents) Moov requires documents for a number of use cases including but not limited to, business and representative verification and underwriting. Below are the parameters for uploading files: - Max size: 10 MB - Max number of files per account: 50 - Acceptable file types: CSV, JPG, PDF, PNG Click the **New document** button to upload a document. Once a file has been uploaded, it will have a status of `Pending` until Moov has reviewed the document. Depending on the requirements the document was intended to satisfy, Moov will review the file and either approve or reject the file, and its status will change to `Approved` or `Rejected` accordingly. Once a document is uploaded, only members with administrator roles can view documents from the document list. ![Uploaded document in Moov Dashboard](../images/view-document.png) If you need to upload documents for any of your users' accounts, navigate to **Accounts** in the Dashboard, select an account, and navigate to the **Documents** tab for that account. Visit the [accounts](/guides/dashboard/accounts/all-accounts/) guide for more information. ## [Merchant statements](#merchant-statements) Click on the **Statements** tab to view merchant statements. Merchant statements for the previous month's activity will be available on the first day of the following month. Merchant statements will include a summary of the following: - Fee names - Transaction processing fees for all rails - Count of instances of the fee assessed - Total fee amount assessed - Network passthrough fees - card network fees - Interchange report (cost-plus plans only) For merchants on a cost-plus fee plan, you’ll also receive a detailed interchange report that breaks down charges by interchange or discount program and rate. ![Merchant statements in Moov Dashboard](../images/merchant-statements.png) --- URL: https://docs.moov.io/guides/dashboard/settings/ --- # Settings Learn how to manage business details in the Moov Dashboard. The **Settings** section of the Dashboard allows you to manage your account. You can view and update your business details, representatives, team members, and payment methods. Additionally, you can upload and manage documents for any account. ![Business detail setting view in Moov Dashboard](./images/business-details.png) --- URL: https://docs.moov.io/guides/dashboard/settings/members/ --- # Members Learn how to invite team members to access your account through the Moov Dashboard. Navigate to **Settings > Members** manage to invite team members to your account through the Moov Dashboard. This guide covers the different role types members can have and the permissions that can be set, as well as the guidelines for accepting an invitation. ![Manage team members view in Moov Dashboard](../images/members-overview.png) ## [Invite team members](#invite-team-members) You can use the mode switcher to choose which account you'd like to invite people to. If you are in test mode, the members you invite will have access to the test account. If you are in production mode, the members you invite will have access to the production account. If you would like some members to have access to both the test and production account, they will need to be invited to each separately. A team member can have one of the following [roles](#role-permissions). - Admin - Developer - Support - View only An invitation to join as a member remains valid for 24 hours before it expires. If a user doesn't accept their invitation within 24 hours, you'll need to re-invite them through the same process. ### [Edit members](#edit-members) You can go back and change roles, or remove team members as needed. Click on a member in the list you want to change and edit as needed. ## [Role permissions](#role-permissions) See the table below for a list of permissible actions associated with each role. | | Admin | | | | | Developer | Support | View only | |--------------------|-------|--------|------|--------|------|------------|---------|-----------| | | View | Update | View | Update | View | Update | View | Update | | Your account | | | | | | | | | | Business profile | ✓ | ✓ | ✓ | X | ✓ | X | ✓ | X | | Capabilities | ✓ | ✓ | X | X | ✓ | X | ✓ | X | | Representatives | ✓ | ✓ | ✓ | X | ✓ | X | ✓ | X | | Bank accounts | ✓ | ✓ | ✓ | X | ✓ | X | ✓ | X | | Cards | ✓ | ✓ | ✓ | X | ✓ | X | ✓ | X | | Apple Pay | ✓ | ✓ | X | X | ✓ | X | ✓ | X | | Wallet | ✓ | ✓ | ✓ | X | ✓ | X | ✓ | X | | Transfers | ✓ | ✓ | ✓ | X | ✓ | X | ✓ | X | | Members | ✓ | ✓ | ✓ | X | ✓ | X | ✓ | X | | API keys | ✓ | ✓ | ✓ | ✓ | X | X | X | X | | Webhooks | ✓ | ✓ | ✓ | ✓ | X | X | X | X | | Files | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | X | | Connected accounts | | | | | | | | | | Accounts | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | X | | Payment methods | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | X | | Cards | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | X | | Bank accounts | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | X | | Transfers | ✓ | ✓ | ✓ | ✓ | ✓ | ✓[1](#fn1) | ✓ | X | | Representatives | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | X | | Wallets | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | X | | Capabilities | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | X | 1. The support role can view or update the description associated with a transfer, but cannot initiate transfers.[↩](#ref1 "Back to footnote") --- URL: https://docs.moov.io/guides/dashboard/settings/payment-methods/ --- # Payment methods View and manage payment methods associated with your account. Navigate to **Settings > Payment methods** to view and edit payment methods connected to your account. All payment methods that have been added to an account will be displayed, along with their status. Clicking on a payment method will show additional details, such as the account holder's information, verification status, and the available payment method sources and destinations. You can also take action on an account, such as finishing verification, or removing the account. ![Payment methods in the Dashboard](../images/payment-method-overview.png) ## [Add payment method](#add-payment-method) Click **Add new** to add a new payment method. Before you start, make sure you have your account's information, such as routing and account number. View the main [payment methods](/guides/money-movement/payment-methods/) guide for more information about what capabilities are required for specific sources and destinations. ## [Wallet transactions](#wallet-transactions) The payment methods page will also display the total value of all your wallet transactions. You can also add funds, cash out, or copy wallet IDs. Click **View transactions** to enter the **Wallet** section of the Dashboard, where you'll see an itemized list of all wallet transactions. Clicking on a transaction will show additional details, such as the transaction source, destination, and ID. View the Dashboard [wallet](/guides/dashboard/wallet/) guide for more information. --- URL: https://docs.moov.io/guides/dashboard/support/ --- # Support Contact Moov's support team directly from the Dashboard. Moov partner accounts and merchants onboarded via the [hosted onboarding](/guides/dashboard/accounts/onboarding-links/) process can chat with Moov support or submit a ticket directly from the Dashboard. You can find the chat icon on the bottom right from any view within the Dashboard. Clicking on the chat icon opens up the support modal where you can start a chat with Moov's support team or open a support ticket. You also have access to an AI search query and helpful links. ## [Chat](#chat) We have actual humans ready to help both partner and merchant accounts. Open the chat and someone from Moov will be in touch shortly. ## [Tickets](#tickets) Partners and merchants can submit tickets for the following support types: - **Problem:** Technical issues, such as bugs or difficulty working with our API or Dashboard. It's most helpful to provide the steps or flow that led you to encounter the issue. - **Feedback:** Feature requests, such as improvements to existing features or brand new features. It's most helpful to provide how you would use a feature or why it's important. - **Question:** Any other question that may not fit into a problem or feedback scenario. ## [Merchant access](#merchant-access) Merchants only have direct access to the Dashboard's support UI if they were onboarded via [hosted onboarding](/guides/dashboard/accounts/onboarding-links/). To provide other merchants direct access to Moov support, use our [support API](/api/moov-accounts/support/) to build an integration within your app. By setting up an integration, you can hand off support to Moov. Within the Dashboard you have access to view messages between your merchants/connected accounts and Moov support. Additionally, you have the ability to close tickets once issues have been resolved. To view a merchant's support messages, navigate to their account in the Dashboard and click on their **Support** tab. ![Merchant support messages](../images/merchant-messages.png) --- URL: https://docs.moov.io/guides/dashboard/test-mode/ --- # Test mode in the Dashboard Familiarize yourself with our Dashboard portal without having to move real money. This guide assumes you have already created an account with test mode API keys. While test mode is optional, we strongly suggest you try it out. When you sign up for Moov, you'll receive access to a test account. To save you time, your test account is pre-populated with sample business details and accounts, and all capabilities have been automatically enabled for you to test: - [Transfers](/guides/accounts/capabilities/enablement/#transfers) - [Wallet](/guides/accounts/capabilities/enablement/#wallet) - [Send funds](/guides/accounts/capabilities/enablement/#send-funds) - [Collect funds](/guides/accounts/capabilities/enablement/#collect-funds) Use the sample data to simulate the flows you'll use once you switch over to production mode. Make sure you're in test mode by using the account switcher on the top left. ![Toggle for test account in Moov Dashboard](../../shared-images/mode-toggle.png) ## [Invite team members](#invite-team-members) While in test mode, you can [invite team members](/guides/dashboard/settings/members/) to your test account. Inviting team members to your test account *does not* enable them to use your production account. If you'd also like to invite team members to your production account, you will need to do that separately in production mode. ## [Transfers](#transfers) Transfers in test mode won't move any real money. For the timing of transfers in test mode, note that: - Wallet to wallet transfers complete almost instantly. - ACH transfers in test mode will complete in about an hour (see the [processing speed](/guides/money-movement/accept-payments/ach/ach-processing-speeds/) guide for production mode). To simulate card transfers and transfer scenarios, like disputes, use the test cards and other specific data listed in the following sections. If you would like to see how Moov handles failures in production, view the [transfer failures](/guides/money-movement/events-and-statuses/) guide. ### [Link cards](#link-cards) Test cards must be added using the [API](/api/sources/cards/create/) or [Moov Drops](/moovjs/drops/card-link/). Before you can use test cards in transfer scenarios, you will have to link them to your test account. Enter any of the test card numbers, provide any 3 numbers for the CVV (4 for American Express), and enter any future date for the expiration. You can also use any postal code to satisfy the required billing postal code field. | Card brand | Test card number | CVV | |------------------|-----------------------|---------------| | Visa | `4111 1111 1111 1111` | Any 3 numbers | | Mastercard | `5555 5555 5555 4444` | Any 3 numbers | | Discover | `6011 1111 1111 1117` | Any 3 numbers | | American Express | `3711 111111 11114` | Any 4 numbers | #### [Name verification](#name-verification) Moov uses Visa's [ANI verification](https://usa.visa.com/content/dam/VCOM/regional/na/us/support-legal/documents/account-name-inquiry-onesheet-merchant-version.pdf) as a check against the supplied holder name when linking a card. You can test the various results by entering the following combinations of correct and incorrect names in the holder name field when linking a test card with the API. *Correct name: Alex Nora Irwin* | Name entered | Individual name check | Full name check | |--------------------|--------------------------------------|-----------------| | "Alex Nora Irwin" | `match`, `match`, `match` | `match` | | "Alex Noraa Irwin" | `match`, `partialMatch`, `match` | `match` | | "Alx Nora Irwin" | `partialMatch`, `match`, `match` | `match` | | "Alex Irwin" | `match`, `notChecked`, `match` | `match` | | "Irwin" | `notChecked`, `notChecked`, `match` | `match` | | "Alex Nor Irwin" | `match`, `noMatch`, `match` | `partialMatch` | | "Axely Nora Irwin" | `noMatch`, `match`, `match` | `partialMatch` | | "A N Irwi" | `noMatch`, `noMatch`, `partialMatch` | `noMatch` | | "Alex Notwin" | `match`, `notChecked`, `noMatch` | `noMatch` | | "Alex Notwin" | `match`, `notChecked`, `noMatch` | `noMatch` | If ANI is not supported, you'll receive `unavailable` for all results. ### [Card acceptance](#card-acceptance) Test card numbers can be used to simulate card transfers: | Card brand | Test card number | CVV | |------------------|-----------------------|---------------| | Visa | `4111 1111 1111 1111` | Any 3 numbers | | Mastercard | `5555 5555 5555 4444` | Any 3 numbers | | Discover | `6011 1111 1111 1117` | Any 3 numbers | | American Express | `3711 111111 11114` | Any 4 numbers | ### [RTP](#rtp) To simulate an RTP transfer in test mode, create a transfer with `Moov Wallet` as the source payment method and `RTP Credit` as the destination. The `RTP Credit` payment method will only appear for bank accounts with routing numbers that are RTP eligible. Use `021000021` as an RTP-enabled routing number in test mode. You can also simulate various RTP failures and rejections by using these specific amounts listed below in your test mode transfers. Using these amounts will result in real time failures. Please note that these failures will result in the linked bank account entering an errored state. | Transfer amount | Failure type | |-----------------|--------------------------| | $72.03 | `AC03` / invalid-account | | $72.04 | `AC04` / account-closed | | $72.06 | `AC06` / account-blocked | ### [Push to card & pull from card](#push-to-card--pull-from-card) Use the test cards in the table below to simulate the following: - [Push to card](/guides/money-movement/send-payments/push-to-card/) transfer generating `Fast funds` payment method - [Pull from card](/guides/money-movement/accept-payments/pull-from-card/) transfer generating `Supported` payment method | Card brand | Completed transfer | Failed transfer | |------------|-----------------------|-----------------------| | Visa | `4111 1000 1000 2000` | `4111 1000 5000 7000` | | Mastercard | `5200 8282 8282 8210` | `5200 8211 1111 1114` | The expiration date can be any future date. CVV can be any 3 numbers for Visa and Mastercard. ### [ACH returns](#ach-returns) You can simulate a few ACH return scenarios during different transfer stages. To simulate a specific return type, input one of the return amounts listed below in the `Amount` modal. For example, if you want to simulate insufficient funds, enter `$55.01`. | Trigger Amount | Return Code | Description | Simulation Stage | |----------------|-------------|------------------------------------|---------------------------------| | $55.01 | `R01` | Insufficient Funds | Debit originated, not completed | | $55.02 | `R02` | Account Closed | Debit originated, not completed | | $55.03 | `R03` | No Account / Unable to Locate | Credit completed | | $55.04 | `R04` | Invalid Account Number Structure | Credit completed | | $55.07 | `R07` | Authorization Revoked by Customer | Debit completed | | $55.08 | `R08` | Payment Stopped | Debit completed | | $55.09 | `R09` | Uncollected Funds | Debit originated, not completed | | $55.10 | `R10` | Customer Not Authorized | Debit completed | | $55.11 | `R11` | Entry Not in Accordance with Terms | Debit originated, not completed | | $55.15 | `R15` | Account Holder Deceased | Debit originated, not completed | | $55.16 | `R16` | Account Frozen | Debit originated, not completed | | $55.20 | `R20` | Non-Transaction Account | Debit originated, not completed | | $55.24 | `R24` | Duplicate Entry | Debit originated, not completed | | $55.29 | `R29` | Corporate Customer Not Authorized | Debit originated, not completed | A return will be only triggered if the transfer type (for example, wallet-to-bank) is applicable to the particular return scenario and amount entered. For example, an `R01` in test mode always occurs on the debit leg, *after* the transfer stage of debit origination. Accordingly, an `R01` return cannot be triggered on a wallet-to-bank transfer, as that transfer type only consists of a credit leg. Creating a return scenario that does not apply to a corresponding transfer type will result in a regular test transfer, not a test return. Once you have created a transfer with an appropriate return code, Moov will update the transfer to `Failed` or `Reversed` based on the transfer stage (see [ACH returns and exceptions](/guides/money-movement/accept-payments/ach/returns/) for more information). The bank account status will also be updated accordingly. The ACH returns and exceptions guide also includes the full ACH [return code](/guides/money-movement/accept-payments/ach/returns/#return-codes) list. ### [Declined card transfers](#declined-card-transfers) To simulate a declined `Card payment` transfer, use the following card numbers when creating a test transfer. The `Expiration date` field for all test cards can be set to any future date. | Card brand | Test card number | CVV | |------------------|-----------------------|---------------| | Visa | `4000 0200 0000 0000` | Any 3 numbers | | Mastercard | `5555 0000 2222 0022` | Any 3 numbers | | Discover | `6011 0000 2222 0002` | Any 3 numbers | | American Express | `3711 0000222 20002` | Any 4 numbers | ### [Disputes](#disputes) To simulate disputes, use the card numbers below when creating a transfer. The expiration date can be any future date. CVV can be any 4 numbers for Amex and any 3 numbers for all other card brands. | Card brand | Test card number | Phase | Reason code | |-----------------------------|-----------------------|------------|-------------| | Visa | `4000 2000 2000 2000` | Chargeback | 10.4 | | Visa - Pull from card | `4111 1000 1000 3008` | Chargeback | 10.4 | | Mastercard | `5555 4444 0000 4444` | Chargeback | 4860 | | Mastercard - Pull from card | `5555 5555 5555 3339` | Chargeback | 4860 | | Discover | `6011 2222 2222 0000` | Chargeback | 05 | | American Express | `3710 100020 00123` | Chargeback | F29 | | American Express | `3720 200020 00188` | Inquiry | 21 | To simulate winning or losing a dispute, you can upload winning or losing **text** evidence (if you submit file evidence, the dispute status will remain `Under review`). The following outcomes can be simulated by entering *winning* or *losing* text evidence: | Text evidence | Phase | Outcome | |--------------------|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------| | `Winning evidence` | `Chargeback` | Dispute will enter an `Under review` status for 10 minutes before updating to `Won`. The chargeback is reversed and funds are credited to the merchant. | | `Winning evidence` | `Inquiry` | Dispute will enter an `Under review` status for 10 minutes before updating to`Closed`. | | `Losing evidence` | `Chargeback` | Dispute will enter an `Under review` status for 10 minutes before updating to `Lost`. | | `Losing evidence` | `Inquiry` | Dispute will enter an `Under review` status for 10 minutes before updating to `Respons -needed`. | ## [Bank accounts](#bank-accounts) We've already added test bank accounts on your behalf. If you'd like to add an additional test bank account, or you did not create an account through the Dashboard, you must include a valid routing number. For example: `322271627` The account number can be any number, for example: `12345654321` ### [Micro-deposit verification](#micro-deposit-verification) To simulate an [instant micro-deposit](/guides/sources/bank-accounts/verification/instant-micro-deposit/) verification in test mode, enter `0001` as the instant verification code. To simulate [traditional micro-deposit](/guides/sources/bank-accounts/verification/micro-deposits/) verification in test mode, enter `0` for both amounts and the bank account verification will succeed. If you input any other amount, the bank account verification will not complete. --- URL: https://docs.moov.io/guides/dashboard/transfers/all-transfers/ --- # Transfers Learn how to create and manage transfers from the Moov Dashboard. The **Transfers** section of the Dashboard provides you with an overview of your account's transfer history. You can create and manage transfers, including reversals, refunds, and cancellations. ## [Create a transfer](#create-a-transfer) Create a transfer between any two Moov accounts by clicking **New transfer** and choosing `Payout` or `Collect` in the Moov Dashboard. You'll need to input the following information to create a transfer: - Amount of the transfer - Your transfer use case - Source - Destination Optionally, you can enter: - Facilitator fee - Description - Metadata - ACH addenda (if transfer is an ACH transfer) ## [Transfer details](#transfer-details) Clicking any transfer will bring you to the **Transfer details** page. You can manage and review information about a transfer and its current status. ![Transfer detail view in Moov Dashboard](../images/transfer-details.png) The transfer timeline shows information on each leg of the transfer to give transparency on where the funds are in the process. For example, if a transfer from a bank account to a Moov wallet is created, you’ll see the ACH debit information followed by the funds availability in the Moov wallet. ### [Initiate a reversal, refund, or cancellation](#initiate-a-reversal-refund-or-cancellation) We strongly recommend initiating reversals for the purposes of refunds due to its broader functionality and enhanced flexibility. Reversals offer more flexibility to return funds to the cardholder. Based on the state of the transfer, Moov dynamically chooses the appropriate action, either a cancellation or refund. When possible, a reversal will cancel a transfer, reversing the authorization and swiftly returning funds. If settlement is in progress or completed, a refund is issued instead. Canceling a transfer offers certain advantages over refunds, such as reducing processing costs and expediting returns to cardholders. #### [Reversal](#reversal) Initiate a refund on the **Transfer details** page by clicking the **Refund** button. Once initiated, you can choose whether it's a full or partial refund, and note how much you're refunding. If you initiate a full refund and the transfer has not settled, you'll be notified that the transfer has been *canceled*. Afterwards, Moov will populate relevant information and status in the transfer details section and the timeline. #### [Refund](#refund) Initiate a refund on by clicking the **Refund** button. Once initiated, you can choose whether it's a full or partial refund, and note how much you're refunding. Afterwards, Moov will populate relevant information and status in the transfer details section and the timeline. ![Initiate a refund](../images/refund.png) #### [Cancel](#cancel) You have the option of initiating a card or ACH cancellation directly. For card transfers, if you request a cancellation, but the card network has already settled, you’ll receive an error. You can cancel an [ACH transfer](/guides/money-movement/accept-payments/ach/cancellations/) based on the following timeframes: ![ACH cancellations must occur within a specific time frame.](../images/ach-cancel-window-light.png) ACH cancellations must occur within a specific time frame. In any of the above scenarios, transfers within a transfer group can be canceled if they fall within the allowed time frame. Once a transfer is successfully canceled, all subsequent transfers in the transfer group will also be automatically canceled. ![Initiate a cancellation](../images/cancellation.png) Note that cancelling a transfer will not affect any associated future scheduled transfers. ## [Transfer statuses](#transfer-statuses) The following is a list of transfer statuses: | Status | Description | |-------------|------------------------------------------------------------------------------------------------------------------------| | `created` | A transfer has been created | | `queued` | A transfer that is part of a group will have the queued status until the preceding transfer has successfully completed | | `pending` | The transfer is in progress, but not yet completed | | `completed` | The transfer has completed | | `canceled` | A transfer that is part of a group can fail and subsequent transfers will be marked as canceled | | `failed` | The transfer did not succeed | | `reversed` | The transfer completed, but funds were returned to the source | Refer the main [transfer events and status](/guides/money-movement/events-and-statuses/) guide for more details, including rail specific statuses, failures, and reversals. --- URL: https://docs.moov.io/guides/dashboard/transfers/disputes/ --- # Disputes View and manage disputes from the Dashboard. Navigate to **Transfers > Disputes** in the Dashboard. You can view, accept, challenge, delete, and update disputes, as well as view, upload, and update dispute evidence. The main disputes table view will list the following details: - Amount - Status & phase - Reason code - Merchant account - Respond by date - Disputed date ![Dispute list in the Dashboard](../images/disputes-view.png) ## [Dispute details & evidence](#dispute-details--evidence) Click a dispute to go to the transfer details page where you can view additional information such as the entire transfer timeline and the dispute and transfer IDs. Here you have the ability to accept the dispute and start the refund process, or you can challenge the dispute by submitting evidence. ![Dispute details in the Dashboard](../images/dispute-details.png) ### [Submit and review evidence](#submit-and-review-evidence) Submit, view, and manage dispute evidence within the transfer details page. If you chose to challenge the dispute, you'll need to upload and submit evidence, such as proof of purchase or terms of service. Time is crucial when dealing with disputes. View the full [dispute](/guides/money-movement/accept-payments/card-acceptance/disputes/#respond-to-disputes) guide for details about accepting or challenging disputes. Responses to disputes are due to Moov by the `Respond by` date and vary by card brand: | Card brand | Dispute respondBy | |------------|-------------------| | Visa | 14 calendar days | | Mastercard | 14 calendar days | | Discover | 14 calendar days | | Amex | 10 calendar days | ### [Accept dispute](#accept-dispute) You can easily accept the dispute from the transfer details page. To accept the dispute, click the **Refund** button and follow the [reversal or refund](/guides/dashboard/transfers/all-transfers/#initiate-a-reversal-or-refund) procedure. ## [Filter disputes](#filter-disputes) You can filter disputes by status, phase, respond by, or disputed dates. You can also search disputes using the dispute ID or transfer ID. ![Dispute details in the Dashboard](../images/disputes-filter.png) --- URL: https://docs.moov.io/guides/dashboard/transfers/ --- # Transfers Create and manage transfers from the Dashboard. The **Transfers** section of the Dashboard allows you to view and manage transfers, disputes, and initiate refunds from the Dashboard. Use the peek preview shortcut to quickly access transfer status and details. ![Transfer detail view in Moov Dashboard](../../shared-images/transfers-view.png) ## [Peek preview](#peek-preview) The peek preview shortcut gives you fast access to details in the Dashboard. Press the `space` key to toggle the preview on and off. You can move your cursor up and down the transfer list and the preview will update with the corresponding transfer details. The `esc` key will also dismiss the preview. Press `c` while the preview is open to copy the `transferID` to your clipboard. --- URL: https://docs.moov.io/guides/dashboard/transfers/schedules/ --- # Schedules View or cancel scheduled transfers from the Dashboard. Navigate to **Transfers > Schedules** in the Dashboard. You can view and cancel scheduled transfers. The main schedules view will provide the following information: - Transfer description, if provided - Amount - The source account - The next scheduled transfer date - When the schedule cycle ends Click on the menu at the end of a transfer row to cancel the schedule or copy the schedule ID. Only the account that creates the schedule can cancel it. For example, if a merchant creates a schedule, only the merchant account is able to cancel that schedule. ![Payment link Dashboard view](../images/schedules-table.png) ## [View details](#view-details) Click on a scheduled transfer row to view the details, such as the source, destination, and when the schedule was originally created. Within the details view, you can also send a receipt and cancel the schedule. --- URL: https://docs.moov.io/guides/dashboard/wallet/ --- # Balances Manage your wallets and view wallet balances and transactions. Moov provides each account with a default wallet. In addition to this wallet, you can create multiple general wallets. Each wallet maintains its own independent balance and transaction history, giving you greater flexibility in fund management and reconciliation. Navigate to the **Balances** section of the Dashboard to manage your wallets and view your available balance. Select a wallet from the list to view all wallet transactions. ![Wallet transaction list view in Moov Dashboard](../images/wallets-view.png) ## [Create a wallet](#create-a-wallet) On the main balances view, click **Create wallet**. Give the wallet a name and description. If you enable [automated payouts](#automated-payouts) (sweeps), you'll also be able to: - Select or add a bank account - Choose a processing speed - Set a minimum balance (optional) - Set a custom statement descriptor (optional) ![Create a wallet in Moov Dashboard](../images/create-wallet.png) ## [Edit a wallet](#edit-a-wallet) Select any general wallet and click **Edit wallet**. In addition to updating the name and description of the wallet, you can enable [automated payouts](#automated-payouts). ## [Close a wallet](#close-a-wallet) If you choose to close a wallet, it will become permanently disabled, as will the corresponding payment method. To close a wallet, the following criteria need to be met: - No pending inbound transfers - Balance is zero and has no activity in the past 75 days - Must be a general wallet (default wallets cannot be closed) Closing a wallet is permanent and cannot be undone. While it has no impact on data retention for past transactions, a closed wallet may still incur transactions from exceptions like disputes or refunds, which could result in a negative balance. Ensure any negative balances are resolved in a timely manner. Open the wallet's menu and select **Close wallet**. ![Close a wallet in Moov Dashboard](../images/close-wallet.png) ## [Automated payouts](#automated-payouts) A sweep automatically initiates daily transfers to external bank accounts on a set schedule. Enabling sweeps will either payout funds from a wallet or pull funds to cover fees and chargebacks. You can configure sweeps to automatically collect fees or other payments your account has received. See the full [sweeps](/guides/money-movement/wallets/sweeps/) API guide for more information. ### [Configure sweeps](#configure-sweeps) You can configure sweeps from multiple places in the Dashboard, such as editing a wallet or navigating to an account’s settings page. Once you've enabled sweeps, you'll see the menu option to view automated payouts directly below the wallet balance. Expanding the menu will show you: - Upcoming payouts - Payout transactions - Associated bank account ### [Reconciliation](#reconciliation) A sweep’s daily `Accrued amount` is what typically can be expected to transfer to the associated bank account. However, there are some cases where the amount accrued in the sweep won’t be the amount transferred. For example, when a sweep is first enabled, or a minimum balance is first set, Moov will calculate the `Transfer amount` based on the wallet’s available balance in order to maintain the balance in the configuration. In those one-off cases, Moov calculates the amount to transfer accordingly: `transferAmount` = `availableBalance` at sweep close - `minimumBalance` See our main [sweeps](/guides/money-movement/wallets/sweeps/) guide for information about negative sweeps and failures. ## [Transactions](#transactions) The transaction list overview will show you the date, type, memo, amount, and remaining wallet balance for each transaction. Click on an individual transaction to see more detail, such as the transaction source, destination, and ID. Click **See details** in the transaction source section to enter the **Transfers** section of the Dashboard, where you can view all the details associated with the transfer. ### [Filters](#filters) By default, the list shows all transactions, but you can quickly filter for just completed or pending transactions. You can also use the search bar to search by source or sweep ID. Additional filters can be accessed by clicking on the **Filter** menu. You can filter by one or multiple transaction types, as well as specify date ranges. --- URL: https://docs.moov.io/guides/developer-tools/breaking-changes-api/ --- # API versioning & breaking changes When Moov manages API changes and releases, it's crucial for us to distinguish between breaking and non-breaking changes to ensure smooth transitions and maintain your functionality. Moov reserves the right to make changes to our API at any time. Breaking changes disrupt existing integrations and require immediate updates to mitigate errors. Non-breaking changes enhance or extend the API without affecting current operations. Certain changes may straddle the line, making it essential to consider the context and usage patterns. This page covers various API change scenarios, identifying which changes are breaking and non-breaking. Moov will communicate all breaking changes directly, in an appropriate time frame for customers to update their integrations accordingly. Breaking changes will also be announced in our [changelog](/changelog/) (subscribe for notifications). Additionally, Moov reserves the right to update and fix our SDKs with the same list of breaking changes when needed. Fixes to our SDKs may result in updates and changes to the API. Note that "field" can refer to a field in a request body, response body, query parameter, header value, or any other variable or value used by the API. ## [Breaking changes](#breaking-changes) The following list has been established as breaking changes and will require action to remedy. Removing an existing field - Example: Removing the `lastName` field from the user profile API. - Outcome: Integrations that depend on this field will encounter errors or incomplete data. * * * Changing the data type of a field - Example: Changing the `id` field from a string to an integer. - Outcome: Integrations expecting a string may fail to parse the new integer value. * * * Changing the structure of the response - Example: Modifying the response structure from a flat JSON to a nested JSON. - Outcome: Integrations that parse the response based on the old structure must adapt to the new structure. * * * Removing an endpoint - Example: Removing the `GET /users/{userID}/profile` endpoint. - Outcome: Integrations that rely on this endpoint will no longer be able to retrieve user profiles. * * * Changing endpoint URLs - Example: Changing the endpoint URL from `/user` to `/profile/user`. - Outcome: Integrations will break if they have not been updated with a call to the new URL. * * * Modifying required fields in requests - Example: Making the `email` field required in a request where it was previously optional, or adding a new required field. - Outcome: Requests will fail if the modified field is not provided. * * * Changing HTTP methods - Example: Changing the HTTP method from `POST` to `PUT` for creating a new resource. - Outcome: Request methods must be updated accordingly. * * * Changing default values - Example: Changing the default value of a `sortOrder` field from `ASC` to `DESC`. - Outcome: The change alters the default behavior of the sort. If the integration relied on the previous default sorting behavior, it will need to accommodate this change, otherwise it can be ignored. * * * Changing date formats - Example: Changing date format from `MM-DD-YYYY` to `YYYY-MM-DD`. - Outcome: Date parsing must adapt to the new format. * * * Adding authentication requirements - Example: Requiring an API key for an endpoint that previously did not need authentication. - Outcome: New authentication mechanisms must be implemented. * * * Changing field names - Example: Renaming `username` to `user_name`. - Outcome: References must update to the new field. * * * Changing pagination logic - Example: Switching from page-based to cursor-based pagination. - Outcome: Changes are required for handling new pagination logic. * * * Changing a field's valid values - Example: Removing a previously valid enum value. - Outcome: Changes are required to use a different value. * * * Adding new fields to responses that require interaction - Example: Adding a `disabledOn` timestamp to the user profile response. - Outcome: Generally considered non-breaking, however in this case it could be considered breaking as it states this model is disabled and non-interactable. * * * Adding a new enum value to field set - Moov set, integration read - Example: Adding a `DISABLED` status to an existing `status` enum. - Outcome: Integrations aren't set up to handle new values. A new enum value will fall through a catch all error. * * * Bug fixes resulting in different status codes - Example: Changing an HTTP response code from `404 Not Found` to `409 Conflict`. - Outcome: Integration expects a `404` for the specific error case but is getting back a `409`. Integration must update to handle this new response code. * * * ## [Non-breaking changes](#non-breaking-changes) The following list has been established as non-breaking changes for integrations that adhere to industry standards. Adding a new optional field to a response - Example: Adding an optional `middleName` field to the user profile response that the integration may or may not return. - Outcome: Integrations should not be affected by this change. However, this action may result in a breaking change if response fields are strictly validated. * * * Adding a new informational field to a response - Example: Adding a `createdAt` or `updatedOn` timestamp to the user profile response that will always be returned. - Outcome: Integrations should not be affected by this change. However, this action may result in a breaking change if response fields are strictly validated. * * * Adding new endpoints - Example: Adding a new endpoint `GET /users/{userID}/friends`. - Outcome: Integrations are not affected by new endpoints. * * * Deprecating an endpoint (with adequate notice) - Example: Marking `GET /users/{userID}/profile` as deprecated but still functional. - Outcome: As long as the endpoint continues to function and integrations have time to update, this is a non-breaking change. * * * Enhancing performance or fixing non-behavioral bugs - Example: Improving response time or fixing a typo in the documentation. - Outcome: These changes do not affect the API's interface or expected behavior. * * * Adding new response headers - Example: Including a new header `X-Request-ID` in responses. - Outcome: As long as existing headers remain unchanged, this is a non-breaking change. * * * New enum value to field set - client set, Moov read - Example: Adding a `NEW_FEATURE` status to an existing `action` enum. - Outcome: Fields set and requested by the integration owner should not break since its return is expected. * * * Bug fixes resulting in different status codes - generic to specific - Example: Changing an HTTP response code from `409 Conflict` to `500 Internal Server Error`. - Outcome: Moov considers this non-breaking if a generic error status code of `500` or `400` is changed to a status code that's already defined by the API. * * * Consistent array ordering without explicit ordering specified - Example: Returning an array of `['b', 'a']` without specifying it must be alphabetical via a query argument. - Outcome: An item in an array doesn't care about order. * * * Consistent map ordering - Example: Returning an map of `{"b": true, "a": true}` - Outcome: All lookups of the value are via the key. ## [API versions](#api-versions) Moov's API versioning follows the format `vYYYY.QQ.BB`, where - `YYYY` is the year - `QQ` is the two-digit month for the first month of the quarter (e.g., `01`, `04`, `07`, `10`) - `BB` is the build number, starting at `.00`, for subsequent builds in the same quarter. For example, `v2026.01.00` is the API version for Q1 of 2026. ### [Release cadence](#release-cadence) To ensure customers maintain insight into upcoming changes, each quarter's API will be made public one quarter early in an **in development** status. Customers should use an **in development** API with caution as breaking changes may occur without notice. At the beginning of every quarter, the API for that quarter will move from its **in development** status to officially released. No breaking changes will be added to an API version after the first day of its quarter. The next quarter's API will be made available as the new **in development** version. For example, `v2027.01.00` is made public on October 1, 2026 as **in development**. On January 1, 2027, `v2027.01.00` is officially released and `v2027.04.00` is made public as **in development**. If no API version is passed in your header request, Moov will default to `v2024.01.00`. See our [API version reference](/api/version-reference/) for more detailed information. --- URL: https://docs.moov.io/guides/developer-tools/data-sync/ --- # Data sync Sync your Moov payment data with Google BigQuery. Data sync is a no-code feature that sends your Moov account data to Google BigQuery, allowing you to access your payment data in your own data warehouse. ## [Features](#features) - Access to near-real-time payments data in your data warehouse - No ETL required - Access and analyze data in BI tools connected to BigQuery, like Looker & Tableau - Granular control over access ## [Setup](#setup) [Contact Moov](https://support.moov.io/) to set up a private data exchange with Google Analytics Hub. Provide us with your Moov account ID and we'll send you a Google Cloud Marketplace private listing. You can accept the listing as an authenticated Google Cloud user. Once configured, your Moov data will be available in BigQuery within a few hours and updated regularly. --- URL: https://docs.moov.io/guides/developer-tools/ --- # Developer tools Moov builds, hosts, and supports tools you can use and contribute to. Explore Postman to view example implementations of the Moov API and use our community tools to engage and contribute to the fintech community. If you'd like information on Moov's various frontend and backend integration options, see our [overview](/guides/) guide. --- URL: https://docs.moov.io/guides/developer-tools/mcp-ai/ai-integration/ --- # AI integration Point your AI coding assistant at Moov and start building. ## [Choose your approach](#choose-your-approach) [Docs MCP server \ Search and read Moov docs from your AI assistant. Read-only documentation search — no API keys needed.](/guides/developer-tools/mcp-ai/docs-mcp/) [AI skill \ Offline integration patterns for Claude Code, Cursor, Windsurf, GitHub Copilot, and more.](/guides/developer-tools/mcp-ai/ai-skill/) [Moov MCP \ Live API operations — create accounts, transfers, and more directly from your IDE.](/guides/developer-tools/mcp-ai/mcp/) ## [Additional resources](#additional-resources) - [**OpenAPI spec**](https://spec.speakeasy.com/moov/moov/api-v2026.01.00) — Machine-readable source of truth for all API endpoints and schemas - [**API reference**](https://docs.moov.io/api/) — Rendered documentation with per-endpoint examples - [**llms.txt**](https://docs.moov.io/llms.txt) — Structured overview of Moov docs with links to every section - [**llms-full.txt**](https://docs.moov.io/llms-full.txt) — Full documentation content in a single file for long-context models or RAG pipelines - [**Contribute skills**](https://github.com/moovfinancial/moov-skills) — Open-source AI skills repo. Contribute improvements, fix errors, or add example prompts. ## [Comparison](#comparison) | Tool | Best for | How it's used | |--------------------------------------------------------------------------|---------------------------------------------------------------|----------------------------------------------------------------| | [**Docs MCP server**](/guides/developer-tools/mcp-ai/docs-mcp/) | AI tools that support MCP (Claude Code, Cursor, Windsurf) | Installed once, searches docs on demand per question | | [**Moov MCP**](/guides/developer-tools/mcp-ai/mcp/) | Live API operations (create accounts, transfers) | Installed once, calls Moov API directly with your credentials | | [**AI skill**](/guides/developer-tools/mcp-ai/ai-skill/) | Offline coding patterns you can paste and run | Copied into your project, loaded automatically by your IDE | | **llms-full.txt** | Tools without MCP support, long-context models, RAG pipelines | Paste URL into Claude/Gemini, or feed into custom agent | | **llms.txt** | Auto-discovery and structural overview | Fetched automatically by some AI tools at the domain root | | [**OpenAPI spec**](https://spec.speakeasy.com/moov/moov/api-v2026.01.00) | Exact request/response schemas and field types | Download YAML and feed to AI, or reference for code generation | The docs MCP server searches documentation. For live API operations like creating accounts and transfers, use the [Moov TypeScript SDK MCP server](/guides/developer-tools/mcp-ai/mcp/). --- URL: https://docs.moov.io/guides/developer-tools/mcp-ai/ai-skill/ --- # Moov AI skill Give your AI coding assistant offline access to opinionated Moov integration patterns. ## [What is an AI skill?](#what-is-an-ai-skill) An AI skill is a markdown file that gives your coding assistant domain-specific knowledge — API patterns, code examples, best practices, and common pitfalls. The Moov skill teaches your AI assistant how to correctly build payment integrations, using native Moov features instead of building custom solutions. The skill works offline with no network calls. It complements the [docs MCP server](/guides/developer-tools/mcp-ai/docs-mcp/) (live documentation search) and the [OpenAPI spec](#openapi-specification) (exact field-level schemas). ## [What's included](#whats-included) - Server-side token generation, scopes, and the multi-token pattern - API version headers and OpenAPI spec reference - Account creation for individuals and businesses - Capability reference table - Hosted onboarding for merchant KYC/KYB - Resolution links for fixing verification issues - Bank account linking and micro-deposit verification - Card linking, verification, card-on-file, and card account updater - Apple Pay and Google Pay integration - Wallet management and automatic sweeps to bank accounts - Moov.js / Drops: pre-built PCI-compliant UI components (card input, onboarding, payment methods) - Transfer creation with Go, TypeScript, Python, and cURL examples - Payment rail comparison table - Refunds and reversals (automatic cancel-or-refund logic) - Dispute/chargeback handling with evidence submission - Transfer groups for chained/split payments - Scheduled and recurring transfers with RRULE - Invoices with line items, payment links, and status tracking - Payment links for collecting payments and disbursing payouts (hosted checkout and payout flows) - Branded receipt emails - Enrichment: institution lookup, address autocomplete, profile enrichment - Card issuing patterns - Tap to Pay on iPhone and Android - Webhook event reference and signature verification - Card failure codes and common errors - SDK installation (Go, TypeScript, Python, .NET, Moov.js) - Docs MCP server setup - Test mode patterns ## [Install the skill](#install-the-skill) All downloads use public URLs at `docs.moov.io` — no authentication needed. Skills are also available directly from [GitHub](https://github.com/moovfinancial/moov-skills). [Claude Code](#tab-238147596-1-0) [Cursor](#tab-238147596-1-1) [Windsurf](#tab-238147596-1-2) [GitHub Copilot](#tab-238147596-1-3) [Codex CLI](#tab-238147596-1-4) [VS Code](#tab-238147596-1-5) [Manual / ChatGPT](#tab-238147596-1-6) Claude Code auto-discovers skill files in `.claude/skills/`. Download all 6 topic-specific skills so Claude only loads what's relevant to each question: ```bash mkdir -p .claude/skills/moov-api/accounts .claude/skills/moov-api/payment-sources .claude/skills/moov-api/money-movement .claude/skills/moov-api/commerce .claude/skills/moov-api/issuing # From docs.moov.io curl -sL https://docs.moov.io/skills/moov-api/SKILL.md -o .claude/skills/moov-api/SKILL.md curl -sL https://docs.moov.io/skills/moov-api/accounts/SKILL.md -o .claude/skills/moov-api/accounts/SKILL.md curl -sL https://docs.moov.io/skills/moov-api/payment-sources/SKILL.md -o .claude/skills/moov-api/payment-sources/SKILL.md curl -sL https://docs.moov.io/skills/moov-api/money-movement/SKILL.md -o .claude/skills/moov-api/money-movement/SKILL.md curl -sL https://docs.moov.io/skills/moov-api/commerce/SKILL.md -o .claude/skills/moov-api/commerce/SKILL.md curl -sL https://docs.moov.io/skills/moov-api/issuing/SKILL.md -o .claude/skills/moov-api/issuing/SKILL.md # Or from GitHub # curl -sL https://raw.githubusercontent.com/moovfinancial/moov-skills/main/moov-api/SKILL.md -o .claude/skills/moov-api/SKILL.md # (same pattern for other files) ``` Cursor 0.45+ supports multiple rule files in `.cursor/rules/`. Download topic-specific skills for selective loading: ```bash mkdir -p .cursor/rules/moov-api curl -sL https://docs.moov.io/skills/moov-api/SKILL.md -o .cursor/rules/moov-api/core.md curl -sL https://docs.moov.io/skills/moov-api/accounts/SKILL.md -o .cursor/rules/moov-api/accounts.md curl -sL https://docs.moov.io/skills/moov-api/payment-sources/SKILL.md -o .cursor/rules/moov-api/payment-sources.md curl -sL https://docs.moov.io/skills/moov-api/money-movement/SKILL.md -o .cursor/rules/moov-api/money-movement.md curl -sL https://docs.moov.io/skills/moov-api/commerce/SKILL.md -o .cursor/rules/moov-api/commerce.md curl -sL https://docs.moov.io/skills/moov-api/issuing/SKILL.md -o .cursor/rules/moov-api/issuing.md ``` Or download the combined file for older Cursor versions: ```bash curl -sL https://docs.moov.io/skills/moov-api/SKILL-full.md -o .cursorrules ``` Download the combined skill file: ```bash curl -sL https://docs.moov.io/skills/moov-api/SKILL-full.md -o .windsurfrules ``` **Note:** Windsurf has a character limit on rule files. If the file is too large, download individual topic skills and reference them separately. Download the combined skill file: ```bash curl -sL https://docs.moov.io/skills/moov-api/SKILL-full.md -o .github/copilot-instructions.md ``` Download the combined skill file: ```bash curl -sL https://docs.moov.io/skills/moov-api/SKILL-full.md -o AGENTS.md ``` Download the combined skill file: ```bash curl -sL https://docs.moov.io/skills/moov-api/SKILL-full.md -o .github/copilot-instructions.md ``` Note - VS Code and ad GitHub Copilot have the same download location. Download or copy the combined skill file and paste it into your conversation: [Download SKILL-full.md](https://docs.moov.io/skills/moov-api/SKILL-full.md) ## [Supported tools at a glance](#supported-tools-at-a-glance) | Tool | Config file | Auto-discovery | |------------------|-------------------------------------------------|------------------------------------------| | Claude Code | `.claude/skills/moov-api/SKILL.md` | Yes — loads relevant skills per question | | Cursor | `.cursor/rules/moov-api/*.md` or `.cursorrules` | Yes — rules loaded per session | | Windsurf | `.windsurfrules` | Yes — loaded on session start | | GitHub Copilot | `.github/copilot-instructions.md` | Yes — loaded per session | | Codex CLI | `AGENTS.md` | Yes — loaded on agent start | | VS Code | `.github/copilot-instructions.md` | Yes — loaded per session | | ChatGPT / Manual | Paste into conversation | No — copy and paste | ## [How the skill works](#how-the-skill-works) The skill is an offline reference — no network calls, no API keys, no MCP connection needed. Your AI assistant reads from disk and uses the patterns to generate code. Key behaviors: - **Defaults to hosted**: Unless the developer indicates they have an existing UI, the skill recommends hosted flows (payment links, hosted onboarding) over embedded API integration - **Opinionated patterns**: Uses native Moov features (sweeps, scheduled transfers, invoices) instead of building custom solutions - **SDK-aware**: Generates code using the correct Moov SDK for the developer's language - **Complement with live data**: For exact field names and response schemas, pair the skill with the [OpenAPI spec](#openapi-specification) or [docs MCP server](/guides/developer-tools/mcp-ai/docs-mcp/) ## [Example prompts](#example-prompts) **Tip:** Tell your AI assistant which language you're using (Go, TypeScript, Python, or .NET) so it generates code with the correct Moov SDK. If you don't specify, a good AI assistant should ask. ### [Rental property management](#rental-property-management) I'm building a rental property management platform. I need to collect rent from tenants and send payouts to property managers. **Users:** Property management companies (merchants) who receive rent. Tenants (individuals) who pay rent and occasional fees. **Flows I need:** 1. **Merchant onboarding** — Property management companies sign up on my platform. I already have their business name and email. I need them to complete KYC/KYB verification and agree to pricing. I want a hosted flow, not custom identity verification forms. 2. **Tenant accounts** — When a tenant signs a lease, create an account for them and collect their payment method (bank account for ACH, or card). 3. **Monthly rent** — Fixed amount, collected on the 1st of every month via ACH debit from the tenant's bank account to the property manager's Moov wallet. This should be automated, not a custom scheduler. 4. **Variable charges** — Cleaning fees, maintenance charges, early check-in fees. One-off, variable amounts. Send the tenant an itemized bill they can pay online with card or bank transfer. 5. **Webhooks** — Track payment status and invoice status to update my database. Build me a step-by-step integration plan using the Moov API. For each step, show me the API call or tell me which Moov feature to use. Don't build custom solutions for things Moov handles natively. ### [Logistics disbursements](#logistics-disbursements) I'm building a logistics platform that connects shipping companies with owner-operator truckers. When a trucker completes a load delivery, the platform needs to pay them out. **Users:** Shipping companies (business accounts/merchants) who post loads. Owner-operator truckers (individuals) who deliver loads and receive payouts. **Flows I need:** 1. **Shipping company onboarding** — Shipping companies sign up on my platform. I already have their business name and email. I need them to complete KYC/KYB verification and agree to pricing. I want a hosted flow, not custom identity verification forms. 2. **Trucker payouts** — When a trucker completes a delivery, my platform confirms the load and needs to send payment. Truckers should receive a link where they verify their identity, add their debit card or bank account, and get paid. I want a hosted disbursement flow, not a custom UI for collecting trucker payment methods. Instant payouts to debit cards are preferred, with ACH as a fallback. 3. **Track disbursement status** — I need to know when a payout link is completed and funds are sent so I can update the load status in my system. Build me a step-by-step integration plan using the Moov API. For each step, show me the API call or tell me which Moov feature to use. Don't build custom solutions for things Moov handles natively. ## [OpenAPI specification](#openapi-specification) The OpenAPI spec is the machine-readable source of truth for all Moov API endpoints, request/response schemas, and parameters. Point your AI tool at the spec when you need exact field names, types, or validation rules. - **API reference:** [docs.moov.io/api/](https://docs.moov.io/api/) — rendered documentation with per-endpoint examples - **OpenAPI spec download:** [spec.speakeasy.com/moov/moov/api-v2026.01.00](https://spec.speakeasy.com/moov/moov/api-v2026.01.00) — raw YAML spec for the current stable version To download a different version, replace the version in the URL (e.g. `api-v2025.07.00`). ## [Contribute](#contribute) Skills are open source at [github.com/moovfinancial/moov-skills](https://github.com/moovfinancial/moov-skills). Contributions welcome — you can improve existing skills, fix errors, or add new [example prompts](https://github.com/moovfinancial/moov-skills/tree/main/examples). See the [contributing guide](https://github.com/moovfinancial/moov-skills/blob/main/CONTRIBUTING.md) for details. ## [Comparison table](#comparison-table) | Tool | Best for | How it's used | |--------------------------------------------------------------------------|---------------------------------------------------------------|----------------------------------------------------------------| | [**Docs MCP server**](/guides/developer-tools/mcp-ai/docs-mcp/) | AI tools that support MCP (Claude Code, Cursor, Windsurf) | Installed once, searches docs on demand per question | | [**Moov MCP**](/guides/developer-tools/mcp-ai/mcp/) | Live API operations (create accounts, transfers) | Installed once, calls Moov API directly with your credentials | | **AI skill** | Offline coding patterns you can paste and run | Copied into your project, loaded automatically by your IDE | | **llms-full.txt** | Tools without MCP support, long-context models, RAG pipelines | Paste URL into Claude/Gemini, or feed into custom agent | | **llms.txt** | Auto-discovery and structural overview | Fetched automatically by some AI tools at the domain root | | [**OpenAPI spec**](https://spec.speakeasy.com/moov/moov/api-v2026.01.00) | Exact request/response schemas and field types | Download YAML and feed to AI, or reference for code generation | --- URL: https://docs.moov.io/guides/developer-tools/mcp-ai/docs-mcp/ --- # Documentation MCP server Search and read Moov docs from your AI coding assistant using the docs MCP server. ## [Quick start](#quick-start) If you use Claude Code, add the docs MCP server with one command: ```bash claude mcp add --transport http moov-docs https://docs.moov.io/mcp ``` For other tools, see the [setup instructions](#set-up-your-ide) below. ## [What is MCP?](#what-is-mcp) The [Model Context Protocol](https://modelcontextprotocol.io/) (MCP) is an open standard that lets AI coding tools connect to external data sources. When your IDE supports MCP, it can call tools provided by an MCP server on your behalf — searching documentation, fetching pages, or listing available sections without leaving the editor. The Moov **docs MCP server** is a read-only documentation search tool. It does not call the Moov API or make changes to your account. For live API operations like creating accounts and transfers, use the [Moov TypeScript SDK MCP server](/guides/developer-tools/mcp-ai/mcp/). ## [Available tools](#available-tools) | Tool | Description | |----------------------|--------------------------------------------------------------------| | `search_moov_docs` | Full-text search across all Moov documentation pages | | `get_moov_doc` | Retrieve the full content of a specific documentation page by path | | `list_moov_sections` | List all available documentation sections and their paths | ## [Set up your IDE](#set-up-your-ide) [Claude Code](#tab-468923751-2-0) [Cursor](#tab-468923751-2-1) [Windsurf](#tab-468923751-2-2) [VS Code](#tab-468923751-2-3) [Zed](#tab-468923751-2-4) [Cline](#tab-468923751-2-5) [Gemini CLI](#tab-468923751-2-6) [Claude Desktop](#tab-468923751-2-7) ```bash claude mcp add --transport http moov-docs https://docs.moov.io/mcp ``` [Claude Code MCP docs](https://code.claude.com/docs/en/mcp) Create a `.cursor/mcp.json` file in your project root: ```json { "mcpServers": { "moov-docs": { "command": "npx", "args": ["-y", "mcp-remote", "https://docs.moov.io/mcp"] } } } ``` [Cursor MCP docs](https://cursor.com/docs/context/model-context-protocol) Add to your Windsurf MCP configuration (`~/.codeium/windsurf/mcp_config.json`): ```json { "mcpServers": { "moov-docs": { "serverUrl": "https://docs.moov.io/mcp" } } } ``` [Windsurf MCP docs](https://docs.windsurf.com/windsurf/cascade/mcp) Add to your VS Code settings (`.vscode/mcp.json`): ```json { "servers": { "moov-docs": { "type": "http", "url": "https://docs.moov.io/mcp" } } } ``` [VS Code MCP docs](https://code.visualstudio.com/docs/copilot/customization/mcp-servers) Add to your Zed settings (`~/.zed/settings.json`): ```json { "context_servers": { "moov-docs": { "url": "https://docs.moov.io/mcp" } } } ``` [Zed MCP docs](https://zed.dev/docs/ai/mcp) Add to your Cline MCP settings (`~/.cline/data/settings/cline_mcp_settings.json`): ```json { "mcpServers": { "moov-docs": { "type": "http", "url": "https://docs.moov.io/mcp" } } } ``` [Cline MCP docs](https://docs.cline.bot/mcp/configuring-mcp-servers) ```bash gemini mcp add --transport http moov-docs https://docs.moov.io/mcp ``` Or add to your settings (`~/.gemini/settings.json`): ```json { "mcpServers": { "moov-docs": { "httpUrl": "https://docs.moov.io/mcp" } } } ``` [Gemini CLI MCP docs](https://google-gemini.github.io/gemini-cli/docs/tools/mcp-server.html) Claude Desktop doesn't support remote MCP servers directly in config. Instead, add the server through the claude.ai web UI: 1. Go to [claude.ai/settings/connectors](https://claude.ai/settings/connectors) 2. Add a new connector with the URL `https://docs.moov.io/mcp` 3. The server syncs automatically to Claude Desktop when signed in with the same account [Claude Desktop MCP docs](https://support.claude.com/en/articles/11175166-getting-started-with-custom-connectors-using-remote-mcp) ## [Example prompts](#example-prompts) Once the MCP server is installed, try prompts like these with your AI assistant: - Create a Moov account and request `send-funds.ach` capability - Show me how to initiate an ACH transfer with the Go SDK - Generate a scoped OAuth token for linking a bank account to an existing account - What payment methods are available for instant payouts? - How do I verify a bank account with micro-deposits? - What capabilities do I need for card issuing? The docs MCP server searches documentation — it does not call the Moov API. Your [API keys](/guides/get-started/api-keys/) are not needed for MCP setup. For live API operations, see the [Moov MCP server](/guides/developer-tools/mcp-ai/mcp/). ## [LLM context files](#llm-context-files) These plain-text files follow the [llms.txt convention](https://llmstxt.org/) for making documentation available to AI tools. [**llms.txt**](https://docs.moov.io/llms.txt) — A structured overview of Moov's documentation with links to every section. Some AI tools automatically fetch `llms.txt` from a site's root when given a domain. You can also paste it into a conversation to give your AI assistant a map of what's available. [**llms-full.txt**](https://docs.moov.io/llms-full.txt) — The complete content of every documentation page concatenated into a single file. Use this when you want to load all of Moov's docs into a context window at once, or feed it into a custom RAG pipeline or agent. **When to use which:** - Use the **MCP server** when your AI tool supports it — it searches on demand and only returns relevant pages, keeping context small. - Use **llms-full.txt** when your tool doesn't support MCP, or you want to front-load all docs into a long-context model (e.g. paste URL into Claude, Gemini, or use `@docs` in Cursor). - Use **llms.txt** when you want your AI tool to understand the structure and decide which pages to fetch individually. ## [Docs MCP vs Moov MCP](#docs-mcp-vs-moov-mcp) | Server | What it does | Needs API keys? | |-----------------------------------------------------------------------------|--------------------------------------------------------|-----------------| | **Docs MCP** (`docs.moov.io/mcp`) | Searches and reads Moov documentation | No | | [**Moov MCP**](/guides/developer-tools/mcp-ai/mcp/) (`moov TypeScript SDK`) | Calls the Moov API — creates accounts, transfers, etc. | Yes | The docs MCP server searches documentation. For live API operations like creating accounts and transfers, use the [Moov TypeScript SDK MCP server](/guides/developer-tools/mcp-ai/mcp/). --- URL: https://docs.moov.io/guides/developer-tools/mcp-ai/ --- # MCP & AI integrations Use a combination of installable MCP servers and AI to read and interact with Moov's API. The Moov MCP server allows you to enable AI assistants to complete various tasks with AI. Write prompts to: - Search and read Moov's documentation - Complete actions via Moov's API and Dashboard Use the guides below to get started with your MCP and AI integration. --- URL: https://docs.moov.io/guides/developer-tools/mcp-ai/mcp/ --- # Moov Model Context Protocol The Moov TypeScript SDK is also an installable MCP server where the various SDK methods are exposed as tools that can be invoked by AI applications. [moovfinancial/ \ moov-typescript \ v25.8.0](https://github.com/moovfinancial/moov-typescript) ## [What is MCP?](#what-is-mcp) Model Context Protocol (MCP) allows AI models to interact with external tools and APIs. By installing the Moov MCP server, you can enable AI assistants to perform Moov operations on your behalf. ## [Installation](#installation) Node.js v20 or greater is required to run the MCP server from npm. [Claude](#tab-528361479-3-0) [Cursor](#tab-528361479-3-1) Add the following server definition to your `claude_desktop_config.json` file: ```json { "mcpServers": { "Moov": { "command": "npx", "args": [ "-y", "--package", "@moovio/sdk", "--", "mcp", "start", "--username", "...", "--password", "..." ] } } } ``` Create a `.cursor/mcp.json` file in your project root with the following content: ```json { "mcpServers": { "Moov": { "command": "npx", "args": [ "-y", "--package", "@moovio/sdk", "--", "mcp", "start", "--username", "...", "--password", "..." ] } } } ``` For a full list of server arguments, run: ```sh npx -y --package @moovio/sdk -- mcp start --help ``` ## [Example usage](#example-usage) Your MCP server has full access to your Moov account and can perform any action you can in the Moov Dashboard. To get you started, here are some example requests: - Create a payment link for $50. Use my platform account's wallet payment method ID as the destination - List the payment methods for account XYZ - What was the latest payout amount from my Moov wallet? - Find the XYZ account and its wallet balance - Resend the receipt to Jules Jackson for her latest transfer --- URL: https://docs.moov.io/guides/developer-tools/postman-collection/ --- # Postman collection To help make your development process simpler, we've published a Postman collection with example calls to our API. 1. Download the Postman [collection](https://www.postman.com/moovfin/workspace/moov/overview) 2. Generate an API key from your [Dashboard](https://dashboard.moov.io/developers/api-keys) 3. Add your `clientId` and `clientSecret` key as variables in the Postman collection When creating your own calls, be sure to include the `Origin` and `Referer` in the header. ## [About scopes](#about-scopes) Since different actions require a different [scopes](/api/authentication/scopes), each folder includes a call to generate a token with the scopes needed for that call. Scopes are required if you're using Moov.js or any client-side integration. --- URL: https://docs.moov.io/guides/developer-tools/test-data/ --- # Test mode data A quick overview of all test mode data for transfers scenarios. The test data on this page can be used in test mode to simulate various transfer scenarios. For more thorough instructions, visit our main [test mode](/guides/get-started/test-mode/) guide or our [Dashboard test mode](/guides/dashboard/test-mode/) guide. ## [Link cards & card acceptance](#link-cards--card-acceptance) | Card brand | Test card number | CVV | Postal code | Expiration date | |------------------|--------------------|---------------|---------------|-----------------| | Visa | `4111111111111111` | Any 3 numbers | Any 5 numbers | Any future date | | Mastercard | `5555555555554444` | Any 3 numbers | Any 5 numbers | Any future date | | Discover | `6011111111111117` | Any 3 numbers | Any 5 numbers | Any future date | | American Express | `371111111111114` | Any 4 numbers | Any 5 numbers | Any future date | See the postal and CVV sections below for additional test verification scenarios. Also note that test cards will expire once your chosen expiration date passes. ### [Postal code verification](#postal-code-verification) | Card brand | Verification result | Postal code | |-----------------|---------------------|-------------| | All card brands | `match` | 11111 | | All card brands | `noMatch` | 22222 | | Visa, Discover | `notChecked` | 88888 | | All card brands | `unavailable` | 99999 | ### [CVV verification](#cvv-verification) | Card brand | Verification result | CVV code | |----------------------------|---------------------|----------| | Visa, Mastercard, Discover | `match` | 111 | | American Express | `match` | 1111 | | Visa, Mastercard, Discover | `noMatch` | 222 | | American Express | `noMatch` | 2222 | | Visa, Mastercard, Discover | `notChecked` | 888 | | American Express | `notChecked` | 8888 | | Visa, Mastercard, Discover | `unavailable` | 999 | | American Express | `unavailable` | 9999 | ## [Push & pull from card](#push--pull-from-card) | Card brand | Completed transfer | Failed transfer | |------------|--------------------|--------------------| | Visa | `4111100010002000` | `4111100050007000` | | Mastercard | `5200828282828210` | `5200821111111114` | ## [Declined card transfers](#declined-card-transfers) | Card brand | Test card number | CVV | |------------------|--------------------|---------------| | Visa | `4000020000000000` | Any 3 numbers | | Mastercard | `5555000022220022` | Any 3 numbers | | Discover | `6011000022220002` | Any 3 numbers | | American Express | `3711000022220002` | Any 4 numbers | ## [RTP failures](#rtp-failures) | Transfer amount | Failure type | |-----------------|--------------------------| | $72.03 | `AC03` / invalid-account | | $72.04 | `AC04` / account-closed | | $72.06 | `AC06` / account-blocked | ## [ACH returns](#ach-returns) | Trigger Amount | Return Code | Description | Simulation Stage | |----------------|-------------|------------------------------------|---------------------------------| | $55.01 | `R01` | Insufficient Funds | Debit originated, not completed | | $55.02 | `R02` | Account Closed | Debit originated, not completed | | $55.03 | `R03` | No Account / Unable to Locate | Credit completed | | $55.04 | `R04` | Invalid Account Number Structure | Credit completed | | $55.07 | `R07` | Authorization Revoked by Customer | Debit completed | | $55.08 | `R08` | Payment Stopped | Debit completed | | $55.09 | `R09` | Uncollected Funds | Debit originated, not completed | | $55.10 | `R10` | Customer Not Authorized | Debit completed | | $55.11 | `R11` | Entry Not in Accordance with Terms | Debit originated, not completed | | $55.15 | `R15` | Account Holder Deceased | Debit originated, not completed | | $55.16 | `R16` | Account Frozen | Debit originated, not completed | | $55.20 | `R20` | Non-Transaction Account | Debit originated, not completed | | $55.24 | `R24` | Duplicate Entry | Debit originated, not completed | | $55.29 | `R29` | Corporate Customer Not Authorized | Debit originated, not completed | ## [Disputes](#disputes) | Card brand | Test card number | Phase | Reason code | |-----------------------------|--------------------|------------|-------------| | Visa | `4000200020002000` | Chargeback | 10.4 | | Visa - Pull from card | `4111100010003008` | Chargeback | 10.4 | | Mastercard | `5555444400004444` | Chargeback | 4860 | | Mastercard - Pull from card | `5555555555553339` | Chargeback | 4860 | | Discover | `6011222222220000` | Chargeback | 05 | | American Express | `371010002000123` | Chargeback | F29 | | American Express | `372020002000188` | Inquiry | 21 | ## [Dispute evidence](#dispute-evidence) | Text evidence | Phase | Outcome | |--------------------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------| | `winning-evidence` | `chargeback` | Dispute will enter an `under-review` status for 10 minutes before updating to `status: won`. The chargeback is reversed and funds are credited to the merchant. | | `winning-evidence` | `inquiry` | Dispute will enter an `under-review` status for 10 minutes before updating to`status: closed`. | | `losing-evidence` | `chargeback` | Dispute will enter an `under-review` status for 10 minutes before updating to `status: lost`. | | `losing-evidence` | `inquiry` | Dispute will enter an `under-review` status for 10 minutes before updating to `status: response-needed`. | ## [Bank accounts](#bank-accounts) | Data | Description | |---------------------------|--------------------------------------------------------------| | Routing number | Requires a valid routing number. Example: `322271627` | | Account number | The account number can be any number. Example: `12345654321` | | Instant verification code | `0001` | | Micro-deposits | `0,0` | --- URL: https://docs.moov.io/guides/get-started/api-keys/ --- # API keys Use the Moov Dashboard to find and create API keys. Moov uses API keys to generate tokens that authenticate your API requests. If your request does not include a valid token, you will receive an error. ## [Create a new API key](#create-a-new-api-key) To create a new API key, navigate to **Developers** in the Dashboard. Select **API keys**, where you can create new API keys, or view and edit existing ones. Test mode and production mode each require their own API keys. Only accounts with `admin` and `developer` permissions will be able to create and view API keys. For more on permissions, see [managing teams](/guides/dashboard/managing-teams). 1. Set a name for the API key. This field is customizable so you can remember the purpose of the API key you're creating. 2. Copy your secret key and save it in a confidential, secure place. 3. Add any domains you will use for testing and production to the domain list. 4. Optional: After creating a key, you can include a note to remind yourself where the key is stored (for example, "Stored as an environment variable in the payments service"). ## [Find your API keys](#find-your-api-keys) If you need to locate your API key, you can always find it in the [Moov Dashboard](https://dashboard.moov.io/developers/api). However, if your account doesn't have `admin` or `developer` permissions, you won't have access to view or create API keys. If you're unable to find your API key, you may want to request access from an administrator on your Moov account. API keys contain a public key and a secret key. The secret key cannot be viewed in Moov after the API key is created, so we recommend immediately storing it in a safe place. If you have lost your secret key, you should delete that API key and create a new one. ## [Deactivate API keys](#deactivate-api-keys) If your API key is compromised, delete it from the list of API keys in Moov. This will immediately ensure that the key cannot be used. You can then create a new key. --- URL: https://docs.moov.io/guides/get-started/data-migrations/ --- # Data migrations Learn how to securely migrate sensitive payment data from your previous payment processor. Before you can get started migrating data, you'll need to contact both [Moov](https://moov.io/contact/) and your previous provider. Moov suggests data is in CSV format - this ensures the smoothest process. Follow the steps below to start the process. ## [Get started migrating data](#get-started-migrating-data) To migrate your tokenized payment data to Moov, you'll need to: ### [Reach out to Moov](#reach-out-to-moov) Reach out to [Moov support](https://moov.io/contact/) to let us know that you'd like to migrate payment data from your previous provider to Moov. ### [Notify your previous provider](#notify-your-previous-provider) Notify your previous provider that you're migrating payment data to Moov. ### [Transfer encrypted data](#transfer-encrypted-data) Work with Moov and your previous provider to transfer the encrypted payment data. Once received, Moov will work with you to import the data into your Moov account. ### [Get the results](#get-the-results) Moov accepts a file that contains the mapping between the previous provider's token and the Moov tokens that you can use to update your system. Moov will work with you and your previous provider to receive the encrypted payment data. The original processor will need to use a PGP key provided by Moov to encrypt data before transmitting it to Moov. ## [PGP migration key](#pgp-migration-key) Pretty Good Privacy (PGP) is an encryption system used for encrypting sensitive files and sending them securely between parties. Payment data must be encrypted using Moov's public key (shown in the table below) before it can be sent to Moov. Ask your previous provider to use this key to encrypt the payment data. After you've imported Moov's key, run the following command: `gpg --encrypt --recipient 75FEA050F91F3B0A FILENAME` If you have questions or issues regarding usage of this key, please [contact Moov](https://support.moov.io/). | | | |-------------|-----------------------------------------------------| | KeyID | `75FEA050F91F3B0A` | | Key type | RSA | | Key size | 4096 | | Fingerprint | `CA4D F5E9 07C5 6DF8 3508 E6F5 75FE A050 F91F 3B0A` | | User ID | Moov `` | ```fallback -----BEGIN PGP PUBLIC KEY BLOCK----- mQINBGRIHk4BEAC38IZ2wkvSrg42dlVJYA59OMFxgQh3z6G+wIxok/ZsVMg4xD9V dTeMnhSiWW3bj89vHrSiytHB8kJggNUjLI4t2RY4Y30+hCIJhIcuZG1NsXVJJmA6 Hd3h19+6eidwpTCxP+iAlBx6Xh/N20IIRTMm1eF94eF+P6yQe2pmQu6p485tLtjV hD/jxrkfu+Wh2UJOnGbT/EE7GpdZEAfpARo/cURLrtO976pMnHckDtRhC/3bjLcq WPUYMlJK+2snsaQRBmUw2ZssNhQhgtTAkIX0nhHrrGWmoS4W9JiQRU7SrB7/e8lZ ZcfS6afDOgrtNJkhCViOylLZgKCe4d0RbfLXV1KkvzMzWXPL9xvg2xJV+RVi39lL f+lhDeP4BDu4sWsF+Ws3hYx7bcZ+G5qBpEVHmAXQCeuQXkobwIfn/35zBS1/6WXa ZOZNqLV4MQkCJ0AACV3WF4oDI2Q4G4qMWTdxHLOOmEU7lD82t7oWhrugBRbTQIAD /cTiDJdCnXSJEOuTVAKDOx1bKMHBXnHGjiJ1ql+zSRNc0CKeKXs/bygVUkcgGPNE ojnBEcQupbvgxrCw9DIfIp7wB58XhIFgVydDgm7REc1e5TPa6mLMbNIEYryN5sNG MCE7bsoTvJghyXSQu40Km4rMngFuzl0eomg0HL2GlxHfRccB8bHpo8brkwARAQAB tBZNb292IDxzdXBwb3J0QG1vb3YuaW8+iQJXBBMBCABBFiEEyk316QfFbfg1COb1 df6gUPkfOwoFAmRIHk4CGw0FCQeEzgAFCwkIBwICIgIGFQoJCAsCBBYCAwECHgcC F4AACgkQdf6gUPkfOwq2Ew//ddFG5MA/vutCBoPNaUe2CfSeqqwiVuJtycwJGUGx B3EYqWIvFRRhyOxA/bSiWdtdkDVU9QZ43uMNtTCodIDxJI1Vtl100yNl1A1i1PFN jZ+4bpA2KE281Wd4OmWoyXVLLgg6IGjWlRZxrMu6NmdfzuNdOpal7GrpoZDNXxXq XzalZhcJf1P5qh/NP538TfA8C45D9LuxCaVwixL6afXkISEAD43Z0pZTbxuj66oR ni8hH5PRILjEyCQup0qSgNR3AtfkCne2Zj+AlBSiupcGEg5WID0DKgENYPAO32vM w1xy1AtrKi8TSuMflTSFJ9/UCvRHvN4UILx3O7WPcD+06NTIgPm6FcF6CoYbmK88 m5ONH3LXAltBQ+E+WhgPXBkBdlFFfaiWc6qoAJbMHDJWw9oA+D2TH7poH0NYViRH 8szpVjuj4BhWdAqNM0JXAMA7WanEUfpBVHVHhZLK537fHzebhs2pyEyzizhmRqRb Dde0K1cpqbICc1HqUYXyOo7RsxmxBLRfjHoVYYA90eAynSwxrF6FdLOPotAy8T6Q IJJ/0+voFmJQhL8htDSygVzBudyt3M9FK0Rw39pgLG1MG1fQqOaUJtpNeLRsxGS6 F7Tio6pFKJuaOulSfLTXVbvd+KIR0LaWZXevwEzfxH4rF0myUEvuMliPXkO9vfKg A5U= =Aah+ -----END PGP PUBLIC KEY BLOCK----- ``` --- URL: https://docs.moov.io/guides/get-started/glossary/ --- # Glossary You don't have to be a payments expert to integrate with Moov. Here's an overview of some key terms and concepts, so you can get started. ## [Accounts](#accounts) **Accounts** represents a legal entity, and describe the account holder. An account can be created by an individual or a business, and can be linked to other Moov accounts. Within our guides and the API docs, you might see more specific terms to describe accounts. An account may be referenced by any of the following terms: ### [Partner account](#partner-account) A partner account is a contracted business entity that uses Moov's platform to facilitate a transfer solution for merchants and connected accounts. ### [Merchant account](#merchant-account) A merchant is a business entity that can accept transfers. A merchant is connected to Moov through a parent Moov account, also known as a partner account. A merchant can also be a connected account. ### [Owner account](#owner-account) An owner account is the account that initiates specific events on Moov's platform, such as creating a payment link. The owner account of such an event can be either the partner account or the merchant account. **Only the owner can update the event.** For example, if a merchant creates a payment link, only the merchant can update the payment link. If a partner account tries to update a merchant created payment link, they will receive an error. You can use the `ownerAccountID` to verify ownership by comparing it with a `partnerAccountID` or `merchantAccountID`. ### [Connected account](#connected-account) A connected account is any account that is linked to another Moov account. A connected account can be a business or an individual account. [Read more](/guides/accounts/) [Account types](/guides/accounts/account-types/) * * * ## [Business representatives](#business-representatives) A **business representative** is someone with beneficial ownership (≥25% ownership) or significant control over a business entity. Moov must verify business representatives before enabling payment capabilities for a business account. There are two types: control officers and beneficial owners. [Read more](/guides/accounts/requirements/business-representatives/) * * * ## [Capabilities](#capabilities) **Capabilities** determine what each Moov account can do, such as receiving transfers, or sending money to others. For risk and fraud protection purposes, we require detailed information when requesting capabilities. For example, we'll request more details if an account wants to collect funds than we would for an account receiving funds. - [Transfers](/guides/accounts/capabilities/reference/#transfers): Participation in any Moov transfer - [Wallet](/guides/accounts/capabilities/reference/#wallet): Store funds with Moov - [Send funds](/guides/accounts/capabilities/reference/#send-funds): Send funds to another account - [Collect funds](/guides/accounts/capabilities/reference/#collect-funds) (Business accounts only): Collect funds from another account [Read more](/guides/accounts/capabilities/) [Capabilities](/moovjs/accounts/capabilities/) * * * ## [Dashboard](#dashboard) The Moov **Dashboard** is an online portal that gives you the ability to create and manage Moov accounts and settings. [Read more](/guides/dashboard/) * * * ## [Facilitator fees](#facilitator-fees) A **facilitator fee** is a way for you, as a platform partner, to monetize payment flows when creating a transfer. [Read more](/guides/money-movement/fees/) * * * ## [Foreign ID](#foreign-id) A `foreignID` is an optional field when creating or updating an account. The foreign ID allows you to provide a unique alias which links an account in your system to a Moov account. For example, you can use an account ID that exists in your system as the foreign ID in our system to reference that account. A foreign ID must be unique to each account. * * * ## [Funding sources](#funding-sources) A **funding source** is a bank account, payment card, or wallet that is linked to a Moov account. [Read more](/guides/sources/) * * * ## [Idempotency](#idempotency) Idempotency is a property where an action will result in the same outcome, regardless of how many times you run that action. In payments, idempotency is particularly important because it eliminates the risk of accidentally charging someone twice. [Read more](/guides/money-movement/idempotency/) * * * ## [Payment methods](#payment-methods) **Payment methods** represent all the ways an account can move funds to another Moov account. The payment methods available for a given Moov account depend on the linked funding source and the capabilities of that account. For example, if your account doesn't have a linked bank account, the only payment method available to you would be the [Moov wallet](#wallets). Once you've added a bank account or card and it's verified, your account will automatically update with the new payment methods available to you. [Read more](/guides/money-movement/payment-methods/) [Payment methods](/moovjs/sources/payment-methods) * * * ## [Scopes](#scopes) Specify **scopes** to generate an authentication token to use with a specific set of Moov endpoints via Moov.js or any client-side integration. Some scopes are not restricted to a single account, while other scopes require an accountID before generating a token. You may need to generate multiple tokens depending on the task. Our authentication flow follows the OAuth 2.0 standard. [Read more](/api/authentication/scopes/) [OAuth 2.0](/api/authentication/access-tokens/create/) * * * ## [Transfers](#transfers) **Transfers** are how money moves through our platform. You can transfer money from one Moov account to another, or your Moov wallet to your linked bank account. Every transfer has a **source** (where the money originates from) and a **destination** (where the money goes). To orchestrate a transfer, Moov needs just four pieces of information: - Source payment method - Destination payment method - Amount - Brief description To receive a list of all possible payment methods available for a transfer, provide the two accounts you're moving money between, and the transfer amount. [Read more](/guides/money-movement/) * * * ## [Wallets](#wallets) A **wallet** stores funds and can be requested for every Moov account. With a wallet, you have more flexibility for when and how to move funds. You can achieve faster payouts with a wallet as a funding source. Additionally, you can: - Transfer funds from one Moov wallet to a different Moov wallet - Transfer funds out of your Moov wallet to your bank account - Add money from your bank account to your Moov wallet [Read more](/guides/sources/wallets/) [Wallet](/moovjs/sources/wallets) * * * Visit the [Moov dictionary](https://moov.io/resources/dictionary/) for a comprehensive overview of industry terms. --- URL: https://docs.moov.io/guides/get-started/ --- # Get started Get started moving fake money with test mode, and real money with production mode. Once you've [created an account](https://dashboard.moov.io/signup), you'll start out in test mode, where we've pre-loaded sample account and business information you can use to start exploring the platform. If you want to move real money, [contact us](https://moov.io/contact/) to start the verification process and select a fee plan. ## [Build modes](#build-modes) Moov provides two build modes: test mode and production mode. Test mode is for trying things out, experimenting, and of course, mistakes. Whether you're already a customer, or you want to get to know the platform before making any commitments, test mode is for trying out existing and new features in a no-risk environment. Production mode is for customers who are ready to move real money. Use the guides below to create API keys and familiarize yourself with how test mode and production mode work. You also have the ability to securely migrate payment data to Moov from other processors. Be sure to swap out the account ID anywhere it's hard coded before switching from test mode to production mode. ## [MCP & AI integrations](#mcp--ai-integrations) Use Moov's TypeScript SDK as an MCP server to build AI integrations which can search Moov's documentation and complete tasks via Moov's API and Dashboard. Visit the [MCP and AI](/guides/developer-tools/mcp-ai/) developer tools for more information. --- URL: https://docs.moov.io/guides/get-started/integration-options/ --- # Integration & onboarding Explore integration and onboarding options depending on your use case and money movement workflow. You can tailor the components of your integration to your particular needs. For example, you may use a Moov Drop for one portion of your workflow and connect directly to the API for another portion of your workflow. There are a variety of both technical and business-related factors that may influence how you choose to integrate, including: - The structure of your integration with your previous provider - The level of customization your integration requires to maintain the look and feel of your user flow - The nature of transfers on your platform (e.g., repeat versus one time customers, what payment rails your customers tend to use) - How your business handles reporting and billing based on payment data - Whether or not your business is equipped to handle sensitive data For specific guidance on setting up an integration that fits your business, [contact us](https://moov.io/contact/). Note that our [authentication protocol](/api/authentication/api-authentication) is different depending on how you are integrating. We require API keys for server side integrations, while client-side integrations like Moov.js and Moov Drops use [OAuth2 access tokens](/api/authentication/scopes/). ## [MCP & AI integrations](#mcp--ai-integrations) Visit the [MCP and AI](/guides/developer-tools/mcp-ai/) developer tools for more information on how to use Moov's TypeScript SDK to search our documentation and complete tasks via the API and Dashboard. ## [Moov.js](#moovjs) If you choose not to use Moov's [hosted onboarding](/guides/accounts/hosted-onboarding/) process for merchant accounts, note that Moov.js is required to use our [terms of service](/moovjs/drops/terms-of-service/) Drop. | PCI compliance | Customization | Development scope | |----------------|---------------|--------------------------------------------------------------------------------| | Not required | Low to medium | Employ a frontend library with the option to use pre-built UI Drop components. | View the [Moov.js](/moovjs/) documentation. ### [Drops](#drops) | PCI compliance | Customization | Development scope | |----------------|---------------|---------------------------------------------------------------| | Not required | Low | Pre-built, but customizable, UI components. Requires Moov.js. | View the [Drops](/moovjs/drops/) documentation. ## [API](#api) | PCI compliance | Customization | Development scope | |----------------|---------------|-------------------------------------------------------------------| | Required | High | Write integration code from scratch, or use our server-side SDKs. | View the [API](/api/) reference. ### [Server-side SDK](#server-side-sdk) | PCI compliance | Customization | Development scope | |----------------|----------------|-------------------------------------------| | Required | Medium to high | Server-side environment for the Moov API. | [View Moov SDKs](/sdks) ## [Onboard merchant options](#onboard-merchant-options) While there are multiple options to onboard merchant accounts, we suggest you send merchants a secure link to create their account through Moov's [hosted onboarding](/guides/accounts/hosted-onboarding/) process. You select the capabilities, pre-fill existing data, choose a pricing plan, and send them a link to finish the application and agree to the terms. See our [accounts](/guides/accounts/) documentation for more details on business and individual requirements. To onboard merchants outside of our hosted onboarding process, you must use the [terms of service Drop](/moovjs/drops/terms-of-service/) to collect terms of service acceptance for accounts. To use the terms of service Drop, you will need to install [Moov.js](/moovjs/). View the create accounts `POST` [endpoint](/api/moov-accounts/accounts/create/) for more information on creating accounts through our API. | Method | Requirements | Customization | |----------------------------------------------------------|------------------------------------------------|---------------| | [Hosted onboarding](/guides/accounts/hosted-onboarding/) | A Moov account | Low | | [Moov Drops](/moovjs/drops/onboarding/) | A Moov account, Moov.js, terms of service Drop | Low to medium | | [API](/api/moov-accounts/accounts/create/) | A Moov account, Moov.js, terms of service Drop | High | --- URL: https://docs.moov.io/guides/get-started/launch-checklist/ --- # Launch checklist Use this list of recommended steps to help you get ready to go live with Moov. We've compiled a list of steps for getting ready to launch your integration with Moov. Depending on the specifics of your money movement use case, some of the steps may not be necessary. If you have questions particular to your integration, reach out to [Moov](https://support.moov.io/). To be approved for a production account to move real money, you'll need to sign a contract and set up a fee plan with Moov. [Contact us](https://moov.io/contact/) for more information and to get the verification process started. ## [Get your Moov account](#get-your-moov-account) When you sign up for a Dashboard account, you'll immediately start out with a test account. You can start inviting team members to your account and interact with Moov's platform in test mode. - [Sign up](https://dashboard.moov.io/signup) for a Dashboard account - Create test [accounts](/guides/dashboard/accounts/) in the dashboard and [transfer funds](/guides/dashboard/transfers/all-transfers/) - Optional: Give administrator or developer [permissions](/guides/dashboard/settings/members/#roles) to your team members and invite them ## [Configure your account](#configure-your-account) - Generate [API keys](/guides/get-started/api-keys/) in production (note that your test mode API keys will not work in production) - Create [webhooks](/guides/webhooks/) to subscribe to event notifications ## [Authenticate](#authenticate) If you're using Moov.js or any client-side integration, you'll need to follow these steps as a part of the OAuth2 authentication flow: - Specify [scopes](/api/authentication/scopes/) - Generate an [access token](/api/authentication/access-tokens/create/) For server-to-server integrations, you can simply use your public API key and secret API key with Basic authentication: - Set the Authorization header to Basic where `credentials` is the Base64 encoding of public key and private key joined by a single colon : ## [Set up users](#set-up-users) Every individual or business you're sending or receiving payments with will need an account connected. - [Create accounts](/guides/accounts/create-accounts/) for users/merchants. We suggest using our [hosted onboarding](/guides/accounts/hosted-onboarding/) process when available. - Link cards with the [card link Drop](/moovjs/drops/card-link/) or [via the Moov API\*](/api/sources/cards/create/). - Link and verify [bank accounts](/guides/sources/bank-accounts/) via the API - Optional: Set up instant account verification with [Plaid](/guides/sources/bank-accounts/verification/plaid/) or [MX](/guides/sources/bank-accounts/verification/mx/) - Understand which [payment methods](/guides/money-movement/payment-methods/) you'll use \*In order to link cards directly through the API, you must provide Moov an attestation of PCI compliance. ## [Create Transfers](#create-transfers) Test Mode allows you to integrate with all of Moov's API and features without moving real money. - Create [transfers](/guides/money-movement/) - Fund a [wallet](/guides/money-movement/wallets/funding/) - Push funds to a [card](/guides/money-movement/send-payments/push-to-card/) - Sends funds to an [bank account instantly](/guides/money-movement/send-payments/rtp/) - Transfer [Account to Account](/guides/money-movement/send-payments/send-funds/) - Handle [transfer responses](/guides/money-movement/events-and-statuses/#transfer-responses) ## [Move to production](#move-to-production) In order to move real money you must switch to production. To move to production, you need to complete your business profile, add business representatives, and submit underwriting information to Moov. - Review the [requirements for production](/guides/accounts/requirements/) - Switch to [production mode](/guides/get-started/production-mode/) in the upper left hand corner of the Dashboard - Set [business representatives](/guides/accounts/requirements/business-representatives/) and submit required [underwriting](/guides/accounts/requirements/underwriting/) documents to Moov - Optional: [Migrate data](/guides/get-started/data-migrations/) into Moov --- URL: https://docs.moov.io/guides/get-started/production-mode/ --- # Production mode Switch to production mode and start moving real money. Every Moov account will receive one test account and one production account. In the [Moov Dashboard](https://dashboard.moov.io/), navigate to the account switcher in the top left corner and find your production account. Before you move real money, make sure you've familiarized yourself with Moov's platform in [test mode](/guides/get-started/test-mode/). Before you can move real money, you'll need to [contact Moov](https://moov.io/contact/) to start the verification and underwriting process. ## [Verification](#verification) Accounts require Know Your Customer (KYC) / Know Your Business (KYB) verification. Verification will automatically take place for accounts that have requested the `wallet` or `send-funds` capability. Each capability will have a status denoting where it is in the process: - **Pending** - Waiting on information from the account holder. - **Needs review** - Waiting on a manual review from Moov. There are some verification scenarios that may require further action on your part: - Address cannot be resolved to the individual: Enter the correct data for the business representative or individual, or, if the data is correct, provide a document with proof of address and upload it to your account. Acceptable documents include a driver's license, utility bill, or bank statement. - No secretary of state filings or inactive status: Upload a document with proof of incorporation. - Business TIN does not match the name: Upload a document proving the business’ legal name (not doing business as). ## [Underwriting](#underwriting) In addition to verification, productions accounts with the `collect-funds` capability will require underwriting. Moov will request a recent processing statement to verify the following: - Do volume expectations map to what is indicated? - What is the ratio of chargebacks to sales? - What is the ratio of refunds to sales? In addition, Moov may request a bank statement to measure the solvency of the business: - Does the business name on the bank statement match the business name on file? - Does the bank account on the statement match the linked bank account? - Is it a recent bank account statement (previous 3 month period)? - What is the average daily balance and does the merchant have the funds to cover the expected chargeback and refund liability? For merchants with no processing history, Moov will set a low transaction velocity limit and will rely on a 90 day rolling average. ## [Pricing](#pricing) Your production account will not be fully activated until your merchant fee pricing plan is set. See our [billing](/guides/billing/) section for more information. ## [Update account](#update-account) Once you're in production mode and ready to start building, make sure to: Switch out `accountID` anywhere in your code where `accountID` is hard coded - Generate new API keys - Set up new webhook URLs - Explore our [Quick start](/guides/quick-start) guide for starter code step by step instructions ## [Invite team members](#invite-team-members) While in production mode, you can [invite team members](/guides/dashboard/settings/members/) to your production account. Inviting team members to your production account *does not* enable them to use your test account. If you'd also like to invite team members to your test account, you will need to do that separately in test mode. --- URL: https://docs.moov.io/guides/get-started/test-mode/ --- # Test mode Simulate account and transfer scenarios on Moov’s platform without using real money. Moov has pre-populated your test account with sample business details and accounts. You aren't required to enter anything for your test account to receive the `verified` status. In test mode, requirements for all [capabilities](/guides/accounts/capabilities/) have been satisfied, so they are automatically enabled for you. You'll have full access to the following capabilities: - [Transfers](/guides/accounts/capabilities/enablement/#transfers) - [Wallet](/guides/accounts/capabilities/enablement/#wallet) - [Send funds](/guides/accounts/capabilities/enablement/#send-funds) - [Collect funds](/guides/accounts/capabilities/enablement/#collect-funds) While you don't need to request capabilities for test mode, for [production mode](/guides/get-started/production-mode/), you'll need to request capabilities. You can do this at the same time you create your account, or request additional capabilities later. ## [Switch to test mode](#switch-to-test-mode) After you've completed your business profile and Moov has approved your production account, you can switch between production and test mode in the Moov Dashboard by using the **Account** dropdown in the upper left hand corner. ![Toggle for test account in Moov Dashboard](../../shared-images/mode-toggle.png) ## [Invite team members](#invite-team-members) While in test mode, you can [invite team members](/guides/dashboard/settings/members/) to your test account. Inviting team members to your test account *does not* enable them to use your production account. If you'd also like to invite team members to your production account, you will need to do that separately in production mode. ## [API keys](#api-keys) You will need to create an API key specific to the test account. We suggest naming the API key something that will help you remember that it's for testing purposes. You can use localhost, ngrok, Netlify, or Vercel domains for these keys. ## [Name verification](#name-verification) The card link `POST` [endpoint](/api/sources/cards/create/) and `PATCH` [endpoint](/api/sources/cards/update/) offer an optional `verifyName` field, which uses Visa's [ANI verification](https://usa.visa.com/content/dam/VCOM/regional/na/us/support-legal/documents/account-name-inquiry-onesheet-merchant-version.pdf) as a check against the supplied `holderName`. You can test the various results by entering the following combinations of correct and incorrect names in the `holderName` field. *Correct name: Alex Nora Irwin* | Name entered | Individual name check | Full name check | |--------------------|--------------------------------------|-----------------| | "Alex Nora Irwin" | `match`, `match`, `match` | `match` | | "Alex Noraa Irwin" | `match`, `partialMatch`, `match` | `match` | | "Alx Nora Irwin" | `partialMatch`, `match`, `match` | `match` | | "Alex Irwin" | `match`, `notChecked`, `match` | `match` | | "Irwin" | `notChecked`, `notChecked`, `match` | `match` | | "Alex Nor Irwin" | `match`, `noMatch`, `match` | `partialMatch` | | "Axely Nora Irwin" | `noMatch`, `match`, `match` | `partialMatch` | | "A N Irwi" | `noMatch`, `noMatch`, `partialMatch` | `noMatch` | | "Alex Notwin" | `match`, `notChecked`, `noMatch` | `noMatch` | | "Alex Notwin" | `match`, `notChecked`, `noMatch` | `noMatch` | If ANI is not supported, you'll receive `unavailable` for all results. ## [Transfers](#transfers) Transfers in test mode won't move any real money. For the timing of transfers in test mode, note that: - Wallet to wallet transfers complete almost instantly - ACH transfers in test mode will complete in about an hour (see the [processing speed](/guides/money-movement/accept-payments/ach/ach-processing-speeds/) guide for production mode) If you would like to see how Moov handles failures in production, view the [transfer failures](/guides/money-movement/events-and-statuses/) guide. To simulate card transfers and transfer scenarios, like disputes, use the test cards and other specific data listed in the following sections. Use the test cards with the create a transfer `POST` [endpoint](/api/money-movement/transfers/create/), using any amount, unless otherwise specified. American Express transfers need to be a minimum of $1. In production mode, American Express transfers less than $1 will result in an error. ## [Link cards for card acceptance](#link-cards-for-card-acceptance) Before you can use test cards in transfer scenarios, you will have to link them to your test account. Use the link a card `POST` [endpoint](/api/sources/cards/create/). Enter any of the test card numbers, provide any three numbers for the CVV (four for American Express), any five numbers for the postal code, and any future date for the expiration. Note that a test card will expire once the expiration date you have chosen has passed. These test cards are only for simulating card payments. For push-to-card and pull-from-card, see the [push and pull test cards](#push-to-card--pull-from-card) section. | Card brand | Test card number | CVV | Postal code | Expiration date | |------------------|--------------------|---------------|---------------|-----------------| | Visa | `4111111111111111` | Any 3 numbers | Any 5 numbers | Any future date | | Mastercard | `5555555555554444` | Any 3 numbers | Any 5 numbers | Any future date | | Discover | `6011111111111117` | Any 3 numbers | Any 5 numbers | Any future date | | American Express | `371111111111114` | Any 4 numbers | Any 5 numbers | Any future date | Additionally, you can enter specific postal codes or CVVs to test verification scenarios. See the sections below for details. ### [Postal code verification](#postal-code-verification) If you want to test postal code verification scenarios when linking a card, you can use the card numbers [above](#link-cards-for-card-acceptance) along with the following postal codes. | Card brand | Verification result | Postal code | |-----------------|---------------------|-------------| | All card brands | `match` | 11111 | | All card brands | `noMatch` | 22222 | | Visa, Discover | `notChecked` | 88888 | | All card brands | `unavailable` | 99999 | ### [CVV verification](#cvv-verification) If you want to test CVV verification scenarios when linking a card, you can use the card numbers [above](#link-cards-for-card-acceptance) along with the following CVV codes. | Card brand | Verification result | CVV code | |----------------------------|---------------------|----------| | Visa, Mastercard, Discover | `match` | 111 | | American Express | `match` | 1111 | | Visa, Mastercard, Discover | `noMatch` | 222 | | American Express | `noMatch` | 2222 | | Visa, Mastercard, Discover | `notChecked` | 888 | | American Express | `notChecked` | 8888 | | Visa, Mastercard, Discover | `unavailable` | 999 | | American Express | `unavailable` | 9999 | ## [Declined card transfers](#declined-card-transfers) To simulate a declined `card-payment` transfer, use the following card numbers when [creating a transfer](/api/money-movement/transfers/create/). The **expiration date** field for all test cards can be set to any future date. | Card brand | Test card number | CVV | |------------------|--------------------|---------------| | Visa | `4000020000000000` | Any 3 numbers | | Mastercard | `5555000022220022` | Any 3 numbers | | Discover | `6011000022220002` | Any 3 numbers | | American Express | `3711000022220002` | Any 4 numbers | ## [Tap to Pay on mobile](#tap-to-pay-on-mobile) Test mode allows you to verify your Tap to Pay integration on iOS and Android before processing live payments. The terminal configuration fetched from the Moov API determines whether the SDK operates in test or production mode. When using a test configuration, the SDK will simulate card tap scenarios. The following test cards are available: | Card brand | Test card number | Result | |------------------|--------------------|----------| | Visa | `4111111111111111` | Approved | | Mastercard | `5555555555554444` | Approved | | Discover | `6011111111111117` | Approved | | American Express | `371111111111114` | Approved | | Visa | `4000020000000000` | Declined | | Mastercard | `5555000022220022` | Declined | | Discover | `6011000022220002` | Declined | | American Express | `3711000022220002` | Declined | Note that when testing Tap to Pay on mobile with test cards, you are not required to enter a CVV, expiration date, or postal code. For platform-specific details on using test mode with Tap to Pay, refer to the SDK documentation: - [Tap to Pay on iPhone](https://moovfinancial.github.io/moov-ios/documentation/moovkit/test-mode) - [Tap to Pay on Android](/guides/money-movement/accept-payments/card-acceptance/tap-to-pay-android/) ## [Disputes](#disputes) To simulate disputes, use the card numbers below when [creating a transfer](/api/money-movement/transfers/create/). The expiration date can be any future date. CVV can be any 4 numbers for Amex and any 3 numbers for all other card brands. | Card brand | Test card number | Phase | Reason code | |-----------------------------|--------------------|------------|-------------| | Visa | `4000200020002000` | Chargeback | 10.4 | | Visa - Pull from card | `4111100010003008` | Chargeback | 10.4 | | Mastercard | `5555444400004444` | Chargeback | 4860 | | Mastercard - Pull from card | `5555555555553339` | Chargeback | 4860 | | Discover | `6011222222220000` | Chargeback | 05 | | American Express | `371010002000123` | Chargeback | F29 | | American Express | `372020002000188` | Inquiry | 21 | To simulate winning or losing a dispute, you can upload winning or losing **text** evidence to the disputes text `POST` [endpoint](/api/money-movement/disputes/post-text/) (if you submit file evidence, the dispute status will remain `under-review`). The following outcomes can be simulated by entering "winning" or "losing" text evidence: | Text evidence | Phase | Outcome | |--------------------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------| | `winning-evidence` | `chargeback` | Dispute will enter an `under-review` status for 10 minutes before updating to `status: won`. The chargeback is reversed and funds are credited to the merchant. | | `winning-evidence` | `inquiry` | Dispute will enter an `under-review` status for 10 minutes before updating to `status: closed`. | | `losing-evidence` | `chargeback` | Dispute will enter an `under-review` status for 10 minutes before updating to `status: lost`. | | `losing-evidence` | `inquiry` | Dispute will enter an `under-review` status for 10 minutes before updating to `status: response-needed`. | ## [Push to card & pull from card](#push-to-card--pull-from-card) Use the test cards in the table below to simulate the following: - [Push to card](/guides/money-movement/send-payments/push-to-card/) transfer generating `fast-funds` payment method - [Pull from card](/guides/money-movement/accept-payments/pull-from-card/) transfer generating `supported` payment method | Card brand | Completed transfer | Failed transfer | |------------|--------------------|--------------------| | Visa | `4111100010002000` | `4111100050007000` | | Mastercard | `5200828282828210` | `5200821111111114` | The expiration date can be any future date. CVV can be any 3 numbers for Visa and Mastercard. Since push & pull card transfers require verifications, test cards will always return a successful match for CVV, postal code, and (if requested) name verification, regardless of the values provided. To test negative verification results, use the test values provided for [CVV verification](#cvv-verification), [postal code verification](#postal-code-verification), and [name verification](#name-verification). ## [RTP](#rtp) To simulate an RTP transfer in test mode, [create a transfer](/api/money-movement/transfers/create/) with `moov-wallet` as the source payment method and `rtp-credit` as the destination. The `rtp-credit` payment method will only appear for bank accounts with routing numbers that are RTP eligible. Use `021000021` as an RTP-enabled routing number in test mode. You can also simulate various RTP failures and rejections by using these specific amounts listed below in your test mode transfers. Using these amounts will result in real time failures. Please note that these failures will result in the linked bank account entering an errored state. | Transfer amount | Failure type | |-----------------|--------------------------| | $72.03 | `AC03` / invalid-account | | $72.04 | `AC04` / account-closed | | $72.06 | `AC06` / account-blocked | If you would prefer to use the API to simulate a failure, you can trigger the RTP failure in test mode by entering any of the return amount codes as the `value`. For example, if you wanted to simulate an invalid account, enter `7703` as the `value`. ```json { "amount": { "currency": "USD", "value": 7703 }, "facilitatorFee": { "total": 0 } } ``` ## [ACH returns](#ach-returns) You can simulate a few ACH return scenarios during different transfer stages. Trigger ACH returns in test mode by entering any of the return amount codes listed below as the `value` when [creating a transfer](/api/money-movement/transfers/create/). For example, if you wanted to simulate insufficient funds, enter `5501` as the `value`. | Trigger Amount | Return Code | Description | Simulation Stage | |----------------|-------------|------------------------------------|---------------------------------| | $55.01 | `R01` | Insufficient Funds | Debit originated, not completed | | $55.02 | `R02` | Account Closed | Debit originated, not completed | | $55.03 | `R03` | No Account / Unable to Locate | Credit completed | | $55.04 | `R04` | Invalid Account Number Structure | Credit completed | | $55.07 | `R07` | Authorization Revoked by Customer | Debit completed | | $55.08 | `R08` | Payment Stopped | Debit completed | | $55.09 | `R09` | Uncollected Funds | Debit originated, not completed | | $55.10 | `R10` | Customer Not Authorized | Debit completed | | $55.11 | `R11` | Entry Not in Accordance with Terms | Debit originated, not completed | | $55.15 | `R15` | Account Holder Deceased | Debit originated, not completed | | $55.16 | `R16` | Account Frozen | Debit originated, not completed | | $55.20 | `R20` | Non-Transaction Account | Debit originated, not completed | | $55.24 | `R24` | Duplicate Entry | Debit originated, not completed | | $55.29 | `R29` | Corporate Customer Not Authorized | Debit originated, not completed | ```json { "amount": { "currency": "USD", "value": 5501 }, "facilitatorFee": { "total": 0 } } ``` A return will be only triggered if the transfer type (for example, wallet-to-bank) is applicable to the particular return scenario and amount entered. For example, an `R01` in test mode always occurs on the debit leg, *after* the transfer stage of debit origination. Accordingly, an `R01` return cannot be triggered on a wallet-to-bank transfer, as that transfer type only consists of a credit leg. Creating a return scenario that does not apply to a corresponding transfer type will result in a regular test transfer, not a test return. Once you have created a transfer with an appropriate return code, Moov will update the transfer to `failed` or `reversed` based on the transfer stage (see [ACH returns and exceptions](/guides/money-movement/accept-payments/ach/returns/) for more information). The bank account status will also be updated accordingly. The ACH returns and exceptions guide also includes the full ACH [return code](/guides/money-movement/accept-payments/ach/returns/#return-codes) list. ## [Bank accounts](#bank-accounts) If you've created an account with the Moov Dashboard, we've already added test bank accounts on your behalf. If you'd like to add an additional test bank account, or you did not create an account through the Dashboard, you must include a valid routing number. For example: ```text 322271627 ``` The account number can be any number, for example: ```text 12345654321 ``` ### [Micro-deposit verification](#micro-deposit-verification) To simulate an [instant micro-deposit](/guides/sources/bank-accounts/verification/instant-micro-deposit/) verification in test mode, enter `0001` as the instant verification code. To simulate [traditional micro-deposit](/guides/sources/bank-accounts/verification/micro-deposits/) verification in test mode, enter `0` for both amounts: `[0,0]`, and the bank account verification will succeed. If you input any other amount, the bank account verification will not complete. ### [Plaid](#plaid) To test linking bank accounts with Plaid, simply pass `env: "sandbox"` into the payload in the [Moov.js initialization](/moovjs/sources/bank-accounts/plaid-link/). You can pass in any token as the processor token and Moov will link default account data that looks like the following: ```fallback RoutingNumber: "011401533", AccountNumber: "1111222233330000", AccountType: "checking", Mask: "0000" ``` --- URL: https://docs.moov.io/guides/get-started/ux-best-practices/ --- # UX/UI best practices Use the tips in this guide to ensure your custom onboarding UX/UI enables your customers to have a smooth onboarding experience. Moov requires very specific information for every account registered on our platform. Providing clear instructions in your custom onboarding experience ensures customers don't get stuck in the onboarding and verification process due to incomplete or missed information. * * * ## [Business onboarding](#business-onboarding) ### [Form shortening](#form-shortening) With a user's work email, use our [form shortening API](/api/enrichment/form-shortening/business/get/) to autofill the business name, website, address, phone, and industry fields. ### [Business logo](#business-logo) Business logos are automatically fetched from the business's website. You can fetch the image with the [avatar API](/api/enrichment/form-shortening/avatars/get/). ### [Business name](#business-name) Always provide additional context that a business name needs to be the *full legal business name* as it appears on their filing documents. This includes capitalization and punctuation. If the business is using a "Doing business as" name (DBA), you can allow users to enter the DBA name in the "Doing business as" field. Moov will use the DBA in most cases, but will still require the legal business name for verification. Legal business name This must match official documents exactly I use a registered DBA to conduct business. Doing business as ### [Business address](#business-address) Always provide additional context that business address must be the physical, commercial address where the business is located. The business address *cannot be any of the following*: - P.O. Box - Registered agent address - Mailing service Use [address autocomplete](/moovjs/enrichment/#autocomplete-address) to help users fill out the address fields and avoid mistakes. Business address Physical location where you conduct day to day business. P.O. Boxes, registered agents, and mailing services are not allowed. Street address Suite or floor (optional) City State SelectAlabamaAlaskaArizonaArkansasCaliforniaColoradoConnecticutDelawareDistrict Of ColumbiaFloridaGeorgiaHawaiiIdahoIllinoisIndianaIowaKansasKentuckyLouisianaMaineMarshall IslandsMarylandMassachusettsMichiganMinnesotaMississippiMissouriMontanaNebraskaNevadaNew HampshireNew JerseyNew MexicoNew YorkNorth CarolinaNorth DakotaOhioOklahomaOregonPennsylvaniaRhode IslandSouth CarolinaSouth DakotaTennesseeTexasUtahVermontVirginiaWashingtonWest VirginiaWisconsinWyomingAmerican SamoaGuamNorthern Mariana IslandsPuerto RicoUnited States Minor Outlying IslandsVirgin IslandsArmed Forces AmericasArmed Forces PacificArmed Forces EuropeArmed Forces Other Zip code ### [Industry selection](#industry-selection) List all industries that are available for selection in your custom onboarding UI. Use our [industry taxonomy](/api/enrichment/form-shortening/industries/get/) to get the list of industries and their corresponding MCC codes. ### [Business representatives](#business-representatives) Clearly indicate that users must add *all* owners with at least 25% ownership or more in the company and at least one control officer with significant management authority. In some instances, a control officer and an owner will be the same person. The maximum amount of business representatives you can enter is 7. Additionally, ensure that users confirm they have added *all* required business representatives before submitting their account to Moov for verification. Owners & officers Add all owners with at least a 25% stake in your company and one control officer. Control officers can be executives, senior managers, or anyone with significant management authority. [Learn more.](https://docs.moov.io/guides/accounts/requirements/business-representatives/) ![Visual of owner and officer modal.](../images/owner-modal.png) I certify, for my company, that I have provided all owners with 25% or greater ownership and one control officer with significant management authority. ### [Representative address](#representative-address) Always provide additional context that representative addresses must be their personal, residential address and cannot be a: - P.O. Box - Commercial address The most common mistake users make is using a commercial address for their personal address. Residential address Your physical residential address. P.O. Boxes, registered agents, and mailing services are not allowed. Street address Apartment, suite, or floor (optional) City State SelectAlabamaAlaskaArizonaArkansasCaliforniaColoradoConnecticutDelawareDistrict Of ColumbiaFloridaGeorgiaHawaiiIdahoIllinoisIndianaIowaKansasKentuckyLouisianaMaineMarshall IslandsMarylandMassachusettsMichiganMinnesotaMississippiMissouriMontanaNebraskaNevadaNew HampshireNew JerseyNew MexicoNew YorkNorth CarolinaNorth DakotaOhioOklahomaOregonPennsylvaniaRhode IslandSouth CarolinaSouth DakotaTennesseeTexasUtahVermontVirginiaWashingtonWest VirginiaWisconsinWyomingAmerican SamoaGuamNorthern Mariana IslandsPuerto RicoUnited States Minor Outlying IslandsVirgin IslandsArmed Forces AmericasArmed Forces PacificArmed Forces EuropeArmed Forces Other Zip code * * * ## [Date of birth](#date-of-birth) When capturing a date of birth, provide a placeholder than indicates the format of the date. Especially on mobile devices, ensure a default value is provided. The native iOS `DatePicker` component defaults to the current date and can't be set to a `nil` value without wrapping it in a custom component. * * * ## [Bank accounts](#bank-accounts) For both business and individual accounts, Moov will only accept bank accounts for financial institutions in the United States. Ensure this context is provided when a user is filling out the bank account field in a custom onboarding UI. Use [routing number lookup](/moovjs/institutions/) to show the institution name when a user enters a routing number, giving them confidence that the routing number is valid. You can pass a valid routing number to [avatar](/moovjs/enrichment/#get-avatar) to get the institution's logo. Routing number --- URL: https://docs.moov.io/guides/ --- # Guides Get the context and information you need to get up and running with Moov. Moov is a platform that enables unlimited money movement use cases in one integration. We’ve put together guides for each step of your journey with Moov. Our guides contain instructions, sample code, and context for understanding why and how our platform works the way it does. Read our glossary to learn about Moov concepts and see our integration options guide to learn what pathway best fits your use case. If you want to explore our frontend and backend integration options, view more detailed information below. To move real money, you'll need to [contact us](https://moov.io/contact/) to start the verification process and select a fee plan. [**Glossary** \ Check out the glossary and learn Moov concepts, so you can implement quickly.](/guides/get-started/glossary/) [**Integration options** \ Learn about the integration pathway that best fits your platform needs.](/guides/get-started/integration-options) * * * The Moov.js [terms of service Drop](/moovjs/drops/terms-of-service/) is required when collecting terms of service acceptance for accounts. Beyond that, you have several frontend and backend options, as well as access to our Dashboard, when building a full integration with Moov. ## [Frontend](#frontend) [**Moov Drops** \ Collection of pre-built UI components for embedding payments securely and quickly.](/moovjs/drops/) [**Moov.js** \ Browser side SDK for secure data collection. All PII goes directly to Moov instead of hitting your servers.](/moovjs/) ## [Backend](#backend) [**Moov API** \ The foundation for all our integration options. You have the option to connect directly to our API.](/api/) [**Postman collection** \ Explore a Postman collection with example calls to our API.](/guides/developer-tools/postman-collection/) [**Breaking changes** \ How Moov treats changes to the API.](/guides/developer-tools/breaking-changes-api/) [moovfinancial/ \ moov-dotnet](/sdks/dotnet/) [moovfinancial/ \ moov-go](/sdks/go/) [moovfinancial/ \ moov-java](/sdks/java/) [moovfinancial/ \ moov-php](/sdks/php/) [moovfinancial/ \ moov-python](/sdks/python/) [moovfinancial/ \ moov-ruby](/sdks/ruby/) [moovfinancial/ \ moov-android](/sdks/tap-to-pay-android/) [moovfinancial/ \ moov-ios](/sdks/tap-to-pay-iphone/) [moovfinancial/ \ moov-typescript](/sdks/typescript/) ## [Dashboard](#dashboard) [**Moov Dashboard** \ Use the Dashboard as an alternative to the API to manage accounts and settings, as well as complete a variety of transfer related tasks.](/guides/dashboard) --- URL: https://docs.moov.io/guides/issue-cards/ --- # Issue cards Learn about building your card program with Moov. \*Card issuing is currently in a closed beta. [Contact Moov](https://moov.io/contact/) for more information. Moov's card issuing solution allows you to create a card program and start issuing virtual cards. A Moov wallet can serve as a funding source for issuing virtual cards, which can then be used to spend funds from the wallet. Note that we currently only issue Visa cards. To learn more, read our how-to guide or explore the card issuing [endpoints](/api/money-movement/issuing). --- URL: https://docs.moov.io/guides/issue-cards/issuing-tutorial/ --- # Card issuing tutorial Follow this step by step guide to issue cards using our API or SDKs. \*Card issuing is currently in a closed beta. [Contact Moov](https://moov.io/contact/) for more information. Moov enables you to instantly issue virtual cards on the Visa network, empowering a broad range of embedded spending and expense management solutions such as: - Replacing traditional checks for bill payments - Providing rapid access to funds from merchant processing - Facilitating immediate payments to vendors ## [Key players](#key-players) For the purposes of this guide, we’ll assume you are a developer building a platform with the following players: - Your Moov account: Your platform that enables your customers to accept payments and use those funds for business-related purchases - Customer: Any business that will utilize the virtual card to make payments using funds from its Moov wallet ## [Prerequisites](#prerequisites) This guide assumes that you have onboarded your business customers. To learn more about onboarding, read our hosted onboarding guide. We also assume that your customer's Moov wallet has already been funded with a balance. This can be accomplished through: - A bank-to-wallet transfer - Funds that have accumulated in your wallet from accepting card payments Read our [wallets guide](/guides/money-movement/wallets/funding/) for more information on funding a wallet. Your customer's Moov wallet will be used as the funds source for the issued card. ## [Request a virtual card](#request-a-virtual-card) After successfully onboarding and verifying your customer's business, you can proceed to request a virtual card through the [Moov API](/api/money-movement/issuing/create/). This card can then be used by the customer for various business transactions. ### [Request parameters](#request-parameters) To issue a virtual card, you will need to submit the following parameters: | Parameter | Description | |-------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `fundingWalletID` | The unique identifier for the Moov wallet associated with the customer account, ensuring the card is correctly linked to the funds source. | | `formFactor` | Currently, Moov only supports "virtual" cards. This parameter specifies the type of card being issued. | | `authorizedUser` | Moov requires the first and last names of the card user to comply with regulatory requirements. Optionally, include the user's birthdate to enhance the accuracy of identity verification and reduce potential false positives during regulatory screenings. | | `expiration` (optional) | Set the card's expiration date (1 to 24 months in the future). If not provided, it defaults to 24 months from the date of issuance. | | `controls` (optional) | Indicate that the card should be single use or apply a maximum per-transaction amount limit. | ```zsh curl -X POST "https://api.moov.io/issuing/{accountID}/issued-cards" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "authorizedUser": { "firstName": "George", "lastName": "Glass", "birthDate": { "day": 29, "month": 4, "year": 1958 } }, "fundingWalletID": "string", "formFactor": "virtual", "memo": "supplies purchase", "expiration": { "month": "01", "year": "25" }, "controls": { "singleUse": false, "velocityLimits" : [ { "amount": 1000, "interval": "per-transaction" } ] } }'\ ``` Once the virtual card has been issued, the customer can then use the card to make purchases within the amount of their wallet balance. ### [Optional card controls](#optional-card-controls) You can limit the usage of an issued card by setting controls in the card creation request. Controls can only be applied during the initial card creation. The following controls are currently supported: - `singleUse`: If true, the card closes after the first successful authorization. - `velocityLimits`: Sets spending limits per time interval. Currently, only per-transaction limits are supported. The following example demonstrates a card configured to close after the first successful authorization (`singleUse`) and enforces a per-transaction spending limit of $50.00. ```JSON { "controls": { "singleUse": true, "velocityLimits": [ { "amount": 5000, // $50.00 "interval": "per-transaction" } ] } } ``` ### [Authorized user screening](#authorized-user-screening) To comply with anti-money laundering (AML) regulations, Moov conducts regulatory screenings as part of the card issuing process. If the screening flags a potential match on regulatory watch lists, the card will enter the `pending-verification` state in the response from the initial create a spending card POST [endpoint](/api/money-movement/issuing/create/). To address this, you can submit the `authorizedUser.birthDate` through the update a spending card PATCH [endpoint](/api/money-movement/issuing/update/) if not initially provided, to help clear any discrepancies. ## [View and use card details](#view-and-use-card-details) Once an issued card is in an active state, your customer can securely access the full PCI-compliant card details for making transactions through the [Issued card Drop](/moovjs/drops/issued-card/), a secure interface for displaying sensitive card information. ```javascript // Card issuing Moov Drop const issuedCard = document.querySelector("moov-issued-card"); // After generating a token, set it on the issued card element issuedCard.oauthToken = "some-generated-token"; // Include the accountID of the Moov account to which the card was issued and the ID of the issued card to display issuedCard.accountID = "account-id"; issuedCard.issuedCardID = "card-id"; ``` ## [View issued card authorizations](#view-issued-card-authorizations) Each time a card is used to make a purchase from a merchant, Moov processes the authorization request in real time. The outcomes of these requests can be tracked through the [card authorization](/api/money-movement/issuing/list-authorizations/) API. ```zsh curl -X GET "https://api.moov.io/issuing/{accountID}/authorizations" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "issuedCardID": "string", "startDateTime": "string", "endDateTime": "string", "statuses": {"pending", "cleared"}, "count": "string", "skip": "integer" } }'\ ``` Below we show an example of the card authorization `LIST` response: ```JSON [ { "authorizationID": "ec7e1848-dc80-4ab0-8827-dd7fc0737b43", "authorizedAmount": "-14.89", "cardTransactions": [], "createdOn": "2024-08-24T14:15:22Z", "fundingWalletID": "ec7e1848-dc80-4ab0-8827-dd7fc0737b43", "issuedCardID": "ec7e1848-dc80-4ab0-8827-dd7fc0737b43", "merchantData": { "city": "San Francisco", "country": "US", "mcc": "7298", "name": "Whole Body Fitness", "networkID": "1234567890", "postalCode": "94107", "state": "CA" }, "network": "visa", "status": "pending" } ] ``` ## [View completed card transactions](#view-completed-card-transactions) When a pending authorization is successfully captured and funds have settled, a card transaction resource is created. This indicates that the funds related to that transaction have been moved. We retain details from the original authorization for reconciliation and tracking purposes. You can list all card transactions associated with a particular Moov account by using the list card transactions `GET` [endpoint](/api/money-movement/issuing/list-card-transactions/) as shown below: ```zsh curl -X GET "https://api.moov.io/issuing/{accountID}/card-transactions" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ ``` Here's an example of a completed card transaction: ```JSON [ { "amount": "-14.89", "authorizationID": "f5f47bfa-fa5a-41f4-99eb-8671c1875b3f", "authorizedOn": "2024-08-24T14:15:22Z", "cardTransactionID": "ec7e1848-dc80-4ab0-8827-dd7fc0737b43", "createdOn": "2024-08-24T14:15:22Z", "fundingWalletID": "ec7e1848-dc80-4ab0-8827-dd7fc0737b43", "issuedCardID": "ec7e1848-dc80-4ab0-8827-dd7fc0737b43", "merchantData": { "city": "San Francisco", "country": "US", "mcc": "7298", "name": "Whole Body Fitness", "networkID": "1234567890", "postalCode": "94107", "state": "CA" } } ] ``` --- URL: https://docs.moov.io/guides/issue-cards/manage-issued-cards/ --- # Manage issued card transactions Learn how to manage your issued cards by understanding authorization statuses, event tracking, and viewing issuing activity in the Moov wallet. \*Card issuing is currently in a closed beta. [Contact Moov](https://moov.io/contact/) for more information. Once you've created a virtual spending card with Moov, you'll want to keep track of how the card is being used, and address any issues that may arise. Read more for details on how to manage your issued cards. ## [Understand authorization statuses](#understand-authorization-statuses) Whenever a card is used at a merchant, Moov processes the authorization request to check that the cardholder has enough funds to cover the cost of that particular transaction. The outcomes of an authorization request can be tracked through the [card authorization](/api/money-movement/issuing/list-authorizations/) API. Understanding the status of each authorization helps you to address any issues that may arise: | Status | Description | |------------|------------------------------------------------------------------------------------------------| | `pending` | The authorization has been approved, and funds are temporarily held pending final settlement. | | `declined` | The request was declined, possibly due to reasons like insufficient funds or an inactive card. | | `canceled` | The authorization was reversed by the merchant before final settlement. | | `cleared` | The transaction has been captured by the merchant and funds have moved. | | `expired` | The authorization expired before being settled by the merchant. | ### [Track authorization by stage](#track-authorization-by-stage) Moov provides detailed tracking of each stage of the card authorization process, which can be accessed through the authorization events `LIST` [endpoint](/api/money-movement/issuing/list-authorization-events/). This endpoint returns an array of authorization events that have occurred, potentially leading to updates of the `authorizedAmount` and accompanying amount being held as pending on the wallet balance. Here's a summary of the different types of authorization events we capture: | Event type | Description | |-----------------------------|-------------------------------------------------------------------------------| | `authorization` | A new transaction authorization has been requested. | | `reversal` | Some amount of the authorization has been reversed. | | `authorization-advice` | Adjustment of the originally authorized amount. | | `authorization-expiration` | Authorization hold expired, releasing the held funds. | | `clearing` | The merchant has captured the whole or a partial amount of the authorization. | | `authorization-incremental` | Request for increasing the initially authorized amount. | See below for an exammple of an authorization event: ```jsx [ { "amount": "-14.89", "createdOn": "2024-03-24T14:15:22Z", "eventID": "ec7e1848-dc80-4ab0-8827-dd7fc0737b43", "eventType": "authorization", "result": "approved" }, { "amount": "-14.89", "createdOn": "2024-03-26T14:15:22Z", "eventID": "dc856489-de10-4816-b3cf-842639f4e2bc", "eventType": "clearing", "result": "approved" } ] ``` ## [View completed card transactions](#view-completed-card-transactions) To view all completed card transactions associated with a particular account, use the list card transactions `GET` [endpoint](/api/money-movement/issuing/list-card-transactions/) and include your customer's `accountID`. A `200` response will include: - `authorizationID`: The identifier for the related authorization resource. If a transaction is submitted by a merchant without a prior authorization (a "force post"), this field will be null. - `authorizedOn`: The timestamp when the linked authorization was created. ## [View issuing activity in the Moov wallet](#view-issuing-activity-in-the-moov-wallet) All activities related to card issuing, such as authorizations and transactions, directly affect the balance of the associated Moov wallet. Each action creates a corresponding wallet transaction, providing a clear trail of funds movement. To learn more, read our [wallet transactions](/guides/sources/wallets/transactions/) guide. Card issuing activity can produce the following types of wallet transactions: - `issuing-auth-hold`: Funds are reserved on the wallet balance due to an approved authorization. Any incremental authorizations result in additional wallet transactions reflecting the amount of the increment. - `issuing-auth-release`: Held funds are released back to the wallet due to an authorization reversal, expiration, or when the authorization is cleared. - `issuing-transaction`: Reflects funds moving out of the wallet from a cleared authorization, a refund, or a force post. Each wallet transaction includes identifiers linking it directly to the issuing activity: | transactionType | sourceType | sourceID | |------------------------|-----------------------|-------------------| | `issuing-auth-hold` | issuing-authorization | authorizationID | | `issuing-auth-release` | issuing-authorization | authorizationID | | `issuing-transaction` | issuing-transaction | cardTransactionID | ## [Update an issued card](#update-an-issued-card) To update an issued card, you can use the update a spending card `PATCH` [endpoint](/api/money-movement/issuing/update/). This endpoint currently only supports closing a virtual spending card. --- URL: https://docs.moov.io/guides/money-movement/accept-payments/ach/ach-details/ --- # ACH details & statuses Learn how to get the details and statuses of ACH transfers. The `achDetails` object offers a variety of useful information about ACH transfers and status details. ## [Get ACH details](#get-ach-details) You can obtain details about a transfer involving the ACH payment rail through the transfers `GET` [endpoint](/api/money-movement/transfers/get/). If the source or destination uses an ACH payment method, the transfers details response will contain an `achDetails` object that contains useful information such as: - `traceNumber`: tracking number (assigned by Moov) that can used by payment recipient to trace the payment with their external financial institution - `return`: ACH return information per Nacha specification - `code` - `reason` - `description` - `correction`: ACH notification of change information per Nacha specification - `code` - `reason` - `description` - A transfer timestamp: Date-time information about transfer status changes - `initiatedOn` - `originatedOn` - `correctedOn` - `returnedOn` - `completedOn` ## [ACH statuses](#ach-statuses) The `achDetails` also contains rail-specific status information: | Status | Description | |--------------|-------------------------------------------------------------------------------------------------------------------------------------| | `initiated` | The ACH transfer from the source into Moov's system has been created | | `originated` | Payment instructions about the source transfer have been sent to Moov's originating depository financial institution (ODFI) partner | | `corrected` | The source transfer completed but a notification of change was received | | `completed` | Funds have been credited to the destination and are available for use | | `returned` | The payment was returned by Moov to the source financial institution | | `canceled` | The payment was successfully canceled | --- URL: https://docs.moov.io/guides/money-movement/accept-payments/ach/ach-overview/ --- # ACH overview Create payments that directly involve external bank accounts using the Automated Clearing House (ACH) network. ## [Payment methods](#payment-methods) Before initiating a transfer, you will need to set appropriate payment method types for debits (money in) and credits (money out). ### [Money in](#money-in) Moov pulls funds into the Moov platform using ACH debits. ACH debits can be created using a payment method with one of the following types: - `ach-debit-fund`: Represents a "funding" flow (for example, topping up your own Moov wallet for a disbursement) - `ach-debit-collect`: Represents the first stage of a "pull" flow (for example,collections or billing) A bank account must be verified using [instant micro-deposit](/guides/sources/bank-accounts/verification/instant-micro-deposit/) verification, or one of Moov's verification partners before it can be debited. ### [Money out](#money-out) Funds leave the Moov platform with ACH credits. You can specify the processing speed using a payment method with one of the following types: - `ach-credit-same-day`: Payment is processed with "same-day" ACH processing - `ach-credit-standard`: Payment is processed with standard "next-day" ACH processing Moov processes in all same-day windows listed below: | Processing speed | Cutoff time | Expected time posted to bank | |-------------------|-------------|------------------------------| | Same-day window 1 | 10:00 AM ET | Early afternoon | | Same-day window 2 | 2:15 PM ET | End of day | | Same-day window 3 | 4:15 PM ET | End of day | | Standard | 5:30 PM ET | Next day | A source account will see `Moov` on their statement, and a destination account will see the source's `displayName` on their bank statement. You can customize the name and description an account sees by using the `achDetails` fields. See the [customized ACH statement descriptors](#customized-ach-statement-descriptors) section for more information. ## [ACH processing and holds](#ach-processing-and-holds) Moov offers both [standard ACH processing](/guides/money-movement/accept-payments/ach/ach-processing-speeds/#standard-same-day-processing) and [faster ACH processing](/guides/money-movement/accept-payments/ach/ach-processing-speeds/#faster-same-day-processing). Three main factors determine the processing speed of a transfer: - The type of transfer (for example, bank-to-bank) - ACH payment method type (for example, `ach-credit-same-day`) - Cutoff times For standard bank-to-bank transfers, Moov holds funds that enter the platform via an ACH debit for two to three banking days before making the funds available, even when using "same-day" processing. The purpose of the hold is to account for the lag in time it takes to hear back about returns or processing issues. For faster bank-to-bank transfers, Moov removes the hold on ACH debits. The ACH credit process starts within hours of the transfer being initiated, allowing for transfers to fully complete within one day as long as the transfer is initiated before certain [cutoff times](/guides/money-movement/accept-payments/ach/ach-processing-speeds/#faster-same-day-processing). **Accounts must be approved by Moov to use faster ACH processing.** ACH payments are processed in batches and must be uploaded to Moov's partner financial institutions before certain cutoff times. See the [processing speed](/guides/money-movement/accept-payments/ach/ach-processing-speeds/) document for more information on processing speed, cutoff timetables, and examples of transfer timelines. For information on how to see transfer details and status information, see the [ACH details](/guides/money-movement/accept-payments/ach/ach-details/) document. ## [Transfer limits](#transfer-limits) The list below describes Moov's platform limits. Accounts may have lower limits than what is listed below due to the verification/underwriting process. Moov must qualify each customer for any exceptions to limits. If you have a question with regards to your account’s specific limits, please [contact Moov](https://support.moov.io/). | Payment method | Moov limit | |--------------------------------|----------------| | `ach-debit-fund` (same day) | $1,000,000 | | `ach-debit-fund` (standard) | $99,999,999.99 | | `ach-debit-collect` (same day) | $1,000,000 | | `ach-debit-collect` (standard) | $99,999,999.99 | | `ach-credit-same-day` | $500,000 | | `ach-credit-standard` | $99,999,999.99 | ## [Customized ACH statement descriptors](#customized-ach-statement-descriptors) You have the option to override the default Nacha file entries that appear on bank statements. To do this, set custom ACH statement descriptors when [creating a transfer](/api/money-movement/transfers/create/). Use the following fields on the source, destination, or both, to provide more clarity or context for an individual transfer: - `achDetails.companyEntryDescription`: Describe the purpose of the transaction - `achDetails.originatingCompanyName`: Set the name how you'd like it to appear on the statement Customizing these fields on the **source** will update the information on the bank statement where the debit occurs. Customizing these fields on the **destination** will update the information on the bank statement where the credit occurs. For example, in a transfer where the source and destination are the same Moov account, your account's ACH company name would be used as the default originating company name unless a customization was set. The example below sets custom descriptors for both the source and destination. [cURL](#tab-368429175-4-0) [Go SDK](#tab-368429175-4-1) ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/transfers" \ -H "Authorization: Bearer {token}" \ -H "X-Idempotency-Key: UUID" \ -H "X-Wait-For: rail-response" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "amount": { "value": 100, "currency": "USD" }, "destination": { "paymentMethodID": "string", "achDetails": { "companyEntryDescription" : "Gym dues", "originatingCompanyName" : "Whole Body Fit" } }, "source": { "paymentMethodID": "string", "achDetails": { "companyEntryDescription" : "Gym dues", "originatingCompanyName" : "Whole Body Fit" } } }'\ ``` ```go mc, _ := moov.NewClient() var accountID string mc.CreateTransfer(ctx, accountID, moov.CreateTransfer{ Amount: moov.Amount{ Currency: "USD", Value: 100, // $1.00 }, Destination: moov.CreateTransfer_Destination{ PaymentMethodID: "string", AchDetails: &moov.CreateTransfer_AchDetailsBase{ CompanyEntryDescription : "Gym dues", OriginatingCompanyName : "Whole Body Fit", }, }, Source: moov.CreateTransfer_Source{ PaymentMethodID: "string", AchDetails: &moov.CreateTransfer_AchDetailsSource{ CompanyEntryDescription : "Gym dues", OriginatingCompanyName : "Whole Body Fit", }, }, }) ``` ## [SEC codes](#sec-codes) You have the option of specifying an SEC code in certain ACH transfer request scenarios. If none is provided, Moov will handle the SEC code on your behalf (`CCD` for business accounts and `PPD` for individual accounts). | SEC code | Authorization type | Description | Supports addenda | |----------|-----------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------| | `CCD` | Corporate credit or debit | An ACH debit *between two business accounts*, such as vendor payments or funding payroll. | Yes | | `PPD` | Prearranged payment and deposit | An ACH transaction involving *an individual account* to make or collect a payment. | Yes | | `WEB` | Internet initiated/mobile entries | Moov allows `WEB` transactions for debit entries *from an individual to a business account.* Authorization is obtained via the internet or a wireless network (not including oral authorization over a telephone). | Yes | | `TEL` | Telephone initiated entries | An ACH debit *from an individual to a business account* with authorization obtained orally through a telephone, and recorded. See Nacha's [guidance](https://www.nacha.org/rules/meaningful-modernization) for use-cases and authorization requirements. | No | ### [Individual to business transactions](#individual-to-business-transactions) You have the option of specifying an SEC code on an ACH transaction that has an individual account as the source and a business account as the destination. The following SEC codes can be provided in **source.achDetails** when making a transfer `POST` [request](/api/money-movement/transfers/create/): `WEB`, `TEL`, `PPD`. If no SEC code is provided, the SEC code will be set as `WEB`. ### [Other transaction scenarios](#other-transaction-scenarios) If the source and destination of an ACH transaction are both business accounts, the SEC code will be set as `CCD`. If the source is a business account and the destination is an individual account, the SEC code will be set as `PPD`. ## [ACH addenda](#ach-addenda) When you create a transfer, you can add supplemental payment information with an addenda record. Set an addenda in the `source.achDetails` and `destination.achDetails` object. Moov supports standard ACH and properly formatted TXP addenda. Use cases for ACH addenda include: - Tax payments (TXP addenda) required by the IRS and many state agencies - B2B payments that include remittance or invoice references - Specialized payments in healthcare, payroll, or government The example below shows a transfer with a TXP addenda record. Addenda must use valid Nacha characters and be less than 80 characters in length. ```zsh curl -X POST POST "https://api.moov.io/accounts/{accountID}/transfers" \ -H "Authorization: Bearer {token}" \ -H "X-Idempotency-Key: UUID" \ -H "X-Wait-For: rail-response" \ -H "x-moov-version: v2024.01.00" \ -d '{ "amount": { "value": 10000, "currency": "USD" }, "source": { "paymentMethodID": "afaa9b4a-4fd7-4678-9fb7-d62e550fa13c", "achDetails": { "secCode": "CCD", "companyEntryDescription": "Tax payment", "originatingCompanyName": "The Body Shop Yoga", "addenda": [ { "record": "TXP*123456789*94105*960301*1*10000*2*5000*3*15000" } ] } }, "destination": { "paymentMethodID": "346039ed-2282-4936-bc30-1c3c396876aa", "achDetails": { "addenda": [ { "record": "Invoice #INV-2025" } ] } }, "description": "Federal tax payment" }' ``` ### [Data masking](#data-masking) ACH addenda, especially TXP records, may contain sensitive information such as SSNs or tax identifiers. For privacy and security reasons, Moov masks personally identifiable information and returns a safe addenda string in the response. If an addenda record has been masked, `isMasked` will be **true**, as shown below. ```json { "achDetails": { "addenda": [ { "isMasked": true, "record": "TXP*XXXXX6789*94105*960301*1*10000*2*5000*3*15000" } ] } } ``` Moov does not validate the semantic correctness of TXP fields — only format, length, and eligibility. An addenda record added to a `TEL` SEC code is not allowed by Nacha and will be rejected. --- URL: https://docs.moov.io/guides/money-movement/accept-payments/ach/ach-processing-speeds/ --- # ACH processing speed Learn about Moov's standard (default) and faster ACH processing. ACH payments are processed in batches and must be uploaded to Moov's partner financial institutions before certain cutoff times. In general, *no news is good news* - the payment succeeded unless you receive a subsequent return file stating that it did not. With **standard ACH processing**, Moov holds funds that enter the platform via an ACH debit for two banking days before making the funds available. The purpose of the hold is to account for the lag in time it takes to hear back about returns or processing issues. In most circumstances, funds are made available in the morning of the second banking day after the transfer was created for example, Wednesday for a Monday transfer. See the full [timetable](#standard-same-day-processing) below. With **faster ACH processing**, you can bypass the two day hold period. With no debit hold period, the credit process starts within hours after the transfer is created. Both bank-to-wallet and bank-to-bank transfers will complete within one day as long as the transfer is created before the specified cutoff times. See the full [timetable](#faster-same-day-processing) below. If the transfer is created after a cutoff time, it will be processed according to the same schedule on the next banking day. Banking days refer to M-F, excluding the Federal Reserve's [bank holidays](https://www.frbservices.org/about/holiday-schedules). See the transfers [overview](/guides/money-movement/overview/#bank-holidays) guide for more information. In [test mode](/guides/get-started/test-mode), ACH transfers will complete much faster. The processing windows in this guide apply to transfers in production mode. ## [Standard same-day processing](#standard-same-day-processing) To expedite standard processing, **Moov processes all ACH debits with same-day processing when available.** You can request ACH credits to be processed same-day by using an `ach-credit-same-day` payment method as the transfer destination. Note that even though the payment is processed the same day, funds will be made available later because of the hold period for possible returns or processing issues. See the diagrams below to see how timing works in different standard ACH transfer scenarios. The diagrams below show various standard processing timelines based on the 4:15 PM ET [cutoff window](/guides/money-movement/accept-payments/ach/ach-overview/#money-out). [Bank-to-wallet](#tab-724185693-3-0) [Bank-to-bank (same-day ACH)](#tab-724185693-3-1) [Bank-to-bank (standard ACH)](#tab-724185693-3-2) ![Standard bank-to-wallet processing diagram](../../images/bank-to-wallet-light.png) ![Bank-to-bank same-day processing diagram](../../images/bank-to-bank-same-day-light.png) ![Bank-to-bank standard processing diagram](../../images/bank-to-bank-standard-light.png) ## [Faster same-day processing](#faster-same-day-processing) Accounts must go through a risk assessment approval process by Moov to use faster ACH same-day processing. To start the approval process for faster ACH processing, [ask our team](https://moov.io/contact/) for more information. When an account is approved for faster processing, Moov will set the debit hold period to `no-hold` as a default for all relevant transfers. The debit portion of the process will complete within a few hours of originating. Bank-to-wallet transfers will complete within one day as long as the transfer is created before 4:15 PM ET. Bank-to-bank transfers will complete within one day as long as the transfer is created before 2:15 PM ET. If a bank-to-bank transfer using `ach-credit-same-day` is not created before the same-day cutoff time, it will complete based on the cutoff times below: | Created by | Debit completes | |-------------|-------------------| | 10:00 AM ET | ~ 1:00 PM ET | | 2:15 PM ET | ~ 4:00 PM ET | | 4:15 PM ET | ~ 6:00 PM ET | | 5:30 PM ET | ~ 7:00 AM ET (+1) | Faster processing is for those who are comfortable with debits clearing quickly from an account. In cases of returns (for example, insufficient funds or accounts closed), funds will be debited from the wallet according to Moov's [ACH returns and exception handling](/guides/money-movement/accept-payments/ach/returns/) process. If your account is set to `no-hold` by default, you can overwrite this in the `achDetails` of the create a transfer `POST` [request](/api/money-movement/transfers/create/) by passing in `2-days` to `debitHoldPeriod`. The diagrams below show various faster processing timelines based on the 2:15 PM ET [cutoff window](/guides/money-movement/accept-payments/ach/ach-overview/#money-out). [Bank-to-wallet](#tab-843915267-6-0) [Bank-to-bank (faster same-day ACH)](#tab-843915267-6-1) [Bank-to-bank (faster standard ACH)](#tab-843915267-6-2) ![Faster bank-to-wallet processing diagram](../../images/faster-ach-bank-to-wallet-light.png) ![Faster bank-to-bank same-day processing diagram](../../images/faster-ach-same-day-light.png) ![Faster bank-to-bank standard processing diagram](../../images/faster-ach-standard-light.png) --- URL: https://docs.moov.io/guides/money-movement/accept-payments/ach/cancellations/ --- # Cancellations In some scenarios, it's possible to cancel an ACH transfer. Learn how to initiate a cancellation through the Dashboard or API. Canceling an ACH transfer is possible if the following conditions are met: - Bank-to-bank: The credit has not yet originated - Wallet-to-bank: The credit has not yet originated - Bank-to-wallet: The debit has not yet originated In any of the above scenarios, transfers within a transfer group can be canceled if they fall within the allowed time frame. Once a transfer is successfully canceled, all subsequent transfers in the transfer group will also be automatically canceled. ![Cancellations must occur within a specific time frame.](../../images/ach-cancel-window-light.png) Cancellations must occur within a specific time frame. Note that cancelling a transfer will not affect any associated future scheduled transfers. ## [Request cancellation](#request-cancellation) [cURL](#tab-678124953-3-0) [Dashboard](#tab-678124953-3-1) Request a cancellation by sending the `accountID` and `transferID` to the cancel a transfer `POST` [endpoint](/api/money-movement/transfers/cancel/). ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/transfers/{transferID}/cancellations" \ -H "Authorization: Bearer {token}" \ -H "X-Idempotency-Key: UUID" \ -H "x-moov-version: v2024.01.00" \ ``` If you request a cancellation, but the transaction has already been originated, previously failed, or already completed, you'll receive a `400` error. If the request is made too close to origination, it's possible the the cancellation will fail. Retrying the cancellation is possible, but likely won't be successful. Additionally, you can get the details of a cancellation using the following: ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/transfers/{transferID}/cancellations/{cancellationID}" \ -H "Authorization: Bearer {token}" \ -H "X-Idempotency-Key: UUID" \ -H "x-moov-version: v2024.01.00" \ ``` Navigate to **Transfers** in the Dashboard. If a transfer can be canceled, you'll be able to use the **Cancel** button located near the transfer amount. If the transfer is outside the cancellation window, the cancel button will be grayed out. Visit the Dashboard [cancellation](/guides/dashboard/transfers/all-transfers/#initiate-a-reversal-refund-or-cancellation) guide for more information. ## [Status](#status) A cancellation status can be one of `pending`, `completed`, or `failed`. The `achDetails` object will also show a status of `canceled` if the transfer has been successfully canceled, along with a `canceledOn` timestamp. For bank-to-bank transfers, a cancellation will be `pending` when the debit transaction has already been originated. Moov waits for the debit to complete and subsequently credits the source wallet before the credit leg is initiated to the destination. If the source does not have a wallet, the destination wallet will be credited and you can initiate a transfer of funds back to the source bank account. A successful transfer request will have the following response: ```jsx { "cancellationID": "8df8e13c-3c20-4b4b-b265-796534cf4275", "status": "pending", "createdOn": "2023-09-09T14:15:22Z" } ``` For updates on a pending cancellation, you can subscribe to the cancellation [webhooks](#webhooks), or get the cancellation status using the cancellation details `GET` [endpoint](/api/money-movement/transfers/cancel-details/). ## [Webhooks](#webhooks) Subscribe to the following [webhook events](/guides/webhooks/webhook-events/#cancellations), which will provide you with relevant cancellation updates: - `cancellation.created` notifies you when the cancellation was successfully created - `cancellation.updated` notifies you when the cancellation was updated - `pending` - `completed` - `failed` --- URL: https://docs.moov.io/guides/money-movement/accept-payments/ach/ --- # ACH transfers Learn about ACH payments, processing speeds, how to find ACH payment details, and how to process returns. ## [What is ACH?](#what-is-ach) ACH (Automated Clearing House) transfers are electronic funds transfers between two financial institutions that can both push funds (ACH credits) and pull funds (ACH debits). ## [How ACH works with Moov](#how-ach-works-with-moov) Moov does not move money directly between external bank accounts. All funds move through the Moov platform on the way to their final destination. In practice, money must move into Moov before it can move out. ![ACH processing flow diagram](../images/moov-ach-overview-light.png) The flow shown above can be achieved in a single transfer when the source and destination are both external bank accounts linked to a Moov account. ACH can also be used to add or withdraw funds from a Moov [wallet](/guides/sources/wallets/). Below is a list of transfer types that use the ACH process: - **Bank-to-bank**: Requires both the debit and credit portion of the ACH process (note, not all use cases may be eligible for bank-to-bank ACH transfers) - **Bank-to-wallet**: Requires the debit portion of the ACH process - **Wallet-to-bank**: Requires the credit portion of the ACH process In order to facilitate any type of ACH transfer with Moov, you will need to ensure the source and destination accounts have the necessary [capabilities](/guides/accounts/capabilities/) and payment methods. Our open source community has built projects like [moov-io/ach](https://github.com/moov-io/ach), a reader, writer, and validator for ACH files. The open source tools are there for you to use, test, and build upon. --- URL: https://docs.moov.io/guides/money-movement/accept-payments/ach/returns/ --- # ACH returns & exception handling Learn about different ACH return scenarios, and how to handle errors. When an ACH return is received, the associated payment is automatically reversed by our financial institution partners. Moov automatically processes ACH returns and uses an account's `moov-wallet` to represent the effects of the funds reversal. Moov treats returns differently depending on the timing and the payment use case. Receiving an ACH return will update the overall transfer `status` to: - `failed`: transfer returned/failed during clearing period or before funds movement - `reversed`: transfer returned/failed after clearing period or marked `completed` ## [Scenarios](#scenarios) The following sections describe various return and exception handling scenarios. ### [Debit return received during clearing period](#debit-return-received-during-clearing-period) This is an example where the source `achDetails` status is `originated` . - If the source payment method type = `ach-debit-fund`: - The transfer status will update to `failed`, with no effect to `moov-wallet` balances - If the source payment method type = `ach-debit-collect`: - The transfer status will update to `failed`, with no effect to `moov-wallet` balances ### [Debit return received after clearing period](#debit-return-received-after-clearing-period) This is an example where the source `achDetails` status is `completed`. - If the source payment method type = `ach-debit-fund`: - The transfer status will update to `reversed` - The transfer amount will be deducted from the **source**`moov-wallet` balance - If the source payment method type = `ach-debit-collect`: - The transfer status will update to `reversed` - The transfer amount will be deducted from the **destination** `moov-wallet` balance ### [Credit returned or failed](#credit-returned-or-failed) This is an example where the source `achDetails` status is `completed` and the destination's achDetails status is `completed`. - If the source payment method type = `ach-debit-fund`: - The transfer status will update to `reversed` - The transfer amount will be credited to the **source** `moov-wallet` balance - If source payment method type = `ach-debit-collect`: - The transfer status will update to `reversed` - The transfer amount credited to the **destination** `moov-wallet` balance ## [Return codes](#return-codes) Moov automatically adjusts the status of a bank account for specific types of ACH returns. If you see the following bank account statuses, you will need to take one of the appropriate actions before you can continue processing with Moov: - `errored`: You will need to add a new bank account (or [contact Moov](https://support.moov.io/)) - `verificationFailed`: You will need to reverify (typically, reinitiate verification) Below you'll find the details on return codes and the action you'll need to take. You will always be able to re-attempt verification if you receive a `verificationFailed` status. You will not be able to re-attempt verification if you receive an `error` status. Required actions differ between returns received on ACH transfers and ACH verification. Use the tabs to see both sets of return codes and their corresponding action. [ACH transfers](#tab-736849215-2-0) [ACH verification](#tab-736849215-2-1) | Return code | Description | Status: action | |-------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------| | `R01` | **Insufficient funds**: The account has insufficient funds to complete the transaction | No action needed | | `R02` | **Account closed**: Previously active account has been closed by customer, or RDFI | `errored`: Add new account | | `R03` | **No account located**: Account number structure is valid and passes editing process, but does not correspond to an individual, or is not an open account | `errored`: Add new account | | `R04` | **Invalid account number**: Account number structure not valid. Entry may fail check digit validation, or may contain an incorrect number of digits. | `errored`: Add new account | | `R05` | **Improper debit**: A CCD, CTX, or CBR debit entry was transmitted to a consumer account of the receiver, but was not authorized by the receiver | `verificationFailed`: Reverify | | `R06` | **Originator requested return**: The ODFI has requested the RDFI to return an erroneous entry, or a credit entry, originated without the authorization on of the originator | `errored`: Add new account | | `R07` | **Authorization revoked by customer**: Consumer, who previously authorized ACH payment, has revoked authorization from originator (must be returned no later than 60 days from settlement date, and customer must sign affidavit) | `errored`: Add a new account | | `R08` | **Payment stopped**: Receiver of a recurring debit transaction has stopped payment to a specific ACH debit. RDFI should verify the receiver’s intent when a request for stop payment is made to ensure this is not intended to be a revocation of authorization. | `verificationFailed`: Reverify | | `R09` | **Uncollected funds**: A sufficient ledger balance exists to satisfy the dollar value of the transaction, but the available balance is below the dollar value of the debit entry | No action needed | | `R10` | **Originator unknown or unauthorized**: The receiver does not know the originator’s identity and/or has not authorized the originator to debit. Alternatively, for ARC, BOC, and POP entries, the signature is not authentic or authorized. | `errored`: Add new account | | `R11` | **Entry unauthorized**: Customer has authorized a debit for a specific amount and/or on a certain day of the month, however, the originator has changed the original terms of the authorization. Customer can send the entry back because the terms have changed. | `verificationFailed`: Reverify | | `R14` | **Payee unable to authorize**: The representative payee authorized to accept entries on behalf of a beneficiary is either deceased, or unable to continue in that capacity | `errored`: Add new account | | `R16` | **Bank account frozen**: Funds in bank account are unavailable due to action by the RDFI, or legal order | `errored`: Add new account | | `R17` | **Receiving bank rejected payment**: (1) Fields cannot be processed by the RDFI; or (2) The entry contains an invalid DFI account number and is believed by the RDFI to have been initiated under questionable circumstances | `verificationFailed`: Reverify | | `R20` | **Non-payment bank account**: Entry destined for non-payment bank account defined by Regulation D | `errored`: Add new account | | `R23` | **Receiver refused payment**: Customer refuses transaction because amount is inaccurate, results in overpayment, account is in litigation, or originator is not known to receiver | `verificationFailed`: Reverify | | `R29` | **Originator unauthorized**: The RDFI has been notified by corporate receiver that debit entry of originator is not authorized | `errored`: Add new account | | `R31` | **Permissible return entry**: The ODFI agrees to accept a return after the 24-hour deadline of a corporate entry reported unauthorized | No action needed | | Return code | Description | Status: action | |-------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------| | `R01` | **Insufficient funds**: The account has insufficient funds to complete the transaction | No action needed | | `R02` | **Account closed**: Previously active account has been closed by customer, or RDFI | `errored`: Add new account | | `R03` | **No account located**: Account number structure is valid and passes editing process, but does not correspond to an individual, or is not an open account | `errored`: Add new account | | `R04` | **Invalid account number**: Account number structure not valid. Entry may fail check digit validation, or may contain an incorrect number of digits. | `errored`: Add new account | | `R05` | **Improper debit**: A CCD, CTX, or CBR debit entry was transmitted to a consumer account of the receiver, but was not authorized by the receiver | `verificationFailed`: Reverify | | `R06` | **Originator requested return**: The ODFI has requested the RDFI to return an erroneous entry, or a credit entry, originated without the authorization on of the originator | `verificationFailed`: Reverify | | `R07` | **Authorization revoked by customer**: Consumer, who previously authorized ACH payment, has revoked authorization from originator (must be returned no later than 60 days from settlement date, and customer must sign affidavit) | `verificationFailed`: Reverify | | `R08` | **Payment stopped**: Receiver of a recurring debit transaction has stopped payment to a specific ACH debit. RDFI should verify the receiver’s intent when a request for stop payment is made to ensure this is not intended to be a revocation of authorization. | `verificationFailed`: Reverify | | `R09` | **Uncollected funds**: A sufficient ledger balance exists to satisfy the dollar value of the transaction, but the available balance is below the dollar value of the debit entry | No action needed | | `R10` | **Originator unknown or unauthorized**: The receiver does not know the originator’s identity and/or has not authorized the originator to debit. Alternatively, for ARC, BOC, and POP entries, the signature is not authentic or authorized. | `verificationFailed`: Reverify | | `R11` | **Entry unauthorized**: Customer has authorized a debit for a specific amount and/or on a certain day of the month, however, the originator has changed the original terms of the authorization. Customer can send the entry back because the terms have changed. | `verificationFailed`: Reverify | | `R14` | **Payee unable to authorize**: The representative payee authorized to accept entries on behalf of a beneficiary is either deceased, or unable to continue in that capacity | `verificationFailed`: Reverify | | `R16` | **Bank account frozen**: Funds in bank account are unavailable due to action by the RDFI, or legal order | `errored`: Add new account | | `R17` | **Receiving bank rejected payment**: (1) Fields cannot be processed by the RDFI; or (2) The entry contains an invalid DFI account number and is believed by the RDFI to have been initiated under questionable circumstances | `verificationFailed`: Reverify | | `R20` | **Non-payment bank account**: Entry destined for non-payment bank account defined by Regulation D | `verificationFailed`: Reverify | | `R23` | **Receiver refused payment**: Customer refuses transaction because amount is inaccurate, results in overpayment, account is in litigation, or originator is not known to receiver | `verificationFailed`: Reverify | | `R29` | **Originator unauthorized**: The RDFI has been notified by corporate receiver that debit entry of originator is not authorized | `verificationFailed`: Reverify | | `R31` | **Permissible return entry**: The ODFI agrees to accept a return after the 24-hour deadline of a corporate entry reported unauthorized | No action needed | If you are unable to resolve your error, [contact Moov](https://support.moov.io/). --- URL: https://docs.moov.io/guides/money-movement/accept-payments/card-acceptance/debt-repayment/ --- # Debt repayment Process debt repayment transactions in compliance with card brands and take advantage of interchange incentive programs with lower fees. Partner with Moov to register eligible merchants in the participating card network incentive programs. After registration, eligible merchants can receive lower interchange fees for qualified loan repayment transactions. If you have a debt repayment use case, [contact us](https://moov.io/contact/) for more information. ## [Merchant eligibility & registration](#merchant-eligibility--registration) To be eligible for debt repayment programs, merchants must fall into one of two MCC codes, `6012` or `6051`. MCC code `6012` is a financial institution such as a bank or credit union. MCC code `6051` is a non-financial institution that deals with currency, such as currency exchanges or money ordering. Debt collection agencies (MCC code `7322`) are not eligible for debt repayment interchange incentive programs. To have card payments qualify for debt repayment interchange incentives, business accounts must be configured with Moov and registered with Visa, Mastercard, and Discover. Moov works with you and the merchants to handle this registration, but requires specific information before the process begins. Once registration is complete, Moov will update the business account's debt repayment settings. ## [Debt repayment transfers](#debt-repayment-transfers) Once an account is configured for debt repayment, payments made with a debit or prepaid card will automatically be marked as debt repayment in the request to the card network. If a credit card is provided, you'll receive the following `400` error: ```json { "error": "unsupported card type for debt repayment" } ``` ## [Card eligibility](#card-eligibility) When a merchant account is configured for debt repayment, only consumer debit and consumer prepaid cards can be accepted. To check card eligibility, view `cardType` in the response object after [linking a card](/api/sources/cards/create/). Eligible cards will have a `debit` or `prepaid` card type. ```json { "cardType": "debit" } ``` ## [Check qualification](#check-qualification) If a merchant has been registered for the network's debt repayment program, then `feeProgram` will reflect which program a transaction qualified for. For merchants ineligible for the card network programs, or with a pending registration, `feeProgram` will reflect a standard interchange program. These transactions will not qualify for the debt repayment interchange program. Use the retrieve a transfer `GET` [endpoint](/api/money-movement/transfers/get/) and check `source.cardDetails.feeProgram` in the response object to see which debt repayment program a transaction qualified for. ```json { "source": { "cardDetails": { "feeProgram": "Debt Repayment 2" } } } ``` ## [Interchange fee details](#interchange-fee-details) The main benefit of the network incentive programs is capped interchange fees. This allows you to control processing costs regardless of the size of the loan repayment transaction. You can find a payment's calculated interchange fee by checking `moovFeeDetails.interchange` in the create a transfer [response](/api/money-movement/transfers/create/). ## [Rates](#rates) For the most up to date program rates, it's always best to check with the card networks directly. ### [Visa interchange program fees](#visa-interchange-program-fees) | Program name | Exempt Visa check card card not present transactions | Regulated Visa card not present transactions | |-------------------------------|------------------------------------------------------|----------------------------------------------| | CPS / Debt Repayment 2 | 0.65% +$0.15 ($2.00 max) | 0.05% +$0.21* | | CPS / Debt Repayment - No fee | 0.65% +$0.15 ($0.65 max) | 0.05% +$0.21* | | Program name | Exempt Visa consumer prepaid, other exempt | Regulated Visa consumer prepaid | |-------------------------------|--------------------------------------------|---------------------------------| | CPS / Debt Repayment 2 | 0.65% +$0.15 ($2.00 cap) | 0.05% +$0.21* | | CPS / Debt Repayment - No fee | 0.65% +$0.15 ($0.65 cap) | 0.05% +$0.21* | *\*Issuers that certify to Visa their compliance with the interim fraud prevention standards will receive an additional US $0.01.* ### [Mastercard program fees](#mastercard-program-fees) | Program name | MasterCard Consumer Signature unregulated debit and prepaid cards | |-----------------------------|-------------------------------------------------------------------| | Merit 1 (Consumer Loan MCC) | 0.80% + $0.25 ($2.95 cap) | ### [Discover program fees](#discover-program-fees) | Card type | Discover debit and prepaid | |--------------------|----------------------------| | Debit | 0.70% + $0.16 | | Debit Maximum | 0.00% + $2.40 | | Debit Non Exempt | 0.50% + $0.21 | | Prepaid | 0.70% + $0.16 | | Prepaid Maximum | 0.00% + $2.40 | | Prepaid Non Exempt | 0.50% + $0.21 | --- URL: https://docs.moov.io/guides/money-movement/accept-payments/card-acceptance/declines/ --- # Declines Understand why certain card payments are declined and how Moov categorizes different types of declines. For troubleshooting purposes, you'll want to know why cards are declined. In transfers where the source is a card, there are a number of possible failure reasons (usually for the sake of mitigating possible fraud). You can view these reasons in the [get a transfer](/api/money-movement/transfers/get/) or [list transfers](/api/money-movement/transfers/list/) endpoints. To view the card decline reason, look for the`failureCode` field within `cardDetails`. If a card payment fails, the card decline reason will also be returned in the synchronous response upon transfer creation. In a soft decline scenario, there has been a *temporary* authorization failure and an action will usually be required before running a card again. In a hard decline scenario, there has been a *permanent* authorization failure, and the card should not be run again. See the table below for a list of card related failure codes, their descriptions, and best practices to follow. While we have provided best practices, note they are suggestions and not exhaustive of all possibilities. ## [Failure codes](#failure-codes) | Failure code | Description | Best practice | |-------------------------------|-----------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------| | `amount-limit-exceeded` | The amount entered exceeds issuer or approved amount | Re-attempt with a lesser amount or at a later date so the limit resets. Contact issuer to discuss adjusting limits | | `call-issuer` | An issue occurred which must be handled by the card issuer | Contact card issuer for decline reason | | `card-not-activated` | The card has not been properly unblocked | Please contact the bank for support or use a different card | | `cardholder-account-closed` | The account is closed | Do not re-attempt with the same information - there will be a fee assessed. Re-submit with different credentials or contact issuer | | `could-not-route` | The financial institution cannot be found for routing (receiving institution ID is invalid) | Please verify the routing information and re-attempt with updated details | | `cvv-mismatch` | The CVV verification failed | Please verify the CVV and re-attempt with updated details. Monitor for potential fraud | | `do-not-honor` | The issuer will not allow the transaction | Re-attempt with different credentials or at a later time. Contact issuer for additional support | | `expired-card` | The card has expired or expiration date is missing | Please verify the expiration and re-attempt with updated details. Monitor for potential fraud | | `incorrect-pin` | The PIN is incorrect or missing when required | Please re-attempt with an updated PIN | | `insufficient-funds` | This card has insufficient funds to complete the transaction | Please re-attempt with a lesser amount or at a later time | | `invalid-amount` | The amount entered is invalid | Please re-attempt with a different amount | | `invalid-card-number` | The card number is incorrect | Do not re-attempt with the same information - there will be a fee assessed. Verify card information and re-submit with different credentials | | `invalid-merchant` | The card is not allowed at this merchant or MCC | Re-attempt once the cardholder has confirmed the restriction has been removed | | `invalid-transaction` | The transaction is invalid | Do not re-attempt - there will be a fee assessed. Evaluate potential fraud or technical issues | | `issuer-not-available` | The Issuer was unavailable for the transaction and STIP is not applicable or not available for this transaction | Can re-attempt the same day. Contact Issuer for additional support | | `lost-or-stolen` | The card was reported as lost or stolen | Do not re-attempt with the same information - there will be a fee assessed. Re-submit with different credentials or contact Issuer | | `no-such-issuer` | The issuer is invalid | Do not re-attempt - there will be a fee assessed. Evaluate potential fraud or technical issues | | `processing-error` | The transaction could not be processed due to processing error | Ensure payment details are valid or contact issuer for more information | | `reenter-transaction` | The transaction could not be processed due to an error in message structure or field format | Review Address Verification Result or contact acquirer to evaluate possible format errors | | `revocation-of-authorization` | Revocation of authorization order | Do not re-attempt with the same information - there will be a fee assessed. Contact cardholder about the recurring payment cancellation | | `suspected-fraud` | The transaction was declined because of suspected fraud | Cardholder should contact issuer and should only re-attempt after receiving confirmation of legitimacy | | `transaction-not-allowed` | The transaction was not allowed | Do not re-attempt with the same information - there will be a fee assessed. Re-submit with different credentials or contact issuer | | `velocity-limit-exceeded` | The transaction exceeds the card or account’s withdrawal frequency limit | Re-attempt at a later date so the limit resets. Contact issuer to discuss adjusting limits | --- URL: https://docs.moov.io/guides/money-movement/accept-payments/card-acceptance/disputes/ --- # Disputes Understand how Moov handles disputes, and the type of information you can receive about them. A dispute occurs when a cardholder formally questions the validity of a payment by raising a complaint to their card issuer. A dispute can be automatically resolved if a merchant utilizes a pre-dispute service. Otherwise, the card issuer will process a chargeback, temporarily reversing the payment for the duration of the dispute. Moov currently supports RDR (Visa Rapid Dispute Resolution) decisioned pre-disputes and chargebacks from all card networks. ## [Dispute handling](#dispute-handling) Moov engages directly with the card networks and communicates dispute details to you via API and Dashboard. Moov’s customers must pull dispute data and pass it along to their merchants on an ongoing basis. The chargeback amount can be either a portion of the original transfer, or the full amount of a transfer. Once we receive chargeback details from the card network, we process the chargeback by debiting the merchant’s Moov wallet. ## [Dispute notifications](#dispute-notifications) You can receive notifications on disputes through the `dispute.created` and `dispute.updated` [webhook events](/guides/webhooks/webhook-events/#disputes). Subscribing to that event will let you know the dispute was created, updated, and completed. The `dispute.updated` webhook will generate if there is a change to `status` or `phase`. Alternatively, you can use the disputes list `GET` [endpoint](/api/money-movement/disputes/list/) to pull a list of disputes on a recurring schedule. Note that even if a transfer has a dispute, its overall transfer status will remain `completed`. ## [View dispute information](#view-dispute-information) If a transfer has been disputed, you can see information about the dispute on the transfer object for the original `transferID` in question. A cardholder can dispute a charge for various reasons. The following response fields provide helpful information about a dispute and will allow merchants to compile the appropriate compelling evidence: | Field | Description | |----------------------------|------------------------------------------------------------------------------------| | `networkReasonCode` | The card network’s category for the dispute. Codes may differ between card brands. | | `networkReasonDescription` | Card network categorization details of the dispute. | | `phase` | The current phase of a dispute. | | `status` | The current status of a dispute. | The following is an example of a dispute response: ```json { "amount": { "currency": "USD", "value": 1204 }, "createdOn": "2023-08-24T14:15:22Z", "disputeID": "ec7e1848-dc80-4ab0-8827-dd7fc0737b43", "merchantAccountID": "ec7e1848-dc80-4ab0-8827-dd7fc0737b43", "networkReasonCode": "string", "networkReasonDescription": "string", "phase": "chargeback", "respondBy": "2023-08-24T14:15:22Z", "status": "response-needed", "transfer": { "transferID": "ec7e1848-dc80-4ab0-8827-dd7fc0737b43" } } ``` ### [Phases](#phases) See the `phase` field in either of the dispute `GET` [endpoint](/api/money-movement/disputes/) responses to see the current phase of a dispute. Disputes can have the following phases (note some phases currently only apply to specific card networks): | Status | Description | |---------------|--------------------------------------------------------------------------------------------------------------------------------------------------------| | `pre-dispute` | Visa only. Moov supports Visa’s Rapid Dispute Resolution integration which helps merchants auto-resolve pre-disputes and avoids potential chargebacks. | | `inquiry` | American Express only. Preliminary phase before a formal chargeback is created. | | `chargeback` | Transfer is actively being disputed. Moov wallet is debited immediately. | | `unknown` | There was a processing error. | American Express may send an inquiry to a merchant to request more information regarding a chargeback. This is a preliminary phase before a formal chargeback is created - no funds are debited from the merchant’s Moov wallet. In this phase, merchants can either accept liability by refunding the transfer, or prevent a chargeback by providing sufficient information. ### [Dispute statuses](#dispute-statuses) See the `status` field in either of the dispute `GET` [endpoint](/api/money-movement/disputes/) responses to see the current status of a dispute. Disputes can have the following statuses: | Status | Description | |-------------------|-------------------------------------------------------------------------------------------------------------------------| | `resolved` | No more action is required on these transactions. | | `response-needed` | Default response for all unresolved disputes. The merchant needs to communicate to Moov how they would like to proceed. | | `under-review` | Evidence has been submitted for a dispute and is being reviewed by the card network. | | `accepted` | The merchant has accepted liability for the dispute. | | `closed` | The issuer has reversed the chargeback, or evidence provided for the inquiry was sufficient. | | `won` | The evidence was compelling and the dispute was won. Funds have been credited back to the merchant wallet. | | `lost` | The evidence was not compelling and the dispute was lost. | | `expired` | The due date for a [response](#respond-to-disputes) to the chargeback or inquiry has passed. | Dispute information is also available in the Dashboard under **Transfers > Disputes**. See our [Dashboard](/guides/dashboard/transfers/disputes/) guide for more information. ## [Respond to disputes](#respond-to-disputes) If a merchant receives a chargeback, they can either **accept liability** or **challenge the chargeback**. Use the endpoints in the following sections to address specific stages of the dispute. If a merchant does not respond to a chargeback by the `respondBy` date, the chargeback expires and the merchant automatically accepts liability. Once evidence is submitted, the merchant will need to wait for the card network's final decision. If the evidence is sufficient, the dispute status will update to `won` and funds will be credited. If the evidence is insufficient, the dispute status will update to `lost`. Use the tabs below to view dispute flow diagrams based on phase. [Phase: Chargeback](#tab-936825714-4-0) [Phase: Pre-dispute (Visa only)](#tab-936825714-4-1) [Phase: Inquiry (Amex only)](#tab-936825714-4-2) A dispute with `phase: chargeback` will update to `status: response-needed` and the merchant is required to accept or deny liability. If the merchant denies liability, evidence will need to be submitted and the merchant will either win or lose the dispute. The dispute can also be closed by the issuer. ![](../../images/dispute-chargeback-light.png) A dispute with `phase: pre-dispute` can be resolved through Visa's Rapid Dispute Resolution, or closed by the issuer. ![](../../images/dispute-pre-light.png) A dispute with `phase: inquiry` is in a preliminary chargeback phase and evidence can be submitted if the merchant denies liability. If the evidence submitted in the inquiry phase is deemed insufficient, the dispute will update to `phase: chargeback`. The liability and evidence process will start over and the merchant will either win or lose the dispute. The dispute can also be closed by the issuer. ![](../../images/dispute-inquiry-light.png) ### [Response deadlines](#response-deadlines) Responses to disputes are due to Moov by the `respondBy` date and vary by card brand: | Card brand | Dispute respondBy | |------------|-------------------| | Visa | 6 calendar days | | Mastercard | 14 calendar days | | Discover | 14 calendar days | | Amex | 10 calendar days | If no response is submitted before the deadline, we’ll accept the dispute on your behalf and the disputed amount will not be recovered. It's possible to receive an American Express chargeback without an inquiry phase. [View dispute information](#view-dispute-information) for details about dispute phases. ### [Accept dispute](#accept-dispute) Accepting liability on a chargeback means the merchant will not contest the dispute and will accept the permanent return of the funds to the cardholder. This is final action and cannot be undone. If the phase is `chargeback` and the status is `response-needed`, the dispute can be accepted using the dispute `POST` [endpoint](/api/money-movement/disputes/post/). If the dispute is successful, the status will update to `accepted`. When a dispute is accepted, there is no additional movement of funds. The funds debit when the chargeback is received. If the phase is `inquiry` and the status is `response-needed`, the dispute can be accepted by [refunding](/api/money-movement/refunds/cancel/) the transfer. ### [Challenge dispute](#challenge-dispute) Challenging a chargeback requires gathering and submitting compelling evidence. Evidence can only be submitted once per dispute. #### [Upload evidence](#upload-evidence) Evidence must be uploaded before the `respondBy` due date. Evidence can only be uploaded if the phase is `chargeback` or `inquiry` and the status is `response-needed`. Evidence must be tagged with one of the following evidence types listed below and adhere to [file size and format](#file-size--format-requirements) guidelines. | Evidence type | Description | |--------------------------|------------------------------------------------------------------------------------------------------| | `receipt` | Proof of purchase notifying the customer about the charge. | | `proof-of-delivery` | Confirmation that the goods or services were delivered to the customer. | | `cancelation-policy` | Cancellation or refund policy as it was provided to the customer. | | `terms-of-service` | Terms of service policy as it was provided to the customer. | | `customer-communication` | Acknowledgement from cardholder withdrawing the dispute or email evidence that dispute was resolved. | | `cover-letter` | Summary of the challenge (Moov can provide guidelines or a template if requested). | | `generic-evidence` | Additional evidence that is outside the definition of the other evidence type categories. | There are two endpoints to upload evidence, depending on the evidence format. For example, you can upload a `cover-letter` as text and a `receipt` as a file. - File `POST` [endpoint](/api/money-movement/disputes/post-file/) - Text `POST` [endpoint](/api/money-movement/disputes/post-text/) After uploading all evidence, it must be [submitted](#submit-evidence). #### [Update evidence](#update-evidence) Evidence can only be updated if the dispute status is `response-needed`. Use the dispute `PATCH` [endpoint](/api/money-movement/disputes/patch/) to update evidence. #### [Delete evidence](#delete-evidence) Use the dispute `DEL` [endpoint](/api/money-movement/disputes/delete/) to delete a specific piece of evidence. #### [Submit evidence](#submit-evidence) **Evidence can only be submitted once per dispute** -- do not submit until everything is finalized. Evidence can only be submitted if the phase is `chargeback` or `inquiry` and the status is `response-needed`. Evidence must be submitted before the `respondBy` due date and cannot be submitted with an empty evidence body. Once evidence is successfully submitted, the status will update to `under-review`. Use the dispute `POST` [endpoint](/api/money-movement/disputes/post-evidence/) to submit evidence. #### [Retrieve evidence](#retrieve-evidence) Use the dispute `GET` endpoints to retrieve evidence metadata for a specific dispute. - List all dispute evidence `GET` [endpoint](/api/money-movement/disputes/list-evidence/) - Retrieve a specific piece of dispute evidence `GET` [endpoint](/api/money-movement/disputes/get-evidence/) The following is an example of retrieved evidence metadata: ```json [ { "evidenceID": "9b56817a-0f9f-4756-86a5-83cff8426d35", "disputeID": "a362c415-1ff3-445a-843a-2f6cf0e031ee", "createdOn": "2022-10-24T00:00:00Z", "evidenceType": "receipt", "filename": "receipt.jpg", "size": 467, "mimeType": "image/jpeg" }, { "evidenceID": "4e677336-464c-4a0c-b125-65aa2422bad3", "disputeID": "a362c415-1ff3-445a-843a-2f6cf0e031ee", "createdOn": "2022-10-24T00:00:00Z", "evidenceType": "proof-of-delivery", "filename": "screenshot.jpg", "size": 723, "mimeType": "image/jpeg" } ] ``` ### [File size & format requirements](#file-size--format-requirements) Moov requires supporting documents to fit within the following type, size, and naming specification parameters: | Type | Size | |------|---------------------------| | PDF | File size maximum is 4 MB | | JPG | File size maximum is 4 MB | | TIFF | File size maximum is 4 MB | **Naming specifications** for all documents are as follows: - 16 or fewer alphanumeric characters - No special characters - Must not contain sensitive info (such as PANs) --- URL: https://docs.moov.io/guides/money-movement/accept-payments/card-acceptance/ --- # Card acceptance Accept card payments, initiate refunds & reversals, deal with disputes, set up recurring payments, and more. Once your platform's Moov account is configured for card payments, you can use your customers' card information and the tokenized details to initiate card payment transfers. ![Card funds flow diagram](../images/card-funds-flow-light.png) Moov has multiple resources to help you get started with card payments. You can simulate card transfers in test mode using pre-populated business data and cards, as well as register a users card with the pre-built card link Drop. If you need to link cards to your customers' accounts, see all available options in our step by step [accept card payments](/guides/sources/cards/accept-card-payments/) guide. ## [Card status](#card-status) The status of a transfer can be found in `cardDetails.status`, which is part of the [create a transfer](/api/money-movement/transfers/create/) response body. You can also use the [list transfers](/api/money-movement/transfers/list/) and [retrieve a transfer](/api/money-movement/transfers/get/) endpoints to get the status. | Rail-specific status | Description | |----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------| | `initiated` | Transfer has been created | | `confirmed` | Successful authorization by the card network | | `settled` | Transaction settled with issuer; Moov wallet will be credited by 1 PM ET on a banking day, or the next banking day if it is a weekend or a holiday | | `completed` | Funds have been credited to the merchant Moov wallet | | `canceled` | Transaction was successfully cancelled and authorization has been reversed | | `failed` | Transaction failed; specific failure reason will be in `cardDetails.failureCode` | [Accept card payments tutorial \ Send card information directly from your user to Moov without handling the PCI data yourself.](/guides/sources/cards/accept-card-payments/) [Test cards \ You can simulate card transfers in test mode by using specific card numbers.](/guides/get-started/test-mode/#card-acceptance) [Card link Moov Drop \ Send card information directly from your user to Moov without handling the PCI data yourself.](/moovjs/drops/card-link) Use the guides in this section to learn about card acceptance on Moov's platform. --- URL: https://docs.moov.io/guides/money-movement/accept-payments/card-acceptance/recurring-payments/ --- # Recurring payments In this guide, we'll introduce card schemes and discuss how to implement recurring payments with Moov's API. Recurring payments allow merchants to collect from customers on a regular basis, without customers initiating a new payment each time. To set up recurring payments, you'll need to set up an initial payment before establishing a recurring schedule. You also have the ability to set up unscheduled payments, which occur outside the set schedule. ## [Get to know card schemes](#get-to-know-card-schemes) To use recurring payments, it's important to understand card scheme rules. Card brands mandate certain information be stored to facilitate recurring payments, and Moov ensures these mandates are met if transfers include the appropriate card scheme. | Transaction source | Description | |--------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `first-recurring` | Indicates when a cardholder initiates the first in a series of recurring transactions, or if the card is being saved for subsequent unscheduled charges initiated by the merchant. | | `recurring` | Indicates subsequent recurring transactions initiated by the merchant on a regular schedule. | | `unscheduled` | Indicates a subsequent transaction that occurs on an irregular basis, such as an account top-up. | ## [Set up card account updater](#set-up-card-account-updater) **[Card account updater](/guides/sources/cards/card-account-updater/) is optional**, but ensures there's no disruption to processing recurring payments if card details change. Card account updater automatically receives updates when a user changes card information on file, like expiration date. To set up card account updater, [link a card](/guides/sources/cards/#save-a-card-for-future-use) to an account and save it for future use by setting `cardOnFile` to **true** and setting the `merchantAccountID`. The account associated with `merchantAccountID` will be billed for successful card updates. Accounts must be approved to use Moov's card account updater. [Contact Moov](https://support.moov.io/) for more information. ``` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ``` ```json { "cardNumber": "string", "expiration": { "month": "01", "year": "28" }, "cardCvv": "0123", "holderName": "Jules Jackson", "billingAddress": { "addressLine1": "123 Main Street", "addressLine2": "Apt 302", "city": "Boulder", "stateOrProvince": "CO", "postalCode": "80301", "country": "US" }, "cardOnFile": true, "merchantAccountID": "50469144-f859-46dc-bdbd-9587c2fa7b42" } ``` ## [Set up initial payment](#set-up-initial-payment) Set up a payment schedule in your app, and initiate the first payment with the transfer `POST` [endpoint](/api/money-movement/transfers/create/). Set the `transactionSource`, located in `source.cardDetails`, to the `first-recurring` card scheme. This step is crucial to ensure the card issuer has the correct information about subsequent payments. Creating a `recurring` or `unscheduled` payment without an existing `first-recurring` payment will result in a failure. If you handle subscription changes, like upsells, you can default to `first-recurring` for the upsell payment in order to be safe. ``` 1 2 3 4 5 6 7 8 9 10 11 12 13 ``` ```json { "amount": { "value": 5000, "currency": "USD" }, "source": { "paymentMethodID": "ec7e1848-dc80-4ab0-8827-dd7fc0737b43", "cardDetails": { "transactionSource": "first-recurring" }, "destination": {} } } ``` ## [Set up recurring payments](#set-up-recurring-payments) After the initial `first-recurring` payment has completed, create a second request using the transfer `POST` [endpoint](/api/money-movement/transfers/create/). Set the `transactionSource` to the `recurring` card scheme. This sets up a payment method for a recurring series of payments. Failing to use the `recurring` option may result in a declined transaction. After the first recurring payment, another option is to create unscheduled, merchant-initiated payments. This is done by setting `transactionSource` to `unscheduled`. The `unscheduled` option is useful when a cardholder needs to make an additional payment outside of the regular recurring schedule. [Recurring](#tab-157249368-0-0) [Unscheduled](#tab-157249368-0-1) ``` 1 2 3 4 5 6 7 8 9 10 11 12 13 ``` ```json { "amount": { "value": 5000, "currency": "USD" }, "source": { "paymentMethodID": "ec7e1848-dc80-4ab0-8827-dd7fc0737b43", "cardDetails": { "transactionSource": "recurring" }, "destination": {} } } ``` ``` 1 2 3 4 5 6 7 8 9 10 11 12 13 ``` ```json { "amount": { "value": 5000, "currency": "USD" }, "source": { "paymentMethodID": "ec7e1848-dc80-4ab0-8827-dd7fc0737b43", "cardDetails": { "transactionSource": "unscheduled" }, "destination": {} } } ``` --- URL: https://docs.moov.io/guides/money-movement/accept-payments/card-acceptance/refunds/ --- # Refunds This guide details Moov's traditional refund method, however, Moov's reversal method is more flexible. See notice below. We strongly recommend using the reversals `POST` [endpoint](/api/money-movement/refunds/cancel/) for initiating refunds due to its broader functionality and enhanced flexibility. Reversals offer more flexibility to return funds to the cardholder, regardless of the state of a transfer. Based on the state of the transfer, Moov dynamically chooses the appropriate action, either a cancel or a refund. If a transfer is in a state where it can no longer be canceled, the reversals endpoint will initiate a traditional refund, and submit the credit information to the cardholder’s issuing bank. Partial cancellations will also initiate the traditional refund process regardless of the transfer's status since transfers cannot be partially canceled. **To streamline refunds, see the [reversals](/guides/money-movement/accept-payments/card-acceptance/reversals/) guide.** ## [Guidelines](#guidelines) A refund immediately debits the destination wallet balance of the original transfer and returns either full or partial funds to the source card used in the transaction. Once a refund is initiated, Moov submits the credit information to the customer's card issuer. Typically, customers should immediately see a pending credit to their card that posts within 5-7 business days, although the actual timing may vary by bank. - Only one refund can be initiated at a time per transfer - You cannot refund more than the original transfer amount - Refunds cannot be canceled after they are issued - To avoid a potential double charge, do not attempt to refund a payment that has been disputed by the cardholder - If the refund fails, you are able to initiate the refund again, for the same transfer ## [Initiating a refund via the API](#initiating-a-refund-via-the-api) You have the ability to initiate either a full or partial refund. **Full refund** To initiate a full refund using the API, use the refunds `POST` [endpoint](/api/money-movement/refunds/create/) without a payload. [cURL](#tab-789346152-2-0) [Go SDK](#tab-789346152-2-1) ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/transfers/{transferID}/refunds" \ -H "Authorization: Bearer {token}" \ -H "X-Idempotency-Key: UUID" \ -H "X-Wait-For: rail-response" \ -H "x-moov-version: v2024.01.00" \ ``` ```go mc, _ := moov.NewClient() var accountID string var transferID string mc.RefundTransfer(ctx, accountID, transferID, moov.CreateRefund{ Amount: 1700, }) ``` **Partial refund** To initiate a partial refund using the API, you can use the refunds `POST` [endpoint](/api/money-movement/refunds/create/) and include an amount in the payload. [cURL](#tab-324568719-3-0) ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/transfers/{transferID}/refunds" \ -H "Authorization: Bearer {token}" \ -H "X-Idempotency-Key: UUID" \ -H "X-Wait-For: rail-response" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "amount": 1000 // $10.00 }' ``` You can also initiate a refund through the Moov [Dashboard](/guides/dashboard/transfers/all-transfers/#initiate-a-reversal-refund-or-cancellation). --- URL: https://docs.moov.io/guides/money-movement/accept-payments/card-acceptance/reversals/ --- # Reversals This guide details how to reverse or refund transfers using Moov's flexible reversals endpoint. The reversals `POST` [endpoint](/api/money-movement/refunds/cancel/) offers a robust solution for returning funds to a cardholder, regardless of the current state of the transfer. When possible, the reversals endpoint cancels the transfer, reversing the authorization and swiftly returning funds. If settlement is in progress or completed, a refund is issued instead. Canceling a transfer offers certain advantages over refunds, such as reducing processing costs and expediting returns to cardholders. ## [Guidelines](#guidelines) - A reversal cannot exceed the original transfer amount - Once requested, reversals cannot be canceled - Avoid requesting a reversal for a payment disputed by the cardholder to prevent a potential double charge - If a reversal request fails, you can initiate it again for the same transfer ## [Initiate a reversal](#initiate-a-reversal) Use the reversals `POST` [endpoint](/api/money-movement/refunds/cancel/) to initiate a reversal. This endpoint dynamically orchestrates one of two actions based on the settlement process: - Cancels the transfer (reverses the authorization) if it hasn't yet settled - Initiates a refund if the transfer is already in the process of settlement, or has been settled The request body is optional and its behavior is as follows: - **No amount specified**: Moov first attempts to cancel the transfer. If settlement is in progress or complete, a full refund is initiated. - **Partial amount specified**: Moov immediately initiates a partial refund, as partial cancellations aren't supported. The cardholder will see a full debit followed by a partial credit. The `amount` is required to process a partial refund. [Full refund](#tab-315276849-1-0) [Partial refund](#tab-315276849-1-1) ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/transfers/{transferID}/reversals" \ -H "Authorization: Bearer {token}" \ -H "X-Idempotency-Key: UUID" \ -H "x-moov-version: v2024.01.00" \ ``` ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/transfers/{transferID}/reversals" \ -H "Authorization: Bearer {token}" \ -H "X-Idempotency-Key: UUID" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "amount": 1000 // $10.00 }' ``` For immediate error correction, we recommend requesting a full reversal and creating a new transfer to create a smoother cardholder experience. You can also initiate a reversal through the Moov [Dashboard](/guides/dashboard/transfers/#reversal). ## [Initiate a cancellation](#initiate-a-cancellation) While a reversal will cancel the transaction if possible, you also have the option of requesting a cancellation directly with the cancel a transfer `POST` [endpoint](/api/money-movement/transfers/cancel/). [Request a cancellation](#tab-862341579-3-0) [Retrieve a cancellation](#tab-862341579-3-1) If you request a cancellation, but the card network has already settled, you'll receive an error. If the cancellation window has passed, use the [reversals](#initiate-a-reversal) or [refunds](/guides/money-movement/accept-payments/card-acceptance/refunds/) endpoint instead. ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/transfers/{transferID}/cancellations" \ -H "Authorization: Bearer {token}" \ -H "X-Idempotency-Key: UUID" \ -H "x-moov-version: v2024.01.00" \ ``` You can get the details of a cancellation using the cancellation details `GET` [endpoint](/api/money-movement/transfers/cancel-details/). ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/transfers/{transferID}/cancellations/{cancellationID}" \ -H "Authorization: Bearer {token}" \ -H "X-Idempotency-Key: UUID" \ -H "x-moov-version: v2024.01.00" \ ``` ## [Settlement status](#settlement-status) Moov automatically checks the settlement status to determine if a transfer can be canceled. A successful request updates the transfer status to `canceled`, reversing the pending authorization. If settlement has already begun, a refund is initiated, which you can monitor using the [cancellation](#webhooks) or [refunds](#webhooks) as well as the [cancellation](/api/money-movement/transfers/cancel-details/) or [refunds](/api/money-movement/refunds/get/) `GET` endpoints. Moov provides a synchronous response to inform you of the reversal outcome, including relevant details based on whether a cancellation or refund occurred. [Cancellation](#tab-574328691-4-0) [Refund](#tab-574328691-4-1) ```jsx { "cancellation": { "cancellationID": "string", "createdOn": "2024-08-24T14:15:22Z", "status": "completed" } } ``` A cancellation typically completes instantly. However, if there's an error with the card network response, a `pending` status is returned until a confirmation is received. A `4xx` error after reversal initiation signifies a decline from the card networks or a processing error. Retry the request with a new idempotency key. See our [reversal](/api/money-movement/refunds/cancel/) API documentation for further information on HTTP error codes. ```jsx { "refund": { "refundID": "ec7e1848-dc80-4ab0-8827-dd7fc0737b43", "createdOn": "2024-08-24T14:15:22Z", "updatedOn": "2024-08-24T14:15:32Z", "status": "pending", "amount": { "currency": "USD", "value": 1204 }, "cardDetails": { "status": "confirmed", "confirmedOn": "2023-09-10T18:23:56Z" } } } ``` A [refund](/api/money-movement/refunds/cancel/) will have a `pending` status while waiting for authorization, or a `failed` status if it was declined by the card networks. The refund's `cardDetails.status` will update with one of the following detailed rail specific statuses: | Rail-specific status | Description | |----------------------|----------------------------------------------| | `initiated` | Refund has been initiated by the user | | `confirmed` | Refund has been accepted by the card network | | `settled` | Refund has been settled | | `completed` | Refund has completed | | `failed` | Refund has failed | If the `refund` status updates to `failed`, the `cardDetails` object will update with a failure code. ```jsx { "refund": { "refundID": "ec7e1848-dc80-4ab0-8827-dd7fc0737b43", "createdOn": "2024-08-24T14:15:22Z", "updatedOn": "2024-08-24T14:15:32Z", "status": "failed", "amount": { "currency": "USD", "value": 1204 }, "cardDetails": { "status": "failed", "failureCode": "suspected-fraud", "failedOn": "2023-09-10T18:23:56Z" } } } ``` If a transfer has a refund or cancellation in any status, we’ll also include that information in the transfers response itself. ```jsx "transferID": "string", "createdOn": "2024-08-24T14:15:22Z", "status": "canceled", "cancellations": [ { "cancellationID": "string", "createdOn": "2023-09-09T14:15:22Z", "status": "completed" } ], ``` ## [Webhooks](#webhooks) Subscribe to the following webhook event, which will provide you with relevant *reversal* updates: - `transfer.updated` notifies you once the reversal status changes to any of the following: - `canceled` - `source.canceled` Subscribe to the following webhook events, which will provide you with relevant *cancellation* updates: - `cancellation.created` notifies you when the cancellation was successfully created - `cancellation.updated` notifies you when the cancellation was updated - `pending` - `completed` - `failed` Subscribe to the following two webhook events, which will provide you with relevant *refund* updates: - `refund.created` notifies you when the refund was successfully created - `refund.updated` notifies you once the refund status changes to any of the following: - `pending` - `completed` - `failed` --- URL: https://docs.moov.io/guides/money-movement/accept-payments/card-acceptance/statement-descriptors/ --- # Statement descriptors Learn how to customize statement descriptors on card payments. Statement descriptors are the text that describe transactions presented to us by our digital banking feeds (or paper statements) so that we can recognize them. Setting clear statement descriptors can help to reduce disputes and improve the user experience by providing context on what the payment was for. For card payments, Moov will use the statement descriptor added at the transfer or account level. Otherwise, Moov will default to the DBA or legal business name of the Moov account truncated based on payment network limits. ## [Account level statement descriptor](#account-level-statement-descriptor) You can set the default statement descriptor for a merchant by using the `account.settings.cardPayment.statementDescriptor` field in the `PATCH` [accounts endpoint](/api/moov-accounts/accounts/patch/). In the example provided, we set a statement descriptor for a local gym called "Whole Body Fitness" at the account level. [cURL](#tab-935718642-1-0) [Go SDK](#tab-935718642-1-1) [Moov.js](#tab-935718642-1-2) ```zsh curl -X PATCH "https://api.moov.io/accounts/{accountID}" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "accountType": "business", "profile": { "business": { "legalBusinessName": "Whole Body Fitness LLC", "businessType": "llc" } }, "settings": { "cardPayment": { "statementDescriptor": "Whole Body Fitness" } } }'\ ``` ```go mc, _ := moov.NewClient() updatedAccount := moov.Account{ AccountID: "string", AccountType: moov.AccountType_Business, Profile: moov.Profile{ Business: &moov.Business{ LegalBusinessName: "Whole Body Fitness LLC", BusinessType: moov.BusinessType_Llc, }, }, Settings: &moov.AccountSettings{ CardPayment: &moov.CardPaymentSettings{ StatementDescriptor: "Whole Body Fitness", }, }, } mc.UpdateAccount(ctx, updatedAccount) ``` ```javascript const moov = Moov(token); const updatedAccount = { accountType: "business", profile: { business: { legalBusinessName: "ClassBooker", businessType: "llc" } }, settings: { cardPayment: { statementDescriptor: "Whole Body Fitness", } } }; moov.accounts.update(updatedAccount); ``` ### [American Express statement descriptors](#american-express-statement-descriptors) Before a transaction settles with the bank, American Express statements may show a description of `Moov Financial` instead of the `statementDescriptor` that has been set for the merchant. Once the transaction settles and moves beyond the `pending` stage, the description will update with the statement descriptor that has been set for the merchant. To avoid any confusion about the origin of the transaction, this information should be passed along to merchants to share with customers. ## [Transfer level statement descriptor](#transfer-level-statement-descriptor) Business accounts must be approved by Moov to set the `source.cardDetails.dynamicDescriptor` when creating a [transfer](/api/money-movement/transfers/create/). This field is an optional override of the default card statement descriptor, which allows a merchant to pass information to the card issuer at the time of transaction. The card issuer will then use this information to generate a description of the cardholder’s statement. In the example provided, we set a dynamic statement descriptor that captures the date of a yoga class at Whole Body Fitness. [cURL](#tab-657289341-2-0) [Go SDK](#tab-657289341-2-1) ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/transfers" \ -H "Authorization: Bearer {token}" \ -H "X-Idempotency-Key: UUID" \ -H "X-Wait-For: rail-response" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "amount": { "value": 100, "currency": "USD" }, "destination": { "paymentMethodID": "string" }, "source": { "paymentMethodID": "string", "cardDetails": { "dynamicDescriptor": "WhlBdy *Yoga 11-12" } }, "description": "Paying Jules for last 4 classes" }'\ ``` ```go mc, _ := moov.NewClient() var accountID string mc.CreateTransfer(ctx, accountID, moov.CreateTransfer{ Amount: moov.Amount{ Currency: "USD", Value: 100, // $1.00 }, Destination: moov.CreateTransfer_Destination{ PaymentMethodID: "string", }, Source: moov.CreateTransfer_Source{ PaymentMethodID: "string", CardDetails: &moov.CreateTransfer_CardDetailsSource{ DynamicDescriptor: "WhlBdy *Yoga 11-12", }, }, Description: "Paying Jules for last 4 classes", }) ``` --- URL: https://docs.moov.io/guides/money-movement/accept-payments/card-acceptance/tap-to-pay-android/ --- # Tap to Pay on Android Moov's Tap to Pay technology allows merchants to accept contactless payments using an Android device's built-in NFC capabilities. Customers can tap their contactless card or mobile wallet against the merchant's phone to securely complete transactions. This guide outlines how to set up Tap to Pay for Android. For the best results, merchants should implement code that prevents the screen or application from sleeping. If the screen or application sleeps while a transaction is in-flight, processing may be interrupted or fail. Additionally, ensure **developer mode** on the terminal device is turned off before starting any transaction in production mode. To use Tap to Pay, you'll need to integrate with Moov's SDKs. Integration consists of two main phases: 1. **Onboard Terminal Applications** – Register terminal applications then link them with a merchant 2. **Accept and Process Payments** – Configure the merchant’s mobile application to process contactless payments View the [Android SDK](https://moovfinancial.github.io/moov-android/moov-android/io.moov.sdk/index.html) documentation. ## [Prerequisites](#prerequisites) Devices must meet the requirements laid out in the prerequisite section below. **Operating System** - Android 10.0 (API 29) minimum - Google Play Services v11+ - Official Android release **Hardware Features** - Active NFC antenna - ARM processor architecture - Secure element for key storage - Unmodified manufacturer firmware **Security Status** - Passes Google Play Integrity verification - No root access detected - Original bootloader intact - Accurate system time ## [Set up app through Google Play](#set-up-app-through-google-play) When distributing the application through Google Play, we recommend limiting the store listing visibility to devices that pass strong integrity checks. Google Play can verify that devices pass integrity checks before the store listing is made visible to users. Enable this feature to limit your app's distribution to unreliable or unknown devices. This will not affect the app's Google Play discoverability or search ranking. 1. Log in to [Google Play Console](https://play.google.com/console/) 2. Navigate to **Release > App Integrity > Store listing visibility** 3. Enable **Strong integrity checks** This process prevents installation on compromised devices that could pose security risks. ## [Register application](#register-application) Applications must be registered with Moov to be authorized to use our [Tap to Pay SDK](). The process for application registration is as follows: 1. Create a `TerminalApplication` via the create terminal application [endpoint](/api/sources/terminal-applications/create/) ```zsh curl -X POST "/terminal-applications" \ -H "Authorization: Bearer {token}" \ --data '{ "platform": "android" }'\ ``` 2. The application will move from `pending` to `enabled` once approved. You can subscribe to the `terminalAppRegistration.updated` webhook to be notified of the status updates 3. Once the application is enabled, you must link the app's `TerminalApplication` to a merchant account via the link terminal application [endpoint](/api/sources/terminal-applications/link/) ```zsh curl -X POST "/accounts/{accountID}/terminal-applications" \ -H "Authorization: Bearer {token}" \ --data '{ "terminalApplicationID": "string" }'\ ``` 4. When a new version of the application is published to Google Play, register this version via the terminal applications version [endpoint](/api/sources/terminal-applications/create-versions/) `POST /terminal-applications/{terminalApplicationID}/versions` ```zsh curl -X POST "https://api.moov.io/terminal-applications/{terminalApplicationID}/versions" \ -H "Authorization: Bearer {token}" \ --data-raw '{ "version": "20440059" }'\ ``` ## [Initialize SDK](#initialize-sdk) SDK initialization requires `MoovSDK.onApplicationCreated` to be called in the app's `Application.onCreate` method. Additionally,`MoovSDK.isApplicationProcess` should be used to determine whether or not the app should proceed with any initialization logic in its `onCreate` method. ```kotlin class MyApplication : Application() { override fun onCreate() { super.onCreate() // initialize the Moov SDK MoovSDK.onApplicationCreated(this) // return if not being called from the main process if (!MoovSDK.isApplicationProcess()) { return } } } ``` ## [Create transfer](#create-transfer) The main entry point is a factory method: [MoovSDK.createTerminal](https://moovfinancial.github.io/moov-android/moov-android/io.moov.sdk/-moov-s-d-k/-factory/create-terminal.html). This initializes a terminal instance which ensures a secure environment. This method should be called as early in the application's lifecycle as is practical, as it may take a significant amount of time to complete the device attestation. Creating an EMV authorization will grab exclusive access to the device's NFC reader, allowing tap of an EMV card. There are two main paths to accept EMV payments: - Directly create a `transfer` from the SDK - Create an authorization via the SDK and create the `transfer` separately [Directly create transfer](#tab-467285391-0-0) [SDK authorization & transfer API](#tab-467285391-0-1) This method accepts the EMV tap, authorizes the transaction with the card network, creates a transfer on the Moov platform, and returns the transfer ID. ```kotlin val terminalConfig = fetchTerminalConfig() // fetch the terminal config from the Moov API val terminal = MoovSDK.createTerminal( applicationContext, terminalConfig, ) val transferID = terminal.createTapTransfer( CreateTransferParams( TapAuthorizationParams( amount = 100L, currency = Currency.getInstance("USD"), customerAccountID = "962aa592-5993-49d6-ae54-d6d6ab917c66", ), partnerAccountID = "fd35bc72-fa52-4fef-a0f5-f99fa1280aeb", destinationPaymentMethodID = "19a76ccb-be73-4394-a9ca-701c0a20fd8a", description = "A fancy widget", )) { LOG.d(TAG, "EMV message received: $it") } ``` This method accepts the EMV tap, authorizes the transaction with the card network, and returns a token which can be passed into the [create transfer](/api/money-movement/transfers/create/) API. If the authorization token expires before creating a transfer, the card authorization is **reverted** (voided). You should ensure transfers are created promptly after receiving the token and within the token’s validity period (set in the `exp` claim of the JWT). JWTs with an expired `exp` claim will not be accepted for processing. ```kotlin val terminalConfig = fetchTerminalConfig() // fetch the terminal config from the Moov API val terminal = MoovSDK.createTerminal( applicationContext, terminalConfig, ) val authorization = terminal.createTapAuthorization( TapAuthorizationParams( amount = 100L, currency = Currency.getInstance("USD"), customerAccountID = "962aa592-5993-49d6-ae54-d6d6ab917c66", )) { LOG.d(TAG, "EMV message received: $it") } // now, create the transfer externally using the authorization as the source ``` ## [Test mode](#test-mode) [Test mode](/guides/get-started/test-mode/) allows you to explore and verify your integration with the Moov SDK before processing live payments. The terminal configuration fetched from the Moov API determines whether the SDK operates in test or production mode. When a terminal is created with a test configuration, the returned `Terminal` implements the `SandboxTerminal` interface, which provides access to testing specific functionality. To use test mode, you'll need to use a bearer token, which is generated when you create a Moov account. You can check for test mode and access specific methods to test different card scenarios: ```kotlin val result = MoovSDK.createTerminal(context, config) if (result is TerminalCreationResult.Created) { val terminal = result.terminal if (terminal is SandboxTerminal) { // Access sandbox-specific methods terminal.getTestCases() // Browse available test cards terminal.selectTestCard("4000000000000010") // Select decline card } } ``` Additionally, you can add a dropdown menu to your application's UI that allows users to select a test card. We recommend placing this dropdown on the same screen as the transaction amount entry field. Note that this feature is available only in test mode — when running in production, users must tap a physical card on the device. ### [Test cards](#test-cards) Use `getTestCases()` to retrieve the list of available test cards. Each test card is tied to a specific authorization outcome, allowing you to test both [approve](/guides/get-started/test-mode/#link-cards-for-card-acceptance) and [decline](/guides/get-started/test-mode/#declined-card-transfers) scenarios. See the [Tap to Pay](/guides/get-started/test-mode/#tap-to-pay-on-mobile) section of the test mode guide for available test cards. Call `selectTestCard()` with the desired card number before initiating a tap authorization. The SDK will simulate that card being tapped, returning the corresponding approve or decline response without requiring a physical card tap. --- URL: https://docs.moov.io/guides/money-movement/accept-payments/card-acceptance/tap-to-pay-iphone/ --- # Tap to Pay on iPhone To process transactions with Tap to Pay on iPhone, integrate Moov's iOS SDK, [MoovKit](https://moovfinancial.github.io/moov-ios/documentation/moovkit/getting-started/). Accept all types of in-person, contactless payments right on your iPhone with no extra terminals or hardware needed. Accept physical debit and credit cards, Apple Pay, and other digital wallets. Tap to Pay on iPhone uses the built-in security and privacy features of iPhone to help protect your business and customer data. ![We're sorry, the video element could not load.](images/ttpoi-poster.webp) This guide outlines how to set up Tap to Pay on iPhone. For the best results, merchants should implement code that prevents the screen or application from sleeping. If the screen or application sleeps while a transaction is in-flight, processing may be interrupted or fail. Additionally, ensure **developer mode** on the device is turned off before starting any transaction in production mode. To use Tap to Pay on iPhone, you'll need to integrate with Moov's SDKs. Integration consists of two main phases: 1. **Onboard Terminal Applications** – Register terminal applications then link them with a merchant 2. **Accept and Process Payments** – Configure the merchant’s mobile application to process contactless payments View Moov's full [iOS SDK (MoovKit)](https://moovfinancial.github.io/moov-ios/documentation/moovkit/getting-started/) documentation for more information. ## [Prerequisites & supported devices](#prerequisites--supported-devices) Ensure the app is running on a compatible device and iOS version. You can use [isPaymentCardSupported()](https://moovfinancial.github.io/moov-ios/documentation/moovkit/moov/ispaymentcardsupported%28%29) to verify device compatibility. - iPhone XS or newer - iOS 16.0+ (US) - Latest iOS version recommended for optimal performance ## [Integrate MoovKit](#integrate-moovkit) Moov's SDK to integrate Tap to Pay on iPhone functionality is available for [download](https://github.com/moovfinancial/moov-ios) and you can find more details in the [documentation](https://moovfinancial.github.io/moov-ios/documentation/moovkit/). Add MoovKit as a package dependency to your project via via Swift Package Manager. ```fallback https://github.com/moovfinancial/moov-ios ``` Within the project you'll also need to embed the framework and link binary with libraries. See the [MoovKit](https://moovfinancial.github.io/moov-ios/documentation/moovkit/getting-started) documentation for complete details. And finally, add MoovKit to your project. ```swift import MoovKit ``` ## [Request entitlement from Apple](#request-entitlement-from-apple) Your application must request an entitlement from Apple for Tap to Pay on iPhone. You can request from your [Apple Developer Account](https://developer.apple.com/contact/request/contactless-payments). After receiving the entitlement, you should configure the entitlement in your project. View the full instructions on [developer.apple.com](https://developer.apple.com/documentation/proximityreader/setting-up-the-entitlement-for-tap-to-pay-on-iphone). ```xml com.apple.developer.proximity-reader.payment.acceptance ``` ## [Review Apple's guidelines](#review-apples-guidelines) Before submitting your application, review Apple’s [human interface guidelines](https://developer.apple.com/design/human-interface-guidelines/tap-to-pay-on-iphone) to ensure your implementation follows all requirements to avoid any delays in the approval process. ## [Implement terminal configuration provider](#implement-terminal-configuration-provider) Implement a terminal configuration provider to initialize MoovKit. For production use, fetch the configuration from your backend. Below is a sample implementation, assuming `PartnerClient` is implemented to interact with your backend API: ```swift import Foundation import PartnerClient import os class TerminalConfigProvider: TerminalConfigurationProvider { let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "main") var terminalConfiguration: String { get async throws { return try await fetch(terminalApplicationID: UUID(uuidString: "7922ce07-daf3-48f2-aab3-ed878c76a1a3")!) } } let partnerClient: PartnerClient let partnerAccountID: UUID let merchantAccountID: UUID public init(partnerClient: PartnerClient, partnerAccountID: UUID, merchantAccountID: UUID) { self.partnerClient = partnerClient self.partnerAccountID = partnerAccountID self.merchantAccountID = merchantAccountID } func fetch(terminalApplicationID: UUID) async throws -> String { do { let terminalConfig = try await partnerClient.getTerminalConfiguration( accountID: merchantAccountID, terminalApplicationID: terminalApplicationID ) return terminalConfig.configuration } catch { logger.error("\(error)") throw error } } } ``` View the [SDK](https://moovfinancial.github.io/moov-ios/documentation/moovkit/getting-started/#6-Configure-Terminal-Provider) documentation for more details and context. ## [Register application](#register-application) Applications must be registered with Moov to be authorized to use [MoovKit](https://moovfinancial.github.io/moov-ios/documentation/moovkit/getting-started/). The process for application registration is as follows: 1. Create a TerminalApplication via the create terminal application [endpoint](/api/sources/terminal-applications/create/) ```zsh curl -X POST "/terminal-applications" \ -H "Authorization: Bearer {token}" \ --data '{ "platform": "android" }'\ ``` 2. The application will move from `pending` to `enabled` once approved. You can subscribe to the `terminalAppRegistration.updated` webhook to be notified of the status updates 3. Once the application is enabled, you must link the app's `TerminalApplication` to a merchant account via the link terminal application [endpoint](/api/sources/terminal-applications/link/) ```zsh curl -X POST "/accounts/{accountID}/terminal-applications" \ -H "Authorization: Bearer {token}" \ --data '{ "terminalApplicationID": "string" }'\ ``` ## [Terms & condition acceptance](#terms--condition-acceptance) Merchants need to accept Apple's terms and conditions - once for each merchant identifier. Once the terms and conditions are accepted, any device using the same merchant identifier can use Tap to Pay on iPhone without accepting the terms and conditions again. The additional devices don’t need to use the same Apple account, or be signed in to Apple. For the best user experience, it’s recommended to present the terms and conditions before the checkout experience. View [Apple's documentation](https://developer.apple.com/documentation/ProximityReader/adding-support-for-tap-to-pay-on-iphone-to-your-app#Display-the-Terms-and-Conditions-interface-to-the-merchant) for more information on terms and conditions. ## [Create transfer](#create-transfer) Tap to Pay on iPhone uses the built-in security and privacy features of iPhone to help protect your business and customer data. When a payment is processed, Apple doesn’t store card numbers on iPhone or on Apple servers. 1. Once terms and conditions have been accepted, initialize the reader hardware. ```swift do { let identifier = try await moov.initReader() logger.debug("identifier \\(String(describing: identifier))") } catch { logger.error("Failed to fetch identifier") } ``` 2. Create a payment session by calling `createSession(invalidateTerminalConfiguration:)` as early as possible to configure the device. 💡 Each time your app launches, create a `PaymentCardReaderSession` to handle the reading of payment card information. You create this session using the `createSession(invalidateTerminalConfiguration:)` method of your Moov object. The initial configuration of the device can take up to two minutes, but subsequent requests typically take only a few seconds. Register an `eventHandler:` to receive an asynchronous stream of events that you can use to display a progress UI to the merchant. There are two main paths to accept EMV payments: - Directly create a `transfer` from the SDK - Create an authorization via the SDK and create the `transfer` separately [Directly create transfer](#tab-498251736-2-0) [SDK authorization & transfer API](#tab-498251736-2-1) This method accepts the EMV tap, authorizes the transaction with the card network, creates a transfer on the Moov platform, and returns the transfer ID. ```swift do { let accessToken = // source from Moov backend let paymentMethodId = // source from Moov backend let transfer = try await moov.createTapTransfer( for: amount, currencyCode: CurrencyCode.USD, transactionType: .purchase, destinationPaymentMethodId: paymentMethodId, customerAccountId: nil, description: nil, using: accessToken ) } catch { logger.error("Card read error: \(error)") } ``` This method accepts the EMV tap, authorizes the transaction with the card network, and returns a token which can be passed into the [create transfer](/api/money-movement/transfers/create/) API. ```swift do { let amt = Decimal(1.23) let authResponse = try await moov.createTapAuthorization( for: amount, currencyCode: CurrencyCode.USD, transactionType: .purchase, customerAccountID: UUID() ) // send authResponse.paymentToken to your backend to create a transfer using authorization as the source } catch { logger.error("Card read error: \(error)") } ``` ## [Test mode](#test-mode) [Test mode](/guides/get-started/test-mode/) allows you to explore and verify your integration with the MoovKit SDK before processing live payments. The terminal configuration fetched from the Moov API determines whether the SDK operates in test or production mode. In test mode, MoovKit provides access to features and methods specifically designed for testing and simulating various scenarios. Select from predefined test cards to simulate different authorization outcomes, including approvals and declines, without requiring a physical card tap. Instead of requiring a physical card tap the SDK will present a screen to select a card to use. See the [Tap to Pay](/guides/get-started/test-mode/#tap-to-pay-on-mobile) section of the test mode guide for available test cards. Refer to the [iOS SDK](https://moovfinancial.github.io/moov-ios/documentation/moovkit/test-mode) documentation for complete details on how to use test-specific functionality. ## [Error handling](#error-handling) MoovKit communicates errors with your application via exceptions. View the documentation for the following error types: - [SDKError](https://moovfinancial.github.io/moov-ios/documentation/moovkit/sdkerror) - [CardReaderError](https://moovfinancial.github.io/moov-ios/documentation/moovkit/cardreadererror) - [CardReadError](https://moovfinancial.github.io/moov-ios/documentation/moovkit/cardreaderror) If you encounter any issues, please create a [support ticket](https://portal.usepylon.com/moov/forms/problem) and attach the SDK logs. Be sure to include: - The SDK version and OS/device details - A description of the steps that led to the error - The relevant portion of the logs (compressed if large) - Ensure any sensitive information (API keys, card details, or PII) is redacted * * * Tap to Pay on iPhone requires a supported payment app and the latest version of iOS. Update to the latest version by going to Settings > General > Software Update. Tap Download and Install. Some contactless cards may not be accepted by your payment app. Transaction limits may apply. The Contactless Symbol is a trademark owned by and used with permission of EMVCo, LLC. Tap to Pay on iPhone is not available in all markets. For Tap to Pay on iPhone countries and regions, see [https://developer.apple.com/tap-to-pay/regions/](https://developer.apple.com/tap-to-pay/regions/). --- URL: https://docs.moov.io/guides/money-movement/accept-payments/card-acceptance/timing/ --- # Card settlement timing At Moov, we’re constantly working on ways to speed up money movement. In an effort to get merchants their funds more quickly, Moov takes advantage of the last settlement cutoff available to us with each card network. The variability across card brands creates some nuance in how transfers are reported in the Moov platform. This guide outlines some tips to help reconcile daily card payment activity and will be updated as we add functionality to improve reporting and speed up the merchant funding process. ## [Cutoff times by card brand](#cutoff-times-by-card-brand) Settlement cutoff times for card payment transfers are outlined below. Transfers created before these times are typically credited to the merchant’s Moov wallet the next banking day. | Card Brand | Cutoff Time | |------------|-----------------------| | Mastercard | 2:00 AM ET (next day) | | AmEx | 1:00 AM ET (next day) | | Discover | 6:00 AM ET (next day) | | Visa | 6:00 AM ET (next day) | Moov transfer statuses generally progress from `pending` → `completed` / `failed`. A card payment transfer will remain `pending` until the funds have been credited to the merchant’s wallet. Card transactions contain a more granular status in `transfer.source.cardDetails{}`: - `confirmed` - successful authorization; eligible for next batch and next banking-day funding. - `settled` - transaction has settled with issuer; Moov wallet will be credited by 1:00 PM ET on a banking day, or the next banking day if it is a weekend or a holiday. - `completed` - funds have been credited to the merchant Moov wallet. The following illustrates a typical Monday business day of processing: | Card Brand | Batch Begin | Batch Cutoff | Settled status | Completed (funded) | |------------|----------------|-----------------|----------------|--------------------| | Mastercard | Mon 2:00 AM ET | Tues 2:00 AM ET | Tues AM | Tues by 1:00 PM | | AmEx | Mon 1:00 AM ET | Tues 1:00 AM ET | Tues AM | Tues by 1:00 PM | | Discover | Mon 6:00 AM ET | Tue 6:00 AM ET | Tues AM | Tues by 1:00 PM | | Visa | Mon 6:00 AM ET | Tue 6:00 AM ET | Tues AM | Tues by 1:00 PM | A `completed` transfer status indicates the funds have been credited to the merchant and are available. Funding to the merchant Moov wallet occurs by 1:00 PM ET on the banking day following the settlement cutoff. For example: - **Visa**, Monday business day: cutoff Tuesday at 6:00 AM ET. Sales completed before Tuesday at 6 AM will be funded to the merchant Moov wallet on Tuesday by 1:00 PM ET. 💸 Once funds have been credited to the merchant’s Moov wallet, they can be transferred out using a bank transfer. See more details in the [ACH transfers](/guides/money-movement/accept-payments/ach/ach-overview/) guide. ## [Reconciliation and Moov wallet balances](#reconciliation-and-moov-wallet-balances) Card payments are available in the merchant’s Moov wallet the day after the transfer is created. However, refunds are immediately deducted from the merchant’s Moov wallet at the time of creation. Chargebacks are also immediately debited at the time that they are received. - **Sales:** credited to Moov wallet by 1:00 PM ET next banking day after transaction - **Refunds:** immediately debited from wallet at the time the refund is initiated - **Chargebacks:** immediately debited from wallet at the time chargeback is processed Suppose the proceeds of card payments are cashed out of the merchant’s Moov wallet at 7:00 AM ET via same-day ACH. On Wednesday, the withdrawal could be expected to contain: - Transfers created before the Monday cutoff times and completed on Tuesday - `confirmed` status on Monday - `settled` status on Tuesday AM - `completed` status by Tuesday EOD - Chargebacks received between 7:00 AM Tuesday and 7:00 AM Wednesday - Refunds created between 7:00 AM Tuesday and 7:00 AM Wednesday --- URL: https://docs.moov.io/guides/money-movement/accept-payments/ --- # Accept payments Transfer funds using cards, ACH, push to card, RTP, or Moov wallets. Use the guides in this section to explore payment rail options. View the card acceptance section for details on Apple Pay, reversals, recurring payments, disputes, and more. If you'd like to accept a payment using payment links, visit our [payment links](/guides/money-movement/payment-links/) guide. --- URL: https://docs.moov.io/guides/money-movement/accept-payments/pull-from-card/ --- # Pull from card Instantly access money from your customers by pulling funds from their cards. With pull from card transfers, Moov supports instant account funding and account-to-account transfers using supported Visa and Mastercard debit cards, available 24/7/365. Pull from card is available for customers that are chartered financial institutions. ![Pull from card funds flow diagram](../images/pull-from-card-funds-flow-light.png) ## [Use cases](#use-cases) Pull transfers, or account funding transactions, facilitate the movement of funds from a supported debit or prepaid card to an external account owned by the cardholder. To use pull transfers, merchants are required to be U.S. regulated financial institutions. These transactions are ideal for: - **Initial account funding**: Quickly deposit funds to newly opened accounts. - **External transfers**: Move money from accounts held at other financial institutions. Currently, pull from card transactions cannot be used for peer-to-peer (P2P) transfers. Within the Moov platform, this payment type is modeled as a transfer from an individual's linked debit or prepaid card to the Moov wallet of the financial institution external account. When initiating a transaction, the following needs to be set: - **Source:** Individual’s debit or prepaid card (Visa and Mastercard only). - **Destination:** Financial institution’s Moov wallet. The destination account requires the `wallet` and `collect-funds` [capabilities](/guides/accounts/capabilities/). ## [Determine support for pull from card](#determine-support-for-pull-from-card) Ensure you have linked a card on the account. The simplest way to securely link a card is by using the [card link Drop](/moovjs/drops/card-link/), a prebuilt UI component for embedding card-based payments. If you've provided proof of PCI compliance, you also have the option to link a card using the `POST` link a card [endpoint](/api/sources/cards/create/). When linking a card, ensure that the Moov account is created with **the same name as the cardholder’s name** on the linked card. You will receive a `400` response during transfer creation if the names do not match. Moov strongly recommends using the `X-Wait-For` header in the request to receive a synchronous response. This includes the rail response and newly created payment methods. If you omit the `X-Wait-For` header, you'll get an asynchronous response and need to call the list payment methods `GET` [endpoint](/api/sources/payment-methods/list/). You can also subscribe to [webhooks](/guides/webhooks/webhook-events/#payment-methods) and wait for the new payment methods to be available for use. Once you’ve linked a card, use the `GET` [endpoint](/api/sources/cards/get/) and check the `domesticPullfromCard` field in the response to see if `pull-from-card` is supported. The `domesticPullfromCard` field will show one of the following: | Eligibility | Description | |-----------------|---------------------------------------------------------------------------------------------| | `supported` | Funds will be available to the destination upon authorization | | `not-supported` | This card is ineligible for `pull-from-card` payments. Contact your issuer for more details | | `unknown` | Eligibility has not been checked or is unknown | [curl](#tab-542863179-4-0) [Go SDK](#tab-542863179-4-1) ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/cards" \ -H 'Authorization: Bearer {token}' \ ``` ```go mc, _ := moov.NewClient() var accountID string var cardID string mc.GetCard(ctx, accountID, cardID) ``` To bolster fraud prevention controls, Moov has taken steps to verify the card’s account ownership. The card verification process will match the existing `cardVerification` object's `addressLine1`, `postalCode`, and `cvv` between the Moov account and the card network in the response: ```json { "cardVerification": { "addressLine1": "match", "postalCode": "match", "cvv": "match" } } ``` Additionally, Moov supports Visa’s [Account Name Inquiry (ANI)](https://usa.visa.com/content/dam/VCOM/regional/na/us/support-legal/documents/account-name-inquiry-onesheet-merchant-version.pdf). ANI provides a way to check that names provided on the linked card match the names held on file with the issuer. This optional tool serves to enhance cardholder verification. To submit a name to Visa's ANI, supply the `holderName` and set `verifyName` to **true** when making a call to the card link `POST` [endpoint](/api/sources/cards/create/) or `PATCH` [endpoint](/api/sources/cards/update/). The response will show a match status for each of the names on file with the issuer: ```json { "cardVerification": { "fullName": "match", // noMatch, match, partialMatch, notChecked "firstName": "match", // noMatch, match, partialMatch, notChecked "middleName": "noMatch", // noMatch, match, partialMatch, notChecked "lastName": "match" // noMatch, match, partialMatch, notChecked }, } ``` **The verification process is crucial in reducing the risk of fraudulent activities and ensuring cards are linked to the rightful owner. If these requirements are not met, the card will be ineligible for pull from card transactions.** You can find example name verification scenarios in our [test mode](/guides/get-started/test-mode/#name-verification) guide. ## [Implement pull from card](#implement-pull-from-card) You can simulate pull from card transfers in test mode using [specific test cards](/guides/get-started/test-mode/#push-to-card--pull-from-card). The `pull-from-card` payment method becomes available when the following criteria are met: - The linked card is `supported` - The linked card meets verification requirements - Moov has approved the account for pull from card transfers Moov has a platform limit of $10,000 per pull from card transaction. Additionally, the merchant must pay for the pull from card transaction. The merchant **cannot** surcharge the end user. ### [Initiate the transfer](#initiate-the-transfer) A pull transfer can be created when the source is a sender with a linked card with the transfers capability and the `destination` is a Moov wallet with `collect-funds` capability. In the response, check the `domesticPullFromCard` field to determine if the card supports pull from card transactions. Possible values are `supported`, `not-supported`, or `unknown`. [curl](#tab-683714529-0-0) [Go SDK](#tab-683714529-0-1) ```zsh curl -X GET "https://api.moov.io/transfers" \ -H 'Authorization: Bearer {token}' \ -H "Origin: https://api.moov.io" \ -H "X-Wait-For: rail-response" \ --data-raw '{ "source": { # Pull from card "paymentMethodID": "string" }, "destination": { # Moov wallet "paymentMethodID": "string" }, "amount": { "value": 10000, "currency": "USD" }, "description": "Account funding example" }'\ ``` ```go mc, _ := moov.NewClient() var accountID string mc.CreateTransfer(ctx, accountID, moov.CreateTransfer{ Amount: moov.Amount{ Currency: "USD", Value: 97, // $0.97 }, Source: moov.CreateTransfer_Source{ // Pull from card PaymentMethodID: "string", CardDetails: &moov.CreateTransfer_CardDetailsSource{ DynamicDescriptor: "Pull transfer", }, }, Destination: moov.CreateTransfer_Destination{ // Moov wallet PaymentMethodID: "string", }, FacilitatorFee: moov.CreateTransfer_FacilitatorFee{ Total: moov.PtrOf(int64(2)), // $0.02 }, Description: "Account funding example", }) ``` ### [Track transfer status](#track-transfer-status) To track the transfer status, view `destination.cardDetails` using the transfers `GET` [endpoint](/api/money-movement/transfers/get/): [curl](#tab-231759684-0-0) [Go SDK](#tab-231759684-0-1) | Status | Description | |-------------|--------------------------------------------------------------------------| | `initiated` | Transaction is created and awaiting authorization | | `failed` | Issuer declined or there was error with processing | | `completed` | Authorization request was successful and Issuer approved the transaction | ### [Refund status](#refund-status) In the event of an error, pull from card transfers can be refunded. The table below lists the possible refund statuses. | Status | Description | |-------------|----------------------------------------------------------------------------------------------------------| | `confirmed` | Authorization request was successful and the issuer has approved the transaction | | `pending` | The refund is in progress, but not yet completed | | `completed` | The card network has settled the transaction and the funds should be available in the customer’s account | | `failed` | Issuer declined, or there was error with processing | ## [Set up recurring transfers](#set-up-recurring-transfers) Using the `transactionSource` parameter in `source.cardDetails` to set up recurring payments. Mark the initial transaction as `first-recurring` and subsequent transactions as `recurring`. [First recurring](#tab-638524719-7-0) [Recurring](#tab-638524719-7-1) ```json { "source": { "cardDetails": { "dynamicDescriptor": "WhlBdy Monthly", "transactionSource": "first-recurring" }, } } ``` ```json { "source": { "cardDetails": { "dynamicDescriptor": "WhlBdy Monthly", "transactionSource": "recurring" }, } } ``` For more details, see our [recurring payments](/guides/money-movement/accept-payments/card-acceptance/recurring-payments/) guide. ## [Transfer & velocity limits](#transfer--velocity-limits) There are limits on the amount a card `fingerprint` can send within a specified time. The following limits are for Visa and Mastercard. | Limit type | Maximum limit | |-----------------|---------------| | Amount | $10,000 | | 1-day velocity | $10,000 | | 7-day velocity | $25,000 | | 30-day velocity | $50,000 | ### [Error responses](#error-responses) **Amount limit:** If you have exceeded the amount limit, you'll receive a `400` error response. You can retry the transfer with a lower amount. **Velocity limits**: If you have exceeded the velocity limits, pull from card transfers will fail. The transfer status will be `failed` and the failure reason will be `rejected-high-risk`. **Issuer limits:** If you have exceeded issuer limits, the transfer status will be `failed` and the failure reason will be `source-payment-error`. American Express transactions less than $1 will also result in a payment error. Contact the issuer if you require guidance on specific issuer limits. The specific transaction decline code can be found in `cardDetails.failureCode` using the retrieve a transfer [endpoint](/api/money-movement/transfers/) or the list transfers [endpoint](/api/money-movement/transfers/get/). ## [Disputes](#disputes) You can receive notifications on disputes by subscribing to the `dispute.created` and `dispute.updated` [webhook events](/guides/webhooks/webhook-events/#disputes). Alternatively, you can use the disputes list `GET` [endpoint](/api/money-movement/disputes/list/) to pull a list of disputes on a recurring schedule. For more details on the disputes lifecycle, see our [disputes guide](/guides/money-movement/accept-payments/card-acceptance/disputes/). Pull from card disputes can be tested in [test mode](/guides/get-started/test-mode/#disputes). --- URL: https://docs.moov.io/guides/money-movement/events-and-statuses/ --- # Events & statuses This guide explains different transfer failure scenarios, responses, statuses and how Moov handles them. In an ideal world, every transfer initiated in Moov's platform would complete seamlessly as expected. However, there are instances in which something goes wrong. In every situation, Moov will provide more information - a failure reason, detailed responses, or status updates. You can also set up webhooks to be notified when certain events occur, like a failed transfer. ## [Transfer failures](#transfer-failures) A transfer's status changes from `pending` to `failed` if the funds don't reach their intended destination. A transfer could fail for a few reasons: - The source account (bank account or linked card) does not have sufficient funds for the amount of the transfer - The source account or transfer recipient closed their account (bank account or linked card) so it no longer exists - The issuer of the linked card denies the transfer attempt for a number of reasons (see the [declines](/guides/money-movement/accept-payments/card-acceptance/declines/) guide) - An phone number or email was reused when linking a card (these must be unique to each cardholder) A transfer's status can change from `pending` to `failed` within 2 business days of when it was initiated. ### [Failure reasons](#failure-reasons) When a transfer fails, we communicate the reason for the transfer failure through the `failureReason` field in API response for a get a transfer [request](/api/money-movement/transfers/get/). See a list of possible failure reasons below: | Status | Description | |-----------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `source-payment-error` | A failure occurred at the source. The failure code is provided in the rail details under the source object. American Express transactions less than $1 will also result in a payment error. | | `destination-payment-error` | A failure occurred at the destination. The failure code is provided in the rail details under the destination object. | | `wallet-insufficient-funds` | Transfer failed due to insufficient funds in the source wallet. | | `rejected-high-risk` | Transfer was flagged with potential fraud and rejected by Moov. | | `processing-error` | Moov encountered an unexpected error processing the transfer. | ## [Transfer reversals](#transfer-reversals) A transfer's status changes from `completed` to `reversed` if the funds made it to the destination, but need to be returned. A reversal scenario can occur when: - A fraudulent, unauthorized, or unrecognized charge was made - Someone used the wrong bank details to pay for goods or services In the case of a reversal, Moov routes the funds back to the party that made an unintentional payment or was accidentally/fraudulently charged. To accomplish this, we deduct from the Moov wallet of the account that received the funds. The recipient of a transfer that's being reversed is responsible for funding the wallet to cover the negative balance. A transfer's status can change from `completed` to `reversed` within 60 calendar days of when it was initiated. ## [Transfer responses](#transfer-responses) Moov uses standard HTTP status codes to communicate the outcome of all Moov API requests. The following table summarizes the possible responses after submitting a Create transfer `POST /transfers` [request](/api/money-movement/transfers/create/). Receiving a `2xx` response code does not indicate that the payment was successful. Use the `X-Wait-For: rail-response` header in your `POST` request to get the full response from the payment network and be prepared to handle timeouts. HTTP code Moov status message Description **200** OK Successfully created a transfer If you included the `X-Wait-For` header in your request, you will receive a synchronous response with transfer details from the payment network. Subscribe to the `transfer.updated` webhook event for updates on the transfer status and rail-specific details as they become available. **201** Created Transfer was successfully created but an error occurred while getting the synchronous response. The asynchronous response object will be returned. Moov is currently unable return the full transfer object as a response, so you will only receive the asynchronous response object. To retrieve full rail-specific details at a later time, use the transfers `GET` [endpoint](/api/money-movement/transfers/get/). Subscribe to the `transfer.updated` webhook event for updates. **202** Accepted The transfer or refund was created, but rail-specific details may not be available within the 15 second timeout window. A timeout occurred with the payment network, so you will only receive the asynchronous response object. To retrieve full rail-specific details at a later time, use the transfers `GET` [endpoint](/api/money-movement/transfers/get/). Subscribe to the `transfer.updated` webhook event for updates. **400** Bad request Invalid request, an error message will be available in the response body. There was an issue with the request payload. Follow the error message instructions and double check your request against the request body schema in the API reference. **409** Conflict Attempted to create a transfer using duplicate X-Idempotency-Key header Retry the request with a different X-Idempotency-Key header **422** Unprocessable content The request body could not be processed The error message will let you know how long to wait (in milliseconds) before you can retry **429** Too many requests Request was refused due to rate limiting The error message will let you know how long to wait (in milliseconds) before you can retry If you receive a 202 response, do not mark the transfer as successful. For payments related to physical goods, make sure that nothing ships until rail-specific transfer details are available. Either perform a subsequent GET for the transfer details or subscribe to the `transfer.updated` webhook event. ## [Transfer statuses](#transfer-statuses) The following is a list of transfer statuses: | Status | Description | |-------------|------------------------------------------------------------------------------------------------------------------------| | `created` | A transfer has been created | | `queued` | A transfer that is part of a group will have the queued status until the preceding transfer has successfully completed | | `pending` | The transfer is in progress, but not yet completed | | `completed` | The transfer has completed | | `canceled` | A transfer that is part of a group can fail and subsequent transfers will be marked as canceled | | `failed` | The transfer did not succeed | | `reversed` | The transfer completed, but funds were returned to the source | Rail specific statuses are also available under the source and destination. You can view rail-specific statuses in our other guides: [Card acceptance](/guides/money-movement/accept-payments/card-acceptance/#card-status) [ACH](/guides/money-movement/accept-payments/ach/ach-details/#ach-statuses) [RTP](/guides/money-movement/send-payments/rtp/#rtp-statuses) ## [Transfer event webhooks](#transfer-event-webhooks) Every transfer status change is an event in Moov, so you can set up webhooks to stay updated on transfer events such as transfer creation or status updates (pending, completed, failed, reversed). See our [webhooks](/guides/webhooks) guide to learn more. --- URL: https://docs.moov.io/guides/money-movement/idempotency/ --- # Idempotency Learn how to use idempotency keys to prevent unintentional duplicate API requests. Idempotency is a property where an action will result in the same outcome, regardless of how many times you run that action. In payments, idempotency is particularly important because it eliminates the risk of accidentally charging someone twice. In order to prevent unintentional duplicate API requests, Moov includes an idempotency key (`X-Idempotency-Key`) in the header for the following endpoints: - `POST` [Create transfer](/api/money-movement/transfers/create/) - `POST` [Refund transfer](/api/money-movement/refunds/create/) - `POST` [Cancel or refund a card transfer](/api/money-movement/refunds/cancel/) You are responsible for generating an idempotency key and setting it in the transfer header. An idempotency key should be deterministic, producing the exact same key each time. An idempotency key can be a unique ID from your system up to 36 characters, or a UUID comprised of unique identifiers for the action. Moov supports UUID v5. An idempotency key will not expire. Moov will flag any transfer with the same idempotency key as a duplicate. If you try to create a transfer with the same idempotency key twice, your second attempt will result in a `409` error response indicating that a transfer was previously created with that idempotency key. --- URL: https://docs.moov.io/guides/money-movement/ --- # Money movement Transfers are the movement of funds across Moov's platform. Take advantage of multiple payment rails which allow you to tailor the cost, speed, and risk of each payment to your particular use case. Transfers occur between a source (where funds originate) and a destination (recipient of funds). The diagram below shows how funds flow from a source to destination on Moov's platform. ![Moov funds flow diagram](./images/transfer-diagram-light.png) Note, not all use cases may be eligible for bank-to-bank ACH transfers Moov supports multiple payment rails depending on the account and its capabilities. Use the guides below to learn more about payment method requirements, rail options, and how to respond to various transfer responses and statuses. Moving money incurs fees - for details on Moov's fee types, billable events, and fee plans, visit our [fees](/guides/fee-plans/) section. --- URL: https://docs.moov.io/guides/money-movement/overview/ --- # Transfers overview Understand how funds flow through Moov when choosing different source and destination payment methods. All transfers facilitated with Moov involve money moving in, out, through, or within the Moov platform. Since all funds flow through Moov, a single transfer can take advantage of multiple payment rails which allows you to tailor the cost, speed, and risk of each payment to your particular use case. Source Bank account Same-day ACH Bank accounts Same-day ACH Faster ACH* Debit / credit cards Card payment Wallets Moov Wallet Destination Bank account Same-day ACH Bank accounts Same-day ACH Standard ACH Wallets Moov Wallet ![](/img/faster-ach-bank-to-wallet.png) ![](/img/faster-ach-same-day.png) ![](/img/faster-ach-standard.png) ![](/img/bank-to-bank-same-day.png) ![](/img/bank-to-bank-standard.png) ![](/img/bank-to-wallet.png) ![](/img/wallet-to-bank-rtp.png) ![](/img/wallet-to-bank-ach-sameday.png) ![](/img/wallet-to-bank-ach-standard.png) ![](/img/wallet-to-wallet.png) ![](/img/card-to-wallet.png) ## [Get transfer options](#get-transfer-options) When initiating a transfer, you'll need to know what payment methods are available to use since not all payment method combinations are valid. Some payment methods can only be used as the source, and some can only be used as the destination. Available payment methods also depend on the enabled capabilities of the source and destination accounts. You can use our API to request valid transfer source and destination combinations between accounts. The transfer options `POST` [endpoint](/api/money-movement/transfers/options/) takes valid payment method combinations and network-specific restrictions such as maximum payment amounts into account. In practice, transfer options can be used to present a menu of different options for how and where you want money to move. If you provide an `accountID`, this endpoint will return you a list of valid payment methods for the `source` or `destination`. If you submit an `accountID` along with `paymentmethodID`, we will return you a list of valid payment methods based on what you provided. For example, if you're looking to make a transfer with a specific account and you know the source is a card, you can learn what destination options are available using this endpoint. In the example below, the information provided will list payment methods filtered on the capabilities of the transfer participants. [cURL](#tab-638152794-2-0) [Go SDK](#tab-638152794-2-1) ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/transfer-options" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "amount": { "value": 100, "currency": "USD" } "destination": { "accountID": "string" }, "source": { "accountID": "string" } }'\ ``` ```go mc, _ := moov.NewClient() // your partner accountID var accountID string mc.TransferOptions(ctx, accountID, moov.CreateTransferOptions{ Source: moov.CreateTransferOptionsTarget{ AccountID: "string", }, Destination: moov.CreateTransferOptionsTarget{ AccountID: "string", }, Amount: moov.Amount{ Currency: "USD", Value: 1, }, }) ``` See the [payment methods](/guides/money-movement/payment-methods/) guide for detailed information on transfer limits and what payment method combinations are valid. ## [Idempotency](#idempotency) To prevent duplicate transfers, every `POST /transfers` [request](/api/money-movement/transfers/create/) requires an `X-Idempotency-Key` header. You are responsible for generating a deterministic [idempotency key](/guides/get-started/glossary/#idempotency). If you try to create a transfer with the same idempotency key twice, your second attempt will result in a `409` error response indicating that a transfer was previously created with that idempotency key. Moov supports unique IDs up to 36 characters and UUID v5. ## [Bank holidays](#bank-holidays) Bank holidays can cause delays in transfers. If you're creating a transfer on a bank holiday, it will be processed on the next business day. Settlement from the prior day's card sales will be delayed when the settlement day is a bank holiday. The Moov Dashboard will show a notice if a bank holiday is coming up. You can also check the [Federal Reserve website](https://www.frbservices.org/about/holiday-schedules) for a full list of bank holidays. Holidays observed by the Federal Reserve System include: - New Year's Day - Martin Luther King Jr. Day - Presidents' Day - Memorial Day - Juneteenth - Independence Day - Labor Day - Columbus Day - Veterans Day - Thanksgiving Day - Christmas Day ## [FAQ](#faq) Why did a transfer fail? Transfers can fail for a number of reasons related to the source or destination, or due to insufficient funds. Read our [transfer failures](/guides/money-movement/events-and-statuses/) guide to learn more. Can I re-start a transfer that never completed? Depending on the status of the transfer, you may be able to replay that transfer. Transfers in a "non-terminal" state (such as a child transfer stuck in `queued`) can be replayed by Moov, but transfers with the `failed` status are in a "terminal state," meaning they cannot be replayed in our system. For reinitiating transfers that were in a terminal state, you will need to create a brand new transfer with the same details. Why is my LIST transfers request taking so long? When you run a [LIST transfers](/api/money-movement/transfers/list/) request, you retrieve 200 transfers at a time. You can advance past a results set of 200 transfers by using the `skip` parameter (for example, if you set `skip`= 10, you will see a results set of 200 transfers after the first 2000). However, if you are searching a high volume of transfers, the request will likely process slowly. To get faster performance, restrict the data as much as you can by using the `StartDateTime` and `EndDateTime` parameters for a limited period of time. You can run multiple requests in smaller time window increments until you've retrieved all the transfers you need. --- URL: https://docs.moov.io/guides/money-movement/payment-links/ --- # Payment links Create payment links with Moov to send or accept from cards, bank accounts, or Apple Pay. Create a payment link from the [API](/api/money-movement/payment-links/) or the [Dashboard](https://dashboard.moov.io/signin) that you can send to merchants through your chosen form of communication, such as email or SMS. Use the generated payment link code to create a QR code for in-person payments. You can use payment links to disburse or accept a payment. The payment link flow authenticates a session that lets your customers securely create a Moov account and link payment methods before submitting payment through the link or QR code. Successfully submitted payment links will use the `transferID` and the `email`/`emailAccountID` to automatically create and send a [receipt](/api/money-movement/receipts/) via email. We suggest using the Dashboard’s payment link process to create payment links. Visit our [Dashboard documentation](/guides/dashboard/transfers/payment-links/) for more information. Before you send your first payment link, you have the option to set up brand colors. Moov offers light and dark mode brand settings, which you can set in the Dashboard or with the [API](/api/enrichment/branding/). Colors you select for light and dark modes will be used as accent colors throughout the customer's user experience, including the payment link UI. ## [Payment methods](#payment-methods) To **accept a payment**, you can choose any or all of the following payment methods: - Apple Pay - Card - ACH debit collect To **send a payment**, you can choose any or all of the following payment methods: - Push to card - RTP credit - ACH credit same day - ACH credit standard ## [Create a payment link](#create-a-payment-link) When creating a payment link, you're required to provide the merchant account ID in the path and the partner account ID in the request. Note that sometimes a partner can be acting as a merchant and therefore the ID is the same account ID for both. Additionally, you must send the merchant's payment method ID and the payment amount. You can optionally require other data such as customer address or phone number, metadata, and a custom dynamic descriptor for the statement. You can also set an expiration date and limit on the amount of times a payment link can be used. Once a payment link is created, you'll receive a sharable URL and QR code. The URL will be in the following format: `https://moov.link/p/{unique-payment-link}`. URLs and QR codes can be retrieved again using the `GET` [payment link](/api/money-movement/payment-links/get/) or [QR code](/api/money-movement/payment-links/get-qrcode/) endpoints, or in the Dashboard by navigating to **Transfers > Payment links**. [cURL](#tab-487539216-2-0) Use the payment links `POST` [endpoint](/api/money-movement/payment-links/create/) to send either a `payment` or `payout`. You can limit the amount of times a payment link can be used with the `maxUses` field. By setting `maxUses` to 0, there is no limit on the amount of times the link can be used. For payouts, `maxUses` is always `1`. The response will include a `paymentLinkCode`, which you can use to retrieve a specific payment link later on. Only the account that creates the payment link can update it. The `ownerAccountID` is returned in the response for reference. This ID will correspond to the `partnerAccountID` or `merchantAccountID` of the account that created the payment link. ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/payment-links" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "accountID": "c197cd40-7745-4413-8f3b-ec962d1b5225", "merchantPaymentMethodID": "3afc7533-7095-43bb-b21a-5c4dc5568451", "partnerAccountID": "d290f1ee-6c54-4b01-90e6-d701748f0851", "amount": { "currency": "USD", "value": 1204 }, "maxUses": 0, "expiresOn": "2025-08-24T14:15:22Z", "display": { "title": "string", "description": "string", "callToAction": "pay" }, "customer": { "requireAddress": true, "requirePhone": true, "metadata": { "property1": "string", "property2": "string" } }, "payment": { "allowedMethods": [ "apple-pay", "card-payment", "ach-debit-collect" ], "cardDetails": { "dynamicDescriptor": "WhlBdy *Yoga 11-12" }, "achDetails": { "companyEntryDescription": "Gym Dues", "originatingCompanyName": "Whole Body Fit" } } }'\ ``` ### [Line items](#line-items) When you create a payment link you have the option of creating a line item. Line items allow you to list items within the transaction, each with their own distinct name, description, image, and price modifier. For tracking purposes, you can give each item a unique identifier using the `productID` field. When using line items, the total `amount` of the payment link needs to include all additional costs and price modifiers associated with each item. ``` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 ``` ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/payment-links" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "accountID": "c197cd40-7745-4413-8f3b-ec962d1b5225", "merchantPaymentMethodID": "3afc7533-7095-43bb-b21a-5c4dc5568451", "partnerAccountID": "d290f1ee-6c54-4b01-90e6-d701748f0851", "amount": { "currency": "USD", "value": 1495 }, "maxUses": 0, "expiresOn": "2025-08-24T14:15:22Z", "display": { "title": "string", "description": "string", "callToAction": "pay" }, "customer": { "requireAddress": true, "requirePhone": true, "metadata": { "property1": "string", "property2": "string" } }, "lineItems": { "item": { "basePrice": { "currency": "USD", "valueDecimal": "14.95" }, "name": "Lunch combo 1", "productID": "5afv22245-7095-24ba-b21a-5c4dc993737", "quantity": 1 } }, "payment": { "allowedMethods": [ "apple-pay", "card-payment", "ach-debit-collect" ] } }' ``` ## [Get generated QR code](#get-generated-qr-code) To facilitate in-person payments, you have the ability to generate a QR code for a customer to use with the payment links QR `GET` [endpoint](/api/money-movement/payment-links/get-qrcode/). [cURL](#tab-512874936-4-0) To generate a QR code, pass the `accountID` and `paymentLinkCode`. ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/payment-links/{paymentLinkCode}/qrcode" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ ``` ## [Manage payment links](#manage-payment-links) Once a payment link is created, you can manage it through the API or the Dashboard. You can list all created payment links, find a specific one, update it, or disable it. ### [Retrieve](#retrieve) View a list of all payment links with the list payment links `GET` [endpoint](/api/money-movement/payment-links/list/), or view an individual payment link with the retrieve payment links `GET` [endpoint](/api/money-movement/payment-links/get/). [cURL - List all links](#tab-893264571-5-0) [cURL - Retrieve a link](#tab-893264571-5-1) To list all payment links for an account, pass the `accountID`. ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/payment-links" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ ``` To retrieve a specific payment link for an account, pass the `accountID` and `paymentLinkCode`. The payment link code is provided in the initial `POST` response when created a payment link. You can use the list payment link endpoint to retrieve all payment links and their payment link codes. ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/payment-links/{paymentLinkCode}" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ ``` ### [Update](#update) You have the ability to update certain properties of payment links with the payment links `PATCH` [endpoint](/api/money-movement/payment-links/update/). You can update the amount, expiration date, display options, customer data, as well as payment and payout options. Only the account that created the payment link can update the payment link. The `ownerAccountID` is returned in the create payment link response if needed for reference. [cURL](#tab-295418673-6-0) To update a payment link, pass the `accountID` and `paymentLinkCode`. ```zsh curl -X PATCH "https://api.moov.io/accounts/{accountID}/payment-links/{paymentLinkCode}" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "amount": { "currency": "USD", "value": 1204 }, "expiresOn": "2025-08-24T14:15:22Z", "display": { "title": "string", "description": "string", "callToAction": "pay" }, "customer": { "requireAddress": true, "requirePhone": true, "metadata": { "property1": "string", "property2": "string" } }, "payment": { "allowedMethods": [ "apple-pay" ], "cardDetails": { "dynamicDescriptor": "WhlBdy *Yoga 11-12" }, "achDetails": { "companyEntryDescription": "Gym Dues", "originatingCompanyName": "Whole Body Fit" } } }'\ ``` ### [Disable](#disable) You can disable a payment link at any time. Customers will receive an error page if they try and access a disabled payment link. Use the payment links `DEL` [endpoint](/api/money-movement/payment-links/delete/) to disable the link. [cURL](#tab-489675312-7-0) To delete (disable) a payment link, pass the `accountID` and `paymentLinkCode`. ```zsh curl -X DELETE "https://api.moov.io/accounts/{accountID}/payment-links/{paymentLinkCode}" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ ``` --- URL: https://docs.moov.io/guides/money-movement/payment-methods/ --- # Payment methods Payment methods represent how funds move into and out of Moov accounts. Payment methods are determined by an account's linked [funding sources](/guides/sources/): bank accounts, cards, or Moov wallets. When a funding source is linked, the associated payment methods become available. Some payment methods, such as `ach-debit-collect`, require additional steps like verifying the bank account. Each payment method has its own characteristics: - **Speed:** Instant, same-day, or 1-2 business days - **Network:** ACH, card networks (Visa/Mastercard), or real-time rails (RTP/FedNow) - **Risk:** Exposure to chargebacks and returns varies by method - **Cost:** Processing fees differ across payment rails Payment methods are separate from [capabilities](/guides/accounts/capabilities/reference/). A payment method defines *how* money moves, while a capability defines *what actions* an account can perform. - **Source payment methods** specify where funds originate - **Destination payment methods** specify where funds are delivered Most payment methods work in a single direction. The exception is `moov-wallet`, which can be both a source and a destination. * * * ## [Source payment methods](#source-payment-methods) Source payment methods fund a transfer. The source is where the money comes from. | Payment method | Funding source | Description | Can send to | |---------------------|----------------------------------------------------------------------|----------------------------------------------------|--------------------| | `moov-wallet` | Moov wallet | Transfer from a wallet balance | Wallet, Bank, Card | | `ach-debit-fund` | [Verified bank account](/guides/sources/bank-accounts/verification/) | Debit a bank account to fund a wallet or payouts | Wallet | | `ach-debit-collect` | [Verified bank account](/guides/sources/bank-accounts/verification/) | Debit a bank account for a consumer or B2B payment | Wallet | | `card-payment` | Card | Charge a credit or debit card | Wallet | | `apple-pay` | Apple Pay | Accept Apple Pay | Wallet | | `pull-from-card` | Debit/prepaid card | Pull funds from a debit or prepaid card | Wallet | * * * ## [Destination payment methods](#destination-payment-methods) Destination payment methods receive a transfer. The destination is where money goes. | Payment method | Funding source | Description | Can receive from | |-----------------------|--------------------|-------------------------------------------|--------------------| | `moov-wallet` | Moov wallet | Credit a wallet balance | Wallet, Bank, Card | | `ach-credit-standard` | Bank account | Credit a bank account (1-2 business days) | Wallet | | `ach-credit-same-day` | Bank account | Credit a bank account (same day) | Wallet | | `instant-bank-credit` | Bank account | Real-time credit via RTP or FedNow | Wallet | | `rtp-credit` | Bank account | Real-time credit via RTP (deprecated) | Wallet | | `push-to-card` | Debit/prepaid card | Instant credit to a debit card | Wallet | * * * ## [Payment methods and capabilities](#payment-methods-and-capabilities) Payment methods belong to an individual account, but [capabilities](/guides/accounts/capabilities/reference/) determine what the **initiating** account is allowed to do. - When **collecting funds**, the *destination account* requires a collect-funds capability. - When **sending funds**, the *source account* requires a send-funds capability. ### [Collecting funds](#collecting-funds) The destination account pulls from a payment method owned by the source (payer). The payer only needs `transfers`. | Source payment method | Destination account needs | |-----------------------------|---------------------------------| | `card-payment`, `apple-pay` | `collect-funds.card-payments` | | `ach-debit-collect` | `collect-funds.ach` | | `pull-from-card` | `money-transfer.pull-from-card` | **Example:** A merchant accepting a card payment pulls from the payer’s `card-payment` method. The merchant (destination) needs `collect-funds.card-payments` and `wallet.balance`. The payer (source) only needs `transfers`. * * * ### [Sending funds](#sending-funds) The source account pushes to a payment method owned by the destination (recipient). The recipient only needs `transfers`. | Destination payment method | Source account needs | |----------------------------------------------|------------------------------------------------------------| | `ach-credit-standard`, `ach-credit-same-day` | `send-funds.ach` | | `instant-bank-credit`, `rtp-credit` | `send-funds.instant-bank` | | `push-to-card` | `send-funds.push-to-card` or `money-transfer.push-to-card` | **Example:** A business sending a payout via `ach-credit-same-day` pushes funds to the recipient’s bank account. The business (source) needs `send-funds.ach` and `wallet.balance`. The recipient (destination) only needs `transfers`. For full details, see the [capabilities reference](/guides/accounts/capabilities/reference/) and [enablement guide](/guides/accounts/capabilities/enablement/). * * * ## [Funding source requirements](#funding-source-requirements) Payment methods require linked and verified funding sources: - **Bank account credit methods** (`ach-credit-same-day`, `instant-bank-credit`, etc.) require a [linked bank account](/guides/sources/bank-accounts/) - **Bank account debit methods** (`ach-debit-fund`, `ach-debit-collect`) require a [verified bank account](/guides/sources/bank-accounts/verification/) - **Card-based methods** (`card-payment`, `push-to-card`, etc.) require a [linked card](/guides/sources/cards/) - **Wallet-based methods** (`moov-wallet`) require an enabled [wallet](/guides/sources/wallets/) * * * ## [Get payment methods](#get-payment-methods) To retrieve payment methods for an account, use the: - [List payment methods](/api/sources/payment-methods/list/) - [Retrieve payment method](/api/sources/payment-methods/get/) ### [List payment methods](#list-payment-methods) [cURL](#tab-687132945-3-0) [Go SDK](#tab-687132945-3-1) [Moov.js](#tab-687132945-3-2) ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/payment-methods" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ ``` ```go mc, _ := moov.NewClient() var accountID string mc.ListPaymentMethods(ctx, accountID) ``` ```javascript const moov = Moov(token); moov.paymentMethods.list(accountID); ``` ### [Retrieve payment method](#retrieve-payment-method) [cURL](#tab-245837169-4-0) [Go SDK](#tab-245837169-4-1) ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/payment-methods/{paymentMethodID}" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ ``` ```go mc, _ := moov.NewClient() var accountID string var paymentMethodID string mc.GetPaymentMethod(ctx, accountID, paymentMethodID) ``` * * * ## [Transfer limits](#transfer-limits) The table below describes Moov platform or payment network limits. Individual accounts may have lower limits depending on [verification](/guides/accounts/requirements/identity-verification/) and [underwriting](/guides/accounts/requirements/underwriting/). To request higher limits, [contact Moov](https://support.moov.io/). | Payment method | Limit | |--------------------------------|------------------------------------------------| | `ach-debit-fund` (same day) | $1,000,000 | | `ach-debit-fund` (standard) | $99,999,999.99 | | `ach-debit-collect` (same day) | $1,000,000 | | `ach-debit-collect` (standard) | $99,999,999.99 | | `ach-credit-same-day` | $500,000 | | `ach-credit-standard` | $99,999,999.99 | | `instant-bank-credit` | $10,000,000 | | `rtp-credit` | $10,000,000 | | `moov-wallet` (as source) | Lesser of $99,999,999.99 or `availableBalance` | | `card-payment` | $99,999,999.99 | | `apple-pay` | $99,999,999.99 | | `push-to-card` | $25,000 | | `pull-from-card` | $10,000 | --- URL: https://docs.moov.io/guides/money-movement/receipts/ --- # Receipts Send branded receipts to payers for each transfer. Send a branded receipt which displays your logo, company name, and links to your customer service portals. You can send a receipt to the payer, the payee, or both. Branded receipts can be sent in the following scenarios: - Transfer has been initiated or confirmed - Transfer has been refunded - Transfer in a series has failed ![Receipt email](./receipt-example.png) [Receipts API \ Send a receipt to the payer after a transfer has been initiated.](/api/money-movement/receipts/) ## [Send receipts](#send-receipts) [Send a receipt](/api/money-movement/receipts/create/) using the transfer receipts `POST` [endpoint](/api/money-movement/transfers/create-receipts/). The examples below show how to send a receipt for a single transfer, a series of transfers, and a single occurrence in a series of transfers. If you want to send a receipt to a different email address, you can specify the `email` field instead of `emailAccountID`. [Transfer](#tab-124985367-0-0) [Schedule](#tab-124985367-0-1) [Occurrence](#tab-124985367-0-2) For a single transfer, use `forTransferID` and Moov will send the confirmation, refund, or failure receipt to the payer. ```json { "kind": "sale.customer.v1", "email": "customer@example.com", "forTransferID": "YOUR_TRANSFER_ID" } ``` Schedule receipts for a series of transfers by using `forScheduleID`. Moov will send the confirmation, refund, or failure receipt to the payer on every occurrence. ```json { "kind": "sale.customer.v1", "email": "customer@example.com", "forScheduleID": "YOUR_SCHEDULE_ID" } ``` For an individual occurrence in a series of transfers, use `forOccurrenceID`. Moov will send the confirmation, refund, or failure receipt to the payer. ```json { "kind": "sale.customer.v1", "email": "customer@example.com", "forOccurrenceID": "YOUR_OCCURRENCE_ID" } ``` ## [Retrieve receipts](#retrieve-receipts) You can retrieve a list of receipts with the transfer receipts `GET` [endpoint](/api/money-movement/transfers/list-receipts/). The following is an example response: ```zsh [ { "createdBy": "25a02396-1048-48f9-bf93-102d2fb7895e", "disabledOn": "2009-11-10T23:00:00Z", "email": "jordan.lee@classbooker.dev", "forTransferID": "193ceb53-94c7-41c4-9272-c90c2832cb4c", "kind": "sale.customer.v1", "receiptID": "4925c8a5-3b9a-4488-a514-9fd992546aca", "sentFor": [ { "idempotencyKey": "0c14c6a6-6f50-4d1e-b0c4-b46ff43ba6a1", "receiptID": "4925c8a5-3b9a-4488-a514-9fd992546aca", "sentOn": "2009-11-10T23:00:00Z" } ] } ] ``` ## [Transfer description](#transfer-description) When [creating a transfer](/api/money-movement/transfers/create/), you can provide a description that will be included in the receipt. This is useful for providing additional context to the payer. If no description is provided, the line item will simply include "Sale". ## [Sales tax](#sales-tax) For transfers that include sales tax, the emailed receipt will include a breakdown of the sales tax amount and the total amount paid. When sales tax is not set, the receipt will only include the total amount paid. ## [Multiple receipts](#multiple-receipts) You can create multiple receipts for the same transfer with the create receipt [endpoint](/api/money-movement/receipts/create/). Creating multiple receipts for a transfer is useful if you want to send a receipt to more than one recipient for the same transaction. You can send multiple receipts for a transfer by sending more than one receipt object in the request, each with a different email address and the associated `forTransferID`. If the transaction is part of a scheduled transfer or an occurrence, you can send the associated `forScheduleID` or `forOccurrenceID` instead. ```zsh curl -X POST "https://api.moov.io/receipts" \ -H "Authorization: Bearer {token}" \ --data '[ { "kind": "sale.customer.v1", "email": "customer1@example.com", "forTransferID": "YOUR_TRANSFER_ID" }, { "kind": "sale.customer.v1", "email": "customer2@example.com", "forTransferID": "YOUR_TRANSFER_ID" }, { "kind": "sale.customer.v1", "email": "billing@example.com", "forTransferID": "YOUR_TRANSFER_ID" } ]'\ ``` ## [Receipt emails](#receipt-emails) Receipt emails are optimized to work on all screen sizes and for all email clients. ### [Sales / purchases](#sales--purchases) Receipts for purchases include the following details: - Transfer amount - Transfer date - Receipt ID - Transfer description (if provided) - Source payment method - Sales tax amount and total amount paid (if applicable) - Issuer confirmation number (if applicable) ### [Refunds](#refunds) Receipts for refunds include the following details: - Refund amount - Refund date - Original payment method - Receipt ID ### [Failures](#failures) Receipts for failed transfers include the following details: - Transfer amount - Receipt ID - Source payment method --- URL: https://docs.moov.io/guides/money-movement/scheduling/ --- # Scheduled transfers Automate money movement on a recurring basis. Define a recurring schedule with a transfer amount, source, and destination. With scheduled transfers, you can create a schedule for a variety of purposes, such as sending payments, setting up a subscription or financing. You can create a schedule specific to your needs, or set [RRULE](https://datatracker.ietf.org/doc/html/rfc5545#section-3.3.10) and let Moov create the schedule. [Schedules API \ Set up future transfers through scheduling.](/api/money-movement/schedules/) ## [Set up a schedule](#set-up-a-schedule) You can set up a schedule of future-dated transfers in a combination of ways - by generating a schedule through Moov, or by providing your own specific future dates. ![Creating a schedule](images/schedule.png) Set up recurring transfers in the Dashboard [Generate a schedule](#tab-253619784-3-0) [Provide your own future dates](#tab-253619784-3-1) Provide transfer details and a recurrence rule for Moov to generate each occurrence of a transfer dated for the future. The `recurrenceRule` accepts a string that conforms to the [RRULE](https://datatracker.ietf.org/doc/html/rfc5545#section-3.3.10). This option is useful for creating a schedule that continues indefinitely or until a date or count where all transfer details are the same. For the account being charged, use the create a schedule `POST` [endpoint](/api/money-movement/schedules/create/). ```json { "description": "Monthly subscription", "recur": { "recurrenceRule": "FREQ=MONTHLY;COUNT=36", "runTransfer": { "amount": { "currency": "USD", "amount": 1000 }, "accountID": "your-account-ID", "source": { "paymentMethodID": "payment-method-ID" }, "destination": { "paymentMethodID": "payment-method-ID" } } } } ``` A recurrence rule is typically made up of the following: - `FREQ` - frequency (daily, weekly, monthly) (required) - `INTERVAL` - interval (1, 2, etc) - `DTSTART` - The recurrence start date - `UNTIL` - The recurrence end date. Not present if indefinite - `COUNT` - The number of occurrences that will be generated. Not present if indefinite Once `DTSTART` is set it should not be changed as it can cause unintended changes to occurrence timing. We suggest you set it to a static value you can continuously use when creating schedules, or leave it empty, which will allow Moov to use our own static value. Create the occurrences of each transfer with a specific date for Moov to initiate them. This option is recommended if the transfer details differ between any occurrences, or if the recurring dates don't follow a pattern supported by [RRULE](https://datatracker.ietf.org/doc/html/rfc5545#section-3.3.10). For the account being charged, create a schedule using `POST` `/accounts/{accountID}/schedules` ```json { "description": "Repayment", "occurrences": [ { "runOn": "datetime", "runTransfer": { "amount": { "currency": "USD", "amount": 1000 }, "source": { "paymentMethodID": "payment-method-ID" }, "destination": { "paymentMethodID": "payment-method-ID" } } }, // remaining occurrences ] } ``` It's possible to combine `recur` and `occurrences` into a single schedule, such as for a one-time charge along with scheduled transfers. For projects written in Go, we recommend [rrule-go](https://github.com/teambition/rrule-go) if you need to support complex recurring rules. For JavaScript projects, we recommend [rrule.js](https://github.com/jkbrzt/rrule). ## [Manage schedules](#manage-schedules) Once created, a schedule can be updated to: - Modify or cancel a future individual occurrences. - Change the recurrence rule. Future occurrences will shift according to the new rule. - Add a new one time occurrence. For example, a fine, or to retry a failed occurrence. - Update the transfer or `runOn` time of an individual occurrence. - Update one transfer in a set of recurring transfers and have the updates apply to all future recurring occurrences. Once created, a schedule can be updated to modify or remove individual occurrences, as well as stop any future transfers from being created. However, transfers that have already been created from a schedule will not be canceled by updating a schedule. Occurrences past the `runOn` time cannot be changed. Only the account that creates the schedule can modify it. An `ownerAccountID` is returned in the [create response](#set-up-a-schedule) for reference. This ID will correspond to the `partnerAccountID` or `merchantAccountID` of the account that created the schedule. You can [list all schedules](/api/money-movement/schedules/list/) for an account with the `GET` `/accounts/{accountID}/schedules` endpoint. This is useful for displaying any scheduled payments to a user, such as the next payment date and amount. ## [Send receipts](#send-receipts) Use the transfers API to [send a receipt](/api/money-movement/transfers/create-receipts/) to the payer after each transfer in the schedule has been initiated. By passing `forScheduleID` in the receipt creation endpoint, you can link the receipt to the schedule and Moov will send receipts automatically for each future occurrence. [Receipts guide \ Send a receipt to the payer after a transfer has been initiated.](/guides/money-movement/receipts/) [Receipts API \ API reference for sending receipts.](/api/money-movement/receipts/) ## [Automatic updates to payment methods](#automatic-updates-to-payment-methods) For debit and credit card payments that have [card-on-file](/guides/sources/cards/card-account-updater/#set-cardonfile) enabled, any issuer updates to the card will allow future-dated transfers to process. Card-based transfers in a schedule are also automatically set with the correct `transactionSource` specifying `first-recurring` or `recurring`. Likewise, for bank accounts, if Moov receives a notice of change from the receiving financial institution, the bank account will be automatically updated to prevent interruption. --- URL: https://docs.moov.io/guides/money-movement/send-payments/ --- # Send payments Learn how to facilitate transfers between accounts, transfer funds to yourself, and send payouts. The guides in this section provide step by step instructions for various transfer scenarios. If you'd like to send a payment using payment links, visit our [payment links](/guides/money-movement/payment-links/) guide. --- URL: https://docs.moov.io/guides/money-movement/send-payments/push-to-card/ --- # Push to card Provide faster access to funds for your customers by pushing funds to cards. Moov supports push to card payments - instant payments from a Moov wallet to supported Visa and Mastercard debit and prepaid cards. With push to card, you can access funds near real time, 24/7/365. ![Push to card funds flow diagram](../images/push-to-card-funds-flow-light.png) ## [Use cases](#use-cases) Moov supports push transfers for two use cases: merchant settlement and funds disbursement. Moov will configure the source account depending on your use case: **Merchant settlement** is commonly used by businesses that are looking to access their funds faster through a self-to-self transfer from their wallet to a card. If you're using push to card for merchant settlement, the source account must have the `wallet` [capability](/guides/accounts/capabilities/enablement/) enabled. **Funds disbursement** enables real-time transfers to another account. Some funds disbursement examples include gig economy payouts, insurance disbursements, corporate rebates, payroll, government, or reimbursements. If you're using push to card for funds disbursement, the source account must have the `send-funds.push-to-card` [capability](/guides/accounts/capabilities/enablement/) enabled. ## [Determine support for push to card](#determine-support-for-push-to-card) Ensure you have linked a card on the account. The simplest way to securely link a card is by using the [card link Drop](/moovjs/drops/card-link/), a prebuilt UI component for embedding card-based payments. If you have provided an attestation of PCI compliance, you also have the option to link a card using the `POST` [link a card](/api/sources/cards/create/) endpoint. Once you've linked a card, you can determine if that card is eligible to receive pushed funds with the `domesticPushtoCard` field. You can use the cards `GET` [endpoint](/api/#tag/Cards/operation/getCard) as shown below. [curl](#tab-467835912-2-0) [Go SDK](#tab-467835912-2-1) ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/cards" \ -H 'Authorization: Bearer {token}' \ ``` ```go mc, _ := moov.NewClient() var accountID string var cardID string mc.GetCard(ctx, accountID, cardID) ``` The `domesticPushtoCard` field describes the push to card timing that is available for the card, if supported: | Timing | Description | |-----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `fast-funds` | Funds will be available to the destination within 30 minutes or less of the authorization. | | `standard` | Fast funds is not supported on this card. Transfer will follow standard card settlement [timing](/guides/money-movement/accept-payments/card-acceptance/timing/). | | `not-supported` | This card is ineligible for push-to-card payments. Contact your issuer for more details. | | `unknown` | Eligibility has not been checked or is unknown. | ## [Implement push to card](#implement-push-to-card) You can simulate push to card transfers in test mode using [specific test cards](/guides/get-started/test-mode/#push-to-card--pull-from-card). The `push-to-card` payment method becomes available when the following criteria are met: - The account has the `transfers` capability - The linked card supports `fast-funds` or `standard` timing - Moov has approved the account for push to card transfers Moov has a transfer limit of $50,000 per push to card transaction. Moov may impose lower transfer limits based on the approved use case. ### [Initiate the transfer](#initiate-the-transfer) A push transfer can be created when the source is a pre-funded Moov wallet and the destination is a recipient with a linked card and the `transfers` capability. [curl](#tab-159346728-0-0) [Go SDK](#tab-159346728-0-1) ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/transfers" \ -H "Authorization: Bearer {token}" \ -H "X-Idempotency-Key: UUID" \ -H "X-Wait-For: rail-response" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "amount": { "value": 100, "currency": "USD" }, "destination": { "paymentMethodID": "string" }, "source": { "paymentMethodID": "string" }, "description": "Optional transaction description." }'\ ``` ```go mc, _ := moov.NewClient() var accountID string // Partner account mc.CreateTransfer(ctx, accountID, moov.CreateTransfer{ Amount: moov.Amount{ Currency: "USD", Value: 100, // $1.00 }, Destination: moov.CreateTransfer_Destination{ PaymentMethodID: "string", }, Source: moov.CreateTransfer_Source{ PaymentMethodID: "string", }, Description: "Optional transaction description.", }) ``` ### [Track transfer status](#track-transfer-status) To track the transfer status, view `cardDetails` under the `destination` object from the transfers `GET` [endpoint](/api/money-movement/transfers/get/): 1. `initiated` - Transaction is created and awaiting authorization 2. `failed` - Issuer declined or there was error with processing 3. `completed` - Authorization request was successful and Issuer approved the transaction If the card is `fast-funds` eligible, the destination’s card will be credited the amount specified within 30 minutes. Otherwise, the funds will be credited according to the standard network settlement [timing](/guides/money-movement/accept-payments/card-acceptance/timing/). [curl](#tab-971865423-0-0) [Go SDK](#tab-971865423-0-1) ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/transfers/{transferID}" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ ``` ```go mc, _ := moov.NewClient() var accountID string var transferID string mc.GetTransfer(ctx, accountID, transferID) ``` ## [Transfer & velocity limits](#transfer--velocity-limits) There are limits on the amount a card `fingerprint` can send within a specified time. Depending on the card brand, you will need to follow these limits specifying the maximum amount and count that the destination account can receive. The following limits are for Visa and Mastercard. | Limit type | Maximum limit | |-----------------|------------------------------| | Amount | $50,000 | | 1-day velocity | 150 transactions or $100,000 | | 7-day velocity | 250 transactions or $250,000 | | 30-day velocity | 750 transactions or 500,000 | Moov may impose lower transfer limits based on the approved use case. ### [Error responses](#error-responses) **Amount limit:** If you have exceeded the amount limit, you'll receive a `400` error response. You can retry the transfer with a lower amount. **Velocity limits:** If you have exceeded the velocity limits, push to card transfers will fail. The transfer status will be `failed` and the failure reason will be `rejected-high-risk`. **Issuer limits:** If you have exceeded issuer limits, the transfer status will be `failed` and the failure reason will be `destination-payment-error`. Contact the issuer if you require guidance on specific issuer limits. The specific transaction decline code can be found in `cardDetails.failureCode` using the retrieve a transfer [endpoint](/api/money-movement/transfers/) or the list transfers [endpoint](/api/money-movement/transfers/get/). You'll also receive a `400` error response if your account is not enabled for disbursement. If you need to enable disbursement, please [contact Moov](https://support.moov.io/) so we can configure your account accordingly. --- URL: https://docs.moov.io/guides/money-movement/send-payments/rtp/ --- # RTP transfers Instantly send funds from a Moov wallet to a bank account with RTP. RTP (Real-time payments), enabled by [The Clearing House](https://www.theclearinghouse.org/), are instant payments between bank accounts. With RTP, transfers are processed almost immediately, 24/7/365. About 65% of US demand deposit accounts can participate in the RTP network, with more banks adding support regularly. With Moov, supported bank accounts can receive RTP transfers from a Moov wallet instantly. ![Standard RTP funds flow diagram](../images/moov-rtp-funds-flow-light.png) ## [Bank account eligibility](#bank-account-eligibility) When a bank account is linked, Moov checks its eligibility to receive payments on the RTP network and creates the `instant-bank-credit` payment method (or `rtp-credit` for legacy accounts). To use RTP, accounts must have the `send-funds.instant-bank` and `wallet.balance` [capabilities](/guides/accounts/capabilities/enablement/) enabled. ## [Money out](#money-out) Funds leave the Moov platform with RTP credits when using the `instant-bank-credit` payment method (or `rtp-credit` for legacy accounts). Once funds are sent, the transfer is final and cannot be reversed. For RTP credit, Moov has a platform limit of $10,000,000.00 per transaction. [Wallet to bank (RTP)](#tab-247186539-2-0) ![Wallet to bank RTP flow diagram](../images/../images/wallet-to-bank-rtp-light.png) The benefits of sending funds with RTP: - RTP transfers can be sent instantly, anytime - even on weekends and bank holidays - Funds are available to the recipient in moments - Moov wallet balances are immediately decreased ## [RTP processing and status details](#rtp-processing-and-status-details) The `rtpDetails` object offers a variety of useful information about RTP transfers and status details. You can obtain details about a transfer through the transfers `GET` [endpoint](/api/money-movement/transfers/get/). If the destination uses an RTP payment method, the transfers details response will contain an `rtpDetails` object that contains the following information: - `status` - Rail-specific status details - `failureCode` - Moov designated failure explanation - `networkReasonCode` - The Clearing House raw failure code response ### [RTP statuses](#rtp-statuses) The `rtpDetails` contains rail-specific transfer status information: | Transfer status | Description | |----------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `initiated` | The payment has reached the rail, but Moov has not yet received a response | | `accepted-without-posting` | Moov has received an accepted without posting message from the receiving bank, as they need more time to process the payment. The funds are moved but are not yet available to the recipient. | | `completed` | Moov has received an accepted message from the receiving bank, and funds are available to the recipient | | `failed` | Moov has received a rejected message from the receiving bank. The failure code, reason, and description is provided in the transfer response. | ### [Failure codes](#failure-codes) If there is an issue with a bank account, Moov automatically adjusts the status. If you receive an `errored` bank account status, you will need to take the following action before you can continue processing with Moov: - Add a new bank account (or [contact Moov](https://support.moov.io/)) Below you'll find the details on failure codes and the action you'll need to take. | Failure code | Description | Status: action | |-----------------------------|---------------------------------------------------------------|----------------------------| | `account-blocked` | Account is blocked. Transactions cannot be posted against it. | `errored`: Add new account | | `account-closed` | Account is closed. | `errored`: Add new account | | `customer-deceased` | Customer is deceased. | `errored`: Add new account | | `invalid-account` | Account number is invalid or missing. | `errored`: Add new account | | `invalid-amount` | Amount entered is invalid. | No action needed | | `invalid-field` | A field entry could not be validated. | No action needed | | `limit-exceeded` | Amount entered exceeds approved amount. | No action needed | | `processing-error` | Transaction could not be processed due to processing error. | No action needed | | `transaction-not-supported` | Transaction is not supported. | No action needed | Refer to the [The Clearing House's](https://www.theclearinghouse.org/payment-systems/rtp/technical-documentation) **Message Status Report appendix** for the latest ISO RTP error codes (`networkReasonCode`). --- URL: https://docs.moov.io/guides/money-movement/send-payments/send-funds/ --- # Send funds tutorial Follow this step by step guide to send funds using our API or SDKs. This guide covers how to send funds. This covers multiple use cases, including: - Payouts to employees, gig workers, and contractors - Facilitating transfers between accounts on a platform The examples below provide step by step instructions on setting up a single transfer, as well as instructions for payouts in a transfer group. For more detailed information, see the [payment methods](/guides/money-movement/payment-methods/) and [transfer groups](/guides/money-movement/transfer-groups/) guides. [Payouts](#tab-421763598-1-0) [Account-to-account](#tab-421763598-1-1) ## [Get accountID](#get-accountid) Retrieve the `accountID` for the Moov account you want to use as a source. Repeat the step for the destination(s). You'll use the `accountID` to retrieve the payment methods in the next step. [cURL](#tab-724351968-0-0) [Go SDK](#tab-724351968-0-1) List account [reference](/api/moov-accounts/accounts/list/) ```zsh curl -X GET "https://api.moov.io/accounts" \ -H "Authorization: Bearer {token}" ``` List account [reference](/api/moov-accounts/accounts/list/) ```go mc, _ := moov.NewClient() mc.ListAccounts(ctx) ``` ## [Get payment methods](#get-payment-methods) Get the `paymentMethodID` for both the source and destination accounts. [cURL](#tab-173652948-0-0) [Go SDK](#tab-173652948-0-1) [Moov.js](#tab-173652948-0-2) List payment methods [reference](/api/sources/payment-methods/list/) ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/payment-methods" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ ``` List payment methods [reference](/api/sources/payment-methods/list/) ```go mc, _ := moov.NewClient() var accountID string mc.ListPaymentMethods(ctx, accountID) ``` List payment methods [reference](/api/sources/payment-methods/list/) ```javascript const moov = Moov(token); moov.paymentMethods.list(accountID); ``` A successful response will return an array of payment method types. A source can be one of the following types: - `ach-debit-fund` - `moov-wallet` A destination can be one of the following types: - `ach-debit-collect` - `ach-credit-standard` - `ach-credit-same-day` - `moov-wallet` - `rtp-credit` See the [payment methods](/guides/money-movement/payment-methods/#payment-methods) guide for information on what source and destination types are compatible. ## [Create the transfer](#create-the-transfer) To send a payout, create a transfer from a sender (source) to a recipient (destination). [cURL](#tab-289643157-0-0) [Go](#tab-289643157-0-1) ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/transfers" \ -H "Authorization: Bearer {token}" \ -H "X-Idempotency-Key: UUID" \ -H "X-Wait-For: rail-response" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "source": { "paymentMethodID": "string" }, "destination": { "paymentMethodID": "string" }, "amount": { "value": 315, // $3.15 "currency": "USD" }, "description": "Optional description of transaction" }'\ ``` ```go mc, _ := moov.NewClient() var accountID string mc.CreateTransfer(ctx, accountID, moov.CreateTransfer{ Source: moov.CreateTransfer_Source{ PaymentMethodID: "string", }, Destination: moov.CreateTransfer_Destination{ PaymentMethodID: "string", }, Amount: moov.Amount{ Value: 315, // $3.15 Currency: "USD", }, Description: "Optional description of transaction", }) ``` ### [Line items](#line-items) When you create a transfer you have the option of creating a line item. Line items allow you to list items within the transaction, each with their own distinct name, description, image, options, and price modifier. For tracking purposes, you can give each item a unique identifier using the `productID` field. The total amount of the transfer must account for any and all costs associated with a line item's base price and price modifiers as well as sales tax: `amount` = `lineItems` + `salesTaxAmount` ``` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 ``` ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/transfers" \ -H "Authorization: Bearer {token}" \ -H "X-Idempotency-Key: UUID" \ -H "X-Wait-For: rail-response" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "amount": { "value": 1595, "currency": "USD" }, "destination": { "paymentMethodID": "string" }, "source": { "paymentMethodID": "string" }, "description": "Optional transaction description.", "lineItems": { "item": { "basePrice": { "currency": "USD", "valueDecimal": "14.95" }, "name": "Lunch combo 1", "productID": "5afv22245-7095-24ba-b21a-5c4dc993737", "quantity": 1 } }, "salesTaxAmount": { "currency": "USD", "value": 100 } }' ``` ### [Send funds using a transfer group](#send-funds-using-a-transfer-group) You have the option to use transfer groups when sending payouts. To create a transfer group, provide the `transferID` (of the immediate preceding transfer) as the `source`. Transfers that belong to a group must have an amount less than or equal to the amount of the source transfer. See the [transfer groups](/guides/money-movement/transfer-groups/) guide for more detailed information. ```json { "source": { "transferID": "transferID" }, "destination": { "paymentMethodID": "string" }, "amount": { "value": 315, // $3.15 "currency": "USD" }, "description": "Optional description of transaction" } ``` ## [Track the transfer](#track-the-transfer) You have the option of subscribing to the `transfer.updated` [webhook event](/guides/webhooks/webhook-events/#transfers). This will notify you of transfer stage updates (rail specific granular updates will also trigger the event). See the diagram below for examples of **ACH same-day transfer timing**. The payment is processed the same day, then funds will be made available later to account for possible returns or processing issues. ![ACH same-day processing flow diagram](../../images/bank-to-bank-same-day-light.png) ## [Next steps](#next-steps) [Events and statuses](/guides/money-movement/events-and-statuses/) [Fees](/guides/money-movement/fees/) --- URL: https://docs.moov.io/guides/money-movement/send-payments/transfer-funds-to-yourself/ --- # Transfer funds to yourself tutorial Follow this step by step guide to send funds to yourself using our API or SDKs. This guide covers how transfer funds to yourself. Some examples of self-to-self transfers include: - A company transferring funds between accounts at two separate banks - A contractor moving money from their [Moov wallet](/guides/get-started/glossary/#wallets) to their bank account - A platform adding funds from their bank account to their [Moov wallet](/guides/get-started/glossary/#wallets) In this guide, we'll use an example where you're performing a transfer from your wallet to your bank account. For the purposes of this guide, we'll assume that you've created a Moov account and gotten your API keys. For more detailed instructions, see our [quick start](/guides/quick-start) guide. ## [Set up the account](#set-up-the-account) Start by creating your Moov account. Request at least one `send-funds` capability for the account. You will need to submit specific data about the user to Moov for verification before the capability is enabled. See our [capabilities](/guides/accounts/capabilities/#capability-requirements) guide for a list of required information. [cURL](#tab-239145786-0-0) [Go SDK](#tab-239145786-0-1) [Moov.js](#tab-239145786-0-2) ```zsh curl -X POST "https://api.moov.io/accounts" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "accountType": "individual", "profile": { "individual": { "email": "julesjacksonyoga@moov.io", "name": { "firstName": "Jules", "lastName": "Jackson", } }, "capabilities": ["send-funds"], "foreignID": "unique-correlation-id" } }'\ ``` ```go mc, _ := moov.NewClient() mc.CreateAccount(ctx, moov.CreateAccount{ Type: moov.AccountType_Business, Profile: moov.CreateProfile{ Business: &moov.CreateBusinessProfile{ Name: "Whole Body Fitness LLC", Type: moov.BusinessType_Llc, }, }, RequestedCapabilities: []moov.CapabilityName{ moov.CapabilityName_SendFundsACH, }, ForeignID: "unique-correlation-id", }) ``` ```javascript const moov = Moov(token); const accountPayload = { accountType: "individual", profile: { individual: { email: "julesjacksonyoga@moov.io", name: { firstName: "Jules", lastName: "Jackson" } } }, capabilities: ["send-funds"], foreignID: "unique-correlation-id" }; const account = await moov.accounts.create({accountPayload}); ``` ## [Add bank account](#add-bank-account) Next, link your bank account account to your Moov account. [cURL](#tab-879531624-0-0) [Go SDK](#tab-879531624-0-1) [Moov.js](#tab-879531624-0-2) ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/bank-accounts" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "account": { "accountNumber": "0004321567000", "bankAccountType": "checking", "holderName": "Jules Jackson", "holderType": "individual", "routingNumber": "123456789" } }'\ ``` ```go mc, _ := moov.NewClient() var accountID string mc.CreateBankAccount(ctx, accountID, moov.WithBankAccount(moov.BankAccountRequest{ AccountNumber: "0004321567000", AccountType: moov.BankAccountType_Checking, HolderName: "Jules Jackson", HolderType: moov.HolderType_Individual, RoutingNumber: "123456789", }), moov.WaitForPaymentMethod()) ``` ```javascript const moov = Moov(token); const accountID = "accountID"; const bankAccountPayload = { accountNumber: "0004321567000", bankAccountType: "checking", holderName: "Jules Jackson", holderType: "individual", routingNumber: "123456789" }; moov.accounts.bankAccounts.link({accountID, bankAccountPayload}); ``` ## [Get payment methods](#get-payment-methods) First, get a list of the available payment methods from the generate transfer options `POST` [endpoint](/api/money-movement/transfers/options/). Specify your account ID as both the source and the destination. You will get a list that includes all the payment methods you can use to make a self-to-self transfer. The payment method for the source of the transfer will be `moov-wallet`, while the payment method for the destination will be `ach-credit-standard` or `ach-credit-same-day`. [cURL](#tab-518632947-0-0) [Go SDK](#tab-518632947-0-1) ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/transfer-options" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "amount": { "value": 100, "currency": "USD" } "destination": { "accountID": "string" }, "source": { "accountID": "string" } }'\ ``` ```go mc, _ := moov.NewClient() // your partner accountID var accountID string mc.TransferOptions(ctx, accountID, moov.CreateTransferOptions{ Source: moov.CreateTransferOptionsTarget{ AccountID: "string", }, Destination: moov.CreateTransferOptionsTarget{ AccountID: "string", }, Amount: moov.Amount{ Currency: "USD", Value: 1, }, }) ``` ## [Initiate the transfer](#initiate-the-transfer) Once you've selected your payment methods, you can initiate a [transfer](/api/#tag/transfers) from your bank account to your wallet, using the payment method IDs you got earlier in the transfer options request. [cURL](#tab-482975613-0-0) [Go SDK](#tab-482975613-0-1) ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/transfers" \ -H "Authorization: Bearer {token}" \ -H "X-Idempotency-Key: UUID" \ -H "X-Wait-For: rail-response" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "amount": { "value": 100, "currency": "USD" }, "destination": { "paymentMethodID": "string" }, "source": { "paymentMethodID": "string" }, "description": "Optional transaction description." }'\ ``` ```go mc, _ := moov.NewClient() var accountID string // Partner account mc.CreateTransfer(ctx, accountID, moov.CreateTransfer{ Amount: moov.Amount{ Currency: "USD", Value: 100, // $1.00 }, Destination: moov.CreateTransfer_Destination{ PaymentMethodID: "string", }, Source: moov.CreateTransfer_Source{ PaymentMethodID: "string", }, Description: "Optional transaction description.", }) ``` --- URL: https://docs.moov.io/guides/money-movement/transfer-groups/ --- # Transfer groups Transfer groups eliminate delays and create a seamless payment experience for multiple parties involved in a single transaction payment flow. Implement transfer groups to associate multiple transfers together and run them sequentially. The final beneficiary in a chain of transfers is made aware of incoming funds before they land in their account. This gives platforms more control over the flow of funds which can be beneficial for reporting and preserving the context of the original transfer. ## [Transfer group use cases](#transfer-group-use-cases) With a transfer group, you can split a transfer into two or more child transfers with distinct destinations. The sum of the child transfers must be less than or equal to the amount of the preceding transfer. For example, if a service-based platform is collecting payments from customers and transferring those funds to the service provider, transfer groups enable funds to flow: - From customers to the platform - From the platform to the service provider The service provider will be able to know that their service fee is incoming at the time of the initial charge, while also giving them the context of the processing fees included as a line item. ## [Guidelines](#guidelines) - Child transfers must be less than or equal to the original transfer amount - You can collect a fee on one or all transfers in the group, but consider the net amount when creating the subsequent transfer - If a child transfer destination is set to a bank account, the child transfer can't become the source of additional transfers ## [Create a transfer group](#create-a-transfer-group) To create a transfer group, provide the `transferID` in the source of your `POST` request of the immediate preceding transfer. Transfers that belong to a group must have an amount less than or equal to the amount of the source transfer. ```json { "source": { "transferID": "string" }, "destination": { "paymentMethodID": "string" }, "amount": {} } ``` ## [Transfer statuses](#transfer-statuses) | Status | Description | |-------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `queued` | A transfer that is part of a group will have the `queued` status until the preceding transfer has successfully `completed` | | `pending` | After the preceding transfer has `completed`, the next transfer will be `pending` indicating we have kicked off the money movement process | | `completed` | The transfer has completed | | `canceled` | When a preceding transfer fails, subsequent transfers will be canceled and the funds will be at the destination of the last completed transfer | | `failed` | If a transfer in a group fails, all subsequent transfers will be `canceled`. For `failed` transfers, you will be able to retry the transfer at any point. The most common reason a transfer in a group may fail is if a wallet doesn’t have sufficient funds in order to fund the next transfer. | Use the `transfer.updated` [webhook](/guides/webhooks/webhook-events/) event to subscribe to changes on the parent and child transfers. ## [Transfer group IDs](#transfer-group-ids) When any amount of transfers are linked through a parent-child relationship, they will share a `groupID`. Moov mints and assigns an identifier for the transfer group automatically, which is the `transferID` of the most senior parent transfer. If a transfer belongs to a group, the `groupID` will be returned in the transfers `GET` [response](/api/money-movement/transfers/get/). ```json { "transferID": "", "createdOn": "", "status": "queued", "source": { "transferID": "string", "paymentMethodID": "string", "paymentMethodType": "moov-wallet", "wallet": { "walletID": "string" }, "account": {} }, "destination": {}, "amount": {}, "groupID": "string" } ``` ## [Get all transfers in a group](#get-all-transfers-in-a-group) You can find all transfers in a transfer group by passing the `groupID` to the list transfers `GET` [endpoint](/api/money-movement/transfers/list/). Applying this filter will result in a list of transfers that belong to the group. You can assemble a chain of events by requesting all of the transfers in a group, and recursively comparing the `source.transferID` of each child transfer. --- URL: https://docs.moov.io/guides/money-movement/wallets/cash-out/ --- # Cash out a wallet Follow this step by step guide to cash out funds from a Moov wallet with our API, SDKs, or Moov.js. This guide covers how to cash out funds from a Moov wallet. If you're looking to cash out funds but haven't yet linked and verified a bank account, see our step by step guide on [linking bank accounts](/guides/sources/bank-accounts/link-bank-accounts/link-bank-accounts/). There are other things you can do with wallet funds, such as: - Spend on an issued card - Transfer funds to another Moov wallet For the purposes of this guide, we'll cover cashing out funds through a wallet-to-bank transfer. ## [Get accountID](#get-accountid) The first step is identifying the`accountID` for the Moov account with the wallet you would like to cash out. If you don't already have it, you can use the list accounts `GET` [endpoint](/api/moov-accounts/accounts/list/) as shown below. [cURL](#tab-329675814-0-0) [Go SDK](#tab-329675814-0-1) List account [reference](/api/moov-accounts/accounts/list/) ```zsh curl -X GET "https://api.moov.io/accounts" \ -H "Authorization: Bearer {token}" ``` List account [reference](/api/moov-accounts/accounts/list/) ```go mc, _ := moov.NewClient() mc.ListAccounts(ctx) ``` ## [Select the payment methods for the transfer](#select-the-payment-methods-for-the-transfer) Get the `paymentMethodIDs` to use as the source and destination when creating a transfer in the next step. [cURL](#tab-867134295-0-0) [Go SDK](#tab-867134295-0-1) [Moov.js](#tab-867134295-0-2) List payment methods [reference](/api/sources/payment-methods/list/) ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/payment-methods" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ ``` List payment methods [reference](/api/sources/payment-methods/list/) ```go mc, _ := moov.NewClient() var accountID string mc.ListPaymentMethods(ctx, accountID) ``` List payment methods [reference](/api/sources/payment-methods/list/) ```javascript const moov = Moov(token); moov.paymentMethods.list(accountID); ``` A successful response will return an array of payment methods of different types. For the transfer source, you'll select the payment method ID associated with the `moov-wallet` payment method type. For the transfer destination, you can choose the payment method ID associated with one of the following payment method types surfaced in the response: - `ach-credit-standard` - `ach-credit-same-day` - `rtp-credit` To learn more about the timing associated with these payment methods, read our guides on ACH and RTP: [ACH processing speed](/guides/money-movement/accept-payments/ach/ach-processing-speeds/) [RTP](/guides/money-movement/send-payments/rtp/) ## [Create the transfer](#create-the-transfer) Using the payment method IDs you got from step 2, you can now initiate a transfer. Once the transfer has completed, the funds will settle in the destination bank account. [cURL](#tab-896435127-0-0) [Go SDK](#tab-896435127-0-1) Create transfer [reference](/api/money-movement/transfers/create/) ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/transfers" \ -H "Authorization: Bearer {token}" \ -H "X-Idempotency-Key: UUID" \ -H "X-Wait-For: rail-response" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "amount": { "value": 100, "currency": "USD" }, "destination": { "paymentMethodID": "string" }, "source": { "paymentMethodID": "string" }, "description": "Optional transaction description." }'\ ``` Create transfer [reference](/api/money-movement/transfers/create/) ```go mc, _ := moov.NewClient() var accountID string // Partner account mc.CreateTransfer(ctx, accountID, moov.CreateTransfer{ Amount: moov.Amount{ Currency: "USD", Value: 100, // $1.00 }, Destination: moov.CreateTransfer_Destination{ PaymentMethodID: "string", }, Source: moov.CreateTransfer_Source{ PaymentMethodID: "string", }, Description: "Optional transaction description.", }) ``` ## [Track the status of the transfer](#track-the-status-of-the-transfer) After you've created the bank-to-wallet transfer, you can track the status of the transfer by retrieving the transfer or using webhooks. [cURL](#tab-152378946-0-0) [Go SDK](#tab-152378946-0-1) Retrieve a transfer [reference](/api/money-movement/transfers/get/) ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/transfers/{transferID}" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ ``` Retrieve a transfer [reference](/api/money-movement/transfers/get/) ```go mc, _ := moov.NewClient() var accountID string var transferID string mc.GetTransfer(ctx, accountID, transferID) ``` To use webhooks to track the transfer's status, you can subscribe to the `transfer.updated` event. Read our [webhooks guide](/guides/webhooks/webhook-events/#transfers) to learn more. ## [Next steps](#next-steps) Beyond cashing out a wallet, you may also want to know how to use wallet funds to send payouts, or generally keep track of your wallet balance. [Send payouts](/guides/money-movement/send-payments/send-payouts) [Manage wallet balance](/guides/sources/wallets/balance) --- URL: https://docs.moov.io/guides/money-movement/wallets/funding/ --- # Fund a wallet Follow this step by step guide to add funds to a Moov wallet with our API, SDKs, or Moov.js. This guide covers how to fund a Moov wallet with a transfer. If you're looking to use a bank-to-wallet transfer to fund wallets and haven't yet added a bank account for the Moov account, see our step by step guide on adding bank accounts. Once you've funded a Moov wallet, its balance can be spent by issued cards. ## [Fund a wallet](#fund-a-wallet) You will be creating a funding transfer from a source (such as a bank account, card, or another wallet) to a Moov account's wallet. ### [Get accountID](#get-accountid) The first step is identifying the`accountID` for the Moov account with the wallet you would like to fund. If you don't already have it, you can use the list accounts `GET` [endpoint](/api/moov-accounts/accounts/list/) as shown below. [cURL](#tab-568137249-0-0) [Go SDK](#tab-568137249-0-1) List account [reference](/api/moov-accounts/accounts/list/) ```zsh curl -X GET "https://api.moov.io/accounts" \ -H "Authorization: Bearer {token}" ``` List account [reference](/api/moov-accounts/accounts/list/) ```go mc, _ := moov.NewClient() mc.ListAccounts(ctx) ``` ### [Select the payment methods for the transfer](#select-the-payment-methods-for-the-transfer) Get the `paymentMethodIDs` to use as the source and destination when creating a transfer in the next step. [cURL](#tab-719428563-0-0) [Go SDK](#tab-719428563-0-1) [Moov.js](#tab-719428563-0-2) List payment methods [reference](/api/sources/payment-methods/list/) ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/payment-methods" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ ``` List payment methods [reference](/api/sources/payment-methods/list/) ```go mc, _ := moov.NewClient() var accountID string mc.ListPaymentMethods(ctx, accountID) ``` List payment methods [reference](/api/sources/payment-methods/list/) ```javascript const moov = Moov(token); moov.paymentMethods.list(accountID); ``` A successful response will return an array of payment methods of different types. For the transfer source, you'll select the payment method ID associated with the payment method type you'd like to use (such as `ach-debit-fund`). For the transfer destination, choose the payment method ID associated with the `moov-wallet` payment method type. ### [Create the transfer](#create-the-transfer) Using the payment method IDs you got from step 2, you can now initiate a transfer. Once the transfer has completed, the funds will settle in the destination wallet. [cURL](#tab-263578941-0-0) [Go SDK](#tab-263578941-0-1) Create transfer [reference](/api/money-movement/transfers/create/) ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/transfers" \ -H "Authorization: Bearer {token}" \ -H "X-Idempotency-Key: UUID" \ -H "X-Wait-For: rail-response" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "amount": { "value": 100, "currency": "USD" }, "destination": { "paymentMethodID": "string" }, "source": { "paymentMethodID": "string" }, "description": "Optional transaction description." }'\ ``` Create transfer [reference](/api/money-movement/transfers/create/) ```go mc, _ := moov.NewClient() var accountID string // Partner account mc.CreateTransfer(ctx, accountID, moov.CreateTransfer{ Amount: moov.Amount{ Currency: "USD", Value: 100, // $1.00 }, Destination: moov.CreateTransfer_Destination{ PaymentMethodID: "string", }, Source: moov.CreateTransfer_Source{ PaymentMethodID: "string", }, Description: "Optional transaction description.", }) ``` ## [Next steps](#next-steps) After you've successfully funded a wallet, you can spend these funds using issued cards. As funds flow in and out of Moov wallets, you'll also want to know how to manage a wallet balance. [Issue cards](/guides/issue-cards/) [Manage wallet balance](/guides/sources/wallets/balance) --- URL: https://docs.moov.io/guides/money-movement/wallets/ --- # Wallets Moov wallets allow account holders to store funds while providing flexibility on when and how they would like to move those funds. Use this guide to understand how to use wallets in various transfer scenarios. With wallets, there are a number of possible transfer scenarios: - Fund a wallet (the wallet as the transfer destination) - Transfer funds between two different Moov wallets (wallet-to-wallet) - Cash out funds from a wallet (the wallet as the transfer source) ## [Transfer types and timing](#transfer-types-and-timing) You can use wallets in several ways, depending on your needs and priorities. Below, we summarize different types of wallet transfers and the associated timing. [Wallet to bank (same-day ACH)](#tab-624985317-1-0) [Wallet to bank (standard ACH)](#tab-624985317-1-1) [Wallet to bank (RTP)](#tab-624985317-1-2) [Card to wallet](#tab-624985317-1-3) ![Wallet to bank same-day ACH processing diagram](../images/wallet-to-bank-ach-sameday-light.png) ![Wallet to bank standard ACH processing diagram](../images/wallet-to-bank-ach-standard-light.png) ![Wallet to bank RTP processing diagram](../images/wallet-to-bank-rtp-light.png) ![Card to wallet transfer diagram](../images/card-to-wallet-light.png) ## [Funds availability timing](#funds-availability-timing) | Transfer type | Payment method | Funds availability | |------------------|-------------------------------|----------------------------------------------------------------------------------| | Bank-to-wallet | `ach-debit-*`,`moov-wallet` | 2-3 banking days | | Wallet-to-wallet | `moov-wallet` | Immediately | | Wallet-to-bank | `moov-wallet`, `ach-credit-*` | End of day for `ach-credit-same-day`, Next banking day for `ach-credit-standard` | | Card-to-wallet | `card-payment`, `moov-wallet` | Next banking day | In some instances, there might be a delay in your wallet funding. To protect both your business and Moov from potential risks, there may be instances where we temporarily hold funds for further review. This precautionary measure helps safeguard your business from fraud that could result in chargebacks. Common scenarios that could lead to a review include: - A new account with limited transaction history - Unusually high payment volumes compared to typical account activity - Certain use cases or business types that present increased risk For more information, [contact Moov](https://support.moov.io/). --- URL: https://docs.moov.io/guides/money-movement/wallets/sweeps/ --- # Sweeps Automate payouts to your customers verified bank accounts by setting up sweeps. A [sweep](/api/money-movement/sweeps) automatically initiates daily transfers to external bank accounts. Sweeps can be used to: - Payout funds from a wallet - Pull funds to cover fees or chargebacks - Automatically collect fees or other payments your account has received Sweeps help ensure funds move predictably and efficiently based on your configuration. ## [Configure sweeps](#configure-sweeps) To set up a sweep, you must first add and verify a bank account. Bank account verification can take a few days during onboarding, depending on the verification method. For faster setup, we recommend [instant micro-deposit verification](/api/sources/bank-accounts/initiate-bank-account-verification/). You can configure sweeps in one of two ways: - From the [Dashboard](/guides/dashboard/wallet/) - Use the create a sweep configuration [endpoint](/api/money-movement/sweeps/create-config/) [cURL](#tab-493175826-1-0) [Go SDK](#tab-493175826-1-1) ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/sweep-configs" \ -H 'Authorization: Bearer {token}' \ --data-raw '{ "walletID": "string", "status": "enabled", "pushPaymentMethodID": "string", "pullPaymentMethodID":"string", "minimumBalance": "150.00" }'\ ``` ```go mc, _ := moov.NewClient() minBalance := "150.00" mc.CreateSweepConfig(ctx, moov.CreateSweepConfig{ AccountID: "string", WalletID: "string", Status: moov.SweepConfigStatus_Enabled, PushPaymentMethodID: "string", PullPaymentMethodID: "string", MinimumBalance: &minBalance, }) ``` To update an existing sweep configuration, use the `PATCH` [endpoint](/api/money-movement/sweeps/patch-config/). Choose your preferred [payment methods](/guides/money-movement/accept-payments/ach/ach-processing-speeds/) for payouts via the `pushPaymentMethodID`. We currently support `ach-credit-same-day`, `ach-credit-standard`, or `rtp-credit`. If you select same-day ACH or RTP, Moov will attempt to send funds using that rail. If the transfer amount exceeds rail limits ($500,000 for same-day ACH or $1,000,000 for RTP) the transfer will automatically fall back to standard ACH. Fees are applied according to the account’s fee plan. To remediate negative balances, you must configure an `ach-debit-fund` for the `pullPaymentMethodID`. Bank accounts used for push (payouts) and pull (debits) sweeps can be different. If a payment method becomes disabled due to a bank account issue, payouts are paused until a new bank account is verified and configured in the sweep. ### [Maintain a daily balance](#maintain-a-daily-balance) Optionally, you can specify a minimum daily wallet balance to support ongoing operations or protect against refunds, disputes, and fees. If set, Moov ensures this balance is maintained when calculating sweep amounts. If not set, the default maintained balance is $0. ### [Default statement descriptor](#default-statement-descriptor) By default, Moov uses the `companyName` from your account’s ACH settings for sweep transfers. You may customize the ACH statement descriptor in the sweep configuration. The default descriptor is a 10 character ID, that is also available on each sweep for reconciliation (`swp_xxxxxx`). ## [Payout timing](#payout-timing) As you process payments, funds accrue into a sweep. A sweep’s accrual period closes daily at 4:00 PM ET. Once a sweep period is closed, a corresponding transfer is created and a new sweep is immediately created and begins accruing. Moov does support alternative close times, please [contact us](https://support.moov.io/) if you would to adjust timing. Since sweeps are not processed on weekends or banking holidays, funds will be paid out the next business day. Card payment funds are typically credited to the Moov wallet by 1:00 PM ET the next banking day following the card payment. You can refer to [card brand timetables](/guides/money-movement/accept-payments/card-acceptance/timing/#cutoff-times-by-card-brand) for details on specific brand cut-off times to know what is included in the next day funding. [ACH processing speeds](/guides/money-movement/accept-payments/ach/ach-processing-speeds/) can vary, but funds are generally available the morning of the second banking day after the transfer is created. For daily payouts, you can expect the funds to be received based on the following schedule: | Push payment method | Receive funds by | |-----------------------|---------------------| | `ach-credit-same-day` | 6 pm ET | | `ach-credit-standard` | 10 am ET (next day) | | `rtp-credit` | Instant | *Sweep transfers will assess a fee based on your pricing schedule.* ## [Reconciliation](#reconciliation) The `accruedAmount` represents the amount typically expected to transfer for a sweep period. In certain cases, such as when a sweep is first enabled or when a minimum balance is newly applied, the transferred amount may differ. In those one-off cases, Moov calculates the amount to transfer accordingly: `transferAmount` = `availableBalance` at sweep close - `minimumBalance` The [get sweep](/api/money-movement/sweeps/get/) and [list sweeps](/api/money-movement/sweeps/list/) endpoints include subtotals grouped by `transactionType`. These breakdowns help you: - Reconcile sweep activity - Track payout sources - Report totals such as sales, fees, and refunds to end users A `sweepID` is assigned to all debit or credit sweep transactions in a Moov wallet and can be used to access all sweep activity. For detailed reporting and reconciliation of sweeps, we recommend supplying the `sweepID` as a query parameter with the list wallet transactions `GET` [endpoint](/api/sources/wallets/list-transactions/). Using the returned list, you can match the amount received in the bank account with the corresponding transactions. ```zsh "subtotals": [ { "amount": { "currency": "USD", "valueDecimal": "50.00" }, "count": 1, "type": "moov-fee" }, { "amount": { "currency": "USD", "valueDecimal": "50.00" }, "count": 1, "type": "account-funding" } ], ``` ## [Negative sweeps](#negative-sweeps) In some cases, you can accrue a negative balance. For example, if you receive $100, but also receive a refund request for a previous payment of $200, the wallet balance would be -$100. Moov allows for a one-day grace period to account for any incoming payments. If the balance remains negative, a debit is initiated the following day. Negative sweeps are not initiated for amounts less than $1. There is a [two-day hold](/guides/money-movement/accept-payments/ach/ach-overview/#ach-processing-and-holds) on ACH debit transactions, so payouts will only resume once the debit transfer completes. ## [Failures](#failures) When a payout can’t be completed, a `sweep.updated` [webhook event](/guides/webhooks/webhook-events/#sweepupdated) will be sent: ```json { "eventID": "14980a04-2e32-4921-a771-4959a36534a6", "type": "sweep.updated", "data": { "sweepID": "51015d0d-8dca-49a0-ba70-abfed073f785", "walletID": "50f31cfa-6e41-412b-9935-655e58127583", "status": "failed", "transferID" : "0a958eb7-4384-41d6-8bd9-ba1cf9e2f5d2" }, "createdOn": "2021-09-02T13:57:50Z" } ``` The transfer's `failureReason` indicates the reason for the failure and may also disable the associated bank account. A bank account becoming disabled will trigger a `bankaccount.Updated` [webhook event](/guides/webhooks/webhook-events/#accounts). Failed sweeps aren’t automatically retried and no payouts will be made until a new bank account is added and verified. While awaiting a resolution, the sweep continues accruing with a status of `action-required`. Once a valid payment method is configured, payouts resume on the normal sweep schedule. --- URL: https://docs.moov.io/guides/quick-start/ --- # Quick start The quick start guide brings you through the process of signing up for Moov, getting authorized for production, and creating user accounts. This guide focuses on the quickest and easiest way to get set up and create your first merchant account with Moov - through our Dashboard. After setting up an account and adding users and merchants, you can complete more complex operations with Moov. While many operations can be completed in the Dashboard, you have other integration options. View the full reference guides by clicking on the cards below: [API](/api/) [Server-side SDKs](/sdks/) [Moov.js](/moovjs/) [Drops](/moovjs/drops/) See our [integration](/guides/get-started/integration-options/) guide for more information. Also check out our [glossary](/guides/get-started/glossary/) for a list of terms associated with Moov. ## [Sign up for Moov](#sign-up-for-moov) Use the [Moov Dashboard](https://dashboard.moov.io/signup) to create a Moov account. You'll instantly have access to a test account. To be approved for a production account that can move real money, you'll need to sign a contract and set up a fee plan with Moov. [Contact us](https://moov.io/contact/) for more information and to get the verification process started. An individual with administrator or developer permissions is required to take the actions laid out in this guide. ## [Create API keys](#create-api-keys) To use Moov's API, you'll need to generate keys. In the Dashboard, navigate to **Developers** and click the **New API key** button. Test mode and production mode each require their own API keys. To create an API key: 1. Name the API key (we suggest giving it a name that relates to the purpose) 2. Make sure to copy the key and save it in a secure place 3. Add any domains you'll use for testing and production 4. Optional: Include a note to remind you where the key is stored Read the [API keys](/guides/get-started/api-keys/) documentation for more information. If you're ready to jump into production mode, make sure to take any [necessary precautions](#switch-to-production-mode) if you've previously been using test mode. ## [Optional: Explore test mode](#optional-explore-test-mode) While [test mode](/guides/get-started/test-mode/) is optional, we strongly suggest you try it out. In test mode, test data is automatically enabled in the Dashboard, which allows you to explore how the platform works. Make sure you're in test mode by using the account switcher on the top left of the Dashboard view. ![Toggle for test account in Moov Dashboard](../shared-images/mode-toggle.png) Try out the following: - Add a bank account - Initiate verification - Initiate a transfer - Initiate a return ### [Switch to production mode](#switch-to-production-mode) When you're ready to switch to [production mode](/guides/get-started/production-mode/), use the account switcher to change modes. Before you start using production mode, make sure to: - Have your production API key - Switch out the account ID anywhere it's hard coded - Set up new webhook URLs if you used any in test mode ## [Onboard with hosted onboarding](#onboard-with-hosted-onboarding) Moov's hosted onboard flow allows you to select capabilities, pre-fill existing information, and select a fee plan before sending a merchant a link to a secure session to finish the sign up process. A merchant can be redirected to your app upon completion. All PII goes straight to Moov, so you won’t be responsible for storing or handling sensitive user data. You'll pre-fill information and send a secure session link to a [co-branded UI](/guides/accounts/hosted-onboarding/#your-branding) to your merchant. The merchant can start and pause the process, picking up where they leave off. During the process, the merchant will give you permission to perform actions on their behalf, as well as agree to the terms of service agreement and pricing disclosure. ![Merchant onboarding flow](../shared-images/onboarding-form.png) You can track the status of a merchant's application by navigating to the onboarding links section of the Dashboard. Visit our [hosted onboarding](/guides/accounts/hosted-onboarding/) guide for more details. ### [Determine Capabilities](#determine-capabilities) Capabilities indicate what an account is able to do. Before you begin the hosted onboarding process, decide what capabilities the account will need: - Transfer: Authorize debit transfers - Wallet: Store funds with Moov - Send funds: Send funds to another account - Collect funds: (business accounts only): Collect funds from another account - Card issuing beta: (business accounts only): Provide a virtual card to a merchant Each capability has different data and verification [requirements](/guides/accounts/capabilities/reference/) depending on whether the account represents an individual, or a business. You should familiarize yourself with capability requirements before moving on to the next step. See our [capabilities](/guides/accounts/capabilities/) section for more information. ### [Choose pricing fee plan](#choose-pricing-fee-plan) During the onboarding process, you'll also select a fee plan for your merchant, which they will agree to as part of their [terms of service](/guides/accounts/requirements/platform-agreement/) platform agreement. After selecting a plan, the pricing disclosure will show the rates for the following: - ACH - Instant payments (AFT, OCT, RTP) - Card acquiring - Transaction management fees - Platform fees - Network fees With a cost plus plan, card networks’ interchange fees and Moov’s processing markup are passed along to the merchant. With a flat rate plan, you can lump all the processing fees together with a flat rate customized for each merchant. When you create a fee plan, you can use it once, or reuse it and assign it to many merchants. A merchant must accept the fee plan and enter into a fee agreement before it can go into effect. ![Choose billing plan](../shared-images/account-pricing-tab.png) See our [pricing](/guides/fee-plans/plan-options/) guide for more information and details on billable events. ## [Alternative: Onboard with Moov.js and Drops](#alternative-onboard-with-moovjs-and-drops) While Moov strongly suggests our hosted onboarding process, you can also use our onboarding Drops. Drops are pre-built, customizable UI components that take care of the entire account creation workflow within your application. The Drop interacts directly with Moov’s API using JWTs to securely send data between your end users browser and Moov. Drops provide a secure flow, and PII goes straight to Moov, so you won’t be responsible for storing or handling sensitive user data. ![](../../moovjs/drops/images/start-screen.png) The Drop is an HTML element with [properties](/moovjs/drops/onboarding/#properties) accessed through JavaScript using a reference to the `moov-onboarding` element. ```html ``` ```javascript const onboarding = document.querySelector('moov-onboarding'); onboarding.token = 'eyjh...'; ``` See our [onboarding Drop](/moovjs/drops/onboarding/) guide for detailed instructions. Also see our [Moov.js](/moovjs/) and [Drops 101](/moovjs/drops/drops-101/) guides for general information. ### [Funding source](#funding-source) A merchant will add their bank account as funding source during their onboarding process. When a merchant adds their bank account, it sets the verification process in motion. If their bank supports [instant micro-deposit](/guides/sources/bank-accounts/verification/), they will be required to check their bank account and enter the the `MV###` code that appears in the transaction description. Otherwise, they will need to complete the [traditional micro-deposit](/guides/sources/bank-accounts/verification/micro-deposits/) process by entering in the two amounts that appear in their bank account. See our [funding sources](/guides/sources/) section for more information. ## [Integrate & initialize](#integrate--initialize) You can complete various operations in the Dashboard, but complex transactions will require a more robust integration. With a server-side integration, you are responsible for handling and storing sensitive user information. With a client-side integration, you can use Moov.js to streamline interactions with the API and avoid storing or handling sensitive information yourself. ### [Server-side: Basic authentication](#server-side-basic-authentication) You can use your API public and private keys with Basic authentication. Set the `Authorization` header to `Basic `, where credentials is the Base64 encoding of public key and private key. ```zsh "Authorization": "Basic " ``` Only use this method if you are developing a server-side integration. If you are developing a client-side integration, use [OAuth](#client-side-oauth-with-jwt) instead. ### [Client-side: OAuth with JWT](#client-side-oauth-with-jwt) You can set up authentication with OAuth and initialize [Moov.js](/moovjs/) in your application. When making requests to Moov from a browser, you can use OAuth with JSON Web Tokens (JWT). If using a client-side integration, you'll also need to work with [scopes](/api/authentication/scopes/). A scope is a permission that limits how a specific account can interact with another account. ### [Initialize](#initialize) The following examples show how to initialize Moov with your chosen integration. [Go SDK](#tab-263874951-1-0) [Moov.js & Drops](#tab-263874951-1-1) ```go mc := moov.NewClient() ``` ```javascript const moov = Moov(token); ``` ## [Move money](#move-money) After successfully creating a merchant account with a funding source, you're ready to move money. Before initiating a transfer, you’ll need to get a payment method. You can retrieve a list of all available payment methods for an account by entering the account ID and the amount of the transfer. For example, you can transfer money from a Moov wallet, or pull funds from another account. The Dashboard will list available payment methods when you create a transfer. For the purposes of this guide, we'll be providing cURL and Go SDK examples. Explore the integration options at the top of this guide for other examples. [cURL](#tab-796325481-0-0) [Go SDK](#tab-796325481-0-1) ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/transfer-options" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "amount": { "value": 100, "currency": "USD" } "destination": { "accountID": "string" }, "source": { "accountID": "string" } }'\ ``` ```go const moov = new Moov(credentialsObject); const transferOptions = { amount: { value: 100, currency: "USD" }, destination: { accountID: "string" }, source: { accountID: "string" } } const options = await moov.transfers.getTransferOptions(transferOptions); ``` Finally, to initiate a transfer, provide the two payment method IDs and the amount you want to send. [cURL](#tab-632851479-1-0) [Go SDK](#tab-632851479-1-1) [Dashboard](#tab-632851479-1-2) ```zsh curl -X POST "https://api.moov.io/transfers" \ -H "Authorization: Bearer {token}" \ -H "X-Idempotency-Key: UUID" \ -H "X-Wait-For: rail-response" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "amount": { "value": 100, "currency": "USD" }, "destination": { "paymentMethodID": "string" }, "source": { "paymentMethodID": "string" }, "description": "Optional transaction description." }'\ ``` ```go mc, _ := moov.NewClient() mc.CreateTransfer(ctx, moov.CreateTransfer{ Amount: moov.Amount{ Currency: "USD", Value: 100, // $1.00 }, Destination: moov.CreateTransfer_Destination{ PaymentMethodID: "string", }, Source: moov.CreateTransfer_Source{ PaymentMethodID: "string", }, Description: "Optional transaction description.", }) ``` View the [money movement](/guides/money-movement/) section for more information. ## [Next steps](#next-steps) Check out our [webhook](/guides/webhooks/) section where you can view all of the available webhooks and a how-to set up guide. --- URL: https://docs.moov.io/guides/sources/bank-accounts/bank-account-status/ --- # Bank account status Check the status of an account that's been verified through instant or standard micro-deposits. Below is a summary of possible bank account statuses: | Account status | Description | |----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------| | `new` | New account that can receive funds, but verification not initiated | | `pending` | Micro-deposit process has kicked off, but is not yet complete | | `verified` | Bank account has been successfully verified | | `verificationFailed` | The maximum number of micro-deposit attempts has been exceeded, the amounts have expired, or a certain event occurred (for example, an ACH return) | | `errored` | Moov locked the account for security purposes, or due to a certain event | Two of the statuses will require you to take action before the verification process can proceed: - `errored`: You will need to add a new bank account (or [contact Moov](https://support.moov.io/)) - `verificationFailed`: You will need to reverify (typically, reinitiate micro-deposits) A `statusReason` is provided alongside `status` and provides further details. Below is a list of reasons a bank account might have a particular status, and the associated action you will need to take: Status reason Account status Action `bank-account-created` `new` None `verification-initiated` `pending` None `verification-successful` `verified` None `micro-deposit-expired` `errored` `verificationFailed` Add new bank account Reverify `micro-deposit-return` `errored` `verificationFailed` Add new bank account Reverify `micro-deposit-attempts-exceeded` `verificationFailed` Reverify `max-verification-failures` `errored` Add new bank account `ach-debit-return` `errored` `verificationFailed` Add new bank account Reverify `ach-credit-return` `errored` `verificationFailed` Add new bank account Reverify `rtp-credit-failure` `errored` `verificationFailed` Add new bank account Reverify `admin-action` Any of the above statuses Any of the above actions `other` Any of the above statuses Any of the above actions As indicated above, status and corresponding actions may differ between returns received on ACH transfers and ACH micro-deposits. See the [ACH returns](/guides/money-movement/accept-payments/ach/returns/#return-codes) guide to view a full list of ACH return codes. Additional information is also available for ACH debit and credit [return scenarios](/guides/money-movement/accept-payments/ach/returns/#scenarios). If you're experiencing issues with a bank account status, [contact Moov](https://support.moov.io/). --- URL: https://docs.moov.io/guides/sources/bank-accounts/ --- # Bank accounts Link bank accounts to Moov accounts and verify bank accounts through instant micro-deposit verification, Plaid Link, or MX. Trigger [micro-deposit verification](/guides/sources/bank-accounts/verification/instant-micro-deposit/) for any bank account immediately after you've captured that bank account's details. Alternatively, you can use instant account verification (IAV) with [Plaid Link](/guides/sources/bank-accounts/verification/plaid/) or [MX](/guides/sources/bank-accounts/verification/mx/) if you have an existing relationship with Plaid or MX. You're still able to send funds to a bank account that hasn't been verified, but in order to collect funds from that account, its ownership *must* be verified. ## [Account types](#account-types) | Account type | Description | Individual account | Business account | |------------------|----------------------------------------------------------------------------------|--------------------|------------------| | `checking` | Standard checking account | **✓** | **✓** | | `savings` | Standard savings account | **✓** | **✓** | | `loan` | Loan account for activities such as debt repayment and consumer bill pay | **✓** | **✓** | | `general-ledger` | Ledger account for activities such as disbursements and external account funding | **×** | **✓** | ## [Payment methods](#payment-methods) Moov will automatically create payment methods for every rail a bank account is eligible to be used with. | Payment method | Use as | Details | |-----------------------|-------------|------------------------------------------------------------------------------------------------------------------------------------| | `ach-debit-fund` | Source | Fund [payouts](/guides/money-movement/send-payments/send-funds/) or add funds to a Moov wallet from a verified linked bank account | | `ach-debit-collect` | Source | Pull funds from a verified linked bank account for bill payment, direct debit, or e-check type use-cases | | `ach-credit-standard` | Destination | Disburse funds to a linked bank account | | `ach-credit-same-day` | Destination | Disburse funds to a linked bank account using same-day processing | | `rtp-credit` | Destination | Disburse funds to a linked bank account in near real time. The source for a `rtp-credit` payment method must be a `moov-wallet`. | Use the guides below to learn more about bank account verification options. --- URL: https://docs.moov.io/guides/sources/bank-accounts/link-bank-accounts/link-bank-accounts/ --- # Link bank accounts Follow this step by step guide to link a bank account as a funding source with our API, SDKs, and Moov.js. This guide covers how to link a bank account through Moov's API, SDKs, and Moov.js. You can also use Plaid or MX to add and verify bank accounts. The instructions in this guide do not apply to bank accounts added or verified via Plaid or MX. See the associated [Plaid](/guides/sources/bank-accounts/verification/plaid/) or [MX](/guides/sources/bank-accounts/verification/mx/) guides for instructions. For detailed information on the verification process, see the [instant micro-deposit](/guides/sources/bank-accounts/verification/instant-micro-deposit/) guide. The following bank account types are available: - `checking` - `savings` - `loan` - `general-ledger` (business holder type only) ## [Add bank account](#add-bank-account) The step by step examples below will show you how to link a bank account to a Moov account, as well as initiate and confirm instant micro-deposit verification. ### [Get accountID](#get-accountid) Retrieve the `accountID` for the Moov account you want to link a bank account to. [cURL](#tab-546723918-0-0) [Go SDK](#tab-546723918-0-1) List account [reference](/api/moov-accounts/accounts/list/) ```zsh curl -X GET "https://api.moov.io/accounts" \ -H "Authorization: Bearer {token}" ``` List account [reference](/api/moov-accounts/accounts/list/) ```go mc, _ := moov.NewClient() mc.ListAccounts(ctx) ``` ### [Link a bank account](#link-a-bank-account) For the purposes of this example, we are adding a bank account to an `individual` Moov account. If you are adding a bank account to a business Moov account, pass `business` as the `holderType` instead. The response will include the `bankAccountID` which is required in the next steps to initiate and complete instant micro-deposit verification. [cURL](#tab-953417268-0-0) [Go SDK](#tab-953417268-0-1) [Moov.js](#tab-953417268-0-2) Link a bank account [reference](/api/sources/bank-accounts/create/) ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/bank-accounts" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "account": { "accountNumber": "0004321567000", "bankAccountType": "checking", "holderName": "Jules Jackson", "holderType": "individual", "routingNumber": "123456789" } }'\ ``` Link a bank account [reference](/api/sources/bank-accounts/create/) ```go mc, _ := moov.NewClient() var accountID string mc.CreateBankAccount(ctx, accountID, moov.WithBankAccount(moov.BankAccountRequest{ AccountNumber: "0004321567000", AccountType: moov.BankAccountType_Checking, HolderName: "Jules Jackson", HolderType: moov.HolderType_Individual, RoutingNumber: "123456789", }), moov.WaitForPaymentMethod()) ``` Link a bank account [reference](/api/sources/bank-accounts/create/) ```javascript const moov = Moov(token); const accountID = "accountID"; const bankAccountPayload = { accountNumber: "0004321567000", bankAccountType: "checking", holderName: "Jules Jackson", holderType: "individual", routingNumber: "123456789" }; moov.accounts.bankAccounts.link({accountID, bankAccountPayload}); ``` ### [Initiate instant micro-deposits](#initiate-instant-micro-deposits) Initiate instant micro-deposits through Moov's verify bank account `POST` [endpoint](/api/sources/bank-accounts/initiate-bank-account-verification/). Moov will generate a 4-digit numeric code and send a $0.01 credit to the user's bank account you're verifying. The 4-digit code will appear as `MV{code}` on the user's credit transaction descriptor. The user will have 14 days and five attempts to enter the verification code. If you initiate verification for a bank account that is not RTP-enabled, Moov will automatically use ACH instead of RTP for verification. ACH verification is not instant. If needed, you can retrieve the `bankAccountID` from the list bank accounts `GET` [endpoint](/api/sources/bank-accounts/list/). [cURL](#tab-316548792-0-0) Initiate micro-deposits [reference](/api/sources/bank-accounts/initiate-bank-account-verification/) ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/bank-accounts/{bankAccountID}/verify" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ ``` ### [Check instant micro-deposits](#check-instant-micro-deposits) You can check the status of instant micro-deposit verification through the `GET` [endpoint](/api/sources/bank-accounts/complete-bank-account-verification/). The response will include if the verification is instant or same-day ACH, as well as the status. [cURL](#tab-538146792-0-0) Check micro-deposits [reference](/api/sources/bank-accounts/complete-bank-account-verification/) ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/bank-accounts/{bankAccountID}/verify" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ ``` ### [Complete instant micro-deposits](#complete-instant-micro-deposits) To complete the verification process, provide the 4-digit code using the verify bank account `PUT` [endpoint](/api/sources/bank-accounts/complete-bank-account-verification/). You'll receive a `2XX` response if the correct code is provided. If an incorrect code is submitted, the response will indicate the attempt's status as `incorrect`. [cURL](#tab-928561743-0-0) Complete micro-deposits [reference](/api/sources/bank-accounts/complete-bank-account-verification/) ```zsh curl -X PUT "https://api.moov.io/accounts/{accountID}/bank-accounts/{bankAccountID}/verify" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "code":"MV1234" }'\ ``` ## [Manage bank accounts](#manage-bank-accounts) List all bank accounts using the list bank accounts `GET` [endpoint](/api/sources/bank-accounts/list/). You can also get an individual account by passing the `accountID` to the retrieve a bank account `GET` [endpoint](/api/sources/bank-accounts/get/). Bank accounts can be deleted by passing the `accountID` to the delete a bank account `DEL` [endpoint](/api/sources/bank-accounts/delete/). A bank account might fail verification during the micro-deposit process. See the [bank account status](/guides/sources/bank-accounts/bank-account-status/) guide for verification failure instructions, as well as general status information. ## [Next steps](#next-steps) [Accept payments](/guides/money-movement/accept-payments/) [Send payments](/guides/money-movement/send-payments/) --- URL: https://docs.moov.io/guides/sources/bank-accounts/verification/ --- # Verification Verify bank accounts with instant micro-deposits, traditional micro-deposits, Plaid, or MX. Bank account ownership must be verified to reduce fraud and the risk of unauthorized activity. Instant micro-deposits verification is the preferred method for RTP-enabled accounts. For eligible bank accounts, a single credit is instantly sent over RTP and verified through sending back a verification code. For banks that do not support RTP, credits are sent over same-day ACH, ensuring compatibility with a wide range of financial institutions. Traditional micro-deposits and instant verification through Plaid or MX are also available verification options. --- URL: https://docs.moov.io/guides/sources/bank-accounts/verification/instant-micro-deposit/ --- # Instant micro-deposit verification Link and verify eligible user bank accounts to their Moov accounts with instant micro-deposit verification via RTP or same-day ACH. Available to RTP-enabled accounts, instant micro-deposit verification provides a fast and efficient, single-session method to confirm bank account ownership while meeting Nacha bank validation requirements. This method improves upon traditional micro-deposit methods, which can take several days. Instant micro-deposit verification: - Initiates a $0.01 credit containing a unique verification code is sent to the user's bank account - Delivers instantly over the RTP network for RTP-enabled banks and over same-day ACH for non-RTP-enabled banks, ensuring broad compatibility - Allows the user to retrieve a code from their transaction history and enters it to complete verification Users have 14 days and five attempts to submit the code for verification. If the code has not been submitted or entered incorrectly five times, you can re-initiate the bank account verification process. Verification can be attempted a total of three times per bank account. If you initiate verification for a bank account that is not RTP-enabled, Moov will automatically use same-day ACH instead of RTP for verification. ACH verification is not instant. ## [Initiate](#initiate) Initiate the instant bank account verification process through Moov's instant micro-deposit verification `POST` [endpoint](/api/sources/bank-accounts/initiate-bank-account-verification/). A 4-digit numeric code is generated and sent with a $0.01 credit to the user's bank account. The code appears on the user’s transaction history as `MV{code}`. Use the `X-Wait-For: rail-response` header to synchronously receive the outcome of the instant credit in the response payload. The response will contain the details of the `verificationMethod` and status. The `verificationMethod` (`instant` for RTP or `ach` for same-day ACH) is automatically selected based on the bank's capabilities. [cURL](#tab-168354297-0-0) [Go](#tab-168354297-0-1) ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/bank-accounts/{bankAccountID}/verify" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ ``` ```go mc, _ := moov.NewClient() var accountID string var bankAccountID string mc.InstantVerificationInitiate(ctx, accountID, bankAccountID) ``` Possible response status: - `new`: Verification initiated, credit pending - `sent-credit`: Credit sent, available for verification in the external bank account - `failed`: Verification failed due to credit rejection/return, see `exceptionDetails` ## [Complete](#complete) Complete the verification by submitting the 4-digit code via the instant micro-deposit verification `PUT` [endpoint](/api/sources/bank-accounts/complete-bank-account-verification/). You'll receive a `2XX` response if the correct code is provided. An incorrect code will result in a `409` response with details. The code is case-insensitive and can be entered with or without the "MV" prefix. The code can follow any of the following accepted formats: - `MV0000` - `mv0000` - `0000` [cURL](#tab-127354968-0-0) [Go](#tab-127354968-0-1) ```zsh curl -X PUT "https://api.moov.io/accounts/{accountID}/bank-accounts/{bankAccountID}/verify" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "code":"MV1234" }'\ ``` ```go mc, _ := moov.NewClient() var accountID string var bankAccountID string mc.InstantVerificationComplete(ctx, accountID, bankAccountID, "MV1234") ``` Upon successful verification, the bank account status will be updated to `verified`, enabling ACH debit transactions. ## [Check status](#check-status) Check the status of the verification using the instant micro-deposit verification `GET` [endpoint](/api/sources/bank-accounts/get-bank-account-verification/). The response includes the `verificationMethod` and the current `status`. ```json { "status": "successful", "verificationMethod": "instant" } ``` The `status` will indicate the following: - `new`: Verification initiated, credit pending to the payment network - `sent-credit`: Credit sent, available for verification - `failed`: Verification failed, description provided, user needs to add a new bank account - `expired`: Verification expired after 14 days, re-initiate verification - `max-attempts-exceeded`: Five incorrect attempts, re-initiate verification --- URL: https://docs.moov.io/guides/sources/bank-accounts/verification/micro-deposits/ --- # Traditional micro-deposits Link user bank accounts to their Moov accounts with traditional micro-deposits. We highly recommended that you verify ownership of every linked bank account. To add a bank account in Moov, you'll need to provide: - Bank account holder's name - Bank account number - Routing number ## [What are micro-deposits?](#what-are-micro-deposits) Micro-deposits are small temporary deposits that land in a customer's bank account for verification purposes. Once the customer correctly verifies the micro-deposit amounts, they are considered the valid owner of that bank account. ## [Verification](#verification) When you initiate the micro-deposit verification process through the [API](/api/sources/bank-accounts/initiate-micro-deposits/), Moov simultaneously initiates a debit to recoup the micro-deposits. You can find information in the [status](/guides/sources/bank-accounts/bank-account-status/) section below about how micro-deposits could impact the overall verification process. Once micro-deposits have been initiated, customers will see the values in their bank account within three business days. Each micro-deposit can be up to .49¢, and will appear in accounts with a description of "AcctVerify". Before the bank account can be used, the account owner must exactly enter the two unique values in your app. The account owner has 30 days to complete micro-deposit verification. If 30 days transpire, and the account owner hasn't entered the micro-deposits, you can re-trigger micro-deposit verification. If you request micro-deposits before 4:00 PM ET, we process them on the same day. If you request micro-deposits any time after 4:00 PM ET, we process them on the next day. Depending on how your bank posts transactions, micro-deposits will appear in your account between 3-5 business days. Once the bank account is verified, Moov will automatically generate new payment methods that allow the bank account to be debited. If Moov receives an ACH return from the financial institution after sending micro-deposits, the bank account’s status will change to `verificationFailed` or `errored` based on the return code. For security purposes, we cap the number of attempts to enter values, as well as the number of attempts to link a bank account that previously resulted in expired or failed verifications. See our [bank account status](/guides/sources/bank-accounts/bank-account-status/) guide for more information on accounts that have been verified through micro-deposits. --- URL: https://docs.moov.io/guides/sources/bank-accounts/verification/mx/ --- # Link bank accounts with MX Moov's partnership with MX allows mutual customers to verify bank accounts through instant account verification (IAV). To enable instant account verification (IAV), you will need to: - Set up your accounts - Get authorization code - Pass the MX authorization code to Moov's bank account `POST` [endpoint](/api/sources/bank-accounts/create/) ## [Set up your accounts](#set-up-your-accounts) You will need an MX account and a Moov account in order to use this integration. If you don't have a Moov account, you can [sign up](https://dashboard.moov.io/signup) for one. Refer to our [quick start](/guides/quick-start) guide for guidance on getting your API keys and configuring your Moov account once you've signed up. Before you can use the Moov + MX integration, you will also need to have an **API key** and a **client ID** for your MX account. Your MX account must also have the following enabled: - `has_payment_processing` - `has_platform_api` - `has_account_verification` ## [Create an authorization code](#create-an-authorization-code) An authorization code is a one-time use token used to authenticate your application with MX. You'll create an authorization code by passing the following information to the `Request Payment Processor Authorization Code` [MX endpoint](https://docs.mx.com/api#processor_token_client_endpoints_authorization_code). ```json { "payment_processor_authorization_code": { "user_guid": "USR-ba246888-cc62-40a6-8967-baa76dbf1cc7", "member_guid": "MBR-4145eb50-3721-4f48-a983-d874c8bd5eb9", "account_guid": "ACT-dc10aeb9-66a0-4c5c-b6a7-720b637f1fb6" } } ``` ## [Pass the authorization code to Moov](#pass-the-authorization-code-to-moov) Once you've successfully created an authorization code, you'll pass that authorization code to Moov via the bank account `POST` [endpoint](/api/sources/bank-accounts/create/). [cURL](#tab-316842597-1-0) [Moov.js](#tab-316842597-1-1) ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/bank-accounts" -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "mx": { "authorizationCode": "mx-authorization-code" } }'\ ``` ```javascript const moov = moov(token); const accountID = "accountID"; const iavAuth = { mx: { authorizationCode: "token" } }; moov.accounts.bankAccounts.link({accountID, iavAuth}); ``` Moov will then retrieve bank account details directly from MX, so you won’t need to directly handle sensitive bank information when linking bank accounts. The bank account must have passed validation with MX, otherwise the bank account will be added in the `verificationFailed` status. --- URL: https://docs.moov.io/guides/sources/bank-accounts/verification/plaid/ --- # Link bank accounts with Plaid Moov's partnership with Plaid allows mutual customers to verify bank accounts through instant account verification (IAV). You have two options to integrate Plaid: - [Moov-managed Plaid](#moov-managed-plaid-integration) - [Bring your own Plaid](#bring-your-own-plaid-integration) ## [Moov-managed Plaid integration](#moov-managed-plaid-integration) Once Plaid has completed the OAuth registration process, you can use Moov.js to link bank accounts using Plaid. See our [Moov.js Plaid Link](/moovjs/sources/bank-accounts/plaid-link) documentation. ## [Bring your own Plaid integration](#bring-your-own-plaid-integration) If you are an existing Plaid customer, follow these steps to connect Plaid with Moov: 1. Follow [Plaid's documentation](https://plaid.com/docs/auth/partnerships/moov/) on adding Moov to your app 2. Verify the user's bank account with Plaid Link 3. Use the output from Plaid Link to retrieve a Plaid `processor_token` via their `/processor/token/create` endpoint 4. Pass the `processor_token` to Moov's bank account `POST` [endpoint](/api/sources/bank-accounts/create/) Once you've completed these steps, Moov will inspect the Plaid processor token for bank account information and treat it as a verified bank account that's ready to be used as a funding source for a Moov account. You must use a Plaid production keys to generate the `processor_token`. Sandbox keys will fail when passed to Moov. * * * Note that there is a 4-6 week time frame before going live with Plaid. In addition to establishing the contract, there is an OAuth registration process that you will need to wait for before having production access to run IAV with Plaid. --- URL: https://docs.moov.io/guides/sources/cards/accept-card-payments/ --- # Accept card payments Follow this step by step guide to set up card acceptance for your merchants using our API or SDKs. Link debit and credit cards to a Moov account and use the card of your choice as the source of a payment transfer. Linking a card to a Moov account automatically verifies the card details with the card networks. This process verifies the existence of the card account and returns information about the Address Verification Service (AVS) and Card Verification Value (CVV) checks that occur. Some examples of card acceptance use cases include: - An ecommerce platform that allows buyers and sellers to transact - A software-as-a-service (SaaS) platform connecting service providers with clients - A utility or subscription based company looking to allow their customers different payment options For the purpose of this guide, we assume that you've already onboarded your merchants. To learn more about onboarding merchants, read our [create accounts](/guides/accounts/create-accounts/) or [hosted onboarding](/guides/accounts/hosted-onboarding/) guide. ## [Link card to Moov account](#link-card-to-moov-account) You can use the pre-built [card link Drop](/moovjs/drops/card-link/), or if you've submitted an attestation of PCI compliance to Moov, you can link cards directly through the API. If you opt for the API method, you'll be responsible for storing and handling card data. ### [Save a card for future use](#save-a-card-for-future-use) Before you link a card, consider whether the card should be saved on file to use Moov's [card account updater](/guides/sources/cards/card-account-updater/) service. This can be done by setting `cardOnFile` to **true** when linking a card. If nothing is passed to `cardOnFile`, or you set it to **false**, the card will not automatically update card number and expiration date information. If a card becomes out of date, it will not work for future payments. If you set the `cardOnFile` flag to **true**, the `merchantAccountID` (Moov account ID of a merchant on your platform) provided should signify which merchant the cardholder has consented to save their information. The account associated with the `merchantAccountID` will incur fees for successful card updates using Moov's card account updater. If you leave the `merchantAccountID` field blank while saving a card on file, the system will default to your platform's account ID, indicating the cardholder's relationship with your platform's brand. You can update the `merchantAccountID` at any time using the update card `PATCH` [endpoint](/api/sources/cards/update/). Accounts must be approved for card account updater. [Contact Moov](https://support.moov.io/) for more information. ### [Drop](#drop) The simplest way to securely collect sensitive card details is by using the card link Drop, a prebuilt UI component for embedding card-based payments. By using the [card link Moov Drop](/moovjs/drops/card-link/), you’ll send card data directly to Moov’s PCI-compliant card vault, and the information will not touch your servers. Once the information has been submitted via the Drop, Moov verifies the card details with card networks. ```html ``` ### [API & SDKs](#api--sdks) Link a card using our API or Go SDKs. If you set the optional `X-Wait-For` header to `payment-method`, the response will include any payment methods that were created for the newly linked card in the `paymentMethods` field. [cURL](#tab-983625147-2-0) [Go SDK](#tab-983625147-2-1) ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/cards" \ -H "Authorization: Bearer {token}" \ -H "X-Wait-For: payment-method" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "billingAddress": { "addressLine1": "123 Main Street", "city": "Denver", "stateOrProvince": "CO", "postalCode": "80301", "country": "US" }, "cardCvv": "123", "cardNumber": "4111111111111111", "expiration": { "month": "01", "year": "28" }, "holderName": "Jules Jackson" }'\ ``` ```go mc, _ := moov.NewClient() var accountID string cardPayload := moov.CreateCard{ BillingAddress: moov.Address{ AddressLine1: "123 Main Street", City: "Denver", StateOrProvince: "CO", PostalCode: "80301", Country: "US", }, CardNumber: "4111111111111111", CardCvv: "123", Expiration: moov.Expiration{ Month: "01", Year: "28", }, HolderName: "Jules Jackson", } mc.CreateCard(ctx, accountID, cardPayload) ``` ## [Card verification](#card-verification) When a card is linked, Moov performs a verification with the relevant card network to confirm that the card account is open and valid. Additionally, the verification checks if the CVV and address match the information on file with the card issuer. The `merchantAccountID` is used to pass merchant information during card verification. Although these verification transactions are rarely visible to cardholders, when they are, it's crucial that cardholders recognize the merchant associated with the verification so they know it's not fraudulent. Although it's best practice to always include the `merchantAccountID` during card verification, it's not mandatory. If you omit this field, the system defaults to your platform's account ID. It is possible the verification request will be declined by the card issuer. Decline information is provided in the response body of the `422` error. Errors could be validation errors, such as an invalid card number, or actual declines from the card issuer. Below is an example of a card issuer decline. ```json { "error": "card verification failure: card-not-activated" } ``` ## [Name verification (optional)](#name-verification-optional) Moov supports Visa’s [Account Name Inquiry (ANI)](https://usa.visa.com/content/dam/VCOM/regional/na/us/support-legal/documents/account-name-inquiry-onesheet-merchant-version.pdf). ANI ensures that the name provided on the linked card matches the name held on file with the issuer. This tool is optional and serves to enhance cardholder verification. The card link `POST` [endpoint](/api/sources/cards/create/) and `PATCH` [endpoint](/api/sources/cards/update/) offer an optional `verifyName` field. To submit a name to Visa for verification, supply the `holderName` and set `verifyName` to **true**. [Pull from card](/guides/money-movement/accept-payments/pull-from-card/) requires name verification. ```json { "cardVerification": { "fullName": "match", // noMatch, match, partialMatch, notChecked "firstName": "match", // noMatch, match, partialMatch, notChecked "middleName": "noMatch", // noMatch, match, partialMatch, notChecked "lastName": "match" // noMatch, match, partialMatch, notChecked }, } ``` ## [Submit the card payment](#submit-the-card-payment) The customer’s card will be the source of funds, so Moov needs the `card-payment` payment method from their account. You can obtain the `paymentmethodID` from the payment methods `GET` [endpoint](/api/sources/payment-methods/list/). The `sourceID` should be the `cardID`, which you can get from the cards `GET`[endpoint](/api/sources/cards/get/). Since the merchant’s wallet will be the destination of the funds, we will need the `moov-wallet` payment method. You can obtain the paymentmethodID using the payment methods `GET` [endpoint](/api/sources/payment-methods/list/) and finding the `moov-wallet` payment method associated with the merchant account. To submit the card payment, create a transfer from the cardholder (source) to the merchant (destination). [cURL](#tab-837291654-0-0) ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/transfers" \ -H "Authorization: Bearer {token}" \ -H "X-Idempotency-Key: UUID" \ -H "X-Wait-For: rail-response" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "amount": { "value": 100, "currency": "USD" }, "destination": { "paymentMethodID": "string" }, "source": { "paymentMethodID": "string" }, "description": "Optional transaction description." }'\ ``` Card-based payments first settle in a Moov wallet. The funds can later be moved to an external bank account through a disbursement transfer. When you include the `X-Wait-For` header in the request, you will get a synchronous response that includes full transfer and rail-specific details from the payment network. This is useful for when a user is clicking a button to make a payment and needs a synchronous response so they can get confirmation that it worked. If you omit the `X-Wait-For` header, you will get an asynchronous response that only includes the transferID and the timestamp for when the transfer was created. ## [Check status](#check-status) After a transfer is created, it will be `pending` until the funds are disbursed to the destination `moov-wallet`. Funds typically settle and become available by the end of the next business day. You can check the [status](/guides/money-movement/events-and-statuses/#transfer-statuses) of the transfer anytime using the `GET` [endpoint](/api/money-movement/transfers/get/). You can also see card specific status details in the response within the `source.cardDetails` object. ```json { "source": { "cardDetails": { "status": "confirmed", "confirmedOn": "2023-09-10T18:23:56Z" } } } ``` ## [Access funds](#access-funds) Once the payment has been processed and the funds are available, the funds can be moved out of the merchant `moov-wallet` using another transfer where that wallet is the source. [Bank holidays](https://www.frbservices.org/about/holiday-schedules) may delay the availability of funds. [Card to wallet](#tab-567291384-0-0) ![Card to wallet transfer diagram](../../images/card-to-wallet-light.png) ## [Cardholder disputes](#cardholder-disputes) As the main account holder, you are responsible for notifying impacted merchants of any incoming disputes. You can receive notifications about incoming disputes by setting up the `dispute.updated` webhook. Read our [webhooks](/guides/webhooks/webhook-events/#disputes) guide for more information. If you receive a `202` response from creating a transfer, do not consider the transfer as successful or failed. Instead, you should wait for the webhook notification to determine the status of the transfer, or subsequently look up the transfer status using the `transferID`. Read more on our [transfer responses](/guides/money-movement/events-and-statuses/#transfer-responses) guide. ## [Reverify a card](#reverify-a-card) Moov will only perform a new verification request if a new CVV is provided. You can use the update a card `PATCH` [endpoint](/api/sources/cards/update/) to update and re-verify certain information about the card. The `cardID` is the ID of the card you want to update, and the `accountID` represents the Moov account that the card is linked to. ```json { "cardCvv": "123" } ``` Optional request data: | Field | Type | Description | |------------------|--------|----------------------------------------------| | `expiration` | object | The card's expiration month and year | | `cardCvv` | string | The card's CVV number | | `billingAddress` | object | The billing address associated with the card | Note that when performing a `PATCH` on an existing card, Moov will perform another CVV verification request to the card networks using the new information provided. If the new verification is declined by the card issuer, the previously linked card will not be affected. If the verification succeeds, the card record will be updated with the new information. Refer to the `cardVerification{}` object in the response to see if the new CVV information is correct. ```json { "cardVerification": { "cvv": "match", "addressLine1": "match", "postalCode": "match" } } ``` ## [Best practices](#best-practices) Some card issuers display alerts or notifications about card verifications to cardholders. Being transparent and recognizable prevents accidental suspicion. Include as much complete and accurate data as possible to comply with card brand rules and mandates, optimize card authorization rates, prevent interchange downgrades, and increase defensibility against chargebacks. Consider the following best practices: - **Street address**: Send the optional `addressLine1` in `billingAddress`. For most situations, Moov recommends sending the address so that full address verification can take place. Not including `addressLine1` may impact approval rates, cause interchange downgrades, and impact chargeback win rate. - **Card verification**: Always include `merchantAccountID` when performing a card verification. This provides context to the cardholder if the verification transaction becomes visible. - **Save a card on file**: If you're saving a card for future use, specify `merchantAccountID` and set the `cardOnFile` flag to **true**. This indicates the cardholder's relationship with the merchant, and their consent to save their card details for future transactions. --- URL: https://docs.moov.io/guides/sources/cards/apple-pay/ --- # Accept cards with Apple Pay Moov allows you to accept card payments with Apple Pay. This step by step guide covers how you can start accepting Apple Pay on the web using the open standard Payment Request API. In addition to being a fast and easy way to accept payments, Apple Pay offers strong privacy and security. In this guide, we'll direct you to Apple's guidelines, and bring you through a step by step process of adding a functional Apple Pay button. ## [Prerequisites](#prerequisites) Before getting started, make sure your website follows Apple's guidelines, and that your server is set up accordingly. - [Apple Pay website guidelines](https://developer.apple.com/apple-pay/acceptable-use-guidelines-for-websites/) - [Apple Pay server requirements](https://developer.apple.com/documentation/apple_pay_on_the_web/setting_up_your_server) - All pages that include Apple Pay must be served over HTTPS - Your domain must have a valid SSL certificate - Your server must support the Transport Layer Security (TLS) protocol version 1.2 or later, and one of the [cipher suites](https://support.apple.com/guide/security/tls-security-sec100a75d12/web) listed Apple Pay is only available in production mode. Moov does not offer Apple Pay in test mode at this time. ## [Register your domains](#register-your-domains) Any domains accepting payments must first be registered and verified with Apple. You can do this through the Moov Dashboard. Domains must be registered for each individual merchant account, which is the destination of the Moov transfer. Within an account, navigate to the **Settings** tab and click the **Add a domain** button to add domains to Apple Pay. To verify your domain, download the file and host it at the path shown for each domain you are registering. Ensure the file is in place before clicking **Add domain**. Note that serving the domain verification file via a redirect is a common cause of failure. If you encounter any issues, refer to this Apple Pay [troubleshooting guide](https://developer.apple.com/documentation/technotes/tn3173-troubleshooting-issues-with-your-apple-pay-merchant-id-configuration) for guidance on common causes and resolutions. You will now see a list of the domains you’ve added. You can come back to this page to remove or add domains. ## [Add Apple Pay button](#add-apple-pay-button) Using the browser-native [Payment Request API](https://developer.apple.com/documentation/apple_pay_on_the_web/payment_request_api), no additional libraries are needed to add an Apple branded button, since everything is supported within Safari. Alternatively, you can also use the [Apple Pay JS API](https://developer.apple.com/documentation/apple_pay_on_the_web/apple_pay_js_api). Add a `button` element to your webpage and use the [Apple Pay documentation](https://developer.apple.com/documentation/apple_pay_on_the_web/displaying_apple_pay_buttons_using_css) to set the button type, and to see best practices on using CSS. Here's sample code for adding a black **Buy with Apple Pay** button, using the default size and corner radius: ```html ``` You can use the [canMakePayment()](https://developer.mozilla.org/en-US/docs/Web/API/PaymentRequest/canMakePayment) method to check if the device supports Apple Pay: ```javascript const supportsApplePay = new PaymentRequest( [{ supportedMethods: "https://apple.com/apple-pay" }], details ).canMakePayment(); // Supports Apple Pay? if (await supportsApplePay) { // show Apple Pay logo, for instance return; } ``` ## [Set up the Payment Request API for Apple Pay](#set-up-the-payment-request-api-for-apple-pay) After adding the button, you can set up methods, details, and options in the Payment Request API. ### [Methods](#methods) In **Methods**, indicate Apple Pay as a payment method by using: - "https://apple.com/apple-pay" - Apple Pay certified Moov account ID - Capabilities - Supported networks For more details, read the [W3 documentation on Methods](https://www.w3.org/TR/payment-request/#paymentmethoddata-dictionary). ### [Details](#details) In **Details**, you can specify transaction details. For example, the transaction’s amount, shipping options, display items, and other modifiers. For Apple Pay transactions, Moov has a platform limit of $100,000.00 per transaction. If you need a higher limit for your use-case, please contact [Moov support](https://support.moov.io/). For more details, read the [W3 documentation on Details](https://www.w3.org/TR/payment-request/#paymentdetailsinit-dictionary). ### [Options](#options) In **Options**, you can include any specific customer details or shipping information. For more details, read the [W3 documentation on Options](https://www.w3.org/TR/payment-request/#paymentoptions-dictionary). ```javascript // Sets up methods, details, and options for Payment Request API const methods = [ { supportedMethods: "https://apple.com/apple-pay", data: { version: 3, merchantIdentifier: "merchants-moov-account-id", merchantCapabilities: ["supports3DS", "supportsCredit", "supportsDebit"], supportedNetworks: ["amex", "discover", "masterCard", "visa"], countryCode: "US", requiredBillingContactFields: ["postalAddress"] }, } ]; // Details about the purchase const details = { total: { label: "Typically the merchant name", amount: { value: "1.00", currency: "USD" }, } }; const options = { requestPayerName: true, requestPayerEmail: true, requestPayerPhone: false }; ``` Failing to include the `requiredBillingContactFields` with `postalAddress` may result in declines or interchange downgrades. ## [Detect if Apple Pay is available](#detect-if-apple-pay-is-available) The Apple Pay button should only be displayed if your user is using a supported device. You can check if the browser will support ApplePaySession with the call below: ```javascript if (window.PaymentRequest) { // If available, show Apple Pay button } ``` Another option is to use Apple’s JS library [canMakePaymentsWithActiveCard](https://developer.apple.com/documentation/apple_pay_on_the_web/applepaysession/1778000-canmakepaymentswithactivecard) method to check if the device supports Apple Pay, and the user has an active card in their wallet. In the request below, use the merchant’s Moov `accountID` as the `merchantIdentifier`. ```javascript if (window.ApplePaySession) { let merchantIdentifier = 'merchants-moov-account-id'; let promise = ApplePaySession.canMakePaymentsWithActiveCard(merchantIdentifier); promise.then((canMakePayments) => { if (canMakePayments) { // Display Apple Pay button here. } }); } ``` Now that you have verified eligibility and added the button, you are ready to create a payment request with the previously defined options when the button is clicked: ```javascript const paymentRequest = new PaymentRequest(methods, details, options); ``` ## [Create & validate a merchant session](#create--validate-a-merchant-session) Once the payment request has been created, it’s time to create and validate an Apple Pay merchant session using the Moov API's create Apple Pay session `POST` [endpoint](/api/sources/apple-pay/session/), or Moov.js method shown below: ```javascript moov.accounts.applePay.sessions.create({ accountID: 'merchants-moov-account-id', applePaySessionConfig: { displayName: 'string' } }); ``` This request accepts the account ID and display name of the merchant that will be accepting the payment. The response is a promise that includes the opaque `merchantSession` response from Apple to be used to resolve the `onmerchantvalidation` step. - `accountID` - Moov account ID of the merchant, which is the destination of the transfer - `displayName` - Merchant name for display in the Apple Pay payment sheet, for example, “Whole Body Fitness” The `displayName` from the merchant session may be displayed as the merchant name in Apple’s native Wallet app. On the actual card statement, the `statementDescriptor` (or `dynamicDescriptor` for [approved accounts](/guides/money-movement/accept-payments/card-acceptance/statement-descriptors/#transfer-level-statement-descriptor)) will be displayed with the same logic as other card payments. ## [Link an Apple Pay token](#link-an-apple-pay-token) Link an Apple Pay token to the payer’s Moov account using the Moov API's link Apple Pay token `POST` [endpoint](/api/sources/apple-pay/token/), or Moov.js method shown below. The request accepts the account ID of the payer as well as the opaque `paymentResponse` from Apple. ```javascript moov.accounts.applePay.tokens.create({ accountID: 'payers-moov-account-id', applePayToken: paymentResponse.details }); ``` ## [Create a transfer & dismiss payment sheet](#create-a-transfer--dismiss-payment-sheet) The response payload from linking a token includes a `paymentMethodID` that is used as the source for the transfer in Moov’s create transfer `POST` [endpoint](/api/money-movement/transfers/create/). No Moov.js method exists for creating a transfer. Besides the `apple-pay` source payment method type, Apple Pay transfers are created the same as other card payments. To learn more about card payments with Moov, read our [Accept card payments](/use-cases/card-acceptance/) use case guide. ```javascript // Pseudo-code: instruct your server to make the transfer const moovTransferResponse = await fetch(`/pay`, { method: 'post', body: JSON.stringify({ paymentMethodID: paymentMethodID }) }); ``` Use the `X-Wait-For` [header](/guides/money-movement/events-and-statuses/#transfer-responses) on the transfer request to receive a synchronous response from the card network to close out the payment sheet. ```javascript let status; if (moovTransferResponse.source.cardDetails.status === 'confirmed') { status = 'success'; } else { status = 'fail'; } // Completes the payment request process and closes the payment sheet try { paymentResponse.complete(status); // Payment sheet is dismissed } catch (error) { console.error(error); } ``` ## [Seeing it altogether](#seeing-it-altogether) Here's a sample that synthesizes the steps above all in one place: ```javascript // Sets up methods, details, and options for Payment Request API const methods = [ { supportedMethods: "https://apple.com/apple-pay", data: { version: 3, merchantIdentifier: "merchants-moov-account-id", merchantCapabilities: ["supports3DS", "supportsCredit", "supportsDebit"], supportedNetworks: ["amex", "discover", "masterCard", "visa"], countryCode: "US", }, } ]; const details = { total: { label: "Typically the merchant name", amount: { value: "1.00", currency: "USD" }, } }; const options = { requestPayerName: true, requestPayerEmail: true, requestPayerPhone: false }; // Assumes a button click handler async function handleApplePayClick(event) { event.preventDefault(); try { // Uses native Payment Request API and passes the options we configured above const paymentRequest = new PaymentRequest(methods, details, options); // Event is fired as soon as the payment sheet is opened paymentRequest.onmerchantvalidation = (event) => { // Note: token with scopes to include this merchant account for use with Moov.js or any client-side integration const merchantSession = await moov.accounts.applePay.sessions.create({ accountID: 'merchant-uuid', applePaySessionConfig: { displayName: 'Merchant name' }}); event.complete(merchantSession); }; // Display the payment sheet via Payment Request API const paymentResponse = await paymentRequest.show(); /* Note: token with scopes should include this payer account for use with Moov.js or any client-side integration moov.accounts.applePay.tokens.create() will return a promise of the token, including. the paymentMethodID */ const { paymentMethodID } = await moov.accounts.applePay.tokens.create({ accountID: 'payer-uuid', applePayToken: paymentResponse.details }); // Pseudo-code: instruct your server to make the transfer. X-Wait-For header is needed to get response. const moovTransferResponse = await fetch(`/pay`, { method: 'post', body: JSON.stringify({ paymentMethodID: paymentMethodID }) }); let status; if (moovTransferResponse.source.cardDetails.status === 'confirmed') { status = 'success'; } else { status = 'fail'; } // Completes the payment request process and closes the payment sheet paymentResponse.complete(status); // Payment sheet is dismissed } catch (error) { console.error(error); } }; ``` For more information, refer to [Apple’s documentation](https://developer.apple.com/documentation/apple_pay_on_the_web/payment_request_api/setting_up_the_payment_request_api_to_accept_apple_pay/). --- URL: https://docs.moov.io/guides/sources/cards/card-account-updater/ --- # Card account updater Learn how you can set up cards to automatically receive updates. If you're interested in using the card account updater service, [contact Moov](https://support.moov.io/) for more information. ## [What is a card account updater?](#what-is-a-card-account-updater) A card account updater is a solution that helps businesses ensure that customer credit card information is up-to-date. The card account updater automatically updates payment information when a card has expired or been replaced, eliminating the need to contact cardholders to obtain new information. When details change on a card linked to Moov, such as the card number or the expiration date, Moov's card account updater service will automatically update the information on your behalf. ## [Set cardOnFile](#set-cardonfile) You must follow the instructions to [save a card for future use](/guides/sources/cards/#save-a-card-for-future-use) during card linking to use the card account updater service. If `cardOnFile` was set to **true** during the card linking and [verification](/guides/sources/cards/#save-a-card-for-future-use) process, the card will be stored and opted in to automatic updates from the issuer. The `merchantAccountID` is also set during card linking and [verification](/guides/sources/cards/#card-verification), and specifies two things: - The merchant that is authorized to store card details - The merchant that will be billed for updates By default, `cardOnFile` is set to **false**, and `merchantAccountID` is set to your platform's account ID. To update a linked card's `cardOnFile` or `merchantAccountID`, and opt-in to automatic updates from the issuer, you can use the card `PATCH` [endpoint](/api/sources/cards/update/). ## [View updated card details](#view-updated-card-details) The card networks will communicate the following types of updates: | Update type | Description | Action | |----------------------|---------------------------------------------------------------------------------------------------------|---------------------------------------| | `number-update` | A new account number has been provided, or a new account number *and* expiration date has been provided | PAN is updated with new record | | `expiration-update` | A new expiration date has been provided | Expiration is updated with new record | | `contact-cardholder` | A match was found, but the account information on file may not be current | Merchant should contact cardholder | | `account-closed` | The account is closed (possibly due to permanent closure or fraud ) | Merchant should disable card | You can view the last update to the card by using the card `GET` [endpoint](/api/sources/cards/get/). In the response, you'll receive the last update type and the date the details were updated on. ```json { "cardID": "ec7e1848-dc80-4ab0-8827-dd7fc0737b43", "cardAccountUpdater": { "updateType": "number-update", "updatedOn": "datetime" } } ``` ## [Webhooks](#webhooks) An event is fired when there's an update to any of the following card details: - `number-update` - `expiration-update` - `contact-cardholder` - `account-closed` Use the `card.autoUpdated` webhook, which will respond with the following event payload: ```json { "eventID": "14980a04-2e32-4921-a771-4959a36534a6", "type": "card.autoUpdated", "data": { "cardID": "51015d0d-8dca-49a0-ba70-abfed073f785", "accountID": "51015d0d-8dca-49a0-ba70-abfed073f785", "updateType": "number-update" }, "createdOn": "2021-09-02T13:57:50Z" } ``` If you'd like to learn more about webhooks, view the [webhooks](/guides/webhooks/) guide. --- URL: https://docs.moov.io/guides/sources/cards/google-pay/ --- # Accept cards with Google Pay™ **This feature is coming soon!** The information below describes a feature that is not yet available in production. The API details are subject to change. Moov allows you to accept card payments with Google Pay. This step by step guide covers how you can start accepting Google Pay on the web using the open standard Payment Request API. In addition to being a fast and easy way to accept payments, Google Pay offers strong privacy and security. In this guide, we'll direct you to Google's guidelines, and bring you through a step by step process of adding a functional Google Pay button. ## [Prerequisites](#prerequisites) Before getting started, make sure your website follows Google's guidelines, and that your server is set up accordingly. - [Google Pay overview](https://developers.google.com/pay/api/web/overview) - [Google Pay website brand guidelines](https://developers.google.com/pay/api/web/guides/brand-guidelines) - [Google Pay integration checklist](https://developers.google.com/pay/api/web/guides/test-and-deploy/integration-checklist) - [Google Pay prerequisites](https://developers.google.com/pay/api/web/guides/setup) - All pages that include Google Pay must be served over HTTPS - Your domain must have a TLS domain-validated certificate - You must adhere to the [Google Pay API Acceptable Use Policy](https://payments.developers.google.com/terms/aup) - You must accept the [Google Pay API Terms of Service](https://payments.developers.google.com/terms/sellertos) ## [Add Google Pay JavaScript library](#add-google-pay-javascript-library) Include the Google Pay JavaScript library: ```html ``` ## [Add Google Pay button](#add-google-pay-button) Add a `div` element to your webpage and use the [Google Pay documentation](https://developers.google.com/pay/api/web/guides/resources/customize) to customize the button type, and to see best practices on using CSS. Here's sample code for adding a simple black **Buy with Google Pay** button, using the default size and corner radius: ```html
``` ## [Set up Google Pay PaymentsClient](#set-up-google-pay-paymentsclient) After adding the button, you can set up the PaymentsClient. Start with a base configuration and modify it to your needs: ```javascript // Environment: TEST or PRODUCTION // Configure object for a production environment once your implementation testing is completed. environment: 'PRODUCTION' const googlePayEnv = 'TEST'; // Moov Account ID const accountID = 'payer-uuid'; // Bearer token const bearerToken = 'my token'; // This is the base configuration for all Google Pay payment data requests. // -- Update `tokenizationSpecification.parameters.gatewayMerchantId` with your own value in the Moov Dashboard. // -- Update the `merchantInfo.merchantId` and `merchantInfo.merchantName` properties with your own values from Google. // Moov only supports the following Auth Methods: 'PAN_ONLY' and 'CRYPTOGRAM_3DS' --> Moov does NOT support 3DS from a third-party provider // Moov only supports the following Card Networks: 'AMEX', 'DISCOVER', 'MASTERCARD' and 'VISA' const googlePayBaseConfiguration = { apiVersion: 2, apiVersionMinor: 0, allowedPaymentMethods: [ { type: 'CARD', parameters: { allowedAuthMethods: ['PAN_ONLY', 'CRYPTOGRAM_3DS'], allowedCardNetworks: ['AMEX', 'DISCOVER', 'MASTERCARD', 'VISA'], billingAddressRequired: true, billingAddressParameters: { format: 'FULL', }, }, tokenizationSpecification: { type: 'PAYMENT_GATEWAY', parameters: { 'gateway': 'moov', 'gatewayMerchantId': 'a2c4e6g8-i9k1-m3o5-q7s9u1w3y5a7c9e1g' } }, }, ], merchantInfo: { merchantId: '01234567890123456789', merchantName: 'Example Merchant', }, emailRequired: true, }; ``` Now create the PaymentsClient: ```javascript let googlePayClient = null; // Create a new PaymentsClient instance. function getGooglePaymentsClient() { if (googlePayClient === null) { googlePayClient = new google.payments.api.PaymentsClient({ environment: googlePayEnv, }); } return googlePayClient; } ``` ## [Set up event handlers for page load and Google Pay button click](#set-up-event-handlers-for-page-load-and-google-pay-button-click) Create an event handler to show the button after the scripts on the page load: ```javascript function onGooglePayLoaded() { paymentRequest = Object.assign({}, googlePayBaseConfiguration); getGooglePaymentsClient() .isReadyToPay(paymentRequest) .then(function(res) { if (res.result) { button = getGooglePaymentsClient().createButton({ onClick: onGooglePayButtonClick }); document.getElementById('gpay-button-container').appendChild(button); } else { console.log("Google Pay is not ready for this user."); } }) .catch(console.error); } ``` When the Google Pay button is clicked, update the transaction info: ```javascript // Moov only supports USD for the United States function onGooglePayButtonClick() { paymentRequest.transactionInfo = { totalPriceStatus: 'FINAL', totalPrice: '12.34', currencyCode: 'USD', countryCode: 'US', }; googlePayClient.loadPaymentData(paymentRequest).then(onGooglePayPaymentLoaded).catch(console.error); } ``` ## [Create payment method](#create-payment-method) Once the customer selects their desired payment method and clicks continue, the client will receive the Google Pay token. Send it to the Moov Platform to get a payment method: ```javascript // When the token is received from Google Pay, pass the token to the Moov Platform to receive a payment method function onGooglePayPaymentLoaded(paymentResponse) { let url = 'https://api.moov.io/accounts/' + accountID; let paymentMethodURL = url + '/google-pay/tokens'; // Create Moov payment method const moovCreatePaymentMethodResponse = fetch(paymentMethodURL, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + bearerToken, }, body: JSON.stringify({ paymentMethodData: paymentResponse.paymentMethodData }) }).then(response => { response.json(); }); }).catch(console.error); } ``` ## [Create Moov transfer](#create-moov-transfer) Now that you have a Moov payment method associated to the Google Pay token, create a transfer: ```javascript // Create Moov transfer let transferURL = url + '/transfers'; const moovTransferResponse = fetch(transferURL, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + bearerToken, 'X-Wait-For': 'rail-response' }, body: JSON.stringify({ paymentMethodID: moovCreatePaymentMethodResponse.paymentMethodID, amount: 12.34 }) }).then(response => { response.json(); }); ``` Use the `X-Wait-For` [header](/guides/money-movement/events-and-statuses/#transfer-responses) on the transfer request to receive a synchronous response from the card network ```javascript let status; if (moovTransferResponse.source.cardDetails.status === 'confirmed') { status = 'success'; } else { status = 'fail'; } ``` ## [Seeing it all together](#seeing-it-all-together) Here's a sample that synthesizes the steps above all in one place: ```html
``` For more information, refer to [Google’s documentation](https://developers.google.com/pay/api/web/guides/tutorial). --- URL: https://docs.moov.io/guides/sources/cards/ --- # Cards Link debit and credit cards to a Moov account and set up cards to receive automatic updates. To use a card as a payment source, Moov must verify the card details with the card networks. Optionally, you can save a card for future use and set up a card to automatically receive updates from the issuer, like a new expiration date. ## [Payment methods](#payment-methods) | Payment method type | Description | Required capability | |---------------------|-------------------------------------|---------------------| | `card-payment` | Can be the source of a card payment | `transfers` | If `card-payment` is the source, the destination must be a `moov-wallet`. Moov has a platform limit of $100,000.00 per transaction using the `card-payment` method. Please contact [Moov support](https://support.moov.io/) if you need a higher limit to support your use-case. Use the guides in this section to learn more about accepting card payments and receiving updates through Moov's card account updater. --- URL: https://docs.moov.io/guides/sources/ --- # Funding sources A funding source is a bank account, payment card, or wallet that is linked to a Moov account. Depending on what kind funding sources are linked to a Moov account, Moov creates the appropriate [payment method](/guides/money-movement/payment-methods/) for that account, which will be then used in transfers. This section will guide you through linking cards and bank accounts. After linking a card you can ensure card information stays up-to-date with our card account updater service. Bank accounts require traditional micro-deposit verification or instant account verification through one of our mutual service partners, Plaid Link or MX. --- URL: https://docs.moov.io/guides/sources/wallets/balance/ --- # Wallet balance Learn how to find details about a wallet's available funds and how to avoid a negative balance. A wallet balance displays the funds currently available for a Moov account. Transferring from a wallet will instantly decrease the wallet’s balance. There are no fees associated with an empty or negative wallet, however, a [negative balance](#negative-balance) should be avoided. A negative balance will impact the accounts ability to continue moving funds. ## [Viewing balance via API](#viewing-balance-via-api) Provide the `walletID` and/or `accountID` path parameters to the following endpoints to view a wallet's balance: - [List wallets](/api/sources/wallets/list/) - Lists all wallets associated with an account - [Retrieve a wallet](/api/sources/wallets/get/) - Gets details of a specific wallet The response will contain the `availableBalance` object. An account ID (also referred to as `X-Account-ID`) can be found in the Dashboard by navigating to **Settings > Business details**. Your account ID will be listed at the top of the **Business details** section and you can copy it to your clipboard. Navigate to the **Wallet** section of the Dashboard and click the menu option in the wallet summary section. You'll be able to copy the wallet ID to your clipboard. You can also retrieve a wallet ID by providing `accountID` to the list payment methods `GET` [endpoint](/api/sources/payment-methods/list/). ## [Negative balance](#negative-balance) Moov will use an account's wallet to settle refunds, disputes, ACH reversals and Moov fees, which could result in a negative balance. For example, an ACH reversal can be triggered on a completed transfer within 60 calendar days of the initial transfer request. A reversal occurs when funds make it to a destination, but need to be returned. In this scenario, Moov routes the funds back to the original party by deducting the funds from the receiving wallet. The recipient of an initiated transfer reversal is responsible for funding the wallet to cover the possibility of a negative balance. See the [ACH exception](/guides/money-movement/accept-payments/ach/returns/) guide for detailed information on return scenarios. ## [Webhooks](#webhooks) You can subscribe to wallet `balance.updated` event using [webhooks](/guides/webhooks/webhook-events/#balance). ```jsx { "eventID": "14980a04-2e32-4921-a771-4959a36534a6", "type": "balance.updated", "data": { "accountID": "51015d0d-8dca-49a0-ba70-abfed073f785", "walletID": "51015d0d-8dca-49a0-ba70-abfed073f785", }, "createdOn": "2021-09-02T13:57:50Z" } ``` --- URL: https://docs.moov.io/guides/sources/wallets/ --- # Wallets Each Moov account is provided with a default wallet and can request additional general wallets, where the account holder can store funds. Every Moov account can request one default wallet, as long as the account meets the wallet capability [requirements](/guides/accounts/capabilities/reference/). A Moov wallet holds funds and can be used as a source or destination for any transfer involving a wallet. Moov automatically creates a `moov-wallet` payment method when the `wallet.balance` capability is enabled for an account. Additionally, every account can request up to 10 general wallets to fulfill additional needs. | Payment method | Description | Required capability | Verification required | |----------------|--------------------------------|---------------------|-----------------------| | `moov-wallet` | Can be the source of a payment | `wallet.balance` | **✓** | If you want to send money to a bank account via RTP, the payment method source *must* be a `moov-wallet`. While you can request the wallet capability directly, any account that is approved for at least one `send-funds` or one `collect-funds` capability will have the `wallet.balance` capability automatically enabled too. A wallet allows for flexibility on when and how you’d like to move funds. You can accomplish the following with a wallet: - Accumulate collected payments - Transfer funds between Moov wallets for instantly available funds - Pre-fund your wallet for faster payouts - Cash out from your wallet at any time See the articles in this section for more information on wallet balances and transaction details. --- URL: https://docs.moov.io/guides/sources/wallets/multiple-wallets/ --- # Multiple wallets Creating multiple wallets allows you to organize and manage funds across different business functions, projects, or purposes within a single Moov account. Moov provides each account with a default wallet. In addition to this wallet, you can create multiple general wallets. Each wallet maintains its own independent balance and transaction history, giving you greater flexibility in fund management and reconciliation. Use cases and benefits: - **Separate business functions**: Allocate funds for different purposes (for example, customer payments, vendor payouts, employee expenses) - **Simplified reconciliation**: Maintain distinct balances that align with your accounting processes - **Automated payouts:** Each wallet can sweep funds to a specific bank account supporting custom settlement structures - **Flexible fund management**: Move money between wallets as your business needs evolve Fees, refunds, disputes, and reversals are automatically associated with the wallet involved in the original transaction. Note, fees and reversals generated from bank-to-bank transfers will affect the default wallet if there is no wallet payment method set. Additionally, each wallet can have its own sweep configuration where you can settle funds to a specified bank account each day. If you normally use the Moov Dashboard, see our Dashboard [balances](/guides/dashboard/wallet) guide for more information. ## [Default wallets](#default-wallets) Moov automatically generates a default wallet for every account when the `wallet.balance` capability is enabled. These wallets cannot be closed, will always be `walletType: default`, and will always remain `status: active`. Default wallets are given a default name, but you can update the wallet to have a custom name and description using the `PATCH` wallets [endpoint](/api/sources/wallets/update/). For example, "Master wallet, Enterprise funds." ```zsh curl -X PATCH "https://api.moov.io/accounts/{accountID}/wallets/{walletID}" \ -H "Authorization: Bearer {token}" \ -d '{ "name": "Master wallet", "description": "Enterprise funds" }' ``` ## [General wallets](#general-wallets) A general wallet is optional, and can be created via the [Moov API](/api/sources/wallets/create/) or within the Dashboard. An account can have up to 10 active `general` wallets. Once a new general wallet is created, an associated `paymentMethodID` will be generated and multiple `moov-wallet` payment methods will be available to use as the source and/or destination in your transfers. Note, depending on your fee plan and agreement with Moov, each wallet that's created might incur a fee. General wallets can also be updated using the `PATCH` wallets [endpoint](/api/sources/wallets/update/). In addition to updating the name and description, you can use the `PATCH` wallets [endpoint](/api/sources/wallets/update/) to close the wallet when no longer needed. ## [Status & closing a wallet](#status--closing-a-wallet) A general wallet can have a status of `active` or `closed`: - `active`: Wallet has a balance and has associated `moov-wallet` payment method enabled - `closed`: A closed wallet is permanently disabled, as is the corresponding payment method To close a general wallet, the following criteria needs to be met: - No pending inbound transfers - Balance is zero and has no activity in the past 75 days - Cannot be a `default` wallet Use the `PATCH` wallets [endpoint](/api/sources/wallets/update/) to close a general wallet: ```zsh curl -X PATCH "https://api.moov.io/accounts/{accountID}/wallets/{walletID}" \ -H "Authorization: Bearer {token}" \ -d '{ "status": "closed" }' ``` Closing a wallet has no impact on data retention for transactions. A closed wallet may incur transactions from exceptions, such as disputes, refunds, or ACH returns, resulting in a negative balance. Ensure any negative balances are resolved within a timely manner. Once a wallet is closed, it cannot be reopened. View our [API](/api/sources/wallets/) for more information. --- URL: https://docs.moov.io/guides/sources/wallets/transactions/ --- # Wallet transactions Learn how wallet transactions provide insight into funds that move in and out of an account’s wallet. For each transfer, a corresponding transaction is created representing how that initial source impacted a wallet. This granularity enables you to: - **Reconcile** a wallet’s balance on any given day - **Create** itemized reports leveraging transaction types (fees earned and paid, payouts, refunds, etc) - **Monitor** your wallet activity to stay informed on the latest transactions Each transaction is paired with a detailed memo that provides more context about the transaction. For additional insight into how the transaction was created, you can provide the source ID to grab details. The source ID is used to link back to a transfer, dispute, or card issuing transaction. You can retrieve the `sourceID` using the wallet transaction `GET` [endpoint](/api/sources/wallets/get-transaction/). ## [Pending transactions](#pending-transactions) A `pending` transaction will only apply to credits, or incoming funds. Any funds in a pending state will not affect the wallet balance, or be available for use until that transaction is completed. If a `pending` transaction results in a failure, we’ll simply omit it from the transaction list. Use the wallet `GET` [endpoint](/api/sources/wallets/get/) to check a wallet's available balance or access a failed transaction's details. ## [Completed transactions](#completed-transactions) The available balance at the time of transaction is included on each `completed` wallet transaction. Once a transaction moves to `completed`, the `completedOn` timestamp will be populated along with the `availableBalance`. ## [Wallet transaction types](#wallet-transaction-types) The [list wallet transactions](/api/sources/wallets/list-transactions/) and [retrieve a wallet transaction](/api/sources/wallets/get-transaction/) endpoints will display the `transactionType` in the response. We categorize wallet transactions by the following distinct types: ### [ACH](#ach) | Type | Description | Source | Memo | |--------------|---------------------------------------------------------------------------------------------|----------|-------------------------------------------------------| | payment | An ACH payment from a bank to the account’s wallet | transfer | ACH payment from {displayName} | | top-up | Transfer of funds into a wallet from the account’s bank | transfer | Top up from {bankAccountType} {lastFourAccountNumber} | | payout | A payment from a wallet to another accounts bank | transfer | ACH payment to {displayName} | | cash-out | Transfer of funds out of a wallet to the account’s bank | transfer | Cash out to {bankAccountType} {lastFourAccountNumber} | | ach-reversal | When an ach payment is returned, funds are either returned or taken from the wallet balance | transfer | Returned ACH credit/debit | ### [Card acquiring](#card-acquiring) | Type | Description | Source | Memo | |------------------|-----------------------------------------------------------------------------------|----------|---------------------------------| | card-payment | A payment that was made from a card | transfer | Card payment from {displayName} | | refund | The requested refund amount is debited from the wallet | transfer | Refund to {displayName} | | refund-failure | To account for refund failures, a credit will be made back into the wallet | transfer | Failed refund to {displayName} | | dispute | When a customer disputes a charge, the disputed amount is debited from the wallet | dispute | Cardholder dispute | | dispute-reversal | If a dispute is won by a merchant, funds will be credited back to their wallet | dispute | Cardholder dispute reversed | ### [RTP](#rtp) | Type | Description | Source | Memo | |-------------|---------------------------------------------------------|----------|-----------------------------------------------------------| | payout | A payment from a wallet to another accounts bank | transfer | Card payout to {displayName} | | cash-out | Transfer of funds out of a wallet to the account’s bank | transfer | RTP cash out to {bankAccountType} {lastFourAccountNumber} | | rtp-failure | The receiving bank has rejected the transfer | transfer | Failed RTP payment {failureCode} | ### [Push to card](#push-to-card) | Type | Description | Source | Memo | |---------------|----------------------------------------------------------------------------------|----------|-----------------------------------------------| | payout | A payment from a wallet to another accounts bank | transfer | Card payout to {displayName} | | cash-out | Transfer of funds out of a wallet to the account’s bank | transfer | Card cash out to {brand} {lastFourCardNumber} | | card-decline | The authorization has failed | transfer | Declined card payout {reason} | | card-reversal | The authorization has been reversed, cancelling the transfer and returning funds | transfer | Card payment reversed | ### [Pull from card](#pull-from-card) | Type | Description | Source | Memo | |------------------|------------------------------------------------------------------------------------|----------|--------------------------------------------------| | account-funding | Debit or prepaid card transfer to an external account owned by the cardholder | transfer | Account funding from {displayName} | | top-up | Transfer of funds into a wallet from the account’s bank | transfer | Wallet funding from {brand} {lastFourCardNumber} | | refund | When a refund is initiated, the requested refund amount is debited from the wallet | transfer | Refund to {displayName} | | refund-failure | To account for refund failures, a credit will be made back into the wallet | transfer | Failed refund to {displayName} | | dispute | When a customer disputes a charge, the disputed amount is debited from the wallet | dispute | Cardholder dispute | | dispute-reversal | If a dispute is won by a merchant, funds will be credited back to their wallet | dispute | Cardholder dispute reversed | ### [Sweeps](#sweeps) Type Description Source Memo auto-sweep Daily transfers to external bank accounts on a set schedule sweep Automatic sweep {bankAccountType} {lastFourAccountNumber}, Failed sweep {endDate} {reason} ### [Moov wallet](#moov-wallet) | Type | Description | Source | Memo | |----------|------------------------------------------------|----------|-------------------| | moov-fee | Fee charged to your account for card transfers | transfer | Fee for {feeName} | ### [Wallet to wallet](#wallet-to-wallet) | Type | Description | Source | Memo | |-----------------|--------------------------------------|----------|---------------------------------------| | wallet-transfer | Funds that move between Moov wallets | transfer | Wallet transfer to/from {displayName} | ### [Fees](#fees) | Type | Description | Source | Memo | |-----------------|------------------------------------------------|----------|---------------------------| | facilitator-fee | Fee earned on a transfer | transfer | Facilitator fee collected | | moov-fee | Fee charged to your account for card transfers | transfer | Fee for {feeName} | ### [Issuing\*](#issuing) Type Description Source Memo issuing-transaction Reflects funds moving out of the wallet from a cleared authorization, a refund, or a force post issuing-transaction Payment {Merchant Name}, Refund {Merchant Name}, Credit {Merchant Name}, Payment {Merchant Name} issuing-auth-release Held funds are released back to the wallet due to an authorization reversal, expiration, or when the authorization is cleared issuing-authorization Authorization release {Merchant Name} issuing-auth-hold Funds are reserved on the wallet balance due to an approved authorization issuing-authorization Authorization hold {Merchant Name} \*Card issuing is currently in a closed beta. [Contact Moov](https://moov.io/contact/) for more information. ## [Webhooks](#webhooks) You can subscribe to the `walletTransaction.updated` [webhook](/guides/webhooks/webhook-events/#wallet-transactions) event to get real-time updates on pending or completed transactions. Below is an example of an event for a completed transaction: ```jsx { "eventID": "14980a04-2e32-4921-a771-4959a36534a6", "type": "walletTranscation.updated", "data": { "accountID": "51015d0d-8dca-49a0-ba70-abfed073f785", "walletID": "51015d0d-8dca-49a0-ba70-abfed073f785", "transactionID": "51015d0d-8dca-49a0-ba70-abfed073f785", "status": "completed", }, }, "createdOn": "2021-09-02T13:57:50.762679289Z" } ``` ## [View transactions via API](#view-transactions-via-api) Provide the `accountID` and `walletID` path parameters to the following endpoints to view wallet transactions for an account. Retrieving a specific wallet transaction additionally requires the `transactionID`. - [Retrieve a wallet transaction](/api/sources/wallets/get-transaction/) - Gets a specific wallet transaction - [List wallet transactions](/api/sources/wallets/list-transactions/) - Lists all transactions associated with a wallet An account ID (also referred to as `X-Account-ID`) can be found in the Dashboard by navigating to **Settings > Business details**. Your account ID will be listed at the top of the **Business details** section and you can copy it to your clipboard. Navigate to the **Wallet** section of the Dashboard and click the menu option in the wallet summary section. You'll be able to copy the wallet ID to your clipboard. You can also retrieve a wallet ID by providing `accountID` to the list payment methods `GET` [endpoint](/api/sources/payment-methods/list/). A transaction ID can be found by navigating to **Wallet** in the Dashboard and clicking on a transaction to open the details. In the details modal, the transaction ID can be copied to your clipboard. You can also retrieve a transaction ID by passing `accountID` and `walletID` to the list transactions `GET` [endpoint](/api/sources/wallets/list-transactions/). You can achieve a faster response by restricting the data with the optional start and end date time parameters. ## [Adjustments](#adjustments) There are one-off scenarios where Moov may make an immediate adjustment to a wallet’s balance. Some examples include partial chargebacks, fee adjustments, or corrections from transaction processing. You’ll receive a `walletTransaction.updated` webhook notification once the adjustment is made. More details about the adjustment can be found in the wallet transaction memo and the source type will link to the `adjustmentID`. To retrieve a specific wallet adjustment or list all adjustments for a specific wallet, you can use the endpoints listed below. You'll need to pass the `walletID` to each endpoint, and to retrieve a specific adjustment, you'll also need to pass the `adjustmentID`. - [Retrieve a wallet adjustment](/api/sources/wallets/get-adjustment/) - Gets a specific wallet adjustment - [List wallet adjustments](/api/sources/wallets/list-adjustments/) - Lists all adjustments associated with a wallet ## [View transactions via Dashboard](#view-transactions-via-dashboard) Navigate to **Wallet** in the Dashboard to view transactions. See the [Dashboard wallet](/guides/dashboard/wallet/) guide for information. --- URL: https://docs.moov.io/guides/webhooks/check-webhook-signatures/ --- # Check webhook signatures Use this guide to learn how to confirm that webhook events were sent by Moov. Every event Moov sends to a webhook endpoint includes a signature generated through a SHA-512 hash-based message authentication code ([HMAC](https://en.wikipedia.org/wiki/HMAC#:~:text=In%20cryptography%2C%20an%20HMAC%20%28sometimes,and%20a%20secret%20cryptographic%20key.%29)). This allows you to verify that Moov (and not a third party) sent these events to your service. ## [Check the signature](#check-the-signature) To check the signature for a particular webhook, use the signing secret to create a new hash through the steps outlined below. If the hash you created matches the value of the `X-Signature` header, you know that the event came from Moov. Otherwise, your service can discard the event. All of the data needed to create the hash, except for the signing secret, is sent in HTTP headers in the `POST` to the configured webhook endpoint. You can obtain the signing secret for each webhook from the [Moov Dashboard](https://dashboard.moov.io/developers/webhooks). The headers with values needed to create the hash are: - `X-Timestamp` - `X-Nonce` - `X-Webhook-ID` - `X-Signature` Using your favorite programming language, perform the following steps to construct your hash and compare against the event signature: 1. Get the signing secret from the [Moov Dashboard](https://dashboard.moov.io/developers/webhooks). 2. Get the header values from the received `POST`. 3. Prepare the signed payload. `timeStamp + "|" + nonce + "|" + webhookID` 4. Determine the expected signature using the signing secret and the payload from step 3. 5. Check both signatures for equality. See the following example: [Javascript](#tab-827394165-1-0) [Go](#tab-827394165-1-1) ```javascript const hmacSHA512 = require("crypto-js/hmac-sha512"); // Get your signing secret from dashboard.moov.io const webhookSecret = process.env.WEBHOOK_SECRET; // Check if the hash of headers match the signature const isSigned = (timestamp, nonce, webhookId, signature) => { const concatHeaders = `${timestamp}|${nonce}|${webhookId}`; const checkHash = hmacSHA512(concatHeaders, webhookSecret); return signature === checkHash.toString(); } // Serverless function exports.handler = async (event, context, callback) => { if (!event.body) { console.log("Invalid request"); callback(null, { statusCode: 400, body: "Invalid request" }); } // Headers are lowercased if (!isSigned( event.headers["x-timestamp"], event.headers["x-nonce"], event.headers["x-webhook-id"], event.headers["x-signature"]) ) { console.log("Signature is invalid"); callback(null, { statusCode: 400, body: "Signature is invalid" }); } let webhook; try { webhook = JSON.parse(event.body); } catch (err) { console.log("Invalid JSON"); callback(null, { statusCode: 400, body: "Invalid JSON" }); } // Logs the event message payload console.log(event.body); callback(null, { statusCode: 200 }); }; ``` ```go package main import ( "crypto/hmac" "crypto/sha512" "encoding/hex" "fmt" "os" "github.com/aws/aws-lambda-go/events" "github.com/aws/aws-lambda-go/lambda" ) func main() { lambda.Start(handler) } func handler(r events.APIGatewayProxyRequest) (*events.APIGatewayProxyResponse, error) { var ( webhookSecret = os.Getenv("WEBHOOK_SECRET") timestamp = r.Headers["x-timestamp"] nonce = r.Headers["x-nonce"] webhookID = r.Headers["x-webhook-id"] gotHash = r.Headers["x-signature"] ) concatHeaders := timestamp + "|" + nonce + "|" + webhookID wantHash, err := hash([]byte(concatHeaders), []byte(webhookSecret)) if err != nil { return nil, err } if *wantHash == gotHash { fmt.Println("Webhook received!") return &events.APIGatewayProxyResponse{ StatusCode: 200, }, nil } else { msg := "Signature is invalid" fmt.Println(msg) return &events.APIGatewayProxyResponse{ StatusCode: 400, Body: msg, }, nil } } // hash generates a SHA512 HMAC hash of p using the secret provided. func hash(p []byte, secret []byte) (*string, error) { h := hmac.New(sha512.New, secret) _, err := h.Write(p) if err != nil { return nil, err } hash := hex.EncodeToString(h.Sum(nil)) return &hash, nil } ``` [Fork example code](https://github.com/moovfinancial/webhook-handler) --- URL: https://docs.moov.io/guides/webhooks/ --- # Webhooks Learn more about webhooks in Moov's platform. ## [What are webhooks?](#what-are-webhooks) Webhooks allow applications to react to state changes in a platform in real time. When an event occurs, a webhook will send a payload to the application corresponding to the target endpoint. A webhook can be setup to be notified of all event types or specific ones, such as a transfer being returned or a customer updating their address. This allows your application to react to different events in Moov's platform, which is more efficient than polling an API to determine if an event has occurred. You can use webhooks in a variety of ways: - Integrate with existing software systems - Send notifications - Collect data for record-keeping and reconciliation With webhooks, you can build systems that react to events as they happen. They are built to be flexible and can be configured to fit your needs in the long-term. Use the guides in this section to learn what webhooks are available and how to set them up. --- URL: https://docs.moov.io/guides/webhooks/set-up-webhooks/ --- # How to set up webhooks Learn how to configure and optimize webhooks for your integration. ## [Determine what events to subscribe to](#determine-what-events-to-subscribe-to) To minimize unnecessary burden on your server, only subscribe to events you need. See our [webhook events](/guides/webhooks/webhook-events/) guide for a full list of events and payload examples. ## [Create a webhook endpoint on your server](#create-a-webhook-endpoint-on-your-server) Set up an HTTPS endpoint that accepts and processes HTTP `POST` calls. A URL with HTTPS is required. ## [Register your endpoint in the Moov Dashboard](#register-your-endpoint-in-the-moov-dashboard) In the Moov Dashboard, navigate to **Developers** and select **Webhooks**. There, you can include your endpoint URL, an optional description, and which events you’d like to subscribe to. ## [Test the endpoint](#test-the-endpoint) In the Moov Dashboard, you can trigger a test event to your webhook by selecting the **Send test webhook** action. ![Test webhook](../images/send-test-webhook.png) The target server URL will receive a test payload that looks like this: ```json { "eventID": "d9d18a42-d1ea-4e4c-b671-0fa93e24d584", "type": "event.test", "data": { "ping": true }, "createdOn": "2024-01-26T20:42:25Z" } ``` ## [Verify events were sent by Moov](#verify-events-were-sent-by-moov) Check out our example [webhook handler project](https://github.com/moovfinancial/webhook-handler) on GitHub. Every event Moov sends to a webhook endpoint includes a signature which allows you to verify that Moov (and not a third party) sent these events to your service. Use the following steps to construct your hash and compare it against the event signature: 1. Get the signing secret from the [Moov Dashboard](https://dashboard.moov.io/developers/webhooks). 2. Get the following header values from the received `POST`: - `X-Timestamp` - `X-Nonce` - `X-Webhook-ID` - `X-Signature` 3. Prepare the string: `{X-Timestamp} + "|" + {X-Nonce} + "|" + {X-Webhook-ID}`. 4. Calculate the expected signature using the hashing algorithm HMAC-SHA512 with the signing secret and string from step 3. 5. Check the expected signature matches the value set in `X-Signature`. If the hash you created matches the value of the `X-Signature` header, you know that the event came from Moov. Otherwise, your service should discard the event. See the example below: ```jsx const hmacSHA512 = require("crypto-js/hmac-sha512"); // Get your signing secret from dashboard.moov.io const webhookSecret = process.env.WEBHOOK_SECRET; // Check if the hash of headers match the signature const isSigned = (timestamp, nonce, webhookId, signature) => { const concatHeaders = `${timestamp}|${nonce}|${webhookId}`; const checkHash = hmacSHA512(concatHeaders, webhookSecret); return signature === checkHash.toString(); } // Serverless function exports.handler = async (event, context, callback) => { if (!event.body) { console.log("Invalid request"); callback(null, { statusCode: 400, body: "Invalid request" }); } if (!isSigned( event.headers["X-Timestamp"], event.headers["X-Nonce"], event.headers["X-Webhook-ID"], event.headers["X-Signature"]) ) { console.log("Signature is invalid"); callback(null, { statusCode: 400, body: "Signature is invalid" }); } let webhook; try { webhook = JSON.parse(event.body); } catch (err) { console.log("Invalid JSON"); callback(null, { statusCode: 400, body: "Invalid JSON" }); } // Logs the event message payload console.log(event.body); callback(null, { statusCode: 200 }); }; ``` ## [Best practices](#best-practices) We recommend implementing the following best practices when using webhooks with Moov. ### [Subscribe to a minimum number of events](#subscribe-to-a-minimum-number-of-events) To optimize performance and avoid overloading your server, subscribe to a minimum number of events. Alternatively, you can set up multiple webhooks subscribed to specific event types. ### [Respond within 5 seconds](#respond-within-5-seconds) If Moov does not receive a `2xx` response from your server within 5 seconds, we’ll consider the delivery of the webhook event as failed. Moov will retry the webhook multiple times, for up to 24 hours. If webhook servers return a `404` after the last retry, the webhook will become disabled. --- URL: https://docs.moov.io/guides/webhooks/webhook-events/ --- # Webhook events We generate an event when something happens in our system, and we record the relevant data. Use this guide to understand Moov's webhook events, and what kind of payloads are supported. This page details the variety of event types and schemas Moov has for supported webhooks. ## [Events](#events) Let's use creating a customer as an example. When a customer is created, we generate an event called `account.created`. The contents of an event object depend on its type. Here's a sample event payload, with `account.created` as an example. ```json { "eventID": "30f39f5b-6a26-4772-b5a5-d8148d2e7c8f", "type": "account.created", "data": { "account": { "accountID": "b6d8cc28a443ef03c1d45a3cdcd7dec4237ec1a8" } }, "createdOn": "2026-03-10T03:07:19Z" } ``` | Key | Type | Description | |-------------|-----------|---------------------------------------------| | `type` | string | Description of the event | | `data` | string | Data associated with the event | | `eventID` | string | Unique identifier for the event object | | `createdOn` | timestamp | Timestamp for when event object was created | ## [Event types](#event-types) Here are the event types that we capture and send. This may not be a comprehensive list as we are continuing to add events to our system. | Event identifier | Description | |-----------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------| | `account.created` | A new account was created in Moov | | `account.updated` | One of the fields for an existing Moov account was updated | | `account.deleted` | An account was deleted | | `representative.created` | A representative was added to an account | | `representative.updated` | A representative was updated | | `representative.deleted` | A representative was deleted | | `capability.requested` | A capability was requested for a Moov account | | `capability.updated` | A capability was updated for a Moov account | | `bankAccount.created` | A bank account was created for a Moov account | | `bankAccount.updated` | A bank account was updated for a Moov account | | `bankAccount.deleted` | A bank account was deleted for a Moov account | | `transfer.created` | A transfer was created to send money from one account to another | | `transfer.updated` | The status of a transfer is pending, completed, failed, or reversed. Granular rail-specific updates on the source and destination also trigger this event. | | `walletTransaction.updated` | A wallet transaction's status has been changed to pending, completed, canceled, or failed | | `dispute.created` | A dispute has been created for a particular transfer. | | `paymentMethod.enabled` | A payment method for account has been enabled | | `paymentMethod.disabled` | A payment method for account has been disabled | | `balance.updated` | The balance of a Moov wallet has been updated | | `cancellation.created` | A cancellation has been created | | `cancellation.updated` | A cancellation's status has changed to pending, completed, or failed | | `refund.created` | A card payment refund has been created | | `refund.updated` | A card payment refund's status has changed to pending, completed, or failed | | `networkID.updated` | The network ID of a merchant with an issued card has been updated | ### [HTTP Delivery headers](#http-delivery-headers) Once a webhook event is sent to your endpoint, you will receive a delivery via HTTP `POST` with some unique headers. These headers are important for verifying that Moov (vs. a third party) sent the payload. For more information on verifying webhooks, see our guide on checking [webhook signatures](/guides/webhooks/check-webhook-signatures/). Here are the unique headers you can expect to see in a webhook event delivery. | Header Name | Description | |----------------|------------------------------------------------------------------------------| | `X-Signature` | Cryptographically generated hash to be checked against for security purposes | | `X-Timestamp` | Timestamp of the event delivery | | `X-Nonce` | One time use number for webhook signature verification | | `X-Webhook-ID` | Unique identifier for the delivery | ## [Event schemas](#event-schemas) Here are sample event payloads for the webhooks we currently support. ### [Accounts](#accounts) #### [`account.created`, `account.updated`, `account.deleted`](#accountcreated-accountupdated-accountdeleted) Events for when a new account was created, updated, or deleted in Moov. [account.created](#tab-719582436-4-0) [account.updated](#tab-719582436-4-1) [account.deleted](#tab-719582436-4-2) ```json { "eventID": "14980a04-2e32-4921-a771-4959a36534a6", "type": "account.created", "data": { "accountID": "51015d0d-8dca-49a0-ba70-abfed073f785", "foreignID": "4528aba-b9a1-11eb-8529-0242ac13003" }, "createdOn": "2026-09-02T13:57:50Z" } ``` ```json { "eventID": "14980a04-2e32-4921-a771-4959a36534a6", "type": "account.updated", "data": { "accountID": "51015d0d-8dca-49a0-ba70-abfed073f785", "foreignID": "4528aba-b9a1-11eb-8529-0242ac13003" }, "createdOn": "2026-09-02T13:57:50Z" } ``` ```json { "eventID": "14980a04-2e32-4921-a771-4959a36534a6", "type": "account.deleted", "data": { "accountID": "51015d0d-8dca-49a0-ba70-abfed073f785", "foreignID": "4528aba-b9a1-11eb-8529-0242ac13003" }, "createdOn": "2026-09-02T13:57:50Z" } ``` ### [Balance](#balance) #### [`balance.updated`](#balanceupdated) Event for when the balance of a Moov wallet has been updated. ```json { "eventID": "14980a04-2e32-4921-a771-4959a36534a6", "type": "balance.updated", "data": { "accountID": "51015d0d-8dca-49a0-ba70-abfed073f785", "walletID": "51015d0d-8dca-49a0-ba70-abfed073f785" }, "createdOn": "2026-09-02T13:57:50Z" } ``` ### [Bank accounts](#bank-accounts) #### [`bankAccount.created`, `bankAccount.deleted`, `bankAccount.updated`](#bankaccountcreated-bankaccountdeleted-bankaccountupdated) Events for when a bank account has been created, deleted, or updated in Moov. [bankAccount.created](#tab-372419586-5-0) [bankAccount.deleted](#tab-372419586-5-1) [bankAccount.updated](#tab-372419586-5-2) ```json { "eventID": "14980a04-2e32-4921-a771-4959a36534a6", "type": "bankAccount.created", "data": { "bankAccountID": "51015d0d-8dca-49a0-ba70-abfed073f785", "accountID": "51015d0d-8dca-49a0-ba70-abfed073f785", "status": "new" }, "createdOn": "2026-09-02T13:57:50Z" } ``` ```json { "eventID": "14980a04-2e32-4921-a771-4959a36534a6", "type": "bankAccount.deleted", "data": { "bankAccountID": "51015d0d-8dca-49a0-ba70-abfed073f785", "accountID": "51015d0d-8dca-49a0-ba70-abfed073f785", "status": "verificationFailed" }, "createdOn": "2026-09-02T13:57:50Z" } ``` ```json { "eventID": "14980a04-2e32-4921-a771-4959a36534a6", "type": "bankAccount.updated", "data": { "bankAccountID": "51015d0d-8dca-49a0-ba70-abfed073f785", "accountID": "51015d0d-8dca-49a0-ba70-abfed073f785", "status": "pending" }, "createdOn": "2026-09-02T13:57:50Z" } ``` The status of the bank account related events can be `new`, `verified`, `verificationFailed`, `pending`, `errored`. ### [Billing](#billing) #### [`billingStatement.created`](#billingstatementcreated) Event for when a merchant billing statement is available for download. ```json { "eventID": "14980a04-2e32-4921-a771-4959a36534a6", "type": "billingStatement.created", "data": { "statementID": "9d45acbf-c4fe-4843-846c-eaa43c9ca17f", "accountID": "51015d0d-8dca-49a0-ba70-abfed073f785" }, "createdOn": "2026-09-02T13:57:50Z" } ``` ### [Cancellations](#cancellations) #### [`cancellation.created`, `cancellation.updated`](#cancellationcreated-cancellationupdated) Events for when a cancellation has been be created or the status of a cancellation has changed. [cancellation.created](#tab-145698372-7-0) [cancellation.updated](#tab-145698372-7-1) ```json { "eventID": "14980a04-2e32-4921-a771-4959a36534a6", "type": "cancellation.created", "data": { "transferID": "51015d0d-8dca-49a0-ba70-abfed073f785", "cancellationID": "51015d0d-8dca-49a0-ba70-abfed073f785", "status": "pending" }, "createdOn": "2026-09-02T13:57:50Z" } ``` ```json { "eventID": "14980a04-2e32-4921-a771-4959a36534a6", "type": "cancellation.updated", "data": { "transferID": "51015d0d-8dca-49a0-ba70-abfed073f785", "cancellationID": "51015d0d-8dca-49a0-ba70-abfed073f785", "status": "completed" }, "createdOn": "2026-09-02T13:57:50Z" } ``` ### [Capabilities](#capabilities) #### [`capability.requested` and `capability.updated`](#capabilityrequested-and-capabilityupdated) Event for when a [capability](/guides/accounts/capabilities/) was requested or updated for a Moov account. [capability.requested](#tab-149527386-8-0) [capability.updated](#tab-149527386-8-1) ```json { "eventID": "14980a04-2e32-4921-a771-4959a36534a6", "type": "capability.requested", "data": { "capabilityID": "transfers", "accountID": "51015d0d-8dca-49a0-ba70-abfed073f785", "foreignID": "4528aba-b9a1-11eb-8529-0242ac13003" }, "createdOn": "2026-09-02T13:57:50Z" } ``` ```json { "eventID": "14980a04-2e32-4921-a771-4959a36534a6", "type": "capability.updated", "data": { "capabilityID": "transfers", "accountID": "51015d0d-8dca-49a0-ba70-abfed073f785", "foreignID": "4528aba-b9a1-11eb-8529-0242ac13003", "status": "enabled" }, "createdOn": "2026-09-02T13:57:50Z" } ``` The status of capability related events can be `enabled`, `disabled`, or `pending`. ### [Card acceptance](#card-acceptance) #### [`card.autoUpdated`](#cardautoupdated) You can receive notifications when any of the following details of a linked card are automatically updated through the [card account updater](/guides/sources/cards/card-account-updater/): | Update type | Description | |----------------------|---------------------------------------------------------------------------| | `number-update` | A new account number has been provided | | `expiration-update` | A new expiration date has been provided | | `contact-cardholder` | A match was found, but the account information on file may not be current | | `account-closed` | The account is closed (possibly due to permanent closure or fraud ) | ```json { "eventID": "14980a04-2e32-4921-a771-4959a36534a6", "type": "card.autoUpdated", "data": { "cardID": "51015d0d-8dca-49a0-ba70-abfed073f785", "accountID": "51015d0d-8dca-49a0-ba70-abfed073f785", "updateType": "number-update" }, "createdOn": "2026-09-02T13:57:50Z" } ``` ### [Card issuing (beta)](#card-issuing-beta) #### [`networkID.updated`](#networkidupdated) External identifier that's used to identify the merchant with the card brand has been updated. ```json { "eventID": "14980a04-2e32-4921-a771-4959a36534a6", "type": "networkID.updated", "data": { "accountID": "51015d0d-8dca-49a0-ba70-abfed073f785", "visaMid": "S123456789", "updatedOn": "2026-10-02T15:06:40Z" }, "createdOn": "2026-09-02T13:57:50Z" } ``` ### [Disputes](#disputes) #### [`dispute.created` and `dispute.updated`](#disputecreated-and-disputeupdated) You can receive notifications on disputes through the `dispute.created` and `dispute.updated` webhook events. Subscribing to these events will let you know the dispute was created, updated, and completed. The `dispute.updated` webhook will generate if there is a change to `status` or `phase`. Note that even if a transfer has a dispute, its overall transfer status will remain `completed`. [dispute.created](#tab-248315967-10-0) [dispute.updated](#tab-248315967-10-1) ```json { "eventID": "14980a04-2e32-4921-a771-4959a36534a6", "type": "dispute.created", "data": { "accountID": "51015d0d-8dca-49a0-ba70-abfed073f785", "transferID": "51015d0d-8dca-49a0-ba70-abfed073f785", "disputeID": "51015d0d-8dca-49a0-ba70-abfed073f785", "status": "created" }, "createdOn": "2026-09-02T13:57:50Z" } ``` ```json { "eventID": "14980a04-2e32-4921-a771-4959a36534a6", "type": "dispute.updated", "data": { "accountID": "51015d0d-8dca-49a0-ba70-abfed073f785", "transferID": "51015d0d-8dca-49a0-ba70-abfed073f785", "disputeID": "51015d0d-8dca-49a0-ba70-abfed073f785", "status": "response-needed", "phase": "chargeback" }, "createdOn": "2026-09-02T13:57:50Z" } ``` ### [Invoices](#invoices) #### [`invoice.created` and `invoice.updated`](#invoicecreated-and-invoiceupdated) Events for when an invoice has been created or updated. [invoice.created](#tab-736159824-11-0) [invoice.updated](#tab-736159824-11-1) ```json { "eventID": "14980a04-2e32-4921-a771-4959a36534a6", "type": "invoice.created", "data": { "accountID": "51015d0d-8dca-49a0-ba70-abfed073f785", "invoiceID": "51015d0d-8dca-49a0-ba70-abfed073f785", "status": "draft" //unpaid, payment-pending, paid, overdue, canceled }, "createdOn": "2026-09-02T13:57:50Z" } ``` ```json { "eventID": "14980a04-2e32-4921-a771-4959a36534a6", "type": "invoice.updated", "data": { "accountID": "51015d0d-8dca-49a0-ba70-abfed073f785", "invoiceID": "51015d0d-8dca-49a0-ba70-abfed073f785", "status": "unpaid", //draft, payment-pending, paid, overdue, canceled }, "createdOn": "2026-09-02T13:57:50Z" } ``` ### [Payment methods](#payment-methods) #### [`paymentMethod.enabled` and `paymentMethod.disabled`](#paymentmethodenabled-and-paymentmethoddisabled) Events for when a [payment method](/guides/money-movement/payment-methods/) for a Moov account has been enabled or disabled. [paymentMethod.enabled](#tab-681794253-12-0) [paymentMethod.disabled](#tab-681794253-12-1) ```json { "eventID": "14980a04-2e32-4921-a771-4959a36534a6", "type": "paymentMethod.enabled", "data": { "paymentMethodID": "51015d0d-8dca-49a0-ba70-abfed073f785", "accountID": "51015d0d-8dca-49a0-ba70-abfed073f785", "sourceID": "51015d0d-8dca-49a0-ba70-abfed073f785" }, "createdOn": "2026-09-02T13:57:50Z" } ``` ```json { "eventID": "14980a04-2e32-4921-a771-4959a36534a6", "type": "paymentMethod.disabled", "data": { "paymentMethodID": "51015d0d-8dca-49a0-ba70-abfed073f785", "accountID": "51015d0d-8dca-49a0-ba70-abfed073f785", "sourceID": "51015d0d-8dca-49a0-ba70-abfed073f785" }, "createdOn": "2026-09-02T13:57:50Z" } ``` ### [Refunds](#refunds) #### [`refund.created`, `refund.updated`](#refundcreated-refundupdated) Events for when a refund has been be created or the status of a refund has changed. [refund.created](#tab-783615942-13-0) [refund.updated](#tab-783615942-13-1) ```json { "eventID": "14980a04-2e32-4921-a771-4959a36534a6", "type": "refund.created", "data": { "accountID": "51015d0d-8dca-49a0-ba70-abfed073f785", "transferID": "51015d0d-8dca-49a0-ba70-abfed073f785", "refundID": "51015d0d-8dca-49a0-ba70-abfed073f785", "status": "created" }, "createdOn": "2026-09-02T13:57:50Z" } ``` ```json { "eventID": "14980a04-2e32-4921-a771-4959a36534a6", "type": "refund.updated", "data": { "accountID": "51015d0d-8dca-49a0-ba70-abfed073f785", "transferID": "51015d0d-8dca-49a0-ba70-abfed073f785", "refundID": "51015d0d-8dca-49a0-ba70-abfed073f785", "status": "completed" }, "createdOn": "2026-09-02T13:57:50Z" } ``` ### [Representatives](#representatives) #### [`representative.created`, `representative.updated`, `representative.disabled`](#representativecreated-representativeupdated-representativedisabled) Events for when a business representative gets created, updated, or disabled for a Moov account. [representative.created](#tab-162597384-14-0) [representative.updated](#tab-162597384-14-1) [representative.disabled](#tab-162597384-14-2) ```json { "eventID": "14980a04-2e32-4921-a771-4959a36534a6", "type": "representative.created", "data": { "representativeID": "51015d0d-8dca-49a0-ba70-abfed073f785", "accountID": "51015d0d-8dca-49a0-ba70-abfed073f785" }, "createdOn": "2026-09-02T13:57:50Z" } ``` ```json { "eventID": "14980a04-2e32-4921-a771-4959a36534a6", "type": "representative.updated", "data": { "representativeID": "51015d0d-8dca-49a0-ba70-abfed073f785", "accountID": "51015d0d-8dca-49a0-ba70-abfed073f785" }, "createdOn": "2026-09-02T13:57:50Z" } ``` ```json { "eventID": "14980a04-2e32-4921-a771-4959a36534a6", "type": "representative.disabled", "data": { "representativeID": "51015d0d-8dca-49a0-ba70-abfed073f785", "accountID": "51015d0d-8dca-49a0-ba70-abfed073f785" }, "createdOn": "2026-09-02T13:57:50Z" } ``` ### [Transfers](#transfers) #### [`transfer.created`, `transfer.updated`](#transfercreated-transferupdated) Events for when a transfer is created or updated in Moov. As a transfer progresses through its lifecycle, Moov will send events on both the overall transfer as well as the granular, rail-specific updates to keep you informed every step of the way. The `transfer.created` event confirms a transfer has been created in the Moov system. The `transfer.updated` event means the transfer’s status has changed to one of the following: - `queued` - `pending` - `completed` - `canceled` - `failed` - `reversed` Rail-specific updates on the source and destination also trigger the `transfer.updated` event. [transfer.created](#tab-524879316-15-0) [transfer.updated](#tab-524879316-15-1) ```json { "eventID": "14980a04-2e32-4921-a771-4959a36534a6", "type": "transfer.created", "data": { "accountID": "51015d0d-8dca-49a0-ba70-abfed073f785", "transferID": "51015d0d-8dca-49a0-ba70-abfed073f785", "status": "created" }, "createdOn": "2026-09-02T13:57:50Z" } ``` ```json { "eventID": "14980a04-2e32-4921-a771-4959a36534a6", "type": "transfer.updated", "data": { "accountID": "51015d0d-8dca-49a0-ba70-abfed073f785", "transferID": "51015d0d-8dca-49a0-ba70-abfed073f785", "status": "pending", "source": { "accountID": "51015d0d-8dca-49a0-ba70-abfed073f785", "paymentMethodID":"51015d0d-8dca-49a0-ba70-abfed073f785" }, "destination": { "accountID": "51015d0d-8dca-49a0-ba70-abfed073f785", "paymentMethodID": "51015d0d-8dca-49a0-ba70-abfed073f785" } }, "createdOn": "2026-09-02T13:57:50Z" } ``` The accountID is the ID for the account facilitating the transfer. #### [Rail-specific transfer statuses](#rail-specific-transfer-statuses) Transfer statuses are specific to different rails, so you have insight into what stage money movement is in. The `transfer.updated` event will be sent each time we receive an update from the rail networks. Rail specific statuses are also available under the source and destination. See statuses by rail below: [Card statuses](#tab-465381927-17-0) [ACH statuses](#tab-465381927-17-1) [Wallet statuses](#tab-465381927-17-2) | Status | Description | |--------------------|-----------------------------------------------------------------------------------------------------| | `source.initiated` | The card transfer was successfully started | | `source.confirmed` | The payment request was approved by the cardholder’s bank and the funds are eligible for settlement | | `source.settled` | Funds have settled and are in the disbursement process | | `source.completed` | Funds have been credited to the destination and are available for use | | `source.canceled` | The transfer has been canceled and authorization has been reversed | | `source.failed` | The payment has failed due to a decline or network error | | Status | Description | |--------------------------|----------------------------------------------------------------------------------------------------------------------------------------| | `source.initiated` | The ACH transfer from the source into Moov's system has been created | | `source.originated` | Payment instructions about the source transfer have been sent to Moov's originating depository financial institution (ODFI) partner | | `source.corrected` | The source transfer completed but a notification of change was received | | `source.completed` | Funds are available in Moov and ready to flow out to the destination | | `source.returned` | The payment was returned by Moov to the source financial institution | | `destination.initiated` | The ACH transfer from Moov to the destination bank account has been created | | `destination.originated` | Payment instructions about the destination transfer have been sent to Moov's receiving depository financial institution (ODFI) partner | | `destination.corrected` | Transfer to the destination completed but a notification of change was received | | `destination.returned` | The transfer was returned by the receiving financial institution | | Status | Description | |-------------------------|----------------------------------------------------------------------------| | `source.completed` | The transfer from the source wallet has successfully completed | | `destination.completed` | The transfer is complete and funds are available in the destination wallet | ### [Wallet transactions](#wallet-transactions) #### [`sweep.created`, `sweep.updated`, `walletTransaction.updated`](#sweepcreated-sweepupdated-wallettransactionupdated) Events for when a sweep has been created or updated, as well as events for when a wallet transaction is pending or has recently completed. [sweep.created](#tab-983157642-18-0) [sweep.updated](#tab-983157642-18-1) ```json { "eventID": "14980a04-2e32-4921-a771-4959a36534a6", "type": "sweep.created", "data": { "sweepID": "51015d0d-8dca-49a0-ba70-abfed073f785", "walletID": "51015d0d-8dca-49a0-ba70-abfed073f785", }, "createdOn": "2026-09-02T13:57:50Z" } ``` ```json { "eventID": "14980a04-2e32-4921-a771-4959a36534a6", "type": "sweep.updated", "data": { "sweepID": "51015d0d-8dca-49a0-ba70-abfed073f785", "walletID": "50f31cfa-6e41-412b-9935-655e58127583", "status": "failed", "transferID" : "0a958eb7-4384-41d6-8bd9-ba1cf9e2f5d2" }, "createdOn": "2026-09-02T13:57:50Z" } ``` [walletTransaction.updated (pending)](#tab-162843579-19-0) [walletTransaction.updated (completed)](#tab-162843579-19-1) ```json { "eventID": "14980a04-2e32-4921-a771-4959a36534a6", "type": "walletTransaction.updated", "data": { "accountID": "51015d0d-8dca-49a0-ba70-abfed073f785", //account that owns the wallet "walletID": "51015d0d-8dca-49a0-ba70-abfed073f785", "transactionID": "51015d0d-8dca-49a0-ba70-abfed073f785", "status": "pending" }, "createdOn": "2026-09-02T13:57:50.762679289Z" } ``` ```json { "eventID": "14980a04-2e32-4921-a771-4959a36534a6", "type": "walletTransaction.updated", "data": { "accountID": "51015d0d-8dca-49a0-ba70-abfed073f785", //account that owns the wallet "walletID": "51015d0d-8dca-49a0-ba70-abfed073f785", "transactionID": "51015d0d-8dca-49a0-ba70-abfed073f785", "status": "completed", "availableBalance": { "currency": "USD", "value": 1204, "valueDecimal": "12.04632" }, }, "createdOn": "2026-09-02T13:57:50.762679289Z" } ``` --- URL: https://docs.moov.io/ips/ --- # IP addresses Moov maintains a range of IP address used to deliver services. While Moov does not necessarily recommend using the listed IP addresses for firewall rules, some organizations require such rules. Moov will strive to update partners and customers when changes to this page are made. The IP ranges listed on this page can be used to configure firewall rules or set up network access controls. These ranges are used by Moov's webhook infrastructure and other services. ## [IPv4 addresses](#ipv4-addresses) The following IPv4 address ranges are used by Moov's services: - `34.33.1.192/28` - `8.34.212.4/30` - `34.133.111.85/32` - `34.71.106.155/32` - `35.222.244.20/32` - `34.122.155.236/32` ## [Update history](#update-history) ### [September 19, 2025](#september-19-2025) - Initial publication ### [March 18, 2026](#march-18-2026) - Added testing/certification ranges * * * ## [Additional resources](#additional-resources) - [Webhooks](/guides/webhooks/check-webhook-signatures/) - [API Authentication](/api/authentication/) - [Dashboard settings](/guides/dashboard/settings/) --- URL: https://docs.moov.io/moovjs/accounts/accounts/ --- # Account Accounts represent a legal entity (either a business or an individual) in Moov. You can create an account for yourself or set up accounts for others. You can retrieve an account to get details on the business or individual account holder, such as an email address or employer identification number (EIN). You can also look at the account object to see what capabilities that account has. ## [Create account](#create-account) You can create accounts for your users by passing the required information to Moov. Note, [capabilities](/guides/accounts/capabilities/) can be requested during account creation, or you can [request](/moovjs/accounts/capabilities/) capabilities as needed later on. To create an account, you'll need to specify the `/accounts.write` scope when generating a token. #### [Parameters](#parameters) | Name | Type | |-----------|------------------------------------------------| | `account` | [Account](/api/moov-accounts/accounts/create/) | ```javascript const updatedAccount = { "accountType": "business", "profile": { "business": { "legalBusinessName": "ClassBooker", "businessType": "llc", } } }; moov.accounts.update(updatedAccount); ``` ## [Get account](#get-account) Retrieves details for the account with the specified ID. To retrieve an account, you'll need to specify the `/accounts/{accountID}/profile.read` scope when generating a token. #### [Parameters](#parameters-1) | Name | Type | |-------------|--------| | `accountID` | string | ```javascript moov.accounts.get({accountID}); ``` ## [Update account](#update-account) If an account's details have changed, you can update the information associated with a specific account ID. To update an account, you'll need to specify the `/accounts/{accountID}/profile.write` scope when generating a token. #### [Parameters](#parameters-2) | Name | Type | |-------------|-----------------------------------------------| | `accountID` | string | | `account` | [account](/api/moov-accounts/accounts/patch/) | ## [Platform terms of service agreement](#platform-terms-of-service-agreement) Each account using the `wallet.balance`, `card-issuing` (beta), or at least one `send-funds`, or `collect-funds` capabilities must agree to Moov's terms of service before a transfer can be created with that account. In your application, you must display a link to the [Moov platform agreement](https://moov.io/legal/platform-agreement/), and the terms must be accepted by the user. To accept the platform agreement terms of service via Moov.js, you can pass the `accountID` into the following method. This will generate a terms of service token and update the account in one step. | Name | Type | |-------------|--------| | `accountID` | string | ```javascript moov.accounts.acceptTermsOfService({ accountID: "..." } ); ``` If you need to generate a terms of service token to pass to the Moov API, you can call the following method. ```javascript moov.accounts.getTermsOfServiceToken(); ``` If needed, you can manually enter the terms of service information via Moov's API with the accounts `POST` [endpoint](/api/moov-accounts/accounts/create/) when creating an account, or with the accounts `PATCH` [endpoint](/api/moov-accounts/accounts/patch/) when updating an account. Check out out our pre-built [terms of service](/moovjs/drops/terms-of-service/) Drop. With the pre-built user interface, you can integrate our privacy policy and terms of service while simultaneously generating a token that can be patched to the account. --- URL: https://docs.moov.io/moovjs/accounts/capabilities/ --- # Capabilities Capabilities determine what a Moov account can do. Each capability has specific information requirements, depending on risk and compliance standards associated with different account activities. For example, there are more information requirements for a business that wants to charge other accounts than for an individual who simply wants to receive funds. When you request a capability, we list the information requirements for that capability. Once you submit the required information, we need to verify the data. Because of this, a requested capability may not immediately become active. ## [Request capabilities](#request-capabilities) Request capabilities for a specific account. To request capabilities, you'll need to specify the `/accounts/{accountID}/capabilities.write` scope when generating a token. #### [Parameters](#parameters) | Name | Type | |----------------|-----------| | `accountID` | string | | `capabilities` | string\[] | ```javascript const accountID = "accountID"; const capabilities = ["transfers", "send-funds.ach", "collect-funds.ach", "wallet.balance"]; moov.accounts.capabilities.request({accountID, capabilities}); ``` ## [Get capability for account](#get-capability-for-account) Retrieve a specific capability that an account has requested. To get capabilities, you'll need to specify the `/accounts/{accountID}/capabilities.read` scope when generating a token. #### [Parameters](#parameters-1) | Name | Type | |----------------|--------| | `accountID` | string | | `capabilityID` | string | ```javascript const accountID = "accountID"; const capabilityID = capabilityID; moov.accounts.capabilities.get({accountID, capabilityID}); ``` ## [List capabilities for account](#list-capabilities-for-account) Retrieve all the capabilities an account has requested. To get capabilities, you'll need to specify the `/accounts/{accountID}/capabilities.read` scope when generating a token. #### [Parameters](#parameters-2) | Name | Type | |-------------|--------| | `accountID` | string | ```javascript const accountID = "accountID"; moov.accounts.capabilities.list({accountID}); ``` --- URL: https://docs.moov.io/moovjs/accounts/files/ --- # Files Files can be used for a multitude of different use cases including but not limited to, individual identity verification and business underwriting. You may need to provide documentation to enable capabilities or to keep capabilities enabled for an account. The maximum file size is 20 MB. Each account is allowed a maximum of 50 files. Acceptable file types include CSV, JPG, PDF, and PNG. [API reference](/api/moov-accounts/files/post/) ## [Upload file](#upload-file) Uploads a file related to a specific account. To upload files, you'll need to specify the `/accounts/{accountID}/files.write` scope when generating a token. #### [Parameters](#parameters) | Name | Type | |---------------|-------------------------------------------------------------------------------------------------------------------------------------------------------| | `accountID` | string | | `file` | binary | | `filePurpose` | `identity_verification` `individual_verification` `representative_verification` `business_verification` `merchant_underwriting` `account_requirement` | | `metadata` | JSON string `keys :` `representative_id` `requirement_id` `error_code` `comment` | ```javascript moov.accounts.files.upload({accountID, file, filePurpose}); ``` ## [List files for account](#list-files-for-account) Retrieve all the files associated with an account. To list files, you'll need to specify the `/accounts/{accountID}/files.read` scope when generating a token. #### [Parameters](#parameters-1) | Name Type | | |-------------|--------| | `accountID` | string | ```javascript moov.accounts.files.list({accountID}); ``` ## [Get details about a file](#get-details-about-a-file) Retrieve file details associated with a specific Moov account. To retrieve file details, you'll need to specify the `/accounts/{accountID}/files.read` scope when generating a token. #### [Parameters](#parameters-2) | Name | Type | |-------------|--------| | `accountID` | string | | `fileID` | string | ```javascript moov.accounts.files.get({accountID, fileID}); ``` --- URL: https://docs.moov.io/moovjs/accounts/ --- # Moov accounts Create and manage Moov accounts without directly handling sensitive data. Using Moov.js, account data is passed directly from your end user to Moov, saving you from the compliance burdens. View the pages in this section for more information. --- URL: https://docs.moov.io/moovjs/accounts/representatives/ --- # Representatives ## [Create representative](#create-representative) Moov accounts associated with businesses require information regarding individuals who represent the business. You can provide this information by creating a representative. To create a representative, you'll need to specify the `/accounts/{accountID}/representatives.write` scope when generating a token. #### [Parameters](#parameters) | Name | Type | |------------------|--------------------------------------------------------------| | `accountID` | string | | `representative` | [Representative](/api/moov-accounts/representatives/create/) | ```javascript const accountID = "accountID"; const representative = { "name": { "firstName": "Amanda", "lastName": "Yang", "suffix": "Jr" }, "phone": { "number": "8185551212", "countryCode": "1" }, "email": "amanda@classbooker.dev", "address": { "addressLine1": "123 Main Street", "addressLine2": "Apt 302", "city": "Boulder", "stateOrProvince": "Colorado", "postalCode": "80301", "country": "US" }, "birthDate": { "day": 10, "month": 11, "year": 1989 }, "governmentID": { "ssn": { "full": "111111111", "lastFour": "1111" }, "itin": { "full": "111111111", "lastFour": "1111" } }, "responsibilities": { "isController": false, "isOwner": true, "ownershipPercentage": 38, "jobTitle": "CEO" } }; moov.accounts.representatives.create({accountID, representative}); ``` ## [List representatives](#list-representatives) A Moov account may have multiple representatives depending on the associated business's ownership and management structure. You can use this method to list all the representatives for a given Moov account. Note that Moov accounts associated with an individual do not have representatives. To list representatives, you'll need to specify the `/accounts/{accountID}/representatives.read` scope when generating a token. #### [Parameters](#parameters-1) | Name | Type | |-------------|--------| | `accountID` | string | ```javascript moov.accounts.representatives.list({accountID}); ``` ## [Get representative](#get-representative) Retrieve a specific representative associated with a given Moov account. To get representatives, you'll need to specify the `/accounts/{accountID}/representatives.read` scope when generating a token. #### [Parameters](#parameters-2) | Name | Type | |--------------------|--------| | `accountID` | string | | `representativeID` | string | ```javascript moov.accounts.representatives.list({accountID, representativeID}); ``` ## [Delete representative](#delete-representative) Deletes a business representative associated with a Moov account. To delete a representative, you'll need to specify the `/accounts/{accountID}/representatives.write` scope when generating a token. #### [Parameters](#parameters-3) | Name | Type | |--------------------|--------| | `accountID` | string | | `representativeID` | string | ```javascript moov.accounts.representatives.delete({accountID, representativeID}); ``` ## [Update representative](#update-representative) If a representative's information has changed and you need to update it, you can use this method to change any of the fields associated with that particular representative. To update a representative, you'll need to specify the `/accounts/{accountID}/representatives.write` scope when generating a token. #### [Parameters](#parameters-4) | Name | Type | |------------------|--------------------------------------------------------------| | `accountID` | string | | `representative` | [Representative](/api/moov-accounts/representatives/create/) | ```javascript const accountID = "accountID"; const representative = { "name": { "firstName": "Amanda", "lastName": "Yang", "suffix": "Jr" }, "phone": { "number": "8185551212", "countryCode": "1" }, "email": "amanda@classbooker.dev", "address": { "addressLine1": "123 Main Street", "addressLine2": "Apt 302", "city": "Boulder", "stateOrProvince": "Colorado", "postalCode": "80301", "country": "US" }, "birthDate": { "day": 10, "month": 11, "year": 1989 }, "governmentID": { "ssn": { "full": "111111111", "lastFour": "1111" }, "itin": { "full": "111111111", "lastFour": "1111" } }, "responsibilities": { "isController": false, "isOwner": true, "ownershipPercentage": 38, "jobTitle": "CEO" } }; moov.accounts.representatives.update({accountID, representative}); ``` --- URL: https://docs.moov.io/moovjs/accounts/underwriting/ --- # Underwriting Underwriting is a tool Moov uses to understand a business’s profile before allowing them to collect funds on our platform. Through underwriting, you can retrieve or update information about the business's transaction volume. [API reference](/api/moov-accounts/underwriting/) ## [Retrieve underwriting details](#retrieve-underwriting-details) Retrieve underwriting associated with a given Moov account. To retrieve underwriting details, you'll need to specify the `/accounts/{accountID}/profile.read` scope when generating a token. #### [Parameters](#parameters) | Name | Type | |-------------|--------| | `accountID` | string | ```javascript moov.accounts.underwriting.get({accountID}); ``` ## [Update underwriting details](#update-underwriting-details) Update the account's underwriting by passing new values for one or more of the fields. To update underwriting details, you'll need to specify the `/accounts/{accountID}/profile.write` scope when generating a token. #### [Parameters](#parameters-1) | Name | Type | |----------------|------------------------------------------------------| | `accountID` | string | | `underwriting` | [Underwriting](/api/moov-accounts/underwriting/put/) | ```javascript const underwriting = { averageTransactionSize: 500, maxTransactionSize: 1000, averageMonthlyTransactionVolume: 500000 }; moov.accounts.underwriting.update({accountID, underwriting}); ``` --- URL: https://docs.moov.io/moovjs/drops/card-link/ --- # Card link Moov Drop For most use cases, we recommend using [Composable Drops](/moovjs/drops/composable-drops/) instead of the card link Drop. The card link Drop enables Moov customers to register a user's credit card in the most secure and seamless way possible. With the `moov-card-link` element, credit card information is entered by the user and processed directly by Moov. The card link Drop interacts directly with the link a card `POST` [endpoint](/api/sources/cards/create/) using JWTs to securely send data between your end users browser and Moov. All information is captured by an iframe and hidden from the customer's website. ```html
``` [Drops 101 \ Learn the basics of properties, attributes, & initializing Drops.](/moovjs/drops/drops-101) [Composable Moov Drops \ For more control over the design and layout, check out how to compose Moov Drops.](/moovjs/drops/composable-drops) Moov Drops require a secure HTTPS connection. If you don't have a test environment with HTTPS enabled, we suggest setting up a hosting environment with ngrok, Netlify, or Vercel. ## [Properties](#properties) Properties can be accessed through JavaScript using a reference to the `moov-card-link` element. | Property | Type | Description | |---------------------|-----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `oauthToken` | String | Auth Token used for hitting the API. Token must include the `accounts/{accountID}/cards.write` scope. | | `accountID` | String | ID for the account you want to add cards to. | | `allowedCardBrands` | String\[] | An array of allowed card brands. If this field is not provided, all card brands will be accepted. Accepted values are `visa`, `mastercard`, `american-express`, `diners-club`, `discover`, `jcb`, `unionpay`, `maestro`, `mir`, `elo`, `hiper`, or `hipercard`. | | `holderName` | String | Optional value specifying the full name of the cardholder. | | `billingAddress` | Object | Optional value for the billing address of the card. Follows the format specified in the [link card schema](/api/sources/cards/create/). `postalCode` is required, `addressLine1` is highly recommended. Supplying a `postalCode` will update the zip input field accordingly. | | `cardOnFile` | Boolean | Optional. Indicates cardholder has authorized card to be stored for future payments. | | `merchantAccountID` | String | Optional. Moov account ID of the merchant or entity authorized to store the card. Defaults to your platform account ID if `cardOnFile` is set to true and no other account is provided. | | `validationEvent` | String | Controls the frequency of validation. Possible values are `submit`, `change`, `keydown`, or `none`. | | `inputStyle` | Object | CSS object to override styles within the iframe. CSS rule names should be camelCased. | | `onEnterKeyPress` | Function | Callback fired when the enter key is pressed inside the iframe. | | `onError` | Function | Callback fired when the submit fails or input is invalid. Provides `clientError` and `apiError` as arguments. | | `onValidated` | Function | Callback fired when input passes validation. | | `onSuccess` | Function | Callback fired when a card is registered successfully. Responds with a card which can be accessed in the function. See the link card [endpoint](/api/sources/cards/create/#response) response for more detail. | #### [How to set a property](#how-to-set-a-property) [validationEvent](#tab-371958264-6-0) [inputStyle](#tab-371958264-6-1) [onSuccess](#tab-371958264-6-2) [onError](#tab-371958264-6-3) ```js const cardInput = document.querySelector('moov-card-link'); cardInput.validationEvent = 'keydown'; ``` ```js const cardInput = document.querySelector('moov-card-link'); const styles = { fontSize: "18.4px", fontFamily: "-apple-system, system-ui, 'Avenir Next'", paddingTop: "1px", "--text-color-invalid": "#FFB300", }; cardInput.inputStyle = styles; ``` ```js const cardInput = document.querySelector('moov-card-link'); const successCallback = (card) => { // The card was successfully added } cardInput.onSuccess = successCallback; ``` ```js const cardInput = document.querySelector('moov-card-link'); const errorCallback = (clientError, apiError) => { // If there was an error adding the card, // clientError will provide a user-friendly error message if (clientError) { console.error(clientError); } // If there was an API error when adding the card, // apiError will provide a detailed error response if (apiError) { if (apiError.error) { // The Moov API returned a detailed, dev-friendly error message console.error("API error: ", apiError.error); } if (apiError.existingCardID) { // If the error was caused by a duplicate card, // The Moov API will return the existing card ID console.error("Existing card ID: ", apiError.existingCardID); } } } cardInput.onError = errorCallback; ``` ## [Methods](#methods) You can call the methods of `moov-card-link` to perform various actions. | Method | Description | Parameters | Returns | |-----------------|---------------------------------------------------------------|------------|---------| | `submit` | Attempts to register a new card using the current values. | None | None | | `clear` | Clears out all user input. | None | None | | `validate` | Triggers validation on the current values. | None | None | | `fetchValidity` | Runs validation asynchronously and resolves to true or false. | None | Promise | #### [How to call a method](#how-to-call-a-method) [submit](#tab-871534629-8-0) [validate](#tab-871534629-8-1) [fetchValidity](#tab-871534629-8-2) ```js const cardInput = document.querySelector('moov-card-link'); cardInput.submit(); // Use onSuccess and onError for the result ``` ```js const cardInput = document.querySelector('moov-card-link'); cardInput.validate(); // Use onValidated and onError for the result ``` ```js const cardInput = document.querySelector('moov-card-link'); const validityPromise = cardInput.fetchValidity(); validityPromise.then(isValid => { // Do something based on isValid }); ``` ## [Attributes](#attributes) String-type properties can be set via attributes on the HTML `` element. | Attribute | Description | |-----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `oauth-token` | Auth Token used for hitting the API. Token must include the `accounts/{accountID}/cards.write` scope. | | `account-id` | ID for the account you want to add cards to . | | `validation-event` | Controls the frequency of validation. Possible values are `submit`, `change`, `keydown`, or `none`. | | `merchant-account-id` | Moov account ID of the merchant or entity authorized to store the card. Defaults to your platform account ID if `cardOnFile` is set to true and no other account is provided. | ## [Scopes](#scopes) To link a card, your Moov API token must include the `accounts/{accountID}/cards.write` scope. ## [Theming](#theming) Read our [themes](/moovjs/drops/theming/) guide to learn how to re-style Moov Drops. To re-style the inner contents of the card link, use the `inputStyle` property. --- URL: https://docs.moov.io/moovjs/drops/composable-drops/card-number-input/ --- # Card number input Drop Include the Moov card number input Drop with the Moov form Drop to securely and seamlessly submit sensitive card numbers to Moov. Combine the `moov-card-number-input` with the `moov-form` to submit sensitive user data to Moov. With the `moov-card-number-input` element, information entered by the user is captured by iframes and hidden from the customer's website. Card number ```html
``` Moov Drops require a secure HTTPS connection. If you don't have a test environment with HTTPS enabled, we suggest setting up a hosting environment with ngrok, Netlify, or Vercel. ## [Properties](#properties) Properties can be accessed through JavaScript using a reference to the `moov-card-number-input` element. | Property | Type | Required | Description | |---------------------|-----------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `name` | String | **✓** | The name of the input. The input value is merged into the request body using this name. For example, the input name `expiration.month` would result in a request body of `{ expiration: { month: "inputValue" } }`. | | `formName` | String | **✓** | The name of the form to which this text input is registered. | | `allowedCardBrands` | String\[] | | An array of allowed card brands. If this field is not provided, all card brands will be accepted. Accepted values are `visa`, `mastercard`, `american-express`, `diners-club`, `discover`, `jcb`, `unionpay`, `maestro`, `mir`, `elo`, `hiper`, or `hipercard`. | | `disabled` | Boolean | | If `true`, this input is disabled, preventing user input. | | `required` | Boolean | | If `true`, this input is required for form submission. | | `readOnly` | Boolean | | If `true`, the input value cannot be edited by a user. | | `size` | Number | | Expected number of characters in this input. | | `inputStyle` | Object | | A record of camelCased CSS variables, passed to the input element within the iframe. For developer convenience, inheritable styles such as color, font-size, and font-family are applied automatically. | | `validationMessage` | String | | Read only. The human-readable message displayed to the user when this input is invalid. | | `validity` | Object | | Read only. A `ValidityState` object. Details whether or not the input is valid and which validations (if any) are passing. | | `willValidate` | Boolean | | Read only. Returns true if this input has any attached validators. | | `onInput` | Function | | Fired when the user changes the input value. No arguments. | | `onChange` | Function | | Fired when the user navigates away from the input. No arguments. | | `onFocus` | Function | | Fired when the user focuses the input. No arguments. | | `onBlur` | Function | | Fired when the input loses focus. No arguments. | | `onBrandChange` | Function | | Fired when the detected card brand changes. Passes the detected brand name as an argument. | | `onInvalid` | Function | | Fired when the input fails a validation check | | `onEnterKeyPress` | Function | | Fired when the user presses the enter key while focusing the input | | `onCheckValidity` | Function | | Fired after a validity check runs on the input. Passes `isValid` as an argument. | | `onReportValidity` | Function | | Fired after a validity report runs on the input. Passes `isValid` as an argument. | ### [How to set a property](#how-to-set-a-property) [name](#tab-879356412-4-0) [inputStyle](#tab-879356412-4-1) [onBrandChange](#tab-879356412-4-2) [onInvalid](#tab-879356412-4-3) ```javascript const input = document.querySelector('moov-card-number-input'); input.name = 'demoInput'; ``` ```javascript const input = document.querySelector('moov-card-number-input'); input.inputStyle = { fontSize: "14px", color: "blue", }; ``` ```javascript const input = document.querySelector('moov-card-number-input'); const brandChangeCallback = (brandName) => { // Detected card brand has changed console.log(brandName); }; input.onBrandChange = brandChangeCallback; ``` ```javascript const input = document.querySelector('moov-card-number-input'); const invalidCallback = () => { // The input failed validation console.error(input.validationMessage); }; input.onInvalid = invalidCallback; ``` ## [Methods](#methods) You can call the methods of `moov-card-number-input` to perform various actions. | Method | Description | Parameters | Returns | |---------------------|---------------------------------------------------------------------------------------------------------|---------------------------|---------| | `blur` | Removes focus from the input. | None | None | | `click` | Imitates a user click on the input. | None | None | | `focus` | Focuses the input. | None | None | | `select` | Selects the input. | None | None | | `setCustomValidity` | Overrides the `validityMessage` on the input. | `validityMessage`: String | None | | `checkValidity` | Runs a validity check on the input. | None | None | | `reportValidity` | Runs a validity check on the input and reports the result to the user through browser default behavior. | None | None | ### [How to call a method](#how-to-call-a-method) [focus](#tab-581693274-6-0) [validate](#tab-581693274-6-1) ```javascript const input = document.querySelector('moov-card-number-input'); input.focus(); ``` ```javascript const input = document.querySelector('moov-card-number-input'); input.checkValidity(); // Use onCheckValidity for the result ``` --- URL: https://docs.moov.io/moovjs/drops/composable-drops/card-security-code-input/ --- # Card security code input Drop Include the Moov security code input Drop with the Moov form Drop to securely and seamlessly submit sensitive card data to Moov. Combine the `moov-card-security-code-input` element with the `moov-form` to submit sensitive user data to Moov. With the`moov-card-security-code-input` element, information entered by the user is captured by iframes and hidden from the customer’s website. Using the `moov-card-security-code-input` with the `moov-card-number-input` will automatically adjust validation to meet the security code requirements for the detected card brand. CVV ```html
``` Moov Drops require a secure HTTPS connection. If you don't have a test environment with HTTPS enabled, we suggest setting up a hosting environment with ngrok, Netlify, or Vercel. ## [Properties](#properties) Properties can be accessed through JavaScript using a reference to the `moov-card-security-code-input` element. | Property | Type | Required | Description | |---------------------|----------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `name` | String | **✓** | The name of the input. The input value is merged into the request body using this name. For example, the input name `expiration.month` would result in a request body of `{ expiration: { month: "inputValue" } }`. | | `formName` | String | **✓** | The name of the form to which this text input is registered. | | `disabled` | Boolean | | If `true`, this input is disabled, preventing user input. | | `required` | Boolean | | If `true`, this input is required for form submission. | | `readOnly` | Boolean | | If `true`, the input value cannot be edited by a user. | | `size` | Number | | Expected number of characters in this input. | | `inputStyle` | Object | | A record of camelCased CSS variables, passed to the input element within the iframe. For developer convenience, inheritable styles such as color, font-size, and font-family are applied automatically. | | `validationMessage` | String | | Read only. The human-readable message displayed to the user when this input is invalid. | | `validity` | Object | | Read only. A `ValidityState` object. Details whether or not the input is valid and which validations (if any) are passing. | | `willValidate` | Boolean | | Read only. Returns true if this input has any attached validators. | | `onInput` | Function | | Fired when the user changes the input value. No arguments. | | `onChange` | Function | | Fired when the user navigates away from the input. No arguments. | | `onFocus` | Function | | Fired when the user focuses the input. No arguments. | | `onBlur` | Function | | Fired when the input loses focus. No arguments. | | `onInvalid` | Function | | Fired when the input fails a validation check. | | `onEnterKeyPress` | Function | | Fired when the user presses the enter key while focusing the input. | | `onCheckValidity` | Function | | Fired after a validity check runs on the input. Passes `isValid` as an argument. | | `onReportValidity` | Function | | Fired after a validity report runs on the input. Passes `isValid` as an argument. | ### [How to set a property](#how-to-set-a-property) [name](#tab-936548172-4-0) [inputStyle](#tab-936548172-4-1) [onBlur](#tab-936548172-4-2) [onInvalid](#tab-936548172-4-3) ```javascript const input = document.querySelector('moov-card-security-code-input'); input.name = 'demoInput'; ``` ```javascript const input = document.querySelector('moov-card-security-code-input'); input.inputStyle = { fontSize: "14px", color: "blue", }; ``` ```javascript const input = document.querySelector('moov-card-security-code-input'); const blurCallback = (brandName) => { // Input lost focus }; input.onBlur = blurCallback; ``` ```javascript const input = document.querySelector('moov-card-security-code-input'); const invalidCallback = () => { // The input failed validation console.error(input.validationMessage); }; input.onInvalid = invalidCallback; ``` ## [Methods](#methods) You can call the methods of `moov-card-security-code-input` to perform various actions. | Method | Description | Parameters | Returns | |---------------------|---------------------------------------------------------------------------------------------------------|---------------------------|---------| | `blur` | Removes focus from the input. | None | None | | `click` | Imitates a user click on the input. | None | None | | `focus` | Focuses the input. | None | None | | `select` | Selects the input. | None | None | | `setCustomValidity` | Overrides the `validityMessage` on the input. | `validityMessage`: String | None | | `checkValidity` | Runs a validity check on the input. | None | None | | `reportValidity` | Runs a validity check on the input and reports the result to the user through browser default behavior. | None | None | ### [How to call a method](#how-to-call-a-method) [focus](#tab-916783425-6-0) [validate](#tab-916783425-6-1) ```javascript const input = document.querySelector('moov-card-security-code-input'); input.focus(); ``` ```javascript const input = document.querySelector('moov-card-security-code-input'); input.checkValidity(); // Use onCheckValidity for the result ``` ## [Best practices](#best-practices) If you're using the `moov-security-code-input` Drop along with the `moov-card-number-input` Drop, update your label and character limit on the security code input by listening for changes to the detected brand. ```javascript const cardNumberInput = document.querySelector('moov-card-number-input'); const cvvInput = document.querySelector('moov-card-security-code-input'); const cvvLabel = document.getElementById('cvv-label'); // Selector for your label element cardNumberInput.onBrandChange = ((brand) => { if (brand) { let size = 3; let label = "CVV"; switch (brand) { case "mastercard": size = 3; label = "CVC"; break; case "discover": size = 3; label = "CID"; break; case "american-express": size = 4; label = "CID"; break; default: size = 3; label = "CVV"; } cvvInput.size = size; cvvLabel.innerText = label; } }); ``` --- URL: https://docs.moov.io/moovjs/drops/composable-drops/expiration-date-input/ --- # Expiration date input Drop Include the Moov expiration date input Drop with the Moov form Drop to securely and seamlessly submit sensitive card data to Moov. Combine the `moov-expiration-date-input` element with the `moov-form` to submit sensitive card data to Moov. With the `moov-expiration-date-input` element, information entered by the user is captured by iframes and hidden from the customer’s website. Expiration date ```html
``` Moov Drops require a secure HTTPS connection. If you don't have a test environment with HTTPS enabled, we suggest setting up a hosting environment with ngrok, Netlify, or Vercel. ## [Properties](#properties) Properties can be accessed through JavaScript using a reference to the `moov-expiration-date-input` element. | Property | Type | Required | Description | |---------------------|----------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `name` | String | **✓** | The name of the input. The input value is merged into the request body using this name. For example, the input name `name.first` would result in a request body of `{ name: { first: "inputValue" } }`. | | `formName` | String | **✓** | The name of the form to which this text input is registered. | | `disabled` | Boolean | | If `true`, this input is disabled, preventing user input. | | `required` | Boolean | | If `true`, this input is required for form submission. | | `readOnly` | Boolean | | If `true`, the input value cannot be edited by a user. | | `size` | Number | | Expected number of characters in this input. | | `inputStyle` | Object | | A record of camelCased CSS variables, passed to the input element within the iframe. For developer convenience, inheritable styles such as color, font-size, and font-family are applied automatically. | | `validationMessage` | String | | Read only. The human-readable message displayed to the user when this input is invalid. | | `validity` | Object | | Read only. A `ValidityState` object. Details whether or not the input is valid and which validations (if any) are passing. | | `willValidate` | Boolean | | Read only. Returns true if this input has any attached validators. | | `onInput` | Function | | Fired when the user changes the input value. No arguments. | | `onChange` | Function | | Fired when the user navigates away from the input. No arguments. | | `onFocus` | Function | | Fired when the user focuses the input. No arguments. | | `onBlur` | Function | | Fired when the input loses focus. No arguments. | | `onInvalid` | Function | | Fired when the input fails a validation check. | | `onEnterKeyPress` | Function | | Fired when the user presses the enter key while focusing the input. | | `onCheckValidity` | Function | | Fired after a validity check runs on the input. Passes `isValid` as an argument. | | `onReportValidity` | Function | | Fired after a validity report runs on the input. Passes `isValid` as an argument. | ### [How to set a property](#how-to-set-a-property) [name](#tab-351247698-4-0) [inputStyle](#tab-351247698-4-1) [onBlur](#tab-351247698-4-2) [onInvalid](#tab-351247698-4-3) ```javascript const input = document.querySelector('moov-expiration-date-input'); input.name = 'demoInput'; ``` ```javascript const input = document.querySelector('moov-expiration-date-input'); input.inputStyle = { fontSize: "14px", color: "blue", }; ``` ```javascript const input = document.querySelector('moov-expiration-date-input'); const blurCallback = (brandName) => { // Input lost focus }; input.onBlur = blurCallback; ``` ```javascript const input = document.querySelector('moov-expiration-date-input'); const invalidCallback = () => { // The input failed validation console.error(input.validationMessage); }; input.onInvalid = invalidCallback; ``` ## [Methods](#methods) You can call the methods of `moov-expiration-date-input` to perform various actions. | Method | Description | Parameters | Returns | |---------------------|---------------------------------------------------------------------------------------------------------|---------------------------|---------| | `blur` | Removes focus from the input. | None | None | | `click` | Imitates a user click on the input. | None | None | | `focus` | Focuses the input. | None | None | | `select` | Selects the input. | None | None | | `setCustomValidity` | Overrides the `validityMessage` on the input. | `validityMessage`: String | None | | `checkValidity` | Runs a validity check on the input. | None | None | | `reportValidity` | Runs a validity check on the input and reports the result to the user through browser default behavior. | None | None | ### [How to call a method](#how-to-call-a-method) [focus](#tab-843769251-6-0) [validate](#tab-843769251-6-1) ```javascript const input = document.querySelector('moov-expiration-date-input'); input.focus(); ``` ```javascript const input = document.querySelector('moov-expiration-date-input'); input.checkValidity(); // Use onCheckValidity for the result ``` --- URL: https://docs.moov.io/moovjs/drops/composable-drops/ --- # Composable Moov Drops Moov's composable Drop elements enable you to collect information by registering and configuring specific fields, and submitting those fields securely and seamlessly to Moov. The composable Drops are a collection of interconnected elements, including `moov-form`, `moov-text-input`, `moov-card-number-input`, and other fields. By combining these elements, your users can interact directly with the Moov API, keeping sensitive data away from your app and simplifying PCI compliance. Need to update a user's credit card information? Combine a `moov-form` with a `moov-card-number-input` and Moov takes care of the rest. Use the [Drops 101](/moovjs/drops/drops-101/) guide to learn the basics of properties, attributes, and initializing Drops. Name on card Card number Expiration CVV Zip ```HTML
``` Moov Drops require a secure HTTPS connection. If you don't have a test environment with HTTPS enabled, we suggest setting up a hosting environment with ngrok, Netlify, or Vercel. ### [Theming & styles](#theming--styles) The composable Drop inputs will automatically style themselves based on inheritable `` styles, such as font-size, color, and line-height. You can further customize the outer contents of an element by targeting the element's tag, such as `moov-text-input`, and applying additional styles. To re-style the inner contents of an element, use the `inputStyle` property. Note: Pseudo-selectors such as `:focus` and `:valid` don't work through iframes. Instead, use `:has(.focus)` to apply styles to these pseudo-classes. All [input pseudo-classes](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes#input_pseudo-classes) are supported. ```CSS moov-text-input:has(.focus) { border-color: var(--focus-color); } moov-text-input + .myErrorMessage { display: none; } moov-text-input:has(.user-invalid) + .myErrorMessage { display: block; color: red; } ``` ## [Properties](#properties) Properties for elements can be accessed through JavaScript using a reference to the specific form element. - View `moov-form` [properties](/moovjs/drops/composable-drops/moov-form/#properties) - View `moov-text-input` [properties](/moovjs/drops/composable-drops/text-input/#properties) - View `moov-card-number-input` [properties](/moovjs/drops/composable-drops/card-number-input/#properties) - View `moov-expiration-date-input` [properties](/moovjs/drops/composable-drops/expiration-date-input/#properties) - View `moov-card-security-code-input` [properties](/moovjs/drops/composable-drops/card-security-code-input/#properties) ### [Attributes](#attributes) Any string-type property can alternatively be set via attributes: - View `moov-form` [attributes](/moovjs/drops/composable-drops/moov-form/#attributes) - View `moov-text-input` [attributes](/moovjs/drops/composable-drops/text-input/#attributes) - View `moov-card-number-input` [attributes](/moovjs/drops/composable-drops/card-number-input/#attributes) - View `moov-expiration-date-input` [attributes](/moovjs/drops/composable-drops/expiration-date-input/#attributes) - View `moov-card-security-code-input` [attributes](/moovjs/drops/composable-drops/card-security-code-input/#attributes) --- URL: https://docs.moov.io/moovjs/drops/composable-drops/moov-form/ --- # Moov form Drop The Moov form Drop enables Moov customers to securely and seamlessly submit sensitive user data to Moov. With the `moov-form` element, information is entered by the user and processed directly by Moov. All information is captured by iframes and hidden from the customer's website. The `moov-form` coordinates user input across a collection of individual form elements, making it highly flexible and adaptable to your needs. Legal business name EIN Website ```html
``` The `moov-text-input` element updates a user's name, the `moov-card-number-input` element updates a user's card number, and the `moov-card-security-code-input` element updates the user's CVV. Moov Drops require a secure HTTPS connection. If you don't have a test environment with HTTPS enabled, we suggest setting up a hosting environment with ngrok, Netlify, or Vercel. ## [Properties](#properties) Properties can be accessed through JavaScript using a reference to the `moov-form` element. | Property | Type | Required | Description | |--------------------|----------|----------|----------------------------------------------------------------------------------------------------------------| | `name` | String | **✓** | The unique name of the form. | | `method` | String | **✓** | The HTTP method to use when submitting the form. `GET`, `POST`, `PATCH`, or `DELETE`. | | `action` | String | **✓** | The Moov API URL to use when submitting the form, such as `/accounts/{accountID}` | | `requestHeaders` | Object | | Headers passed with the request. Include your Moov API token in the `Authorization` header. | | `requestBody` | Object | | A default value for the request body. Input values will be merged into this object when the form is submitted. | | `elements` | Array | | Read-only. An array of the `moov-*-input` elements attached to this form. | | `length` | Number | | Read-only. The number of `moov-*-input` elements attached to this form. | | `onSuccess` | Function | | Fired after a successful form submission. Provides `response` as an argument. | | `onError` | Function | | Fired after an unsuccessful form submission. Provides `response` as an argument. | | `onCheckValidity` | Function | | Fired after a validity check runs on the form. Provides `isValid` as an argument. | | `onReportValidity` | Function | | Fired after the forms reports validity to the user. Provides `isValid` as an argument. | ### [How to set a property](#how-to-set-a-property) [name](#tab-693584271-4-0) [requestHeaders](#tab-693584271-4-1) [onSuccess](#tab-693584271-4-2) [onError](#tab-693584271-4-3) ```javascript const form = document.querySelector('moov-form'); form.name = 'demo-form'; ``` ```javascript const form = document.querySelector('moov-form'); form.method = "PUT"; form.requestHeaders = { "content-type": "application/json", "Authorization": "Bearer " + token, }; ``` ```javascript const form = document.querySelector('moov-form'); const successCallback = (response) => { // The form was submitted successfully response.json().then(console.log); }; form.onSuccess = successCallback; ``` ```javascript const form = document.querySelector('moov-form'); const errorCallback = (response) => { // There was an error submitting the form response.json().then(console.error); }; form.onError = errorCallback; ``` ## [Methods](#methods) You can call the methods of `moov-form` to perform various actions. | Method | Description | Parameters | Returns | |------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------|---------| | `checkValidity` | Updates the validation state for all form inputs, and returns an `isValid` boolean through the `onCheckValidity` callback function. | None | None | | `reportValidity` | Checks validity of the form, and alerts the user to invalid inputs using the browser's default behavior. Returns an `isValid` boolean through the `onReportValidity` callback function. | None | None | | `requestSubmit` | Checks validity of the form, and submits the form only if all inputs are valid. | None | None | | `reset` | Clears out all inputs. | None | None | | `submit` | Immediately submits the form without checking for validity. | None | None | ### [How to call a method](#how-to-call-a-method) [submit](#tab-983271654-6-0) [validate](#tab-983271654-6-1) ```js const form = document.querySelector('moov-form'); form.submit(); // Use onSuccess and onError for the result ``` ```js const form = document.querySelector('moov-form'); form.checkValidity(); // Use onCheckValidity for the result ``` ## [Attributes](#attributes) String-type properties can be set via attributes on the HTML `` element. | Attribute | Type | Description | |-----------|--------|---------------------------------------------------------------------------------------| | `name` | String | The unique name of the form. | | `method` | String | The HTTP method to use when submitting the form. `GET`, `POST`, `PATCH`, or `DELETE`. | | `action` | String | The Moov API url to use when submitting the form, such as `/accounts/{accountID}`. | ## [Scopes](#scopes) Your Moov API token must include the required scopes for the desired form action. Refer to the [API docs](/api/) for your desired action to find the required scopes. --- URL: https://docs.moov.io/moovjs/drops/composable-drops/text-input/ --- # Text input Drop Include the Moov text input Drop with the Moov form Drop to securely and seamlessly submit sensitive user data to Moov. Combine the `moov-text-input` with the `moov-form` to submit sensitive user data to Moov. With the `moov-text-input` element, information entered by the user is captured by iframes and hidden from the customer's website. Cardholder name ```html
``` Moov Drops require a secure HTTPS connection. If you don't have a test environment with HTTPS enabled, we suggest setting up a hosting environment with ngrok, Netlify, or Vercel. ## [Properties](#properties) Properties can be accessed through JavaScript using a reference to the `moov-text-input` element. | Property | Type | Required | Description | |---------------------|----------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `name` | String | **✓** | The name of the input. The input value is merged into the request body using this name. For example, the input name `expiration.month` would result in a request body of `{ expiration: { month: "inputValue" } }`. | | `formName` | String | **✓** | The name of the form to which this text input is registered | | `inputmode` | String | | Prompts the users device to display certain keyboards, and restricts the allowed characters in the input. | | `value` | String | | The value of the input. Writeable, but not readable. User input will override this value. | | `defaultValue` | String | | The default value of the input on first load. | | `disabled` | Boolean | | If `true`, this input is disabled, preventing user input. | | `required` | Boolean | | If `true`, this input is required for form submission. | | `autocomplete` | Boolean | | If `true`, enables browser autocomplete features on this input. | | `maxLength` | Number | | Maximum number of characters allowed in this input. | | `minLength` | Number | | Minimum number of characters allowed in this input. | | `pattern` | String | | A regex string specifying the expected structure for this input's value. | | `placeholder` | String | | Placeholder text displayed when the input has no value. | | `readOnly` | Boolean | | If `true`, the input value cannot be edited by a user. | | `size` | Number | | Expected number of characters in this input. | | `inputStyle` | Object | | A record of camelCased CSS variables, passed to the input element within the iframe. For developer convenience, inheritable styles such as color, font-size, and font-family are applied automatically. | | `validationMessage` | String | | Read only. The human-readable message displayed to the user when this input is invalid. | | `validity` | Object | | Read only. A `ValidityState` object. Details whether or not the input is valid and which validations (if any) are passing. | | `willValidate` | Boolean | | Read only. Returns true if this input has any attached validators. | | `onInput` | Function | | Fired when the user changes the input value. No arguments. | | `onChange` | Function | | Fired when the user navigates away from the input. No arguments. | | `onFocus` | Function | | Fired when the user focuses the input. No arguments. | | `onBlur` | Function | | Fired when the input loses focus. No arguments. | | `onInvalid` | Function | | Fired when the input fails a validation check. | | `onEnterKeyPress` | Function | | Fired when the user presses the enter key while focusing the input | | `onCheckValidity` | Function | | Fired after a validity check runs on the input. Passes `isValid` as an argument. | | `onReportValidity` | Function | | Fired after a validity report runs on the input. Passes `isValid` as an argument. | ### [How to set a property](#how-to-set-a-property) [name](#tab-965842173-4-0) [inputStyle](#tab-965842173-4-1) [onBlur](#tab-965842173-4-2) [onInvalid](#tab-965842173-4-3) ```javascript const input = document.querySelector('moov-text-input'); input.name = 'demoInput'; ``` ```javascript const input = document.querySelector('moov-text-input'); input.inputStyle = { fontSize: "14px", color: "blue", }; ``` ```javascript const input = document.querySelector('moov-text-input'); const blurCallback = () => { // The input lost focus input.checkValidity(); }; input.onBlur = blurCallback; ``` ```javascript const input = document.querySelector('moov-text-input'); const invalidCallback = () => { // The input failed validation console.error(input.validationMessage); }; input.onInvalid = invalidCallback; ``` ## [Methods](#methods) You can call the methods of `moov-text-input` to perform various actions. | Method | Description | Parameters | Returns | |---------------------|---------------------------------------------------------------------------------------------------------|---------------------------|---------| | `blur` | Removes focus from the input. | None | None | | `click` | Imitates a user click on the input. | None | None | | `focus` | Focuses the input. | None | None | | `select` | Selects the input. | None | None | | `setCustomValidity` | Overrides the `validityMessage` on the input. | `validityMessage`: String | None | | `checkValidity` | Runs a validity check on the input. | None | None | | `reportValidity` | Runs a validity check on the input and reports the result to the user through browser default behavior. | None | None | ### [How to call a method](#how-to-call-a-method) [focus](#tab-359724168-6-0) [validate](#tab-359724168-6-1) ```javascript const input = document.querySelector('moov-text-input'); input.focus(); ``` ```javascript const input = document.querySelector('moov-text-input'); input.checkValidity(); // Use onCheckValidity for the result ``` --- URL: https://docs.moov.io/moovjs/drops/drops-101/ --- # Drops 101 Learn the basics of Moov Drops Moov Drops are custom web components added to your page the same way you would add any HTML tag. Moov Drops are defined in the [Moov.js](/moovjs) package. After [initializing](/moovjs/installation) Moov.js, you will have access to our full library of Drops. ```html ``` Moov Drops require a secure HTTPS connection. If you don't have a test environment with HTTPS enabled, we suggest setting up a hosting environment with ngrok, Netlify, or Vercel. ## [Properties](#properties) You can configure a Drop via **properties** set through JavaScript. Properties can be accessed using a reference to the Drop's HTML element (`` in this case). #### [How to set a property](#how-to-set-a-property) ```js const exampleDrop = document.querySelector('moov-example-drop'); exampleDrop.exampleProperty = 'example-value'; ``` ## [Attributes](#attributes) For your convenience, string-type properties can be set directly on the HTML element through a corresponding **attribute**. Properties are written in `camelCase`, while attributes are written in `kebab-case`. #### [How to set an attribute](#how-to-set-an-attribute) ```html ``` Attribute changes will always update the corresponding property. However, for performance reasons, property changes will **not** update the corresponding attribute. ## [Methods](#methods) Some Drops expose functional properties called **methods**. You can call these methods to perform some action. #### [How to call a method](#how-to-call-a-method) ```js const exampleDrop = document.querySelector('moov-example-drop'); exampleDrop.exampleMethod('example-argument'); ``` ## [Themes](#themes) You can customize the look and feel of Moov Drops by editing our pre-defined CSS variables. Read our [themes](/moovjs/drops/theming/) guide to learn more. --- URL: https://docs.moov.io/moovjs/drops/file-upload/ --- # Prebuilt file upload UI Allow users to easily upload documents to their Moov account. With the `moov-file-upload` drop, you can easily allow end users to upload important documents to their existing Moov account. The file upload Drop interacts directly with the upload file `POST` [endpoint](/api/moov-accounts/files/post/) using JWTs to securely send data between your end user's browser and Moov. ![Upload document modal in Moov drop](../images/document-upload-screens.png) ```html ``` Visit our [Drops 101](/moovjs/drops/drops-101/) guide to learn the basics of properties, attributes, and initializing Drops. Moov Drops require a secure HTTPS connection. If you don't have a test environment with HTTPS enabled, we suggest setting up a hosting environment with ngrok, Netlify, or Vercel. ## [Properties](#properties) Properties can be accessed through JavaScript using a reference to the `moov-file-upload` element. | Property | Type | Description | |-------------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `token` | String | Auth token used for hitting the API. See the [scopes](/moovjs/drops/file-upload/#scopes) section for more detail. | | `accountID` | String | The ID of the Moov user account to which the file will be uploaded. | | `open` | Boolean | Whether or not the dialog is currently displayed to the user. | | `onError` | Function | Callback fired when the dialog encounters an error. | | `onCancel` | Function | Callback fired when the user attempts to close the dialog. | | `onSuccess` | Function | Callback fired when the user uploads a file. Passes a Moov file object as a parameter. See the upload a file `POST` [endpoint](/api/moov-accounts/files/post/#response) response for details on the Moov file object. | ### [How to set a property](#how-to-set-a-property) [token](#tab-519738624-3-0) [onError](#tab-519738624-3-1) ```js const fileUpload = document.querySelector('moov-file-upload'); fileUpload.token = 'eyjh...'; ``` ```js const fileUpload = file.querySelector('moov-file-upload'); fileUpload.onError = ({ errorType, error }) => { console.log(errorType); // "token", "document", etc console.error(error); // Error message }; ``` ## [Attributes](#attributes) String-type properties can be set via attributes on the HTML `` element. | Attribute | Description | |--------------|-------------------------------------------------------------------------------------------------------------------| | `token` | Auth token used for hitting the API. See the [scopes](/moovjs/drops/file-upload/#scopes) section for more detail. | | `account-id` | ID of the Moov account to which the payment method will be added. | ## [Scopes](#scopes) To upload a document, your Moov API token must include the following scopes. - `/files.write` Read our [scopes](/api/authentication/scopes/) guide for more information on Moov's authentication protocol. ## [Theming](#theming) Read our [themes](/moovjs/drops/theming/) guide to learn how to re-style Moov Drops. --- URL: https://docs.moov.io/moovjs/drops/ --- # Moov Drops Explore our collection of UI components for embedding payments securely and quickly. We’ve pre-built user interfaces that take care of form shortening, error handling, and secure PII data collection. As a developer, you have the option to use our defaults, or customize the Moov Drops to match your brand. --- URL: https://docs.moov.io/moovjs/drops/issued-card/ --- # Issued card UI The issued card Drop enables Moov customers to display a previously issued virtual card within a secure, Moov-hosted iframe. With the `moov-issued-card` element, issued card information is displayed to the user and rendered directly by Moov. The issued card Drop interacts directly with the retrieve a spending card`GET` [endpoint](/api/money-movement/issuing/get/) using JWTs to securely send data between your end user's browser and Moov. All information is displayed through an iframe and protected from programmatic access. Note: To use the issued card drop, [Moov support](https://support.moov.io/) must first enable the `issued-cards.read-secure` scope for your account. ![](../images/issued-card-drop.png) ```html ``` Visit our [Drops 101](/moovjs/drops/drops-101/) guide to learn the basics of properties, attributes, and initializing Drops. Note that the use of the issued card Drop requires a secure HTTPS connection. Moov Drops require a secure HTTPS connection. If you don't have a test environment with HTTPS enabled, we suggest setting up a hosting environment with ngrok, Netlify, or Vercel. ## [Properties](#properties) Properties can be accessed through JavaScript using a reference to the `moov-issued-card` element. | Property | Type | Description | |----------------|--------|------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `oauthToken` | String | Auth Token used for hitting the API. Token must include the `accounts/{accountID}/issued-cards.read` and `accounts/{accountID}/issued-cards.read-secure` scopes. | | `accountID` | String | ID of the Moov account to which the card was issued. | | `issuedCardID` | String | ID of the issued card to display. | ### [How to set a property](#how-to-set-a-property) [oauthToken](#tab-753826194-5-0) [accountID](#tab-753826194-5-1) ```js const issuedCard = document.querySelector('moov-issued-card'); issuedCard.oauthToken = 'eyjh...'; ``` ```js const issuedCard = document.querySelector('moov-issued-card'); issuedCard.accountID = "abc123-x..."; ``` ## [Attributes](#attributes) String-type properties can be set via attributes on the HTML `` element. | Attribute | Description | |------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `oauth-token` | Auth Token used for hitting the API. Token must include the `accounts/{accountID}/issued-cards.read` and `accounts/{accountID}/issued-cards.read-secure` scopes. | | `account-id` | ID of the Moov account to which the card was issued. | | `issued-card-id` | ID of the issued card to display. | ## [Scopes](#scopes) To display an issued card, your Moov API token must include the following scopes: - `accounts/{accountID}/issued-cards.read` - `accounts/{accountID}/issued-cards.read-secure`* \*The `issued-cards.read-secure` scope must be enabled by Moov support. If you're looking to use the issued card Drop but haven't had this scope enabled by a member of our team yet, [contact Moov](https://support.moov.io/). ## [Theming](#theming) Read our [themes](/moovjs/drops/theming/) guide to learn how to re-style Moov Drops. --- URL: https://docs.moov.io/moovjs/drops/onboarding/ --- # Prebuilt onboarding UI Implement a pre-built user interface for onboarding individuals or businesses easily, even if they require verification. With the `moov-onboarding` element, users can enter individual or business information to create an account, and Moov handles the onboarding process. The onboarding Drop takes care of the entire account creation workflow, interacting directly with Moov's API using JWTs to securely send data between your end user's browser and Moov. For business accounts, this includes gathering the business, representative, and underwriting data requirements for accounts requesting the `wallet.balance`, `card-issuing`, or one of the `send-funds` or `collect-funds` capabilities. Accounts that require just the `transfer` capability should see the standard Moov.js [accounts](/moovjs/accounts/accounts/) guide to get set up. The onboarding Drop is for users looking to create a complete account with `wallet.balance`, `card-issuing`, or any of the `send-funds` or `collect-funds` capabilities. ![](../images/onboarding-drop-splash-screen.png) ![](../images/onboarding-drop-business-details.png) ```html ``` Visit our [Drops 101](/moovjs/drops/drops-101/) guide to learn the basics of properties, attributes, and initializing Drops. Moov Drops require a secure HTTPS connection. If you don't have a test environment with HTTPS enabled, we suggest setting up a hosting environment with ngrok, Netlify, or Vercel. ## [Properties](#properties) Properties can be accessed through JavaScript using a reference to the `moov-onboarding` element. If you're still using legacy capabilities, you can update to [granular capabilities](/guides/accounts/capabilities/reference/) by updating your `capabilities` property accordingly. | Property | Type | Description | |------------------------|-----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `token` | String | Auth Token used for hitting the API. Multiple tokens will be needed to fully complete the onboarding process. See the `Scopes` section for more detail. | | `facilitatorAccountID` | String | ID for your account. The account created through onboarding will be connected to this account. | | `accountData` | Object | Partial account data used to pre-populate fields in the onboarding dialog. | | `capabilities` | String\[] | The capabilities requested by this account. Defaults to `["transfers"]`. Fields in the onboarding dialog will be marked as optional or required based on the requested capabilities. In some cases, entire steps are shown or hidden. See the [capabilities](/moovjs/accounts/capabilities/) section for more detail. | | `open` | Boolean | Whether or not the dialog is currently displayed to the user. | | `onResourceCreated` | Function | Callback fired when the onboarding dialog creates a new resource (account, payment method, etc). Use this callback to update your token with the appropriate scopes before creating the next resource. Note: the onboarding dialog creates multiple resources. Do not exit the onboarding dialog as soon as the `account` resource is created; there are more steps. See the [Scopes](/moovjs/drops/payment-methods/#scopes) section for more detail. | | `onError` | Function | Callback fired when the onboarding dialog encounters an error. | | `onCancel` | Function | Callback fired when the user attempts to close the dialog. | | `onSuccess` | Function | Callback fired when the user completes the onboarding process. | | `plaid` | Object | A Plaid configuration object. Used for setting up a payment method through Plaid. | | `onPlaidRedirect` | Function | Callback fired after following a redirect from Plaid. Provides a `restoredProperties` object which can be used to restore the state of the drop. | | `paymentMethodTypes` | String\[] | An array of allowed payment method types. Possible values are `card` or `bankAccount`. Defaults to `["card", "bankAccount"]`. An empty array `[]` will hide the payment method step completely. | | `allowedCardBrands` | String\[] | An array of allowed card brands. If this field is not provided, all card brands will be accepted. Accepted values are `visa`, `mastercard`, `american-express`, `diners-club`, `discover`, `jcb`, `unionpay`, `maestro`, `mir`, `elo`, `hiper`, or `hipercard`. | | `cardOnFile` | Boolean | If true, indicates cardholder has authorized card to be stored for future payments. (e.g., recurring payments). If true and no merchantAccountID is provided, the partner account's ID is used as the merchant account for verification. | | `merchantAccountID` | String | If provided, this is the merchant account whose details (statement descriptor, address, etc.) are used for the card verification authorization. If omitted, the partner account's details are used instead. | | `microDeposits` | Boolean | If false, hides the micro deposit verification step when adding a payment method. Defaults to `true`. | | `showLogo` | Boolean | If true, shows your business' avatar on the start screen. Defaults to `false`. | ### [How to set a property](#how-to-set-a-property) [token](#tab-917532684-5-0) [accountData](#tab-917532684-5-1) [onError](#tab-917532684-5-2) ```js const onboarding = document.querySelector('moov-onboarding'); onboarding.token = 'eyjh...'; ``` ```js const onboarding = document.querySelector('moov-onboarding'); onboarding.accountData = { profile: { individual: { email: "john.doe@moov.io", name: { firstName: "John", lastName: "Doe" }, birthDate: { day: 1, month: 1, year: 1990, }, }, }, }; ``` ```js const onboarding = document.querySelector('moov-onboarding'); onboarding.onError = ({ errorType, error }) => { console.log(errorType); // "account", "representative", "bankAccount", etc console.error(error); // Error message }; ``` ## [Attributes](#attributes) String-type properties can be set via attributes on the HTML `` element. | Attribute | Description | |--------------------------|-------------------------------------------------------------------------------------------------------------| | `token` | Auth Token used for hitting the API. See the `Scopes` section for more detail. | | `facilitator-account-id` | ID for the main account. The account created through onboarding will be connected to this account. | | `show-logo` | Boolean attribute that should only be present if you want to show your business avatar on the start screen. | ## [Scopes](#scopes) The `moov-onboarding` Drop requires different scopes at different steps in the onboarding process. As users move through the onboarding flow, the Drop creates new resources (accounts, payment methods, etc), and it needs the appropriate permissions to read or modify those resources. The developer is responsible for updating the onboarding token with new scopes as resources are created. 1. Create a token with the following initial scopes: - `/accounts.write` - `/accounts/{facilitatorAccountID}/profile.read` - `/fed.read` - `/profile-enrichment.read` 2. Initialize the onboarding Drop with the token and make the Drop available to the user. ```js // Get `myToken` with initial scopes onboarding.token = myToken; onboarding.open = true; ``` 3. The user enters information for their new account. 4. The onboarding Drop creates the account and fires the `onResourceCreated` callback. ```js onboarding.onResourceCreated = ({ resourceType, resource }) => { // This fires when the account is created console.log("Resource created! ", resource); } ``` 5. Get the account from the `onResourceCreated` callback: ```js onboarding.onResourceCreated = ({ resourceType, resource }) => { if (resourceType === "account") { // Save the account resource somewhere } }; ``` 6. Use the `accountID` to create a new token and add the following scopes: - All initial scopes - `/accounts/{newAccountID}/bank-accounts.read` - `/accounts/{newAccountID}/bank-accounts.write` - `/accounts/{newAccountID}/capabilities.read` - `/accounts/{newAccountID}/capabilities.write` - `/accounts/{newAccountID}/cards.read` - `/accounts/{newAccountID}/cards.write` - `/accounts/{newAccountID}/profile.read` - `/accounts/{newAccountID}/profile.write` - `/accounts/{newAccountID}/representatives.read` - `/accounts/{newAccountID}/representatives.write` 7. Update the onboarding Drop with the new token: ```js // Get `myToken2` with account-related scopes onboarding.token = myToken2; ``` 8. The user can now continue on to add representatives and payment methods to the account. ## [Theming](#theming) Read our [themes](/moovjs/drops/theming/) guide to learn how to re-style Moov Drops. --- URL: https://docs.moov.io/moovjs/drops/payment-methods/ --- # Link payment methods UI Implement a pre-built user interface for registering new payment methods. With the `moov-payment-methods` drop, you can easily allow end users to register new payment methods with their existing Moov account. The payment methods Drop interacts directly with the link a card `POST` [endpoint](/api/sources/cards/create/) and the link a bank account `POST` [endpoint](/api/sources/bank-accounts/create/) using JWTs to securely send data between your end user's browser and Moov. If you want to set up payment methods on a new Moov account, use the [moov-onboarding](/moovjs/drops/onboarding/) drop, which flows straight into payment methods after an account is created. Note that you can configure your payment method flow to support both card acceptance and bank accounts or just one of them. ![Set up payment methods modal in Moov drop](../images/set-up-bank-account.png) ```html ``` Visit our [Drops 101](/moovjs/drops/drops-101/) guide to learn the basics of properties, attributes, and initializing Drops. Moov Drops require a secure HTTPS connection. If you don't have a test environment with HTTPS enabled, we suggest setting up a hosting environment with ngrok, Netlify, or Vercel. ## [Properties](#properties) Properties can be accessed through JavaScript using a reference to the `moov-payment-methods` element. | Property | Type | Description | |----------------------|-----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `token` | String | Auth Token used for hitting the API. See the `Scopes` section for more detail. | | `accountID` | String | The ID of the Moov user account to which the payment method will be added. | | `open` | Boolean | Whether or not the dialog is currently displayed to the user. | | `onResourceCreated` | Function | Callback fired when the dialog creates a new resource (account, payment method, etc). Use this callback to update your token with the appropriate scopes before creating the next resource. See the [Scopes](/moovjs/drops/payment-methods/#scopes) section for more detail. | | `onError` | Function | Callback fired when the dialog encounters an error. | | `onCancel` | Function | Callback fired when the user attempts to close the dialog. | | `onSuccess` | Function | Callback fired when the user links a payment method. Responds with a card or bank account which can be accessed in the function. See the link card [endpoint](/api/sources/cards/create/#response) or the link bank account [endpoint](/api/sources/bank-accounts/create/#response) response for more detail. | | `plaid` | Object | A Plaid configuration object. Used for setting up a payment method through Plaid. | | `onPlaidRedirect` | Function | Callback fired after following a redirect from Plaid. Provides a `restoredProperties` object which can be used to restore the state of the drop. | | `paymentMethodTypes` | String\[] | An array of allowed payment method types. Possible values are `card` or `bankAccount`. Defaults to `["card", "bankAccount"]`. | | `allowedCardBrands` | String\[] | An array of allowed card brands. If this field is not provided, all card brands will be accepted. Accepted values are `visa`, `mastercard`, `american-express`, `diners-club`, `discover`, `jcb`, `unionpay`, `maestro`, `mir`, `elo`, `hiper`, or `hipercard`. | | `cardOnFile` | Boolean | If true, indicates cardholder has authorized card to be stored for future payments. (e.g., recurring payments). If true and no merchantAccountID is provided, the partner account's ID is used as the merchant account for verification. | | `merchantAccountID` | String | If provided, this is the merchant account whose details (statement descriptor, address, etc.) are used for the card verification authorization. If omitted, the partner account's details are used instead. | | `microDeposits` | Boolean | If false, hides the micro deposit verification step when adding a payment method. Defaults to `true`. | ### [How to set a property](#how-to-set-a-property) [token](#tab-481539276-3-0) [onError](#tab-481539276-3-1) ```js const paymentMethods = document.querySelector('moov-payment-methods'); paymentMethods.token = 'eyjh...'; ``` ```js const paymentMethods = document.querySelector('moov-payment-methods'); paymentMethods.onError = ({ errorType, error }) => { console.log(errorType); // "bankAccount", "plaid", etc console.error(error); // Error message }; ``` ## [Attributes](#attributes) String-type properties can be set via attributes on the HTML `` element. | Attribute | Description | |--------------|--------------------------------------------------------------------------------| | `token` | Auth Token used for hitting the API. See the `Scopes` section for more detail. | | `account-id` | The ID of the Moov user account to which the payment method will be added. | ## [Scopes](#scopes) To add a payment method, your Moov API token must include the following scopes. - `/fed.read` - `/accounts/{accountID}/cards.read` - `/accounts/{accountID}/cards.write` - `/accounts/{accountID}/bank-accounts.read` - `/accounts/{accountID}/bank-accounts.write` ## [Using Plaid for instant account verification](#using-plaid-for-instant-account-verification) Instead of using micro-deposit verification which can take up to a few days to complete, you can use Plaid directly from Moov Drops to add new bank accounts. To use Plaid, you must pass a configuration object into the `plaid` and `onPlaidRedirect` properties of the `moov-payment-methods` drop. #### [Plaid configuration object parameters](#plaid-configuration-object-parameters) | Name | Type | Description | |---------------------------|--------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `env` | `"sandbox"` or `undefined` | Plaid environment. Use `"sandbox"` for testing. Use `undefined` for production. | | `redirectURL` | URL string | If Plaid forces the user to a bank's website, they will eventually return to this url. Must be a webpage on your current domain. [Contact Moov](https://support.moov.io/) and include the `redirectURL` to get it registered in the Plaid dashboard. | | `receivedRedirectUri` | URL string | URL of the current page. Will be a combination of your `redirectURL` and query parameters set by Plaid. | | `token` | String | Optional. For Moov customers who manage their own Plaid integration. Create a Plaid `link_token` and enter it here to bypass the Moov-managed Plaid request. See [Plaid documentation](https://plaid.com/docs/auth/partnerships/moov/#create-a-link_token) for more details. | | `onSuccess` | (moovBankAccount) => void | Optional. Callback function executed when Plaid successfully links a bank account to Moov. Moov bank account object is passed as a parameter. | | `onExit` | (err, metadata) => void | Optional. Callback function executed when the user exits the Plaid flow. | | `onEvent` | (eventName, metadata) => void | Optional. Callback function executed on each Plaid event. | | `onLoad` | () => void | Optional. Callback function executed when Plaid loads. | | `onProcessorTokenRequest` | (public\_token, bank\_account\_id) => Promise | Optional. For Moov customers who manage their own Plaid integration. When this callback fires, use your existing Plaid integration to convert the given `public_token` and `bank_account_id` into a `processor_token` and return it. | [Basic](#tab-496153278-5-0) [Redirect handling](#tab-496153278-5-1) [BYO Plaid](#tab-496153278-5-2) ```js const paymentMethods = document.querySelector('moov-payment-methods'); paymentMethods.token = "eyj..."; paymentMethods.accountID = "abc123..."; paymentMethods.plaid = { env: "sandbox", redirectURL: "https://yoursite.com/plaidredirecturl", onExit: (...args) => console.log("on plaid exit", ...args), onEvent: (...args) => console.log("on plaid event", ...args), onLoad: (...args) => console.log("on plaid load", ...args), onSuccess: (...args) => console.log("on plaid success", ...args), }; ``` ```js const paymentMethods = document.querySelector('moov-payment-methods'); paymentMethods.token = "eyj..."; paymentMethods.accountID = "abc123..."; paymentMethods.plaid = { env: "sandbox", redirectURL: "https://yoursite.com/plaidredirecturl", // After following a Plaid redirect, we pass the new URL here receivedRedirectUri: window.location.href.includes("?oauth_state_id") ? window.location.href : undefined, }; // After following Plaid redirect, restore the drop to its previous state paymentMethods.onPlaidRedirect: (restoredProperties) => { paymentMethods.token = restoredProperties.token; paymentMethods.accountID = restoredProperties.accountID; paymentMethods.open = restoredProperties.open; }; ``` ```js const paymentMethods = document.querySelector('moov-payment-methods'); paymentMethods.token = "eyj..."; paymentMethods.accountID = "abc123..."; paymentMethods.plaid = { env: "sandbox", redirectURL: "https://yoursite.com/plaidredirecturl", // Pre-existing Plaid customers pass their own token here: token: "plaid_eyj123-the-token-you-requested-from-plaid", // Pre-existing Plaid customers convert Plaid data into a Moov processor token here: onProcessorTokenRequest: (public_token, bank_account_id) => { return fetch(`/your-processor-token-endpoint?pt=${public_token}&bai=${bank_account_id}`) .then((res) => res.json()) .then(({ processor_token }) => processor_token); }, }; ``` ## [Theming](#theming) Read our [themes](/moovjs/drops/theming/) guide to learn how to re-style Moov Drops. --- URL: https://docs.moov.io/moovjs/drops/terms-of-service/ --- # Prebuilt terms of service UI Implement a pre-built user interface for reviewing and accepting terms of service. The `moov-terms-of-service` Drop provides links to Moov's privacy policy and terms of service agreement and generates a token in the background. The token can be [patched to an account](/api/moov-accounts/accounts/patch/) for the purpose of accepting Moov's terms of service. The terms of service Drop interacts directly with the generate a terms of service token `GET` [endpoint](/api/moov-accounts/accounts/get-tos/) using JWTs to securely send data between your end user's browser and Moov. ![Set up terms of service Moov drop](../images/tos-hero.png) ```html ``` Visit our [Drops 101](/moovjs/drops/drops-101/) guide to learn the basics of properties, attributes, and initializing Drops. Moov Drops require a secure HTTPS connection. If you don't have a test environment with HTTPS enabled, we suggest setting up a hosting environment with ngrok, Netlify, or Vercel. ## [Visual requirements](#visual-requirements) The terms of service (TOS) Drop must adhere to the following minimum visual requirements: 1. Text color and background color must comply with ARIA color contrast standards. 2. Link color and background color must comply with ARIA color contrast standards. 3. Font size must not be smaller than 10px. If the minimum visual requirements are not met, this component will not load, and you will see an error in your console. In addition to the minimum requirements, the action button which allows users to accept the terms of service must be within close proximity of the TOS Drop, and the agreement statement must be in English. Tab through the visual requirement examples below. [Color contrast](#tab-872169354-2-0) [Font size](#tab-872169354-2-1) [Button spacing](#tab-872169354-2-2) [Language](#tab-872169354-2-3) ![Moov Drop color contrast requirements](../images/tos-accessibility.png) ![Moov Drop font size requirements](../images/tos-font-size.png) ![Moov Drop button spacing](../images/tos-button-spacing.png) ![Moov Drop language](../images/tos-language.png) ## [Properties](#properties) Properties can be accessed through JavaScript using a reference to the `moov-terms-of-service` element. ```html ``` | Property | Type | Description | |------------------------------|----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `token` | String | Auth token used for hitting the API | | `customActionCopy` | String | Default copy will be "By clicking continue, you agree to the terms of Moov's Privacy Policy and Terms of Service." This property allows you to adjust the "By clicking continue" portion of the copy to fit your use case. | | `textColor` | String | The color of the terms of service text. Must be in a valid rgb format. | | `linkColor` | String | The color of the terms of service links. Must be in a valid rgb format. | | `backgroundColor` | String | The color of the terms of service background. Must be in a valid rgb format. | | `fontSize` | String | The font size of the terms of service text. Must be use a valid font size unit. (i.e. 16px, 1rem, etc) | | `onTermsOfServiceTokenReady` | Function | The callback function used when the generated terms of service token is fetched | | `onTermsOfServiceTokenError` | Function | The callback function used when generating the terms of service token errors | ### [How to set a property](#how-to-set-a-property) [token](#tab-395721486-4-0) [onTermsOfServiceTokenReady](#tab-395721486-4-1) [onTermsOfServiceTokenError](#tab-395721486-4-2) [customActionCopy](#tab-395721486-4-3) ```js const termsOfService = document.querySelector("moov-terms-of-service"); termsOfService.token = "eyjh..."; ``` ```js const termsOfService = document.querySelector("moov-terms-of-service"); termsOfService.onTermsOfServiceTokenReady = (termsOfServiceToken) => { console.log(termsOfServiceToken); // This is the terms of service token, not to be confused with the api token prop. }; ``` ```js const termsOfService = document.querySelector("moov-terms-of-service"); termsOfService.onTermsOfServiceTokenError = (error) => { console.log(error); }; ``` ```js const termsOfService = document.querySelector("moov-terms-of-service"); termsOfService.customActionCopy = "By selecting finish"; ``` ## [Attributes](#attributes) String-type properties can be set via attributes on the HTML `` element. ```html ``` | Attribute | Description | |--------------------|--------------------------------------------------------------| | `token` | Auth token used for hitting the API | | `customActionCopy` | Custom action copy to replace default "By clicking continue" | ## [Theming](#theming) Read our [themes](/moovjs/drops/theming/) guide to learn how to re-style Moov Drops. --- URL: https://docs.moov.io/moovjs/drops/theming/ --- # Themes Customize the look of Moov Drops to match your brand. Moov Drops are custom web components you can add to your page the same way you would add any HTML tag. Moov Drops are defined in the [Moov.js](/moovjs) package. After [initializing](/moovjs/installation) Moov.js, you will have access to our full library of Drops. **Moov** **Midnight** **Blueprint** Every Moov Drop shares a color palette defined through a handful of CSS variables. You can edit these variables to alter the look of any Drop on the page, and create a seamless visual experience for your users. Moov Drops require a secure HTTPS connection. If you don't have a test environment with HTTPS enabled, we suggest setting up a hosting environment with ngrok, Netlify, or Vercel. ## [How to use](#how-to-use) To override the Moov Drops color palette, add a `style` or `link` tag within the body of your webpage. ```html ``` The default Drops palette is defined in the `head` of the document. To ensure that your custom colors override the default palette, they must be placed in the `body` tag or with greater specificity. In your style tag, target the `:root` and provide custom values for any or all of our predefined CSS variables. [Moov default](#tab-581627943-5-0) [Midnight](#tab-581627943-5-1) [Blueprint](#tab-581627943-5-2) ```css :root { --moov-color-background: #111111; --moov-color-background-secondary: #222222; --moov-color-background-tertiary: #333333; --moov-color-primary: #77D656; --moov-color-secondary: #79F0AA; --moov-color-tertiary: #4F4F4F; --moov-color-info: #94CBFF; --moov-color-warn: #F2994A; --moov-color-danger: #EB5757; --moov-color-success: #77D656; --moov-color-low-contrast: #969696; --moov-color-medium-contrast: #E0E0E0; --moov-color-high-contrast: #FFFFFF; --moov-color-graphic-1: #79F0AA; --moov-color-graphic-2: #D194E9; --moov-color-graphic-3: #68B2FD; --moov-radius-small: .375rem; --moov-radius-large: .5rem; } ``` ```css :root { --moov-color-background: #25262D; --moov-color-background-secondary: #2D3037; --moov-color-background-tertiary: #3A3C45; --moov-color-primary: #6171F9; --moov-color-secondary: #828FFE; --moov-color-tertiary: #494A57; --moov-color-info: #94CBFF; --moov-color-warn: #EB5757; --moov-color-danger: #ED655C; --moov-color-success: #62E599; --moov-color-low-contrast: #9294A0; --moov-color-medium-contrast: #EBEBEF; --moov-color-high-contrast: #FFFFFF; --moov-color-graphic-1: #62E599; --moov-color-graphic-2: #62E599; --moov-color-graphic-3: #62E599; --moov-radius-small: 0; --moov-radius-large: .25rem; } ``` ```css :root { --moov-color-background: #FFFFFF; --moov-color-background-secondary: #F5F6F9; --moov-color-background-tertiary: #E7E7F1; --moov-color-primary: #4A5CF5; --moov-color-secondary: #3D50EC; --moov-color-tertiary: #B9BBC3; --moov-color-info: #94CBFF; --moov-color-warn: #EB5757; --moov-color-danger: #EA0F43; --moov-color-success: #62E599; --moov-color-low-contrast: #5B5D6A; --moov-color-medium-contrast: #494A57; --moov-color-high-contrast: #000000; --moov-color-graphic-1: #3D50EC; --moov-color-graphic-2: #3D50EC; --moov-color-graphic-3: #3D50EC; --moov-radius-small: .375rem; --moov-radius-large: .5rem; } ``` --- URL: https://docs.moov.io/moovjs/drops/theming/theme/ --- # Themes --- URL: https://docs.moov.io/moovjs/enrichment/ --- # Enrichment ## [Form shortening](#form-shortening) Find publicly available information to autofill form fields based on an email address. #### [Parameters](#parameters) | Name | Type | |---------|--------| | `email` | string | ```javascript moov.enrichment.lookup('amanda@classbooker.dev'); ``` If available, the response includes details about the individual and/or business tied to the email address. ## [Get avatar](#get-avatar) You can retrieve an account's profile image. This is especially useful if you'd like to use the profile image for a corresponding account in your own product. To get an avatar, you'll need to specify the `/profile-enrichment.read` scope when generating a token. #### [Parameters](#parameters-1) | Name | Type | |------------|--------| | `avatarID` | string | ```javascript const avatarID = avatarID; moov.enrichment.avatar({ avatarID: avatarID }); ``` The unique ID can be a Moov account ID, representative ID, or bank account ID. ## [Get industries](#get-industries) Get a list of industry names and their corresponding MCC, NAICS, and SIC codes. To get industries, you'll need to specify the `/profile-enrichment.read` scope when generating a token. ```javascript moov.enrichment.listIndustries(); ``` ## [Autocomplete address](#autocomplete-address) Lookup a list of addresses based on partial address information. This is useful for auto-completing address fields with data that is more likely to pass KYC validation. To get address suggestions, you'll need to specify the `/profile-enrichment.read` scope when generating a token. #### [Parameters](#parameters-2) | Name | Type | |----------|--------| | `search` | string | ```javascript moov.enrichment.lookupAddress({ search: '123 Main St' }); ``` Additional parameters are available to limit the number of results returned or filter the results. See [enriched address](/api/enrichment/form-shortening/address/get/) for more information. --- URL: https://docs.moov.io/moovjs/ --- # Moov.js Use Moov.js to streamline your interactions with the Moov API. With Moov.js, all PII goes straight to Moov so you won't be responsible for storing or handling sensitive user data. When making calls from the browser, you'll need to specify [scopes](/api/authentication/scopes/) when generating an access token. Scopes specify what actions an account can take. When generating an OAuth2 [access token](/api/authentication/access-tokens/create/), you'll include the name of the scope that covers the type of access needed. You'll use a generated token for each API call you make. --- URL: https://docs.moov.io/moovjs/installation/ --- # Install & authenticate Install, authenticate, and initialize Moov.js in your application. After installation, you'll generate a token server-side to communicate between Moov and your account. You'll also set [scopes](/api/authentication/scopes/) to make API calls from Moov.js. ## [Install](#install) Include Moov.js in your application by loading the Moov.js script, or downloading the Moov.js package via [npm](https://www.npmjs.com/package/@moovio/moov-js?activeTab=readme). [Script tag](#tab-634751829-1-0) [npm](#tab-634751829-1-1) ```html ``` ```zsh npm i @moovio/moov-js ``` ## [Authenticate](#authenticate) For each action you take with Moov.js, you'll need a unique short lived access token that contains information needed to securely communicate with your Moov account. You must generate tokens from your server-side application. Once you’ve generated a token, send it back to your client to use with Moov.js. ![Token generation process diagram](images/token-diagram-moovjs-light.png) ### [Create an access token](#create-an-access-token) The examples below create an access token with a scope set to create an account. See the [scopes](/api/authentication/scopes/) documentation for more information. [cURL](#tab-694752183-3-0) ```zsh curl -X POST "https://api.moov.io/oauth2/token" \ -u "PUBLIC_KEY:PRIVATE_KEY" \ --data '{ "grant_type":"client_credentials", "client_id":"5clTR_MdVrrkgxw2", "client_secret":"dNC-hg7sVm22jc3g_Eogtyu0_1Mqh_4-", "scope":"/accounts.write", "refresh_token":"i1qxz68gu50zp4i8ceyxqogmq7y0yienm52351c6..." }'\ ``` ## [Initialize](#initialize) Once you've generated a token from your server, initialize Moov.js in the browser by passing the token to Moov. [Script installation](#tab-743691285-4-0) [npm installation](#tab-743691285-4-1) ```html ``` ```javascript import { loadMoov } from '@moovio/moov-js'; const moovAccessToken = await fetch(...); const moov = await loadMoov(moovAccessToken); ``` ## [Next steps](#next-steps) - Learn what [scopes](/api/authentication/scopes/) are available for Moov.js actions - Check out Moov.js [Drops](/moovjs/drops/), a collection of UI components --- URL: https://docs.moov.io/moovjs/institutions/ --- # Institution lookup Lookup ACH and wire participating financial institutions. We recommend using this endpoint when an end-user enters a routing number to confirm their bank or credit union. ## [Rail data for institutions](#rail-data-for-institutions) Retrieve rail support data for a given institution. To retrieve rail data for an institution, you'll need to specify the `/fed.read` scope when generating a token. #### [Parameters](#parameters) | Name | Type | |-----------------|--------| | `routingNumber` | string | ```javascript const routingNumber = routingNumber; moov.institutions.lookupAllRailsByRoutingNumber(routingNumber); ``` ## [Search institutions](#search-institutions) Search for institutions by their routing number or name. To search institutions, you'll need to specify the `/fed.read` scope when generating a token. #### [Parameters](#parameters-1) | Name | Type | |-----------------|------------------| | `routingNumber` | string | | `exact` | Optional boolean | ```javascript const routingNumber = routingNumber; const exact = true; moov.institutions.lookupByRoutingNumber(routingNumber, exact); ``` --- URL: https://docs.moov.io/moovjs/sources/bank-accounts/ --- # Bank accounts To transfer money with Moov, you’ll need to link a bank account to your Moov account, then verify that account. You can link a bank account to a Moov account by adding the bank account number and routing number to the account object. We require micro-deposit verification to reduce the risk of fraud or unauthorized activity. You can verify a bank account by initiating instant micro-deposits, which sends a code to a bank account. Alternatively, you can link and verify a bank account in one step through an instant account verification token from a third party provider like Plaid. ## [Add bank account](#add-bank-account) Link a bank account to an existing Moov account. To link a bank account, you'll need to specify the `/accounts/{accountID}/bank-accounts.write` scope when generating a token. **Parameters** | Name | Type | |-------------|--------| | `accountID` | string | [Bank account](#tab-429536781-0-0) [Bring your own Plaid](#tab-429536781-0-1) ```javascript const accountID = "accountID"; const bankAccount = { "holderName": "Jules Jackson", "holderType": "individual", "accountNumber": "0004321567000", "bankAccountType": "checking", "routingNumber": "123456789" }; moov.accounts.bankAccounts.link({accountID, bankAccount}); ``` ```javascript const accountID = "accountID"; moov.accounts.bankAccounts.link({accountID, plaid: { token: "token"}}); ``` Read more on setting up a [Moov managed Plaid integration](/moovjs/sources/bank-accounts/plaid-link/) ## [List bank accounts](#list-bank-accounts) List all the bank accounts associated with a particular Moov account. To list bank accounts, you'll need to specify the `/accounts/{accountID}/bank-accounts.read` scope when generating a token. **Parameters** | Name | Type | |-------------|--------| | `accountID` | string | ```javascript const accountID = "accountID"; moov.accounts.bankAccounts.list({accountID}); ``` ## [Get bank account](#get-bank-account) Retrieve bank account details (routing number or account type) associated with a specific Moov account. To retrieve bank account details, you'll need to specify the `/accounts/{accountID}/bank-accounts.read` scope when generating a token. **Parameters** | Name | Type | |-------------|--------| | `accountID` | string | ```javascript const accountID = "accountID"; moov.accounts.bankAccounts.get({accountID}); ``` ## [Disable bank account](#disable-bank-account) Discontinue using a specified bank account linked to a Moov account. To delete a bank account, you'll need to specify the `/accounts/{accountID}/bank-accounts.write` scope when generating a token. **Parameters** | Name | Type | |-------------|--------| | `accountID` | string | ```javascript const accountID = "accountID"; moov.accounts.bankAccounts.delete({accountID}); ``` ## [Initiate instant micro-deposits verification](#initiate-instant-micro-deposits-verification) Verification helps confirm bank account ownership, reducing fraud and risk of unauthorized activity. Use this method to initiate instant micro-deposits, which sends a 4-digit numeric code and a $0.01 credit to the bank account. The code will be in the form of `MV0000`, `mv0000`, or `0000`. If instant micro-deposits verification is not available at the participating bank, the fallback is same-day ACH. To initiate, you'll need to specify the `/accounts/{accountID}/bank-accounts.write` scope when generating a token. **Parameters** | Name | Type | |-----------------|--------| | `accountID` | string | | `bankAccountID` | string | ```javascript const accountID = "accountID"; const bankAccountID = bankAccountID; moov.accounts.bankAccounts.startVerification({accountID, bankAccountID}); ``` If you choose to request [standard micro-deposit](/api/sources/bank-accounts/initiate-micro-deposits/) verification, be aware of the following timelines. Before 4:00 PM ET, micro-deposits will appear the same day. After 4:00 PM ET micro-deposits will appear the next banking day. ## [Check instant micro-deposit verification](#check-instant-micro-deposit-verification) You can track instant bank account verifications. The response includes whether the verification method was instant or same-day ACH, as well as exception details. ```javascript const accountID = "accountID"; const bankAccountID = bankAccountID; moov.accounts.bankAccounts.getVerification({accountID, bankAccountID}); ``` The status indicates the following: - `new`: Verification initiated, credit pending to the payment network. - `sent-credit`: Credit sent, available for verification. - `failed`: Verification failed, description provided, user needs to add a new bank account. - `expired`: Verification expired after 14 days, initiate another verification. - `max-attempts-exceeded`: Five incorrect code attempts exhausted, initiate another verification. ## [Complete instant micro-deposit verification](#complete-instant-micro-deposit-verification) Complete the instant micro-deposit verification process by passing the code sent to the bank account. You'll need to specify the `/accounts/{accountID}/bank-accounts.write` scope when generating a token. #### [Parameters](#parameters) | Name | Type | |-----------------|--------| | `accountID` | string | | `bankAccountID` | string | | `code` | string | ```javascript const accountID = "accountID"; const bankAccountID = bankAccountID; moov.accounts.bankAccounts.completeVerification({accountID, bankccountID, code}); ``` --- URL: https://docs.moov.io/moovjs/sources/bank-accounts/plaid-link/ --- # Plaid Link Plaid Link allows users to quickly verify bank accounts through instant account verification (IAV). If Moov is managing your Plaid relationship, you can use Moov.js to link bank accounts with Plaid. Once you have a signed contract with Moov, you can work with Moov's customer success team to prepare your account for Plaid. ## [Initialize Moov.js](#initialize-moovjs) As with all Moov.js methods, you will need a [Moov access token](/api/authentication/access-tokens/create/) with the appropriate [scopes](/api/authentication/scopes/). The Moov.js Plaid functions require the following scopes: - `/accounts/{accountID}/bank-accounts.write` ```html ``` ## [Initialize Plaid Link](#initialize-plaid-link) Initialize a connection to Plaid, allowing users to instantly verify and link bank accounts to an existing Moov account. **Note:** For Moov-managed Plaid integrations only. ### [Parameters](#parameters) | Name | Type | Description | |---------------------|----------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `accountID` | string | ID for an existing Moov user account | | `env` | `"sandbox"` or `undefined` | Plaid environment. Use `"sandbox"` for testing. Use `undefined` for production. | | `elementID` | string | Optional. If provided, Plaid flow will open when the DOM element with this ID is clicked. | | `shadowRootElement` | object | Optional. Used in tandem with `elementID`. If provided, the `shadowRootElement` will be used when querying for `elementID`. | | `redirectURL` | URL string | If Plaid forces the user to a bank's website, they will eventually return to this URL. Must be a webpage on your current domain. [Contact Moov](https://support.moov.io/) and include the `redirectURL` so Moov can register this URL in the Plaid dashboard. If you ever change your `redirectURL`, [contact Moov](https://support.moov.io/) again and include the new URL. | | `onSuccess` | (moovBankAccount) => void | Optional. Callback function executed when Plaid successfully links a bank account to Moov. Moov bank account object is passed as a parameter. | | `onExit` | (err, metadata) => void | Optional. Callback function executed when the user exits the Plaid flow. | | `onEvent` | (eventName, metadata) => void | Optional. Callback function executed on each Plaid event. | [Initialize Plaid with button](#tab-712358469-1-0) [Initialize Plaid programmatically](#tab-712358469-1-1) ```javascript moov.plaid.initialize({ accountID: "your-connected-account-id", env: "sandbox", elementID: "your-plaid-button-id", redirectURL: "https://yoursite.com/plaidredirecturl", onSuccess: (bankAccount) => { console.log("Success! Moov bank account: ", bankAccount); }, onExit: (err, metadata) => { console.log("Plaid flow exited: ", err); }, onEvent: (eventName, metadata) => { console.log("Plaid event emitted: ", eventName); } }); ``` ```javascript moov.plaid.initialize({ accountID: "your-connected-account-id", env: "sandbox", redirectURL: "https://yoursite.com/plaidredirecturl", onSuccess: (bankAccount) => { console.log("Success! Moov bank account: ", bankAccount); }, onExit: (err, metadata) => { console.log("Plaid flow exited: ", err); }, onEvent: (eventName, metadata) => { console.log("Plaid event emitted: ", eventName); } }).then((plaidHandler) => { plaidHandler.open(); }); ``` ## [Reinitialize Plaid (OAuth redirects)](#reinitialize-plaid-oauth-redirects) Some banks use an OAuth flow to connect to Plaid. In these situations, your user will be redirected to the bank's website to authenticate, and then redirected back to your specified `redirectURL`. This redirect landing page must run `moov.plaid.reinitialize` to resume the Plaid flow. ### [Parameters](#parameters-1) | Name | Type | Description | |-----------------------|----------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `receivedRedirectUri` | URL string | Brings the user back to the page they were on before Plaid redirected to a bank's website. From there, Moov will detect that the Plaid process has completed and will resume linking the bank account. This parameter will be a combination of your `redirectURL` and query parameters set by Plaid. | | `accountID` | string | ID for an existing Moov user account | | `env` | `"sandbox"` or `undefined` | Plaid environment. Use `"sandbox"` for testing. Use `undefined` for production. | | `elementID` | string | Optional. If provided, Plaid flow will open when the DOM element with this ID is clicked. | | `onSuccess` | (moovBankAccount) => void | Optional. Callback function executed when Plaid successfully links a bank account to Moov. Moov bank account object is passed as a parameter. | | `onExit` | (err, metadata) => void | Optional. Callback function executed when the user exits the Plaid flow. | | `onEvent` | (eventName, metadata) => void | Optional. Callback function executed on each Plaid event. | ```js moov.plaid.reinitialize({ accountID: "your-connected-account-id", receivedRedirectUri: window.location.href, env: "sandbox", onSuccess: (bankAccount) => { console.log("Success! Moov bank account: ", bankAccount); }, onExit: (err, metadata) => { console.log("Plaid flow exited: ", err); }, onEvent: (eventName, metadata) => { console.log("Plaid event emitted: ", eventName); } }); ``` ## [Using Plaid sandbox](#using-plaid-sandbox) You can use the `env: "sandbox"` setting in your Plaid configuration object to simulate the process for connecting a bank account with Plaid. In Plaid's sandbox environment, you can find test bank accounts by searching for `Platypus`. For all `Platypus` bank accounts, the username is `user_good` and the password is `pass_good`. Note that the `Platypus` account cannot be used for testing transfers. The purpose of the test account is solely for simulating connecting bank accounts. **Duplicate accounts:** There's an ongoing issue with Plaid's sandbox environment, where OAuth `Platypus` banks may throw a `duplicate account` error at the end of the Plaid Link flow. Unfortunately, this issue is outside of Moov's control. This issue is limited to Plaid's sandbox environment, and should not affect users in production. --- URL: https://docs.moov.io/moovjs/sources/cards/ --- # Card acceptance You are able to update a linked card and/or resubmit it for verification. If a value is provided for CVV, a new verification ($0 authorization) will be submitted for the card. Updating the expiration date or address will update the information stored on file for the card, but will not be verified. Only use this method if you have provided Moov with a copy of your PCI attestation of compliance. To update a card, you'll need to specify the `/accounts/{accountID}/cards.write` scope when generating a token. #### [Parameters](#parameters) | Name | Type | |-------------|------------------------------------| | `accountID` | string | | `cardID` | string | | `card` | [Card](/api/sources/cards/update/) | ```javascript const accountID = "accountID"; const cardID = "cardID"; const card = { "cardCvv": "123", "billingAddress": { "postalCode": "50613" } }; moov.accounts.cards.update({accountID, cardID, card}); ``` --- URL: https://docs.moov.io/moovjs/sources/ --- # Funding sources Add funding sources in the form of bank accounts, cards, or wallets. Moov abstracts the differences between these sources and provides a common interface for interacting with them, called `payment-methods`. View the pages in this section for more information. --- URL: https://docs.moov.io/moovjs/sources/payment-methods/ --- # Payment methods Payments methods represent all of the ways an account can move funds to another Moov account. Payment methods are generated programmatically when a card or bank account is added or the status is updated, for example, `ach-debit` will be added as a payment method once the bank account is verified. ## [List payment methods](#list-payment-methods) Retrieve all of the payment methods associated with a Moov account. To retrieve payment methods, you'll need to specify the `/accounts/{accountID}/payment-methods.read` scope when generating a token. #### [Parameters](#parameters) | Name | Type | |-------------|--------| | `accountID` | string | ```javascript const accountID = "accountID"; moov.accounts.paymentMethods.list({accountID}); ``` ## [Get payment method](#get-payment-method) Get the specified payment method associated with a Moov account. To get a specified payment method, you'll need to specify the `/accounts/{accountID}/payment-methods.read` scope when generating a token. #### [Parameters](#parameters-1) | Name | Type | |-------------------|--------| | `accountID` | string | | `paymentMethodID` | string | ```javascript const accountID = "accountID"; const paymentMethodID = "paymentMethodID"; moov.accounts.paymentMethods.get({accountID, paymentMethodID}); ``` --- URL: https://docs.moov.io/moovjs/sources/wallets/ --- # Wallets A Moov wallet serves as a funding source as you accumulate funds. You can also use the Moov wallet to: - Pre-fund transfers for faster payouts - Transfer funds between Moov wallets for instantly available funds At this time, wallets can't be manually created, deleted or modified. They are read-only and are automatically created when you sign up for a Moov account and when you request the `wallet` capability for a verified Moov account. ## [Get wallet](#get-wallet) Get information on a specific Moov wallet (for example, the available balance). To get a wallet, you'll need to specify the `/accounts/{accountID}/wallets.read` scope when generating a token. ```javascript wallets.get(accountID, walletID) ``` **Parameters** | Name | Type | Description | |-----------|----------|--------------------------------------------------| | accountID | `string` | Account on which to request wallet | | walletID | `string` | The ID for the wallet associated with an account | **Returns** `Promise.` ## [List wallets](#list-wallets) List the wallet associated with a Moov account. To list wallets, you'll need to specify the `/accounts/{accountID}/wallets.read` scope when generating a token. ```javascript wallets.list(accountID) ``` **Parameters** | Name | Type | Description | |-----------|----------|-------------------------------------| | accountID | `string` | Account on which to request wallets | **Returns** `Promise.>` ## [Get wallet transaction](#get-wallet-transaction) Get the details of a specific wallet transaction. To get wallet transaction details, you'll need to specify the `/accounts/{accountID}/wallets.read` scope when generating a token. ```javascript wallets.getTransaction(accountID, walletID, transactionID) ``` **Parameters** | Name | Type | Description | |---------------|----------|-------------| | accountID | `string` | A unique ID | | walletID | `string` | A unique ID | | transactionID | `string` | A unique ID | **Returns** `Promise.` ## [List wallet transactions](#list-wallet-transactions) List the transactions in a wallet. To list wallet transactions, you'll need to specify the `/accounts/{accountID}/wallets.read` scope when generating a token. ```javascript wallets.listTransactions(accountID, walletID, criteria) ``` **Parameters** | Name | Type | Description | |-----------|-----------------------------------------------------------------|--------------------------------------------------| | accountID | `string` | A unique ID | | walletID | `string` | A unique ID | | criteria | [WalletTransactionListCriteria](#wallettransactionlistcriteria) | Filtering criteria to limit the results returned | **Returns** `Promise.>` ## [Types](#types) ### [Wallet](#wallet) Describes a Moov Wallet **Properties** [Details](#tab-275948163-4-0) [Example](#tab-275948163-4-1) | Property | Type | Description | |------------------|-----------|----------------------------------------------------------------| | walletID | `string` | A unique ID | | availableBalance | `integer` | Balance based on all completed transactions against the wallet | ```javascript { "walletID": "ec7e1848-dc80-4ab0-8827-dd7fc0737b43", "availableBalance": { "currency": "USD", "value": 1204 // $12.04 } } ``` ### [WalletTransaction](#wallettransaction) **Properties** | Property | Type | Description | |------------------|----------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | walletID | `string` | A unique ID | | transactionID | `string` | A unique ID | | transactionType | [WALLET\_TRANSACTION\_TYPE](#wallet_transaction_type) | wallet transaction type. | | sourceType | [WALLET\_TRANSACTION\_SOURCE\_TYPE](#wallet_transaction_source_type) | where the transaction originated | | sourceID | `string` | ID of the source Moov object to which this transaction is related. Can be one of [walletID](/api/sources/wallets/get/), [cardID](/api/sources/cards/get/), or [bankAccountID](/api/sources/bank-accounts/get/). | | status | [WALLET\_TRANSACTION\_STATUS](#wallet_transaction_status) | wallet transaction status | | memo | `string` | Detailed description of the transaction | | createdOn | `string` | Date transaction was created | | completedOn | `string` | Date transaction was completed | | currency | `string` | 3-letter ISO 4217 currency code | | grossAmount | `integer` | The total transaction amount. The amount is in the smallest unit of the specified currency. In USD this is cents, so $12.04 is 1204 and $0.99 would be 99 | | fee | `integer` | Total fees paid for the transaction. The amount is in the smallest unit of the specified currency. In USD this is cents, so $12.04 is 1204 and $0.99 would be 99 | | netAmount | `integer` | Net amount is the gross amount less fees paid, and the amount that affects the wallet's balance. The amount is in the smallest unit of the specified currency. In USD this is cents, so $12.04 is 1204 and $0.99 would be 99 | | availableBalance | `integer` | The wallet's total available balance after recording a completed transaction. The value is in the smallest unit of the specified currency. In USD this is cents, so $12.04 is 1204 and $0.99 would be 99. | ### [WalletTransactionListCriteria](#wallettransactionlistcriteria) **Properties** | Property | Type | Description | |------------------------|----------------------------------------------------------------------|--------------------------------------------------------------| | transactionType | [WALLET\_TRANSACTION\_TYPE](#wallet_transaction_type) | Only return transactions of this type | | sourceType | [WALLET\_TRANSACTION\_SOURCE\_TYPE](#wallet_transaction_source_type) | Only return transactions of this source type | | sourceID | `string` | Only return transactions that were part of this transfer ID | | status | [WALLET\_TRANSACTION\_STATUS](#wallet_transaction_status) | Only return transactions in this state | | createdStartDateTime | `string` | Only return transactions created on or after this datetime | | createdEndDateTime | `string` | Only return transactions created before this datetime | | completedStartDateTime | `string` | Only return transactions completed on or after this datetime | | completedEndDateTime | `string` | Only return transactions completed before this datetime | | count | `number` | Maximum number of transactions to return in results | | skip | `number` | Number of transactions to skip before collection results | ## [Enums](#enums) ### [WALLET\_TRANSACTION\_TYPE](#wallet_transaction_type) | Value | Description | |----------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------| | ACH\_REVERSAL | When an ACH payment is returned, funds are either returned or taken from the wallet balance | | CARD\_PAYMENT | A payment that was made from a card | | CASH\_OUT | Transfer of funds out of a wallet to the account’s bank | | DISPUTE | When a customer disputes a charge, the disputed amount is debited from the wallet | | DISPUTE\_REVERSAL | If a dispute is won by a merchant, funds will be credited back to their wallet | | FACILITATOR\_FEE | Fee earned on a transfer | | ISSUING\_REFUND | A refund on a purchase from a Moov issued card | | ISSUING\_TRANSACTION | An authorized purchase from a Moov issued card | | ISSUING\_TRANSACTION\_ADJUSTMENT | If an authorized purchase is captured for more or less than the original authorization amount, an adjustment will be made to reflect the difference | | ISSUING\_AUTH\_RELEASE | Any funds that were not captured from an authorized purchase from a Moov issued card will be released | | PAYMENT | An ACH payment from a bank to the account’s wallet | | PAYOUT | A payment from a wallet to another accounts bank | | REFUND | When a refund is initiated, the requested refund amount is debited from the wallet | | REFUND\_FAILURE | To account for refund failures, a credit will be made back into the wallet | | TOP\_UP | Transfer of funds into a wallet from the account’s bank | | WALLET\_TRANSFER | Funds that move between Moov wallets | ### [WALLET\_TRANSACTION\_SOURCE\_TYPE](#wallet_transaction_source_type) | Value | Description | |----------------------|------------------------------------------------| | TRANSFER | Transaction was part of a transfer | | DISPUTE | Transaction was part of a dispute | | ISSUING\_TRANSACTION | Transaction was part of an issuing transaction | ### [WALLET\_TRANSACTION\_STATUS](#wallet_transaction_status) | Value | Description | |-----------|-------------------------------| | PENDING | Transaction has not completed | | COMPLETED | Transaction has completed | | FAILED | Transaction failed | --- URL: https://docs.moov.io/moovjs/transfers/ --- # Transfers Use the API or the Dashboard to facilitate transfers with Moov. ## [API](#api) In order to make a transfer with Moov, you'll need to use the transfers `POST` [endpoint](/api/money-movement/transfers/create/) directly. The [payments](/guides/money-movement/accept-payments/) section of our documentation has more details on how funds move across our platform, as well as information on topics such as payment methods, ACH, card transfers, and fees. ## [Dashboard](#dashboard) If you'd like to use the Moov Dashboard for transfers, see the [Dashboard transfer](/guides/dashboard/transfers/) guide. --- URL: https://docs.moov.io/sdks/dotnet/ --- # .NET SDK --- URL: https://docs.moov.io/sdks/drops/ --- # Moov Drops --- URL: https://docs.moov.io/sdks/go/ --- # Go SDK --- URL: https://docs.moov.io/sdks/hosted-onboarding/ --- # Hosted onboarding --- URL: https://docs.moov.io/sdks/ --- # SDKs The official client libraries for interacting with the Moov API. If you run into any issues with an SDK and a specific API version, please [report it](https://support.moov.io/). --- URL: https://docs.moov.io/sdks/java/ --- # Java SDK --- URL: https://docs.moov.io/sdks/moovjs/ --- # Moov.js --- URL: https://docs.moov.io/sdks/payment-links/ --- # Payment links --- URL: https://docs.moov.io/sdks/php/ --- # PHP SDK --- URL: https://docs.moov.io/sdks/python/ --- # Python SDK --- URL: https://docs.moov.io/sdks/ruby/ --- # Ruby SDK --- URL: https://docs.moov.io/sdks/tap-to-pay-android/ --- # Tap to Pay on Android SDK --- URL: https://docs.moov.io/sdks/tap-to-pay-iphone/ --- # Tap to Pay on iPhone SDK --- URL: https://docs.moov.io/sdks/typescript/ --- # TypeScript SDK --- URL: https://docs.moov.io/use-cases/construction/ --- # Construction Moov is your single vendor for payment process efficiency, faster cash access, and simplified compliance. This guide focuses on the quickest and easiest way to get started with the features of Moov we think you'll find most useful for the construction industry. Verify bank accounts instantly, facilitate multi-party payouts with Moov wallets, and send instant transfers with push to card and RTP payments. Moov offers a variety of integration options to get started. Use [Drops](/moovjs/drops/) or the [Dashboard](https://dashboard.moov.io/signin) UIs for a low to no-code solution, or choose the [API](/api/) or one of many [SDKs](/sdks/) for more complex integrations. For the purposes of this guide, we'll provide Dashboard and API examples. ## [Verify bank accounts instantly](#verify-bank-accounts-instantly) After you've [onboarded](/guides/dashboard/accounts/onboarding-links/) contractors, you can [link bank accounts](/guides/dashboard/settings/payment-methods/). Verifying linked bank accounts reduces fraud. You can initiate micro-deposit verification to confirm ownership of accounts. Banks that support instant verification will verify micro-deposits in a single session, in real time, via RTP. If a bank doesn't support instant verification, same-day ACH is used as a fallback. [Get IDs](#tab-164827953-0-0) [Initiate instant micro-deposits](#tab-164827953-0-1) The easiest way to find a contractor's account ID and bank account ID is in the Dashboard. Search for an account and click on it to open their profile. The account ID can be found under **Business details** and the bank account ID can be found by clicking on the linked bank account under **Payment methods**. ![Account ID in the Dashboard](../../guides/shared-images/account-overview-id.png) You can also retrieve a [list](/api/moov-accounts/accounts/list/) of accounts and their IDs with the API. ```zsh curl -X GET "https://api.moov.io/accounts" \ -H "Authorization: Bearer {token}" ``` Once you have an account ID, you can retrieve a [list](/api/sources/bank-accounts/list/) of bank account IDs with the API. ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/bank-accounts" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ ``` Use the IDs you've retrieved for an account to initiate [instant micro deposit verification](/api/sources/bank-accounts/initiate-bank-account-verification/) through the API. ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/bank-accounts/{bankAccountID}/verify" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ ``` If the bank supports instant verification, the response will show `instant` as the verification method. If instant verification is not supported, the verification method will be `ach`. ```zsh { "status": "new", "verificationMethod": "instant" } ``` Read more on bank account verification in our documentation: [Bank accounts](/guides/sources/bank-accounts/) [Instant verification](/guides/sources/bank-accounts/verification/instant-micro-deposit/) ## [Facilitate multi-party payments](#facilitate-multi-party-payments) With Moov wallets, you can facilitate complex money movement scenarios such as multi-party payouts where a contractor is paying out subcontractors. The wallet ledger tracks every debit and credit, automatically correlating transactions to the original payment method. Transfers between wallets are instant - send funds instantly from your wallet to a contractor's wallet so they can make timely payouts to their subcontractors. [Dashboard](#tab-632978451-0-0) [cURL](#tab-632978451-0-1) To create a wallet to wallet transfer in the Dashboard, click the **New transfer** button, select **Payout** and enter the source wallet and destination wallet. ![Transfer detail view in Moov Dashboard](../../guides/shared-images/transfers-view.png) To create a wallet to wallet transfer with the [API](/api/money-movement/transfers/create/), send the source wallet and destination wallet in the request. ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/transfers" \ -H "Authorization: Bearer {token}" \ -H "X-Idempotency-Key: UUID" \ -H "X-Wait-For: rail-response" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "amount": { "value": 100000, "currency": "USD" }, "source": { "paymentMethodID": "your-wallet-ID" }, "destination": { "paymentMethodID": "contractor-wallet-ID" }, "description": "Optional transaction description." }'\ ``` [Wallets](/guides/money-movement/wallets/) [Send funds](/guides/money-movement/send-payments/send-funds/) ## [Set up transfer groups](#set-up-transfer-groups) Transfer groups provide a way to associate multiple transfers together by a shared ID of the parent transfer. Transfer groups make the final beneficiary in a chain of transfers aware of incoming funds before they land in their account. This also gives you more control over the flow of funds, making reporting and preserving the context of the original transfer easier. [Get transfer ID](#tab-986751324-0-0) [Create a transfer](#tab-986751324-0-1) You'll need to retrieve the ID of what you want to be the parent transfer before you can create a transfer group. The easiest way to do this is in the Dashboard. Search for the transfer and click on it to open the transfer page. The transfer ID is listed at the top and you can copy it to your clipboard. ![Transfer ID in the Dashboard](../../guides/shared-images/account-overview-id.png) You an also retrieve a [list of transfers](/api/money-movement/transfers/list/) with the API which will return the `transferID`. ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/transfers" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ ``` To create a transfer group, provide a `transferID` as the source when [creating a transfer](/api/money-movement/transfers/create/) with the API. ``` 1 2 3 4 5 6 7 8 9 10 11 12 13 ``` ```json { "amount": { "value": 100, "currency": "USD" }, "source": { "paymentMethodID": "transferID" }, "destination": { "paymentMethodID": "string" }, "description": "Optional transaction description." } ``` Read more about transfer groups in our documentation: [Transfer groups](/guides/money-movement/transfer-groups/) ## [Send instant payments](#send-instant-payments) Eligible linked bank accounts and cards have access to instant [RTP](/guides/money-movement/send-payments/rtp/) and [push to card](/guides/money-movement/send-payments/push-to-card/) payments respectively. ![Standard RTP funds flow diagram](./images/instant-funds-flow-light.png) ### [Check eligibility](#check-eligibility) Before you create a transfer, you can check if the bank account or card linked to a contractor's account is eligible for instant RTP or push to card payments. [Push to card](#tab-942817536-1-0) [RTP](#tab-942817536-1-1) Use the cards `GET` [endpoint](/api/sources/cards/get/) to check if a card is eligible for push to card. You can find the account ID and card ID in the Dashboard using the same methods [described above](#verify-bank-accounts-instantly) in the Get IDs tab. ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/cards" \ -H 'Authorization: Bearer {token}' \ ``` In the response, the `domesticPushtoCard` field will describe the push to card timing that is available for the card (if supported): | Timing | Description | |-----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `fast-funds` | Funds will be available to the destination within 30 minutes or less of the authorization. | | `standard` | Fast funds is not supported on this card. Transfer will follow standard card settlement [timing](/guides/money-movement/accept-payments/card-acceptance/timing/). | | `not-supported` | This card is ineligible for push-to-card payments. Contact your issuer for more details. | | `unknown` | Eligibility has not been checked or is unknown. | A push transfer can be created when the source is a pre-funded Moov wallet and the destination is a recipient with a linked card and the `transfers` [capability](/guides/accounts/capabilities/). When a bank account is linked, Moov checks its eligibility to receive payments on the RTP network and creates the `rtp-credit` payment method automatically. To use RTP, accounts must have the `send-funds.instant-bank` and `wallet.balance` [capabilities](/guides/accounts/capabilities/) enabled. Read more about instant payments in our documentation: [Push to card](/guides/money-movement/send-payments/push-to-card/) [RTP](/guides/money-movement/send-payments/rtp/) ## [Set metadata](#set-metadata) You can store free-form metadata on transfers, such as invoice numbers or correlation IDs. You can use this metadata to reconcile and correlate payments in your system. In addition to setting metadata when creating a transfer, you can also update metadata after a transfer has initiated or completed. [Dashboard](#tab-645397182-0-0) [cURL](#tab-645397182-0-1) When creating a transfer in the Dashboard, open the **Advanced settings** to enter metadata. ![Metadata](../../guides/shared-images/metadata.png) When creating a transfer in the API, enter the metadata you want in your request. ```zsh ... "metadata": { "property1": "string", "property2": "string" }, ... ``` Read more about metadata in our API documentation: [Update metadata](/api/money-movement/transfers/patch/) ## [Other resources](#other-resources) [Test mode](/guides/get-started/test-mode/) [Dashboard](/guides/dashboard/) [Webhooks](/guides/webhooks/) [API](/api/) [SDKs](/sdks/) --- URL: https://docs.moov.io/use-cases/digital-banking/ --- # Digital banking Moov is your single vendor for digital banking with easy payments, real-time insights, and tools to grow deposits. This guide focuses on the quickest and easiest way to get started with the features of Moov we think you'll find most useful for the digital banking industry. Quickly onboard and fund accounts, configure interchange incentives, and facilitate simple loan repayments with payment links. Moov offers a variety of integration options to get started. Use [Drops](/moovjs/drops/) or the [Dashboard](https://dashboard.moov.io/signin) UIs for a low to no-code solution, or choose the [API](/api/) or one of many [SDKs](/sdks/) for more complex integrations. For the purposes of this guide, we'll provide Dashboard and API examples. ## [Onboard accounts](#onboard-accounts) As you move through the onboarding process to create Moov accounts, some data is required while other data is optional. To view our full onboarding guides, visit the [Dashboard](/guides/dashboard/accounts/onboarding-links/) or main [onboarding](/guides/accounts/hosted-onboarding/) guides. | Onboarding data | Required | |----------------------|----------| | Capabilities | **✓** | | Fee plan | **✓** | | Scopes | **✓** | | Return URL | **×** | | Terms of service URL | **×** | | Prefilled data | **×** | **Capabilities** determine what each Moov account can do, such as receiving transfers, or sending money to others. For risk and fraud protection purposes, we require detailed information when requesting capabilities. For example, we'll request more details if an account wants to collect funds than we would for an account receiving funds. - [Transfers](/guides/accounts/capabilities/enablement/#transfers): Authorize debit transfers - [Wallet](/guides/accounts/capabilities/enablement/#wallet): Store funds with Moov - [Send funds](/guides/accounts/capabilities/enablement/#send-funds): Send funds to another account - [Collect funds](/guides/accounts/capabilities/enablement/#collect-funds) (Business accounts only): Collect funds from another account **Pricing & fee plans** can be assigned to one merchant or reused for many merchants. Merchants must agree to and accept the fee plan before it can go into effect. Moov offers two types of plans: - **Cost plus:** With a cost plus plan, card networks’ interchange fees and Moov’s processing markup are passed along to the merchant. Cost plus plans are beneficial for merchants with a high and varied transaction volume that prefer to have more control over fees. Fees are broken down into a more digestible and transparent format. - **Flat rate:** With a flat rate plan, you can lump all the processing fees together with a flat rate customized for each merchant. Flat plans are beneficial for merchants with a low transaction volume that prefer a predictable solution over lowering cost as much as possible. **Scopes** are used to determine what can be done with the account once it's onboarded. For example, the `/accounts.read` scope provides access to view all connected user accounts and the `/accounts/{accountID}/files.read` scope provides access to view or upload files associated with a Moov account. Read more on required data in our documentation: [Capabilities](/guides/accounts/capabilities/) [Fee plans](/guides/fee-plans/) [Scopes](/api/authentication/scopes/) [Dashboard](#tab-138459276-1-0) [cURL](#tab-138459276-1-1) Moov will send the [terms of service platform agreement](/guides/accounts/requirements/platform-agreement/) as part of the onboarding process through the Dashboard. Everyone with a Moov account must agree to and accept the terms of service before using Moov. The following clip demonstrates how to create a new onboarding link in the Dashboard: You'll need to generate and send a terms of service platform agreement as part of the onboarding process. Everyone with a Moov account must agree to and accept the terms of service before using Moov. If you're using the API, an SDK, or Moov Drops to onboard, see the [terms of service platform agreement](/guides/accounts/requirements/platform-agreement/) guide for more information and instructions. The following is a sample request to [create an account](/api/moov-accounts/accounts/create/) with all available data: ```zsh curl --X POST "https://api.moov.io/onboarding-invites" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "returnURL": "https://mycompany.com/account", "termsOfServiceURL": "https://mycompany.com/terms-of-service", "capabilities": [ "transfers", "wallet" ], "feePlanCodes": [ "merchant-direct" ], "scopes": [ "accounts.read" ], "prefill": { "mode": "production", "accountType": "individual", "profile": { "individual": { "email": "julesjacksonyoga@classbooker.dev", "name": { "firstName": "Jules", "lastName": "Jackson" } } }, "metadata": { "property1": "string", "property2": "string" }, "termsOfService": { "token": "kgT1uxoMAk7QKuyJcmQE8nqW_HjpyuXBabiXPi6T83fUKRJkA3dsFID6fzitMpm2qrOh4" }, "foreignID": "4528aba-b9a1-11eb-8529-0242ac13003", "settings": { "cardPayment": { "statementDescriptor": "Jules Jackson payment" }, "achPayment": { "companyName": "Jules Jackson payment" } } } }'\ ``` Read more about accounts and onboarding in our documentation: [Accounts](/guides/accounts/) [Onboarding links](/guides/dashboard/accounts/onboarding-links/) ## [Use form shortening](#use-form-shortening) Use the [enrichment API](/api/enrichment/form-shortening/) to find publicly available information to autofill form fields based on an email address. With the enrichment API you can: - Autocomplete addresses - Get avatars - Look up bank by routing number - List industries - Enrich business profile If you're using a Moov.js integration, you can use Moov's pre-built Drops UI for form shortening. Read more in the Moov.js documentation: [Moov.js](/moovjs/) [Composable Drops](/moovjs/drops/composable-drops/) ## [Set up payment methods](#set-up-payment-methods) Moov enables customers to instantly send money from a Moov wallet. After an account is linked to Moov, we'll check its eligibility to send and receive payments on the RTP, ACH and card networks and we'll automatically create the payment methods for the account. Every account that meets the wallet capability [requirements](/guides/accounts/capabilities/reference/#account-requirements) will automatically have the wallet enabled. | Source Payment method | Details | Destination | Required capabilities | |-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------|----------------------------|----------------------------------------| | `card-payment` | Initiate a [payment](/guides/money-movement/accept-payments/card-acceptance/) from a linked credit or debit card | Wallet | `transfers`, `wallet` | | `pull-from-card` | Instantly [pull funds](/guides/money-movement/accept-payments/pull-from-card/) from a supported debit or prepaid card to an external account | Wallet | `transfers`, `wallet`, `collect-funds` | | `ach-debit-fund` | Fund [payouts](/guides/money-movement/send-payments/send-funds/) or add funds from a linked bank account | Wallet | `transfers`, `wallet`, `send-funds` | | `ach-debit-collect` | [Pull funds](/guides/money-movement/accept-payments/ach/) for bill payment, direct debit, or e-check type use-cases | Bank account | `transfers`, `collect-funds` | | `moov-wallet` | Fund [payouts](/guides/money-movement/send-payments/send-funds/) or withdraw funds from the Moov platform | Wallet, Bank account, Card | `transfers`, `wallet` | | Destination Payment method | Details | Source | Required capabilities | |----------------------------|-----------------------------------------------------------------------------------------------------------------|----------------------------|----------------------------------------------------------| | `rtp-credit` | [Disburse funds](/guides/money-movement/send-payments/rtp/) to a linked bank account in near real time | Wallet | `send-funds.instant-bank`, `wallet.balance` | | `push-to-card` | Instantly [push funds](/guides/money-movement/send-payments/push-to-card/) to a supported debit or prepaid card | Card | `transfers`, `wallet.balance`, `send-funds.push-to-card` | | `ach-credit-standard` | Disburse funds to a linked bank account | Bank account | `transfers`, `collect-funds.ach` | | `ach-credit-same-day` | Disburse funds to a linked bank account using same-day processing | Bank account | `transfers`, `collect-funds.ach` | | `moov-wallet` | Fund [payouts](/guides/money-movement/send-payments/send-funds/) or withdraw funds from the Moov platform | Wallet, Bank account, Card | `transfers`, `wallet.balance` | ### [Bank accounts](#bank-accounts) Link a bank account through the Dashboard or API for access to instant [RTP](/guides/money-movement/send-payments/rtp/) and fast [ACH](/guides/money-movement/accept-payments/ach/) payment methods. [Dashboard](#tab-183492576-1-0) [cURL](#tab-183492576-1-1) [Link a bank account](/api/sources/bank-accounts/create/) through the API. ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/bank-accounts" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "account": { "accountNumber": "0004321567000", "bankAccountType": "checking", "holderName": "Jules Jackson", "holderType": "individual", "routingNumber": "123456789" } }'\ ``` ### [Cards](#cards) [Link a card](/api/sources/cards/create/) through the API for access to the instant [pull](/guides/money-movement/accept-payments/pull-from-card/) and [push](/guides/money-movement/send-payments/push-to-card/) card payment methods. [Cards](#tab-417386529-2-0) ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/cards" \ -H "Authorization: Bearer {token}" \ -H "X-Wait-For: payment-method" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "billingAddress": { "addressLine1": "123 Main Street", "city": "Denver", "stateOrProvince": "CO", "postalCode": "80301", "country": "US" }, "cardCvv": "123", "cardNumber": "4111111111111111", "expiration": { "month": "01", "year": "28" }, "holderName": "Jules Jackson" }'\ ``` Read more about payment methods in our documentation: [Payment methods](/guides/money-movement/payment-methods/) [Funding sources](/guides/sources/) ## [Fund accounts](#fund-accounts) Customers can fund a new account with an existing external account. [Fund an account](#tab-871645239-1-0) Create a basic transfer to fund an account (as shown in the example below). Customers can send funds from an external account to fund their new bank account. The source will be the external account, and the destination will be the new account. The source `paymentMethodID` is taken from the payment method type, such as `pull-from-card` or `ach-debit-fund`. The destination `paymentMethodID` is taken from the payment method type, such as `moov-wallet` or `ach-credit-same-day`. To find what payment method types are available to an account and retrieve the associated `paymentMethodID`, use the payment method `GET` [endpoint](/api/sources/payment-methods/list/). ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/transfers" \ -H "Authorization: Bearer {token}" \ -H "X-Idempotency-Key: UUID" \ -H "X-Wait-For: rail-response" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "source": { "paymentMethodID": "string" }, "destination": { "paymentMethodID": "string" }, "amount": { "value": 300000, // $3000.00 "currency": "USD" }, "description": "New account initial funding deposit" }'\ ``` []()[]() ## [Configure interchange incentives](#configure-interchange-incentives) To have card payments qualify for debt repayment interchange incentives, business accounts must be configured with Moov and registered with Visa, Mastercard, and Discover. After configuration and registration, eligible merchants can receive lower interchange fees for qualified loan repayment transactions. When you link a card, you can check the response object to see if it qualifies. Qualifying cards will have card type `debit` or `prepaid`. ```zsh { "cardType": "debit" } ``` Payments made with a debit or prepaid card will automatically be marked as debt repayment in the request to the card network. To see what debt repayment program a transaction qualifies for, use the retrieve transfer `GET` [endpoint](/api/money-movement/transfers/get/) and check the fee program. ```zsh { "source": { "cardDetails": { "feeProgram": "Debt Repayment 2" } } } ``` Read more about interchange incentives in our debt repayment documentation: [Debt repayment](/guides/money-movement/accept-payments/card-acceptance/debt-repayment/) ## [Send payment links](#send-payment-links) Create and send customers payment links and make paying back loans simple. Create a payment link and share it with your customers via email, SMS, or social media. When customers click on a link, they can pay using a credit card, debit card, or bank account. A payment link can be sent as a URL or QR code. [Dashboard](#tab-159247368-0-0) [cURL](#tab-159247368-0-1) ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/payment-links" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "accountID": "c197cd40-7745-4413-8f3b-ec962d1b5225", "merchantPaymentMethodID": "3afc7533-7095-43bb-b21a-5c4dc5568451", "amount": { "currency": "USD", "value": 1000 }, "maxUses": 0, "expiresOn": "2025-08-24T14:15:22Z", "display": { "title": "string", "description": "string", "callToAction": "pay" }, "customer": { "requireAddress": true, "requirePhone": true, "metadata": { "property1": "string", "property2": "string" } }, "payment": { "allowedMethods": [ "apple-pay", "card-payment", "ach-debit-collect" ], "cardDetails": { "dynamicDescriptor": "Customer payment 11-12" }, "achDetails": { "companyEntryDescription": "Monthly loan repayment", "originatingCompanyName": "Jules Jackson LLC" } } }'\ ``` Once a payment link has been created in the Dashboard, you'll be presented with a URL and QR code to copy and send. If you're using the API, the payment link `code` will be in the response. You can append the code to the payment link URL `https://moov.link/` and send it to customers. You can also use the payment link `GET` [endpoint](/api/money-movement/payment-links/get-qrcode/) to retrieve the QR code. [Dashboard](#tab-931562784-1-0) [cURL](#tab-931562784-1-1) ![Sharable link and QR code](../../guides/shared-images/payment-link-qr.png) The following is an example response when creating a payment link. The payment link URL with the code would be `https://moov.link/3QLHtONjd5`. ```zsh { "amount": { "currency": "USD", "value": 100000 }, "code": "3QLHtONjd5", "createdOn": "2025-01-09T17:09:13.33Z", "customer": { "requirePhone": true }, "display": { "callToAction": "pay", "description": "This is an example payment link.", "title": "Example Payment Link" }, "link": "https://moov.link/3QLHtONjd5", "merchantAccountID": "34233b72-780c-4e0e-8b08-cbbe1bc878f8", "merchantPaymentMethodID": "4c4e7f8e-81f4-4f3d-8f6f-6f6e7f8e4c4e", "mode": "sandbox", "partnerAccountID": "d290f1ee-6c54-4b01-90e6-d701748f0851", "payment": { "allowedMethods": [ "card-payment", "ach-debit-collect" ] }, "status": "active", "updatedOn": "2025-01-09T17:09:13.33Z", "uses": 0 } ``` Read more about payments links in our documentation: [Dashboard payment links](/guides/dashboard/transfers/payment-links/) [Payment links](/guides/money-movement/payment-links/) [Payment link API](/api/money-movement/payment-links/) ## [Manage accounts](#manage-accounts) The easiest way to manage accounts is in the Dashboard. Within the Dashboard you can view all accounts, create new accounts, upload documents, update fee plans, view transfers, and more. [Accounts in the Dashboard](#tab-314985672-0-0) Read more about managing accounts in the Dashboard and API: [Accounts](/guides/dashboard/accounts/) [Accounts API](/api/moov-accounts/accounts/) ## [Other resources](#other-resources) [Test mode](/guides/get-started/test-mode/) [Dashboard](/guides/dashboard/) [Webhooks](/guides/webhooks/) [API](/api/) [SDKs](/sdks/) --- URL: https://docs.moov.io/use-cases/fundraising/ --- # Fundraising platforms Moov is your single vendor for fundraising with flexible payment options and easy funds management. This guide focuses on the quickest and easiest way to get started with the features of Moov we think you'll find most useful for the fundraising industry. Create a platform with recurring donations and flexible payment options like payment links and QR codes. Moov offers a variety of integration options to get started. Use [Drops](/moovjs/drops/) or the [Dashboard](https://dashboard.moov.io/signin) UIs for a low to no-code solution, or choose the [API](/api/) or one of many [SDKs](/sdks/) for more complex integrations. For the purposes of this guide, we'll provide Dashboard and API examples. ## [Save a card on file](#save-a-card-on-file) When you link a card to your platform, you can choose to save it as a card on file for future use. This makes future donations easier, and also gives you access to Moov's card account updater service (CAU). CAU automatically updates payment information when a card has expired or been replaced, eliminating the need to contact donors to obtain new information. When you [link a card](/api/sources/cards/create/) with the API, just set `cardOnFile` to true. [cURL](#tab-579418632-0-0) ``` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ``` ```json { "billingAddress": { "addressLine1": "123 Main Street", "city": "Denver", "stateOrProvince": "CO", "postalCode": "80301", "country": "US" }, "cardCvv": "123", "cardNumber": "4111111111111111", "expiration": { "month": "01", "year": "28" }, "holderName": "Jules Jackson", "cardOnFile": true } ``` Read more about card payments in our documentation: [Card payments](/guides/sources/cards/accept-card-payments/) [Card account updater](/guides/sources/cards/card-account-updater/) ## [Explore payment options](#explore-payment-options) While Moov offers a variety of payment options, payment links are the fastest way to engage donors. Send a URL or have donors scan a QR code for quick payment. Additionally, when creating payments, you can create transfer groups. Transfer groups provide a way to associate multiple transfers together by a shared ID of the parent transfer. Transfer groups make the final beneficiary in a chain of transfers aware of incoming funds before they land in their account. [Payment links & QR codes](#tab-659214378-0-0) [Transfer groups](#tab-659214378-0-1) Make donations simple by creating payment links for donors. Payment links can be shared via email, SMS, or social media. When donors click on a link, they can pay using a credit card, debit card, or bank account. A payment link can be sent as a URL or QR code. The clip below shows how to create a payment link in the Dashboard. You can also [create payment links](/api/money-movement/payment-links/create/) with the API. To create a transfer group, just provide the `transferID` of the parent transfer as the source when [creating a transfer](/api/money-movement/transfers/create/) with the API. ``` 1 2 3 4 5 6 7 8 9 10 11 12 13 ``` ```json { "amount": { "value": 100, "currency": "USD" }, "source": { "paymentMethodID": "transferID" }, "destination": { "paymentMethodID": "string" }, "description": "Optional transaction description." } ``` Read more about payment options in our documentation: [Payment links](/guides/dashboard/transfers/payment-links/) [Transfer groups](/guides/money-movement/transfer-groups/) ## [Set up recurring donations](#set-up-recurring-donations) Recurring donations collect from donors on a regular basis, without the need for a donor to initiate a new payment each time. An initial payment is required before establishing a recurring schedule. Unscheduled payments which occur outside the set schedule can also be processed. Use the [transfers API](/api/money-movement/transfers/create/) to set up recurring payments. [Initial payment](#tab-789632415-0-0) [Recurring payments](#tab-789632415-0-1) Before setting up a recurring payment, an initial first recurring payment must be sent with a `first-recurring` transaction source. ```zsh { "amount": { "value": 500, "currency": "USD" }, "source": { "paymentMethodID": "ec7e1848-dc80-4ab0-8827-dd7fc0737b43", "cardDetails": { "transactionSource": "first-recurring" }, "destination": {} } } ``` Once an initial recurring payment has been processed, a recurring payments schedule can be set using the `recurring` transaction source. ```zsh { "amount": { "value": 500, "currency": "USD" }, "source": { "paymentMethodID": "ec7e1848-dc80-4ab0-8827-dd7fc0737b43", "cardDetails": { "transactionSource": "recurring" }, "destination": {} } } ``` Read more about recurring payments in our documentation: [Recurring payments](/guides/money-movement/accept-payments/card-acceptance/recurring-payments/) ## [Set up automated payouts](#set-up-automated-payouts) Your Moov wallet gives you access to automatic payouts through sweeps. A sweep automatically initiates daily transfers to external bank accounts on a set schedule. You can choose to maintain a specific balance in your wallet to cover day-to-day operations, or to prevent a negative balance from refunds, disputes, and fees. [Dashboard](#tab-937256418-0-0) [cURL](#tab-937256418-0-1) Navigate to **Settings** in the Dashboard to configure sweeps and set a minimum balance. Configure sweeps and set a minimum balance with the [accounts API](/api/money-movement/sweeps/create-config/). ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/sweep-configs" \ -H 'Authorization: Bearer {token}' \ --data-raw '{ "walletID": "string", "status": "enabled", "pushPaymentMethodID": "string", "pullPaymentMethodID":"string", "minimumBalance": "150.00" }'\ ``` Read more about sweeps in our documentation: [Sweeps](/guides/money-movement/wallets/sweeps/) ## [Access your data reports](#access-your-data-reports) Data sync is a no-code feature that sends your Moov account data to Google BigQuery, allowing you to access your payment data in your own data warehouse. Features of data sync include: - Access to near-real-time payments data in your data warehouse - No ETL required - Access and analyze data in BI tools connected to BigQuery, like Looker & Tableau - Granular control over access You'll need to [contact Moov](https://support.moov.io/) to set up a private data exchange with Google Analytics Hub. ## [Other resources](#other-resources) [Test mode](/guides/get-started/test-mode/) [Dashboard](/guides/dashboard/) [Webhooks](/guides/webhooks/) [API](/api/) [SDKs](/sdks/) --- URL: https://docs.moov.io/use-cases/ --- # Use case quick start Get started with Moov's features that matter most to your business and merchant's needs. Select an industry to view a quick start guide that showcases features we've built to solve industry specific problems. We've streamlined complex and inefficient payment processes, built customer data solutions for compliance headaches, and turned manual workflows into feature integrations. --- URL: https://docs.moov.io/use-cases/loan-servicing/ --- # Loan servicing Moov is your single vendor for loan disbursement, payment management, automated compliance, and real-time insights. This guide focuses on the quickest and easiest way to get started with the features of Moov we think you'll find most useful for the loan servicing industry. Quickly onboard accounts, configure interchange incentives, set up recurring payments, and manage borrowers. Moov offers a variety of integration options to get started. Use [Drops](/moovjs/drops/) or the [Dashboard](https://dashboard.moov.io/signin) UIs for a low to no-code solution, or choose the [API](/api/) or one of many [SDKs](/sdks/) for more complex integrations. For the purposes of this guide, we'll provide Dashboard and API examples. ## [Onboard borrowers](#onboard-borrowers) As you move through the onboarding process to create Moov accounts, some data is required while other data is optional. To view our full onboarding guides, visit the [Dashboard](/guides/dashboard/accounts/onboarding-links/) or main [onboarding](/guides/accounts/hosted-onboarding/) guides. | Onboarding data | Required | |----------------------|----------| | Capabilities | **✓** | | Fee plan | **✓** | | Scopes | **✓** | | Return URL | **×** | | Terms of service URL | **×** | | Prefilled data | **×** | **Capabilities** determine what each Moov account can do, such as receiving transfers, or sending money to others. For risk and fraud protection purposes, we require detailed information when requesting capabilities. For example, we'll request more details if an account wants to collect funds than we would for an account receiving funds. - [Transfers](/guides/accounts/capabilities/enablement/#transfers): Authorize debit transfers - [Wallet](/guides/accounts/capabilities/enablement/#wallet): Store funds with Moov - [Send funds](/guides/accounts/capabilities/enablement/#send-funds): Send funds to another account - [Collect funds](/guides/accounts/capabilities/enablement/#collect-funds) (Business accounts only): Collect funds from another account **Pricing & fee plans** can be assigned to one merchant or reused for many merchants. Merchants must agree to and accept the fee plan before it can go into effect. Moov offers two types of plans: - **Cost plus:** With a cost plus plan, card networks’ interchange fees and Moov’s processing markup are passed along to the merchant. Cost plus plans are beneficial for merchants with a high and varied transaction volume that prefer to have more control over fees. Fees are broken down into a more digestible and transparent format. - **Flat rate:** With a flat rate plan, you can lump all the processing fees together with a flat rate customized for each merchant. Flat plans are beneficial for merchants with a low transaction volume that prefer a predictable solution over lowering cost as much as possible. **Scopes** are used to determine what can be done with the account once it's onboarded. For example, the `/accounts.read` scope provides access to view all connected user accounts and the `/accounts/{accountID}/files.read` scope provides access to view or upload files associated with a Moov account. Read more on required data in our documentation: [Capabilities](/guides/accounts/capabilities/) [Fee plans](/guides/fee-plans/) [Scopes](/api/authentication/scopes/) [Dashboard](#tab-738416592-1-0) [cURL](#tab-738416592-1-1) Moov will send the [terms of service platform agreement](/guides/accounts/requirements/platform-agreement/) as part of the onboarding process through the Dashboard. Everyone with a Moov account must agree to and accept the terms of service before using Moov. The following clip demonstrates how to create a new onboarding link in the Dashboard: You'll need to generate and send a terms of service platform agreement as part of the onboarding process. Everyone with a Moov account must agree to and accept the terms of service before using Moov. If you're using the API, an SDK, or Moov Drops to onboard, see the [terms of service platform agreement](/guides/accounts/requirements/platform-agreement/) guide for more information and instructions. The following is a sample request to create an [onboarding invite](/api/moov-accounts/onboarding/post/) with all available data: ```zsh curl --X POST "https://api.moov.io/onboarding-invites" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "returnURL": "https://mycompany.com/account", "termsOfServiceURL": "https://mycompany.com/terms-of-service", "scopes": [ "accounts.read" ], "capabilities": [ "transfers", "wallet.balance" ], "feePlanCodes": [ "merchant-direct" ], "prefill": { "mode": "production", "accountType": "business", "profile": { "business": { "legalBusinessName": "LBM Lenders LLC", "doingBusinessAs": "LBM Lenders", "businessType": "llc", "address": { "addressLine1": "123 Main Street", "addressLine2": "Apt 302", "city": "Boulder", "stateOrProvince": "CO", "postalCode": "80301", "country": "US" }, "phone": { "number": "8185551212", "countryCode": "1" }, "email": "amanda@classbooker.dev", "website": "www.lbmlenders.com", "description": "Financial institution for personal lending", "taxID": { "ein": { "number": "123-45-6789" } }, "industryCodes": { "naics": "522291", "sic": "6141", "mcc": "6141" }, "primaryRegulator": "FDIC" } }, "metadata": { "property1": "string", "property2": "string" }, "termsOfService": { "token": "kgT1uxoMAk7QKuyJcmQE8nqW_HjpyuXBabiXPi6T83fUKRJkA3dsFID6fzitMpm2qrOh4" }, "foreignID": "4528aba-b9a1-11eb-8529-0242ac13003", "customerSupport": { "phone": { "number": "8185551212", "countryCode": "1" }, "email": "amanda@classbooker.dev", "address": { "addressLine1": "123 Main Street", "addressLine2": "Apt 302", "city": "Boulder", "stateOrProvince": "CO", "postalCode": "80301", "country": "US" }, "website": "www.lbmlenders.com" }, "settings": { "cardPayment": { "statementDescriptor": "LBM Lenders" }, "achPayment": { "companyName": "LBM Lenders" } } } }'\ ``` Read more about accounts and onboarding in our documentation: [Accounts](/guides/accounts/) [Onboarding links](/guides/dashboard/accounts/onboarding-links/) ## [Use form shortening](#use-form-shortening) Use the [enrichment API](/api/enrichment/form-shortening/) to find publicly available information to autofill form fields based on an email address. With the enrichment API you can: - Autocomplete addresses - Get avatars - Look up bank by routing number - List industries - Enrich business profile If you're using a Moov.js integration, you can use Moov's pre-built Drops UI for form shortening. Read more in the Moov.js documentation: [Moov.js](/moovjs/) [Composable Drops](/moovjs/drops/composable-drops/) ## [Set up payment methods](#set-up-payment-methods) Moov enables lenders to instantly send money to borrowers from a Moov wallet. After an account is linked to Moov, we'll check its eligibility to send and receive payments on the RTP, ACH and card networks and we'll automatically create the payment methods for the account. Every account that meets the wallet capability [requirements](/guides/accounts/capabilities/reference/#account-requirements) will automatically have the wallet enabled. | Source Payment method | Details | Destination | Required capabilities | |-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------|----------------------------|----------------------------------------| | `card-payment` | Initiate a [payment](/guides/money-movement/accept-payments/card-acceptance/) from a linked credit or debit card | Wallet | `transfers`, `wallet` | | `pull-from-card` | Instantly [pull funds](/guides/money-movement/accept-payments/pull-from-card/) from a supported debit or prepaid card to an external account | Wallet | `transfers`, `wallet`, `collect-funds` | | `ach-debit-fund` | Fund [payouts](/guides/money-movement/send-payments/send-funds/) or add funds from a linked bank account | Wallet | `transfers`, `wallet`, `send-funds` | | `ach-debit-collect` | [Pull funds](/guides/money-movement/accept-payments/ach/) for bill payment, direct debit, or e-check type use-cases | Bank account | `transfers`, `collect-funds` | | `moov-wallet` | Fund [payouts](/guides/money-movement/send-payments/send-funds/) or withdraw funds from the Moov platform | Wallet, Bank account, Card | `transfers`, `wallet` | | Destination Payment method | Details | Source | Required capabilities | |----------------------------|-----------------------------------------------------------------------------------------------------------------|----------------------------|----------------------------------------------------------| | `rtp-credit` | [Disburse funds](/guides/money-movement/send-payments/rtp/) to a linked bank account in near real time | Wallet | `send-funds.instant-bank`, `wallet.balance` | | `push-to-card` | Instantly [push funds](/guides/money-movement/send-payments/push-to-card/) to a supported debit or prepaid card | Card | `transfers`, `wallet.balance`, `send-funds.push-to-card` | | `ach-credit-standard` | Disburse funds to a linked bank account | Bank account | `transfers`, `collect-funds.ach` | | `ach-credit-same-day` | Disburse funds to a linked bank account using same-day processing | Bank account | `transfers`, `collect-funds.ach` | | `moov-wallet` | Fund [payouts](/guides/money-movement/send-payments/send-funds/) or withdraw funds from the Moov platform | Wallet, Bank account, Card | `transfers`, `wallet.balance` | ### [RTP & ACH](#rtp--ach) Link an eligible bank account through the Dashboard or API for access to instant [RTP](/guides/money-movement/send-payments/rtp/) and fast [ACH](/guides/money-movement/accept-payments/ach/) payment methods. [Dashboard](#tab-769548213-1-0) [cURL](#tab-769548213-1-1) [Link a bank account](/api/sources/bank-accounts/create/) through the API. ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/bank-accounts" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "account": { "accountNumber": "0004321567000", "bankAccountType": "checking", "holderName": "Jules Jackson", "holderType": "individual", "routingNumber": "123456789" } }'\ ``` ### [Cards](#cards) [Link a card](/api/sources/cards/create/) through the API for access to the instant [pull](/guides/money-movement/accept-payments/pull-from-card/) and [push](/guides/money-movement/send-payments/push-to-card/) card payment methods (note, not all cards are eligible for instant payments). [Cards](#tab-912648753-2-0) ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/cards" \ -H "Authorization: Bearer {token}" \ -H "X-Wait-For: payment-method" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "billingAddress": { "addressLine1": "123 Main Street", "city": "Denver", "stateOrProvince": "CO", "postalCode": "80301", "country": "US" }, "cardCvv": "123", "cardNumber": "4111111111111111", "expiration": { "month": "01", "year": "28" }, "holderName": "Jules Jackson" }'\ ``` See our [settlement timing](/guides/money-movement/accept-payments/card-acceptance/timing/) guide for more information on card acceptance timing. Read more about payment methods in our documentation: [Payment methods](/guides/money-movement/payment-methods/) [Funding sources](/guides/sources/) ## [Configure interchange incentives](#configure-interchange-incentives) To have card payments qualify for debt repayment interchange incentives, business accounts must be configured with Moov and registered with Visa, Mastercard, and Discover. After configuration and registration, eligible merchants can receive lower interchange fees for qualified loan repayment transactions. When you link a card, you can check the response object to see if it qualifies. Qualifying cards will have card type `debit` or `prepaid`. ```zsh { "cardType": "debit" } ``` Payments made with a debit or prepaid card will automatically be marked as debt repayment in the request to the card network. To see what debt repayment program a transaction qualifies for, use the retrieve transfer `GET` [endpoint](/api/money-movement/transfers/get/) and check the fee program. ```zsh { "source": { "cardDetails": { "feeProgram": "Debt Repayment 2" } } } ``` Read more about interchange incentives in our debt repayment documentation: [Debt repayment](/guides/money-movement/accept-payments/card-acceptance/debt-repayment/) ## [Set up recurring payments](#set-up-recurring-payments) Recurring payments will collect from borrowers on a regular basis, without the need for a borrower to initiate a new payment each time. An initial payment is required before establishing a recurring schedule. Unscheduled payments which occur outside the set schedule can also be processed. Use the [transfers API](/api/money-movement/transfers/create/) to set up recurring payments. [Initial payment](#tab-958432617-0-0) [Recurring payments](#tab-958432617-0-1) Before setting up a recurring payment, an initial first recurring payment must be sent with a `first-recurring` transaction source. ```zsh { "amount": { "value": 5000, "currency": "USD" }, "source": { "paymentMethodID": "ec7e1848-dc80-4ab0-8827-dd7fc0737b43", "cardDetails": { "transactionSource": "first-recurring" }, "destination": {} } } ``` Once an initial recurring payment has been processed, a recurring payments schedule can be set using the `recurring` transaction source. ```zsh { "amount": { "value": 5000, "currency": "USD" }, "source": { "paymentMethodID": "ec7e1848-dc80-4ab0-8827-dd7fc0737b43", "cardDetails": { "transactionSource": "recurring" }, "destination": {} } } ``` Moov also provides a card account updater (CAU) service. CAU automatically updates payment information when a card has expired or been replaced, eliminating the need to contact cardholders to obtain new information. Read more about recurring payments and CAU in our documentation: [Recurring payments](/guides/money-movement/accept-payments/card-acceptance/recurring-payments/) [Card account updater](/guides/sources/cards/card-account-updater/) ## [Manage borrowers](#manage-borrowers) The easiest way to manage borrowers is in the Dashboard. Within the Dashboard you can view all accounts, create new accounts, upload documents, update fee plans, view transfers, and more. [Accounts in the Dashboard](#tab-521936478-0-0) Read more about managing accounts in the Dashboard and API: [Accounts](/guides/dashboard/accounts/) [Accounts API](/api/moov-accounts/accounts/) ## [Other resources](#other-resources) [Test mode](/guides/get-started/test-mode/) [Dashboard](/guides/dashboard/) [Webhooks](/guides/webhooks/) [API](/api/) [SDKs](/sdks/) --- URL: https://docs.moov.io/use-cases/small-business/ --- # Small business Moov is your single vendor for running and managing a modern payment solution that will reduce costs for your small business. This guide focuses on the quickest and easiest way to get started with the features of Moov we think you'll find most useful running a small business. Onboard customers to a secure payment platform, send payment link QR codes, and smoothly handle refunds and disputes. Moov offers a variety of integration options to get started. Use [Drops](/moovjs/drops/) or the [Dashboard](https://dashboard.moov.io/signin) UIs for a low to no-code solution, or choose the [API](/api/) or one of many [SDKs](/sdks/) for more complex integrations. For the purposes of this guide, we'll provide Dashboard and API examples. ## [Onboard customers](#onboard-customers) As you move through the onboarding process to create Moov accounts, some data is required while other data is optional. To view our full onboarding guides, visit the [Dashboard](/guides/dashboard/accounts/onboarding-links/) or main [onboarding](/guides/accounts/hosted-onboarding/) guides. | Onboarding data | Required | |----------------------|----------| | Capabilities | **✓** | | Fee plan | **✓** | | Scopes | **✓** | | Return URL | **×** | | Terms of service URL | **×** | | Prefilled data | **×** | **Capabilities** determine what each Moov account can do, such as receiving transfers, or sending money to others. For risk and fraud protection purposes, we require detailed information when requesting capabilities. For example, we'll request more details if an account wants to collect funds than we would for an account receiving funds. - [Transfers](/guides/accounts/capabilities/enablement/#transfers): Authorize debit transfers - [Wallet](/guides/accounts/capabilities/enablement/#wallet): Store funds with Moov - [Send funds](/guides/accounts/capabilities/enablement/#send-funds): Send funds to another account - [Collect funds](/guides/accounts/capabilities/enablement/#collect-funds) (Business accounts only): Collect funds from another account **Pricing & fee plans** can be assigned to one merchant or reused for many merchants. Merchants must agree to and accept the fee plan before it can go into effect. Moov offers two types of plans: - **Cost plus:** With a cost plus plan, card networks’ interchange fees and Moov’s processing markup are passed along to the merchant. Cost plus plans are beneficial for merchants with a high and varied transaction volume that prefer to have more control over fees. Fees are broken down into a more digestible and transparent format. - **Flat rate:** With a flat rate plan, you can lump all the processing fees together with a flat rate customized for each merchant. Flat plans are beneficial for merchants with a low transaction volume that prefer a predictable solution over lowering cost as much as possible. **Scopes** are used to determine what can be done with the account once it's onboarded. For example, the `/accounts.read` scope provides access to view all connected user accounts and the `/accounts/{accountID}/files.read` scope provides access to view or upload files associated with a Moov account. Read more on required data in our documentation: [Capabilities](/guides/accounts/capabilities/) [Fee plans](/guides/fee-plans/) [Scopes](/api/authentication/scopes/) [Dashboard](#tab-579281463-1-0) [cURL](#tab-579281463-1-1) Moov will send the [terms of service platform agreement](/guides/accounts/requirements/platform-agreement/) as part of the onboarding process through the Dashboard. Everyone with a Moov account must agree to and accept the terms of service before using Moov. The following clip demonstrates how to create a new onboarding link in the Dashboard: You'll need to generate and send a terms of service platform agreement as part of the onboarding process. Everyone with a Moov account must agree to and accept the terms of service before using Moov. If you're using the API, an SDK, or Moov Drops to onboard, see the [terms of service platform agreement](/guides/accounts/requirements/platform-agreement/) guide for more information and instructions. The following is a sample request to create an [onboarding invite](/api/moov-accounts/onboarding/post/) with all available data: ```zsh curl --X POST "https://api.moov.io/onboarding-invites" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "returnURL": "https://mycompany.com/account", "termsOfServiceURL": "https://mycompany.com/terms-of-service", "scopes": [ "accounts.read" ], "capabilities": [ "transfers", "wallet.balance" ], "feePlanCodes": [ "merchant-direct" ], "prefill": { "mode": "production", "accountType": "business", "profile": { "business": { "legalBusinessName": "LBM Lenders LLC", "doingBusinessAs": "LBM Lenders", "businessType": "llc", "address": { "addressLine1": "123 Main Street", "addressLine2": "Apt 302", "city": "Boulder", "stateOrProvince": "CO", "postalCode": "80301", "country": "US" }, "phone": { "number": "8185551212", "countryCode": "1" }, "email": "amanda@classbooker.dev", "website": "www.lbmlenders.com", "description": "Financial institution for personal lending", "taxID": { "ein": { "number": "123-45-6789" } }, "industryCodes": { "naics": "522291", "sic": "6141", "mcc": "6141" }, "primaryRegulator": "FDIC" } }, "metadata": { "property1": "string", "property2": "string" }, "termsOfService": { "token": "kgT1uxoMAk7QKuyJcmQE8nqW_HjpyuXBabiXPi6T83fUKRJkA3dsFID6fzitMpm2qrOh4" }, "foreignID": "4528aba-b9a1-11eb-8529-0242ac13003", "customerSupport": { "phone": { "number": "8185551212", "countryCode": "1" }, "email": "amanda@classbooker.dev", "address": { "addressLine1": "123 Main Street", "addressLine2": "Apt 302", "city": "Boulder", "stateOrProvince": "CO", "postalCode": "80301", "country": "US" }, "website": "www.lbmlenders.com" }, "settings": { "cardPayment": { "statementDescriptor": "LBM Lenders" }, "achPayment": { "companyName": "LBM Lenders" } } } }'\ ``` Read more about accounts and onboarding in our documentation: [Accounts](/guides/accounts/) [Onboarding links](/guides/dashboard/accounts/onboarding-links/) ## [Use form shortening](#use-form-shortening) Use the [enrichment API](/api/enrichment/form-shortening/) to find publicly available information to autofill form fields based on an email address. With the enrichment API you can: - Autocomplete addresses - Get avatars - Look up bank by routing number - List industries - Enrich business profile If you're using a Moov.js integration, you can use Moov's pre-built Drops UI for form shortening. Read more in the Moov.js documentation: [Moov.js](/moovjs/) [Composable Drops](/moovjs/drops/composable-drops/) ## [Send secure payment links](#send-secure-payment-links) Payment links are a secure way to collet payments from customers. Payment links can be shared via email, SMS, or social media. When customers click on a link, they can pay using a credit card, debit card, or bank account. A payment link can be sent as a URL or QR code. [Dashboard](#tab-651743298-0-0) [cURL](#tab-651743298-0-1) You can also create payment links with the [API](/api/money-movement/payment-links/create/). ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/payment-links" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "accountID": "c197cd40-7745-4413-8f3b-ec962d1b5225", "merchantPaymentMethodID": "3afc7533-7095-43bb-b21a-5c4dc5568451", "amount": { "currency": "USD", "value": 1500 }, "maxUses": 0, "expiresOn": "2025-08-24T14:15:22Z", "display": { "title": "string", "description": "string", "callToAction": "pay" }, "customer": { "requireAddress": true, "requirePhone": true, "metadata": { "property1": "string", "property2": "string" } }, "payment": { "allowedMethods": [ "apple-pay", "card-payment", "ach-debit-collect" ], "cardDetails": { "dynamicDescriptor": "Monthly payment 08-25" }, "achDetails": { "companyEntryDescription": "Monthly dues", "originatingCompanyName": "Quahog & Co" } } }'\ ``` [Dashboard payment links](/guides/dashboard/transfers/payment-links/) [Payment links](/guides/money-movement/payment-links/) [Payment link API](/api/money-movement/payment-links/) ## [Facilitate in-person payments](#facilitate-in-person-payments) For in-person payments, use the QR code generated with the payment links process. Once a payment link has been created in the Dashboard, you'll be presented with a URL and QR code to copy and send. If you're using the API, the payment link `code` will be in the response. You can append the code to the payment link URL `https://moov.link/` and send it to customers. [Dashboard](#tab-478129356-0-0) [cURL](#tab-478129356-0-1) ![Sharable link and QR code](../../guides/shared-images/payment-link-qr.png) The following is an example response when creating a payment link. The payment link URL with the code would be `https://moov.link/3QLHtONjd5`. ```zsh { "amount": { "currency": "USD", "value": 100000 }, "code": "3QLHtONjd5", "createdOn": "2025-01-09T17:09:13.33Z", "customer": { "requirePhone": true }, "display": { "callToAction": "pay", "description": "This is an example payment link.", "title": "Example Payment Link" }, "link": "https://moov.link/3QLHtONjd5", "merchantAccountID": "34233b72-780c-4e0e-8b08-cbbe1bc878f8", "merchantPaymentMethodID": "4c4e7f8e-81f4-4f3d-8f6f-6f6e7f8e4c4e", "mode": "sandbox", "partnerAccountID": "d290f1ee-6c54-4b01-90e6-d701748f0851", "payment": { "allowedMethods": [ "card-payment", "ach-debit-collect" ] }, "status": "active", "updatedOn": "2025-01-09T17:09:13.33Z", "uses": 0 } ``` You can also use the payment link `GET` [endpoint](/api/money-movement/payment-links/get-qrcode/) to retrieve the QR code. Moov is currently developing tap to pay for iPhone and Android. View our [product roadmap](https://moov.io/platform/roadmap/) for updated progress. ## [Handle reversals & refunds](#handle-reversals--refunds) Moov's reversal process offers a robust solution for returning funds to a cardholder, regardless of the current state of the transfer. When possible, a reversal cancels the transfer, reversing the authorization and swiftly returning funds. If a reversal is not possible, a refund is initiated instead. [Reversals & refunds](#tab-516234978-0-0) Moov automatically moves your request into the reversal or refund flow depending on settlement status and type, such as a full or partial refund. For ACH transfers, depending on settlement status, you also have the option of cancelling the ACH transfer directly. If a transfer is cancelable, you will have a **Cancel** option within the Dashboard. Read more about reversals, refunds, and cancellations in our documentation: [Reversals in the Dashbaord](/guides/dashboard/transfers/all-transfers/#initiate-a-reversal-refund-or-cancellation) [Reversals](/guides/money-movement/accept-payments/card-acceptance/reversals/) [ACH cancellations](/guides/money-movement/accept-payments/ach/cancellations/) [Reversals API](/api/money-movement/refunds/cancel/) ## [Handle disputes](#handle-disputes) The Dashboard will notify you of any disputes that come in and the deadline in which they will need to be handled. You can choose to accept the dispute and facilitate a refund, or challenge the dispute by submitting evidence. Within the Dashboard, you can view, accept, challenge, delete, and update disputes, as well as view, upload, and update dispute evidence. Moov currently supports RDR (Visa Rapid Dispute Resolution) decisioned pre-disputes and chargebacks from all card networks. [Accept dispute](#tab-416938275-0-0) [Challenge dispute](#tab-416938275-0-1) To accept the dispute, click the **Refund** button and follow the refund procedure. If you challenge the dispute, the Dashboard will guide you through uploading and submitting evidence, such as proof of purchase or terms of service. Read more about disputes in our documentation: [Card disputes](/guides/money-movement/accept-payments/card-acceptance/disputes/) [Disputes in the Dashboard](/guides/dashboard/transfers/disputes/) [Disputes API](/api/money-movement/disputes/). ## [Other resources](#other-resources) [Test mode](/guides/get-started/test-mode/) [Dashboard](/guides/dashboard/) [Webhooks](/guides/webhooks/) [API](/api/) [SDKs](/sdks/) --- URL: https://docs.moov.io/use-cases/transportation/ --- # Transportation & logistics Moov is your single vendor to simplify complex payment processes, view real-time cash flow visibility, and reduce operational costs. This guide focuses on the quickest and easiest way to get started with the features of Moov we think you'll find most useful for the transportation industry. Simplify complex payment processes, quickly verify bank accounts, and instantly send payouts with RTP and push to card. Moov offers a variety of integration options to get started. Use [Drops](/moovjs/drops/) or the [Dashboard](https://dashboard.moov.io/signin) UIs for a low to no-code solution, or choose the [API](/api/) or one of many [SDKs](/sdks/) for more complex integrations. For the purposes of this guide, we'll provide Dashboard and API examples. ## [Verify bank accounts instantly](#verify-bank-accounts-instantly) After you've [onboarded](/guides/dashboard/accounts/onboarding-links/) carriers, you can [link bank accounts](/guides/dashboard/settings/payment-methods/). Verifying linked bank accounts reduces fraud. You can initiate micro-deposit verification to confirm ownership of accounts. Banks that support instant verification will verify micro-deposits in a single session, in real time, via RTP. If a bank doesn't support instant verification, same-day ACH is used as a fallback. [Get IDs](#tab-653849721-0-0) [Initiate instant micro-deposits](#tab-653849721-0-1) The easiest way to find a carriers's account ID and bank account ID is in the Dashboard. Search for an account and click on it to open their profile. The account ID can be found under **Business details** and the bank account ID can be found by clicking on the linked bank account under **Payment methods**. ![Account ID in the Dashboard](../../guides/shared-images/account-overview-id.png) You can also retrieve a [list](/api/moov-accounts/accounts/list/) of accounts and their IDs with the API. ```zsh curl -X GET "https://api.moov.io/accounts" \ -H "Authorization: Bearer {token}" ``` Once you have an account ID, you can retrieve a [list](/api/sources/bank-accounts/list/) of bank account IDs with the API. ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/bank-accounts" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ ``` Use the IDs you've retrieved for an account to initiate [instant micro deposit verification](/api/sources/bank-accounts/initiate-bank-account-verification/) through the API. ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/bank-accounts/{bankAccountID}/verify" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ ``` If the bank supports instant verification, the response will show `instant` as the verification method. If instant verification is not supported, the verification method will be `ach`. ```zsh { "status": "new", "verificationMethod": "instant" } ``` Read more on bank account verification in our documentation: [Bank accounts](/guides/sources/bank-accounts/) [Instant verification](/guides/sources/bank-accounts/verification/instant-micro-deposit/) ## [Facilitate multi-party payments](#facilitate-multi-party-payments) With Moov wallets, you can facilitate complex money movement scenarios such as multi-party payouts where a carrier is paying out subcontractors. The wallet ledger tracks every debit and credit, automatically correlating transactions to the original payment method. Transfers between wallets are instant - send funds instantly from your wallet to a carriers's wallet so they can make timely payouts to their subcontractors. [Dashboard](#tab-428569713-0-0) [cURL](#tab-428569713-0-1) To create a wallet to wallet transfer in the Dashboard, click the **New transfer** button, select **Payout** and enter the source wallet and destination wallet. ![Transfer detail view in Moov Dashboard](../../guides/shared-images/transfers-view.png) To create a wallet to wallet transfer with the [API](/api/money-movement/transfers/create/), send the source wallet and destination wallet in the request. ```zsh curl -X POST "https://api.moov.io/accounts/{accountID}/transfers" \ -H "Authorization: Bearer {token}" \ -H "X-Idempotency-Key: UUID" \ -H "X-Wait-For: rail-response" \ -H "x-moov-version: v2024.01.00" \ --data-raw '{ "amount": { "value": 100000, "currency": "USD" }, "source": { "paymentMethodID": "your-wallet-ID" }, "destination": { "paymentMethodID": "carriers-wallet-ID" }, "description": "Optional transaction description." }'\ ``` [Wallets](/guides/money-movement/wallets/) [Send funds](/guides/money-movement/send-payments/send-funds/) ## [Set up transfer groups](#set-up-transfer-groups) Transfer groups provide a way to associate multiple transfers together by a shared ID of the parent transfer. Transfer groups make the final beneficiary in a chain of transfers aware of incoming funds before they land in their account. This also gives you more control over the flow of funds, making reporting and preserving the context of the original transfer easier. [Get transfer ID](#tab-791362548-0-0) [Create a transfer](#tab-791362548-0-1) You'll need to retrieve the ID of what you want to be the parent transfer before you can create a transfer group. The easiest way to do this is in the Dashboard. Search for the transfer and click on it to open the transfer page. The transfer ID is listed at the top and you can copy it to your clipboard. ![Transfer ID in the Dashboard](../../guides/shared-images/account-overview-id.png) You an also retrieve a [list of transfers](/api/money-movement/transfers/list/) with the API which will return the `transferID`. ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/transfers" \ -H "Authorization: Bearer {token}" \ -H "x-moov-version: v2024.01.00" \ ``` To create a transfer group, provide a `transferID` as the source when [creating a transfer](/api/money-movement/transfers/create/) with the API. ``` 1 2 3 4 5 6 7 8 9 10 11 12 13 ``` ```json { "amount": { "value": 100, "currency": "USD" }, "source": { "paymentMethodID": "transferID" }, "destination": { "paymentMethodID": "string" }, "description": "Optional transaction description." } ``` Read more about transfer groups in our documentation: [Transfer groups](/guides/money-movement/transfer-groups/) ## [Send instant payments](#send-instant-payments) Eligible linked bank accounts and cards have access to instant [RTP](/guides/money-movement/send-payments/rtp/) and [push to card](/guides/money-movement/send-payments/push-to-card/) payments respectively. ![Standard RTP funds flow diagram](./images/instant-funds-flow-light.png) ### [Check eligibility](#check-eligibility) Before you create a transfer, you can check if the bank account or card linked to a carriers's account is eligible for instant RTP or push to card payments. [Push to card](#tab-157682934-1-0) [RTP](#tab-157682934-1-1) Use the cards `GET` [endpoint](/api/sources/cards/get/) to check if a card is eligible for push to card. You can find the account ID and card ID in the Dashboard using the same methods [described above](#verify-bank-accounts-instantly) in the Get IDs tab. ```zsh curl -X GET "https://api.moov.io/accounts/{accountID}/cards" \ -H 'Authorization: Bearer {token}' \ ``` In the response, the `domesticPushtoCard` field will describe the push to card timing that is available for the card (if supported): | Timing | Description | |-----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `fast-funds` | Funds will be available to the destination within 30 minutes or less of the authorization. | | `standard` | Fast funds is not supported on this card. Transfer will follow standard card settlement [timing](/guides/money-movement/accept-payments/card-acceptance/timing/). | | `not-supported` | This card is ineligible for push-to-card payments. Contact your issuer for more details. | | `unknown` | Eligibility has not been checked or is unknown. | A push transfer can be created when the source is a pre-funded Moov wallet and the destination is a recipient with a linked card and the `transfers` [capability](/guides/accounts/capabilities/). When a bank account is linked, Moov checks its eligibility to receive payments on the RTP network and creates the `rtp-credit` payment method automatically. To use RTP, accounts must have the `send-funds.instant-bank` and `wallet.balance` [capabilities](/guides/accounts/capabilities/) enabled. Read more about instant payments in our documentation: [Push to card](/guides/money-movement/send-payments/push-to-card/) [RTP](/guides/money-movement/send-payments/rtp/) ## [Set metadata](#set-metadata) You can store free-form metadata on transfers, such as invoice numbers or correlation IDs. You can use this metadata to reconcile and correlate payments in your system. In addition to setting metadata when creating a transfer, you can also update metadata after a transfer has initiated or completed. [Dashboard](#tab-436251987-0-0) [cURL](#tab-436251987-0-1) When creating a transfer in the Dashboard, open the **Advanced settings** to enter metadata. ![Metadata](../../guides/shared-images/metadata.png) When creating a transfer in the API, enter the metadata you want in your request. ```zsh ... "metadata": { "property1": "string", "property2": "string" }, ... ``` Read more about metadata in our API documentation: [Update metadata](/api/money-movement/transfers/patch/) ## [Other resources](#other-resources) [Test mode](/guides/get-started/test-mode/) [Dashboard](/guides/dashboard/) [Webhooks](/guides/webhooks/) [API](/api/) [SDKs](/sdks/)