Skip to main content
When a user builds a custom plan by picking individual features, the receipt metadata contains the feature details directly.

How metadata is stored

Stripe limits metadata values to 500 characters. Cuprice splits the feature JSON across multiple keys:
{
  "customPlan": "true",
  "featureDetails_0": "[{\"name\":\"AI Prompt\",\"type\":\"Standard\",\"price\":10},",
  "featureDetails_1": "{\"name\":\"Dashboard\",\"type\":\"Standard\",\"price\":20}]"
}

Reconstructing the feature list

Join all featureDetails_* keys and parse the JSON:
const metadata = receipt.metadata;

let json = "";
Object.keys(metadata)
  .filter(k => k.startsWith("featureDetails"))
  .sort()
  .forEach(k => json += metadata[k]);

const features = JSON.parse(json);
// => [{ name: "AI Prompt", type: "Standard", price: 10 }, ...]

Feature object shape

Each feature in the array has:
name
string
required
Feature name (e.g. “AI Prompt”)
type
string
required
Feature type: “Standard”, “Limits”, or “Usage Based”
price
number
required
Price for this feature
quantity
number
For Limits/Usage Based features, the purchased quantity