파트너 센터 API를 호출하는 파트너를 위한 API 제한 지침
Microsoft는 파트너 센터 API를 호출하는 파트너의 시간 범위 내에서 보다 일관된 성능을 허용하도록 API 제한을 구현하고 있습니다. 제한은 특정 시간 범위의 서비스 요청 수를 제한하여 과도한 리소스 사용을 방지합니다. 파트너 센터는 많은 양의 요청을 처리하도록 설계되었지만 몇몇 파트너로 인해 압도적으로 많은 수의 요청이 발생하는 경우 제한을 통해 모든 파트너에 대해 최적의 성능과 안정성을 유지할 수 있습니다.
제한 한도는 시나리오에 따라 다릅니다. 예를 들어 많은 양의 쓰기를 수행하는 경우 읽기만 수행하는 경우보다 제한 가능성이 높습니다.
제한이 발생하면 어떻게 되나요?
제한 임계값을 초과하면 파트너 센터는 해당 클라이언트의 추가 요청을 일정 시간 동안 제한합니다. 제한 동작은 요청의 유형과 수에 따라 달라집니다.
일반적인 제한 시나리오
클라이언트 제한의 가장 일반적인 원인은 다음과 같습니다.
- 파트너 테넌트 ID당 API에 대한 요청 수가 많습니다. 일부 파트너 센터 API의 경우 제한은 파트너 테넌트 ID에 따라 결정됩니다. 동일한 파트너 테넌트 ID에서 해당 API를 너무 많이 호출하면 제한 임계값을 초과합니다.
- 고객 테넌트 ID당 파트너 테넌트 ID당 API에 대한 요청 수가 많습니다. 다른 API의 경우 제한은 파트너 테넌트 ID/고객 테넌트 ID 조합에 따라 결정됩니다. 이러한 경우 동일한 고객 테넌트 ID에 대해 너무 많은 호출을 수행하면 제한이 발생하지만 다른 고객에 대한 호출은 성공할 수 있습니다.
제한 방지 모범 사례
업데이트를 확인하기 위해 리소스를 지속적으로 폴링하고 리소스 컬렉션을 정기적으로 검사하여 새 리소스 또는 삭제된 리소스를 확인하는 등의 프로그래밍 방법은 제한으로 이어질 가능성이 높으며 전반적인 성능이 저하될 가능성이 높습니다. 동시 API 호출은 단위 시간당 요청 수가 많을 수 있으므로 요청이 제한될 수 있습니다. 대신 변경 내용 추적 및 변경 알림을 사용해야 합니다. 또한 변경 내용을 검색하기 위해 활동 로그를 사용할 수 있어야 합니다. 자세한 내용은 파트너 센터 활동 로그를 참조 하세요. 파트너는 효율성을 높이고 제한을 방지하기 위해 활동 로그 API를 사용하는 것을 고려하는 것이 좋습니다. 아래 활동 로그를 사용하는 예제도 참조하세요.
제한 처리 모범 사례
다음은 제한을 처리하는 모범 사례입니다.
- 병렬도를 줄입니다.
- 호출 빈도를 줄입니다.
- 모든 요청은 사용량 제한에 누적되므로 즉각적인 재시도는 피합니다.
오류 처리를 구현하는 경우 HTTP 오류 코드 429를 사용하여 제한을 검색합니다. 실패한 응답에는 Retry-After 응답 헤더가 포함됩니다. 다시 시도 후 지연을 사용하여 요청을 백업하는 것이 제한에서 복구하는 가장 빠른 방법입니다.
다시 시도 후 지연을 사용하려면 다음을 수행합니다.
- Retry-After 헤더에 지정된 시간(초)을 기다립니다.
- 요청을 재시도합니다.
- 429 오류 코드에 따라 요청이 다시 실패하면 여전히 제한되고 있는 것입니다. 지수 백오프를 사용하여 다시 시도하고 권장되는 Retry-After 지연을 사용하고 성공할 때까지 요청을 다시 시도합니다.
- SDK를 사용하는 경우 요청이 제한될 때 상태 코드 429와 함께 예외가 발생합니다. 예외에서 RetryAfter 속성을 사용하고 시간이 경과된 후 요청을 다시 시도합니다.
현재 제한의 영향을 받는 API
결국 엔드포인트 "api.partnercenter.microsoft.com/"을 호출하는 모든 단일 파트너 센터 API가 제한됩니다. 현재 제한 제한은 아래에 나열된 API에만 적용됩니다. 파트너 센터는 각 API에서 원격 분석을 수집하고 제한 제한을 동적으로 조정합니다. 다음 표에서는 현재 제한이 적용되는 API를 나열합니다.
연산 | 파트너 센터 설명서 |
---|---|
{baseURL}/v1/customers/{customer_id}/orders | 주문 만들기 |
{baseURL}/v1/customers/{customer-tenant-id}/subscriptions/{id-for-subscription}/upgrades | 구독 전환 |
{baseURL}/v1/customers/{customer-tenant-id}/orders/{order-id} | 구독에 추가 기능 구매 |
{baseURL}/v1/customers/{customer-id}/carts/{cart-id} | 카트 만들기 |
{baseURL}/v1/customers/{customer-id}/carts/{cart-id}/checkout | 카트 체크 아웃 |
{baseURL}/v1/customers/{customer-id}/carts/{cart-id} | 카트 업데이트 |
{baseURL}/v1/customers/{customer-id}/subscriptions/{subscription-id}/registrations | 구독 등록 |
{baseURL}/v1/productupgrades | 제품 업그레이드 엔터티 만들기 |
{baseURL}/v1/customers/{customer-id}/subscriptions/{subscription-id}/conversions | 평가판 구독을 유료로 변환 |
{baseURL}/v1/customers/{customer-tenant-id} | ID로 고객 가져오기 |
{baseURL}/v1/customers?size={size} | 고객 목록 가져오기 |
{baseURL}/v1/productUpgrades/eligibility | 제품 업그레이드 자격 가져오기 |
{baseURL}/v1/customers/{customer-tenant-id}/subscriptions/{id-for-subscription} | 구독 관리 |
{baseURL}/v1/customers/{customer_id}/subscriptions | 모든 고객 구독 가져오기 |
{baseURL}/v1/customers/{customer_id}/subscriptions/{subscription_id} | ID별 구독 가져오기 |
{baseURL}/v1/customers/{customer_id}/orders | 모든 고객 주문 가져오기 |
{baseURL}/v1/customers/{customer_id}/orders/{order_id} | ID별 주문 가져오기 |
{baseURL}/v1/customers/{customer_id}/orders/{order_id}/provisioningstatus | 구독 프로비전 상태 가져오기 |
{baseURL}/v1/customers/{customer_id}/subscriptions/{subscription_id} | 주문 관리 및 구독 관리 |
{baseURL}/v1/customers/{customer_id}/subscriptions/{subscription_id}/addons | 구독에 대한 추가 기능 목록 가져오기 |
{baseURL}/v1/customers/{customer_id}/subscriptions/{subscription_id}/azureEntitlements | 구독에 대한 Azure 자격 목록 가져오기 |
{baseURL}/v1/customers/{customer_id}/subscriptions/{subscription_id}/registrationstatus | 구독 등록 상태 가져오기 |
{baseURL}/v1/customers/{customer-tenant-id}/transfers | 고객의 모든 전송 정보 가져오기 |
{baseURL}/v1/productUpgrades/{upgrade-id}/status | 제품 업그레이드 상태 가져오기 |
{baseURL}/v1/customers/{customer-id}/subscriptions/{subscription-id}/conversions | 평가판 전환 제품 목록 가져오기 |
{baseURL}/v1/customers/{customer-tenant-id}/migrations/newcommerce/validate | 마이그레이션에 대한 구독 유효성 검사 |
{baseURL}/v1/customers/{customer-tenant-id}/migrations/newcommerce | 새 상거래 마이그레이션 만들기 |
{baseURL}/v1/customers/{customerId}/promotionEligibilities | 프로모션 자격 확인 |
오류 코드 응답:
HTTP/1.1 429 Too Many Requests
Content-Length: 84
Content-Type: application/json
Retry-After: 57
Date: Tue, 21 Jul 2020 04:10:58 GMT
{ "statusCode": 429, "message": "Rate limit is exceeded. Try again in 57 seconds." }
활동 로그의 예
일일 변경 내용을 분석하는 모범 사례를 위해 특정 날짜에 대한 감사 레코드를 쿼리하는 것이 좋습니다.
응답에서 특정 작업 유형이 변경된 결과를 가져옵니다. 관심 있는 작업에 따라 필터링할 수 있습니다. 예를 들어 새로 만든 고객에 관심이 있는 경우 operationType = "add_customer"을 확인할 수 있습니다.
operationtype/리소스 목록은 이러한 API 문서에서 찾을 수 있습니다.
응답 예제
요청:
Http Get call: https://api.partnercenter.microsoft.com/v1/auditrecords?startDate=2020-09-02&endDate=2020-09-02&size=50
Authorization: Bearer <token>
Accept: application/json
MS-RequestId: 127facaa-e389-41f8-8bb7-1d1af99db893
MS-CorrelationId: aaaa0000-bb11-2222-33cc-444444dddddd
X-Locale: en-US
Host: api.partnercenter.microsoft.com
Connection: Keep-Alive
응답:
{
"totalCount": 17,
"items": [
{
"id": "9daaeb1c-4195-4db5-9f1d-509eb70c8c2d_e905b566-4779-4e57-944c-7b1b5312705b_updatecustomeruserlicenses_637346859797753934",
"partnerId": "9daaeb1c-4195-4db5-9f1d-509eb70c8c2d",
"participants": [
"9daaeb1c-4195-4db5-9f1d-509eb70c8c2d"
],
"customerId": "e905b566-4779-4e57-944c-7b1b5312705b",
"userPrincipalName": "admin@testsw09.onmicrosoft.com",
"applicationId": "FulfillmentService",
"resourceType": "license",
"operationType": "update_customer_user_licenses",
"operationDate": "2020-09-02T23:26:19.7753934Z",
"operationStatus": "succeeded",
"customizedData": [
{
"key": "CustomerUserId",
"value": "933808c7-b165-496c-a24e-1a4b7846fab4"
}
],
"attributes": {
"objectType": "AuditRecord"
}
},
{
"id": "9daaeb1c-4195-4db5-9f1d-509eb70c8c2d_86bddccf-9a53-40c6-907c-08067a3f8da7_ia80zlkxp6ewoqpp35pbqjlhqv9iigvz1_createorder_637346662909268372",
"partnerId": "9daaeb1c-4195-4db5-9f1d-509eb70c8c2d",
"participants": [
"9daaeb1c-4195-4db5-9f1d-509eb70c8c2d"
],
"customerId": "aaaabbbb-0000-cccc-1111-dddd2222eeee",
"customerName": "CustomMetersStagingTest",
"userPrincipalName": "admin@testsw09.onmicrosoft.com",
"applicationId": "00001111-aaaa-2222-bbbb-3333cccc4444",
"resourceType": "order",
"resourceNewValue": "{\"Id\":\"Ia80ZLkXp6eWOqpp35pBQJLhqv9IiGVZ1\",\"AlternateId\":\"64144d300bde\",\"ReferenceCustomerId\":\"aaaabbbb-0000-cccc-1111-dddd2222eeee\",\"BillingCycle\":\"monthly\",\"CurrencyCode\":\"USD\",\"CurrencySymbol\":\"$\",\"LineItems\":[{\"LineItemNumber\":0,\"ProvisioningContext\":null,\"OfferId\":\"DZH318Z0C964:0001:DZH318Z0BZDG\",\"SubscriptionId\":\"aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e\",\"ParentSubscriptionId\":null,\"TermDuration\":\"P1M\",\"TransactionType\":\"New\",\"FriendlyName\":\"SaaS custom meter offer - Bronze\",\"Quantity\":1,\"Pricing\":null,\"PartnerIdOnRecord\":null,\"RenewsTo\":null,\"Links\":{\"Product\":{\"Uri\":\"/products/DZH318Z0C964?country=US\",\"Method\":\"GET\",\"Body\":null,\"Headers\":[]},\"Sku\":{\"Uri\":\"/products/DZH318Z0C964/skus/0001?country=US\",\"Method\":\"GET\",\"Body\":null,\"Headers\":[]},\"Availability\":{\"Uri\":\"/products/DZH318Z0C964/skus/0001/availabilities/DZH318Z0BZDG?country=US\",\"Method\":\"GET\",\"Body\":null,\"Headers\":[]},\"ActivationLinks\":{\"Uri\":\"/customers/aaaabbbb-0000-cccc-1111-dddd2222eeee/orders/Ia80ZLkXp6eWOqpp35pBQJLhqv9IiGVZ1/lineitems/0/activationlinks\",\"Method\":\"GET\",\"Body\":null,\"Headers\":[]}}}],\"CreationDate\":\"2020-09-02T17:58:01.7755853Z\",\"Status\":\"pending\",\"TransactionType\":\"UserPurchase\",\"Links\":{\"Self\":{\"Uri\":\"/customers/aaaabbbb-0000-cccc-1111-dddd2222eeee/orders/Ia80ZLkXp6eWOqpp35pBQJLhqv9IiGVZ1\",\"Method\":\"GET\",\"Body\":null,\"Headers\":[]},\"ProvisioningStatus\":{\"Uri\":\"/customers/aaaabbbb-0000-cccc-1111-dddd2222eeee/orders/Ia80ZLkXp6eWOqpp35pBQJLhqv9IiGVZ1/provisioningstatus\",\"Method\":\"GET\",\"Body\":null,\"Headers\":[]},\"PatchOperation\":{\"Uri\":\"/customers/aaaabbbb-0000-cccc-1111-dddd2222eeee/orders/Ia80ZLkXp6eWOqpp35pBQJLhqv9IiGVZ1\",\"Method\":\"PATCH\",\"Body\":null,\"Headers\":[]}},\"Client\":{\"marketplaceCountry\":\"US\",\"deviceFamily\":\"UniversalStore-PartnerCenter\",\"name\":\"Partner Center Web\"},\"Attributes\":{\"ObjectType\":\"Order\"}}",
"operationType": "create_order",
"originalCorrelationId": "96514ebe-c1b2-4865-cb46-2c2d20a2e911",
"operationDate": "2020-09-02T17:58:10.9268372Z",
"operationStatus": "succeeded",
"customizedData": [
{
"key": "OrderId",
"value": "Ia80ZLkXp6eWOqpp35pBQJLhqv9IiGVZ1"
},
{
"key": "AlternateId",
"value": "64144d300bde"
},
{
"key": "BillingCycle",
"value": "Monthly"
},
{
"key": "OfferId-0",
"value": "DZH318Z0C964:0001:DZH318Z0BZDG"
},
{
"key": "SubscriptionId-0",
"value": "aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e"
},
{
"key": "SubscriptionName-0",
"value": "SaaS custom meter offer - Bronze"
},
{
"key": "Quantity-0",
"value": "1"
},
{
"key": "PartnerOnRecord-0",
"value": null
}
],
"attributes": {
"objectType": "AuditRecord"
}
},
{
"id": "9daaeb1c-4195-4db5-9f1d-509eb70c8c2d_86bddccf-9a53-40c6-907c-08067a3f8da7_86bddccf-9a53-40c6-907c-08067a3f8da7_addcustomer_637346648528069005",
"partnerId": "9daaeb1c-4195-4db5-9f1d-509eb70c8c2d",
"participants": [
"9daaeb1c-4195-4db5-9f1d-509eb70c8c2d"
],
"customerId": "aaaabbbb-0000-cccc-1111-dddd2222eeee",
"customerName": "CustomMetersStagingTest",
"userPrincipalName": "admin@testsw09.onmicrosoft.com",
"applicationId": "00001111-aaaa-2222-bbbb-3333cccc4444",
"resourceType": "customer",
"resourceNewValue": "{\"Id\":\"aaaabbbb-0000-cccc-1111-dddd2222eeee\",\"CommerceId\":\"9dd78b4f-f98a-44b4-a2fa-2b82ac58d24c\",\"CompanyProfile\":{\"TenantId\":\"aaaabbbb-0000-cccc-1111-dddd2222eeee\",\"Domain\":\"CustomMetersStagingTest.onmicrosoft.com\",\"CompanyName\":\"CustomMetersStagingTest\",\"Address\":null,\"Email\":null,\"OrganizationRegistrationNumber\":null,\"Links\":{\"Self\":{\"Uri\":\"/customers/aaaabbbb-0000-cccc-1111-dddd2222eeee/profiles/company\",\"Method\":\"GET\",\"Body\":null,\"Headers\":[]}},\"Attributes\":{\"ObjectType\":\"CustomerCompanyProfile\"}},\"BillingProfile\":{\"Id\":\"bbbbcccc-1111-dddd-2222-eeee3333ffff\",\"FirstName\":\"CustomMetersStagingTest\",\"LastName\":\"CustomMetersStagingTest\",\"Email\":\"CustomMetersStagingTest@CustomMetersStagingTest.com\",\"Culture\":\"en-US\",\"Language\":\"en\",\"CompanyName\":\"CustomMetersStagingTest\",\"DefaultAddress\":{\"Id\":null,\"Country\":\"US\",\"Region\":null,\"City\":\"Seattle\",\"State\":\"WA\",\"District\":null,\"AddressLine1\":\"CustomMetersStagingTest\",\"AddressLine2\":null,\"AddressLine3\":null,\"PostalCode\":\"98122\",\"FirstName\":\"CustomMetersStagingTest\",\"LastName\":\"CustomMetersStagingTest\",\"EmailAddress\":null,\"PhoneNumber\":null,\"MiddleName\":null},\"Attributes\":{\"Etag\":\"-2279334701316321663\",\"ObjectType\":\"CustomerBillingProfile\"}},\"RelationshipToPartner\":\"reseller\",\"AllowDelegatedAccess\":true,\"UserCredentials\":{\"userName\":\"admin\",\"password\":\"\"},\"AssociatedPartnerId\":null,\"CustomDomains\":null,\"Attributes\":{\"ObjectType\":\"Customer\"}}",
"operationType": "add_customer",
"originalCorrelationId": "7550d9ea-e64a-416f-e49b-3670c516cf69",
"operationDate": "2020-09-02T17:34:12.8069005Z",
"operationStatus": "succeeded",
"customizedData": [
{
"key": "PrimaryDomainName",
"value": "CustomMetersStagingTest.onmicrosoft.com"
},
{
"key": "Relationship",
"value": "Reseller"
}
],
"attributes": {
"objectType": "AuditRecord"
}
},
...
],
"links": {
"self": {
"uri": "/auditrecords?startDate=2020-09-02&endDate=2020-09-02&size=50",
"method": "GET",
"headers": []
}
},
"attributes": {
"objectType": "Collection"
}
}