A strange experience and a bug
You can read this post in two ways, either get the full story or scroll down to the solution. My guess is that you found this post because you searched for this error message:
"Definitions/body parameters are not exported since this API references multiple schemas with OpenAPI components as opposed to one. Schemas referenced: [number],[another number]"
And you have spent some time being frustrated because removing the whole API and starting over did not work.
Backstory
This is not only filler, but it also describes how the error occured. Perhaps you recognize yourself in this.
The error from my point of view
I had developed an API for a colleague. The API had a demand for using Definitions of both requests and responses. Honestly, we as API developers, do not use that as much as we should. The colleague supplied me with examples and I got to working using the portal interface to enter definitions.
Things started going south when the portal stopped responding, but after a refresh everything seemed ok. I added all the definitions and then connected them to operations within the API. When I was done I exported the API as OpenAPI v2 (compatability reasons). This is when the error occured.
Looking at the OpenAPI file I could see that all my operations was missing their content
properties, meaning that all definitions I had put in, had been omitted. Scrolling down in the OpenAPI file I found the error above.
Redeploy will not solve it
I deleted the entire API and started over, but the same thing happened again! How could APIm remeber “schemas” from an API that I had deleted? Time to get creative and provide the solution.
The solution – short version
You need to delete the “schemas” and you cannot do that from the portal, you need to access your APIm instance using the RestAPI. Find the offending schema using Api Schema – List By Api and the delete it using Api Schema – Delete
The solution – how to version
I will try to explain every aspect of this operation, to make you feel confident about deleting things from your APIm instance.
Schemas?
Looking back at the error message, it mentions schemas, which might seem strange as APIm never seem to use schemas but rather definitions. The reason is simple: OpenAPI uses schemas and a collection of definition is a schema. APIm usually puts all your defintions into one single schema. The problem was that something went wrong and my API had multiple schemas which messed up the export.
Since the schema property is never surfaced in APIm you cannot delete them. Even if I deleted the entire API, the schema was retained and since you cannot delete it (you can only delete all values/definitions within a schema) I was stuck.
The APIm Rest API?
One of the most confusing things is that there is an API to manage your Azure API management. A manager’s manager if you will. This is really well documented an you can find the basics on how to activate and access it here.
You need to activate the API via the portal and also generate an accesskey in order to execute any APIs. You can use Azure OAuth if you want to but I find it easy to just generate a key and supply it using an Authentication header. I use this in all my calls.
Using the APIm Rest API
This API can be used for all sorts of operations on your APIm instance and I encourage you to explore it further. For now you need to execute two calls: one to find the extra schema(s), and one to delete.
There is one important exception to the documentation, and that is the API base-address. If you want to use the easy, key-based, authentication you need to update the address given in the documentation. Lets look at the first API, Api Schema – ListByApi. The documentation gives the following address:
https://management.azure.com/... etc
You must use the direct API path:
https://serviceinstancename.management.azure-api.net.management.azure-api.net/... etc
If you use the first one, you will get an authentication error.
Find the extra schemas
The schema identifiers are given in the error message, but you need to know which one is the wrong one. Therefore you need to list the schemas for your API. Issue this call:
GET https://serviceinstancename.management.azure-api.net/subscriptions/[subscriptionID]/resourceGroups/[resourcegroupname]/providers/Microsoft.ApiManagement/service/[serviceinstancename]/apis/[ApiID]?api-version=2020-06-01-preview
If you use Postman you can easily handle the path variables by using this:
GET https://{{api-servicename}}.management.azure-api.net/subscriptions/:subscriptionID/resourceGroups/:resourceGroupName/providers/Microsoft.ApiManagement/service/:serviceName/apis/:apiId/schemas?api-version=2020-06-01-preview?api-version=2020-06-01-preview
The API-ID can be found on the Settings-page for the API, but there it is called Name
and is located below Display Name
.
The response contains the schemas, in an array and a count property at the end. If this property is > 1, you have too many schemas.
Find the schema ID
The schema object is defined with four base properties, id
, type
, name
and properties
. Confusingly the ID you are looking for is located in name
. The ID is a string of numbers and sometimes also letters, but it is not a GUID.
As to finding which schema you need to delete? I cannot tell you. It depends on your data model. In my case it was easy.
Deleting the schema
To be extra sure that you will be deleting the correct schema; find the schema first. Issue this call:
GET https://serviceinstancename.management.azure-api.net/subscriptions/[subscriptionID]/resourceGroups/[resourcegroupname]/providers/Microsoft.ApiManagement/service/[serviceinstancename]/apis/[ApiID]/schemas/[SchemaID]?api-version=2020-06-01-preview
The schema ID is the one you got from the call above.
Here is a Postman call for you:
GET https://{{api-servicename-neu}}.management.azure-api.net/subscriptions/:subscriptionId/resourceGroups/:resourceGroup/providers/Microsoft.ApiManagement/service/:serviceName/apis/:apiId/schemas/:schemaId?api-version=2020-06-01-preview
If you get back the schema you want to delete, you simply issue the same call again, just change the VERB from GET to DELETE.
Conclusion
I have NO IDEA how the problem happened to begin with, and I do not like that schemas cannot be deleted from the portal, but is is easy to do using the API Management REST.