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) | ❌ | ❌ |
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) | ✅ 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/update API (member info update API) | Cannot update (ec_point returns an error) | — | — | — | — |
| Existing features such as e-commerce orders and campaigns | As before | ✅ Recorded | ❌ Not recorded | As before | ❌ |
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) |
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 (granted as fixed points, never as temporary points) | 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 |
| 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 |
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 / 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) | 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, or expire_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 |
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)
- 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
- The member/update API (member info update API) cannot update
ec_point(including it in the request returns an error). To operate points externally, use the point update API, the bulk_upsert API, or CSV upload. - 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.