Skip to main content

Add Products to Case

POST/api/v1/cases/:caseId/products

Attaches one or more products to an existing case. Supports an optional top-level payment that covers all products in the request. Each product can also include an optional intake form and subscription configuration.

cv-api-key
Productionhttps://api.care360-next.carevalidate.com/api/v1/cases/:caseId/products
Staginghttps://api-staging.care360-next.carevalidate.com/api/v1/cases/:caseId/products

Parameters

Headers
cv-api-keystringrequired
Your unique API key for authentication.
Content-Typestringrequired
Must be application/json.
Example: application/json
Path Parameters
caseIdstring (UUID)required
Unique identifier of the case to add products to
Request Body
paymentobjectoptional
Optional payment covering all products in this request. A single payment can cover one or more products. For BNPL redirect flows (Klarna, Afterpay), you can pass a pending `PAYMENT_INTENT` here — products will be attached as inactive (`CLOSE`) and automatically activated once the PaymentIntent resolves (see Payment Status Lifecycle below). `amount` is required whenever a pending or already-charged `PAYMENT_INTENT` is provided, since it cannot be inferred from the PaymentIntent in that state.
Show 4 child properties
amountnumberrequired
Payment amount
currencystringrequired
ISO 4217 currency code
Example: USD
descriptionstringoptional
Payment description
providerReferenceobjectoptional
Payment gateway reference
Show 2 child properties
typestringrequired
Payment reference type
Values:SETUP_INTENTPAYMENT_INTENT
idstringrequired
Gateway reference ID (e.g. Stripe PaymentIntent or SetupIntent ID)
productsarrayrequired
Products to attach to the case. Each case can include one or more products. When a top-level `payment` is provided, it is linked to all products in this array.
Show 4 child properties
idstring (UUID)required
Organization product ID
visitTypestringoptional
Visit type for this product
Values:ASYNC_TEXT_EMAILSYNC_IN_PERSONSYNC_PHONESYNC_VIDEO
formobjectoptional
Healthcare intake form (see Form section below)
Show 3 child properties
titlestringoptional
Form title
descriptionstringoptional
Form description
questionsarrayoptional
Array of form questions
subscriptionobjectoptional
Optional subscription for this case product. Values are stored on the case product and returned in GET /api/v1/cases and in GraphQL.
Show 2 child properties
intervalstringoptional
Subscription interval (case-sensitive, lowercase)
Values:dayweekmonthyear
intervalCountintegeroptional
Positive integer for interval count (e.g. 1, 2, 3, 6, 12)

Form Question Fields

Question Object
questionstringrequired
Question text
answerstringrequired
User response
typestringrequired
Question type
Values:TEXTSINGLESELECTMULTISELECT
requiredbooleanoptional
Whether the question is mandatory
phibooleanoptional
PHI indicator. Questions marked with `true` are treated as Protected Health Information and stored per HIPAA compliance requirements.
optionsarrayoptional
Selectable options for SINGLESELECT and MULTISELECT question types

Payment Status Lifecycle

When a PAYMENT_INTENT is still pending at attach time (the BNPL pre-redirect flow), the product and its payment move through the following states as Stripe webhook events arrive. No polling is required — the case product's status/reason and the linked payment's status update automatically.

EventProduct statusProduct reasonPayment status
Pending PAYMENT_INTENT attachedCLOSEPending paymentUNPAID
payment_intent.amount_capturable_updated (BNPL hold acquired)OPENnullUNPAID (capture happens later)
payment_intent.succeeded (charge captured)OPENnullPAID
payment_intent.payment_failedCLOSEPayment failedERROR

If a PaymentIntent fails, only the product(s) and payment tied to it are closed/errored — the case itself remains OPEN. To retry, re-add the same product with a new PAYMENT_INTENT; it starts a fresh pending-payment cycle independent of the failed one.

Examples

curl -X POST "https://api.care360-next.carevalidate.com/api/v1/cases/550e8400-e29b-41d4-a716-446655440000/products" \
-H "cv-api-key: <redacted>" \
-H "Content-Type: application/json" \
-d '{
"products": [
{
"id": "8dff2c47-b2ab-42d8-9af0-4c4dbca8b4b6",
"visitType": "SYNC_VIDEO",
"subscription": {
"interval": "month",
"intervalCount": 3
}
},
{
"id": "621527f5-3877-48b3-b27f-df395a5308bb",
"form": {
"title": "Healthcare Intake Form",
"description": "Patient intake form for healthcare services",
"questions": [
{
"question": "How much do you weigh?",
"answer": "138 lbs",
"phi": true,
"type": "TEXT"
},
{
"question": "What are your weight loss goals?",
"answer": "Lose 1-20lbs for good",
"type": "SINGLESELECT",
"required": true,
"options": [
"Lose 1-20lbs for good",
"Lose 21-50lbs for good",
"Lose over 50 for good",
"Maintain my healthy weight"
]
}
]
}
}
]
}'

Responses

200SuccessProducts successfully attached to the case.
{
"success": true,
"data": {
"caseId": "550e8400-e29b-41d4-a716-446655440000"
}
}
400Bad RequestInvalid request body or parameters. Also returned when a pending or already-charged `PAYMENT_INTENT` is provided without an `amount`.
{
"success": false,
"message": "Invalid request"
}
401UnauthorizedMissing or invalid authentication token.
{
"success": false,
"message": "Unauthorized"
}
409ConflictCase conflict (e.g., duplicate product attachment).
{
"success": false,
"message": "Case conflict"
}
422Validation FailedRequest body failed validation rules.
{
"success": false,
"message": "Validation failed"
}
500Internal Server ErrorUnexpected server error.
{
"success": false,
"message": "Internal server error"
}

Try It Out


API Version: v2.2