Skip to content

mpac-pgw API Reference

Base URL: https://pgw.example.com (production) / http://localhost:8080 (development)

Authentication

HMAC-SHA256 (Server-to-Server)

Used for: Create, List, Capture, Sync endpoints.

Authorization: HMAC-SHA256 <api_key>:<timestamp>:<signature>

Message   = METHOD + "\n" + PATH + "\n" + TIMESTAMP + "\n" + HEX(SHA256(BODY))
Key       = bytes(HEX(SHA256(secret_key)))
Signature = HEX(HMAC-SHA256(Key, Message))

The HMAC key is the byte representation of the hex-encoded SHA-256 of the secret key (64 ASCII bytes), matching the secret_key_hash column in the database.

Timestamp window: 5 minutes.

payment_token (Client/Frontend)

Used for: Retrieve, Confirm, Cancel endpoints.

  • GET: ?payment_token=<token>
  • POST: { "payment_token": "<token>" } in request body

Endpoints

Health Check

GET /health

Returns service health status. No authentication required.

Response:

json
{
  "status": "ok"
}

Create PaymentIntent

POST /v1/payment_intents

Auth: HMAC-SHA256

Request Body:

json
{
  "amount": 1000,
  "currency": "JPY",
  "payment_method_types": ["qr_mpm"],
  "merchant_ref_id": "order_12345",
  "merchant_store_id": "store_001",
  "merchant_terminal_id": "terminal_001",
  "description": "Order #12345",
  "expires_in_minutes": 30
}
FieldTypeRequiredDescription
amountintegerYesPayment amount in smallest currency unit
currencystringYesISO 4217 currency code (e.g., JPY)
payment_method_typesstring[]YesAllowed payment methods
merchant_ref_idstringYesMerchant's order reference
merchant_store_idstringNoStore identifier
merchant_terminal_idstringNoTerminal identifier
descriptionstringNoHuman-readable description
expires_in_minutesintegerNoExpiry time (default: 30)

Response (201):

json
{
  "id": "pi_01JXXXXXXXXXXXXXXXXXXXXXXXXX",
  "status": "requires_payment_method",
  "amount": 1000,
  "currency": "JPY",
  "payment_method_types": ["qr_mpm"],
  "merchant_ref_id": "order_12345",
  "merchant_store_id": "store_001",
  "payment_token": "pi_01JX..._secret_abc123def456",
  "created_at": "2026-01-15T10:00:00Z",
  "expires_at": "2026-01-15T10:30:00Z"
}

List PaymentIntents

GET /v1/payment_intents

Auth: HMAC-SHA256

Query Parameters:

ParameterTypeDescription
merchant_store_idstringFilter by store
statusstringFilter by status
limitintegerMax results (default: 20, max: 100)
offsetintegerPagination offset

Response (200):

json
[
  {
    "id": "pi_01JXXXXXXXXXXXXXXXXXXXXXXXXX",
    "status": "succeeded",
    "amount": 1000,
    "currency": "JPY",
    ...
  }
]

Retrieve PaymentIntent

GET /v1/payment_intents/:id

Auth: payment_token (query parameter)

Response (200):

json
{
  "id": "pi_01JXXXXXXXXXXXXXXXXXXXXXXXXX",
  "status": "requires_payment_method",
  "amount": 1000,
  "currency": "JPY",
  "payment_method_types": ["qr_mpm"],
  "merchant_ref_id": "order_12345",
  "created_at": "2026-01-15T10:00:00Z",
  "expires_at": "2026-01-15T10:30:00Z"
}

Confirm PaymentIntent

POST /v1/payment_intents/:id/confirm

Auth: payment_token (in body)

Request Body:

json
{
  "payment_token": "pi_01JX..._secret_abc123def456",
  "payment_method_type": "qr_mpm",
  "provider": "PAYPAY"
}

Response (200):

json
{
  "payment_id": "pi_01JXXXXXXXXXXXXXXXXXXXXXXXXX",
  "qr_content": "https://qr.paypay.ne.jp/...",
  "expires_at": "2026-01-15T10:05:00Z",
  "provider": "PAYPAY"
}

Cancel PaymentIntent

POST /v1/payment_intents/:id/cancel

Auth: payment_token (in body)

Request Body:

json
{
  "payment_token": "pi_01JX..._secret_abc123def456"
}

Response (200):

json
{
  "id": "pi_01JXXXXXXXXXXXXXXXXXXXXXXXXX",
  "status": "cancelled"
}

Capture PaymentIntent

POST /v1/payment_intents/:id/capture

Auth: HMAC-SHA256

Used for manual processing mode (e.g., cash payments confirmed by staff).

Request Body:

json
{
  "amount": 1000
}

Response (200):

json
{
  "id": "pi_01JXXXXXXXXXXXXXXXXXXXXXXXXX",
  "status": "succeeded",
  "amount": 1000,
  "currency": "JPY"
}

Sync Merchants

POST /v1/sync/merchants

Auth: HMAC-SHA256

Synchronizes merchant and store data from the upstream system. Uses UPSERT semantics.

Request Body:

json
{
  "merchants": [
    {
      "id": "merchant_001",
      "name": "Example Restaurant Chain",
      "stores": [
        {
          "id": "store_001",
          "name": "Tokyo Branch",
          "payment_processor_configs": [
            {
              "provider": "PAYPAY",
              "is_active": true,
              "credentials": {
                "merchant_id": "paypay_merchant_123"
              }
            }
          ]
        }
      ]
    }
  ]
}

Response (200):

json
{
  "synced_merchants": 1,
  "synced_stores": 1
}

Webhooks

PayPay Webhook

POST /v1/webhooks/paypay

Receives payment status updates from PayPay. Authenticated via PayPay's webhook signature.

Error Responses

All error responses follow a consistent format:

json
{
  "code": "invalid_request",
  "message": "Amount must be greater than 0",
  "details": {
    "field": "amount",
    "constraint": "min_value"
  }
}

Common Error Codes

HTTP StatusCodeDescription
400invalid_requestRequest validation failed
401unauthorizedMissing or invalid authentication
401invalid_tokenPayment token is invalid or expired
403forbiddenInsufficient permissions
404not_foundResource not found
409idempotency_conflictConflicting idempotent request
429rate_limit_exceededRate limit exceeded
500internal_errorServer error

Rate Limiting

ScopeLimit
Per merchant1,000 requests/minute
Global10,000 requests/minute

Rate limit headers are included in all responses:

  • X-RateLimit-Limit: Maximum requests allowed
  • X-RateLimit-Remaining: Remaining requests in window
  • X-RateLimit-Reset: Unix timestamp when window resets

Idempotency

POST requests support idempotency via the Idempotency-Key header. Keys are cached for 24 hours.

Idempotency-Key: unique-request-id-12345

If a duplicate key is received within the retention window, the original response is returned without re-executing the operation.

MPAC — MP-Solution Advanced Cloud Service