MuleSoft

MuleSoft API-Led Connectivity: ghid arhitectura

Petru Constantin
--10 min lectura
#mulesoft#api-led#integration-architecture#api-design#microservices

API-led connectivity transforma integrarea enterprise printr-o abordare pe straturi de API-uri reutilizabile. Acest ghid acopera pattern-uri arhitecturale, strategii de implementare si governance pentru o adoptare API-led de succes.

Straturile arhitecturii API-Led

Cele trei straturi ale arhitecturii:

┌─────────────────────────────────────────────────────────────────┐
│                    EXPERIENCE LAYER                              │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐       │
│  │ Mobile   │  │   Web    │  │ Partner  │  │   IoT    │       │
│  │   API    │  │   API    │  │   API    │  │   API    │       │
│  └────┬─────┘  └────┬─────┘  └────┬─────┘  └────┬─────┘       │
├───────┼─────────────┼─────────────┼─────────────┼──────────────┤
│       │    PROCESS LAYER          │             │              │
│  ┌────▼─────────────▼─────────────▼─────────────▼────┐         │
│  │              Order Process API                     │         │
│  └────┬─────────────┬─────────────┬─────────────┬────┘         │
│       │             │             │             │               │
│  ┌────▼────┐   ┌────▼────┐   ┌────▼────┐   ┌────▼────┐        │
│  │Customer │   │Inventory│   │ Payment │   │Shipping │        │
│  │ Process │   │ Process │   │ Process │   │ Process │        │
│  └────┬────┘   └────┬────┘   └────┬────┘   └────┬────┘        │
├───────┼─────────────┼─────────────┼─────────────┼──────────────┤
│       │    SYSTEM LAYER           │             │              │
│  ┌────▼────┐   ┌────▼────┐   ┌────▼────┐   ┌────▼────┐        │
│  │Salesforce│  │   SAP   │  │ Stripe  │  │   FedEx  │        │
│  │  sAPI   │   │  sAPI   │  │  sAPI   │  │  sAPI    │        │
│  └────┬────┘   └────┬────┘   └────┬────┘   └────┬────┘        │
└───────┼─────────────┼─────────────┼─────────────┼──────────────┘
        │             │             │             │
   [Salesforce]    [SAP ERP]    [Stripe]      [FedEx API]

Implementarea System API

System API-urile expun sisteme backend cu interfete standardizate:

Salesforce System API

<!-- salesforce-sapi.xml -->
<mule xmlns="http://www.mulesoft.org/schema/mule/core"
      xmlns:http="http://www.mulesoft.org/schema/mule/http"
      xmlns:salesforce="http://www.mulesoft.org/schema/mule/salesforce"
      xmlns:apikit="http://www.mulesoft.org/schema/mule/mule-apikit">
 
    <!-- API Router -->
    <flow name="salesforce-sapi-main">
        <http:listener config-ref="HTTPS_Listener_Config" path="/api/*">
            <http:response statusCode="#[vars.httpStatus default 200]">
                <http:headers>#[vars.responseHeaders default {}]</http:headers>
            </http:response>
        </http:listener>
 
        <!-- Client ID enforcement -->
        <apikit:router config-ref="salesforce-sapi-config"/>
    </flow>
 
    <!-- GET /customers -->
    <flow name="get:\customers:salesforce-sapi-config">
        <ee:transform doc:name="Build Query">
            <ee:message>
                <ee:set-payload><![CDATA[%dw 2.0
output text/plain
var searchTerm = attributes.queryParams.search default ""
var limit = attributes.queryParams.limit default 100
var offset = attributes.queryParams.offset default 0
---
"SELECT Id, Name, Email, Phone, Industry, BillingCity, BillingCountry,
        CreatedDate, LastModifiedDate
 FROM Account
 WHERE IsDeleted = false" ++
 (if (searchTerm != "") " AND Name LIKE '%" ++ searchTerm ++ "%'" else "") ++
 " ORDER BY Name
 LIMIT " ++ (limit as String) ++
 " OFFSET " ++ (offset as String)]]></ee:set-payload>
            </ee:message>
        </ee:transform>
 
        <salesforce:query config-ref="Salesforce_Config" doc:name="Query Accounts"/>
 
        <ee:transform doc:name="Transform to Canonical">
            <ee:message>
                <ee:set-payload><![CDATA[%dw 2.0
output application/json
---
{
    metadata: {
        totalRecords: sizeOf(payload),
        offset: attributes.queryParams.offset default 0,
        limit: attributes.queryParams.limit default 100,
        source: "salesforce"
    },
    customers: payload map {
        id: $.Id,
        externalId: $.Id,
        name: $.Name,
        email: $.Email,
        phone: $.Phone,
        industry: $.Industry,
        address: {
            city: $.BillingCity,
            country: $.BillingCountry
        },
        createdAt: $.CreatedDate,
        updatedAt: $.LastModifiedDate
    }
}]]></ee:set-payload>
            </ee:message>
        </ee:transform>
    </flow>
 
    <!-- GET /customers/{customerId} -->
    <flow name="get:\customers\(customerId):salesforce-sapi-config">
        <salesforce:query-single config-ref="Salesforce_Config" doc:name="Get Account">
            <salesforce:salesforce-query><![CDATA[
                SELECT Id, Name, Email, Phone, Industry, Website, Description,
                       BillingStreet, BillingCity, BillingState, BillingPostalCode, BillingCountry,
                       ShippingStreet, ShippingCity, ShippingState, ShippingPostalCode, ShippingCountry,
                       NumberOfEmployees, AnnualRevenue, CreatedDate, LastModifiedDate
                FROM Account
                WHERE Id = ':customerId'
            ]]></salesforce:salesforce-query>
            <salesforce:parameters><![CDATA[#[{
                customerId: attributes.uriParams.customerId
            }]]]></salesforce:parameters>
        </salesforce:query-single>
 
        <choice doc:name="Check Result">
            <when expression="#[payload != null]">
                <ee:transform doc:name="Transform Response">
                    <ee:message>
                        <ee:set-payload><![CDATA[%dw 2.0
output application/json
---
{
    id: payload.Id,
    externalId: payload.Id,
    name: payload.Name,
    email: payload.Email,
    phone: payload.Phone,
    website: payload.Website,
    industry: payload.Industry,
    description: payload.Description,
    employees: payload.NumberOfEmployees,
    revenue: payload.AnnualRevenue,
    billingAddress: {
        street: payload.BillingStreet,
        city: payload.BillingCity,
        state: payload.BillingState,
        postalCode: payload.BillingPostalCode,
        country: payload.BillingCountry
    },
    shippingAddress: {
        street: payload.ShippingStreet,
        city: payload.ShippingCity,
        state: payload.ShippingState,
        postalCode: payload.ShippingPostalCode,
        country: payload.ShippingCountry
    },
    createdAt: payload.CreatedDate,
    updatedAt: payload.LastModifiedDate,
    _links: {
        self: "/customers/" ++ payload.Id,
        contacts: "/customers/" ++ payload.Id ++ "/contacts",
        orders: "/customers/" ++ payload.Id ++ "/orders"
    }
}]]></ee:set-payload>
                    </ee:message>
                </ee:transform>
            </when>
            <otherwise>
                <raise-error type="APP:NOT_FOUND" description="Customer not found"/>
            </otherwise>
        </choice>
    </flow>
 
    <!-- POST /customers -->
    <flow name="post:\customers:application\json:salesforce-sapi-config">
        <ee:transform doc:name="Map to Salesforce">
            <ee:message>
                <ee:set-payload><![CDATA[%dw 2.0
output application/java
---
[{
    Name: payload.name,
    Email: payload.email,
    Phone: payload.phone,
    Website: payload.website,
    Industry: payload.industry,
    Description: payload.description,
    NumberOfEmployees: payload.employees,
    BillingStreet: payload.billingAddress.street,
    BillingCity: payload.billingAddress.city,
    BillingState: payload.billingAddress.state,
    BillingPostalCode: payload.billingAddress.postalCode,
    BillingCountry: payload.billingAddress.country
}]]]></ee:set-payload>
            </ee:message>
        </ee:transform>
 
        <salesforce:create config-ref="Salesforce_Config" type="Account" doc:name="Create Account"/>
 
        <ee:transform doc:name="Build Response">
            <ee:message>
                <ee:set-payload><![CDATA[%dw 2.0
output application/json
---
{
    id: payload[0].id,
    success: payload[0].success,
    message: if (payload[0].success) "Customer created successfully"
             else payload[0].errors[0].message
}]]></ee:set-payload>
            </ee:message>
            <ee:variables>
                <ee:set-variable variableName="httpStatus">
                    #[if (payload[0].success) 201 else 400]
                </ee:set-variable>
            </ee:variables>
        </ee:transform>
    </flow>
</mule>

SAP System API

<!-- sap-sapi.xml -->
<flow name="get:\products:sap-sapi-config">
    <ee:transform doc:name="Build RFC Parameters">
        <ee:message>
            <ee:set-payload><![CDATA[%dw 2.0
output application/java
---
{
    I_MATERIAL_TYPE: attributes.queryParams.type default "*",
    I_PLANT: attributes.queryParams.plant default "1000",
    I_MAX_ROWS: attributes.queryParams.limit default 100
}]]></ee:set-payload>
        </ee:message>
    </ee:transform>
 
    <!-- Call SAP RFC/BAPI -->
    <sap:execute-synchronous-remote-function-call
        config-ref="SAP_Config"
        functionName="BAPI_MATERIAL_GETLIST"
        doc:name="Get Materials">
        <sap:content>#[payload]</sap:content>
    </sap:execute-synchronous-remote-function-call>
 
    <ee:transform doc:name="Transform to Canonical">
        <ee:message>
            <ee:set-payload><![CDATA[%dw 2.0
output application/json
 
var materials = payload.MATNRLIST default []
var returnMessages = payload.RETURN default []
---
{
    metadata: {
        totalRecords: sizeOf(materials),
        source: "sap",
        plant: attributes.queryParams.plant default "1000"
    },
    products: materials map {
        id: $.MATERIAL,
        sku: $.MATERIAL,
        name: $.MATL_DESC,
        type: $.MATL_TYPE,
        group: $.MATL_GROUP,
        unit: $.BASE_UOM,
        status: $.MATL_STATUS default "active",
        plant: $.PLANT
    },
    (warnings: returnMessages filter ($.TYPE == "W") map $.MESSAGE)
        if (sizeOf(returnMessages filter ($.TYPE == "W")) > 0)
}]]></ee:set-payload>
        </ee:message>
    </ee:transform>
</flow>
 
<flow name="get:\inventory\{productId}:sap-sapi-config">
    <sap:execute-synchronous-remote-function-call
        config-ref="SAP_Config"
        functionName="BAPI_MATERIAL_STOCK_REQ_LIST"
        doc:name="Get Stock">
        <sap:content><![CDATA[#[{
            MATERIAL: attributes.uriParams.productId,
            PLANT: attributes.queryParams.plant default "1000"
        }]]]></sap:content>
    </sap:execute-synchronous-remote-function-call>
 
    <ee:transform doc:name="Transform Stock Response">
        <ee:message>
            <ee:set-payload><![CDATA[%dw 2.0
output application/json
 
var stockData = payload.STOCK_REQ_LIST default []
---
{
    productId: attributes.uriParams.productId,
    plant: attributes.queryParams.plant default "1000",
    inventory: {
        available: sum(stockData.AVAIL_QTY default [0]),
        reserved: sum(stockData.RES_QTY default [0]),
        blocked: sum(stockData.BLOCK_QTY default [0]),
        inTransit: sum(stockData.TRANSIT_QTY default [0])
    },
    locations: stockData map {
        storageLocation: $.STGE_LOC,
        available: $.AVAIL_QTY,
        reserved: $.RES_QTY,
        unit: $.BASE_UOM
    },
    lastUpdated: now()
}]]></ee:set-payload>
        </ee:message>
    </ee:transform>
</flow>

Implementarea Process API

Process API-urile orchestreaza procese de business pe mai multe System API-uri:

<!-- order-process-api.xml -->
<flow name="post:\orders:application\json:order-papi-config">
    <set-variable variableName="orderRequest" value="#[payload]" doc:name="Store Order Request"/>
    <set-variable variableName="orderId" value="#[uuid()]" doc:name="Generate Order ID"/>
 
    <!-- Pasul 1: Valideaza clientul -->
    <flow-ref name="validate-customer" doc:name="Validate Customer"/>
 
    <!-- Pasul 2: Verifica stocul -->
    <flow-ref name="check-inventory" doc:name="Check Inventory"/>
 
    <!-- Pasul 3: Calculeaza pretul -->
    <flow-ref name="calculate-pricing" doc:name="Calculate Pricing"/>
 
    <!-- Pasul 4: Proceseaza plata -->
    <flow-ref name="process-payment" doc:name="Process Payment"/>
 
    <!-- Pasul 5: Creeaza inregistrarile comenzii -->
    <flow-ref name="create-order-records" doc:name="Create Order Records"/>
 
    <!-- Pasul 6: Rezerva stocul -->
    <flow-ref name="reserve-inventory" doc:name="Reserve Inventory"/>
 
    <!-- Pasul 7: Initiaza fulfillment-ul -->
    <flow-ref name="initiate-fulfillment" doc:name="Initiate Fulfillment"/>
 
    <!-- Construieste raspunsul -->
    <ee:transform doc:name="Build Order Response">
        <ee:message>
            <ee:set-payload><![CDATA[%dw 2.0
output application/json
---
{
    orderId: vars.orderId,
    status: "CONFIRMED",
    customer: vars.customerDetails,
    items: vars.pricedItems,
    totals: vars.orderTotals,
    payment: {
        transactionId: vars.paymentResult.transactionId,
        status: vars.paymentResult.status
    },
    fulfillment: {
        estimatedDelivery: vars.fulfillmentDetails.estimatedDelivery,
        trackingAvailable: vars.fulfillmentDetails.trackingAvailable
    },
    createdAt: now()
}]]></ee:set-payload>
        </ee:message>
    </ee:transform>
 
    <!-- Error Handler cu compensare -->
    <error-handler>
        <on-error-propagate type="ANY">
            <flow-ref name="compensate-order-failure" doc:name="Compensation"/>
        </on-error-propagate>
    </error-handler>
</flow>
 
<sub-flow name="validate-customer">
    <http:request
        method="GET"
        config-ref="Salesforce_SAPI_Config"
        path="/customers/{customerId}"
        doc:name="Get Customer">
        <http:uri-params><![CDATA[#[{
            customerId: vars.orderRequest.customerId
        }]]]></http:uri-params>
    </http:request>
 
    <choice doc:name="Check Customer Status">
        <when expression="#[payload.status == 'SUSPENDED']">
            <raise-error type="APP:CUSTOMER_SUSPENDED" description="Customer account is suspended"/>
        </when>
    </choice>
 
    <set-variable variableName="customerDetails" value="#[payload]" doc:name="Store Customer"/>
</sub-flow>
 
<sub-flow name="check-inventory">
    <scatter-gather doc:name="Check All Items">
        <route>
            <foreach collection="#[vars.orderRequest.items]" doc:name="For Each Item">
                <http:request
                    method="GET"
                    config-ref="SAP_SAPI_Config"
                    path="/inventory/{productId}"
                    doc:name="Check Stock">
                    <http:uri-params><![CDATA[#[{
                        productId: payload.productId
                    }]]]></http:uri-params>
                </http:request>
 
                <choice doc:name="Validate Stock">
                    <when expression="#[payload.inventory.available &lt; vars.rootMessage.payload.quantity]">
                        <raise-error type="APP:INSUFFICIENT_STOCK"
                                     description='Insufficient stock for $(payload.productId)'/>
                    </when>
                </choice>
            </foreach>
        </route>
    </scatter-gather>
 
    <set-variable variableName="inventoryChecked" value="#[true]" doc:name="Mark Inventory Checked"/>
</sub-flow>
 
<sub-flow name="process-payment">
    <http:request
        method="POST"
        config-ref="Stripe_SAPI_Config"
        path="/payments"
        doc:name="Create Payment">
        <http:body><![CDATA[#[{
            amount: vars.orderTotals.grandTotal,
            currency: vars.orderRequest.currency default "USD",
            customerId: vars.customerDetails.stripeCustomerId,
            paymentMethod: vars.orderRequest.payment.methodId,
            description: "Order " ++ vars.orderId,
            metadata: {
                orderId: vars.orderId,
                customerId: vars.orderRequest.customerId
            }
        }]]]></http:body>
    </http:request>
 
    <choice doc:name="Check Payment Result">
        <when expression="#[payload.status != 'succeeded']">
            <raise-error type="APP:PAYMENT_FAILED" description="#[payload.failureMessage]"/>
        </when>
    </choice>
 
    <set-variable variableName="paymentResult" value="#[payload]" doc:name="Store Payment Result"/>
</sub-flow>
 
<sub-flow name="compensate-order-failure">
    <!-- Inverseaza plata daca a fost procesata -->
    <choice doc:name="Check Payment to Reverse">
        <when expression="#[vars.paymentResult != null]">
            <http:request
                method="POST"
                config-ref="Stripe_SAPI_Config"
                path="/payments/{paymentId}/refund"
                doc:name="Refund Payment">
                <http:uri-params><![CDATA[#[{
                    paymentId: vars.paymentResult.transactionId
                }]]]></http:uri-params>
            </http:request>
            <logger level="INFO" message="Payment reversed: #[vars.paymentResult.transactionId]"/>
        </when>
    </choice>
 
    <!-- Elibereaza stocul daca a fost rezervat -->
    <choice doc:name="Check Inventory to Release">
        <when expression="#[vars.inventoryReserved == true]">
            <foreach collection="#[vars.orderRequest.items]" doc:name="Release Each Item">
                <http:request
                    method="DELETE"
                    config-ref="SAP_SAPI_Config"
                    path="/inventory/reservations/{reservationId}"
                    doc:name="Release Reservation"/>
            </foreach>
            <logger level="INFO" message="Inventory reservations released"/>
        </when>
    </choice>
 
    <!-- Construieste raspunsul de eroare -->
    <ee:transform doc:name="Build Error Response">
        <ee:message>
            <ee:set-payload><![CDATA[%dw 2.0
output application/json
---
{
    orderId: vars.orderId,
    status: "FAILED",
    error: {
        code: error.errorType.identifier,
        message: error.description,
        compensationApplied: true
    }
}]]></ee:set-payload>
        </ee:message>
    </ee:transform>
</sub-flow>

Implementarea Experience API

Experience API-urile adapteaza datele pentru consumatori specifici:

<!-- mobile-experience-api.xml -->
<flow name="get:\dashboard:mobile-eapi-config">
    <!-- Apeluri paralele pentru datele dashboard-ului -->
    <scatter-gather doc:name="Gather Dashboard Data">
        <!-- Comenzi recente -->
        <route>
            <http:request
                method="GET"
                config-ref="Order_PAPI_Config"
                path="/orders"
                doc:name="Get Recent Orders">
                <http:query-params><![CDATA[#[{
                    customerId: vars.userId,
                    limit: 5,
                    status: "RECENT"
                }]]]></http:query-params>
            </http:request>
            <set-variable variableName="recentOrders" value="#[payload]"/>
        </route>
 
        <!-- Sumar cont -->
        <route>
            <http:request
                method="GET"
                config-ref="Customer_PAPI_Config"
                path="/customers/{customerId}/summary"
                doc:name="Get Account Summary">
                <http:uri-params><![CDATA[#[{
                    customerId: vars.userId
                }]]]></http:uri-params>
            </http:request>
            <set-variable variableName="accountSummary" value="#[payload]"/>
        </route>
 
        <!-- Notificari -->
        <route>
            <http:request
                method="GET"
                config-ref="Notification_PAPI_Config"
                path="/notifications"
                doc:name="Get Notifications">
                <http:query-params><![CDATA[#[{
                    userId: vars.userId,
                    unreadOnly: true,
                    limit: 10
                }]]]></http:query-params>
            </http:request>
            <set-variable variableName="notifications" value="#[payload]"/>
        </route>
 
        <!-- Recomandari -->
        <route>
            <http:request
                method="GET"
                config-ref="Recommendation_PAPI_Config"
                path="/recommendations"
                doc:name="Get Recommendations">
                <http:query-params><![CDATA[#[{
                    userId: vars.userId,
                    limit: 6
                }]]]></http:query-params>
            </http:request>
            <set-variable variableName="recommendations" value="#[payload]"/>
        </route>
    </scatter-gather>
 
    <!-- Construieste raspunsul optimizat pentru mobil -->
    <ee:transform doc:name="Build Mobile Dashboard">
        <ee:message>
            <ee:set-payload><![CDATA[%dw 2.0
output application/json
 
// Helper pentru formatarea preturilor pe mobil
fun formatPrice(amount, currency) =
    currency ++ " " ++ (amount as String {format: "#,##0.00"})
---
{
    user: {
        name: vars.accountSummary.name,
        avatar: vars.accountSummary.avatarUrl,
        memberSince: vars.accountSummary.memberSince as Date as String {format: "MMM yyyy"}
    },
 
    // Carduri de comenzi compacte pentru mobil
    recentOrders: vars.recentOrders.orders[0 to 2] map {
        id: $.orderId,
        date: $.createdAt as Date as String {format: "MMM d"},
        total: formatPrice($.totals.grandTotal, $.currency),
        status: $.status,
        statusColor: $.status match {
            case "DELIVERED" -> "#4CAF50"
            case "SHIPPED" -> "#2196F3"
            case "PROCESSING" -> "#FF9800"
            else -> "#9E9E9E"
        },
        itemCount: sizeOf($.items),
        thumbnail: $.items[0].imageUrl
    },
 
    // Badge-uri de notificari
    notifications: {
        unreadCount: sizeOf(vars.notifications.items),
        items: vars.notifications.items[0 to 4] map {
            id: $.id,
            title: $.title,
            preview: if (sizeOf($.message) > 50)
                        $.message[0 to 47] ++ "..."
                     else
                        $.message,
            type: $.type,
            icon: $.type match {
                case "ORDER" -> "shopping_cart"
                case "PROMO" -> "local_offer"
                case "ALERT" -> "warning"
                else -> "notifications"
            },
            timestamp: $.createdAt
        }
    },
 
    // Carduri de produse optimizate pentru grid-ul mobil
    recommendations: vars.recommendations.products map {
        id: $.productId,
        name: if (sizeOf($.name) > 25) $.name[0 to 22] ++ "..." else $.name,
        price: formatPrice($.price, "USD"),
        originalPrice: if ($.onSale) formatPrice($.originalPrice, "USD") else null,
        discount: if ($.onSale) round((1 - $.price / $.originalPrice) * 100) ++ "%" else null,
        image: $.images[0].thumbnailUrl,
        rating: $.rating,
        reviewCount: $.reviewCount
    },
 
    // Butoane de actiuni rapide
    quickActions: [
        {id: "reorder", label: "Reorder", icon: "replay"},
        {id: "track", label: "Track Order", icon: "local_shipping"},
        {id: "support", label: "Support", icon: "help_outline"},
        {id: "deals", label: "Deals", icon: "local_offer"}
    ],
 
    _meta: {
        generatedAt: now(),
        cacheControl: "max-age=300"
    }
}]]></ee:set-payload>
        </ee:message>
    </ee:transform>
</flow>

API Governance

Stabilirea governance-ului pe toate straturile API:

# api-governance-policy.yaml
governance:
  naming_conventions:
    system_api:
      pattern: "{system-name}-sapi"
      examples: ["salesforce-sapi", "sap-sapi", "stripe-sapi"]
    process_api:
      pattern: "{business-process}-papi"
      examples: ["order-papi", "customer-papi", "fulfillment-papi"]
    experience_api:
      pattern: "{channel}-{domain}-eapi"
      examples: ["mobile-commerce-eapi", "web-account-eapi", "partner-orders-eapi"]
 
  versioning:
    strategy: "URI path versioning"
    format: "/v{major}"
    examples:
      - "/v1/customers"
      - "/v2/customers"
    deprecation:
      notice_period_days: 90
      sunset_header: true
 
  security:
    authentication:
      system_api: "Client Credentials OAuth 2.0"
      process_api: "Client Credentials OAuth 2.0"
      experience_api: "Authorization Code OAuth 2.0 or JWT"
    policies:
      required:
        - "Client ID enforcement"
        - "Rate limiting"
        - "Spike control"
      recommended:
        - "IP allowlist (system APIs)"
        - "JWT validation (experience APIs)"
 
  documentation:
    required_elements:
      - "API description and purpose"
      - "Authentication requirements"
      - "Request/response examples"
      - "Error codes and handling"
      - "Rate limits and quotas"
    format: "OAS 3.0"
    hosting: "Anypoint Exchange"
 
  sla:
    system_api:
      availability: "99.5%"
      latency_p95: "500ms"
    process_api:
      availability: "99.5%"
      latency_p95: "2000ms"
    experience_api:
      availability: "99.9%"
      latency_p95: "1000ms"

Concluzie

API-led connectivity ofera o abordare scalabila si reutilizabila pentru integrarea enterprise. System API-urile abstractizeaza complexitatea backend-ului, Process API-urile orchestreaza logica de business, iar Experience API-urile optimizeaza datele pentru nevoile consumatorilor. Un governance solid asigura consistenta si calitate pe intregul ecosistem de API-uri. Aceasta arhitectura pe straturi permite agilitate mentinand in acelasi timp standardele enterprise.


Sistemul tau AI e conform cu EU AI Act? Evaluare gratuita de risc - afla in 2 minute →

Ai nevoie de ajutor cu conformitatea EU AI Act sau securitatea AI?

Programeaza o consultatie gratuita de 30 de minute. Fara obligatii.

Programeaza un Apel

Weekly AI Security & Automation Digest

Get the latest on AI Security, workflow automation, secure integrations, and custom platform development delivered weekly.

No spam. Unsubscribe anytime.