Skip to main content

Card Lifecycle Management

Freezing Cards

Freeze a card temporarily to prevent unauthorized transactions while maintaining the card account.
function freezeCard(workspaceAccountID: number, card: Card, currentUserAccountID: number) {
    const cardID = card.cardID;
    const previousFrozen = card?.nameValuePairs?.frozen ?? null;
    const shouldUpdateCardList = card.accountID === currentUserAccountID;

    const frozenData: CardListUpdateData = {
        state: CONST.EXPENSIFY_CARD.STATE.STATE_SUSPENDED,
        nameValuePairs: {
            frozen: {
                byAccountID: currentUserAccountID,
                date: DateUtils.getDBTime(),
            },
            pendingFields: {frozen: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE},
        },
        pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
        isLoading: true,
        errors: null,
    };

    const optimisticData = buildCardListUpdates(workspaceAccountID, cardID, frozenData, shouldUpdateCardList);
    
    const parameters: FreezeCardParams = {
        cardID,
    };

    API.write(WRITE_COMMANDS.FREEZE_CARD, parameters, {
        optimisticData,
        successData,
        failureData,
    });
}

Unfreezing Cards

Reactivate a frozen card to resume normal operations.
function unfreezeCard(workspaceAccountID: number, card: Card, currentUserAccountID: number) {
    const cardID = card.cardID;
    const previousFrozen = card?.nameValuePairs?.frozen ?? null;
    const shouldUpdateCardList = card.accountID === currentUserAccountID;

    const unfrozenData: CardListUpdateData = {
        state: CONST.EXPENSIFY_CARD.STATE.OPEN,
        nameValuePairs: {
            frozen: null,
            pendingFields: {frozen: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE},
        },
        pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
        isLoading: true,
        errors: null,
    };

    const optimisticData = buildCardListUpdates(workspaceAccountID, cardID, unfrozenData, shouldUpdateCardList);
    
    const parameters: FreezeCardParams = {
        cardID,
    };

    API.write(WRITE_COMMANDS.UNFREEZE_CARD, parameters, {
        optimisticData,
        successData,
        failureData,
    });
}

Card Limits

Updating Card Limits

Set spending limits for individual cards to control expenses.
function updateExpensifyCardLimit(
    workspaceAccountID: number,
    cardID: number,
    newLimit: number,
    newAvailableSpend: number,
    oldLimit?: number,
    oldAvailableSpend?: number,
    isVirtualCard?: boolean,
) {
    const optimisticData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST>> = [
        {
            onyxMethod: Onyx.METHOD.MERGE,
            key: `${ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST}${workspaceAccountID}_${CONST.EXPENSIFY_CARD.BANK}`,
            value: {
                [cardID]: {
                    availableSpend: newAvailableSpend,
                    nameValuePairs: {
                        unapprovedExpenseLimit: newLimit,
                        pendingFields: {unapprovedExpenseLimit: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE},
                    },
                    pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
                    pendingFields: {availableSpend: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE},
                    isLoading: true,
                    errors: null,
                },
            },
        },
    ];

    const parameters: UpdateExpensifyCardLimitParams = {
        cardID,
        limit: newLimit,
        isVirtualCard: isVirtualCard ?? false,
    };

    API.write(WRITE_COMMANDS.UPDATE_EXPENSIFY_CARD_LIMIT, parameters, {
        optimisticData,
        successData,
        failureData,
    });
}

Updating Limit Types

Configure different limit types (daily, monthly, etc.) with validity periods.
function updateExpensifyCardLimitType(
    workspaceAccountID: number,
    cardID: number,
    newLimitType: CardLimitType,
    timeZone: SelectedTimezone | undefined,
    oldCardNameValuePairs?: Card['nameValuePairs'],
    validFrom?: string,
    validThru?: string,
    shouldClearValidityDates?: boolean,
) {
    const optimisticData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST>> = [
        {
            onyxMethod: Onyx.METHOD.MERGE,
            key: `${ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST}${workspaceAccountID}_${CONST.EXPENSIFY_CARD.BANK}`,
            value: {
                [cardID]: {
                    nameValuePairs: {
                        limitType: newLimitType,
                        pendingFields: {
                            limitType: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
                            validFrom: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
                            validThru: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
                        },
                        validFrom: shouldClearValidityDates ? null : validFrom,
                        validThru: shouldClearValidityDates ? null : validThru,
                    },
                    pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
                    pendingFields: {availableSpend: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE},
                    isLoading: true,
                    errors: null,
                },
            },
        },
    ];

    const parameters: UpdateExpensifyCardLimitTypeParams = {
        cardID,
        limitType: newLimitType,
        validFrom: validFrom ? DateUtils.normalizeDateToStartOfDay(validFrom, timeZone) : undefined,
        validThru: validThru ? DateUtils.normalizeDateToEndOfDay(validThru, timeZone) : undefined,
        clearValidityDates: shouldClearValidityDates,
    };

    API.write(WRITE_COMMANDS.UPDATE_EXPENSIFY_CARD_LIMIT_TYPE, parameters, {
        optimisticData,
        successData,
        failureData,
    });
}

Card Replacement

Replace lost, stolen, or damaged cards.
type ReplacementReason = 'damaged' | 'stolen';

function requestReplacementExpensifyCard(
    cardID: number,
    reason: ReplacementReason,
    validateCode: string
) {
    const optimisticData: Array<OnyxUpdate<typeof ONYXKEYS.FORMS.REPORT_PHYSICAL_CARD_FORM | typeof ONYXKEYS.VALIDATE_ACTION_CODE>> = [
        {
            onyxMethod: Onyx.METHOD.MERGE,
            key: ONYXKEYS.FORMS.REPORT_PHYSICAL_CARD_FORM,
            value: {
                isLoading: true,
                errors: null,
            },
        },
        {
            onyxMethod: Onyx.METHOD.MERGE,
            key: ONYXKEYS.VALIDATE_ACTION_CODE,
            value: {
                validateCodeSent: null,
            },
        },
    ];

    const parameters: RequestReplacementExpensifyCardParams = {
        cardID,
        reason,
        validateCode,
    };

    API.write(WRITE_COMMANDS.REQUEST_REPLACEMENT_EXPENSIFY_CARD, parameters, {
        optimisticData,
        successData,
        failureData,
    });
}

Fraud Detection

Report and handle fraudulent card activity.
function reportVirtualExpensifyCardFraud(card: Card, validateCode: string) {
    const cardID = card?.cardID ?? CONST.DEFAULT_NUMBER_ID;
    const optimisticData: Array<OnyxUpdate<typeof ONYXKEYS.FORMS.REPORT_VIRTUAL_CARD_FRAUD | typeof ONYXKEYS.ACCOUNT>> = [
        {
            onyxMethod: Onyx.METHOD.MERGE,
            key: ONYXKEYS.FORMS.REPORT_VIRTUAL_CARD_FRAUD,
            value: {
                cardID,
                isLoading: true,
                errors: null,
            },
        },
        {
            onyxMethod: Onyx.METHOD.MERGE,
            key: ONYXKEYS.ACCOUNT,
            value: {isLoading: true},
        },
    ];

    const parameters: ReportVirtualExpensifyCardFraudParams = {
        cardID,
        validateCode,
    };

    API.write(WRITE_COMMANDS.REPORT_VIRTUAL_EXPENSIFY_CARD_FRAUD, parameters, {
        optimisticData,
        successData,
        failureData,
    });
}

Deactivating Cards

Permanently deactivate a card.
function deactivateCard(workspaceAccountID: number, card?: Card) {
    const cardID = card?.cardID ?? CONST.DEFAULT_NUMBER_ID;

    const optimisticData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST | typeof ONYXKEYS.CARD_LIST>> = [
        {
            onyxMethod: Onyx.METHOD.MERGE,
            key: `${ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST}${workspaceAccountID}_${CONST.EXPENSIFY_CARD.BANK}`,
            value: {
                [cardID]: null,
            },
        },
        {
            onyxMethod: Onyx.METHOD.MERGE,
            key: ONYXKEYS.CARD_LIST,
            value: {
                [cardID]: null,
            },
        },
    ];

    const parameters: CardDeactivateParams = {
        cardID,
    };

    API.write(WRITE_COMMANDS.CARD_DEACTIVATE, parameters, {optimisticData, failureData});
}
Deactivating a card is permanent and cannot be undone. Consider freezing the card instead if you may want to reactivate it later.

Updating Card Details

Card Title

function updateExpensifyCardTitle(
    workspaceAccountID: number,
    cardID: number,
    newCardTitle: string,
    oldCardTitle?: string
) {
    const optimisticData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST>> = [
        {
            onyxMethod: Onyx.METHOD.MERGE,
            key: `${ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST}${workspaceAccountID}_${CONST.EXPENSIFY_CARD.BANK}`,
            value: {
                [cardID]: {
                    nameValuePairs: {
                        cardTitle: newCardTitle,
                        pendingFields: {cardTitle: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE},
                    },
                    pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
                    isLoading: true,
                    errors: null,
                },
            },
        },
    ];

    const parameters: UpdateExpensifyCardTitleParams = {
        cardID,
        cardTitle: newCardTitle,
    };

    API.write(WRITE_COMMANDS.UPDATE_EXPENSIFY_CARD_TITLE, parameters, {
        optimisticData,
        successData,
        failureData,
    });
}

Overview

Learn about Expensify Card basics

Company Cards

Managing company card integrations

Build docs developers (and LLMs) love