Building an On-demand App

This guide is an in-depth walkthrough to implementing an on-demand app using Connect. If you need help after reading this, check out our answers to common questions or chat live with other developers in #stripe on freenode.

For some businesses, the platform’s brand is at the center of the commerce: they aren’t just providing a software platform, they’re providing an end-to-end experience. For example, with an on-demand app, rates are set by the platform, and although a third-party is providing the specific service, the platform is managing the experience, guaranteeing the quality, and handling the customer service.

Thanks to Connect, the complexity of this entire commercial flow can be reduced to a single API call, as you identify the intended recipient of funds when a charge is processed. Additionally, Connect makes it easy to create and manage accounts to work with and pay your service providers.

The following steps walk through an on-demand app implementation, although the recipe is applicable to any business that has the primary relationship with its customers and pays its service providers directly. This implementation makes some additional assumptions about your business:

  • The platform is responsible for all fees, disputes, fraud, and customer service.
  • The service provider is an independent contractor, not an employee.
  • The contractor would not have a Stripe login, and Stripe would not contact them.

Getting prepared

First, understand that when you, the on-demand app creator, control the entire experience, you create managed accounts on behalf of your service providers. One of the most important considerations with managed accounts is that you are entirely responsible for providing the necessary information about your contractors, as Stripe will never interact with them. This means you must:

If you’re properly prepared to do the above as a prerequisite for creating a new account on behalf of a service provider, you’ll have a smoother onboarding process and reduce the likelihood of delays in paying contractors once they start working. Towards that end, it’d make sense for you to create a page where all the necessary information can be provided. This would simply be a form—perhaps part of a contractor portal—where the service provider enters their:

  • Name
  • Address
  • Date of birth
  • Last 4 digits of their Social Security number

(This assumes the contractor is a US individual, not being paid as a corporation; service providers in other countries would have different requirements.)

Again, the contractor would also need to formally agree to Stripe’s Services Agreement, and you would note the timestamp and the contractor’s IP address as a record of that. As the above information would only need to be taken once, you will separately request the contractor’s bank (explained below).

Creating accounts

With the necessary information in hand, create a new managed account for the service provider:

curl https://api.stripe.com/v1/accounts \
   -u sk_test_BQokikJOvBiI2HlWgH4olfQ2: \
   -d managed=true \
   -d country=US \
   -d legal_entity[type]=individual \
   -d legal_entity[first_name]=Jane \
   -d legal_entity[last_name]=Doe \
   -d legal_entity[address][city]="San Francisco" \
   -d "/* Other address fields */" \
   -d legal_entity[dob][day]=31 \
   -d legal_entity[dob][month]=12 \
   -d legal_entity[dob][year]=1969 \
   -d legal_entity[ssn_last_4]=1234 \
   -d tos_acceptance[date]=1475008633 \
   -d tos_acceptance[ip]="8.8.8.8"

The result of a successful API call will be the account information (not all fields are shown):

{
  "id": "acct_12QkqYGSOD4VcegJ",
  "keys": {
    "secret": "sk_live_AxSI9q6ieYWjGIeRbURf6EG0",
    "publishable": "pk_live_h9xguYGf2GcfytemKs5tHrtg"
  },
  "managed": true,
  "charges_enabled": true,
  "transfers_enabled": false,
  ...
  "legal_entity": {
    ...
    "verification": {
      "status": "pending",
      ...
    }
  },
  "verification": {
    "fields_needed": ['bank_account'],
    "due_by": null,
    "contacted": false
  }
}

You’ll need to store the account ID to later control and use the account. Note that the response shows charges_enabled as true, meaning you can start processing payments on behalf of this contractor right now. The legal_entity[verification] hash’s status property is “pending”, meaning that Stripe is in the process of verifying the new account. The top-level verification property shows that a bank account is still required.

In short, this contractor is ready to start working for your on-demand app, but can’t yet be paid (because of the lack of a bank account; to be remedied shortly).

Processing payments

To pay contractors directly, simply process the charge on your account, setting a destination parameter identifying the Stripe account that should receive the funds from the payment (i.e., the contractor). This requires a payment token created using the platform’s publishable API key.

curl https://api.stripe.com/v1/charges \
   -u sk_test_BQokikJOvBiI2HlWgH4olfQ2: \
   -d amount=1000 \
   -d currency=usd \
   -d source="{TOKEN}" \
   -d destination=acct_12QkqYGSOD4VcegJ \
   -d application_fee=200

The customer is being charged $10.00, and you’re taking a $2.00 application fee. The payment appears as a charge in your account, along with a transfer from your account to the contractor’s account. The Stripe fees (of 59 cents) will come out of your account; you’ll net $1.41. The contractor receives $8.00.

(Instead of using the token directly, you could choose to create customers in your, the platform’s, account. You would then create charges using the customer ID instead of a token source.)

To be clear, these funds are directly going into your, and the contractor’s, Stripe accounts. The funds will become available for transfer to a bank account on the normal rolling basis. If you haven’t already done so, you’ll need to add a bank account in order for the contractor to actually receive the payment.

Adding a bank account

The final step in completing the flow of funds here is to update the service provider’s account by adding a bank account to which Stripe will transfer payments. Perhaps, on another form on your site, you’ll have your contractor’s manage their bank account, allowing new service providers to add one and existing contractors to change theirs.

You can securely take a person’s banking information using Stripe.js, receiving a representative token in return. This can be added to the contractor’s Stripe account:

curl https://api.stripe.com/v1/accounts/acct_12QkqYGSOD4VcegJ \
   -u sk_test_BQokikJOvBiI2HlWgH4olfQ2: \
   -d bank_account="{TOKEN}"

The result of that successful API call will show transfers now enabled on the account:

{
  ...
  "transfers_enabled": true,
  ...
}

While you’re at it, you can also dictate the contractor’s transfer schedule. For example, maybe you’ve said contractors are paid out every Thursday:

curl https://api.stripe.com/v1/accounts/acct_12QkqYGSOD4VcegJ \
   -u sk_test_BQokikJOvBiI2HlWgH4olfQ2: \
   -d transfer_schedule[interval]=weekly \
   -d transfer_schedule[weekly_anchor]=thursday

With a bank account attached, and payments being processed, the contractor will now automatically be paid out by Stripe every Thursday for all funds that became available since the previous transfer. No additional effort is required on your part to make that happen!

Using webhooks

After registering your platform with Stripe, you’d want to be certain that you have a webhook defined. With managed accounts, you’ll specifically need to watch for account.updated events, which Stripe uses to indicate a need for more information, among other things. Failure to respond to those events can result in delayed transfers to your contractors. For example, you might see this:

{
  "id": "evt_1234",
  "user_id": "acct_12QkqYGSOD4VcegJ",
  ...
  "data": {
    "object": {
      ...
      "legal_entity": {
        "verification": {
          "status": "unverified"
          ...
        }
      },
      "verification": {
        "fields_needed": ['legal_entity.personal_id_number']
        "due_by": null,
        "contacted": false
      }
    },
    "previous_attributes": {
      "legal_entity": {
        "verification": {
          "status": "pending"
        }
      },
      "verification": {
        "fields_needed": []
      }
    }
  }
}

This event is Stripe’s way of telling you:

  • This contractor’s verification failed (the status changed from pending to unverified).
  • Stripe now needs the contractor’s entire Social Security number (legal_entity.personal_id_number is in the fields_needed).
  • It’s not urgent, because due_by is null.

If the due_by was set, the additional information would be required by that time (usually at least 3 days). Failure to provide that information by that time could result in transfers to the driver being held.

For any information required by Stripe, you’d request it from the contractor—if you did not have it already—and update the account.

Running a promotion

Everything is now going smoothly with paying your contractors and managing their accounts, but to drum up more business, you’ve decided to give each new customer the first service at no cost. However, your contractors aren’t working for free! Connect will help you out here, too.

To handle this promotion, as the customer isn’t charged anything, you’ll instead represent each free service as a transfer from your Stripe account to the contractor’s:

curl https://api.stripe.com/v1/transfers \
   -u sk_test_BQokikJOvBiI2HlWgH4olfQ2: \
   -d amount=800 \
   -d currency=usd \
   -d destination=acct_12QkqYGSOD4VcegJ

This is similar to how a charge is processed, except no application fee is set, no token is required, and no Stripe fees will be assessed. The $8.00 will appear as a payment in the contractor’s account and be automatically paid out next Thursday—just the same as with a conventional charge.

Other recipes

Looking to build another type of platform? Check out these other recipes.