Microsoft Store-api för insändning för MSI- eller EXE-app

Använd Microsoft Store-inlämnings-API:et för MSI- eller EXE-appar för att programmera fråga efter och skapa inlämningar för MSI- eller EXE-appar för ditt eller din organisations Partnercenter-konto. Det här API:et är användbart om ditt konto hanterar många appar och du vill automatisera och optimera överföringsprocessen för dessa tillgångar. Det här API:et använder Microsoft Entra-ID för att autentisera anropen från din app eller tjänst.

Följande steg beskriver processen från början till slut för att använda Microsoft Store API för inlämning.

  1. Kontrollera att du har slutfört alla förberedelser.
  2. Innan du anropar en metod i Microsoft Store-submissions-API:et hämtar du en Microsoft Entra ID-åtkomsttoken. När du har hämtat en token har du 60 minuter på dig att använda den här token i anrop till Microsoft Store-api:et för överföring innan token upphör att gälla. När token har upphört att gälla kan du generera en ny token.
  3. Anropa MICROSOFT Store-api:et för insändning för MSI- eller EXE-appen.

Steg 1: Slutför kraven för att använda API:et för Microsoft Store-överföring

Innan du börjar skriva kod för att anropa Microsoft Store-api:et för insändning för MSI- eller EXE-appen kontrollerar du att du har slutfört följande krav.

  • Du (eller din organisation) måste ha en Microsoft Entra-ID-katalog och du måste ha global administratörsbehörighet för katalogen. Om du redan använder Microsoft 365 eller andra företagstjänster från Microsoft har du redan microsoft entra-ID-katalog. Annars kan du skapa ett nytt Microsoft Entra-ID i Partnercenter utan extra kostnad.
  • Du måste associera en Microsoft Entra ID-applikation med ditt Partnercenter-konto och hämta ditt tenant-ID, klient-ID och nyckel. Du behöver dessa värden för att få en Microsoft Entra ID-access token, som du kommer att använda i anrop till Microsoft Store-insändnings-API:et.
  • Förbered din app för användning med Microsoft Store-api:et för överföring:
    • Om din app ännu inte finns i Partnercenter måste du skapa din app genom att reservera dess namn i Partnercenter. Du kan inte använda Microsoft Store-api:et för insändning för att skapa en app i Partnercenter. Du måste arbeta i Partnercenter för att skapa det och sedan kan du använda API:et för att komma åt appen och programmatiskt skapa inskickade filer för den.
    • Innan du kan skapa en insändning för en viss app med hjälp av det här API:et måste du först skapa en sändning för appen i Partnercenter, inklusive att svara på frågeformuläret för åldersklassificeringar . När du gör det kan du programmatiskt skapa nya inlämningar för den här appen med hjälp av API:et.
    • Om du skapar eller uppdaterar en appöverföring och behöver inkludera ett nytt paket förbereda paketinformationen.
    • Om du skapar eller uppdaterar en appöverföring och du behöver ta med skärmbilder eller bilder för Store-listan förbereda appskärmbilderna och bilderna.

Så här associerar du ett Microsoft Entra-ID-program med ditt Partnercenter-konto

Innan du kan använda Microsoft Store-API:et för överföring av MSI eller EXE, måste du associera en Microsoft Entra ID-applikation med ditt Partner Center-konto, hämta tenant ID och klient-ID för applikationen och generera en nyckel. Microsoft Entra-ID-programmet representerar den app eller tjänst som du vill anropa Microsoft Store-api:et för insändning från. Du behöver klientorganisations-ID, klient-ID och nyckel för att hämta en Microsoft Entra ID-åtkomsttoken som du skickar till API:et.

Anmärkning

Du behöver bara utföra den här uppgiften en gång. När du har tenant-ID, klient-ID och nyckel kan du återanvända dem när du behöver skapa en ny Microsoft Entra ID-åtkomsttoken.

  1. I Partnercenter associerar du organisationens Partnercenter-konto med organisationens Microsoft Entra-ID-katalog.
  2. Från sidan Användare i avsnittet Kontoinställningar i Partnercenter lägger du sedan till Microsoft Entra-ID-programmet som representerar den app eller tjänst som du kommer att använda för att få åtkomst till inlämningar för ditt Partnercenter-konto. Se till att du tilldelar den här applikationen rollen Manager. Om programmet inte finns ännu i din Microsoft Entra-ID-katalog kan du skapa ett nytt Microsoft Entra-ID-program i Partnercenter.
  3. Gå tillbaka till sidan Användare, klicka på namnet på din Microsoft Entra-ID-applikation för att gå till applikationsinställningarna och kopiera värdena för Tenant-ID och klient-ID.
  4. Om du vill lägga till en ny nyckel eller klienthemlighet kan du läsa följande instruktioner eller läsa anvisningarna för att registrera appen via Azure Portal:

Så här registrerar du din app:

  1. Logga in på Azure-portalen.

  2. Om du har åtkomst till flera klienter använder du filtret Kataloger + prenumerationer på den översta menyn för att växla till den klientorganisation där du vill registrera programmet.

  3. Sök efter och välj Microsoft Entra ID Directory.

  4. Under Hantera väljer du Appregistreringar > Välj ditt program.

  5. Välj Certifikat och hemligheter > Klienthemligheter > Ny klienthemlighet.

  6. Lägg till en beskrivning av klienthemligheten.

  7. Välj en förfallotid för hemligheten eller ange en anpassad livslängd.

  8. Klienthemlighetens livslängd är begränsad till två år (24 månader) eller mindre. Du kan inte ange en anpassad livslängd som är längre än 24 månader.

    Anmärkning

    Microsoft rekommenderar att du anger ett förfallovärde på mindre än 12 månader.

  9. Välj Lägg till.

  10. Registrera hemlighetens värde för användning i klientprogramkoden. Det här hemliga värdet visas aldrig igen när du har lämnat den här sidan.

Steg 2: Hämta en Åtkomsttoken för Microsoft Entra-ID

Innan du anropar någon av metoderna i Microsoft Store-överförings-API:et för MSI- eller EXE-appen måste du först skaffa en Microsoft Entra ID-åtkomsttoken som du skickar till auktoriseringshuvudet för varje metod i API:et. När du har fått en åtkomsttoken har du 60 minuter på dig att använda den innan den upphör att gälla. När token upphör att gälla kan du uppdatera token så att du kan fortsätta att använda den i ytterligare anrop till API:et.

Om du vill hämta åtkomsttoken följer du anvisningarna i Tjänst-till-tjänst-anrop med klientautentiseringsuppgifter för att skicka en HTTP POST till https://login.microsoftonline.com/<slutpunkten tenant_id>/oauth2/token. Här är en exempelbegäran.

POST https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded; charset=utf-8

grant_type=client_credentials
&client_id=<your_client_id>
&client_secret=<your_client_secret>
&scope=https://api.store.microsoft.com/.default

För tenant_id-värdet i POST-URI:n och parametrarna client_id och client_secret anger du tenant-ID, klient-ID och nyckeln för ditt program som du hämtade från Partner Center i föregående avsnitt. För omfångsparametern måste du ange https://api.store.microsoft.com/.default.

När din åtkomsttoken har upphört att gälla kan du uppdatera den genom att följa anvisningarna här.

Exempel som visar hur du hämtar en åtkomsttoken med hjälp av C# eller Node.jsfinns i kodexempel för Microsoft Store-överförings-API för MSI- eller EXE-app.

Steg 3: Använd Microsoft Store-inlämnings-API:et

När du har en åtkomsttoken för Microsoft Entra-ID, kan du anropa metoder i Microsoft Store submissions-API:et för inlämning av MSI- eller EXE-appar. API:et innehåller många metoder som är grupperade i scenarier för appar. Om du vill skapa eller uppdatera inskickade filer anropar du vanligtvis flera metoder i en viss ordning. Information om varje scenario och syntax för varje metod finns i följande avsnitt:

Anmärkning

När du har hämtat en åtkomsttoken har du 60 minuter på dig att anropa metoder i Microsoft Store-api:et för överföring av MSI eller EXE innan token upphör att gälla.

Bas-webbadress

Bas-URL:en för Microsoft Store Submission API för EXE- eller MSI-appen är: https://api.store.microsoft.com

API-kontrakt

Hämta aktuellt metadatainlämnings-API för utkast.

Hämtar metadata i varje modul (listor, egenskaper eller tillgänglighet) under aktuellt utkast.

Sökväg [Alla moduler]: /submission/v1/product/{productId}/metadata?languages={languages}&includelanguagelist={true/false}
sökväg [Enskild modul]: /submission/v1/product/{productId}/metadata/{moduleName}?languages={languages}&includelanguagelist={true/false}
Metod: GET

sökvägsparametrar

Parameter Beskrivning
produkt-id Partnercenter-ID:t för produkten
modulNamn Partnercenter-modul – listor, egenskaper eller tillgänglighet

Frågeparametrar

Parameter Beskrivning
Språk Valfritt Listspråken filtreras som kommaavgränsad sträng [gräns på upp till 200 språk].

Om det saknas, hämtas metadata för de första 200 tillgängliga språken i listorna. [ t.ex. "en-us, en-gb"].
inkluderaspråklista Valfritt booleskt värde – om sant returnerar listan över tillagda listspråk och deras fullständighetsstatus.

Nödvändiga Rubriker

Rubrik Värde
Authorization: Bearer <Token> Microsoft Entra ID-app-ID som är registrerad med ett Partner Center-konto
X-Seller-Account-Id Säljar-ID för Partnercenter-konto

Svarshuvuden

Rubrik Värde
X-Correlation-ID GUID-typens unikt ID för varje begäran. Detta kan delas med supportteamet för att analysera eventuella problem.
Retry-After Den tid i sekunder som klienten måste vänta innan den anropar API:erna igen på grund av hastighetsbegränsning.

Svarsparametrar

Namn Typ Beskrivning
tillgänglighetsstöd Boolesk
ytterligare licensvillkor Sträng
tillgänglighet Objekt Tillgänglighetsmoduldata
kategori Sträng Se en lista över kategorier nedan
certifieringsanteckningar Sträng
kod Sträng Felkoden för meddelandet
kontaktinformation Sträng
upphovsrätt Sträng
beroendePåDrivrutinerEllerNT Boolesk
beskrivning Sträng
utveckladAv Sträng
upptäckbarhet Sträng [UPPTÄCKBAR, ENDAST DIREKTLÄNK]
enableInFutureMarkets Boolesk
Felaktigheter Matris med objekt Listan över eventuella fel- eller varningsmeddelanden
freeTrial Sträng [INGEN_GRATIS_PROVNING, GRATIS_PROVNING]
hårdvaruobjekttyp Sträng
ÄrIntegritetspolicyNödvändig Boolesk
ärRekommenderad Boolesk
obligatorisk Boolesk
ärFramgång Boolesk
ärSystemfunktionNödvändig Matris med objekt
Språk Sträng Se listan över språk nedan
Listningar Matris med objekt Visar moduldata för varje språk
Marknader Matris med strängar Se lista över marknader nedan
meddelande Sträng Beskrivningen av felet
minsta hårdvara Sträng
minimikrav Sträng
stöd för penna och bläck Boolesk
prissättning Sträng [GRATIS, FREEMIUM, PRENUMERATION, BETALD]
Integritetspolicy-URL Sträng
produktdeklarationer Objekt
produktfunktioner Matris med strängar
egenskaper Objekt Egenskaper för moduldata
rekommenderad hårdvara Sträng
rekommenderat krav Sträng
svarData Objekt Innehåller faktisk svarsnyttolast för begäran
Krav Matris med objekt
söktermer Matris med strängar
kort beskrivning Sträng
underkategori Sträng Se listan över underkategorier nedan
supportkontaktinformation Sträng
systemkravdetaljer Matris med objekt
mål Sträng Entiteten från vilken felet uppstod
webbplats Sträng
Nyheter Sträng

Uppdatera API för metadata för inlämning av aktuellt utkast

Uppdaterar metadata i varje modul under utkastöverföring. API-kontrollerna

  • För aktiv inlämning. Om det finns, misslyckas med ett felmeddelande.
  • Om alla moduler är i klar status för att tillåta åtgärden Spara utkast.
  • Varje fält i sändningen verifieras enligt kraven i Store
  • Verifieringsregler för systemkravsdetaljer
    • Tillåtna värden i hardwareItemType = Minne: 300 MB, 750 MB, 1 GB, 2 GB, 4 GB, 6 GB, 8 GB, 12 GB, 16 GB, 20 GB
    • Tillåtna värden i hardwareItemType = DirectX: DX9, DX10, DX11, DX12-FEATURELEVEL11, DX12-FEATURELEVEL12
    • Tillåtna värden i hardwareItemType = Video_Memory: 1 GB, 2 GB, 4 GB, 6 GB

sökväg [Fullständig moduluppdatering]: /submission/v1/product/{productId}/metadata
Metod: PUT

sökväg [Uppdatering av modulkorrigering]: /submission/v1/product/{productId}/metadata
Metod: PATCH

API-beteende

När det gäller API för fullständig moduluppdatering – måste hela moduldata finnas i Begäran om fullständig uppdatering av varje fält. Alla fält som inte finns i Begäran, dess standardvärde används för att skriva över aktuellt värde för den specifika modulen.
När det gäller Uppdaterings-API för korrigeringsmodul – behöver endast fält som ska uppdateras finnas i Begäran. Dessa fältvärden från Begäran skriver över sina befintliga värden och behåller alla andra fält som inte finns i begäran, samma som aktuella för den specifika modulen.

sökvägsparametrar

Parameter Beskrivning
produkt-id Partnercenter-ID:t för produkten

Nödvändiga Rubriker

Rubrik Värde
Authorization: Bearer <Token> Microsoft Entra ID-app-ID som är registrerad med ett Partner Center-konto
X-Seller-Account-Id Säljar-ID för Partnercenter-konto

parametrar för begäran

Namn Typ Beskrivning
tillgänglighet Objekt Objekt för att lagra metadata för tillgänglighetsmodulen
Marknader Matris med strängar Obligatorisk Se lista över marknader nedan
upptäckbarhet Sträng Krävs [UPPTÄCKBAR, DIREKTLÄNK_ENDAST]
enableInFutureMarkets Boolesk Obligatoriskt
prissättning Sträng Krävs [GRATIS, FREEMIUM, PRENUMERATIONSBASERAD, BETALD]
freeTrial Sträng Krävs om prissättningen är BETALD eller PRENUMERATION [NO_FREE_TRIAL, FREE_TRIAL]
egenskaper Objekt Objekt som ska innehålla metadata för egenskapsmodulen
ÄrIntegritetspolicyNödvändig Boolesk Obligatoriskt
Integritetspolicy-URL Sträng Krävs om isPrivacyPolicyRequired = sant måste vara en giltig URL
webbplats Sträng Måste vara en giltig URL
supportkontaktinformation Sträng Måste vara en giltig URL eller e-postadress
certifieringsanteckningar Sträng Rekommenderad Teckengräns = 2000
kategori Sträng Obligatorisk Se listan över kategorier nedan
underkategori Sträng Obligatorisk Se listan över underkategorier nedan
produktdeklarationer Objekt Obligatoriskt
ärSystemfunktionNödvändig Matris med objekt [Touch, Tangentbord, Mus, Kamera, NFC_HCE, NFC_Proximity, Bluetooth_LE, Telefoni, Mikrofon]
obligatorisk Boolesk Obligatoriskt
ärRekommenderad Boolesk Obligatoriskt
hårdvaruobjekttyp Sträng Obligatoriskt
systemkravdetaljer Matris med objekt [Processor, grafik, minne, DirectX, Video_Memory]
minimikrav Sträng Krävs För systemRequirementsText, MaxLength = 200

Tillåtna värden i hardwareItemType = Minne: [300 MB, 750 MB, 1 GB, 2 GB, 4 GB, 6 GB, 8 GB, 12 GB, 16 GB, 20 GB]

Tillåtna värden i hardwareItemType = DirectX: [DX9, DX10, DX11, DX12-FEATURELEVEL11, DX12-FEATURELEVEL12]

Tillåtna värden i hardwareItemType = Video_Memory: [1 GB, 2 GB, 4 GB, 6 GB]
rekommenderat krav Sträng Krävs För systemRequirementsText, MaxLength = 200

Tillåtna värden i hardwareItemType = Minne: [300 MB, 750 MB, 1 GB, 2 GB, 4 GB, 6 GB, 8 GB, 12 GB, 16 GB, 20 GB]

Tillåtna värden i hardwareItemType = DirectX: [DX9, DX10, DX11, DX12-FEATURELEVEL11, DX12-FEATURELEVEL12]

Tillåtna värden i hardwareItemType = Video_Memory: [1 GB, 2 GB, 4 GB, 6 GB]
beroendePåDrivrutinerEllerNT Boolesk Obligatoriskt
tillgänglighetsstöd Boolesk Obligatoriskt
stöd för penna och bläck Boolesk Obligatoriskt
Listningar Objekt Objekt för att visa moduldata för ett enda språk
Språk Sträng Obligatorisk Se lista över språk nedan
beskrivning Sträng Obligatorisk Teckengräns = 10000
Nyheter Sträng Teckengräns = 1500
produktfunktioner Matris av strängar 200 tecken per funktion; Upp till 20 funktioner
kort beskrivning Sträng Teckengräns = 1 000
söktermer Matris av strängar 30 tecken per sökterm; Upp till 7 söktermer

21 unika ord TOTALT för alla söktermer
ytterligare licensvillkor Sträng Obligatorisk Teckengräns = 10000
upphovsrätt Sträng Teckengräns = 200
utveckladAv Sträng Teckengräns = 255
Krav Matris med objekt 200 tecken per objekt; Upp till 11 objekt TOTALT mellan minimum och rekommenderas]
minsta hårdvara Sträng Teckengräns = 200
rekommenderad hårdvara Sträng Teckengräns = 200
kontaktinformation Sträng Teckengräns = 200
listor att lägga till Matris med strängar Se listan över språk nedan
listorAttTaBort Matris med strängar Se listan över språk nedan

Marknader

Visa tabell | Marknad | Förkortning | |--------|--------------| | Afghanistan | AF | | Albanien | AL | | Algeriet | DZ | | Amerikanska Samoa | AS | | Andorra | AD | | Angola | AO | | Anguilla | AI | | Antarktis | AQ | | Antigua och Barbuda | AG | | Argentina | AR | | Armenien | AM | | Aruba | AW | | Australien | AU | | Österrike | AT | | Azerbajdzjan | AZ | | Bahamas | BS | | Bahrain | BH | | Bangladesh | BD | | Barbados | BB | | Vitryssland | BY | | Belgien | BE | | Belize | BZ | | Benin | BJ | | Bermuda | BM | | Bhutan | BT | | Bolivarianska republiken Venezuela | VE | | Bolivia | BO | | Bonaire | BQ | | Bosnien och Hercegovina | BA | | Botswana | BW | | Bouvet Island | BV | | Brasilien | BR | | Brittiska Indiska oceanens territorium | IO | | Brittiska Jungfruöarna | VG | | Brunei | BN | | Bulgarien | BG | | Burkina Faso | BF | | Burundi | BI | | Kambodja | KH | | Kamerun | CM | | Kanada | CA | | Cabo Verde | CV | | Caymanöarna | KY | | Centralafrikanska republiken | CF | | Tchad | TD | | Chile | CL | | Kina | CN | | Christmas Island | CX | | Cocos (Keeling) Islands | CC | | Colombia | CO | | Komorerna | KM | | Kongo | CG | | Kongo (DRC) | CD | | Cooköarna | CK | | Costa Rica | CR | | Kroatien | HR | | Curaçao | CW | | Cypern | CY | | Tjeckien | CZ | | Elfenbenskusten | CI | | Danmark | DK | | Djibouti | DJ | | Dominica | DM | | Dominikanska republiken | DO | | Ecuador | EC | | Egypten | EG | | El Salvador | SV | | Ekvatorialguinea | GQ | | Eritrea | ER | | Estland | EE | | Etiopien | ET | | Falklandsöarna | FK | | Färöarna | FO | | Fiji | FJ | | Finland | FI | | Frankrike | FR | | Franska Guyana | GF | | Franska Polynesien | PF | | Franska södra och Antarktis territorier | TF | | Gabon | GA | | Gambia | GM | | Georgien | GE | | Tyskland | DE | | Ghana | GH | | Gibraltar | GI | | Grekland | GR | | Grönland | GL | | Grenada | GD | | Guadeloupe | GP | | Guam | GU | | Guatemala | GT | | Guernsey | GG | | Guinea | GN | | Guinea-Bissau | GW | | Guyana | GY | | Haiti | HT | | Heard Island och McDonaldöarna | HM | | Vatikanstaten | VA | | Honduras | HN | | Hongkong SAR | HK | | Ungern | HU | | Island | IS | | Indien | IN | | Indonesien | ID | | Irak | IQ | | Irland | IE | | Israel | IL | | Italien | IT | | Jamaica | JM | | Japan | JP | | Jersey | JE | | Jordanien | JO | | Kazakstan | KZ | | Kenya | KE | | Kiribati | KI | | Korea | KR | | Kuwait | KW | | Kirgizistan | KG | | Laos | LA | | Lettland | LV | | Libanon | LB | | Lesotho | LS | | Liberia | LR | | Libyen | LY | | Liechtenstein | LI | | Litauen | LT | | Luxemburg | LU | | Macao SAR | MO | | Nordmakedonien | MK | | Madagaskar | MG | | Malawi | MW | | Malaysia | MY | | Maldiverna | MV | | Mali | ML | | Malta | MT | | Isle of Man | IM | | Marshallöarna | MH | | Martinique | MQ | | Mauretanien | MR | | Mauritius | MU | | Mayotte | YT | | Mexiko | MX | | Mikronesiens federerade stater | FM | | Moldavien | MD | | Monaco | MC | | Mongoliet | MN | | Montenegro | ME | | Montserrat | MS | | Marocko | MA | | Moçambique | MZ | | Myanmar | MM | | Namibia | NA | | Nauru | NR | | Nepal | NP | | Nederländerna | NL | | Nya Kaledonien | NC | | Nya Zeeland | NZ | | Nicaragua | NI | | Niger | NE | | Nigeria | NG | | Niue | NU | | Norfolkön | NF | | Nordmarianerna | MP | | Norge | NO | | Oman | OM | | Pakistan | PK | | Palau | PW | | Palestinska myndigheten | PS | | Panama | PA | | Papua Nya Guinea | PG | | Paraguay | PY | | Peru | PE | | Filippinerna | PH | | Pitcairnöarna | PN | | Polen | PL | | Portugal | PT | | Qatar | QA | | Réunion | RE | | Rumänien | RO | | Ryssland | RU | | Rwanda | RW | | Saint Barthélemy | BL | | Saint Helena, Ascension och Tristan da Cunha | SH | | Saint Kitts och Nevis | KN | | Saint Lucia | LC | | Saint Martin (franska delen) | MF | | Saint Pierre och Miquelon | PM | | Saint Vincent och Grenadinerna | VC | | Samoa | WS | | San Marino | SM | | Saudiarabien | SA | | Senegal | SN | | Serbien | RS | | Seychellerna | SC | | Sierra Leone | SL | | Singapore | SG | | Sint Maarten (nederländska delen) | SX | | Slovakien | SK | | Slovenien | SI | | Salomonöarna | SB | | Somalia | SO | | Sydafrika | ZA | | Sydgeorgien och Sydsandwichöarna | GS | | Spanien | ES | | Sri Lanka | LK | | Surinam | SR | | Svalbard och Jan Mayen | SJ | | Swaziland | SZ | | Sverige | SE | | Schweiz | CH | | São Tomé och Príncipe | ST | | Taiwan | TW | | Tadzjikistan | TJ | | Tanzania | TZ | | Thailand | TH | | Timor-Leste | TL | | Togo | TG | | Tokelau | TK | | Tonga | TO | | Trinidad och Tobago | TT | | Tunisien | TN | | Türkiye | TR | | Turkmenistan | TM | | Turks- och Caicosöarna | TC | | Tuvalu | TV | | U.S. Minor Outlying Islands | UM | | Amerikanska Jungfruöarna | VI | | Uganda | UG | | Ukraina | UA | | Förenade Arabemiraten | AE | | Storbritannien | GB | | USA | US | | Uruguay | UY | | Uzbekistan | UZ | | Vanuatu | VU | | Vietnam | VN | | Wallis och Futuna | WF | | Jemen | YE | | Zambia | ZM | | Zimbabwe | ZW | | Åland | AX |

kategorier och underkategorier

Visa tabell | Kategori | Underkategorier | |-----------------------|---------------| | BöckerOchReferens | E-läsare, Skönlitteratur, Facklitteratur, Referens | | Företag | RedovisningOchFinans, Samarbete, CRM, DataOchAnalys, Filhantering, InventeringOchLogistik, JuridikOchHR, Projektledning, Fjärrskrivbord, FörsäljningOchMarknadsföring, TidOchKostnader | | Utvecklingsverktyg | Databas, Designverktyg, Utvecklingskit, Nätverk, ReferensOchUtbildning, Servrar, Verktyg, Webhosting | Utbildning | UtbildningsböckerOchReferens, TidigLärande, Instruktionsverktyg, Språk, Studierhjälpmedel | | Underhållning | (Ingen) | | MatOchDryck | (Ingen) | | StatOchPolitik | (Ingen) | | HälsaOchFitness | (Ingen) | | BarnOchFamilj | BarnOchFamiljBöckerOchReferens, BarnOchFamiljUnderhållning, HobbysOchLeksaker, SportOchAktiviteter, BarnOchFamiljResor | | Livsstil | Bil, GörDetSjälv, HemOchTrädgård, Relationer, SpecialIntressen, StilOchMode | | Medicinsk | (Ingen) | | Multimediadesign | IllustrationOchGrafikdesign, Musikproduktion, FotoOchVideoproduktion | | Musik | (Ingen) | | NavigationOchKartor | (Ingen) | | NyheterOchVäder | Nyheter, Väder | | PersonligEkonomi | BankOchInvesteringar, BudgeteringOchSkatter | | Anpassning | RingsignalerOchLjud, teman, BakgrundOchLåsskärmar | | FotoOchVideo | (Ingen) | | Produktivitet | (Ingen) | | Säkerhet | Datorskydd, PersonligSäkerhet | | Shopping | (Ingen) | | Social | (Ingen) | | Sport | (Ingen) | | Resor | Stadsguider, Hotell | | VerktygOchHjälpmedel | BackupOchHantera, Filhanterare |

Språk

Visa tabell | Språknamn | Språkkoder som stöds | |---------------|--------------------------| | | Afrikaans | af, af-za | | Albansk | sq, sq-al | | | Amharisk | am, am-et | | Armeniska | hy, hy-am | | | Assamese | as, as-in | | | Azerbajdzjan | az-arab, az-arab-az, az-cyrl, az-cyrl-az, az-latn, az-latn-az | | | Baskiska (baskiska) | eu, eu-es | | | Vitryska | be, be-by | | Bangla | bn, bn-bd, bn-in | | | Bosniska | bs, bs-cyrl, bs-cyrl-ba, bs-latn, bs-latn-ba | | | Bulgariska | bg, bg-bg | | | Katalanska | ca, ca-es, ca-es-valencia | | Cherokee | chr-cher, chr-cher-us, chr-latn | | Kinesiska (förenklad) | zh-Hans, zh-cn, zh-hans-cn, zh-sg, zh-hans-sg | | | Kinesiska (traditionell) | zh-Hant, zh-hk, zh-mo, zh-tw, zh-hant-hk, zh-hant-mo, zh-hant-tw, zh-mo, zh-tw, zh-hant-hk, zh-hant-mo, zh-hant-tw | | Kroatiska | hr, hr-hr, hr-ba | | | Tjeckiska | cs, cs-cz | | | Danska | da, da-dk | | Dari | prs, prs-af, prs-arab | | | Nederländska | nl, nl-nl, nl-be | | | Engelska | en, en-au, en-ca, en-gb, en-ie, en-in, en-nz, en-sg, en-us, en-za, en-bz, en-hk, en-id, en-jm, en-kz, en-mt, en-my, en-ph, en-pk, en-tt, en-vn, en-zw | | Estniska | et, et-ee | | | Filipin - fil, fil-latn, fil-ph | | | Finska | fi, fi-fi | | | Franska | fr, fr-be , fr-ca , fr-ch , fr-fr , fr-lu, fr-cd, fr-ci, fr-cm, fr-ht, fr-ma, fr-mc, fr-ml, fr-re, frc-latn, frp-latn | | | Galiciska | gl, gl-es | | Georgiska | ka, ka-ge | | | Tyska | de, de-at, de-ch, de-de, de-lu, de-li | | | Grekiska | el, el-gr | | | Gujarati | gu, gu-in | | | Hausa | ha, ha-latn, ha-latn-ng | | | Hebreiska | he, he-il | | Hindi | hej, hi-in | | Ungerska | hu, hu-hu | | | Isländska | is, is-is | | Igb – ig-latn, ig-ng | | Indonesiska | id, id-id | | | Inuktitut (latinsk) | iu-cans, iu-latn, iu-latn-ca | | Irländska | ga, ga-ie | | | isiXhosa | xh, xh-za | | | isiZulu | zu, zu-za | | | Italienska | it, it-it, it-ch | | | Japanska | ja , ja-jp | | | Kannada | kn, kn-in | | | Kazakiska | kk, kk-kz | | | Khmer | km, km-kh | | | K'iche' | quc-latn, qut-gt, qut-latn | | | Kinyarwanda | rw, rw-rw | | | KiSwahili | sw, sw-ke | | | Konkani | kok, kok-in | | Koreanska | ko, ko-kr | | Kurdiska | ku-arab, ku-arab-iq | | | Kirgizistan | ky-kg, ky-cyrl | | Lao | lo, lo-la | | | Lettiska | lv, lv-lv | | | Litauiska | lt, lt-lt | | | Luxemburgsk | lb, lb-lu | | Makedonska | mk, mk-mk | | | Malay | ms, ms-bn, ms-my | | | Malayalam | ml, ml-in | | | Maltesiska | mt, mt-mt | | | Maori | mi, mi-latn, mi-nz | | Marathi | mr, mr-in | | Mongoliska (kyrilliska) | mn-cyrl, mn-mong, mn-mn, mn-phag | | Nepali | ne, ne-np | | | Norska | nb, nb-no, nn, nn-no, nej, no-no | | | Odia | eller, or-in | | | Persiska | fa, fa-ir | | | Polska | pl, pl-pl | | | Portugisiska (Brasilien) | pt-br | | Portugisiska (Portugal) | pt, pt-pt | | | Punjabi | pa, pa-arab, pa-arab-pk, pa-deva, pa-in | | Quechua | quz, quz-bo, quz-ec, quz-pe | | Rumänska | ro, ro-ro | | | Ryska | ru , ru-ru | | | Skotsk gaeliska | gd-gb, gd-latn | | Serbiska (latinsk) | sr-Latn, sr-latn-cs, sr, sr-latn-ba, sr-latn-me, sr-latn-rs | | | Serbiska (kyrillisk) | sr-cyrl, sr-cyrl-ba, sr-cyrl-cs, sr-cyrl-me, sr-cyrl-rs | | | Sesotho sa Leboa | nso, nso-za | | | Setswana | tn, tn-bw, tn-za | | | Sindhi | sd-arab, sd-arab-pk, sd-deva | | Sinhala | si, si-lk | | | Slovakiska | sk, sk-sk | | | Slovenska | sl, sl-si | | | Spanska | es, es-cl, es-co, es-es, es-mx, es-ar, es-bo, es-cr, es-do, es-ec, es-gt, es-hn, es-ni, es-pa, es-pe, es-pr, es-py, es-sv, es-us, es-uy, es-ve | | Svenska | sv, sv-se, sv-fi | | | Tadzjikiska (kyrilliska) | tg-arab, tg-cyrl, tg-cyrl-tj, tg-latn | | Tamil | ta, ta-in | | | Tatar | tt-arab, tt-cyrl, tt-latn, tt-ru | | Telugu | te, te-in | | | Thailändska | th, th-th | | | Tigrinya | ti, ti-et | | | Turkiska | tr, tr-tr | | | Turkmen | tk-cyrl, tk-latn, tk-tm, tk-latn-tr, tk-cyrl-tr | | | Ukrainska | uk, uk-ua | | | Urdu | din, ur-pk | | | Uiguriska | ug-arab, ug-cn, ug-cyrl, ug-latn | | | Uzbekiska (latinsk) | uz, uz-cyrl, uz-latn, uz-latn-uz | | Vietnamesiska | vi, vi-vn | | | Walesiska | cy, cy-gb | | | Wolof | wo, wo-sn | | Yoruba | yo-latn, yo-ng |

Exempelbegäran

{
    "availability":{
        "markets": ["US"],
        "discoverability": "DISCOVERABLE",
        "enableInFutureMarkets": true,
        "pricing": "PAID",
        "freeTrial": "NO_FREE_TRIAL"
    },
    "properties":{
        "isPrivacyPolicyRequired": true,
        "privacyPolicyUrl": "http://contoso.com",
        "website": "http://contoso.com",
        "supportContactInfo": "http://contoso.com",
        "certificationNotes": "Certification Notes",
        "category": "DeveloperTools",
        "subcategory": "Database",
        "productDeclarations": {
            "dependsOnDriversOrNT": false,
            "accessibilitySupport": false,
            "penAndInkSupport": false
        },
        "isSystemFeatureRequired": [
        {
            "isRequired": true,
                "isRecommended": false,
                "hardwareItemType": "Touch"
            },
            {
                "isRequired": true,
                "isRecommended": false,
                "hardwareItemType": "Keyboard"
            },
            {
                "isRequired": false,
                "isRecommended": false,
                "hardwareItemType": "Mouse"
            },
            {
                "isRequired": false,
                "isRecommended": false,
                "hardwareItemType": "Camera"
            },
            {
                "isRequired": false,
                "isRecommended": false,
                "hardwareItemType": "NFC_HCE"
            },
            {
                "isRequired": false,
                "isRecommended": false,
                "hardwareItemType": "NFC_Proximity"
            },
            {
                "isRequired": false,
                "isRecommended": false,
                "hardwareItemType": "Bluetooth_LE"
            },
            {
                "isRequired": false,
                "isRecommended": false,
                "hardwareItemType": "Telephony"
            },
            {
                "isRequired": false,
                "isRecommended": false,
                "hardwareItemType": "Microphone"
            }
        ],
        "systemRequirementDetails": [
            {
                "minimumRequirement": "1GB",
                "recommendedRequirement": "4GB",
                "hardwareItemType": "Memory"
            },
            {
                "minimumRequirement": "",
                "recommendedRequirement": "",
                "hardwareItemType": "DirectX"
            },
            {
                "minimumRequirement": "",
                "recommendedRequirement": "",
                "hardwareItemType": "Video_Memory"
            },
            {
                "minimumRequirement": "",
                "recommendedRequirement": "",
                "hardwareItemType": "Processor"
            },
            {
                "minimumRequirement": "",
                "recommendedRequirement": "",
                "hardwareItemType": "Graphics"
            }
        ]
    },
    "listings":{
        "language": "en-us",
        "description": "Description",
        "whatsNew": "What's New",
        "productFeatures": ["Feature 1"],
        "shortDescription": "Short Description",
        "searchTerms": ["Search Ter 1"],
        "additionalLicenseTerms": "License Terms",
        "copyright": "Copyright Information",
        "developedBy": "Developer Details",
        "sortTitle": "Product 101",
        "requirements": [
            {
                "minimumHardware": "Pentium4",
                "recommendedHardware": "Corei9"
            }
        ],
        "contactInfo": "contactus@contoso.com"               
    },      
    "listingsToAdd": ["en-au"],
    "listingsToRemove": ["en-gb"]
}

Svarshuvuden

Rubrik Värde
X-Correlation-ID GUID-typens unikt ID för varje begäran. Detta kan delas med supportteamet för att analysera eventuella problem.
Retry-After Den tid i sekunder som klienten måste vänta innan den anropar API:erna igen på grund av hastighetsbegränsning

Svarsparametrar

Namn Typ Beskrivning
ärFramgång Boolesk
Felaktigheter Matris med objekt Listan över eventuella fel- eller varningsmeddelanden
kod Sträng Felkoden för meddelandet
meddelande Sträng Beskrivningen av felet
mål Sträng Entiteten från vilken felet uppstod
svarData Objekt Innehåller faktisk svarsnyttolast för begäran
pollingadress Sträng Avsöknings-URL för att hämta status för alla In-Progress inskickade
pågående inlämnings-ID Sträng Inskicknings-ID för alla redan inskickade In-Progress-inskickningar.

Exempelsvar

{
    "isSuccess": true,
    "errors": [{
        "code": "badrequest",
        "message": "Error Message 1",
        "target": "listings"
        }, {
        "code": "warning",
        "message": "Warning Message 1",
        "target": "properties"
    }],
    "responseData": {
        "pollingUrl": "/submission/v1/product/{productId}/submission/{submissionId}/status",
        "ongoingSubmissionId": ""
    } 
}

Hämta API för aktuellt utkastpaket

Hämtar paketinformation under aktuellt utkast.

sökväg [Alla paket]: /submission/v1/product/{productId}/packages
Metod: GET

sökväg [Enkelt paket]: /submission/v1/product/{productId}/packages/{packageId}
Metod: GET

sökvägsparametrar

Namn Beskrivning
produkt-id Partnercenter-ID:t för produkten
paket-ID Det unika ID för paketet som ska hämtas

Nödvändiga Rubriker

Rubrik Värde
Authorization: Bearer <Token> Använda Microsoft Entra ID-app-ID som registrerats med Partnercenter-kontot
X-Seller-Account-Id Säljar-ID för Partnercenter-konto

Svarshuvuden

Rubrik Värde
X-Correlation-ID GUID-typens unikt ID för varje begäran. Detta kan delas med supportteamet för att analysera eventuella problem.
Retry-After Den tid i sekunder som klienten måste vänta innan den anropar API:erna igen på grund av hastighetsbegränsning.

Svarsparametrar

Namn Typ Beskrivning
ärFramgång Boolesk
Felaktigheter Matris med objekt Listan över eventuella fel eller varningsmeddelanden
kod Sträng Felkoden för meddelandet
meddelande Sträng Beskrivningen av felet
mål Sträng Entiteten som felet uppstod från
svarData Objekt
Paket Matris med objekt Objekt för att lagra paketmoduldata
paket-ID Sträng
paketURL Sträng
Språk Matris med strängar
Arkitekturer Matris med strängar [Neutral, X86, X64, Arm, Arm64]
isSilentInstall Boolesk Detta bör markeras som sant om installationsprogrammet körs i tyst läge utan att det krävs växlar eller annars falskt
installerParametrar Sträng
genericDocUrl Sträng
felfaktadetaljer Matris med objekt
errorScenario Sträng
errorScenarioDetails Matris med objekt
errorValue Sträng
errorUrl Sträng
pakettyp Sträng

Exempelsvar

{   
    "isSuccess": true,
    "errors": [{
        "code": "badrequest",
        "message": "Error Message 1",
        "target": "listings"
    }, {
        "code": "warning",
        "message": "Warning Message 1",
        "target": "properties"
    }],
    "responseData":{
        "packages":[{
            "packageId": "pack0832",
            "packageUrl": "https://www.contoso.com/downloads/1.1/setup.exe",
            "languages": ["en-us"],
            "architectures": ["X86"],
            "isSilentInstall": true,
            "installerParameters": "/s",
            "genericDocUrl": "https://docs.contoso.com/doclink",
            "errorDetails": [{
                "errorScenario": "rebootRequired",
                "errorScenarioDetails": [{
                    "errorValue": "ERR001001",
                    "errorUrl": "https://errors.contoso.com/errors/ERR001001"
                }]
            }],
            "packageType": "exe",
        }]
    }
}

Uppdatera API för aktuella utkastpaket

Uppdaterar paketinformationen under aktuellt utkast.

sökväg [Fullständig moduluppdatering]: /submission/v1/product/{productId}/packages
Metod: PUT

sökväg [Uppdatering av enstaka paketkorrigering]: /submission/v1/product/{productId}/packages/{packageId}
Metod: PATCH

API-beteende

När det gäller API för fullständig moduluppdatering – måste hela paketdata finnas i begäran om fullständig uppdatering av varje fält. Alla fält som inte finns i begäran används standardvärdet för att skriva över aktuellt värde för den specifika modulen. Detta resulterar i att alla befintliga paket skrivs över med en ny uppsättning paket från begäran. Detta resulterar i regenerering av paket-ID:n och användaren bör anropa GET Packages API för de senaste paket-ID:n.

När det gäller API för uppdatering av enstaka paketpatch – behöver endast fält som ska uppdateras för ett visst paket finnas med i anropet. Dessa fältvärden från begäran skriver över sina befintliga värden och behåller alla andra fält som inte finns i begäran, samma som aktuella för det specifika paketet. Andra paket i uppsättningen förblir oförändrade.

sökvägsparametrar

Namn Beskrivning
produkt-id Partnercenter-ID:t för produkten
paket-ID Paketets unika ID

Nödvändiga Rubriker

Rubrik Värde
Authorization: Bearer <Token> Använda Microsoft Entra ID-app-ID som registrerats med Partnercenter-kontot
X-Seller-Account-Id Säljar-ID för Partnercenter-konto

parametrar för begäran

Namn Typ Beskrivning
Paket Matris med objekt Objekt för att lagra paketmoduldata [Krävs endast för fullständig moduluppdatering]
paketURL Sträng Obligatoriskt
Språk Matris med strängar Obligatoriskt
Arkitekturer Matris med strängar Krävs Ska innehålla en enda arkitektur – Neutral, X86, X64, Arm, Arm64
isSilentInstall Boolesk Obligatoriskt Detta bör markeras som sant om installationsprogrammet körs i tyst läge utan att det krävs växlar eller annars falskt
installerParametrar Sträng Krävs om isSilentInstall är falskt
genericDocUrl Sträng Krävs om packageType är exe Länk till dokument som innehåller information om anpassade felkoder för installationsprogrammet av EXE-typ
felfaktadetaljer Matris med objekt Metadata för att lagra anpassade felkoder och information för INSTALLATIONsprogram av EXE-typ.
errorScenario Sträng Identifiera det specifika felscenariot. [installationAvbrutenAvAnvändare, applikationenFinnsRedan, installationPågårRedan, diskenFull, omstartKrävs, nätverksfel, paketAvvisadUnderInstallation, installationLyckad, olika]
errorScenarioDetails Matris med objekt
errorValue Sträng Felkod som kan finnas under installationen
errorUrl Sträng URL för att ha information om felet
pakettyp Sträng Obligatoriskt [exe, msi]

exempelbegäran [fullständig moduluppdatering]

{
    "packages":[{
        "packageUrl": "https://www.contoso.com/downloads/1.1/setup.exe",
        "languages": ["en-us"],
        "architectures": ["X86"],
        "isSilentInstall": true,
        "installerParameters": "/s",
        "genericDocUrl": "https://docs.contoso.com/doclink",
        "errorDetails": [{
            "errorScenario": "rebootRequired",
            "errorScenarioDetails": [{
                "errorValue": "ERR001001",
                "errorUrl": "https://errors.contoso.com/errors/ERR001001"
            }]
        }],
        "packageType": "exe",
    }]
}

Förfrågan om exempel [Uppdatering av enstaka paketkorrigering]

{
    "packageUrl": "https://www.contoso.com/downloads/1.1/setup.exe",
    "languages": ["en-us"],
    "architectures": ["X86"],
    "isSilentInstall": true,
    "installerParameters": "/s",
    "genericDocUrl": "https://docs.contoso.com/doclink",
    "errorDetails": [{
        "errorScenario": "rebootRequired",
        "errorScenarioDetails": [{
            "errorValue": "ERR001001",
            "errorUrl": "https://errors.contoso.com/errors/ERR001001"
        }]
    }],
    "packageType": "exe",
}

Svarshuvuden

Rubrik Värde
X-Correlation-ID GUID-typens unikt ID för varje begäran. Detta kan delas med supportteamet för att analysera eventuella problem.
Retry-After Den tid i sekunder som klienten måste vänta innan den anropar API:erna igen på grund av hastighetsbegränsning.

Svarsparametrar

Namn Typ Beskrivning
ärFramgång Boolesk
Felaktigheter Matris med objekt [Listan över eventuella fel- eller varningsmeddelanden]
kod Sträng Meddelandets felkod
meddelande Sträng Beskrivningen av felet
mål Sträng Entiteten från vilken felet uppstod
svarData Objekt
pollingadress Sträng [Fråge-URL för att hämta inskickningsstatus om det redan är In-Progress inskickad]
pågående inlämnings-ID Sträng [Överförings-ID för alla redan In-Progress inskickade]

Exempelsvar

{
    "isSuccess": true,
    "errors": [{
        "code": "badrequest",
        "message": "Error Message 1",
        "target": "listings"
        }, {
        "code": "warning",
        "message": "Warning Message 1",
        "target": "properties"
    }],
    "responseData": {
        "pollingUrl": "/submission/v1/product/{productId}/submission/{submissionId}/status",
        "ongoingSubmissionId": ""
    } 
}

Commitpaket-API

Bekräftar den nya uppsättningen paket som har uppdaterats med hjälp av API:er för paketuppdatering under det aktuella utkastet. Det här API:et returnerar en avsöknings-URL för att spåra paketuppladdningen.

Sökväg: /submission/v1/product/{productId}/packages/commit
Metod: POST

sökvägsparametrar

Namn Beskrivning
produkt-id Partnercenter-ID:t för produkten

Nödvändiga Rubriker

Rubrik Värde
Authorization: Bearer <Token> Använda Microsoft Entra ID-app-ID:t som registrerats med Partnercenter-kontot
X-Seller-Account-Id Säljar-ID för Partnercenter-konto

Svarshuvuden

Rubrik Värde
X-Correlation-ID GUID-typens unikt ID för varje begäran. Detta kan delas med supportteamet för att analysera eventuella problem.
Retry-After Den tid i sekunder som klienten måste vänta innan den anropar API:erna igen på grund av hastighetsbegränsning.

Svarsparametrar

Namn Typ Beskrivning
ärFramgång Boolesk
Felaktigheter Matris med objekt [Listan över eventuella fel- eller varningsmeddelanden]
kod Sträng Felkoden för meddelandet
meddelande Sträng Beskrivningen av felet
mål Sträng Entiteten som felet uppstod från
svarData Objekt
pollingadress Sträng [Polling-URL för att hämta status för paketuppladdning eller inlämningsstatus vid eventuell redan In-Progress inlämnad]
pågående inlämnings-ID Sträng [Inskicknings-ID för alla inskickningar redan identifierade som In-Progress]

Exempelsvar

{
    "isSuccess": true,
    "errors": [{
        "code": "badrequest",
        "message": "Error Message 1",
        "target": "listings"
        }, {
        "code": "warning",
        "message": "Warning Message 1",
        "target": "properties"
    }],
    "responseData": {
        "pollingUrl": "/submission/v1/product/{productId}/status",
        "ongoingSubmissionId": ""
    } 
}

Hämta API för nuvarande utkast av listningstillgångar

Hämtar en lista över tillgångsinformation under aktuell utkastöverföring.

Sökväg: /submission/v1/product/{productId}/listings/assets?languages={languages}
Metod: GET

sökvägsparametrar

Namn Beskrivning
produkt-id Partnercenter-ID:t för produkten

Frågeparametrar

Namn Beskrivning
Språk [Valfritt] Listspråken filtreras som kommaavgränsad sträng [gräns på upp till 200 språk]. Om de saknas hämtas de första 200 tillgängliga listspråkets tillgångsdata. (t.ex. "en-us, en-gb")

Nödvändiga Rubriker

Rubrik Värde
Authorization: Bearer <Token> Använda Microsoft Entra ID-app-ID:t som registrerats med Partnercenter-kontot
X-Seller-Account-Id Säljar-ID för Partnercenter-konto

Svarshuvuden

Rubrik Värde
X-Correlation-ID GUID-typens unikt ID för varje begäran. Detta kan delas med supportteamet för att analysera eventuella problem.
Retry-After Den tid i sekunder som klienten måste vänta innan den anropar API:erna igen på grund av hastighetsbegränsning.

Svarsparametrar

Namn Typ Beskrivning
ärFramgång Boolesk
Felaktigheter Matris med objekt Listan över eventuella fel- eller varningsmeddelanden
kod Sträng Felkoden för meddelandet
meddelande Sträng Beskrivningen av felet
mål Sträng Entiteten som felet uppstod från
svarData Objekt
listningsresurser Matris med objekt Listar tillgångsdetaljer för varje språk
Språk Sträng
butikens logotyper Matris med objekt
skärmbilder Matris med objekt
Id-nummer Sträng
resursURL Sträng Måste vara en giltig URL
bildstorlek Objekt
bredd Heltal
höjd Heltal

Exempelsvar

{   
"isSuccess": true,
    "errors": [{
        "code": "badrequest",
        "message": "Error Message 1",
        "target": "listings"
        }, {
        "code": "warning",
        "message": "Warning Message 1",
        "target": "properties"
    }],
    "responseData":{
        "listingAssets": [{
            "language": "en-us",
            "storeLogos": [
                {
                    "id": "1234567890abcdefgh",
                    "assetUrl": "https://contoso.com/blob=1234567890abcdefgh",
                    "imageSize": {
                        "width": 2160,
                        "height": 2160
                    }
                }
            ],
            "screenshots": [
                {
                    "id": "1234567891abcdefgh",
                    "assetUrl": "https://contoso.com/blob=1234567891abcdefgh",
                    "imageSize": {
                        "width": 2160,
                        "height": 2160
                    }
                }
            ]
        }]
    }
}

API för att skapa listobjekt

Skapar ny uppladdning av listtillgång under aktuellt utkast.

Uppdatering av listningstillgångar

Microsoft Store Submission API för EXE- eller MSI-appar använder runtime-genererade SAS-URL:er till Blob Stores för uppladdning av varje enskild bildtillgång, följt av ett Commit API-anrop när uppladdningen har slutförts. För att kunna uppdatera listningstillgångar och i sin tur kunna lägga till/ta bort nationella inställningar i listningsmodulen kan följande metod användas:

  1. Använd API:et Skapa listningstillgång för att skicka begäran om uppladdning av tillgångar tillsammans med språk, typ och antal tillgångar.
  2. Baserat på antalet begärda tillgångar skapas tillgångs-ID:er på begäran och skapar en kortsiktig SAS-URL och skickar tillbaka den i svarstexten under typ av tillgångar. Du kan använda den här URL:en för att ladda upp avbildningstillgångar av en viss typ med hjälp av HTTP-klienter [Put Blob (REST API) – Azure Storage | Microsoft Docs].
  3. Efter uppladdningen kan du använda API:et Commit Listing Assets för att även skicka den nya tillgångs-ID-informationen som togs emot tidigare från föregående API-anrop. Det enskilda API:et checkar in listningsdata för tillgångar internt efter valideringen.
  4. Den här metoden skriver effektivt över hela uppsättningen av tidigare avbildningar av tillgångstypen under det specifika språk som skickas i Begäran. Därför tas tidigare uppladdade tillgångar bort.

Sökväg: /submission/v1/product/{productId}/listings/assets/create
Metod: POST

sökvägsparametrar

Namn Beskrivning
produkt-id Partnercenter-ID:t för produkten

Nödvändiga Rubriker

Rubrik Beskrivning
Authorization: Bearer <Token> Använda Microsoft Entra ID-app-ID:t som registrerats med Partnercenter-kontot
X-Seller-Account-Id Säljar-ID för Partnercenter-konto

parametrar för begäran

Namn Typ Beskrivning
Språk Sträng Obligatoriskt
skapaTillgångsförfrågan Objekt Obligatoriskt
Skärmbild Heltal Krävs om ISV behöver uppdatera skärmbilder eller lägga till nytt listspråk [1–10]
Logotyp Heltal Krävs om ISV behöver uppdatera logotyper eller lägga till nytt listspråk [1 eller 2]

Svarshuvuden

Rubrik Beskrivning
X-Correlation-ID GUID-typens unikt ID för varje begäran. Detta kan delas med supportteamet för att analysera eventuella problem.
Retry-After Den tid i sekunder som klienten måste vänta innan den anropar API:erna igen på grund av hastighetsbegränsning.

Svarsparametrar

Namn Typ Beskrivning
ärFramgång Boolesk
Felaktigheter Matris med objekt Listan över eventuella fel- eller varningsmeddelanden
kod Sträng Felkoden för meddelandet
meddelande Sträng Beskrivningen av felet
mål Sträng Entiteten som felet uppstod från
svarData Objekt
listningsresurser Objekt Objekt som innehåller information om StoreLogos och skärmbilder som ska laddas upp
Språk Sträng
butikens logotyper Matris med objekt
skärmbilder Matris med objekt
Id-nummer Sträng
primaryAssetUploadUrl Sträng Primär URL för att ladda upp listtillgång med hjälp av Azure Blob REST API
secondaryAssetUploadUrl Sträng Sekundär URL för att ladda upp listtillgång med hjälp av Azure Blob REST API
httpMetod HTTP-metod HTTP-metoden behövde användas för att ladda upp tillgångar via URL:er för tillgångsuppladdning – primär eller sekundär
httpHeaders (på engelska) Objekt Ett objekt med nycklar som obligatoriska rubriker som ska finnas i UPPladdnings-API-anropet till URL:er för uppladdning av tillgångar. Om värdet inte är tomt måste rubrikerna ha specifika värden. Annars beräknas värden under API-anropet.

Exempelsvar

{
    "isSuccess": true,
    "errors": [{
        "code": "badrequest",
        "message": "Error Message 1",
        "target": "listings"
        }, {
        "code": "warning",
        "message": "Warning Message 1",
        "target": "properties"
    }],
    "responseData": {
        "listingAssets": {
            "language": "en-us",
            "storeLogos":[{
                "id": "1234567890abcdefgh",
                "primaryAssetUploadUrl": "https://contoso.com/upload?blob=1234567890abcdefgh&sig=12345",
                "secondaryAssetUploadUrl": "https://contoso.com/upload?blob=0987654321abcdfger&sig=54326",
                "httpMethod": "PUT",
                "httpHeaders": {"Required Header Name": "Header Value"}
            }],
            "screenshots":[{
                "id": "0987654321abcdfger",
                "primaryAssetUploadUrl": "https://contoso.com/upload?blob=0987654321abcdfger&sig=54321",
                "secondaryAssetUploadUrl": "https://contoso.com/upload?blob=0987654321abcdfger&sig=54322",
                "httpMethod": "PUT",
                "httpHeaders": {"Required Header Name": "Header Value"}

            }]
        }
    } 
}

API för att bekräfta listningstillgångar

Bekräftar den nya noteringstillgång som laddats upp med hjälp av informationen från Create Assets API i det aktuella utkastet.

Sökväg: /submission/v1/product/{productId}/listings/assets/commit
Metod: PUT

sökvägsparametrar

Namn Beskrivning
produkt-id Partnercenter-ID:t för produkten

Nödvändiga Rubriker

Rubrik Beskrivning
Authorization: Bearer <Token> Använda Microsoft Entra ID-app-ID:t som registrerats med Partnercenter-kontot
X-Seller-Account-Id Säljar-ID för Partnercenter-konto

parametrar för begäran

Namn Typ Beskrivning
listningsresurser Objekt
Språk Sträng
butikens logotyper Matris med objekt
skärmbilder Matris med objekt
Id-nummer Sträng Ska antingen vara ett befintligt ID som användaren vill spara från API:et Hämta aktuella listtillgångar eller ett nytt ID där en ny tillgång laddades upp i API:et Skapa listningstillgångar.
resursURL Sträng Ska antingen vara den befintliga tillgångens URL som användaren vill spara från API:et Hämta aktuella listtillgångar eller uppladdnings-URL:en – primär eller sekundär, med vilken en ny tillgång laddades upp i API:et Skapa listningstillgångar. Måste vara en giltig URL

Exempelbegäran

{
    "listingAssets": { 
        "language": "en-us",    
        "storeLogos": [
            {
                "id": "1234567890abcdefgh",
                "assetUrl": "https://contoso.com/blob=1234567890abcdefgh",
            }
        ],
        "screenshots": [
            {
                "id": "1234567891abcdefgh",
                "assetUrl": "https://contoso.com/blob=1234567891abcdefgh",
            }
        ]
    }
}

Svarshuvuden

Rubrik Beskrivning
X-Correlation-ID GUID-typens unikt ID för varje begäran. Detta kan delas med supportteamet för att analysera eventuella problem.
Retry-After Den tid i sekunder som klienten måste vänta innan den anropar API:erna igen på grund av hastighetsbegränsning.

Svarsparametrar

Namn Typ Beskrivning
ärFramgång Boolesk
Felaktigheter Matris med objekt Listan över eventuella fel- eller varningsmeddelanden
kod Sträng Felkoden för meddelandet
meddelande Sträng Beskrivningen av felet
mål Sträng Entiteten som felet uppstod från
svarData Objekt
pollingadress Sträng Pollning-URL för att hämta statusen för pågående inlämning
pågående inlämnings-ID Sträng Inlämnings-ID för någon redan pågående inlämning

Exempelsvar

{
    "isSuccess": true,
    "errors": [{
        "code": "badrequest",
        "message": "Error Message 1",
        "target": "listings"
        }, {
        "code": "warning",
        "message": "Warning Message 1",
        "target": "properties"
    }],
    "responseData": {
        "pollingUrl": "/submission/v1/product/{productId}/submission/{submissionId}/status",
        "ongoingSubmissionId": ""
    } 
}

API för avsökning av modulstatus

API:et för att kontrollera modulberedskapen innan inlämning kan skapas. Verifierar även paketuppladdningsstatusen.

Sökväg: /submission/v1/product/{productId}/status
Metod: GET

sökvägsparametrar

Namn Beskrivning
produkt-id Partnercenter-ID:t för produkten

Nödvändiga Rubriker

Rubrik Beskrivning
Authorization: Bearer <Token> Använda Microsoft Entra ID-app-ID:t som registrerats med Partnercenter-kontot
X-Seller-Account-Id Säljar-ID för Partnercenter-konto

Svarshuvuden

Rubrik Beskrivning
X-Correlation-ID GUID-typens unikt ID för varje begäran. Detta kan delas med supportteamet för att analysera eventuella problem.
Retry-After Den tid i sekunder som klienten måste vänta innan den anropar API:erna igen på grund av hastighetsbegränsning.

Svarsparametrar

Namn Typ Beskrivning
ärFramgång Boolesk
Felaktigheter Matris med objekt Listan över eventuella fel- eller varningsmeddelanden
kod Sträng Felkoden för meddelandet
meddelande Sträng Beskrivningen av felet
mål Sträng Entiteten som felet uppstod från
svarData Objekt
ÄrKlar Boolesk Anger om alla moduler är i klart tillstånd, inklusive paketuppladdning
pågående inlämnings-ID Sträng Inlämnings-ID för någon redan pågående inlämning

Exempelsvar

{
    "isSuccess": true,
    "errors": [{
        "code": "badrequest",
        "message": "Error Message 1",
        "target": "listings"
        }, {
        "code": "warning",
        "message": "Warning Message 1",
        "target": "properties"
    }],
    "responseData": {
        "isReady": true,
        "ongoingSubmissionId": ""
    }
}

Skapa API för överföring

Skapar en inlämning från aktuellt utkast för appen MSI eller EXE. API:et kontrollerar:

  • för aktiv inlämning och resulterar i ett felmeddelande om det finns en aktiv inlämning.
  • om alla moduler är redo för att skapa inlämning.
  • varje fält i sändningen verifieras enligt kraven i Store

Sökväg:/submission/v1/product/{productId}/submit
Metod: POST

sökvägsparametrar

Namn Beskrivning
produkt-id Partnercenter-ID:t för produkten

Nödvändiga Rubriker

Rubrik Beskrivning
Authorization: Bearer <Token> Använda Microsoft Entra ID-app-ID:t som registrerats med Partnercenter-kontot
X-Seller-Account-Id Säljar-ID för Partnercenter-konto

Svarshuvuden

Rubrik Beskrivning
X-Correlation-ID GUID-typens unikt ID för varje begäran. Detta kan delas med supportteamet för att analysera eventuella problem.
Retry-After Den tid i sekunder som klienten måste vänta innan den anropar API:erna igen på grund av hastighetsbegränsning.

Svarsparametrar

Namn Typ Beskrivning
ärFramgång Boolesk
Felaktigheter Matris med objekt Listan över eventuella fel- eller varningsmeddelanden
kod Sträng Felkoden för meddelandet
meddelande Sträng Beskrivningen av felet
mål Sträng Entiteten som felet uppstod från
svarData Objekt
pollingadress Sträng Kontroll-URL för att hämta status för modulens beredskap, inklusive uppladdning av paket för inlämning
insändningsID Sträng ID:t för den nyligen skapade sändningen
pågående inlämnings-ID Sträng Inlämnings-ID för någon redan pågående inlämning

Exempelsvar

{
    "isSuccess": true,
    "errors": [{
        "code": "badrequest",
        "message": "Error Message 1",
        "target": "listings"
        }, {
        "code": "warning",
        "message": "Warning Message 1",
        "target": "properties"
    }],
    "responseData": {
        "submissionId": "1234567890", 
        "pollingUrl": "/submission/v1/product/{productId}/submission/{submissionId}/status",
        "ongoingSubmissionId": ""
    }
}

API för avsökning av inlämningsstatus

API:et för att kontrollera sändningsstatusen.

Sökväg: /submission/v1/product/{productId}/submission/{submissionId}/status
Metod: GET

sökvägsparametrar

Namn Beskrivning
produkt-id Partnercenter-ID:t för produkten

Nödvändiga Rubriker

Rubrik Beskrivning
Authorization: Bearer <Token> Använda Microsoft Entra ID-app-ID:t som registrerats med Partnercenter-kontot
X-Seller-Account-Id Säljar-ID för Partnercenter-konto

Svarshuvuden

Rubrik Beskrivning
X-Correlation-ID GUID-typens unikt ID för varje begäran. Detta kan delas med supportteamet för att analysera eventuella problem.
Retry-After Den tid i sekunder som klienten måste vänta innan den anropar API:erna igen på grund av hastighetsbegränsning.

Svarsparametrar

Namn Typ Beskrivning
ärFramgång Boolesk
Felaktigheter Matris med objekt Listan över eventuella fel- eller varningsmeddelanden
kod Sträng Felkoden för meddelandet
meddelande Sträng Beskrivningen av felet
mål Sträng Entiteten som felet uppstod från
svarData Objekt
publiceringsstatus Sträng Publiceringsstatus för insändning – [INPROGRESS, PUBLICERAD, MISSLYCKAD, OKÄND]
har misslyckats Boolesk Anger om publiceringen har misslyckats och inte kommer att göras om

Exempelsvar

{
    "isSuccess": true,
    "errors": [{
        "code": "badrequest",
        "message": "Error Message 1",
        "target": "listings"
        }, {
        "code": "warning",
        "message": "Warning Message 1",
        "target": "properties"
    }],
    "responseData": {
        "publishingStatus": "INPROGRESS",
        "hasFailed": false
    }
}

Kodexempel

Följande artiklar innehåller detaljerade kodexempel som visar hur du använder Microsoft Store-api:et för överföring på olika programmeringsspråk:

C#-exempel: Microsoft Store Submission API för MSI- eller EXE-app

Den här artikeln innehåller C#-kodexempel som visar hur du använder Microsoft Store-api:et för insändning för MSI eller EXE-appen. Du kan granska varje exempel om du vill veta mer om den uppgift som visas, eller så kan du skapa alla kodexempel i den här artikeln i ett konsolprogram.

Förutsättningar Följande exempel använder följande bibliotek:

  • Newtonsoft.Json NuGet-paket från Newtonsoft.

Main-programmet I följande exempel implementeras ett kommandoradsprogram som anropar de andra exempelmetoderna i den här artikeln för att demonstrera olika sätt att använda api:et för insändning av Microsoft Store. Så här anpassar du det här programmet för eget bruk:

  • Tilldela egenskapen SellerId till säljar-ID:t för ditt Partnercenter-konto.
  • Tilldela egenskapen ApplicationId till ID:t för den app som du vill hantera.
  • Tilldela egenskaperna ClientId och ClientSecret till klient-ID och nyckel för din app och ersätt klient-ID-strängen i TokenEndpoint-URL:en med klient-ID:t för din app. Mer information finns i Så här associerar du ett Microsoft Entra-ID-program med ditt Partnercenter-konto
using System;
using System.Threading.Tasks;

namespace Win32SubmissionApiCSharpSample
{
    public class Program
    {
        static async Task Main(string[] args)
        {
            var config = new ClientConfiguration()
            {
                ApplicationId = "...",
                ClientId = "...",
                ClientSecret = "...",
                Scope = "https://api.store.microsoft.com/.default",
                ServiceUrl = "https://api.store.microsoft.com",
                TokenEndpoint = "...",
                SellerId = 0
            };

            await new AppSubmissionUpdateSample(config).RunAppSubmissionUpdateSample();

        }
    }
}

Hjälpklassen ClientConfiguration med C#

Exempelappen använder hjälpklassen ClientConfiguration för att skicka Microsoft Entra ID Directory-data och appdata till var och en av de exempelmetoder som använder Microsoft Store-api:et för överföring.

using System;
using System.Collections.Generic;
using System.Text;

namespace Win32SubmissionApiCSharpSample
{
    public class ClientConfiguration
    {
        /// <summary>
        /// Client Id of your Microsoft Entra ID Directory app.
        /// Example" 00001111-aaaa-2222-bbbb-3333cccc4444
        /// </summary>
        public string ClientId { get; set; }

        /// <summary>
        /// Client secret of your Microsoft Entra ID Directory app
        /// </summary>
        public string ClientSecret { get; set; }

        /// <summary>
        /// Service root endpoint.
        /// Example: "https://api.store.microsoft.com"
        /// </summary>
        public string ServiceUrl { get; set; }

        /// <summary>
        /// Token endpoint to which the request is to be made. Specific to your Microsoft Entra ID Directory app
        /// Example: https://login.microsoftonline.com/d454d300-128e-2d81-334a-27d9b2baf002/oauth2/v2.0/token
        /// </summary>
        public string TokenEndpoint { get; set; }

        /// <summary>
        /// Resource scope. If not provided (set to null), default one is used for the production API
        /// endpoint ("https://api.store.microsoft.com/.default")
        /// </summary>
        public string Scope { get; set; }

        /// <summary>
        /// Partner Center Application ID.
        /// Example: 3e31a9f9-84e8-4d2d-9eba-487878d02ebf
        /// </summary>
        public string ApplicationId { get; set; }


        /// <summary>
        /// The Partner Center Seller Id
        /// Example: 123456892
        /// </summary>
        public int SellerId { get; set; }
    }
}

Skapa en appinlämning med C#

I följande exempel implementeras en klass som använder flera metoder i Microsoft Store-api:et för insändning för att uppdatera en appöverföring.

using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

namespace Win32SubmissionApiCSharpSample
{
    public class AppSubmissionUpdateSample
    {
        private ClientConfiguration ClientConfig;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="configuration">An instance of ClientConfiguration that contains all parameters populated</param>
        public AppSubmissionUpdateSample(ClientConfiguration configuration)
        {
            this.ClientConfig = configuration;
        }

        /// <summary>
        /// Main method to Run the Sample Application
        /// </summary>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        public async Task RunAppSubmissionUpdateSample()
        {
            // **********************
            //       SETTINGS
            // **********************
            var appId = this.ClientConfig.ApplicationId;
            var clientId = this.ClientConfig.ClientId;
            var clientSecret = this.ClientConfig.ClientSecret;
            var serviceEndpoint = this.ClientConfig.ServiceUrl;
            var tokenEndpoint = this.ClientConfig.TokenEndpoint;
            var scope = this.ClientConfig.Scope;

            // Get authorization token.
            Console.WriteLine("Getting authorization token");
            var accessToken = await SubmissionClient.GetClientCredentialAccessToken(
                tokenEndpoint,
                clientId,
                clientSecret,
                scope);

            var client = new SubmissionClient(accessToken, serviceEndpoint);

            client.DefaultHeaders = new Dictionary<string, string>()
            {
                {"X-Seller-Account-Id", this.ClientConfig.SellerId.ToString() }
            };

            Console.WriteLine("Getting Current Application Draft Status");
            
            dynamic AppDraftStatus = await client.Invoke<dynamic>(HttpMethod.Get, string.Format(SubmissionClient.ProductDraftStatusPollingUrlTemplate,
                SubmissionClient.Version, appId), null);
            
            Console.WriteLine(AppDraftStatus.ToString());

            Console.WriteLine("Getting Application Packages ");

            dynamic PackagesResponse = await client.Invoke<dynamic>(HttpMethod.Get, string.Format(SubmissionClient.PackagesUrlTemplate,
                SubmissionClient.Version, appId), null);

            Console.WriteLine(PackagesResponse.ToString());

            Console.WriteLine("Getting Single Package");

            dynamic SinglePackageResponse = await client.Invoke<dynamic>(HttpMethod.Get, string.Format(SubmissionClient.PackageByIdUrlTemplate,
                SubmissionClient.Version, appId, (string)PackagesResponse.responseData.packages[0].packageId), null);

            Console.WriteLine(SinglePackageResponse.ToString());

            Console.WriteLine("Updating Entire Package Set");

            // Update data in Packages list to have final set of updated Packages

            // Example - Updating Installer Parameters
            PackagesResponse.responseData.packages[0].installerParameters = "/s /r new-args";

            dynamic PackagesUpdateRequest = new
            {
                packages = PackagesResponse.responseData.packages
            };

            dynamic PackagesUpdateResponse = await client.Invoke<dynamic>(HttpMethod.Put, string.Format(SubmissionClient.PackagesUrlTemplate,
                SubmissionClient.Version, appId), PackagesUpdateRequest);

            Console.WriteLine(PackagesUpdateResponse.ToString());

            Console.WriteLine("Updating Single Package's Download Url");

            // Update data in the SinglePackage object

            var SinglePackageUpdateRequest = SinglePackageResponse.responseData.packages[0];

            // Example - Updating Installer Parameters
            SinglePackageUpdateRequest.installerParameters = "/s /r /t new-args";

            dynamic PackageUpdateResponse = await client.Invoke<dynamic>(HttpMethod.Patch, string.Format(SubmissionClient.PackageByIdUrlTemplate,
                SubmissionClient.Version, appId, SinglePackageUpdateRequest.packageId), SinglePackageUpdateRequest);

            Console.WriteLine("Committing Packages");

            dynamic PackageCommitResponse = await client.Invoke<dynamic>(HttpMethod.Post, string.Format(SubmissionClient.PackagesCommitUrlTemplate,
                SubmissionClient.Version, appId), null);

            Console.WriteLine(PackageCommitResponse.ToString());

            Console.WriteLine("Polling Package Upload Status");

            AppDraftStatus = await client.Invoke<dynamic>(HttpMethod.Get, string.Format(SubmissionClient.ProductDraftStatusPollingUrlTemplate,
                SubmissionClient.Version, appId), null);

            while (!((bool)AppDraftStatus.responseData.isReady))
            {
                AppDraftStatus = await client.Invoke<dynamic>(HttpMethod.Get, string.Format(SubmissionClient.ProductDraftStatusPollingUrlTemplate,
                    SubmissionClient.Version, appId), null);

                Console.WriteLine("Waiting for Upload to finish");

                await Task.Delay(TimeSpan.FromSeconds(2));

                if(AppDraftStatus.errors != null && AppDraftStatus.errors.Count > 0)
                {
                    for(var index = 0; index < AppDraftStatus.errors.Count; index++)
                    {
                        if(AppDraftStatus.errors[index].code == "packageuploaderror")
                        {
                            throw new InvalidOperationException("Package Upload Failed. Please try committing packages again.");
                        }
                    }
                }
            }

            Console.WriteLine("Getting Application Metadata - All Modules");

            dynamic AppMetadata = await client.Invoke<dynamic>(HttpMethod.Get, string.Format(SubmissionClient.AppMetadataUrlTemplate,
                SubmissionClient.Version, appId), null);

            Console.WriteLine(AppMetadata.ToString());

            Console.WriteLine("Getting Application Metadata - Listings");

            dynamic AppListingsMetadata = await client.Invoke<dynamic>(HttpMethod.Get, string.Format(SubmissionClient.AppListingsFetchMetadataUrlTemplate,
                SubmissionClient.Version, appId), null);

            Console.WriteLine(AppListingsMetadata.ToString());

            Console.WriteLine("Updating Listings Metadata - Description");

            // Update Required Fields in Listings Metadata Object - Per Language. For eg. AppListingsMetadata.responseData.listings[0]

            // Example - Updating Description
            AppListingsMetadata.responseData.listings[0].description = "New Description Updated By C# Sample Code";

            dynamic ListingsUpdateRequest = new
            {
                listings = AppListingsMetadata.responseData.listings[0]
            };

            dynamic UpdateListingsMetadataResponse = await client.Invoke<dynamic>(HttpMethod.Put, string.Format(SubmissionClient.AppMetadataUrlTemplate,
                SubmissionClient.Version, appId), ListingsUpdateRequest);

            Console.WriteLine(UpdateListingsMetadataResponse.ToString());

            Console.WriteLine("Getting All Listings Assets");

            dynamic ListingAssets = await client.Invoke<dynamic>(HttpMethod.Get, string.Format(SubmissionClient.ListingAssetsUrlTemplate,
                SubmissionClient.Version, appId), null);

            Console.WriteLine(ListingAssets.ToString());

            Console.WriteLine("Creating Listing Assets for 1 Screenshot");

            
            dynamic AssetCreateRequest = new
            {
                language = ListingAssets.responseData.listingAssets[0].language,
                createAssetRequest = new Dictionary<string, int>()
                {
                    {"Screenshot", 1 },
                    {"Logo", 0 }
                }
            };

            dynamic AssetCreateResponse = await client.Invoke<dynamic>(HttpMethod.Post, string.Format(SubmissionClient.ListingAssetsCreateUrlTemplate,
               SubmissionClient.Version, appId), AssetCreateRequest);

            Console.WriteLine(AssetCreateResponse.ToString());

            Console.WriteLine("Uploading Listing Assets");

            // Path to PNG File to be Uploaded as Screenshot / Logo
            var PathToFile = "./Image.png";
            var AssetToUpload = File.OpenRead(PathToFile);

            await client.UploadAsset(AssetCreateResponse.responseData.listingAssets.screenshots[0].primaryAssetUploadUrl.Value as string, AssetToUpload);

            Console.WriteLine("Committing Listing Assets");

            dynamic AssetCommitRequest = new
            {
                listingAssets = new
                {
                    language = ListingAssets.responseData.listingAssets[0].language,
                    storeLogos = ListingAssets.responseData.listingAssets[0].storeLogos,
                    screenshots = JToken.FromObject(new List<dynamic>() { new
                {
                    id = AssetCreateResponse.responseData.listingAssets.screenshots[0].id.Value as string,
                    assetUrl = AssetCreateResponse.responseData.listingAssets.screenshots[0].primaryAssetUploadUrl.Value as string
                }
                }.ToArray())
                }
            };

            dynamic AssetCommitResponse = await client.Invoke<dynamic>(HttpMethod.Put, string.Format(SubmissionClient.ListingAssetsCommitUrlTemplate,
               SubmissionClient.Version, appId), AssetCommitRequest);

            Console.WriteLine(AssetCommitResponse.ToString());

            Console.WriteLine("Getting Current Application Draft Status before Submission");

            AppDraftStatus = await client.Invoke<dynamic>(HttpMethod.Get, string.Format(SubmissionClient.ProductDraftStatusPollingUrlTemplate,
                SubmissionClient.Version, appId), null);

            Console.WriteLine(AppDraftStatus.ToString());

            if (AppDraftStatus == null || !((bool)AppDraftStatus.responseData.isReady))
            {
                throw new InvalidOperationException("Application Current Status is not in Ready Status for All Modules");
            }

            Console.WriteLine("Creating Submission");

            dynamic SubmissionCreationResponse = await client.Invoke<dynamic>(HttpMethod.Post, string.Format(SubmissionClient.CreateSubmissionUrlTemplate,
                SubmissionClient.Version, appId), null);

            Console.WriteLine(SubmissionCreationResponse.ToString());

            Console.WriteLine("Current Submission Status");

            dynamic SubmissionStatus = await client.Invoke<dynamic>(HttpMethod.Get, string.Format(SubmissionClient.SubmissionStatusPollingUrlTemplate,
                SubmissionClient.Version, appId, SubmissionCreationResponse.responseData.submissionId.Value as string), null);

            Console.Write(SubmissionStatus.ToString());

            // User can Poll on this API to know if Submission Status is INPROGRESS, PUBLISHED or FAILED.
            // This Process involves File Scanning, App Certification and Publishing and can take more than a day.
        }
    }
}

IngestionClient-hjälpklass med hjälp av C#

Klassen IngestionClient innehåller hjälpmetoder som används av andra metoder i exempelappen för att utföra följande uppgifter:

  • Få en Microsoft Entra ID-åtkomst-token som kan användas för att anropa metoder i Microsoft Store-API för inskickning. När du har hämtat en token har du 60 minuter på dig att använda den här token i anrop till Microsoft Store-api:et för överföring innan token upphör att gälla. När token har upphört att gälla kan du generera en ny token.
  • Bearbeta HTTP-begäranden för Microsoft Store-api:et för överföring.
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

namespace Win32SubmissionApiCSharpSample
{
    /// <summary>
    /// This class is a proxy that abstracts the functionality of the API service
    /// </summary>
    public class SubmissionClient : IDisposable
    {
        public static readonly string Version = "1";
        private HttpClient httpClient;
        private HttpClient imageUploadClient;

        private readonly string accessToken;

        public static readonly string PackagesUrlTemplate = "/submission/v{0}/product/{1}/packages";
        public static readonly string PackageByIdUrlTemplate = "/submission/v{0}/product/{1}/packages/{2}";
        public static readonly string PackagesCommitUrlTemplate = "/submission/v{0}/product/{1}/packages/commit";
        public static readonly string AppMetadataUrlTemplate = "/submission/v{0}/product/{1}/metadata";
        public static readonly string AppListingsFetchMetadataUrlTemplate = "/submission/v{0}/product/{1}/metadata/listings";
        public static readonly string ListingAssetsUrlTemplate = "/submission/v{0}/product/{1}/listings/assets";
        public static readonly string ListingAssetsCreateUrlTemplate = "/submission/v{0}/product/{1}/listings/assets/create";
        public static readonly string ListingAssetsCommitUrlTemplate = "/submission/v{0}/product/{1}/listings/assets/commit";
        public static readonly string ProductDraftStatusPollingUrlTemplate = "/submission/v{0}/product/{1}/status";
        public static readonly string CreateSubmissionUrlTemplate = "/submission/v{0}/product/{1}/submit";
        public static readonly string SubmissionStatusPollingUrlTemplate = "/submission/v{0}/product/{1}/submission/{2}/status";

        public const string JsonContentType = "application/json";
        public const string PngContentType = "image/png";
        public const string BinaryStreamContentType = "application/octet-stream";

        /// <summary>
        /// Initializes a new instance of the <see cref="SubmissionClient" /> class.
        /// </summary>
        /// <param name="accessToken">
        /// The access token. This is JWT a token obtained from Microsoft Entra ID Directory allowing the caller to invoke the API
        /// on behalf of a user
        /// </param>
        /// <param name="serviceUrl">The service URL.</param>
        public SubmissionClient(string accessToken, string serviceUrl)
        {
            if (string.IsNullOrEmpty(accessToken))
            {
                throw new ArgumentNullException("accessToken");
            }

            if (string.IsNullOrEmpty(serviceUrl))
            {
                throw new ArgumentNullException("serviceUrl");
            }

            this.accessToken = accessToken;
            this.httpClient = new HttpClient
            {
                BaseAddress = new Uri(serviceUrl)
            };
            this.imageUploadClient = new HttpClient();
            this.DefaultHeaders = new Dictionary<string, string>();
        }

        /// <summary>
        /// Gets or Sets the default headers.
        /// </summary>
        public Dictionary<string, string> DefaultHeaders { get; set; }

        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting
        /// unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            if (this.httpClient != null)
            {
                this.httpClient.Dispose();
                this.httpClient = null;
                GC.SuppressFinalize(this);
            }
        }

        /// <summary>
        /// Gets the authorization token for the provided client id, client secret, and the scope.
        /// This token is usually valid for 1 hour, so if your submission takes longer than that to complete,
        /// make sure to get a new one periodically.
        /// </summary>
        /// <param name="tokenEndpoint">Token endpoint to which the request is to be made. Specific to your
        /// Microsoft Entra ID Directory app. Example: https://login.microsoftonline.com/d454d300-128e-2d81-334a-27d9b2baf002/oauth2/v2.0/token </param>
        /// <param name="clientId">Client Id of your Microsoft Entra ID Directory app. Example" 00001111-aaaa-2222-bbbb-3333cccc4444</param>
        /// <param name="clientSecret">Client secret of your Microsoft Entra ID Directory app</param>
        /// <param name="scope">Scope. If not provided, default one is used for the production API endpoint.</param>
        /// <returns>Autorization token. Prepend it with "Bearer: " and pass it in the request header as the
        /// value for "Authorization: " header.</returns>
        public static async Task<string> GetClientCredentialAccessToken(
            string tokenEndpoint,
            string clientId,
            string clientSecret,
            string scope = null)
        {
            if (scope == null)
            {
                scope = "https://api.store.microsoft.com/.default";
            }

            dynamic result;
            using (HttpClient client = new HttpClient())
            {
                string tokenUrl = tokenEndpoint;
                using (
                    HttpRequestMessage request = new HttpRequestMessage(
                        HttpMethod.Post,
                        tokenUrl))
                {
                    string strContent =
                        string.Format(
                            "grant_type=client_credentials&client_id={0}&client_secret={1}&scope={2}",
                            clientId,
                            clientSecret,
                            scope);

                    request.Content = new StringContent(strContent, Encoding.UTF8,
                        "application/x-www-form-urlencoded");

                    using (HttpResponseMessage response = await client.SendAsync(request))
                    {
                        string responseContent = await response.Content.ReadAsStringAsync();
                        result = JsonConvert.DeserializeObject(responseContent);
                    }
                }
            }

            return result.access_token;
        }


        /// <summary>
        /// Invokes the specified HTTP method.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="httpMethod">The HTTP method.</param>
        /// <param name="relativeUrl">The relative URL.</param>
        /// <param name="requestContent">Content of the request.</param>
        /// <returns>instance of the type T</returns>
        /// <exception cref="ServiceException"></exception>
        public async Task<T> Invoke<T>(HttpMethod httpMethod,
            string relativeUrl,
            object requestContent)
        {
            using (var request = new HttpRequestMessage(httpMethod, relativeUrl))
            {
                this.SetRequest(request, requestContent);

                using (HttpResponseMessage response = await this.httpClient.SendAsync(request))
                {
                    T result;
                    if (this.TryHandleResponse(response, out result))
                    {
                        return result;
                    }

                    if (response.IsSuccessStatusCode)
                    {
                        var resource = JsonConvert.DeserializeObject<T>(await response.Content.ReadAsStringAsync());
                        return resource;
                    }

                    throw new Exception(await response.Content.ReadAsStringAsync());
                }
            }
        }

        /// <summary>
        /// Uploads a given Image Asset file to Asset Storage
        /// </summary>
        /// <param name="assetUploadUrl">Asset Storage Url</param>
        /// <param name="fileStream">The Stream instance of file to be uploaded</param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public async Task UploadAsset(string assetUploadUrl, Stream fileStream)
        {
            using (var request = new HttpRequestMessage(HttpMethod.Put, assetUploadUrl))
            {
                request.Headers.Add("x-ms-blob-type", "BlockBlob");
                request.Content = new StreamContent(fileStream);
                request.Content.Headers.ContentType = new MediaTypeHeaderValue(PngContentType);
                using (HttpResponseMessage response = await this.imageUploadClient.SendAsync(request))
                {
                    if (response.IsSuccessStatusCode)
                    {
                        return;
                    }
                    throw new Exception(await response.Content.ReadAsStringAsync());
                }
            }
        }

        /// <summary>
        /// Sets the request.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <param name="requestContent">Content of the request.</param>
        protected virtual void SetRequest(HttpRequestMessage request, object requestContent)
        {
            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", this.accessToken);

            foreach (var header in this.DefaultHeaders)
            {
                request.Headers.Add(header.Key, header.Value);
            }

            if (requestContent != null)
            {
                request.Content = new StringContent(JsonConvert.SerializeObject(requestContent),
                        Encoding.UTF8,
                        JsonContentType);
                
            }
        }


        /// <summary>
        /// Tries the handle response.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="response">The response.</param>
        /// <param name="result">The result.</param>
        /// <returns>true if the response was handled</returns>
        protected virtual bool TryHandleResponse<T>(HttpResponseMessage response, out T result)
        {
            result = default(T);
            return false;
        }
    }
}

Node.js exempel: Microsoft Store Submission API för MSI- eller EXE-app

Den här artikeln innehåller Node.js kodexempel som visar hur du använder Microsoft Store-api:et för insändning för MSI eller EXE-appen. Du kan granska varje exempel om du vill veta mer om den uppgift som visas, eller så kan du skapa alla kodexempel i den här artikeln i ett konsolprogram.

Förutsättningar Följande exempel använder följande bibliotek:

  • node-fetch v2 [npm install node-fetch@2]

Skapa en appinlämning med hjälp av node.js

I följande exempel anropas de andra exempelmetoderna i den här artikeln för att demonstrera olika sätt att använda Microsoft Store-api:et för insändning. Så här anpassar du det här programmet för eget bruk:

  • Tilldela egenskapen SellerId till säljar-ID:t för ditt Partnercenter-konto.
  • Tilldela egenskapen ApplicationId till ID:t för den app som du vill hantera.
  • Tilldela egenskaperna ClientId och ClientSecret till klient-ID och nyckel för din app och ersätt klient-ID-strängen i TokenEndpoint-URL:en med klient-ID:t för din app. Mer information finns i Så här associerar du ett Microsoft Entra-ID-program med ditt Partnercenter-konto

I följande exempel implementeras en klass som använder flera metoder i Microsoft Store-api:et för insändning för att uppdatera en appöverföring.

const config = require('./Configuration');
const submissionClient = require('./SubmissionClient');
const fs = require('fs');

var client = new submissionClient(config);

/**
 * Main entry method to Run the Store Submission API Node.js Sample
 */
async function RunNodeJsSample(){
    print('Getting Access Token');
    await client.getAccessToken();
    
    print('Getting Current Application Draft Status');
    var currentDraftStatus = await client.callStoreAPI(client.productDraftStatusPollingUrlTemplate, 'get');
    print(currentDraftStatus);

    print('Getting Application Packages');
    var currentPackages = await client.callStoreAPI(client.packagesUrlTemplate, 'get');
    print(currentPackages);

    print('Getting Single Package');
    var packageId = currentPackages.responseData.packages[0].packageId;
    var packageIdUrl = `${client.packageByIdUrlTemplate}`.replace('{packageId}', packageId);
    var singlePackage = await client.callStoreAPI(packageIdUrl, 'get');
    print(singlePackage);

    print('Updating Entire Package Set');
    // Update data in Packages list to have final set of updated Packages
    currentPackages.responseData.packages[0].installerParameters = "/s /r new-args";
    var packagesUpdateRequest = {
        'packages': currentPackages.responseData.packages
    };
    print(packagesUpdateRequest);
    var packagesUpdateResponse = await client.callStoreAPI(client.packagesUrlTemplate, 'put', packagesUpdateRequest);
    print(packagesUpdateResponse);

    print('Updating Single Package\'s Download Url');
    // Update data in the SinglePackage object
    singlePackage.responseData.packages[0].installerParameters = "/s /r /t new-args";
    var singlePackageUpdateResponse = await client.callStoreAPI(packageIdUrl, 'patch', singlePackage.responseData.packages[0]);
    print(singlePackageUpdateResponse);

    print('Committing Packages');
    var commitPackagesResponse = await client.callStoreAPI(client.packagesCommitUrlTemplate, 'post');
    print(commitPackagesResponse);

    await poll(async ()=>{
        print('Waiting for Upload to finish');
        return await client.callStoreAPI(client.productDraftStatusPollingUrlTemplate, 'get');
    }, 2);

    print('Getting Application Metadata - All Modules');
    var appMetadata = await client.callStoreAPI(client.appMetadataUrlTemplate, 'get');
    print(appMetadata);

    print('Getting Application Metadata - Listings');
    var appListingMetadata = await client.callStoreAPI(client.appListingsFetchMetadataUrlTemplate, 'get');
    print(appListingMetadata);

    print('Updating Listings Metadata - Description');   
    // Update Required Fields in Listings Metadata Object - Per Language. For eg. AppListingsMetadata.responseData.listings[0]
    // Example - Updating Description
    appListingMetadata.responseData.listings[0].description = 'New Description Updated By Node.js Sample Code';
    var listingsUpdateRequest = {
        'listings': appListingMetadata.responseData.listings[0]
    };
    var listingsMetadataUpdateResponse = await client.callStoreAPI(client.appMetadataUrlTemplate, 'put', listingsUpdateRequest);
    print(listingsMetadataUpdateResponse);

    print('Getting All Listings Assets');
    var listingAssets = await client.callStoreAPI(client.listingAssetsUrlTemplate, 'get');
    print(listingAssets);

    print('Creating Listing Assets for 1 Screenshot');
    var listingAssetCreateRequest = {
        'language': listingAssets.responseData.listingAssets[0].language,
        'createAssetRequest': {
            'Screenshot': 1,
            'Logo': 0
        }
    };
    var listingAssetCreateResponse = await client.callStoreAPI(client.listingAssetsCreateUrlTemplate, 'post', listingAssetCreateRequest);
    print(listingAssetCreateResponse);

    print('Uploading Listing Assets');
    const pathToFile = './Image.png';
    const stats = fs.statSync(pathToFile);
    const fileSize = stats.size;
    const fileStream = fs.createReadStream(pathToFile);
    await client.uploadAssets(listingAssetCreateResponse.responseData.listingAssets.screenshots[0].primaryAssetUploadUrl, fileStream, fileSize);

    print('Committing Listing Assets');
    var assetCommitRequest = {
        'listingAssets': {
            'language': listingAssets.responseData.listingAssets[0].language,
            'storeLogos': listingAssets.responseData.listingAssets[0].storeLogos,
            'screenshots': [{
                'id': listingAssetCreateResponse.responseData.listingAssets.screenshots[0].id,
                'assetUrl': listingAssetCreateResponse.responseData.listingAssets.screenshots[0].primaryAssetUploadUrl
            }]
        }
    };
    var assetCommitResponse = await client.callStoreAPI(client.listingAssetsCommitUrlTemplate, 'put', assetCommitRequest);
    print(assetCommitResponse);

    print('Getting Current Application Draft Status before Submission');
    currentDraftStatus = await client.callStoreAPI(client.productDraftStatusPollingUrlTemplate, 'get');
    print(currentDraftStatus);
    if(!currentDraftStatus.responseData.isReady){
        throw new Error('Application Current Status is not in Ready Status for All Modules');
    }

    print('Creating Submission');
    var submissionCreationResponse = await client.callStoreAPI(client.createSubmissionUrlTemplate, 'post');
    print(submissionCreationResponse);

    print('Current Submission Status');
    var submissionStatusUrl = `${client.submissionStatusPollingUrlTemplate}`.replace('{submissionId}', submissionCreationResponse.responseData.submissionId);
    var submissionStatusResponse = await client.callStoreAPI(submissionStatusUrl, 'get');
    print(submissionStatusResponse);

    // User can Poll on this API to know if Submission Status is INPROGRESS, PUBLISHED or FAILED.
    // This Process involves File Scanning, App Certification and Publishing and can take more than a day.
}

/**
 * Utility Method to Poll using a given function and time interval in seconds
 * @param {*} func 
 * @param {*} intervalInSeconds 
 * @returns 
 */
async function poll(func, intervalInSeconds){
var result = await func();
if(result.responseData.isReady){
    Promise.resolve(true);
}
else if(result.errors && result.errors.length > 0 && result.errors.find(element => element.code == 'packageuploaderror') != undefined){
throw new Error('Package Upload Failed');
}
else{
    await new Promise(resolve => setTimeout(resolve, intervalInSeconds*1000));
    return await poll(func, intervalInSeconds); 
}
}

/**
 * Utility function to Print a Json or normal string
 * @param {*} json 
 */
function print(json){
    if(typeof(json) == 'string'){
        console.log(json);
    }
    else{
        console.log(JSON.stringify(json));
    }
    console.log("\n");
}

/** Run the Node.js Sample Application */
RunNodeJsSample();

ClientConfiguration-hjälpare

Exempelappen använder hjälpklassen ClientConfiguration för att skicka Microsoft Entra ID Directory-data och appdata till var och en av de exempelmetoder som använder Microsoft Store-api:et för överföring.

/** Configuration Object for Store Submission API */
var config = {
    version : "1",
    applicationId : "...",
    clientId : "...",
    clientSecret : "...",
    serviceEndpoint : "https://api.store.microsoft.com",
    tokenEndpoint : "...",
    scope : "https://api.store.microsoft.com/.default",
    sellerId : "...",
    jsonContentType : "application/json",
    pngContentType : "image/png",
    binaryStreamContentType : "application/octet-stream"
};

module.exports = config;

IngestionClient-hjälpverktyg via node.js

Klassen IngestionClient innehåller hjälpmetoder som används av andra metoder i exempelappen för att utföra följande uppgifter:

  • Få en Microsoft Entra ID-åtkomst-token som kan användas för att anropa metoder i Microsoft Store-API för inskickning. När du har hämtat en token har du 60 minuter på dig att använda den här token i anrop till Microsoft Store-api:et för överföring innan token upphör att gälla. När token har upphört att gälla kan du generera en ny token.
  • Bearbeta HTTP-begäranden för Microsoft Store-api:et för överföring.
const fetch = require('node-fetch');
/**
 * Submission Client to invoke all available Store Submission API and Asset Upload to Blob Store
 */
class SubmissionClient{

    constructor(config){
        this.configuration = config;
        this.accessToken = "";
        this.packagesUrlTemplate = `/submission/v${this.configuration.version}/product/${this.configuration.applicationId}/packages`;
        this.packageByIdUrlTemplate = `/submission/v${this.configuration.version}/product/${this.configuration.applicationId}/packages/{packageId}`;
        this.packagesCommitUrlTemplate = `/submission/v${this.configuration.version}/product/${this.configuration.applicationId}/packages/commit`;
        this.appMetadataUrlTemplate = `/submission/v${this.configuration.version}/product/${this.configuration.applicationId}/metadata`;
        this.appListingsFetchMetadataUrlTemplate = `/submission/v${this.configuration.version}/product/${this.configuration.applicationId}/metadata/listings`;
        this.listingAssetsUrlTemplate = `/submission/v${this.configuration.version}/product/${this.configuration.applicationId}/listings/assets`;
        this.listingAssetsCreateUrlTemplate = `/submission/v${this.configuration.version}/product/${this.configuration.applicationId}/listings/assets/create`;
        this.listingAssetsCommitUrlTemplate = `/submission/v${this.configuration.version}/product/${this.configuration.applicationId}/listings/assets/commit`;
        this.productDraftStatusPollingUrlTemplate = `/submission/v${this.configuration.version}/product/${this.configuration.applicationId}/status`;
        this.createSubmissionUrlTemplate = `/submission/v${this.configuration.version}/product/${this.configuration.applicationId}/submit`;
        this.submissionStatusPollingUrlTemplate = `/submission/v${this.configuration.version}/product/${this.configuration.applicationId}/submission/{submissionId}/status`;
    }
    
    async getAccessToken(){
        var params = new URLSearchParams();
        params.append('grant_type','client_credentials');
        params.append('client_id',this.configuration.clientId);
        params.append('client_secret',this.configuration.clientSecret);
        params.append('scope',this.configuration.scope);
        var response = await fetch(this.configuration.tokenEndpoint,{
            method: "POST",
            body: params
        });    
        var data = await response.json();
        this.accessToken = data.access_token;
    }

    async callStoreAPI(url, method, data){
        var request = {
            method: method,
            headers:{
                'Authorization': `Bearer ${this.accessToken}`,
                'Content-Type': this.configuration.jsonContentType,
                'X-Seller-Account-Id': this.configuration.sellerId
            },            
        };
        if(data){
            request.body = JSON.stringify(data);
        }
        var response = await fetch(`${this.configuration.serviceEndpoint}${url}`,request);
        var jsonResponse = await response.json();
        return jsonResponse;
    }

    async uploadAssets(url, stream, size){
        var request = {
            method: 'put',
            headers:{
                'Content-Type': this.configuration.pngContentType,
                'x-ms-blob-type': 'BlockBlob',
                "Content-length": size
            },            
            body: stream
        };
        var response = await fetch(`${url}`,request);
        if(response.ok){
            return response;
        }
        else{
            throw new Error('Uploading of assets failed');
        }
    }
}
module.exports = SubmissionClient;

Ytterligare hjälp

Om du har frågor om MICROSOFT Store-api:et för insändning eller om du behöver hjälp med att hantera dina bidrag med det här API:et använder du följande resurser:

  • Ställ dina frågor på våra forum.
  • Besök vår supportsida och begär ett av de assisterade supportalternativen för Partner Center. Om du uppmanas att välja en problemtyp och kategori väljer du Appöverföring och certifiering respektive Skicka in en app.

Vanliga frågor och svar

  1. Vad kan jag göra via api:et för Microsoft Store överföring?

    API:n för Microsoft Store-insändning gör det möjligt för utvecklare att automatisera apphanterings-uppgifter, inklusive:

    • Skapa och skicka nya appuppdateringar.
    • Ladda upp och hantera apppaket.
    • Uppdaterar metadata och Store-listor.

    Du kan integrera det här API:et i dina kontinuerliga integrerings- eller byggarbetsflöden och automatisera rutinuppgifter för att effektivisera publiceringsprocessen.