Atomic logo

Gig Payouts

Debit card payouts for gig workers

Gig platforms and earned wage access providers often pay workers in more than one way:

  • Direct deposit: A scheduled transfer of available earnings to the user's bank account, typically weekly.
  • Debit card payout: An on-demand payment to the bank or prepaid account behind an eligible debit card, for a fee. These payouts travel over push-to-card services such as Visa Direct or Mastercard Send, not ACH, and often arrive within seconds or minutes. Real-Time Payments (RTP) and FedNow can also move money instantly, but they use bank account details and are not debit card payouts.
  • Platform-issued account or card: A financial account or debit card offered by the platform itself, often with instant or low-cost access to earnings.
  • PayPal and Venmo: Digital wallet payout options that some platforms offer alongside bank and card payouts.

With Gig Payouts, one Transact session can update both the direct deposit and the debit card. When your user switches their direct deposit to a supported platform, Atomic also puts your debit card on file as the platform's fast-payout card, so the user's earnings reach you however they choose to cash out.

  • Add deferredPaymentMethodStrategy to your UserLink Transact SDK configuration.
  • Optionally, add partial debit card details to your access token request, so users see the card's name and last four in Transact.
  • Handle the new debit card switch request in onDataRequest.

This is purely additive: however you pass deposit accounts and identity today stays exactly as it is. Contact your Atomic representative to have the feature enabled for your account.

PlatformScheduled payout (bank)Fast payout (debit card)Platform-issued accountSupport
DoorDashWeekly payFast Pay (daily)DoorDash CrimsonAvailable
UberWeekly payoutInstant Pay / Cash OutUber Pro CardComing soon
LyftWeekly payoutExpress PayLyft DirectComing soon
DailyPayNext business dayInstant transferDailyPay Visa® Prepaid CardPlanned
PayactivVaries by employerReal-time transferPayactiv Visa® CardPlanned

Scheduled payouts land in the user's bank account automatically. Fast payouts are on-demand transfers to a debit card, and the platform always charges a fee for them.

Only active debit cards are supported. Credit cards and frozen or expired debit cards are not supported. If a card is frozen or expired, tell the user clearly before they start so they can choose another eligible debit card. If you deeplink users to a platform, check the card's status first and don't offer the debit card option when the card isn't eligible.

DoorDash is available today. Uber and Lyft are coming soon. DailyPay and Payactiv are earned wage access platforms Atomic plans to support next.

Atomic updates the bank payout and the debit card payout. It never changes the platform's own issued account.

DoorDash may lock Fast Pay for 7 days after the card changes. Transact tells the user this before they opt in. Plan your user messaging around this if fast payout is central to your value proposition.

  • 1

    The user picks their account and selects a supported platform, exactly as they would for any direct deposit switch.

  • 2

    The user opts in: Before sign-in, Transact shows the direct deposit account and a toggle, on by default, to also put your debit card on file for fast payouts. It shows your card's last four if you provided one. On DoorDash the toggle reads "Set up Fast Pay." Turning it off updates the direct deposit only.

  • 3

    The user signs in once: A single login to the platform covers both updates.

  • 4

    Atomic asks you for the card: Transact sends a debit card switch request through onDataRequest, with product: "switch", and you supply the debit card and the cardholder's billing identity.

  • 5

    Atomic updates the platform: The debit card goes on file for fast payouts and the bank account is updated for scheduled payouts. If the platform asks the user to verify their identity, Transact handles that step.

  • 6

    Atomic reports the results: You receive one webhook for the switch task that adds the debit card and one for the deposit task that updates direct deposit. If one update fails, the other is not rolled back.

Choose a deferred payment method strategy. It tells Atomic you will supply the debit card during the session rather than up front. Pick the strategy that matches where your card data lives.

StrategyYou respond byCard data travels
sdk Returning the card from onDataRequest. Transact takes it from there. From the user's device straight to the platform. Use this when the card is available in your app.
api Sending the card from your backend to Atomic's PCI endpoint at pci.atomicfi.com, which tokenizes it. See Using the API strategy below. From your backend to Atomic's PCI environment. Use this when the card already lives server-side.

When you create the user's access token with POST /access-token, you can list their debit card with partial details alongside the deposit account you already send. Transact shows its name and last four on the opt-in screen, so the user knows which card goes on file, and echoes them back in the debit card switch request.

POST /access-token
{
  // your existing deposit access-token creation payload
  "identifier": "your-user-id",
  "accounts": [
    {
      "type": "checking",
      "title": "Premier Plus Checking",
      "routingNumber": "124003116",
      "accountNumber": "2157834891"
    }
  ],

  // optionally, you can add 1 card
  "cards": [
    {
      "lastFour": "0008",
      "title": "Everyday Debit",
      "cardType": "debit",
      "externalId": "card_8f2c"
    }
  ]
}

Debit cards only, with cardType set to exactly "debit", in lowercase. Other values such as "Debit" are accepted when the token is created but Transact ignores the card. Send just lastFour and title, never the card number, so the access token stays out of PCI scope. externalId is optional: your own ID for the card, so you know which card to send. Only the first debit card is used, and if you list one, include it every time you create an access token for the user.

Transact configuration (iOS)
import AtomicTransact

let config = AtomicConfig(
  publicToken: "PUBLIC_TOKEN",
  scope: .userLink,
  tasks: [.init(operation: .deposit)],

  // Add this line. .sdk keeps card data on the user's device.
  deferredPaymentMethodStrategy: .sdk
)

Requires iOS SDK 3.28.0 or later, the first version with CardData.cardType.

When the user opts in, Transact sends a debit card switch request through onDataRequest. The product field identifies it as switch. Check that field first and handle only switch here. Any other data request your integration already receives keeps working exactly as it does today.

onDataRequest payload
{
  "product": "switch",
  "fields": [
    "identity",
    "card"
  ],
  "userId": "6a9...",
  "identifier": "your-user-id",
  "taskId": "6a9...",
  "taskWorkflowId": "6a9...",
  "company": {
    "_id": "5df8...",
    "name": "DoorDash"
  },
  "properties": {
    "lastFour": "0008",
    "title": "Everyday Debit",
    "externalId": "card_8f2c"
  }
}

fields always includes identity. It includes card only when Atomic still needs the card number, so check fields.includes("card") rather than matching the whole array. properties echoes the card you added to the access token in Step 1. If you did not add one, it is empty. taskId is the ID of the deposit task in the same session, not the switch task.

On iOS, userId, identifier, fields, and taskId are typed properties on TransactDataRequest. Everything else, including product and taskWorkflowId, is read from the data dictionary.

A debit card switch request asks for both. Its identity is the cardholder's name and billing address, which the platform verifies against the card. It is not the same identity data used for direct deposit. How you answer depends on your strategy: under sdk you return the values from your handler and Atomic submits them for you, and under api your backend sends them to pci.atomicfi.com.

Both handle the same debit card switch request; they differ only in where the card goes.

deferredPaymentMethodStrategy: .sdk: return the card and billing identity. Transact submits them for you.

sdk strategy (iOS)
Atomic.presentTransact(
  from: self,
  config: config,
  onDataRequest: { request in
    if request.data["product"] as? String == "switch" {
      // Debit card switch request. properties echoes the Step 1 card
      // (lastFour "0008", externalId "card_8f2c"), so send that card.
      // Use a sandbox test card (see Testing) when testing in sandbox.
      // Replace this with your actual data collection logic in production.
      let card = TransactDataResponse.CardData(
        number: "5100000000000008",
        expiry: "03/29",
        cvv: "111",
        cardType: .debit
      )

      let identity = TransactDataResponse.Identity(
        firstName: "Jane",
        lastName: "Dasher",
        postalCode: "12345",
        address: "123 Main St",
        city: "New York",
        state: "NY"
      )

      guard identity.isValid() else { return nil }

      return TransactDataResponse(card: card, identity: identity)
    } else {
      // Any other existing deposit data request handling code you have
      return nil
    }
  },
  onTaskStatusUpdate: { task in
    print("Task \(task.taskId) status: \(task.status)")
  }
)

deferredPaymentMethodStrategy: .api: send the card from your backend to Atomic's PCI endpoint, which tokenizes it and attaches it to the task.

api strategy (iOS)
Atomic.presentTransact(
  from: self,
  config: config, // deferredPaymentMethodStrategy: .api
  onDataRequest: { request in
    if request.data["product"] as? String == "switch" {
      // Debit card switch request. Your backend sends the card matching
      // properties.externalId ("card_8f2c") from the Step 1 access token.
      // Your backend PUTs the card and billing identity with this
      // taskWorkflowId to https://pci.atomicfi.com/user in production,
      // or https://sandbox-pci.atomicfi.com/user in sandbox.
      await yourBackend.sendCardToAtomicPci(
        identifier: request.identifier,
        taskWorkflowId: request.data["taskWorkflowId"] as? String
      )

      // Nothing is returned to Transact; your backend submits the card.
      return nil
    } else {
      // Any other existing deposit data request handling code you have
      return nil
    }
  }
)
Testing
Use pci.atomicfi.com in production and sandbox-pci.atomicfi.com in sandbox. When testing in sandbox, only use the test card numbers listed in Testing.
ObjectRequiredOptional
cardnumber, expiry (MM/YY), cvvcardType: set .debit for a known debit card. This declares the card type; it does not validate whether the card is debit or credit.
identityfirstName, lastName, address, city, state, postalCodeaddress2, phone, email

Apart from the card number, every field is optional in the SDK types, but the debit card switch needs the ones listed as required. Use the two-letter state abbreviation: identity.validate() flags any other length, as well as a postal code outside 5 to 10 characters, a first or last name over 50 characters, or an address or city over 100. The billing identity should match what the card issuer has on file.

With api, Transact never collects the card itself. Your backend sends it when the debit card switch request arrives. Four things to get right:

Do thisOr else
Send the card shown to the user, matched by externalId or the last four on the debit card switch request. If you did not list a card, send the user's debit card. A different card is not rejected. Whatever you send is the card that goes on file.
Include the request's taskWorkflowId in your PUT /user to pci.atomicfi.com. The card may not be attached to this session. With taskWorkflowId, the card is used for this session only and is not saved to the user's cards. Without it, Atomic matches the card to the user's cards by last four.
Include the billing identity in the card's PUT /user, unless the user record already has it. The request fails with a missing identity error. Identity you send this way is also saved to the user.
Send the requested card promptly. Queued workflows become eligible for cancellation 5 minutes after workflow creation. Cancellation typically occurs after 5 to 10 minutes. A data request does not restart this timeout.

From your backend, authenticate the PUT /user request with both x-api-key and x-api-secret. Keep identifier at the top level and nest taskWorkflowId, card, and identity under data:

PUT /user request body
{
  "identifier": "your-user-id",
  "data": {
    "taskWorkflowId": "TASK_WORKFLOW_ID_FROM_ON_DATA_REQUEST",
    "card": {
      "number": "5100000000000008",
      "expiry": "03/29",
      "cvv": "111",
      "cardType": "debit"
    },
    "identity": {
      "firstName": "Jane",
      "lastName": "Dasher",
      "address": "123 Main St",
      "city": "New York",
      "state": "NY",
      "postalCode": "12345"
    }
  }
}

If you already launch the user with a full deposit account in the access token, no change is needed here.

POST /access-token
{
  "identifier": "your-user-id",
  "accounts": [
    {
      "type": "checking",
      "title": "Premier Plus Checking",
      "routingNumber": "124003116",
      "accountNumber": "2157834891"
    }
  ]
}

If you pass only partial deposit account details in the access token and provide the full account just in time through your existing deposit data request, onDataRequest now fires twice in the same session: once for the deposit account and once for the debit card switch request. Make sure your handler checks product and fields before responding.

productfieldsRespond with
depositIncludes accountThe full deposit account, as you do today.
switchIncludes identity, and card when neededThe debit card and billing identity, through your chosen strategy.
  • Answer each request on its own. Keep the account out of the debit card switch response, and the card out of the deposit account response.
  • Send the account and the card in separate calls. A single PUT /user with both is rejected. The deposit account always comes from your backend with your API key, even under the sdk strategy, because the SDK response carries only the card and identity.
  • Order does not matter. Neither update starts until both pieces have arrived.
  • Answer both promptly. If only one arrives, the workflow stays queued and neither update runs, including the direct deposit. The timeout starts at workflow creation, not when either data request arrives.

Both updates run behind one progress screen. The user doesn't see two flows or sign in twice.

The outcome screen reflects the debit card update, which finishes last. It does not report the direct deposit result separately, so use the deposit task's webhook to confirm the direct deposit before you message the user about it.

The direct deposit and the debit card are separate tasks, and each sends its own webhook: a switch task for the debit card and a deposit task for direct deposit. The switch task's events are described in the PayLink webhooks reference. If one fails, the other is not rolled back. These are the fail reasons you may see on each.

ScenarioTaskFail reason
The card is a credit card, or a debit card the platform can't send fast payouts to switchpayment-method-not-supported
The card could not be added for another reasonswitchpayment-switch-unsuccessful
The platform rejected the bank accountdepositaccount-unusable
The user did not complete the platform's identity verification. The switch task does not run, so the card is not added either. depositidentity-verification-required

If the platform already has a card with the same last four on file, the switch task completes without changing it.

Both strategies share the same guarantee: the card number and CVV are entered into the gig platform from the user's own device, never from an Atomic server. They are scoped to the single task that needs them, are never written to your Atomic user record, and never appear in task logs or request history. The strategies differ only in how the card gets to the device.

  • sdk keeps the card on the device. Your app returns it from onDataRequest, and Atomic's servers never receive the card number or CVV.
  • api tokenizes the card in Atomic's PCI environment. Your backend sends it to pci.atomicfi.com, and only a token reaches the rest of Atomic.
sdkapi
Where Atomic receives the cardNowhere. It stays on the device.pci.atomicfi.com only, then tokenized
What Atomic's services store A stand-in token, expiry, last four, brand, and card type (no number or CVV) A token, plus expiry and last four
Who sends the card to the platformThe user's deviceThe user's device
After the task finishesAtomic attempts to clear card data from device memoryAtomic attempts to clear card data from device memory