Skip to main content
POST
/
v1
/
actions
curl --request POST \
  --url https://api.mageloyalty.com/v1/actions \
  --header 'Authorization: <api-key>' \
  --header 'Content-Type: application/json' \
  --data '{
  "action_key": "mobile_app_install",
  "customer_id": "6789012345",
  "idempotency_key": "install-6789012345-ios"
}'
{
  "data": {
    "type": "earning_history_entry",
    "id": "cer_abc123",
    "attributes": {
      "earning_rule_id": "rule_abc",
      "action": "custom",
      "points": 100,
      "points_balance": 1200,
      "status": "approved",
      "idempotency_key": "install-6789012345-ios",
      "replayed": false,
      "points_given_at": "2026-06-23T12:00:00.000Z",
      "points_due_at": null,
      "created_at": "2026-06-23T12:00:00.000Z"
    }
  }
}
Custom actions let you award points for things that happen outside Shopify — a mobile app install, an in-app purchase, an event check-in, a completed survey, or any milestone your own systems track. You create a custom action once in the Mage admin (Loyalty Program → Earning rules → Advanced → Custom Action), give it a stable action key, then call this endpoint from your backend whenever the action happens. You can also trigger it with no code using the Shopify Flow action.
Custom actions are available on the Growth plan and above. The customer must already be a loyalty member — a call for someone who is not enrolled returns 404.
Points come from the rule’s configured amount, with any applicable VIP tier and bonus campaign multipliers applied automatically. Each rule is either once per customer or unlimited, depending on how you configured it.

Request body

FieldTypeRequiredDescription
action_keystringYesThe action key of the custom rule. Lowercase letters, numbers, and underscores only
customer_idstringConditionalShopify customer ID (numeric). Required if customer_email is not provided
customer_emailstringConditionalCustomer email. Required if customer_id is not provided
idempotency_keystringNoA unique value for this specific completion. A repeat with the same key returns the original award instead of granting again
metadataobjectNoFree-form context stored alongside the earning record

Idempotency

If you pass an idempotency_key, a repeated request with the same key for the same rule returns the original award with 200 OK and replayed: true — points are never granted twice. For an unlimited rule where each completion should count once, set the key to a stable id for that completion, such as an event id or order id.
An unlimited rule awards on every call. Without an idempotency_key there is nothing to deduplicate on, so any retry — a network failure, an app relaunch, a repeated event — awards again and double-grants points. Always send a stable idempotency_key per real completion on unlimited rules.Once-per-customer rules are protected regardless: a second award returns 409, with or without a key.

Validations

  • Customer must exist and not be excluded from the loyalty program
  • A custom action with the given action_key must exist and be active
  • For a once-per-customer rule, the customer must not have already been awarded this action

Response

Returns 201 Created on success, or 200 OK for an idempotent replay.
When the rule has an approval delay configured, status is pending, points_given_at is null, points_due_at reflects when the points will be approved, and points_balance excludes the pending points until then.
If the loyalty program is disabled, or test mode is filtering this customer, the request still succeeds with 200 OK but no points are awarded:
{
  "data": null,
  "meta": { "awarded": false, "reason": "program_disabled" }
}

Errors

StatusScenario
400action_key missing or invalid, neither customer_id nor customer_email provided, or invalid JSON
403Customer is excluded from the loyalty program
404No active custom action matches the action_key, or the customer is not a loyalty member
409A once-per-customer rule has already been awarded to this customer
429Rate limit exceeded (6 requests/second)
Example 409 response:
{
  "errors": [
    {
      "status": "409",
      "title": "Conflict",
      "detail": "Customer has already been awarded points for this action. The action is configured to award once per customer."
    }
  ]
}

Trigger from Shopify Flow

If you would rather not write code, add the Award Custom Action action to any Shopify Flow workflow and set:
  • Action key — the same key from the rule’s setup page
  • Customer — map a customer from the workflow’s trigger
  • Idempotency key (optional) — leave blank to use the Flow run id automatically, so a retried run never awards twice
Shopify Flow signs and sends the request for you, so no API key is needed for this path.
curl --request POST \
  --url https://api.mageloyalty.com/v1/actions \
  --header 'Authorization: <api-key>' \
  --header 'Content-Type: application/json' \
  --data '{
  "action_key": "mobile_app_install",
  "customer_id": "6789012345",
  "idempotency_key": "install-6789012345-ios"
}'
{
  "data": {
    "type": "earning_history_entry",
    "id": "cer_abc123",
    "attributes": {
      "earning_rule_id": "rule_abc",
      "action": "custom",
      "points": 100,
      "points_balance": 1200,
      "status": "approved",
      "idempotency_key": "install-6789012345-ios",
      "replayed": false,
      "points_given_at": "2026-06-23T12:00:00.000Z",
      "points_due_at": null,
      "created_at": "2026-06-23T12:00:00.000Z"
    }
  }
}