Skip to main content

Overview

The updateIntent() method modifies an existing purchase intent. This operation requires Passkey authentication to ensure the user explicitly approves the changes.
Updating an intent invalidates any previously generated credentials. If you already invoked the intent, you’ll need to invoke it again after updating.

Method Signature

prava.updateIntent(intentId: string, updates: IntentUpdates): Promise<RegisteredIntent>

Parameters

intentId
string
required
Intent identifier from registerIntent() response
updates
IntentUpdates
required
Fields to update

Return Value

result
RegisteredIntent
Updated intent with new updatedAt timestamp

Example

const prava = new PravaSDK({
  publishableKey: 'pk_sandbox_your_key',
  environment: 'sandbox'
});

// Original intent: $100 max
const intent = await prava.registerIntent({
  cardId: 'card_123',
  merchantName: 'Amazon',
  declineThreshold: { amount: 100, currency: 'USD' },
  effectiveUntilTime: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(),
  consumerPrompt: 'Headphones under $100'
});

// User finds better headphones for $149
// Update the intent (triggers Passkey)
const updated = await prava.updateIntent(intent.intentId, {
  declineThreshold: { amount: 150, currency: 'USD' },
  consumerPrompt: 'Sony WH-1000XM5 headphones for $149'
});

// Now agent can execute with new amount
const credentials = await prava.invokeIntent(updated.intentId);

Passkey Authentication Flow

The Passkey prompt will show the changes being made (e.g., “Increase limit from 100to100 to 150”).

What Can Be Updated?

✅ Allowed Updates

  • Decline Threshold: Increase or decrease amount
  • Expiration Time: Extend or shorten validity period
  • Products: Add, remove, or modify product list
  • Consumer Prompt: Update description

❌ Cannot Be Updated

  • Card: Cannot switch to a different card (delete and create new instead)
  • Merchant: Cannot change merchant (security restriction)
  • Merchant Category Code: Cannot change MCC (security restriction)
  • Mandate ID: Immutable identifier

Use Cases

Price Change at Checkout

async function handlePriceIncrease(intentId: string, newPrice: number) {
  const currentIntent = await prava.getIntent(intentId);
  
  if (newPrice > currentIntent.declineThreshold.amount) {
    // Price went up, need to update
    try {
      const updated = await prava.updateIntent(intentId, {
        declineThreshold: {
          amount: newPrice + 5, // Add buffer for taxes/fees
          currency: 'USD'
        },
        consumerPrompt: `Updated price: $${newPrice} + taxes`
      });

      return { success: true, updated };
    } catch (error) {
      if (error.code === 'PASSKEY_CANCELLED') {
        return { success: false, reason: 'User declined price increase' };
      }
      throw error;
    }
  }

  return { success: true, noUpdateNeeded: true };
}

Cart Modifications

async function updateCart(intentId: string, cart: CartItem[]) {
  const totalAmount = cart.reduce((sum, item) => sum + (item.price * item.quantity), 0);

  const updated = await prava.updateIntent(intentId, {
    declineThreshold: {
      amount: totalAmount * 1.1, // 10% buffer
      currency: 'USD'
    },
    products: cart.map(item => ({
      name: item.name,
      url: item.url,
      quantity: item.quantity,
      amount: item.price
    })),
    consumerPrompt: `Cart total: $${totalAmount.toFixed(2)}`
  });

  return updated;
}

Expiration Extension

async function extendIntentValidity(intentId: string, additionalHours: number) {
  const currentIntent = await prava.getIntent(intentId);
  const currentExpiry = new Date(currentIntent.expiresAt);
  const newExpiry = new Date(currentExpiry.getTime() + additionalHours * 60 * 60 * 1000);

  try {
    const updated = await prava.updateIntent(intentId, {
      effectiveUntilTime: newExpiry.toISOString()
    });

    return {
      success: true,
      newExpiry: updated.expiresAt
    };
  } catch (error) {
    if (error.code === 'PASSKEY_CANCELLED') {
      return {
        success: false,
        reason: 'User declined extension'
      };
    }
    throw error;
  }
}

Error Handling

error
PravaError

Common Errors

CodeCauseResolution
INTENT_NOT_FOUNDIntent ID doesn’t existVerify intentId
INTENT_EXPIREDIntent already expiredCreate new intent
PASSKEY_CANCELLEDUser cancelled updateAllow retry or cancel
PASSKEY_FAILEDBiometric verification failedAsk user to retry
INVALID_AMOUNTAmount outside allowed rangeAdjust amount
INVALID_EXPIRATIONExpiration in past or too far futureUse valid date range
MERCHANT_CHANGE_NOT_ALLOWEDAttempted to change merchantCreate new intent

Update Validation

The system validates updates to prevent security issues:
// ✅ Valid updates
await prava.updateIntent(intentId, {
  declineThreshold: { amount: 150, currency: 'USD' } // Same currency
});

// ❌ Invalid: Cannot change currency
await prava.updateIntent(intentId, {
  declineThreshold: { amount: 100, currency: 'EUR' } // Different currency
});

// ✅ Valid: Extend expiration
await prava.updateIntent(intentId, {
  effectiveUntilTime: new Date(Date.now() + 48 * 60 * 60 * 1000).toISOString()
});

// ❌ Invalid: Expiration in the past
await prava.updateIntent(intentId, {
  effectiveUntilTime: new Date(Date.now() - 60 * 60 * 1000).toISOString()
});

Partial Updates

You only need to provide the fields you want to change:
// Update only amount
await prava.updateIntent(intentId, {
  declineThreshold: { amount: 200, currency: 'USD' }
});

// Update only expiration
await prava.updateIntent(intentId, {
  effectiveUntilTime: new Date(Date.now() + 12 * 60 * 60 * 1000).toISOString()
});

// Update both
await prava.updateIntent(intentId, {
  declineThreshold: { amount: 200, currency: 'USD' },
  effectiveUntilTime: new Date(Date.now() + 12 * 60 * 60 * 1000).toISOString()
});

Credentials Invalidation

Important: Updating an intent invalidates any previously generated credentials. You must invoke the intent again after updating.
// ❌ Wrong: Using old credentials after update
const credentials = await prava.invokeIntent(intentId);
await prava.updateIntent(intentId, { declineThreshold: { amount: 200, currency: 'USD' } });
await checkout(credentials); // These credentials are now invalid!

// ✅ Correct: Re-invoke after update
const oldCredentials = await prava.invokeIntent(intentId);
await prava.updateIntent(intentId, { declineThreshold: { amount: 200, currency: 'USD' } });
const newCredentials = await prava.invokeIntent(intentId);
await checkout(newCredentials);

Security Considerations

Passkey required for all updates: This ensures malicious actors cannot modify purchase authorizations without user consent.
Amount increases are logged: All amount increases are recorded in audit logs and may trigger additional fraud checks.

Next Steps