Quick start

This step by step guide provides you with instructions for a basic set up to create accounts and transfer money.

If you have not done so already, use the Moov Dashboard to create an account. You’ll need to be approved for a production account before you can start moving real money. An individual with administrator or developer permissions is required to continue with this guide.

Read our documentation for full details on any of the topics covered in this guide.

This guide assumes you have already signed up for Moov, been approved for a production account, and have administrator or developer permissions.

Resources:

Prerequisites

After being approved for a production account, you’ll need to create API keys. We strongly suggest you explore test mode before using production mode. If you’re ready to jump into production mode, make sure to take any necessary precautions if you’ve previously been using test mode.

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 documentation.

Authenticate

Most capabilities you request for accounts will require terms of service acceptance by the user. Authentication and the Moov.js terms of service Drop are required when collecting terms of service acceptance for these accounts. The terms of service Drop securely captures a user’s platform agreement acceptance which you can then send to Moov.

Explore test mode

While test mode is optional, we strongly suggest you try it out. After you’ve created an account, test mode with test data will be automatically enabled in the Dashboard so you can explore how the platform works. Make sure you’re in test mode by using the account switcher on the top left.

Toggle for test account in Moov Dashboard

Try out the following:

  • Add a bank account
  • Initiate micro-deposits
  • Initiate a transfer
  • Initiate a return

Read the test mode documentation.

Switch to production mode

When you’re ready to switch to production mode, use the account switcher located on the top left of the Dashboard. 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 production mode documentation.

Integrate

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

You can use your API key’s public and private keys with Basic authentication.

Set the Authorization header to Basic <credentials>, 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 instead.

Client-side: OAuth with JWT

You can set up authentication with OAuth and initialize Moov.js in your application. When making requests to Moov from a browser, you can use OAuth with JSON Web Tokens (JWT).

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 documentation.

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.

Token generation process diagram

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.

1
2
3
4
curl -X POST "https://api.moov.io/oauth2/token" \
  -u "PUBLIC_KEY:PRIVATE_KEY" \
  --data-urlencode "grant_type=client_credentials" \
  --data-urlencode  "scope=/accounts.write" \
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import { Moov, SCOPES } from '@moovio/node';

const moov = new Moov({
  accountID: "YOUR_MOOV_ACCOUNT_ID",
  publicKey: "PUBLIC_KEY",
  secretKey: "PRIVATE_KEY",
  domain: "YOUR_DOMAIN"
});

const scopes = [SCOPES.ACCOUNTS_CREATE];
try {
  const {token} = await moov.generateToken(scopes);
  // Do something with token
} catch(err) {
  // Handle any errors
}

Install Moov.js

You can install Moov.js via npm, or by including the script:

1
npm i @moovio/moov-js
1
2
3
4
5
import { loadMoov } from '@moovio/moov-js';

// Use your server to get a Moov access token with appropriate scopes
const moovAccessToken = await fetch(...);
const moov = await loadMoov(moovAccessToken);
1
2
3
4
<script type="text/javascript" src="https://js.moov.io/v1"></script>
<script>
  const moov = Moov(token)
</script>

If you make calls from a browser to Moov without using Moov.js, you can include the access token in the Authorization header.

1
2
3
const headers = {
  'Authorization': `Bearer ${token}`
};

Read the Moov.js documentation.

Create an account

To move money, you need to set up Moov accounts. We suggest using our hosted onboarding process when available. If you’d like to link a Moov account to an account in your system, you have the option to pass a foreignID.

The /accounts.write scope is required in order to create the access token. The /accounts/{accountID}/capabilities.write scope to is also required if requesting capabilities during account creation. You can specify capabilities when the account is created, or add them later.

Determine capabilities

Capabilities indicate what an account is able to do. Before you create an account, decide what capabilities you want to request for the account.

Each capability has different data and verification requirements depending on whether the account represents an individual, or a business. Most capabilities also require account holders to agree to Moov’s platform terms of service agreement, which you can initiate using Moov’s terms of service Drop.

The example below creates an account with the transfer capability.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
curl -X POST "https://api.moov.io/accounts" \
  -H "Authorization: Bearer {token}" \
  --data-raw '{
    "accountType": "business",
    "profile": {
      "business": {
        "legalBusinessName": "Whole Body Fitness LLC",
        "businessType": "llc",
        "website": "wbfllc.com"
      }
    },
    "foreignId": "your-correlation-id"
  }'\
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
const moov = new Moov(credentialsObject);

const accountPayload = {
  accountType: "business",
  profile: {
    business: {
      legalBusinessName: "Whole Body Fitness LLC",
      businessType: "llc",
      website: "wbfllc.com"
    }
  },
  foreignId: "your-correlation-id"
};

const account = await moov.accounts.create(accountPayload);
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
const moov = Moov(token);

const accountPayload = {
  accountType: "business",
  profile: {
    business: {
      legalBusinessName: "Whole Body Fitness LLC",
      businessType: "llc",
      website: "wbfllc.com"
    }
  },
  foreignId: "your-correlation-id"
};

const account = await moov.accounts.create({accountPayload});

You can also request capabilities after an account has been created. To see all capability requirements, read the capabilities documentation.

Add a funding source

To move funds, you’ll need to add a funding source, such as a bank account or card. Once the funding source is linked and verified, you’re ready to move money. A payment method is automatically created for you when you add a bank account, link a card, or are approved for a Moov wallet.

Generate the access token

Create an access token using your API key following the steps from above. Note that the /accounts/{accountID}/bank-accounts.write scope is required for bank accounts, and the /accounts/{accountID}/cards.write scope is required for cards when creating an access token.

Add a bank account or card

You can manually add bank accounts as shown below, or use MX or Plaid.

To link a customer’s card to their Moov account, you can use the pre-built card link Drop in an HTML document as shown below and include the token you generated in the previous step. Once the information has been submitted, Moov verifies the card details with card networks. You will not be responsible for storing or handling any of the card data, since all PII goes directly to Moov. Alternatively, you can link a card using the POST link card endpoint if you have provided Moov with a copy of your PCI attestation of compliance.

If using the link card POST endpoint, you can set the optional X-Wait-For header to payment-method and the response will include any payment methods that were created for the newly linked card in the paymentMethods field.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
curl -X POST "https://api.moov.io/accounts/{accountID}/bank-accounts" \
  -H "Authorization: Bearer {token}" \
  --data-raw '{
    "account": {
      "accountNumber": "0004321567000",
      "bankAccountType": "checking",
      "holderName": "Jules Jackson",
      "holderType": "individual",
      "routingNumber": "123456789"
    }
  }'\
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
const moov = new Moov(credentialsObject);

const accountID = "accountID";
const bankAccountPayload = {
  bankAccount: {
    accountNumber: "0004321567000",
    bankAccountType: "checking",
    holderName: "Jules Jackson",
    holderType: "individual",
    routingNumber: "123456789"
  }
}

const response = await moov.bankaccounts.link(accountID, bankAccountPayload);
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
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});
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<moov-card-link class="card-link"></moov-card-link>

<script>
  let moovCardLink = document.querySelector("moov-card-link");
  moovCardLink.accountID = "accountID";
  moovCardLink.oauthToken = "oauthToken";
  moovCardLink.onSuccess = (card) => {
    console.log("Card linked");
    // now show a success screen
  }
  moovCardLink.onError = (error) => {
    console.log("Error linking card");
    // now show an error screen
  }

  // call submit when button is pressed
  moovCardLink.submit();
</script>

Initiate instant micro-deposits

Manually added bank accounts need to be verified through an instant micro-deposit.

1
2
curl -X POST "https://api.moov.io/accounts/{accountID}/bank-accounts/{bankAccountID}/verify" \
  -H "Authorization: Bearer {token}" \

Complete instant micro-deposits

1
2
3
4
5
curl -X PUT "https://api.moov.io/accounts/{accountID}/bank-accounts/{bankAccountID}/verify" \
  -H "Authorization: Bearer {token}" \
  --data-raw '{
    "code":"MV1234"
  }'\

Read the bank accounts documentation.

Move money

You’re now ready to move money with our API through your servers. Before initiating a transfer, you’ll need to get a payment method. You can get 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 through ACH debit.

To get a payment method, the /accounts/{accountID}/payment-methods.read OAuth scope is required to create the access token.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
curl -X POST "https://api.moov.io/transfer-options" \
  -H "Authorization: Bearer {token}" \
  --data-raw '{
    "amount": {
      "value": 100,
      "currency": "USD"
    }
    "destination": {
      "accountID": "UUID"
    },
    "source": {
      "accountID": "UUID"
    }
  }'\
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
const moov = new Moov(credentialsObject);

const transferOptions = {
  amount: {
    value: 100, 
    currency: "USD"
  },
  destination: {
    accountID: UUID
  },
  source: {
    accountID: UUID
  }
}

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.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
curl -X POST "https://api.moov.io/transfers" \
  -H "Authorization: Bearer {token}" \
  -H "X-Idempotency-Key: UUID" \
  -H "X-Wait-For: rail-response" \
  --data-raw '{
    "amount": {
      "value": 100,
      "currency": "USD"
    },
    "destination": {
      "paymentMethodID": "UUID"
    },
    "source": {
      "paymentMethodID": "UUID"
    },
    "description": "Optional transaction description."
  }'\
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
mc, _ := moov.NewClient()

mc.CreateTransfer(ctx, moov.CreateTransfer{
  Amount: moov.Amount{
    Currency: "usd",
    Value:    100, // $1.00
  },
  Destination: moov.CreateTransfer_Destination{
    PaymentMethodID: "UUID",
  },
  Source: moov.CreateTransfer_Source{
    PaymentMethodID: "UUID",
  },
  Description: "Optional transaction description.",
})
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
const moov = new Moov(credentialsObject);

const transfer = await moov.transfers.create({
  amount: {
    value: 100,
    currency: "USD"
  },
  destination: {
    paymentMethodID: "UUID"
  },
  source: {
    paymentMethodID: "UUID"
  },
  description: "Optional transaction description."
});

Next steps

You’ve just moved money! Once you’re set up, you can continue to make transfers or accept payments.

Use the Moov Dashboard to:

  • Customize account settings
  • Add team members
  • Manage roles and permissions

We also suggest you consider doing the following:

FAQ

I’m getting a 401 unauthorized error while making an API call. How should I troubleshoot this?
There could be a number of possible reasons for a 401 unauthorized error. Troubleshoot the error by making sure you have:

If you are still getting an error, please write a support ticket and provide the x-request-id response header from your request so our team can troubleshoot further.

I’ve received a CORS error or failed request. What do I do?
To troubleshoot a CORS error or a failed request, make sure to check you’ve done the following:
  • Sent your request coming from a secure https domain. Note that localhost is not secure, even if it displays as https in your browser.
  • Included the domain sending the request in the allowed domain list for your Moov API key
  • Generated an access token that includes all the required scopes for your request from Moov.js or a client-side integration
  • Included the generated access token in your request header
Summary Beta