Skip to content

New: AI agent integration via Model Context Protocol (MCP).Learn more

REST endpoints & webhooks

Evolve services primarily expose a GraphQL subgraph for client consumption. REST endpoints are used for integrations that don’t fit the GraphQL model: webhook callbacks from external providers, session management, commercetools API extensions, and payment flows.

GraphQL is the API for frontend clients and service-to-service queries through federation. All product, cart, account, and order operations go through GraphQL.

REST is used when:

  • An external system pushes data in (payment webhooks, CMS webhooks)
  • The protocol requires it (commercetools API extensions, OAuth token endpoints)
  • The interaction is a simple request/response without the flexibility needs of GraphQL (session creation, health checks)

Each payment provider sends asynchronous status updates through webhook callbacks. Every provider’s webhook endpoint follows the same pattern but uses provider-specific verification:

sequenceDiagram
    participant PSP as Payment provider
    participant WH as Webhook endpoint
    participant CT as commercetools
    participant Bus as Event bus

    PSP->>WH: POST /push (status update)
    WH->>WH: Verify signature
    WH->>CT: Update transaction status
    CT-->>WH: Confirmation
    CT->>Bus: PaymentStatusStateTransition event
    WH-->>PSP: 200 OK / 202 Accepted

Method: HMAC

Validates each notificationItem with hmacValidator.validateHMAC() using ADYEN_HMAC_KEY. Returns 202 Accepted on success, 401 on invalid HMAC.

Adyen decouples webhook acknowledgement from processing. The webhook handler publishes each notification to an internal queue and returns 202 immediately. A separate consumer processes notifications and updates commercetools. This prevents Adyen from timing out and retrying when commercetools mutations are slow.

The Invoice provider (pay on account) is fully offline: there is no PSP to call back, so it exposes no webhook endpoint.

The account service exposes REST endpoints for session management. These are documented in detail in Authentication & tokens:

  • POST /api/create-session: creates an anonymous session (REST alternative to the createGuestSession mutation)
  • POST /token/anonymous: creates an anonymous session with raw token info (used by server-side consumers)
  • POST /api/client-context: returns customer metadata for a given access token (cached in Redis)

commercetools API extensions are synchronous HTTP callbacks that fire when resources are created or updated. They allow services to modify resources during the API call, for example setting defaults on a new cart or generating an order number.

The checkout service registers extensions for:

Resource Action Behavior
Cart Create Copies customer addresses and email onto the cart. For B2B, uses the business unit’s addresses.
Cart Update Auto-selects a default shipping method when a shipping address is set.
Order Create Generates a unique order number, ensures customer email is set, applies default order type.
Payment Create Transitions the payment to the PaymentInitial state.

Extensions are registered through Terraform with a shared secret for authentication:

resource "commercetools_api_extension" "main" {
destination {
type = "HTTP"
url = "${api_gateway_hostname}/${service_name}/extension"
authorization_header = "Bearer ${random_password.api_extension_secret.result}"
}
trigger {
resource_type_id = "cart"
actions = ["Create", "Update"]
}
trigger {
resource_type_id = "order"
actions = ["Create"]
}
trigger {
resource_type_id = "payment"
actions = ["Create"]
}
}

The service validates the Authorization: Bearer <secret> header on every extension request. The handler dispatches based on the resource type and action, then returns update actions or errors:

const handlers = {
cart: {
Create: createCartExtension,
Update: updateCartExtension,
},
order: {
Create: createOrderExtension,
},
payment: {
Create: (payment) => ({
actions: [{ action: "transitionState", state: { typeId: "state", key: "PaymentInitial" } }],
}),
},
};

Because API extensions are synchronous, they add latency to the commercetools API call. Keep extension logic fast and avoid external API calls where possible.