# Choose a connection point

Two questions narrow every integration requirement to one or two connection points: which way does the data move, and what starts the exchange? Volume and consistency then decide between the remaining options.

Zen Electron has five integration requirements on one whiteboard. This page sorts them before anyone chooses a technology.

## Connection points at a glance

Each summary below describes how a connection point behaves and links to its reference. Use the reference for field lists and exact limits.

### Direct API

The [HTTP API](/api) and [GraphQL API](/api/graphql.md) are synchronous: the caller waits for the result. Use them for on-demand reads and writes, from storefronts, back-office tools, and other systems.

At volume, the Direct API puts pagination, retries, and polling cost in your hands. Filter on `lastModifiedAt` to query for changes instead of fetching the full dataset. For the details, see the [query limits](/api/limits.md#queries), [Iterate over all elements](/api/general-concepts.md#iterate-over-all-elements), [Performance considerations](/api/predicates/query.md#performance-considerations), and [Client resiliency](/api/general-concepts.md#client-resiliency). For planned traffic peaks, contact the [commercetools support team](https://support.commercetools.com/) in advance.

### Import API

The [Import API](/api/import-export/overview.md) is asynchronous. You submit resources, and commercetools processes them in the background. The Import API resolves references between resources by `key`, so you can submit a Product before the Category it references. [Why choose the Import API?](/api/import-export/overview.md#why-choose-the-import-api) compares it with the other APIs.

- Monitor ImportOperations until they reach a final state. Missing references must resolve within the operation lifetime; see [ImportOperations and reference resolution](/api/import-export/overview.md#what-are-importoperations) for the current lifecycle and retry behavior.
- Changes are not visible immediately, so the Import API doesn't suit flows that need the result in the same request.

For hands-on practice, see the [Import API module](/learning-developer-essentials/import-api/overview.md).

### Subscriptions

[Subscriptions](/api/projects/subscriptions.md) send a notification to a message queue after a change is saved in commercetools. Your consumer reads the queue and acts.

- Choose the notification payload and queue from the supported [Subscription representations](/api/projects/subscriptions.md#representations).
- Plan fan-out in the queue service instead of creating one Subscription per consumer. This reduces pressure on the current [Subscription limit](/api/limit-increase-guidance.md#extensibility-and-eventing-limits).

### API Extensions

[API Extensions](/api/projects/api-extensions.md) call your service during a create or update request. Your service can approve the request, reject it, or return update actions to apply.

- An API Extension applies to requests from every API client, including the Merchant Center.
- Each Extension supports a defined set of resources. Before selecting an Extension for a resource, check the supported resources, [conditional triggers](/api/projects/api-extensions.md#conditional-triggers), [Extension chaining](/api/projects/api-extensions.md#extension-chaining), and the [Extension input](/api/projects/api-extensions.md#input).

### Merchant Center customizations

[Custom Applications and Custom Views](/merchant-center-customizations/overview.md) add screens to the Merchant Center. Use them when a business user starts or reviews the work.

## Choose by direction and trigger

Start with two questions: which way does the data move, and what starts the exchange? The following decision tree maps the answers to a connection point:

```mermaid
flowchart TD
 Q["What starts the exchange,<br/>and which way does data move?"]

 Q -->|"A system or user needs data<br/>or must write it now"| DIRECT["Direct API"]
 Q -->|"An external system pushes<br/>a change to you"| ENDPOINT["Your endpoint"]
 ENDPOINT --> INBOUND{"Volume and<br/>consistency?"}
 Q -->|"A rule must hold during<br/>a commercetools write"| EXT["API Extension<br/>or application-side logic"]
 Q -->|"React after something<br/>changes in commercetools"| SUBS["Subscription"]
 Q -->|"A schedule"| JOB["Job or scheduler"]
 JOB --> INBOUND
 Q -->|"You load data from<br/>another system"| INBOUND
 Q -->|"A business user in the<br/>Merchant Center"| MC["Custom Application<br/>or Custom View"]

 INBOUND -->|"Low volume, or the<br/>result is needed now"| DIRECT2["Direct API"]
 INBOUND -->|"High volume, eventual<br/>consistency is acceptable"| IMPORT2["Import API"]

 classDef point fill:#e8f1fb,stroke:#2266a5,color:#16324a
 class DIRECT,EXT,SUBS,MC,DIRECT2,IMPORT2 point
```

The tree has two refinements:

- **Inbound flows can use either the Direct API or the Import API.** Whether a source pushes changes, a schedule starts a job, or you load data in bulk, volume and consistency decide. Choose the Direct API when volumes are low or the caller needs the result immediately. Choose the Import API for large volumes when a short delay is acceptable.
- **Scheduled flows are not a separate connection point.** A job runs on a schedule and then calls the Direct API or the Import API.

### The task view

Teams often describe integrations as tasks. The following table maps each task to the direction and trigger, and then to the usual connection point:

| Task | Direction and trigger | Usual connection point |
| --- | --- | --- |
| Import data from a PIM or ERP | Inbound; pushed by the source or pulled on a schedule | Import API for bulk loads; Direct API for low-volume changes |
| Export data to an OMS, search engine, or warehouse | Outbound; after a change, or on a schedule for backfills | Subscription; Direct API queries for backfills |
| React to a commercetools event, such as a new Order | Outbound; after a change | Subscription |
| Extend platform behavior, such as validating a Cart | In-request; during a write | API Extension or application-side logic |
| Serve a storefront or compose third-party data for shoppers | In-request; a shopper's client reads or writes | Direct API through your BFF, or the Commerce Integration Layer's [Experience API](/learning-integrate-with-commercetools/commerce-integration-layer/experience-api-overview.md) |

## Application-side logic or an API Extension

For in-request rules, you have two options:

- **Application-side logic**: your storefront or backend-for-frontend (BFF) runs the rule before it calls commercetools.
- **API Extension**: commercetools calls your service during the write.

The deciding question is which clients the rule must cover. Application-side logic only covers requests that pass through your application. An API Extension covers every API client, including the Merchant Center, a PIM writing Products, and other integrations.

| Characteristic | Application-side logic | API Extension |
| --- | --- | --- |
| Where it runs | In your application, before the API call | In your service, called by commercetools during the API call |
| Clients covered | Only clients that use your application | Every API client |
| Effect on API latency | None. Your application controls its own latency. | Adds the Extension's response time to the API call |
| Failure handling | Your application decides what the customer sees | The API call fails if the Extension times out or returns an invalid response |

Application-side logic gives you more control over the user experience and more freedom in how long the logic takes. An API Extension is the right choice when the rule must hold no matter how the resource is changed. [Price the contract](/learning-integrate-with-commercetools/integration-essentials/price-the-contract.md) covers what an Extension commits you to.

> The [Commerce Integration Layer's extension types](/learning-integrate-with-commercetools/commerce-integration-layer/extension-types.md) follow the same split. A schema extension is application-side logic: it runs at the edge and only covers traffic through the Commerce Integration Layer. A Managed API Extension is an API Extension that the Commerce Integration Layer hosts and registers, so it covers every API client.

Don't use an API Extension for side effects, such as sending an email or pushing an Order to an ERP. Side effects belong in a Subscription consumer, so they don't slow down or fail the original request.

## Worked example: classify Zen Electron's requirements

Zen Electron's team classifies each requirement by direction and trigger before choosing a connection point. The team labels the five integrations A to E, and the rest of this module uses the same labels:

| Integration | Direction and trigger | Volume and consistency | Connection point |
| --- | --- | --- | --- |
| A. Catalog and stock feed | Inbound; initial bulk load, then ongoing changes | 46,000 Products in the initial load; frequent, smaller stock changes | Import API for the initial load; Direct API or Import API for ongoing changes |
| B. Same-day metro delivery eligibility | In-request; during Cart creation and address changes | Every relevant Cart update; the result is needed in the same request | API Extension or application-side logic |
| C. Checkout payments | Checkout-driven; PSP webhooks arrive inbound | Every checkout | Defined by the payment Connector (see [Integrate a payment service provider](/guides/payment-integration.md)) |
| D. Order confirmation email | Outbound after an Order is saved | Every Order; a delay of a few minutes is acceptable | Subscription |
| E. Omnichannel back office | Outbound after Order and Customer changes; inbound webhooks; scheduled reconciliation | Every Order and Customer change | Subscriptions; your endpoints calling the Direct API; scheduled Direct API queries |

### Same-day metro delivery eligibility: application-side logic or an API Extension

The same-day metro delivery eligibility integration (B) sets `isMetroArea` on the Cart so that the same-day Shipping Method predicate can check it. Both options work, and they differ in coverage:

- **Application-side logic**: the Electronics High Tech storefront calls the eligibility service and sets the Custom Field before it updates the Cart. Carts created from the Merchant Center or by other clients don't get the value.
- **API Extension**: commercetools calls the eligibility service whenever a matching Cart changes, regardless of the client. Customer service agents creating Carts in the Merchant Center also get correct eligibility.

If Electronics High Tech only takes same-day orders through its storefront, application-side logic is enough. If agents also create Carts for customers, choose the Extension.

The following request creates the Extension, with a condition that calls it when a Cart is created and whenever the shipping address is set, changed, or removed. The condition doesn't filter by country, so the handler also sees an address that changes to a non-Australian or missing one. For those Carts, the handler sets `isMetroArea` to `false`, so the earlier Shipping Method predicate `custom.isMetroArea = true` stops passing:

```http title="Request: create the eligibility Extension"
POST https://api.australia-southeast1.gcp.commercetools.com/zen-electron/extensions
Authorization: Bearer {access_token}
Content-Type: application/json

{
  "key": "metro-delivery-eligibility",
  "destination": {
    "type": "HTTP",
    "url": "https://eligibility.example.com/cart-extension",
    "authentication": {
      "type": "AuthorizationHeader",
      "headerValue": "Bearer {extension_secret}"
    }
  },
  "triggers": [
    {
      "resourceTypeId": "cart",
      "actions": ["Create", "Update"],
      "condition": "shippingAddress has changed"
    }
  ],
  "timeoutInMs": 1000
}
```

- `condition` uses [Query Predicate syntax](/api/predicates/query.md#use-predicates-in-conditional-api-extensions). The `has changed` operator evaluates to true for every create, so the Extension is called for every new Cart, with or without a shipping address. On updates, it's called only when the address changes, including when it's removed. The handler decides eligibility from the country, and treats a Cart with no address as not eligible. [Conditional triggers](/api/projects/api-extensions.md#conditional-triggers) lists the evaluation outcomes.
- `timeoutInMs` is optional. [Price the contract](/learning-integrate-with-commercetools/integration-essentials/price-the-contract.md) explains how to choose a value.
- Authentication values, such as `headerValue`, are partially hidden when you retrieve the Extension. See [AuthorizationHeaderAuthentication](/search.md?urn=ctp:api:type:AuthorizationHeaderAuthentication).

### The order confirmation Subscription

The order confirmation email from [How integrations fit together](/learning-integrate-with-commercetools/integration-essentials/how-integrations-fit-together.md) reacts after an Order is saved, so it uses a Subscription:

```http title="Request: create the OrderCreated Subscription"
POST https://api.australia-southeast1.gcp.commercetools.com/zen-electron/subscriptions
Authorization: Bearer {access_token}
Content-Type: application/json

{
  "key": "order-created-to-sqs",
  "destination": {
    "type": "SQS",
    "queueUrl": "https://sqs.ap-southeast-2.amazonaws.com/123456789012/zen-order-events",
    "region": "ap-southeast-2",
    "authenticationMode": "IAM"
  },
  "messages": [
    { "resourceTypeId": "order", "types": ["OrderCreated"] }
  ]
}
```

- Prefer `IAM` for `authenticationMode`. [SQSDestination](/api/projects/subscriptions.md#sqsdestination) defines the queue type, the permissions to grant before you create the Subscription, and the default authentication mode.
- [SubscriptionDraft](/search.md?urn=ctp:api:type:SubscriptionDraft) defines which of `messages`, `changes`, and `events` the request must set.
- This request suits a consumer on your own infrastructure. If the consumer runs as a Connect `event` application instead, as in [Deploy and build Connectors](/learning-integrate-with-commercetools/deploy-and-build-connectors/overview.md), its `postDeploy` script creates the Subscription with the destination that Connect provides, so you don't create it yourself.

For step-by-step tutorials, see [Implement an API Extension](/guides/extensions.md) and [Subscribe to Messages](/guides/subscriptions.md).

## Key takeaways

- Direction and trigger narrow the choice of connection point. Volume and consistency decide between the Direct API and the Import API for inbound flows.
- Inbound pushes arrive at your endpoint, which then calls the Direct API or the Import API.
- Scheduled flows are a job calling the Direct API or the Import API, not a separate connection point.
- Choose an API Extension over application-side logic when a rule must hold for every API client.
- Use Subscriptions, not Extensions, for side effects.
- Fan notifications out in the queue service instead of creating one Subscription per consumer. Set `timeoutInMs` on each Extension for the work it does.

## Related pages

- [Area overview page with navigation](/learning-integrate-with-commercetools.md)
- [Previous page: How integrations fit together](/learning-integrate-with-commercetools/integration-essentials/how-integrations-fit-together.md)
- [Next page: Price the contract](/learning-integrate-with-commercetools/integration-essentials/price-the-contract.md)
- [Search documentation and API specs](/search.md)