Subscribe to an API¶
What happens
A developer subscribes one of their applications to a published API and picks a subscription tier, e.g. Gold. APIM stores one row in AM_SUBSCRIPTION that joins the application to the API. That row is the "permission slip" the gateway checks on every call.
Who: Developer (Dev Portal) · Tables written: AM_SUBSCRIPTION, optionally AM_WORKFLOWS · Tables read: AM_API, AM_APPLICATION, AM_POLICY_SUBSCRIPTION, AM_TIER_PERMISSIONS
How the tables connect¶
A subscription is the join between an application and an API. It also names a tier.
erDiagram
AM_APPLICATION ||--o{ AM_SUBSCRIPTION : "subscribes via"
AM_API ||--o{ AM_SUBSCRIPTION : "is subscribed by"
AM_SUBSCRIPTION }o..|| AM_POLICY_SUBSCRIPTION : "logical: TIER_ID = NAME"
- An application can subscribe to many APIs, and an API can have many subscribing applications.
- The tier is matched by name (plus tenant), not by a foreign key.
The flow at a glance¶
sequenceDiagram
actor Dev as Developer
participant Portal as Dev Portal
participant DB as APIM DB
participant GW as Gateway
Dev->>Portal: Subscribe PizzaApp to PizzaShack (Gold)
Portal->>DB: check tier allowed (AM_TIER_PERMISSIONS)
Portal->>DB: insert AM_SUBSCRIPTION (UNBLOCKED, or ON_HOLD if approval on)
Portal->>DB: insert AM_WORKFLOWS (only if approval on)
Portal-->>GW: event "subscription created"
Portal-->>Dev: Subscribed
- Gateways learn about new subscriptions through events, and keep a copy in memory. They don't query this table on every call.
Step by step¶
-
Checks.
- The API must be Published (or Prototyped), and the tier must be one the API offers. The offered tiers are kept in the API's registry artifact.
- If an admin restricted the tier to certain roles,
AM_TIER_PERMISSIONS(TIER,PERMISSIONS_TYPE,ROLES) is checked.
-
Subscription row. One row goes into
AM_SUBSCRIPTION:APPLICATION_ID→AM_APPLICATION(FK, cascade).API_ID→AM_API(FK, cascade). This works for API products too.TIER_ID→ the tier name, e.g.Gold.SUB_STATUS→UNBLOCKEDstraight away, orON_HOLDwhile waiting for approval.SUBS_CREATE_STATE→SUBSCRIBE.UUID→ used by the REST APIs.
SUBSCRIPTION_ID APPLICATION_ID API_ID TIER_ID SUB_STATUS SUBS_CREATE_STATE UUID 1 2 (PizzaApp) 1 (PizzaShack 1.0.0) Gold UNBLOCKED SUBSCRIBE 1e67…TIER_ID_PENDINGis filled in too (Gold), andLAST_ACCESSEDstaysNULL.Logical link (no foreign key)
AM_SUBSCRIPTION.TIER_IDmatchesAM_POLICY_SUBSCRIPTION.NAMEfor the same tenant. Deleting a tier doesn't touch existing subscriptions. APIM blocks that delete in code instead. -
Approval (optional). With the subscription creation workflow on, APIM adds an
AM_WORKFLOWSrow withWF_TYPE = 'AM_SUBSCRIPTION_CREATION'andWF_REFERENCE = SUBSCRIPTION_ID.SUB_STATUSstaysON_HOLDuntil the workflow is approved (→UNBLOCKED) or rejected (→REJECTED). -
Later changes. All of these update the same row:
Action What changes in AM_SUBSCRIPTIONDeveloper requests a different tier TIER_ID_PENDINGholds the new tier, andSUB_STATUS = 'TIER_UPDATE_PENDING'until it's approved (workflow typeAM_SUBSCRIPTION_UPDATE)Publisher blocks the subscription SUB_STATUS = 'BLOCKED', or'PROD_ONLY_BLOCKED'to block only production keysDeveloper unsubscribes The row is deleted. With a deletion workflow, SUBS_CREATE_STATE = 'UNSUBSCRIBE'until it's approved
What gets cleaned up¶
- Deleting the application cascades and removes its subscriptions.
- The FK to
AM_APIwould cascade too, but APIM refuses to delete an API that still has subscriptions (HTTP 409, "active subscriptions exist"). You have to remove the subscriptions first. - Unsubscribing deletes the row and sends an event, so the gateways drop it from memory.
Try it¶
This query answers "which applications can call PizzaShack, and at which tier?".
SELECT ap.NAME AS APPLICATION, s.USER_ID AS OWNER,
sub.TIER_ID, sub.SUB_STATUS, p.QUOTA, p.TIME_UNIT
FROM AM_SUBSCRIPTION sub
JOIN AM_APPLICATION ap ON ap.APPLICATION_ID = sub.APPLICATION_ID
JOIN AM_SUBSCRIBER s ON s.SUBSCRIBER_ID = ap.SUBSCRIBER_ID
JOIN AM_API a ON a.API_ID = sub.API_ID
LEFT JOIN AM_POLICY_SUBSCRIPTION p ON p.NAME = sub.TIER_ID AND p.TENANT_ID = s.TENANT_ID
WHERE a.API_NAME = 'PizzaShackAPI' AND a.API_VERSION = '1.0.0';
Different in 3.x
In 3.x, both FKs on AM_SUBSCRIPTION are ON DELETE RESTRICT. That means you can't delete an application or API while subscriptions exist, so APIM's code deletes the subscriptions first. See 3.x: Subscribe to an API.
Related domains: Applications & subscriptions · Throttling policies · Workflows