Error Code 4128

I am using powershell to automate the upload and submission of my app.
i can upload the file and I get a file key in response but when I go to update and add the binary to my app I get the following error:

Invoke-RestMethod : {“from”:“seller”,“body”:{“ctntId”:null,“contentStatus”:null,“httpStatus”:“BAD_REQUEST”,“errorCode”:“4128”,“errorMsg”:“You must have an app in service that is already registered on the Seller Portal. The Developer API does not support
new app registration.”},“message”:“Request failed with status code 400”}

I already have an app that is registered and is for sale on the store.
This is my powershell script, can you please advise how I can resolve this?

Import function

Import-Module ./Generate-JWT.psm1

if (-not (Test-Path function:\Generate-JWT)) {

throw "Failed to import function."

}

Write-Host “Function imported successfully, Obtaining access token…”

Use function to generate JSON Web Token

$jwt = Generate-JWT -Algorithm “RS256” -Issuer $ServiceID -ValidforSeconds 1199 -privateKeyXml $privateKeyXml

$authHeader = @{
“Content-Type” = “application/json”
“Authorization” = “Bearer $jwt”
}

$accessTokenResponse = Invoke-RestMethod -Uri $AuthUrl -Method Post -Headers $authHeader

$accessToken = $accessTokenResponse.createdItem.AccessToken

if ($accessTokenResponse.ok -ne “True”) {
throw “Failed to retrieve access token”
}

Write-Host “Access Token Obtained, Retrieving session ID…”

$sessionHeader = @{
“Content-Type” = “Application/json”
“service-account-id” = $ServiceID
“Authorization” = “Bearer $accessToken”
}

$sessionIDResponse = Invoke-RestMethod -Uri $SessionIdUrl -Method Post -Headers $sessionHeader

$sessionID = $sessionIDResponse.sessionID

if ($sessionID -eq $null) {
throw “Failed to obtain session ID”
}

Write-Host “Session ID has been obtained, Uploading File…”

Read file content

$fileContent = [System.IO.File]::ReadAllBytes($ApkPath)
$boundary = [System.Guid]::NewGuid().ToString()
$LF = “rn”

Construct body lines

$uploadBody = @()
$uploadBody += “–$boundary”
$uploadBody += “Content-Disposition: form-data; name="sessionId”"
$uploadBody += “”
$uploadBody += $SessionID
$uploadBody += “–$boundary”
$uploadBody += “Content-Disposition: form-data; name="file”; filename="$(Split-Path -Leaf $ApkPath)“”
$uploadBody += “Content-Type: multipart/form-data”
$uploadBody += “”
$uploadBody += [System.IO.File]::ReadAllText($ApkPath)
$uploadBody += “–$boundary–”

Join body lines

$body = $uploadBody -join $LF

Convert body to bytes

$uploadBodyBytes = [System.Text.Encoding]::UTF8.GetBytes($body)

Set headers

$uploadHeaders = @{
“Content-Type” = “multipart/form-data; boundary=$boundary”
“service-account-id” = $ServiceID
“Authorization” = “Bearer $accessToken”
}

[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }

Send the POST request

$uploadResponse = Invoke-RestMethod -Uri $UploadUrl -Method Post -Headers $uploadHeaders -Body $uploadBodyBytes

if ($uploadResponse.filekey -eq $null) {
throw “Failed to obtain file key”
}

Write-Host “File has successfully uploaded, Attempting to register the app”

$binaryList = @(
@{
fileName = “app-prod-release.apk”
binarySeq = “1”
versionCode = $null
versionName = $null
packageName = “com.entersekt.authapp.parmenion”
nativePlatforms = $null
apiminSdkVersion = “1”
apimaxSdkVersion = $null
iapSdk = “N”
gms = “Y”
filekey = $null
},
@{
gms = “Y”
filekey = $uploadResponse.filekey
}
)

$updateBody = @{
ContentId = $ContentId
AppTitle = $AppTitle
DefaultLanguageCode = $DefaultLanguageCode
paid = “N”
binaryList = $binaryList
} | ConvertTo-Json

$updateHeaders = @{
“Authorization” = “Bearer $accessToken”
“service-account-id” = $ServiceID
“Content-Type” = “application/json”
}

$UpdateResponse = Invoke-RestMethod -Uri $UpdateUrl -Method Post -Headers $updateHeaders -Body $updateBody

Hi @abul.hassan

Would you be able to provide the content ID of your app? 4128 means the app has to be FOR SALE in the store. I also saw you opened a ticket for this same question, feel free to reply to the ticket if you prefer.

Thank you,
Gaby

Hi Gaby

Yes my app is already on sale, my intention are to just add a new binary to the existing app, so i can release a new version of it. Hence my confusion.

Content ID is : 000006592144

the error message i get is : {“from”:“seller”,“body”:{“ctntId”:null,“contentStatus”:null,“httpStatus”:“BAD_REQUEST”,“errorCode”:“4128”,“errorMsg”:“You must have an app in service that is already registered on the Seller Portal. The Developer API does not support
new app registration.”},“message”:“Request failed with status code 400”}

Hi @abul.hassan

Yes, your app current state is FOR SALE, which is needed in order to submit an update with the API. Few things to check:

  1. contentId, defaultLanguageCode, paid, and publicationType must be included in the contentUpdate request. I did not see a publicationType in the snippet that you provided.
  2. When you are adding the new binary, please make sure to include “binarySeq” : “2”.
    Example:
binaryList":[
  {
    "fileName": "App_filename.apk",
    "binarySeq" : "1",
    "versionCode": "3",
    "versionName": "3",
    "packageName": "my.package.name",
    "nativePlatforms": null,
    "apiminSdkVersion": "26",
    "apimaxSdkVersion": null,
    "iapSdk": "N",
    "gms": "Y",
    "filekey": null
  },
  {
    "binarySeq" : "2",
    "gms": "Y",
    "filekey": "<new-binary-filekey>"
  }
]
  1. I recommend you test your API call first using Postman, so you can ensure the API is working correctly with your app and the calls you are making. Once that is confirmed, you can use your script. Even with the current error message that you receive, the contentID and contentStatus are as null, but the error should show the actual value.
1 Like

Hi Gaby

My api calls work just fine, i can get the session id, I can upload my file and I can retrieve a filekey.

I’ve made those changes you suggested, so I’ve included publicationType, and I’ve included the binarySeq:2 in my binary list.

I’m still however receiving the same error.

Could someone look at my script and see where I may be going wrong?

Import function

Import-Module ./Generate-JWT.psm1

if (-not (Test-Path function:\Generate-JWT)) {

throw "Failed to import function."

}

Write-Host “Function imported successfully, Obtaining access token…”

Use function to generate JSON Web Token

$jwt = Generate-JWT -Algorithm “RS256” -Issuer $ServiceID -ValidforSeconds 1199 -privateKeyXml $privateKeyXml

$authHeader = @{
“Content-Type” = “application/json”
“Authorization” = “Bearer $jwt”
“service-account-id” = $ServiceID
}

$accessTokenResponse = Invoke-RestMethod -Uri $AuthUrl -Method Post -Headers $authHeader

$accessToken = $accessTokenResponse.createdItem.AccessToken

if ($accessTokenResponse.ok -ne “True”) {
throw “Failed to retrieve access token”
}

Write-Host “Access Token Obtained, Retrieving session ID…”

$sessionHeader = @{
“Content-Type” = “Application/json”
“service-account-id” = $ServiceID
“Authorization” = “Bearer $accessToken”
}

$sessionIDResponse = Invoke-RestMethod -Uri $SessionIdUrl -Method Post -Headers $sessionHeader

$sessionID = $sessionIDResponse.sessionID

if ($sessionID -eq $null) {
throw “Failed to obtain session ID”
}

Write-Host “Session ID has been obtained, Uploading File…”

Read file content

$fileContent = [System.IO.File]::ReadAllBytes($ApkPath)
$boundary = [System.Guid]::NewGuid().ToString()
$LF = “rn”

Construct body lines

$uploadBody = @()
$uploadBody += “–$boundary”
$uploadBody += “Content-Disposition: form-data; name="sessionId”"
$uploadBody += “”
$uploadBody += $SessionID
$uploadBody += “–$boundary”
$uploadBody += “Content-Disposition: form-data; name="file”; filename="$(Split-Path -Leaf $ApkPath)“”
$uploadBody += “Content-Type: multipart/form-data”
$uploadBody += “”
$uploadBody += [System.IO.File]::ReadAllText($ApkPath)
$uploadBody += “–$boundary–”

Join body lines

$body = $uploadBody -join $LF

Convert body to bytes

$uploadBodyBytes = [System.Text.Encoding]::UTF8.GetBytes($body)

Set headers

$uploadHeaders = @{
“Content-Type” = “multipart/form-data; boundary=$boundary”
“service-account-id” = $ServiceID
“Authorization” = “Bearer $accessToken”
}

[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }

Send the POST request

$uploadResponse = Invoke-RestMethod -Uri $UploadUrl -Method Post -Headers $uploadHeaders -Body $uploadBodyBytes

if ($uploadResponse.filekey -eq $null) {
throw “Failed to obtain file key”
}

Write-Host “File has successfully uploaded, Attempting to register the app”

$binaryList = @(
@{
fileName = “250000569.apk”
binarySeq = “1”
versionCode = “250000569”
versionName = “2.2.0”
packageName = “com.entersekt.authapp.parmenion”
nativePlatforms = “32/64bit”
apiminSdkVersion = “26”
apimaxSdkVersion = $null
iapSdk = “N”
gms = “N”
filekey = $null
},
@{
binarySeq = “2”
gms = “N”
filekey = $uploadResponse.filekey
}
)

$updateBody = @{
ContentId = $ContentId
AppTitle = $AppTitle
DefaultLanguageCode = $DefaultLanguageCode
paid = “N”
publicationType = “01”
binaryList = $binaryList
} | ConvertTo-Json

$updateHeaders = @{
“Authorization” = “Bearer $accessToken”
“service-account-id” = $ServiceID
“Content-Type” = “application/json”
}

$UpdateResponse = Invoke-RestMethod -Uri $UpdateUrl -Method Post -Headers $updateHeaders -Body $updateBody

Hello abul.hassan
This is Jakia from Samsung Developer Program Team.

You are getting ‘4128 Error’ which may occur if the contentId is not properly set. Could you please check again this part?

Have you tested the ‘contentUpdate’ API using CURL or Postman tool? If it works well then please share your CURL request and PowerShell script so that we can test it on our end. If you want, you can share them in our 1-1 support channel as well.

Thank you.