E-commerce point specifications and point update/history APIs
This page explains how the e-commerce points held by Kuroco members are managed, and describes the APIs for updating and retrieving points from external systems.
- Point update API (
ECPoint::update): Grants or spends a member's points. - Point history API (
ECPoint::history): Retrieves a member's point history and current balance.
Basic concepts
- Each member has a point balance (total points).
- Every change to the balance is recorded in the point history, which is the authoritative record. Point changes are not recorded in the member's "Update history".
- Point grants are managed in lots (one lot per grant), and each lot keeps its "remaining points" (the unspent portion of that lot).
- Spending is applied starting from the lot with the nearest expiration date. Lots without an expiration date are used last.
Point status and properties
| Fixed points | Temporary points | Expired points | |
|---|---|---|---|
| Included in the balance | ✅ | ❌ | ❌ |
| Can be spent | ✅ | ❌ | ❌ |
| Processed by the temporary point fixing batch | ❌ | ✅ (fixed and added to the balance when the fix date arrives) | ❌ |
| Processed by the point expiration batch | ✅ (only the unspent portion expires after the expiration date) | ❌ | ❌ |
Operations that create temporary points and when they are fixed
Temporary points are created by the following operations. The timing of fixing depends on how the points were granted.
| Grant channel | Status when granted | When the points are fixed |
|---|---|---|
| Product purchase point grants (payment methods other than cash on delivery) | Temporary | Fixed and added to the balance when the sales processing is performed. The temporary period of the point settings does not apply. |
| Product purchase point grants (cash on delivery) | Temporary | The fix date (sales processing date + the temporary period of the point settings) is set when the sales processing is performed, and the points are fixed by the temporary point fixing batch after the fix date arrives. If no temporary period is set, the sales processing date becomes the fix date. |
| Login / member registration point grants (when a temporary period is set in the point settings) | Temporary | Fixed by the temporary point fixing batch after the fix date (grant date + temporary period) arrives. |
Point update API (ECPoint::update) grants with a future fix_date | Temporary | Fixed by the temporary point fixing batch after the specified fix date arrives. |
| Adding a row with the "Temporary" status in the point details on the member edit screen | Temporary | Fixed by the temporary point fixing batch after the entered fix date arrives. |
The following channels never create temporary points.
- Login / member registration point grants (no temporary period): Granted immediately as fixed points.
- Point update API (
fix_dateomitted, today, or a past date): Granted immediately as fixed points. - CSV upload / bulk_upsert API: Overwrites the balance (fixed points).
- member/insert and member/update APIs (with
allow_ec_pointenabled): Directly overwrite the balance (fixed points).
Automatic grants for product purchases, logins, and member registrations work only when a point grant condition is configured on the Point editor screen. For product purchases, the purchased product must also be linked to a point setting via the "Point rate" field in the Product settings. The point update API, CSV uploads, and operations on the member edit screen can be used without any point grant condition.
The temporary period is configured per point grant condition on the Point editor screen.
Point fixing and expiration batches
- Temporary point fixing batch: Fixes temporary points whose fix date has arrived and adds them to the balance.
- Point expiration batch (daily): Expires only the unspent portion of fixed lots whose expiration date (
expire_date) has passed. Points that have already been spent are never deducted twice. When points expire, a spending entry labeled "ポイント失効(...)" is added to the point history.
If the balance is smaller than the unspent portion of the lot (for example, when direct history edits have caused the balance and the lots to diverge), the deduction is limited to the available balance. The balance never goes negative, and the lot still becomes expired.
For the batch execution schedule, see Default batch processing list (ec_fix_point / ec_expire_point).
Even on sites with no e-commerce orders, the fixing and expiration batches run as long as point histories exist. Points managed via the API or CSV uploads are also fixed and expired.
Point operation channels
No matter which channel is used to operate points, every balance change leaves a point history entry.
| Channel | Balance update | Point history | Member update history | Spending with insufficient balance | Idempotency key |
|---|---|---|---|---|---|
Point update API (ECPoint::update) | Immediate (fixed). With a future fix_date, granted as temporary points (added to the balance after the fix date arrives) | ✅ Recorded (reason = reason in the request) | ❌ Not recorded | 422 error (nothing changes) | ✅ |
| CSV upload / bulk_upsert API | Overwrite | ✅ Difference recorded (reason = "CSVで更新") | ❌ Not recorded | — (always succeeds because it overwrites) | ❌ |
| Point details on the member edit screen (adding a fixed row) | Immediate | ✅ Recorded (reason = entered content) | ❌ Not recorded | Error shown (not applied) | ❌ |
| Total points field on the member edit screen | Not editable (display only) | — | — | — | — |
member/insert and member/update APIs (with allow_ec_point enabled) | Overwrite (direct update of the fixed points) | ✅ Difference recorded (reason = "Update by API") | ❌ Not recorded | — (always succeeds because it overwrites) | ❌ |
| Existing features such as e-commerce orders and campaigns | As before | ✅ Recorded | ❌ Not recorded | As before | ❌ |
Setting or updating ec_point via the member/insert and member/update APIs is possible only when allow_ec_point is enabled in the endpoint settings (it is disabled by default, and including ec_point in the request body returns an error). allow_ec_point is never honored on endpoints with self_only enabled. This channel overwrites the balance, and the difference is recorded in the point history (reason = "Update by API"; an increase is recorded as a grant and a decrease as a spend). Because idempotency keys and custom reasons are not available on this channel, we recommend using the point update API for external point operations.
Point update API (ECPoint::update)
This API increases or decreases a member's points from an external system.
Endpoint settings
Create an endpoint in the API settings of the admin panel.
| Field | Value |
|---|---|
| Model | ECPoint |
| Operation | update |
| HTTP method | POST |
Since this API can issue points, always operate it with authentication required. Exposing it without authentication can lead to fraudulent point issuance.
Request parameters
The request body is in application/json format.
| Parameter | Required | Description |
|---|---|---|
member_id | ✅ | Target member ID |
point | ✅ | Points to add or subtract (integers only; decimals and non-numeric values return an error). Positive value = grant, negative value = spend. 0 is not allowed. The maximum absolute value is 2,000,000,000 |
reason | ✅ | Reason for the update. Recorded in the point history and shown in the point history API and the admin panel |
expire_date | - | Expiration date of the granted points (e.g. 2030-12-31) |
fix_date | - | Fix (confirmation) date of the granted points (e.g. 2030-12-31). Allowed only for grants (positive point). When a future date is specified, the points are granted as temporary points and are fixed and added to the balance by the temporary point fixing batch after the fix date arrives. When omitted or set to today or a past date, the points are fixed immediately |
idempotency_key | - | Idempotency key (up to 255 characters). See Idempotency key |
Grant and spend behavior
| Grant (point > 0) | Spend (point < 0) | |
|---|---|---|
| Balance update | Added immediately (fixed points). With a future fix_date, granted as temporary points and added to the balance after the fix date arrives | Subtracted immediately |
| History entry | Granted points (add_point) plus remaining points | Used points (use_point) |
expire_date | ✅ Effective (no expiration if omitted; a past date expires at the next expiration batch) | ❌ Ignored |
fix_date | ✅ Effective (a future date grants temporary points; today, a past date, or omission fixes them immediately) | ❌ Returns a 422 error |
| Insufficient balance | — | 422 error. Neither the balance nor the history changes at all |
| Application order | — | Spent from the grants with the nearest expiration date |
Response
| Field | Description |
|---|---|
point | Balance after the update (unconfirmed temporary points are not included) |
ec_point_history_id | ID of the created point history entry |
Errors
| Code | Condition |
|---|---|
| 400 | JSON schema violation (unknown parameters, invalid types, etc.) |
| 401 | Invalid credentials |
| 404 | Member does not exist |
| 422 | point is 0, not an integer, or exceeds the maximum / reason is empty / expire_date is not a valid date / fix_date is not a valid date or is combined with spending (negative point) / idempotency_key exceeds 255 characters / insufficient balance / incorrect reuse of an idempotency key |
Idempotency key (idempotency_key)
The idempotency key prevents double grants and double deductions when a request is retried after a communication timeout or similar failure. We recommend specifying it for external integrations. Use a unique string such as an order number combined with an operation type.
| Retry pattern | Result |
|---|---|
Same key × same content (same member_id / point / expire_date / fix_date) | Not applied again. Returns the same ec_point_history_id as the first request and the current balance (200). On timeout, it is safe to resend the request as is with the same key |
Same key × different content (different member_id, point, expire_date, or fix_date) | 422 error (rejected as key reuse; nothing changes) |
| Key omitted or empty string | No idempotency check (applied every time) |
| Concurrent requests with the same key | Only one is applied; the other returns the result of the first request |
A request without fix_date means immediate fixing, so if the already-processed history is still a temporary point, the retry is treated as "different content" and returns a 422 error. Likewise, once temporary points granted with a future fix_date have been fixed, resending the same key with the original fix_date also returns a 422 error. In neither case is the update applied again.
Point history API (ECPoint::history)
This API retrieves a member's point history and current balance.
Endpoint settings
| Field | Value |
|---|---|
| Model | ECPoint |
| Operation | history |
| HTTP method | GET |
Usage patterns and parameters
| Usage pattern | Parameters | Notes |
|---|---|---|
| Administration / server-to-server integration (any member) | member_id | 404 if the member does not exist |
| Member-facing My Page (own history only) | self_only=1 | member_id is ignored. 401 if not logged in |
| Paging | cnt (items per page) / pageID (page number) | cnt defaults to 20 when omitted |
| Count only | only_count=1 | list is returned empty, pageInfo contains only totalCnt, and total_point is not returned |
Response
| Field | Description |
|---|---|
total_point | Current balance |
pageInfo | totalCnt / perPage / pageNo / totalPageCnt |
list | Array of history entries (newest first) |
The main fields of list are as follows.
| Field | Description |
|---|---|
add_point / add_reason | Granted points and reason |
use_point / use_reason | Spent points and reason |
point_status | 1 = fixed / 2 = temporary / 3 = expired |
remaining_point | Unspent remainder of a grant lot. Decreases with spending and expiration |
fix_date | Fix date |
expire_date | Scheduled expiration date (null if no expiration) |
inst_ymdhi / update_ymdhi | Created/updated datetime (ISO 8601) |
Internal information such as administrator names and idempotency keys of other systems are not included in the response.
Overwriting points via member CSV upload / bulk_upsert API
The ec_point column of the member CSV upload overwrites the point balance (the bulk_upsert API behaves the same way).
| CSV content | Balance | Point history |
|---|---|---|
ec_point column present with a value larger than the current balance | Overwritten | ✅ Difference recorded as a grant (reason = "CSVで更新") |
ec_point column present with a value smaller than the current balance | Overwritten | ✅ Difference recorded as spending |
ec_point column present with the same value as the current balance | No change | Not recorded |
ec_point column present but empty + empty-update setting ON | Cleared (empty) | ✅ The full previous balance recorded as spending |
New member row with ec_point | Set as the initial value | ✅ Initial balance recorded as a grant |
No ec_point column | No change at all (as before) | Not recorded |
If recording the point history fails for a row after the balance has been overwritten, the error "会員データは更新されましたが、ポイント履歴の記録に失敗しました。" (Member data was updated, but recording the point history failed.) is displayed. In this case, the member data of that row (including the balance overwrite) itself has been updated.
For the upload procedure, see Member upload.
Point operations on the admin panel (member edit screen)
To use the point info tab on the member edit screen on a site that does not use EC, enable Enable EC Point on the site management screen. When EC is in use, the point features are available regardless of this setting.
- The field for directly editing total points has been removed; the total is now display only.
- A "Remaining points" column has been added to the point details (history) table, showing the unspent remainder of fixed grant lots (i.e., how far spending and expiration have progressed).
Adding a row to the point details behaves as follows depending on its status.
| Status of the added row | Balance update | Notes |
|---|---|---|
| Fixed × grant | Added immediately | Recorded as a lot with remaining points |
| Fixed × spend | Subtracted immediately | If the balance is insufficient, an error occurs before saving, and nothing is saved, including the member information |
| Temporary | Not applied | Added to the balance by the fixing batch when the fix date arrives |
| Expired | Not applied | Recorded only |
- A fixed-status row cannot have both a grant and a spend entered on the same row.
- Existing history rows with fixed status cannot be edited or deleted, and the status of an existing row cannot be changed to fixed. Temporary points are fixed by the temporary point fixing batch.
For the field descriptions of the screen, see Member.
Notes and limitations
- Setting or updating
ec_pointvia the member/insert and member/update APIs is possible only whenallow_ec_pointis enabled in the endpoint settings (it is disabled by default, and includingec_pointin the request returns an error; it is never honored whenself_onlyis enabled). This channel overwrites the balance, and the difference is recorded in the point history with the reason "Update by API". Because idempotency keys and custom reasons are not available on this channel, we recommend the point update API, the bulk_upsert API, or CSV upload for external point operations. - The point expiration batch expires "only the unspent portion". It does not expire the full amount including already-spent points.
Related documents
Support
If you have any other questions, please contact us or check out Our Slack Community.