Record a purchase
POST/api/public/purchases
Record a product purchase for a trainee. Credits, expiration and membership dates are derived from the product when omitted: a punch card opens with the product credits and a one-year expiration, a membership starts immediately for the product duration.
Authentication
Requires an API key, sent as Authorization: Bearer cp_live_....
API keys carry scopes. Get the catalog of scopes and webhook events lists every scope.
Header parameters
| Name | Type | Description |
|---|---|---|
Idempotency-Key | string | Optional. Send a unique key (e.g. a UUID) to make this POST safe to retry. The same key within 24h returns the original result instead of creating a duplicate. |
Request body
application/json, required
| Name | Type | Description |
|---|---|---|
traineeIdrequired | string | Trainee buying the product |
productIdrequired | string | Product to purchase. Must be active. |
purchaseAmount | number | Amount actually charged. Defaults to the product price. |
currency | string | Defaults to ILS |
status | string | Defaults to ACTIVE. Use WAITING_FOR_PAYMENT to record a purchase before payment clears. |
purchaseDate | string | Purchase date as YYYY-MM-DD or a full ISO-8601 date-time. Defaults to now. Use it to backdate an imported purchase. |
expirationDate | string | Expiration as YYYY-MM-DD or a full ISO-8601 date-time, and never before purchaseDate. Defaults to one year from now for punch cards. A date in the past is accepted for history imports; the purchase flips to EXPIRED the first time its credits are used. |
initialCredits | number | Punch card credits granted. PUNCH_CARD products only. Defaults to the product credits. |
remainingCredits | number | Credits still available, and never more than initialCredits. PUNCH_CARD products only. Defaults to initialCredits; set it lower to import a partly used card. |
Request examples
curl --request POST \
--url 'https://api.coach-platform.com/api/public/purchases' \
--header 'Authorization: Bearer cp_live_...' \
--header 'Content-Type: application/json' \
--data '{
"traineeId": "<string>",
"productId": "<string>"
}'const response = await fetch('https://api.coach-platform.com/api/public/purchases', {
method: 'POST',
headers: {
Authorization: 'Bearer cp_live_...',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"traineeId": "<string>",
"productId": "<string>"
}),
});
const data = await response.json();Responses
201 Created
{
"data": {
"id": "<string>",
"coachId": "<string>",
"traineeId": "<string>",
"productId": "<string>",
"purchaseDate": "<date-time>",
"expirationDate": "<date-time>",
"purchaseAmount": 123,
"currency": "ILS",
"status": "ACTIVE",
"initialCredits": 123,
"remainingCredits": 123,
"membershipStartDate": "<date-time>",
"membershipEndDate": "<date-time>",
"currentPeriodUsages": 123,
"periodResetDate": "<date-time>",
"createdAt": "<date-time>",
"updatedAt": "<date-time>"
},
"warnings": [
{
"field": "<string>",
"message": "<string>"
}
]
}Response fields (21)
| Name | Type | Description |
|---|---|---|
data | object | |
data.id | string | |
data.coachId | string | |
data.traineeId | string | |
data.productId | string | |
data.purchaseDate | string<date-time> | |
data.expirationDate | string<date-time> | |
data.purchaseAmount | number | |
data.currency | string | |
data.status | string | |
data.initialCredits | number | |
data.remainingCredits | number | |
data.membershipStartDate | string<date-time> | |
data.membershipEndDate | string<date-time> | |
data.currentPeriodUsages | number | |
data.periodResetDate | string<date-time> | |
data.createdAt | string<date-time> | |
data.updatedAt | string<date-time> | |
warnings | object[] | Non-fatal problems with follow-up writes. The resource was created, but each listed field was not applied. |
warnings[].field | string | |
warnings[].message | string |
Error responses
400Bad Request401Unauthorized403Forbidden404Not Found409Conflict429Too Many Requests500Internal Server Error
These statuses share the same response body.
{
"error": {
"code": "<string>",
"message": "<string>",
"fix": "<string>",
"details": {},
"retryAfterMs": 123
}
}Error fields (6)
| Name | Type | Description |
|---|---|---|
error | object | |
error.code | string | |
error.message | string | |
error.fix | string | null | |
error.details | object | null | |
error.retryAfterMs | number | null |
More Purchases endpoints
This page is also available as Markdown. Browse it in the interactive explorer or download the OpenAPI spec.