diff --git a/apihub-curation/enrich-with-specs/README.md b/apihub-curation/enrich-with-specs/README.md new file mode 100644 index 00000000..a3c56102 --- /dev/null +++ b/apihub-curation/enrich-with-specs/README.md @@ -0,0 +1,66 @@ +*** + +# Enrich API Data with Custom Curation in Apigee API Hub + +![Architecture](enrich-with-spec.png) + +This sample shows how **Apigee API hub** can be configured with custom curation logic to enrich API metadata automatically. It uses Application Integration to define a workflow that fetches OpenAPI specifications from a Cloud Storage bucket and attaches them to the corresponding API versionss registered in API hub from an Apigee instance. + +## Prerequisites + +* A Google Cloud project with billing enabled. +* The following services provisioned in your Google Cloud project: + * Apigee + * Apigee API hub + * Application Integration + * Integration Connectors +* A service account with the following IAM roles: + * `roles/secretmanager.viewer` + * `roles/secretmanager.secretAccessor` + * `roles/storage.admin` +* The Cloud Storage API enabled in your project +* Sample files from the tutorial downloaded to your local machine: + * enrich-with-spec.json + * specs/orders-api.yaml + * specs/products-api.yaml + * specs/users-api.yaml + +## Setup instructions + +### Step 1: Prepare the environment + +To begin, you will prepare your Apigee, Cloud Storage, and Integration Connectors environment. + +1. **Create API Proxies in Apigee**: Register three sample API proxies (`Orders API`, `Products API`, `Users API`) in your Apigee project and ensure they are deployed ([source](https://cloud.devsite.corp.google.com/apigee/docs/apihub/tutorials/enrich-api-data?content_ref=enable%20the%20cloud%20storage%20api#create_api_proxies_in)). These will be automatically discovered by the API hub plugin. +2. **Set up Cloud Storage**: Create a Cloud Storage bucket (e.g., `test_bucket`) ([source](https://cloud.devsite.corp.google.com/apigee/docs/apihub/tutorials/enrich-api-data?content_ref=enable%20the%20cloud%20storage%20api#set_up)). Upload the three sample API specification files (`orders-api.yaml`, `products-api.yaml`, `users-api.yaml`) to this bucket ([source](https://cloud.devsite.corp.google.com/apigee/docs/apihub/tutorials/enrich-api-data?content_ref=enable%20the%20cloud%20storage%20api#upload_api_specification_files)). +3. **Configure Cloud Storage Connection**: In Integration Connectors, create a new Cloud Storage connection named `fetch-specs` ([source](https://cloud.devsite.corp.google.com/apigee/docs/apihub/tutorials/enrich-api-data?content_ref=enable%20the%20cloud%20storage%20api#configure_connection)). Configure it to use the service account you created earlier. This allows the integration to access the bucket. + +### Step 2: Create an integration for custom curation + +This step will create the custom logic in Application Integration that fetches and attaches the specs. + +1. **Create an Integration**: In the Application Integration UI, create a new integration named `test-curation` in the same region as API hub (e.g., `us-central1`) ([source](https://cloud.devsite.corp.google.com/apigee/docs/apihub/tutorials/enrich-api-data?content_ref=enable%20the%20cloud%20storage%20api#step1)). +2. **Upload and Configure**: Upload the `enrich-with-spec-yaml.json` file to create a new version of the integration. Configure the `Fetch spec from GCS` connector task to use the `fetch-specs` connection you created ([source](https://cloud.devsite.corp.google.com/apigee/docs/apihub/tutorials/enrich-api-data?content_ref=enable%20the%20cloud%20storage%20api#configure_connector_task_in_the_integration)). +3. **Test and Publish**: Test the integration with the sample input provided in the tutorial to ensure it correctly constructs the enriched API data payload ([source](https://cloud.devsite.corp.google.com/apigee/docs/apihub/tutorials/enrich-api-data?content_ref=enable%20the%20cloud%20storage%20api#test_and_publish_the_integration)). After a successful test, publish the integration to make it active. + +### Step 3: Set up and verify custom curation in API hub + +Now, you will configure API hub to use the integration you just published. + +1. **Set Up Custom Curation**: In the API hub **Settings > Curations** tab, set up a new curation named `enrich-curation` ([source](https://cloud.devsite.corp.google.com/apigee/docs/apihub/tutorials/enrich-api-data?content_ref=enable%20the%20cloud%20storage%20api#step2)). Associate it with your `test-curation` integration by selecting the correct integration and its API trigger ID. +2. **Edit the Plugin Instance**: Navigate to the **Plugins** tab and edit the default **Apigee X and Hybrid** plugin instance ([source](https://cloud.devsite.corp.google.com/apigee/docs/apihub/tutorials/enrich-api-data?content_ref=enable%20the%20cloud%20storage%20api#step3)). Change its Curation logic from the default to your newly created `enrich-curation` custom curation. +3. **Verify Enriched Data**: Go to the **APIs** page in API hub. After the plugin runs, you will see that the `DemoAPI` proxies are now enriched with their corresponding specification files from the Cloud Storage bucket ([source](https://cloud.devsite.corp.google.com/apigee/docs/apihub/tutorials/enrich-api-data?content_ref=enable%20the%20cloud%20storage%20api#step4)). + +### Step 4: Clean up resources + +To avoid incurring charges, clean up the resources created during this tutorial. You can either delete the entire Google Cloud project or delete the individual resources you created, such as the Cloud Storage bucket ([source](https://cloud.devsite.corp.google.com/apigee/docs/apihub/tutorials/enrich-api-data?content_ref=enable%20the%20cloud%20storage%20api#clean-up)). + +```bash +# To delete the Cloud Storage bucket +gcloud storage buckets delete BUCKET_NAME + +# To delete the project +gcloud projects delete PROJECT_ID +``` + +Congrats, you have successfully used Application Integration to create a custom curation workflow that automatically enriches API data in API hub from an external source. \ No newline at end of file diff --git a/apihub-curation/enrich-with-specs/artifacts/sample_input.txt b/apihub-curation/enrich-with-specs/artifacts/sample_input.txt new file mode 100644 index 00000000..be3c3115 --- /dev/null +++ b/apihub-curation/enrich-with-specs/artifacts/sample_input.txt @@ -0,0 +1,69 @@ +{ + "apiMetadataList": { + "apiMetadata": [ + { + "api": { + "name": "projects/api-hub-demo-5/locations/us-central1/apis/api-hub-demo-5-Products-API", + "displayName": "Products-API", + "fingerprint": "products-api" + }, + "versions": [ + { + "version": { + "name": "projects/api-hub-demo-5/locations/us-central1/apis/api-hub-demo-5-Products-API/versions/version-1", + "displayName": "version-1" + }, + "deployments": [ + { + "deployment": { + "displayName": "Products-API", + "description": "API for managing product inventory. This API allows for the creation, retrieval, update, and deletion of product records.", + "deploymentType": { + "enumValues": { + "values": [ + { + "id": "apigee" + } + ] + }, + "attribute": "projects/api-hub-demo-5/locations/us-central1/attributes/system-deployment-type" + }, + "resourceUri": "organizations/api-hub-demo-5/apis/Products-API/revisions/1/environments/test-env", + "endpoints": [ + "https://googleapis.com/products-api" + ], + "attributes": { + "projects/api-hub-demo-5/locations/us-central1/attributes/plugin-system-apigee-x-and-hybrid-environment": { + "stringValues": { + "values": [ + "test-env" + ] + }, + "attribute": "projects/api-hub-demo-5/locations/us-central1/attributes/plugin-system-apigee-x-and-hybrid-environment" + }, + "projects/api-hub-demo-5/locations/us-central1/attributes/plugin-system-apigee-x-and-hybrid-organization": { + "stringValues": { + "values": [ + "api-hub-demo-5" + ] + }, + "attribute": "projects/api-hub-demo-5/locations/us-central1/attributes/plugin-system-apigee-x-and-hybrid-organization" + } + } + }, + "originalId": "apis/Products-API/revisions/1/environments/test-env", + "originalCreateTime": "2025-07-07T05:23:51.617Z", + "originalUpdateTime": "2025-07-07T05:23:51.617Z" + } + ], + "originalId": "apis/Products-API/revisions/1", + "originalCreateTime": "2025-07-07T05:23:47.982Z", + "originalUpdateTime": "2025-07-07T05:23:47.982Z" + } + ], + "originalId": "apis/Products-API", + "originalUpdateTime": "2025-07-07T05:23:47.982Z" + } + ] + } +} \ No newline at end of file diff --git a/apihub-curation/enrich-with-specs/artifacts/sample_output.txt b/apihub-curation/enrich-with-specs/artifacts/sample_output.txt new file mode 100644 index 00000000..7a39bd53 --- /dev/null +++ b/apihub-curation/enrich-with-specs/artifacts/sample_output.txt @@ -0,0 +1,90 @@ +{ + "apiMetadataList": { + "apiMetadata": [ + { + "api": { + "name": "projects/api-hub-demo-5/locations/us-central1/apis/api-hub-demo-5-Products-API", + "displayName": "Products-API", + "fingerprint": "products-api" + }, + "versions": [ + { + "version": { + "name": "projects/api-hub-demo-5/locations/us-central1/apis/api-hub-demo-5-Products-API/versions/version-1", + "displayName": "version-1" + }, + "deployments": [ + { + "deployment": { + "displayName": "Products-API", + "description": "API for managing product inventory. This API allows for the creation, retrieval, update, and deletion of product records.", + "deploymentType": { + "enumValues": { + "values": [ + { + "id": "apigee" + } + ] + }, + "attribute": "projects/api-hub-demo-5/locations/us-central1/attributes/system-deployment-type" + }, + "resourceUri": "organizations/api-hub-demo-5/apis/Products-API/revisions/1/environments/test-env", + "endpoints": [ + "https://googleapis.com/products-api" + ], + "attributes": { + "projects/api-hub-demo-5/locations/us-central1/attributes/plugin-system-apigee-x-and-hybrid-environment": { + "stringValues": { + "values": [ + "test-env" + ] + }, + "attribute": "projects/api-hub-demo-5/locations/us-central1/attributes/plugin-system-apigee-x-and-hybrid-environment" + }, + "projects/api-hub-demo-5/locations/us-central1/attributes/plugin-system-apigee-x-and-hybrid-organization": { + "stringValues": { + "values": [ + "api-hub-demo-5" + ] + }, + "attribute": "projects/api-hub-demo-5/locations/us-central1/attributes/plugin-system-apigee-x-and-hybrid-organization" + } + } + }, + "originalId": "apis/Products-API/revisions/1/environments/test-env", + "originalCreateTime": "2025-07-07T05:23:51.617Z", + "originalUpdateTime": "2025-07-07T05:23:51.617Z" + } + ], + "originalId": "apis/Products-API/revisions/1", + "originalCreateTime": "2025-07-07T05:23:47.982Z", + "originalUpdateTime": "2025-07-07T05:23:47.982Z", + "specs": [ + { + "originalModifiedTime": "2025-07-07T05:23:47.982Z", + "spec": { + "displayName": "open-api-spec", + "specType": { + "enumValues": { + "values": [ + { + "id": "openapi" + } + ] + } + }, + "contents": { + "mimeType": "application/yaml", + "contents": "b3BlbmFwaTogMy4wLjAKaW5mbzoKICB0aXRsZTogUHJvZHVjdHMgQVBJCiAgdmVyc2lvbjogMS4wLjAKICBkZXNjcmlwdGlvbjogQVBJIGZvciBtYW5hZ2luZyBwcm9kdWN0IGludmVudG9yeS4gVGhpcyBBUEkgYWxsb3dzIGZvciB0aGUgY3JlYXRpb24sIHJldHJpZXZhbCwgdXBkYXRlLCBhbmQgZGVsZXRpb24gb2YgcHJvZHVjdCByZWNvcmRzLgpzZXJ2ZXJzOgogIC0gdXJsOiBodHRwczovL2FwaS5leGFtcGxlLmNvbS9wcm9kdWN0cy92MQogICAgZGVzY3JpcHRpb246IFByb2R1Y3Rpb24gc2VydmVyIGZvciB0aGUgUHJvZHVjdHMgQVBJLgpwYXRoczoKICAvcHJvZHVjdHM6CiAgICBnZXQ6CiAgICAgIHN1bW1hcnk6IEdldCBhbGwgcHJvZHVjdHMKICAgICAgb3BlcmF0aW9uSWQ6IGdldEFsbFByb2R1Y3RzCiAgICAgIHJlc3BvbnNlczoKICAgICAgICAnMjAwJzoKICAgICAgICAgIGRlc2NyaXB0aW9uOiBBIGxpc3Qgb2YgcHJvZHVjdHMgc3VjY2Vzc2Z1bGx5IHJldHJpZXZlZC4KICAgICAgICAgIGNvbnRlbnQ6CiAgICAgICAgICAgIGFwcGxpY2F0aW9uL2pzb246CiAgICAgICAgICAgICAgc2NoZW1hOgogICAgICAgICAgICAgICAgdHlwZTogYXJyYXkKICAgICAgICAgICAgICAgIGl0ZW1zOgogICAgICAgICAgICAgICAgICAkcmVmOiAnIy9jb21wb25lbnRzL3NjaGVtYXMvUHJvZHVjdCcKICAgIHBvc3Q6CiAgICAgIHN1bW1hcnk6IEFkZCBhIG5ldyBwcm9kdWN0CiAgICAgIG9wZXJhdGlvbklkOiBhZGRQcm9kdWN0CiAgICAgIHJlcXVlc3RCb2R5OgogICAgICAgIHJlcXVpcmVkOiB0cnVlCiAgICAgICAgZGVzY3JpcHRpb246IFByb2R1Y3QgZGF0YSB0byBiZSBhZGRlZC4KICAgICAgICBjb250ZW50OgogICAgICAgICAgYXBwbGljYXRpb24vanNvbjoKICAgICAgICAgICAgc2NoZW1hOgogICAgICAgICAgICAgICRyZWY6ICcjL2NvbXBvbmVudHMvc2NoZW1hcy9Qcm9kdWN0SW5wdXQnCiAgICAgIHJlc3BvbnNlczoKICAgICAgICAnMjAxJzoKICAgICAgICAgIGRlc2NyaXB0aW9uOiBQcm9kdWN0IHN1Y2Nlc3NmdWxseSBjcmVhdGVkLgogICAgICAgICAgY29udGVudDoKICAgICAgICAgICAgYXBwbGljYXRpb24vanNvbjoKICAgICAgICAgICAgICBzY2hlbWE6CiAgICAgICAgICAgICAgICAkcmVmOiAnIy9jb21wb25lbnRzL3NjaGVtYXMvUHJvZHVjdCcKICAgICAgICAnNDAwJzoKICAgICAgICAgIGRlc2NyaXB0aW9uOiBJbnZhbGlkIGlucHV0IHByb3ZpZGVkIGZvciBwcm9kdWN0IGNyZWF0aW9uLgogIC9wcm9kdWN0cy97cHJvZHVjdElkfToKICAgIGdldDoKICAgICAgc3VtbWFyeTogR2V0IGEgcHJvZHVjdCBieSBJRAogICAgICBvcGVyYXRpb25JZDogZ2V0UHJvZHVjdEJ5SWQKICAgICAgcGFyYW1ldGVyczoKICAgICAgICAtIG5hbWU6IHByb2R1Y3RJZAogICAgICAgICAgaW46IHBhdGgKICAgICAgICAgIHJlcXVpcmVkOiB0cnVlCiAgICAgICAgICBkZXNjcmlwdGlvbjogVW5pcXVlIGlkZW50aWZpZXIgb2YgdGhlIHByb2R1Y3QgdG8gcmV0cmlldmUuCiAgICAgICAgICBzY2hlbWE6CiAgICAgICAgICAgIHR5cGU6IHN0cmluZwogICAgICAgICAgICBmb3JtYXQ6IHV1aWQKICAgICAgcmVzcG9uc2VzOgogICAgICAgICcyMDAnOgogICAgICAgICAgZGVzY3JpcHRpb246IFByb2R1Y3QgZGV0YWlscyBzdWNjZXNzZnVsbHkgcmV0cmlldmVkLgogICAgICAgICAgY29udGVudDoKICAgICAgICAgICAgYXBwbGljYXRpb24vanNvbjoKICAgICAgICAgICAgICBzY2hlbWE6CiAgICAgICAgICAgICAgICAkcmVmOiAnIy9jb21wb25lbnRzL3NjaGVtYXMvUHJvZHVjdCcKICAgICAgICAnNDA0JzoKICAgICAgICAgIGRlc2NyaXB0aW9uOiBQcm9kdWN0IG5vdCBmb3VuZCB3aXRoIHRoZSBnaXZlbiBJRC4KICAgIHB1dDoKICAgICAgc3VtbWFyeTogVXBkYXRlIGFuIGV4aXN0aW5nIHByb2R1Y3QKICAgICAgb3BlcmF0aW9uSWQ6IHVwZGF0ZVByb2R1Y3QKICAgICAgcGFyYW1ldGVyczoKICAgICAgICAtIG5hbWU6IHByb2R1Y3RJZAogICAgICAgICAgaW46IHBhdGgKICAgICAgICAgIHJlcXVpcmVkOiB0cnVlCiAgICAgICAgICBkZXNjcmlwdGlvbjogVW5pcXVlIGlkZW50aWZpZXIgb2YgdGhlIHByb2R1Y3QgdG8gdXBkYXRlLgogICAgICAgICAgc2NoZW1hOgogICAgICAgICAgICB0eXBlOiBzdHJpbmcKICAgICAgICAgICAgZm9ybWF0OiB1dWlkCiAgICAgIHJlcXVlc3RCb2R5OgogICAgICAgIHJlcXVpcmVkOiB0cnVlCiAgICAgICAgZGVzY3JpcHRpb246IFVwZGF0ZWQgcHJvZHVjdCBkYXRhLgogICAgICAgIGNvbnRlbnQ6CiAgICAgICAgICBhcHBsaWNhdGlvbi9qc29uOgogICAgICAgICAgICBzY2hlbWE6CiAgICAgICAgICAgICAgJHJlZjogJyMvY29tcG9uZW50cy9zY2hlbWFzL1Byb2R1Y3RJbnB1dCcKICAgICAgcmVzcG9uc2VzOgogICAgICAgICcyMDAnOgogICAgICAgICAgZGVzY3JpcHRpb246IFByb2R1Y3Qgc3VjY2Vzc2Z1bGx5IHVwZGF0ZWQuCiAgICAgICAgJzQwMCc6CiAgICAgICAgICBkZXNjcmlwdGlvbjogSW52YWxpZCBpbnB1dCBwcm92aWRlZCBmb3IgcHJvZHVjdCB1cGRhdGUuCiAgICAgICAgJzQwNCc6CiAgICAgICAgICBkZXNjcmlwdGlvbjogUHJvZHVjdCBub3QgZm91bmQgd2l0aCB0aGUgZ2l2ZW4gSUQuCiAgICBkZWxldGU6CiAgICAgIHN1bW1hcnk6IERlbGV0ZSBhIHByb2R1Y3QKICAgICAgb3BlcmF0aW9uSWQ6IGRlbGV0ZVByb2R1Y3QKICAgICAgcGFyYW1ldGVyczoKICAgICAgICAtIG5hbWU6IHByb2R1Y3RJZAogICAgICAgICAgaW46IHBhdGgKICAgICAgICAgIHJlcXVpcmVkOiB0cnVlCiAgICAgICAgICBkZXNjcmlwdGlvbjogVW5pcXVlIGlkZW50aWZpZXIgb2YgdGhlIHByb2R1Y3QgdG8gZGVsZXRlLgogICAgICAgICAgc2NoZW1hOgogICAgICAgICAgICB0eXBlOiBzdHJpbmcKICAgICAgICAgICAgZm9ybWF0OiB1dWlkCiAgICAgIHJlc3BvbnNlczoKICAgICAgICAnMjA0JzoKICAgICAgICAgIGRlc2NyaXB0aW9uOiBQcm9kdWN0IHN1Y2Nlc3NmdWxseSBkZWxldGVkLiBObyBjb250ZW50LgogICAgICAgICc0MDQnOgogICAgICAgICAgZGVzY3JpcHRpb246IFByb2R1Y3Qgbm90IGZvdW5kIHdpdGggdGhlIGdpdmVuIElELgpjb21wb25lbnRzOgogIHNjaGVtYXM6CiAgICBQcm9kdWN0OgogICAgICB0eXBlOiBvYmplY3QKICAgICAgcmVxdWlyZWQ6CiAgICAgICAgLSBpZAogICAgICAgIC0gbmFtZQogICAgICAgIC0gcHJpY2UKICAgICAgcHJvcGVydGllczoKICAgICAgICBpZDoKICAgICAgICAgIHR5cGU6IHN0cmluZwogICAgICAgICAgZm9ybWF0OiB1dWlkCiAgICAgICAgICBkZXNjcmlwdGlvbjogVW5pcXVlIHByb2R1Y3QgaWRlbnRpZmllci4KICAgICAgICBuYW1lOgogICAgICAgICAgdHlwZTogc3RyaW5nCiAgICAgICAgICBkZXNjcmlwdGlvbjogTmFtZSBvZiB0aGUgcHJvZHVjdC4KICAgICAgICBkZXNjcmlwdGlvbjoKICAgICAgICAgIHR5cGU6IHN0cmluZwogICAgICAgICAgbnVsbGFibGU6IHRydWUKICAgICAgICAgIGRlc2NyaXB0aW9uOiBEZXRhaWxlZCBkZXNjcmlwdGlvbiBvZiB0aGUgcHJvZHVjdC4KICAgICAgICBwcmljZToKICAgICAgICAgIHR5cGU6IG51bWJlcgogICAgICAgICAgZm9ybWF0OiBmbG9hdAogICAgICAgICAgZGVzY3JpcHRpb246IFByaWNlIG9mIHRoZSBwcm9kdWN0LgogICAgICAgIHN0b2NrOgogICAgICAgICAgdHlwZTogaW50ZWdlcgogICAgICAgICAgZm9ybWF0OiBpbnQzMgogICAgICAgICAgZGVzY3JpcHRpb246IEN1cnJlbnQgc3RvY2sgcXVhbnRpdHkuCiAgICAgICAgICBkZWZhdWx0OiAwCiAgICBQcm9kdWN0SW5wdXQ6CiAgICAgIHR5cGU6IG9iamVjdAogICAgICByZXF1aXJlZDoKICAgICAgICAtIG5hbWUKICAgICAgICAtIHByaWNlCiAgICAgIHByb3BlcnRpZXM6CiAgICAgICAgbmFtZToKICAgICAgICAgIHR5cGU6IHN0cmluZwogICAgICAgICAgZGVzY3JpcHRpb246IE5hbWUgb2YgdGhlIHByb2R1Y3QuCiAgICAgICAgZGVzY3JpcHRpb246CiAgICAgICAgICB0eXBlOiBzdHJpbmcKICAgICAgICAgIG51bGxhYmxlOiB0cnVlCiAgICAgICAgICBkZXNjcmlwdGlvbjogRGV0YWlsZWQgZGVzY3JpcHRpb24gb2YgdGhlIHByb2R1Y3QuCiAgICAgICAgcHJpY2U6CiAgICAgICAgICB0eXBlOiBudW1iZXIKICAgICAgICAgIGZvcm1hdDogZmxvYXQKICAgICAgICAgIGRlc2NyaXB0aW9uOiBQcmljZSBvZiB0aGUgcHJvZHVjdC4KICAgICAgICBzdG9jazoKICAgICAgICAgIHR5cGU6IGludGVnZXIKICAgICAgICAgIGZvcm1hdDogaW50MzIKICAgICAgICAgIGRlc2NyaXB0aW9uOiBJbml0aWFsIHN0b2NrIHF1YW50aXR5LgogICAgICAgICAgZGVmYXVsdDogMA==" + } + } + } + ] + } + ], + "originalId": "apis/Products-API", + "originalUpdateTime": "2025-07-07T05:23:47.982Z" + } + ] + } +} \ No newline at end of file diff --git a/apihub-curation/enrich-with-specs/enrich-with-spec.json b/apihub-curation/enrich-with-specs/enrich-with-spec.json new file mode 100644 index 00000000..f0366061 --- /dev/null +++ b/apihub-curation/enrich-with-specs/enrich-with-spec.json @@ -0,0 +1,479 @@ +{ + "name": "projects/556128491130/locations/us-central1/integrations/enrich-with-spec/versions/63489a58-a913-44db-afe4-87eb93392c21", + "updateTime": "2025-08-06T08:00:52.068Z", + "createTime": "2025-08-06T07:12:23.797Z", + "lastModifierEmail": "roshnisheikh@google.com", + "triggerConfigs": [{ + "label": "API Trigger", + "startTasks": [{ + "taskId": "4" + }], + "properties": { + "Trigger name": "test-custom-curation_API_1" + }, + "triggerType": "API", + "triggerNumber": "1", + "triggerId": "api_trigger/test-custom-curation_API_1", + "position": { + "x": 140, + "y": 92 + }, + "inputVariables": { + "names": ["apiData"] + }, + "outputVariables": { + "names": ["apiData", "curatedAPIMetadata"] + } + }, { + "label": "Enrich API metadata with spec", + "startTasks": [{ + "taskId": "6" + }], + "properties": { + "Trigger name": "test-curate-1_Private_1" + }, + "triggerType": "PRIVATE_TRIGGER", + "triggerNumber": "2", + "triggerId": "private_trigger/test-curate-1_Private_1", + "position": { + "x": 620, + "y": 92 + } + }], + "taskConfigs": [{ + "task": "JavaScriptTask", + "taskId": "2", + "parameters": { + "javaScriptEngine": { + "key": "javaScriptEngine", + "value": { + "stringValue": "V8" + } + }, + "script": { + "key": "script", + "value": { + "stringValue": "/**\n * Processes and curates API metadata with spec contents.\n * @param {object} event The event object containing API data and spec content.\n */\nfunction executeScript(event) {\n let apiMetadata \u003d event.getParameter(\u0027apiMetadata\u0027);\n let specContent \u003d event.getParameter(\u0027specContent\u0027);\n\n // Initialize curatedAPIMetadata directly from apiMetadata\n const curatedAPIMetadata \u003d { ...apiMetadata\n };\n\n // Construct the \u0027spec\u0027 object efficiently\n const spec \u003d {\n displayName: \"open-api-spec\",\n specType: {\n enumValues: {\n values: [{\n id: \"openapi\"\n }]\n }\n },\n contents: {\n mimeType: \"application/yaml\",\n contents: specContent,\n },\n };\n\n // Create the specMetadata object\n const specMetadata \u003d {\n // Ensure originalUpdateTime exists before assigning, provide a fallback if needed\n originalUpdateTime: curatedAPIMetadata.originalUpdateTime || new Date().toISOString(),\n spec: spec,\n };\n\n // Initialize or update the specs array within the first version\n // This assumes versions[0] always exists. Add checks if it might not.\n if (!curatedAPIMetadata.versions || curatedAPIMetadata.versions.length \u003d\u003d\u003d 0) {\n curatedAPIMetadata.versions \u003d [{\n specs: []\n }];\n } else if (!curatedAPIMetadata.versions[0].specs) {\n curatedAPIMetadata.versions[0].specs \u003d [];\n }\n\n curatedAPIMetadata.versions[0].specs.push(specMetadata);\n\n // Set the modified apiData parameter\n event.setParameter(\u0027curatedAPIMetadata\u0027, curatedAPIMetadata);\n}" + } + } + }, + "taskExecutionStrategy": "WHEN_ALL_SUCCEED", + "displayName": "Enrich API Metadata with spec contents", + "externalTaskType": "ERROR_TASK", + "position": { + "x": 416, + "y": 620 + } + }, { + "task": "GenericConnectorTask", + "taskId": "3", + "parameters": { + "filterClause": { + "key": "filterClause", + "value": { + "stringValue": "" + } + }, + "entityType": { + "key": "entityType", + "value": { + "stringValue": "" + } + }, + "executeQueryRequestConfig": { + "key": "executeQueryRequestConfig" + }, + "authOverrideEnabled": { + "key": "authOverrideEnabled", + "value": { + "booleanValue": false + } + }, + "entityId": { + "key": "entityId", + "value": { + "stringValue": "" + } + }, + "enableDynamicConnection": { + "key": "enableDynamicConnection", + "value": { + "booleanValue": false + } + }, + "serviceName": { + "key": "serviceName", + "value": { + "stringValue": "" + } + }, + "connectorOutputPayload": { + "key": "connectorOutputPayload", + "value": { + "stringValue": "$`Task_3_connectorOutputPayload`$" + } + }, + "timeout": { + "key": "timeout", + "value": { + "intValue": "0" + } + }, + "listEntitiesSortByColumns": { + "key": "listEntitiesSortByColumns", + "value": { + "stringArray": { + } + } + }, + "listEntitiesPageToken": { + "key": "listEntitiesPageToken", + "value": { + "stringValue": "" + } + }, + "connectorInputPayload": { + "key": "connectorInputPayload", + "value": { + "stringValue": "$`Task_3_connectorInputPayload`$" + } + }, + "listEntitiesPageSize": { + "key": "listEntitiesPageSize", + "value": { + "intValue": "0" + } + }, + "host": { + "key": "host", + "value": { + "stringValue": "" + } + }, + "useHttpHeaderForDynamicAuthConfig": { + "key": "useHttpHeaderForDynamicAuthConfig" + }, + "connectionName": { + "key": "connectionName", + "value": { + "stringValue": "$`CONFIG_gcsConnectionName`$" + } + }, + "operation": { + "key": "operation", + "value": { + "stringValue": "EXECUTE_ACTION" + } + }, + "config": { + "key": "config" + }, + "connectionVersion": { + "key": "connectionVersion", + "value": { + "stringValue": "projects/api-hub-demo-5/locations/global/providers/gcp/connectors/gcs/versions/1" + } + }, + "actionName": { + "key": "actionName", + "value": { + "stringValue": "DownloadObject" + } + }, + "dynamicAuthConfig": { + "key": "dynamicAuthConfig", + "value": { + "jsonValue": "null" + } + } + }, + "nextTasks": [{ + "taskId": "7", + "condition": "$`ErrorInfo`.code$ \u003d 0", + "displayName": "Fetched spec successfully" + }, { + "taskId": "9", + "condition": "$`ErrorInfo`.code$ !\u003d 0", + "displayName": "Failed to fetch spec" + }], + "taskExecutionStrategy": "WHEN_ALL_SUCCEED", + "displayName": "Fetch spec from GCS", + "externalTaskType": "ERROR_TASK", + "position": { + "x": 620, + "y": 364 + }, + "conditionalFailurePolicies": { + "defaultFailurePolicy": { + "retryStrategy": "IGNORE" + } + } + }, { + "task": "SubWorkflowForEachLoopV2Task", + "taskId": "4", + "parameters": { + "iterationElementMapping": { + "key": "iterationElementMapping", + "value": { + "stringValue": "apiMetadata" + } + }, + "triggerId": { + "key": "triggerId", + "value": { + "stringValue": "private_trigger/test-curate-1_Private_1" + } + }, + "aggregatorParameterMapping": { + "key": "aggregatorParameterMapping", + "value": { + "jsonValue": "{\n \"@type\": \"type.googleapis.com/enterprise.crm.eventbus.proto.ParameterMap\",\n \"entries\": [{\n \"key\": {\n \"literalValue\": {\n \"stringValue\": \"curatedAPIMetadata\"\n }\n },\n \"value\": {\n \"literalValue\": {\n \"stringValue\": \"curatedAPIMetadataList\"\n }\n }\n }]\n}" + } + }, + "loopMetadata": { + "key": "loopMetadata", + "value": { + "stringArray": { + "stringValues": ["$`Task_4_loopMetadata`$"] + } + } + }, + "disableEucPropagation": { + "key": "disableEucPropagation", + "value": { + "booleanValue": false + } + }, + "listToIterate": { + "key": "listToIterate", + "value": { + "stringValue": "$apiData.apiMetadataList.apiMetadata$" + } + }, + "workflowName": { + "key": "workflowName", + "value": { + "stringValue": "enrich-with-spec" + } + }, + "requestParameterMapping": { + "key": "requestParameterMapping" + }, + "overrideParameterMapping": { + "key": "overrideParameterMapping" + } + }, + "nextTasks": [{ + "taskId": "5" + }], + "taskExecutionStrategy": "WHEN_ALL_SUCCEED", + "displayName": "For Each API", + "externalTaskType": "NORMAL_TASK", + "position": { + "x": 140, + "y": 228 + } + }, { + "task": "FieldMappingTask", + "taskId": "5", + "parameters": { + "FieldMappingConfigTaskParameterKey": { + "key": "FieldMappingConfigTaskParameterKey", + "value": { + "jsonValue": "{\n \"@type\": \"type.googleapis.com/enterprise.crm.eventbus.proto.FieldMappingConfig\",\n \"mappedFields\": [{\n \"inputField\": {\n \"fieldType\": \"JSON_VALUE\",\n \"transformExpression\": {\n \"initialValue\": {\n \"referenceValue\": \"$apiData$\"\n },\n \"transformationFunctions\": [{\n \"functionType\": {\n \"jsonFunction\": {\n \"functionName\": \"SET_PROPERTY\"\n }\n },\n \"parameters\": [{\n \"initialValue\": {\n \"referenceValue\": \"$curatedAPIMetadataList$\"\n }\n }, {\n \"initialValue\": {\n \"literalValue\": {\n \"stringValue\": \"apiMetadataList.apiMetadata\"\n }\n }\n }]\n }]\n }\n },\n \"outputField\": {\n \"referenceKey\": \"$apiData$\",\n \"fieldType\": \"JSON_VALUE\",\n \"cardinality\": \"OPTIONAL\"\n }\n }]\n}" + } + } + }, + "taskExecutionStrategy": "WHEN_ALL_SUCCEED", + "displayName": "Set curated API data", + "externalTaskType": "NORMAL_TASK", + "position": { + "x": 140, + "y": 364 + } + }, { + "task": "FieldMappingTask", + "taskId": "6", + "parameters": { + "FieldMappingConfigTaskParameterKey": { + "key": "FieldMappingConfigTaskParameterKey", + "value": { + "jsonValue": "{\n \"@type\": \"type.googleapis.com/enterprise.crm.eventbus.proto.FieldMappingConfig\",\n \"mappedFields\": [{\n \"inputField\": {\n \"fieldType\": \"JSON_VALUE\",\n \"transformExpression\": {\n \"initialValue\": {\n \"referenceValue\": \"$`Task_3_connectorInputPayload`$\"\n },\n \"transformationFunctions\": [{\n \"functionType\": {\n \"jsonFunction\": {\n \"functionName\": \"SET_PROPERTY\"\n }\n },\n \"parameters\": [{\n \"initialValue\": {\n \"referenceValue\": \"$apiMetadata$\"\n },\n \"transformationFunctions\": [{\n \"functionType\": {\n \"jsonFunction\": {\n \"functionName\": \"GET_PROPERTY\"\n }\n },\n \"parameters\": [{\n \"initialValue\": {\n \"literalValue\": {\n \"stringValue\": \"api\"\n }\n }\n }]\n }, {\n \"functionType\": {\n \"jsonFunction\": {\n \"functionName\": \"GET_PROPERTY\"\n }\n },\n \"parameters\": [{\n \"initialValue\": {\n \"literalValue\": {\n \"stringValue\": \"displayName\"\n }\n }\n }]\n }, {\n \"functionType\": {\n \"jsonFunction\": {\n \"functionName\": \"TO_STRING\"\n }\n }\n }, {\n \"functionType\": {\n \"stringFunction\": {\n \"functionName\": \"CONCAT\"\n }\n },\n \"parameters\": [{\n \"initialValue\": {\n \"literalValue\": {\n \"stringValue\": \".yaml\"\n }\n }\n }]\n }, {\n \"functionType\": {\n \"stringFunction\": {\n \"functionName\": \"TO_LOWERCASE\"\n }\n }\n }]\n }, {\n \"initialValue\": {\n \"literalValue\": {\n \"stringValue\": \"ObjectFilePath\"\n }\n }\n }]\n }, {\n \"functionType\": {\n \"jsonFunction\": {\n \"functionName\": \"SET_PROPERTY\"\n }\n },\n \"parameters\": [{\n \"initialValue\": {\n \"referenceValue\": \"$`CONFIG_bucketName`$\"\n }\n }, {\n \"initialValue\": {\n \"literalValue\": {\n \"stringValue\": \"Bucket\"\n }\n }\n }]\n }]\n }\n },\n \"outputField\": {\n \"referenceKey\": \"$`Task_3_connectorInputPayload`$\",\n \"fieldType\": \"JSON_VALUE\",\n \"cardinality\": \"OPTIONAL\"\n }\n }, {\n \"inputField\": {\n \"fieldType\": \"JSON_VALUE\",\n \"transformExpression\": {\n \"initialValue\": {\n \"referenceValue\": \"$`Task_3_connectorInputPayload`$\"\n },\n \"transformationFunctions\": [{\n \"functionType\": {\n \"jsonFunction\": {\n \"functionName\": \"SET_PROPERTY\"\n }\n },\n \"parameters\": [{\n \"initialValue\": {\n \"referenceValue\": \"$`CONFIG_bucketName`$\"\n }\n }, {\n \"initialValue\": {\n \"referenceValue\": \"$`Task_3_connectorInputPayload`.Bucket$\"\n }\n }]\n }]\n }\n },\n \"outputField\": {\n \"referenceKey\": \"$`Task_3_connectorInputPayload`$\",\n \"fieldType\": \"JSON_VALUE\",\n \"cardinality\": \"OPTIONAL\"\n }\n }]\n}" + } + } + }, + "nextTasks": [{ + "taskId": "3" + }], + "taskExecutionStrategy": "WHEN_ALL_SUCCEED", + "displayName": "Construct GCS connector payload", + "externalTaskType": "ERROR_TASK", + "position": { + "x": 620, + "y": 228 + } + }, { + "task": "FieldMappingTask", + "taskId": "7", + "parameters": { + "FieldMappingConfigTaskParameterKey": { + "key": "FieldMappingConfigTaskParameterKey", + "value": { + "jsonValue": "{\n \"@type\": \"type.googleapis.com/enterprise.crm.eventbus.proto.FieldMappingConfig\",\n \"mappedFields\": [{\n \"inputField\": {\n \"fieldType\": \"JSON_VALUE\",\n \"transformExpression\": {\n \"initialValue\": {\n \"referenceValue\": \"$`Task_3_connectorOutputPayload`$\"\n },\n \"transformationFunctions\": [{\n \"functionType\": {\n \"jsonFunction\": {\n \"functionName\": \"GET_ELEMENT\"\n }\n },\n \"parameters\": [{\n \"initialValue\": {\n \"literalValue\": {\n \"intValue\": \"0\"\n }\n }\n }]\n }]\n }\n },\n \"outputField\": {\n \"referenceKey\": \"$gcsResponseTemp$\",\n \"fieldType\": \"JSON_VALUE\",\n \"cardinality\": \"OPTIONAL\"\n }\n }, {\n \"inputField\": {\n \"fieldType\": \"STRING_VALUE\",\n \"transformExpression\": {\n \"initialValue\": {\n \"referenceValue\": \"$gcsResponseTemp$\"\n },\n \"transformationFunctions\": [{\n \"functionType\": {\n \"jsonFunction\": {\n \"functionName\": \"GET_PROPERTY\"\n }\n },\n \"parameters\": [{\n \"initialValue\": {\n \"literalValue\": {\n \"stringValue\": \"Content\"\n }\n }\n }]\n }, {\n \"functionType\": {\n \"jsonFunction\": {\n \"functionName\": \"TO_STRING\"\n }\n }\n }, {\n \"functionType\": {\n \"stringFunction\": {\n \"functionName\": \"TO_BASE_64\"\n }\n }\n }]\n }\n },\n \"outputField\": {\n \"referenceKey\": \"$specContent$\",\n \"fieldType\": \"STRING_VALUE\",\n \"cardinality\": \"OPTIONAL\"\n }\n }]\n}" + } + } + }, + "nextTasks": [{ + "taskId": "2" + }], + "taskExecutionStrategy": "WHEN_ALL_SUCCEED", + "displayName": "Parse spec contents", + "externalTaskType": "ERROR_TASK", + "position": { + "x": 418, + "y": 493 + } + }, { + "task": "JavaScriptTask", + "taskId": "9", + "parameters": { + "javaScriptEngine": { + "key": "javaScriptEngine", + "value": { + "stringValue": "V8" + } + }, + "script": { + "key": "script", + "value": { + "stringValue": "function executeScript(event) {\n // Retrieve the apiData parameter.\n let apiMetadata \u003d event.getParameter(\u0027apiMetadata\u0027);\n\n\n // Set the curated API metadata parameter same as API data.\n event.setParameter(\u0027curatedAPIMetadata\u0027, apiMetadata);\n}" + } + } + }, + "taskExecutionStrategy": "WHEN_ALL_SUCCEED", + "displayName": "Do not enrich API metadata", + "externalTaskType": "ERROR_TASK", + "position": { + "x": 806, + "y": 499 + } + }], + "integrationParameters": [{ + "key": "`ExecutionMode`", + "dataType": "STRING_VALUE", + "defaultValue": { + "stringValue": "" + }, + "displayName": "`ExecutionMode`", + "isTransient": true + }, { + "key": "`ErrorInfo`", + "dataType": "JSON_VALUE", + "defaultValue": { + "jsonValue": "{\n \"message\": \"\",\n \"code\": 0.0\n}" + }, + "displayName": "`ErrorInfo`", + "isTransient": true, + "jsonSchema": "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"type\": \"object\",\n \"properties\": {\n \"code\": {\n \"type\": \"number\"\n },\n \"message\": {\n \"type\": \"string\"\n }\n }\n}" + }, { + "key": "`ExecutionId`", + "dataType": "STRING_VALUE", + "defaultValue": { + "stringValue": "" + }, + "displayName": "`ExecutionId`", + "isTransient": true + }, { + "key": "`IntegrationName`", + "dataType": "STRING_VALUE", + "defaultValue": { + "stringValue": "" + }, + "displayName": "`IntegrationName`", + "isTransient": true + }, { + "key": "`Region`", + "dataType": "STRING_VALUE", + "defaultValue": { + "stringValue": "" + }, + "displayName": "`Region`", + "isTransient": true + }, { + "key": "`ProjectId`", + "dataType": "STRING_VALUE", + "defaultValue": { + "stringValue": "" + }, + "displayName": "`ProjectId`", + "isTransient": true + }, { + "key": "`Task_4_loopMetadata`", + "dataType": "JSON_VALUE", + "displayName": "`Task_4_loopMetadata`", + "isTransient": true, + "producer": "1_4", + "jsonSchema": "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"type\": \"object\",\n \"properties\": {\n \"sub_integration_execution_ids\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"current_iteration_count\": {\n \"type\": \"number\"\n },\n \"failure_message\": {\n \"type\": \"string\"\n },\n \"failure_location\": {\n \"type\": \"string\"\n },\n \"current_element\": {\n \"type\": [\"string\", \"number\", \"object\", \"array\"]\n }\n }\n}" + }, { + "key": "curatedAPIMetadataList", + "dataType": "JSON_VALUE", + "displayName": "curatedAPIMetadataList" + }, { + "key": "specContent", + "dataType": "STRING_VALUE", + "displayName": "specContent" + }, { + "key": "gcsResponseTemp", + "dataType": "JSON_VALUE", + "displayName": "gcsResponseTemp" + }, { + "key": "apiData", + "dataType": "JSON_VALUE", + "displayName": "apiData", + "inputOutputType": "IN_OUT", + "jsonSchema": "{\n \"description\": \"The API data to be collected.\",\n \"type\": \"object\",\n \"properties\": {\n \"apiMetadataList\": {\n \"description\": \"Optional. The list of API metadata.\",\n \"type\": \"object\",\n \"properties\": {\n \"apiMetadata\": {\n \"description\": \"Required. The list of API metadata.\",\n \"type\": \"array\",\n \"items\": {\n \"description\": \"The API metadata.\",\n \"type\": \"object\",\n \"properties\": {\n \"api\": {\n \"description\": \"Required. The API resource to be pushed to Hub\\u0027s collect layer. The ID of the API resource will be generated by Hub to ensure uniqueness across all APIs across systems.\",\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"description\": \"Identifier. The name of the API resource in the API Hub.\\n\\nFormat:\\n`projects/{project}/locations/{location}/apis/{api}`\",\n \"x-google-identifier\": true,\n \"type\": \"string\"\n },\n \"displayName\": {\n \"description\": \"Required. The display name of the API resource.\",\n \"type\": \"string\"\n },\n \"description\": {\n \"description\": \"Optional. The description of the API resource.\",\n \"type\": \"string\"\n },\n \"documentation\": {\n \"description\": \"Optional. The documentation for the API resource.\",\n \"type\": \"object\",\n \"properties\": {\n \"externalUri\": {\n \"description\": \"Optional. The uri of the externally hosted documentation.\",\n \"type\": \"string\"\n }\n }\n },\n \"owner\": {\n \"description\": \"Optional. Owner details for the API resource.\",\n \"type\": \"object\",\n \"properties\": {\n \"displayName\": {\n \"description\": \"Optional. The name of the owner.\",\n \"type\": \"string\"\n },\n \"email\": {\n \"description\": \"Required. The email of the owner.\",\n \"type\": \"string\"\n }\n },\n \"required\": [\"email\"]\n },\n \"versions\": {\n \"description\": \"Output only. The list of versions present in an API resource.\\nNote: An API resource can be associated with more than 1 version.\\nFormat is\\n`projects/{project}/locations/{location}/apis/{api}/versions/{version}`\",\n \"readOnly\": true,\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"createTime\": {\n \"description\": \"Output only. The time at which the API resource was created.\",\n \"readOnly\": true,\n \"type\": \"string\",\n \"format\": \"date-time\"\n },\n \"updateTime\": {\n \"description\": \"Output only. The time at which the API resource was last updated.\",\n \"readOnly\": true,\n \"type\": \"string\",\n \"format\": \"date-time\"\n },\n \"targetUser\": {\n \"description\": \"Optional. The target users for the API.\\nThis maps to the following system defined attribute:\\n`projects/{project}/locations/{location}/attributes/system-target-user`\\nattribute.\\nThe number of values for this attribute will be based on the\\ncardinality of the attribute. The same can be retrieved via GetAttribute\\nAPI. All values should be from the list of allowed values defined for the\\nattribute.\",\n \"type\": \"object\",\n \"properties\": {\n \"enumValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is enum.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is enum.\",\n \"type\": \"array\",\n \"items\": {\n \"description\": \"The value that can be assigned to the attribute when the data type is\\nenum.\",\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"description\": \"Required. The ID of the allowed value.\\n* If provided, the same will be used. The service will throw an error if\\nthe specified id is already used by another allowed value in the same\\nattribute resource.\\n* If not provided, a system generated id derived from the display name\\nwill be used. In this case, the service will handle conflict resolution\\nby adding a system generated suffix in case of duplicates.\\n\\nThis value should be 4-63 characters, and valid characters\\nare /a-z-/.\",\n \"type\": \"string\"\n },\n \"displayName\": {\n \"description\": \"Required. The display name of the allowed value.\",\n \"type\": \"string\"\n },\n \"description\": {\n \"description\": \"Optional. The detailed description of the allowed value.\",\n \"type\": \"string\"\n },\n \"immutable\": {\n \"description\": \"Optional. When set to true, the allowed value cannot be updated or deleted by the\\nuser. It can only be true for System defined attributes.\",\n \"type\": \"boolean\"\n }\n },\n \"required\": [\"id\", \"displayName\"]\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"stringValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is string.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"jsonValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is JSON.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"uriValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is URL, URI or IP, like gs://bucket-name/object-name.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"attribute\": {\n \"description\": \"Output only. The name of the attribute.\\nFormat: projects/{project}/locations/{location}/attributes/{attribute}\",\n \"readOnly\": true,\n \"type\": \"string\"\n }\n }\n },\n \"team\": {\n \"description\": \"Optional. The team owning the API.\\nThis maps to the following system defined attribute:\\n`projects/{project}/locations/{location}/attributes/system-team`\\nattribute.\\nThe number of values for this attribute will be based on the\\ncardinality of the attribute. The same can be retrieved via GetAttribute\\nAPI. All values should be from the list of allowed values defined for the\\nattribute.\",\n \"type\": \"object\",\n \"properties\": {\n \"enumValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is enum.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is enum.\",\n \"type\": \"array\",\n \"items\": {\n \"description\": \"The value that can be assigned to the attribute when the data type is\\nenum.\",\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"description\": \"Required. The ID of the allowed value.\\n* If provided, the same will be used. The service will throw an error if\\nthe specified id is already used by another allowed value in the same\\nattribute resource.\\n* If not provided, a system generated id derived from the display name\\nwill be used. In this case, the service will handle conflict resolution\\nby adding a system generated suffix in case of duplicates.\\n\\nThis value should be 4-63 characters, and valid characters\\nare /a-z-/.\",\n \"type\": \"string\"\n },\n \"displayName\": {\n \"description\": \"Required. The display name of the allowed value.\",\n \"type\": \"string\"\n },\n \"description\": {\n \"description\": \"Optional. The detailed description of the allowed value.\",\n \"type\": \"string\"\n },\n \"immutable\": {\n \"description\": \"Optional. When set to true, the allowed value cannot be updated or deleted by the\\nuser. It can only be true for System defined attributes.\",\n \"type\": \"boolean\"\n }\n },\n \"required\": [\"id\", \"displayName\"]\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"stringValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is string.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"jsonValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is JSON.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"uriValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is URL, URI or IP, like gs://bucket-name/object-name.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"attribute\": {\n \"description\": \"Output only. The name of the attribute.\\nFormat: projects/{project}/locations/{location}/attributes/{attribute}\",\n \"readOnly\": true,\n \"type\": \"string\"\n }\n }\n },\n \"businessUnit\": {\n \"description\": \"Optional. The business unit owning the API.\\nThis maps to the following system defined attribute:\\n`projects/{project}/locations/{location}/attributes/system-business-unit`\\nattribute.\\nThe number of values for this attribute will be based on the\\ncardinality of the attribute. The same can be retrieved via GetAttribute\\nAPI. All values should be from the list of allowed values defined for the\\nattribute.\",\n \"type\": \"object\",\n \"properties\": {\n \"enumValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is enum.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is enum.\",\n \"type\": \"array\",\n \"items\": {\n \"description\": \"The value that can be assigned to the attribute when the data type is\\nenum.\",\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"description\": \"Required. The ID of the allowed value.\\n* If provided, the same will be used. The service will throw an error if\\nthe specified id is already used by another allowed value in the same\\nattribute resource.\\n* If not provided, a system generated id derived from the display name\\nwill be used. In this case, the service will handle conflict resolution\\nby adding a system generated suffix in case of duplicates.\\n\\nThis value should be 4-63 characters, and valid characters\\nare /a-z-/.\",\n \"type\": \"string\"\n },\n \"displayName\": {\n \"description\": \"Required. The display name of the allowed value.\",\n \"type\": \"string\"\n },\n \"description\": {\n \"description\": \"Optional. The detailed description of the allowed value.\",\n \"type\": \"string\"\n },\n \"immutable\": {\n \"description\": \"Optional. When set to true, the allowed value cannot be updated or deleted by the\\nuser. It can only be true for System defined attributes.\",\n \"type\": \"boolean\"\n }\n },\n \"required\": [\"id\", \"displayName\"]\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"stringValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is string.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"jsonValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is JSON.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"uriValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is URL, URI or IP, like gs://bucket-name/object-name.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"attribute\": {\n \"description\": \"Output only. The name of the attribute.\\nFormat: projects/{project}/locations/{location}/attributes/{attribute}\",\n \"readOnly\": true,\n \"type\": \"string\"\n }\n }\n },\n \"maturityLevel\": {\n \"description\": \"Optional. The maturity level of the API.\\nThis maps to the following system defined attribute:\\n`projects/{project}/locations/{location}/attributes/system-maturity-level`\\nattribute.\\nThe number of values for this attribute will be based on the\\ncardinality of the attribute. The same can be retrieved via GetAttribute\\nAPI. All values should be from the list of allowed values defined for the\\nattribute.\",\n \"type\": \"object\",\n \"properties\": {\n \"enumValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is enum.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is enum.\",\n \"type\": \"array\",\n \"items\": {\n \"description\": \"The value that can be assigned to the attribute when the data type is\\nenum.\",\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"description\": \"Required. The ID of the allowed value.\\n* If provided, the same will be used. The service will throw an error if\\nthe specified id is already used by another allowed value in the same\\nattribute resource.\\n* If not provided, a system generated id derived from the display name\\nwill be used. In this case, the service will handle conflict resolution\\nby adding a system generated suffix in case of duplicates.\\n\\nThis value should be 4-63 characters, and valid characters\\nare /a-z-/.\",\n \"type\": \"string\"\n },\n \"displayName\": {\n \"description\": \"Required. The display name of the allowed value.\",\n \"type\": \"string\"\n },\n \"description\": {\n \"description\": \"Optional. The detailed description of the allowed value.\",\n \"type\": \"string\"\n },\n \"immutable\": {\n \"description\": \"Optional. When set to true, the allowed value cannot be updated or deleted by the\\nuser. It can only be true for System defined attributes.\",\n \"type\": \"boolean\"\n }\n },\n \"required\": [\"id\", \"displayName\"]\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"stringValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is string.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"jsonValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is JSON.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"uriValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is URL, URI or IP, like gs://bucket-name/object-name.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"attribute\": {\n \"description\": \"Output only. The name of the attribute.\\nFormat: projects/{project}/locations/{location}/attributes/{attribute}\",\n \"readOnly\": true,\n \"type\": \"string\"\n }\n }\n },\n \"attributes\": {\n \"description\": \"Optional. The list of user defined attributes associated with the API resource.\\nThe key is the attribute name. It will be of the format:\\n`projects/{project}/locations/{location}/attributes/{attribute}`.\\nThe value is the attribute values associated with the resource.\",\n \"type\": \"object\",\n \"additionalProperties\": {\n \"description\": \"The attribute values associated with resource.\",\n \"type\": \"object\",\n \"properties\": {\n \"enumValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is enum.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is enum.\",\n \"type\": \"array\",\n \"items\": {\n \"description\": \"The value that can be assigned to the attribute when the data type is\\nenum.\",\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"description\": \"Required. The ID of the allowed value.\\n* If provided, the same will be used. The service will throw an error if\\nthe specified id is already used by another allowed value in the same\\nattribute resource.\\n* If not provided, a system generated id derived from the display name\\nwill be used. In this case, the service will handle conflict resolution\\nby adding a system generated suffix in case of duplicates.\\n\\nThis value should be 4-63 characters, and valid characters\\nare /a-z-/.\",\n \"type\": \"string\"\n },\n \"displayName\": {\n \"description\": \"Required. The display name of the allowed value.\",\n \"type\": \"string\"\n },\n \"description\": {\n \"description\": \"Optional. The detailed description of the allowed value.\",\n \"type\": \"string\"\n },\n \"immutable\": {\n \"description\": \"Optional. When set to true, the allowed value cannot be updated or deleted by the\\nuser. It can only be true for System defined attributes.\",\n \"type\": \"boolean\"\n }\n },\n \"required\": [\"id\", \"displayName\"]\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"stringValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is string.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"jsonValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is JSON.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"uriValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is URL, URI or IP, like gs://bucket-name/object-name.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"attribute\": {\n \"description\": \"Output only. The name of the attribute.\\nFormat: projects/{project}/locations/{location}/attributes/{attribute}\",\n \"readOnly\": true,\n \"type\": \"string\"\n }\n }\n }\n },\n \"apiStyle\": {\n \"description\": \"Optional. The style of the API.\\nThis maps to the following system defined attribute:\\n`projects/{project}/locations/{location}/attributes/system-api-style`\\nattribute.\\nThe number of values for this attribute will be based on the\\ncardinality of the attribute. The same can be retrieved via GetAttribute\\nAPI. All values should be from the list of allowed values defined for the\\nattribute.\",\n \"type\": \"object\",\n \"properties\": {\n \"enumValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is enum.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is enum.\",\n \"type\": \"array\",\n \"items\": {\n \"description\": \"The value that can be assigned to the attribute when the data type is\\nenum.\",\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"description\": \"Required. The ID of the allowed value.\\n* If provided, the same will be used. The service will throw an error if\\nthe specified id is already used by another allowed value in the same\\nattribute resource.\\n* If not provided, a system generated id derived from the display name\\nwill be used. In this case, the service will handle conflict resolution\\nby adding a system generated suffix in case of duplicates.\\n\\nThis value should be 4-63 characters, and valid characters\\nare /a-z-/.\",\n \"type\": \"string\"\n },\n \"displayName\": {\n \"description\": \"Required. The display name of the allowed value.\",\n \"type\": \"string\"\n },\n \"description\": {\n \"description\": \"Optional. The detailed description of the allowed value.\",\n \"type\": \"string\"\n },\n \"immutable\": {\n \"description\": \"Optional. When set to true, the allowed value cannot be updated or deleted by the\\nuser. It can only be true for System defined attributes.\",\n \"type\": \"boolean\"\n }\n },\n \"required\": [\"id\", \"displayName\"]\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"stringValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is string.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"jsonValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is JSON.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"uriValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is URL, URI or IP, like gs://bucket-name/object-name.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"attribute\": {\n \"description\": \"Output only. The name of the attribute.\\nFormat: projects/{project}/locations/{location}/attributes/{attribute}\",\n \"readOnly\": true,\n \"type\": \"string\"\n }\n }\n },\n \"selectedVersion\": {\n \"description\": \"Optional. The selected version for an API resource.\\nThis can be used when special handling is needed on client side for\\nparticular version of the API. Format is\\n`projects/{project}/locations/{location}/apis/{api}/versions/{version}`\",\n \"type\": \"string\"\n },\n \"apiRequirements\": {\n \"description\": \"Optional. The api requirement doc associated with the API resource. Carinality is 1\\nfor this attribute.\",\n \"type\": \"object\",\n \"properties\": {\n \"enumValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is enum.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is enum.\",\n \"type\": \"array\",\n \"items\": {\n \"description\": \"The value that can be assigned to the attribute when the data type is\\nenum.\",\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"description\": \"Required. The ID of the allowed value.\\n* If provided, the same will be used. The service will throw an error if\\nthe specified id is already used by another allowed value in the same\\nattribute resource.\\n* If not provided, a system generated id derived from the display name\\nwill be used. In this case, the service will handle conflict resolution\\nby adding a system generated suffix in case of duplicates.\\n\\nThis value should be 4-63 characters, and valid characters\\nare /a-z-/.\",\n \"type\": \"string\"\n },\n \"displayName\": {\n \"description\": \"Required. The display name of the allowed value.\",\n \"type\": \"string\"\n },\n \"description\": {\n \"description\": \"Optional. The detailed description of the allowed value.\",\n \"type\": \"string\"\n },\n \"immutable\": {\n \"description\": \"Optional. When set to true, the allowed value cannot be updated or deleted by the\\nuser. It can only be true for System defined attributes.\",\n \"type\": \"boolean\"\n }\n },\n \"required\": [\"id\", \"displayName\"]\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"stringValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is string.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"jsonValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is JSON.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"uriValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is URL, URI or IP, like gs://bucket-name/object-name.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"attribute\": {\n \"description\": \"Output only. The name of the attribute.\\nFormat: projects/{project}/locations/{location}/attributes/{attribute}\",\n \"readOnly\": true,\n \"type\": \"string\"\n }\n }\n },\n \"fingerprint\": {\n \"description\": \"Optional. Fingerprint of the API resource.\",\n \"type\": \"string\"\n },\n \"sourceMetadata\": {\n \"description\": \"Output only. The list of sources and metadata from the sources of the API resource.\",\n \"readOnly\": true,\n \"type\": \"array\",\n \"items\": {\n \"description\": \"SourceMetadata represents the metadata for a resource at the source.\",\n \"type\": \"object\",\n \"properties\": {\n \"pluginInstanceActionSource\": {\n \"description\": \"Output only. The source of the resource is a plugin instance action.\",\n \"readOnly\": true,\n \"type\": \"object\",\n \"properties\": {\n \"pluginInstance\": {\n \"description\": \"Output only. The resource name of the source plugin instance.\\nFormat is\\n`projects/{project}/locations/{location}/plugins/{plugin}/instances/{instance}`\",\n \"readOnly\": true,\n \"type\": \"string\"\n },\n \"actionId\": {\n \"description\": \"Output only. The id of the plugin instance action.\",\n \"readOnly\": true,\n \"type\": \"string\"\n }\n }\n },\n \"sourceType\": {\n \"description\": \"Output only. The type of the source.\",\n \"readOnly\": true,\n \"type\": \"string\",\n \"x-google-enum-descriptions\": [\"Source type not specified.\", \"Source type plugin.\"],\n \"enum\": [\"SOURCE_TYPE_UNSPECIFIED\", \"PLUGIN\"]\n },\n \"originalResourceId\": {\n \"description\": \"Output only. The unique identifier of the resource at the source.\",\n \"readOnly\": true,\n \"type\": \"string\"\n },\n \"originalResourceCreateTime\": {\n \"description\": \"Output only. The time at which the resource was created at the source.\",\n \"readOnly\": true,\n \"type\": \"string\",\n \"format\": \"date-time\"\n },\n \"originalResourceUpdateTime\": {\n \"description\": \"Output only. The time at which the resource was last updated at the source.\",\n \"readOnly\": true,\n \"type\": \"string\",\n \"format\": \"date-time\"\n }\n }\n }\n },\n \"apiFunctionalRequirements\": {\n \"description\": \"Optional. The api functional requirements associated with the API resource.\\nCarinality is 1 for this attribute.\",\n \"type\": \"object\",\n \"properties\": {\n \"enumValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is enum.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is enum.\",\n \"type\": \"array\",\n \"items\": {\n \"description\": \"The value that can be assigned to the attribute when the data type is\\nenum.\",\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"description\": \"Required. The ID of the allowed value.\\n* If provided, the same will be used. The service will throw an error if\\nthe specified id is already used by another allowed value in the same\\nattribute resource.\\n* If not provided, a system generated id derived from the display name\\nwill be used. In this case, the service will handle conflict resolution\\nby adding a system generated suffix in case of duplicates.\\n\\nThis value should be 4-63 characters, and valid characters\\nare /a-z-/.\",\n \"type\": \"string\"\n },\n \"displayName\": {\n \"description\": \"Required. The display name of the allowed value.\",\n \"type\": \"string\"\n },\n \"description\": {\n \"description\": \"Optional. The detailed description of the allowed value.\",\n \"type\": \"string\"\n },\n \"immutable\": {\n \"description\": \"Optional. When set to true, the allowed value cannot be updated or deleted by the\\nuser. It can only be true for System defined attributes.\",\n \"type\": \"boolean\"\n }\n },\n \"required\": [\"id\", \"displayName\"]\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"stringValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is string.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"jsonValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is JSON.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"uriValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is URL, URI or IP, like gs://bucket-name/object-name.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"attribute\": {\n \"description\": \"Output only. The name of the attribute.\\nFormat: projects/{project}/locations/{location}/attributes/{attribute}\",\n \"readOnly\": true,\n \"type\": \"string\"\n }\n }\n },\n \"apiTechnicalRequirements\": {\n \"description\": \"Optional. The api technical requirements associated with the API resource. Carinality\\nis 1 for this attribute.\",\n \"type\": \"object\",\n \"properties\": {\n \"enumValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is enum.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is enum.\",\n \"type\": \"array\",\n \"items\": {\n \"description\": \"The value that can be assigned to the attribute when the data type is\\nenum.\",\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"description\": \"Required. The ID of the allowed value.\\n* If provided, the same will be used. The service will throw an error if\\nthe specified id is already used by another allowed value in the same\\nattribute resource.\\n* If not provided, a system generated id derived from the display name\\nwill be used. In this case, the service will handle conflict resolution\\nby adding a system generated suffix in case of duplicates.\\n\\nThis value should be 4-63 characters, and valid characters\\nare /a-z-/.\",\n \"type\": \"string\"\n },\n \"displayName\": {\n \"description\": \"Required. The display name of the allowed value.\",\n \"type\": \"string\"\n },\n \"description\": {\n \"description\": \"Optional. The detailed description of the allowed value.\",\n \"type\": \"string\"\n },\n \"immutable\": {\n \"description\": \"Optional. When set to true, the allowed value cannot be updated or deleted by the\\nuser. It can only be true for System defined attributes.\",\n \"type\": \"boolean\"\n }\n },\n \"required\": [\"id\", \"displayName\"]\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"stringValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is string.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"jsonValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is JSON.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"uriValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is URL, URI or IP, like gs://bucket-name/object-name.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"attribute\": {\n \"description\": \"Output only. The name of the attribute.\\nFormat: projects/{project}/locations/{location}/attributes/{attribute}\",\n \"readOnly\": true,\n \"type\": \"string\"\n }\n }\n }\n },\n \"required\": [\"displayName\"]\n },\n \"versions\": {\n \"description\": \"Optional. The list of versions present in an API resource.\",\n \"type\": \"array\",\n \"items\": {\n \"description\": \"The metadata associated with a version of the API resource.\",\n \"type\": \"object\",\n \"properties\": {\n \"version\": {\n \"description\": \"Required. Represents a version of the API resource in API hub. The ID of the version\\nwill be generated by Hub.\",\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"description\": \"Identifier. The name of the version.\\n\\nFormat:\\n`projects/{project}/locations/{location}/apis/{api}/versions/{version}`\",\n \"x-google-identifier\": true,\n \"type\": \"string\"\n },\n \"displayName\": {\n \"description\": \"Required. The display name of the version.\",\n \"type\": \"string\"\n },\n \"description\": {\n \"description\": \"Optional. The description of the version.\",\n \"type\": \"string\"\n },\n \"documentation\": {\n \"description\": \"Optional. The documentation of the version.\",\n \"type\": \"object\",\n \"properties\": {\n \"externalUri\": {\n \"description\": \"Optional. The uri of the externally hosted documentation.\",\n \"type\": \"string\"\n }\n }\n },\n \"specs\": {\n \"description\": \"Output only. The specs associated with this version.\\nNote that an API version can be associated with multiple specs.\\nFormat is\\n`projects/{project}/locations/{location}/apis/{api}/versions/{version}/specs/{spec}`\",\n \"readOnly\": true,\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"apiOperations\": {\n \"description\": \"Output only. The operations contained in the API version.\\nThese operations will be added to the version when a new spec is\\nadded or when an existing spec is updated. Format is\\n`projects/{project}/locations/{location}/apis/{api}/versions/{version}/operations/{operation}`\",\n \"readOnly\": true,\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"definitions\": {\n \"description\": \"Output only. The definitions contained in the API version.\\nThese definitions will be added to the version when a new spec is\\nadded or when an existing spec is updated. Format is\\n`projects/{project}/locations/{location}/apis/{api}/versions/{version}/definitions/{definition}`\",\n \"readOnly\": true,\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"deployments\": {\n \"description\": \"Optional. The deployments linked to this API version.\\nNote: A particular API version could be deployed to multiple deployments\\n(for dev deployment, UAT deployment, etc)\\nFormat is\\n`projects/{project}/locations/{location}/deployments/{deployment}`\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"createTime\": {\n \"description\": \"Output only. The time at which the version was created.\",\n \"readOnly\": true,\n \"type\": \"string\",\n \"format\": \"date-time\"\n },\n \"updateTime\": {\n \"description\": \"Output only. The time at which the version was last updated.\",\n \"readOnly\": true,\n \"type\": \"string\",\n \"format\": \"date-time\"\n },\n \"lifecycle\": {\n \"description\": \"Optional. The lifecycle of the API version.\\nThis maps to the following system defined attribute:\\n`projects/{project}/locations/{location}/attributes/system-lifecycle`\\nattribute.\\nThe number of values for this attribute will be based on the\\ncardinality of the attribute. The same can be retrieved via GetAttribute\\nAPI. All values should be from the list of allowed values defined for the\\nattribute.\",\n \"type\": \"object\",\n \"properties\": {\n \"enumValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is enum.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is enum.\",\n \"type\": \"array\",\n \"items\": {\n \"description\": \"The value that can be assigned to the attribute when the data type is\\nenum.\",\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"description\": \"Required. The ID of the allowed value.\\n* If provided, the same will be used. The service will throw an error if\\nthe specified id is already used by another allowed value in the same\\nattribute resource.\\n* If not provided, a system generated id derived from the display name\\nwill be used. In this case, the service will handle conflict resolution\\nby adding a system generated suffix in case of duplicates.\\n\\nThis value should be 4-63 characters, and valid characters\\nare /a-z-/.\",\n \"type\": \"string\"\n },\n \"displayName\": {\n \"description\": \"Required. The display name of the allowed value.\",\n \"type\": \"string\"\n },\n \"description\": {\n \"description\": \"Optional. The detailed description of the allowed value.\",\n \"type\": \"string\"\n },\n \"immutable\": {\n \"description\": \"Optional. When set to true, the allowed value cannot be updated or deleted by the\\nuser. It can only be true for System defined attributes.\",\n \"type\": \"boolean\"\n }\n },\n \"required\": [\"id\", \"displayName\"]\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"stringValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is string.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"jsonValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is JSON.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"uriValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is URL, URI or IP, like gs://bucket-name/object-name.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"attribute\": {\n \"description\": \"Output only. The name of the attribute.\\nFormat: projects/{project}/locations/{location}/attributes/{attribute}\",\n \"readOnly\": true,\n \"type\": \"string\"\n }\n }\n },\n \"compliance\": {\n \"description\": \"Optional. The compliance associated with the API version.\\nThis maps to the following system defined attribute:\\n`projects/{project}/locations/{location}/attributes/system-compliance`\\nattribute.\\nThe number of values for this attribute will be based on the\\ncardinality of the attribute. The same can be retrieved via GetAttribute\\nAPI. All values should be from the list of allowed values defined for the\\nattribute.\",\n \"type\": \"object\",\n \"properties\": {\n \"enumValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is enum.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is enum.\",\n \"type\": \"array\",\n \"items\": {\n \"description\": \"The value that can be assigned to the attribute when the data type is\\nenum.\",\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"description\": \"Required. The ID of the allowed value.\\n* If provided, the same will be used. The service will throw an error if\\nthe specified id is already used by another allowed value in the same\\nattribute resource.\\n* If not provided, a system generated id derived from the display name\\nwill be used. In this case, the service will handle conflict resolution\\nby adding a system generated suffix in case of duplicates.\\n\\nThis value should be 4-63 characters, and valid characters\\nare /a-z-/.\",\n \"type\": \"string\"\n },\n \"displayName\": {\n \"description\": \"Required. The display name of the allowed value.\",\n \"type\": \"string\"\n },\n \"description\": {\n \"description\": \"Optional. The detailed description of the allowed value.\",\n \"type\": \"string\"\n },\n \"immutable\": {\n \"description\": \"Optional. When set to true, the allowed value cannot be updated or deleted by the\\nuser. It can only be true for System defined attributes.\",\n \"type\": \"boolean\"\n }\n },\n \"required\": [\"id\", \"displayName\"]\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"stringValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is string.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"jsonValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is JSON.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"uriValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is URL, URI or IP, like gs://bucket-name/object-name.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"attribute\": {\n \"description\": \"Output only. The name of the attribute.\\nFormat: projects/{project}/locations/{location}/attributes/{attribute}\",\n \"readOnly\": true,\n \"type\": \"string\"\n }\n }\n },\n \"accreditation\": {\n \"description\": \"Optional. The accreditations associated with the API version.\\nThis maps to the following system defined attribute:\\n`projects/{project}/locations/{location}/attributes/system-accreditation`\\nattribute.\\nThe number of values for this attribute will be based on the\\ncardinality of the attribute. The same can be retrieved via GetAttribute\\nAPI. All values should be from the list of allowed values defined for the\\nattribute.\",\n \"type\": \"object\",\n \"properties\": {\n \"enumValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is enum.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is enum.\",\n \"type\": \"array\",\n \"items\": {\n \"description\": \"The value that can be assigned to the attribute when the data type is\\nenum.\",\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"description\": \"Required. The ID of the allowed value.\\n* If provided, the same will be used. The service will throw an error if\\nthe specified id is already used by another allowed value in the same\\nattribute resource.\\n* If not provided, a system generated id derived from the display name\\nwill be used. In this case, the service will handle conflict resolution\\nby adding a system generated suffix in case of duplicates.\\n\\nThis value should be 4-63 characters, and valid characters\\nare /a-z-/.\",\n \"type\": \"string\"\n },\n \"displayName\": {\n \"description\": \"Required. The display name of the allowed value.\",\n \"type\": \"string\"\n },\n \"description\": {\n \"description\": \"Optional. The detailed description of the allowed value.\",\n \"type\": \"string\"\n },\n \"immutable\": {\n \"description\": \"Optional. When set to true, the allowed value cannot be updated or deleted by the\\nuser. It can only be true for System defined attributes.\",\n \"type\": \"boolean\"\n }\n },\n \"required\": [\"id\", \"displayName\"]\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"stringValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is string.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"jsonValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is JSON.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"uriValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is URL, URI or IP, like gs://bucket-name/object-name.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"attribute\": {\n \"description\": \"Output only. The name of the attribute.\\nFormat: projects/{project}/locations/{location}/attributes/{attribute}\",\n \"readOnly\": true,\n \"type\": \"string\"\n }\n }\n },\n \"attributes\": {\n \"description\": \"Optional. The list of user defined attributes associated with the Version resource.\\nThe key is the attribute name. It will be of the format:\\n`projects/{project}/locations/{location}/attributes/{attribute}`.\\nThe value is the attribute values associated with the resource.\",\n \"type\": \"object\",\n \"additionalProperties\": {\n \"description\": \"The attribute values associated with resource.\",\n \"type\": \"object\",\n \"properties\": {\n \"enumValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is enum.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is enum.\",\n \"type\": \"array\",\n \"items\": {\n \"description\": \"The value that can be assigned to the attribute when the data type is\\nenum.\",\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"description\": \"Required. The ID of the allowed value.\\n* If provided, the same will be used. The service will throw an error if\\nthe specified id is already used by another allowed value in the same\\nattribute resource.\\n* If not provided, a system generated id derived from the display name\\nwill be used. In this case, the service will handle conflict resolution\\nby adding a system generated suffix in case of duplicates.\\n\\nThis value should be 4-63 characters, and valid characters\\nare /a-z-/.\",\n \"type\": \"string\"\n },\n \"displayName\": {\n \"description\": \"Required. The display name of the allowed value.\",\n \"type\": \"string\"\n },\n \"description\": {\n \"description\": \"Optional. The detailed description of the allowed value.\",\n \"type\": \"string\"\n },\n \"immutable\": {\n \"description\": \"Optional. When set to true, the allowed value cannot be updated or deleted by the\\nuser. It can only be true for System defined attributes.\",\n \"type\": \"boolean\"\n }\n },\n \"required\": [\"id\", \"displayName\"]\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"stringValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is string.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"jsonValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is JSON.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"uriValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is URL, URI or IP, like gs://bucket-name/object-name.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"attribute\": {\n \"description\": \"Output only. The name of the attribute.\\nFormat: projects/{project}/locations/{location}/attributes/{attribute}\",\n \"readOnly\": true,\n \"type\": \"string\"\n }\n }\n }\n },\n \"selectedDeployment\": {\n \"description\": \"Optional. The selected deployment for a Version resource.\\nThis can be used when special handling is needed on client side for a\\nparticular deployment linked to the version.\\nFormat is\\n`projects/{project}/locations/{location}/deployments/{deployment}`\",\n \"type\": \"string\"\n },\n \"sourceMetadata\": {\n \"description\": \"Output only. The list of sources and metadata from the sources of the version.\",\n \"readOnly\": true,\n \"type\": \"array\",\n \"items\": {\n \"description\": \"SourceMetadata represents the metadata for a resource at the source.\",\n \"type\": \"object\",\n \"properties\": {\n \"pluginInstanceActionSource\": {\n \"description\": \"Output only. The source of the resource is a plugin instance action.\",\n \"readOnly\": true,\n \"type\": \"object\",\n \"properties\": {\n \"pluginInstance\": {\n \"description\": \"Output only. The resource name of the source plugin instance.\\nFormat is\\n`projects/{project}/locations/{location}/plugins/{plugin}/instances/{instance}`\",\n \"readOnly\": true,\n \"type\": \"string\"\n },\n \"actionId\": {\n \"description\": \"Output only. The id of the plugin instance action.\",\n \"readOnly\": true,\n \"type\": \"string\"\n }\n }\n },\n \"sourceType\": {\n \"description\": \"Output only. The type of the source.\",\n \"readOnly\": true,\n \"type\": \"string\",\n \"x-google-enum-descriptions\": [\"Source type not specified.\", \"Source type plugin.\"],\n \"enum\": [\"SOURCE_TYPE_UNSPECIFIED\", \"PLUGIN\"]\n },\n \"originalResourceId\": {\n \"description\": \"Output only. The unique identifier of the resource at the source.\",\n \"readOnly\": true,\n \"type\": \"string\"\n },\n \"originalResourceCreateTime\": {\n \"description\": \"Output only. The time at which the resource was created at the source.\",\n \"readOnly\": true,\n \"type\": \"string\",\n \"format\": \"date-time\"\n },\n \"originalResourceUpdateTime\": {\n \"description\": \"Output only. The time at which the resource was last updated at the source.\",\n \"readOnly\": true,\n \"type\": \"string\",\n \"format\": \"date-time\"\n }\n }\n }\n }\n },\n \"required\": [\"displayName\"]\n },\n \"specs\": {\n \"description\": \"Optional. The specs associated with this version.\\nNote that an API version can be associated with multiple specs.\",\n \"type\": \"array\",\n \"items\": {\n \"description\": \"The metadata associated with a spec of the API version.\",\n \"type\": \"object\",\n \"properties\": {\n \"spec\": {\n \"description\": \"Required. The spec resource to be pushed to Hub\\u0027s collect layer. The ID of the spec\\nwill be generated by Hub.\",\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"description\": \"Identifier. The name of the spec.\\n\\nFormat:\\n`projects/{project}/locations/{location}/apis/{api}/versions/{version}/specs/{spec}`\",\n \"x-google-identifier\": true,\n \"type\": \"string\"\n },\n \"displayName\": {\n \"description\": \"Required. The display name of the spec.\\nThis can contain the file name of the spec.\",\n \"type\": \"string\"\n },\n \"specType\": {\n \"description\": \"Required. The type of spec.\\nThe value should be one of the allowed values defined for\\n`projects/{project}/locations/{location}/attributes/system-spec-type`\\nattribute.\\nThe number of values for this attribute will be based on the\\ncardinality of the attribute. The same can be retrieved via GetAttribute\\nAPI.\\n\\nNote, this field is mandatory if content is provided.\",\n \"type\": \"object\",\n \"properties\": {\n \"enumValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is enum.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is enum.\",\n \"type\": \"array\",\n \"items\": {\n \"description\": \"The value that can be assigned to the attribute when the data type is\\nenum.\",\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"description\": \"Required. The ID of the allowed value.\\n* If provided, the same will be used. The service will throw an error if\\nthe specified id is already used by another allowed value in the same\\nattribute resource.\\n* If not provided, a system generated id derived from the display name\\nwill be used. In this case, the service will handle conflict resolution\\nby adding a system generated suffix in case of duplicates.\\n\\nThis value should be 4-63 characters, and valid characters\\nare /a-z-/.\",\n \"type\": \"string\"\n },\n \"displayName\": {\n \"description\": \"Required. The display name of the allowed value.\",\n \"type\": \"string\"\n },\n \"description\": {\n \"description\": \"Optional. The detailed description of the allowed value.\",\n \"type\": \"string\"\n },\n \"immutable\": {\n \"description\": \"Optional. When set to true, the allowed value cannot be updated or deleted by the\\nuser. It can only be true for System defined attributes.\",\n \"type\": \"boolean\"\n }\n },\n \"required\": [\"id\", \"displayName\"]\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"stringValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is string.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"jsonValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is JSON.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"uriValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is URL, URI or IP, like gs://bucket-name/object-name.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"attribute\": {\n \"description\": \"Output only. The name of the attribute.\\nFormat: projects/{project}/locations/{location}/attributes/{attribute}\",\n \"readOnly\": true,\n \"type\": \"string\"\n }\n }\n },\n \"contents\": {\n \"description\": \"Optional. Input only. The contents of the uploaded spec.\",\n \"writeOnly\": true,\n \"type\": \"object\",\n \"properties\": {\n \"contents\": {\n \"description\": \"Required. The contents of the spec.\",\n \"type\": \"string\",\n \"format\": \"byte\"\n },\n \"mimeType\": {\n \"description\": \"Required. The mime type of the content for example application/json,\\napplication/yaml, application/wsdl etc.\",\n \"type\": \"string\"\n }\n },\n \"required\": [\"contents\", \"mimeType\"]\n },\n \"details\": {\n \"description\": \"Output only. Details parsed from the spec.\",\n \"readOnly\": true,\n \"type\": \"object\",\n \"properties\": {\n \"openApiSpecDetails\": {\n \"description\": \"Output only. Additional details apart from `OperationDetails` parsed from an OpenAPI\\nspec. The OperationDetails parsed from the spec can be obtained by using\\nListAPIOperations method.\",\n \"readOnly\": true,\n \"type\": \"object\",\n \"properties\": {\n \"format\": {\n \"description\": \"Output only. The format of the spec.\",\n \"readOnly\": true,\n \"type\": \"string\",\n \"x-google-enum-descriptions\": [\"SpecFile type unspecified.\", \"OpenAPI Spec v2.0.\", \"OpenAPI Spec v3.0.\", \"OpenAPI Spec v3.1.\"],\n \"enum\": [\"FORMAT_UNSPECIFIED\", \"OPEN_API_SPEC_2_0\", \"OPEN_API_SPEC_3_0\", \"OPEN_API_SPEC_3_1\"]\n },\n \"version\": {\n \"description\": \"Output only. The version in the spec.\\nThis maps to `info.version` in OpenAPI spec.\",\n \"readOnly\": true,\n \"type\": \"string\"\n },\n \"owner\": {\n \"description\": \"Output only. Owner details for the spec.\\nThis maps to `info.contact` in OpenAPI spec.\",\n \"readOnly\": true,\n \"type\": \"object\",\n \"properties\": {\n \"displayName\": {\n \"description\": \"Optional. The name of the owner.\",\n \"type\": \"string\"\n },\n \"email\": {\n \"description\": \"Required. The email of the owner.\",\n \"type\": \"string\"\n }\n },\n \"required\": [\"email\"]\n }\n }\n },\n \"description\": {\n \"description\": \"Output only. The description of the spec.\",\n \"readOnly\": true,\n \"type\": \"string\"\n }\n }\n },\n \"sourceUri\": {\n \"description\": \"Optional. The URI of the spec source in case file is uploaded\\nfrom an external version control system.\",\n \"type\": \"string\"\n },\n \"createTime\": {\n \"description\": \"Output only. The time at which the spec was created.\",\n \"readOnly\": true,\n \"type\": \"string\",\n \"format\": \"date-time\"\n },\n \"updateTime\": {\n \"description\": \"Output only. The time at which the spec was last updated.\",\n \"readOnly\": true,\n \"type\": \"string\",\n \"format\": \"date-time\"\n },\n \"lintResponse\": {\n \"description\": \"Optional. The lint response for the spec.\",\n \"type\": \"object\",\n \"properties\": {\n \"issues\": {\n \"description\": \"Optional. Array of issues found in the analyzed document.\",\n \"type\": \"array\",\n \"items\": {\n \"description\": \"Issue contains the details of a single issue found by the linter.\",\n \"type\": \"object\",\n \"properties\": {\n \"code\": {\n \"description\": \"Required. Rule code unique to each rule defined in linter.\",\n \"type\": \"string\"\n },\n \"path\": {\n \"description\": \"Required. An array of strings indicating the location in the analyzed document where\\nthe rule was triggered.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"message\": {\n \"description\": \"Required. Human-readable message describing the issue found by the linter.\",\n \"type\": \"string\"\n },\n \"severity\": {\n \"description\": \"Required. Severity level of the rule violation.\",\n \"type\": \"string\",\n \"x-google-enum-descriptions\": [\"Severity unspecified.\", \"Severity error.\", \"Severity warning.\", \"Severity info.\", \"Severity hint.\"],\n \"enum\": [\"SEVERITY_UNSPECIFIED\", \"SEVERITY_ERROR\", \"SEVERITY_WARNING\", \"SEVERITY_INFO\", \"SEVERITY_HINT\"]\n },\n \"range\": {\n \"description\": \"Required. Object describing where in the file the issue was found.\",\n \"type\": \"object\",\n \"properties\": {\n \"start\": {\n \"description\": \"Required. Start of the issue.\",\n \"type\": \"object\",\n \"properties\": {\n \"line\": {\n \"description\": \"Required. Line number (zero-indexed).\",\n \"type\": \"integer\",\n \"format\": \"int32\"\n },\n \"character\": {\n \"description\": \"Required. Character position within the line (zero-indexed).\",\n \"type\": \"integer\",\n \"format\": \"int32\"\n }\n },\n \"required\": [\"line\", \"character\"]\n },\n \"end\": {\n \"description\": \"Required. End of the issue.\",\n \"type\": \"object\",\n \"properties\": {\n \"line\": {\n \"description\": \"Required. Line number (zero-indexed).\",\n \"type\": \"integer\",\n \"format\": \"int32\"\n },\n \"character\": {\n \"description\": \"Required. Character position within the line (zero-indexed).\",\n \"type\": \"integer\",\n \"format\": \"int32\"\n }\n },\n \"required\": [\"line\", \"character\"]\n }\n },\n \"required\": [\"start\", \"end\"]\n }\n },\n \"required\": [\"code\", \"path\", \"message\", \"severity\", \"range\"]\n }\n },\n \"summary\": {\n \"description\": \"Optional. Summary of all issue types and counts for each severity level.\",\n \"type\": \"array\",\n \"items\": {\n \"description\": \"Count of issues with a given severity.\",\n \"type\": \"object\",\n \"properties\": {\n \"severity\": {\n \"description\": \"Required. Severity of the issue.\",\n \"type\": \"string\",\n \"x-google-enum-descriptions\": [\"Severity unspecified.\", \"Severity error.\", \"Severity warning.\", \"Severity info.\", \"Severity hint.\"],\n \"enum\": [\"SEVERITY_UNSPECIFIED\", \"SEVERITY_ERROR\", \"SEVERITY_WARNING\", \"SEVERITY_INFO\", \"SEVERITY_HINT\"]\n },\n \"count\": {\n \"description\": \"Required. Count of issues with the given severity.\",\n \"type\": \"integer\",\n \"format\": \"int32\"\n }\n },\n \"required\": [\"severity\", \"count\"]\n }\n },\n \"state\": {\n \"description\": \"Required. Lint state represents success or failure for linting.\",\n \"type\": \"string\",\n \"x-google-enum-descriptions\": [\"Lint state unspecified.\", \"Linting was completed successfully.\", \"Linting encountered errors.\"],\n \"enum\": [\"LINT_STATE_UNSPECIFIED\", \"LINT_STATE_SUCCESS\", \"LINT_STATE_ERROR\"]\n },\n \"source\": {\n \"description\": \"Required. Name of the linting application.\",\n \"type\": \"string\"\n },\n \"linter\": {\n \"description\": \"Required. Name of the linter used.\",\n \"type\": \"string\",\n \"x-google-enum-descriptions\": [\"Linter type unspecified.\", \"Linter type spectral.\", \"Linter type other.\"],\n \"enum\": [\"LINTER_UNSPECIFIED\", \"SPECTRAL\", \"OTHER\"]\n },\n \"createTime\": {\n \"description\": \"Required. Timestamp when the linting response was generated.\",\n \"type\": \"string\",\n \"format\": \"date-time\"\n }\n },\n \"required\": [\"state\", \"source\", \"linter\", \"createTime\"]\n },\n \"attributes\": {\n \"description\": \"Optional. The list of user defined attributes associated with the spec.\\nThe key is the attribute name. It will be of the format:\\n`projects/{project}/locations/{location}/attributes/{attribute}`.\\nThe value is the attribute values associated with the resource.\",\n \"type\": \"object\",\n \"additionalProperties\": {\n \"description\": \"The attribute values associated with resource.\",\n \"type\": \"object\",\n \"properties\": {\n \"enumValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is enum.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is enum.\",\n \"type\": \"array\",\n \"items\": {\n \"description\": \"The value that can be assigned to the attribute when the data type is\\nenum.\",\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"description\": \"Required. The ID of the allowed value.\\n* If provided, the same will be used. The service will throw an error if\\nthe specified id is already used by another allowed value in the same\\nattribute resource.\\n* If not provided, a system generated id derived from the display name\\nwill be used. In this case, the service will handle conflict resolution\\nby adding a system generated suffix in case of duplicates.\\n\\nThis value should be 4-63 characters, and valid characters\\nare /a-z-/.\",\n \"type\": \"string\"\n },\n \"displayName\": {\n \"description\": \"Required. The display name of the allowed value.\",\n \"type\": \"string\"\n },\n \"description\": {\n \"description\": \"Optional. The detailed description of the allowed value.\",\n \"type\": \"string\"\n },\n \"immutable\": {\n \"description\": \"Optional. When set to true, the allowed value cannot be updated or deleted by the\\nuser. It can only be true for System defined attributes.\",\n \"type\": \"boolean\"\n }\n },\n \"required\": [\"id\", \"displayName\"]\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"stringValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is string.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"jsonValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is JSON.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"uriValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is URL, URI or IP, like gs://bucket-name/object-name.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"attribute\": {\n \"description\": \"Output only. The name of the attribute.\\nFormat: projects/{project}/locations/{location}/attributes/{attribute}\",\n \"readOnly\": true,\n \"type\": \"string\"\n }\n }\n }\n },\n \"documentation\": {\n \"description\": \"Optional. The documentation of the spec.\\nFor OpenAPI spec, this will be populated from `externalDocs` in OpenAPI\\nspec.\",\n \"type\": \"object\",\n \"properties\": {\n \"externalUri\": {\n \"description\": \"Optional. The uri of the externally hosted documentation.\",\n \"type\": \"string\"\n }\n }\n },\n \"parsingMode\": {\n \"description\": \"Optional. Input only. Enum specifying the parsing mode for OpenAPI Specification (OAS) parsing.\",\n \"writeOnly\": true,\n \"type\": \"string\",\n \"x-google-enum-descriptions\": [\"Defaults to `RELAXED`.\", \"Parsing of the Spec on create and update is relaxed, meaning that\\nparsing errors the spec contents will not fail the API call.\", \"Parsing of the Spec on create and update is strict, meaning that\\nparsing errors in the spec contents will fail the API call.\"],\n \"enum\": [\"PARSING_MODE_UNSPECIFIED\", \"RELAXED\", \"STRICT\"]\n },\n \"sourceMetadata\": {\n \"description\": \"Output only. The list of sources and metadata from the sources of the spec.\",\n \"readOnly\": true,\n \"type\": \"array\",\n \"items\": {\n \"description\": \"SourceMetadata represents the metadata for a resource at the source.\",\n \"type\": \"object\",\n \"properties\": {\n \"pluginInstanceActionSource\": {\n \"description\": \"Output only. The source of the resource is a plugin instance action.\",\n \"readOnly\": true,\n \"type\": \"object\",\n \"properties\": {\n \"pluginInstance\": {\n \"description\": \"Output only. The resource name of the source plugin instance.\\nFormat is\\n`projects/{project}/locations/{location}/plugins/{plugin}/instances/{instance}`\",\n \"readOnly\": true,\n \"type\": \"string\"\n },\n \"actionId\": {\n \"description\": \"Output only. The id of the plugin instance action.\",\n \"readOnly\": true,\n \"type\": \"string\"\n }\n }\n },\n \"sourceType\": {\n \"description\": \"Output only. The type of the source.\",\n \"readOnly\": true,\n \"type\": \"string\",\n \"x-google-enum-descriptions\": [\"Source type not specified.\", \"Source type plugin.\"],\n \"enum\": [\"SOURCE_TYPE_UNSPECIFIED\", \"PLUGIN\"]\n },\n \"originalResourceId\": {\n \"description\": \"Output only. The unique identifier of the resource at the source.\",\n \"readOnly\": true,\n \"type\": \"string\"\n },\n \"originalResourceCreateTime\": {\n \"description\": \"Output only. The time at which the resource was created at the source.\",\n \"readOnly\": true,\n \"type\": \"string\",\n \"format\": \"date-time\"\n },\n \"originalResourceUpdateTime\": {\n \"description\": \"Output only. The time at which the resource was last updated at the source.\",\n \"readOnly\": true,\n \"type\": \"string\",\n \"format\": \"date-time\"\n }\n }\n }\n }\n },\n \"required\": [\"displayName\", \"specType\"]\n },\n \"originalId\": {\n \"description\": \"Optional. The unique identifier of the spec in the system where it was originally\\ncreated.\",\n \"type\": \"string\"\n },\n \"originalCreateTime\": {\n \"description\": \"Optional. Timestamp indicating when the spec was created at the source.\",\n \"type\": \"string\",\n \"format\": \"date-time\"\n },\n \"originalUpdateTime\": {\n \"description\": \"Required. Timestamp indicating when the spec was last updated at the source.\",\n \"type\": \"string\",\n \"format\": \"date-time\"\n }\n },\n \"required\": [\"spec\", \"originalUpdateTime\"]\n }\n },\n \"deployments\": {\n \"description\": \"Optional. The deployments linked to this API version.\\nNote: A particular API version could be deployed to multiple deployments\\n(for dev deployment, UAT deployment, etc.)\",\n \"type\": \"array\",\n \"items\": {\n \"description\": \"The metadata associated with a deployment.\",\n \"type\": \"object\",\n \"properties\": {\n \"deployment\": {\n \"description\": \"Required. The deployment resource to be pushed to Hub\\u0027s collect layer. The ID of the\\ndeployment will be generated by Hub.\",\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"description\": \"Identifier. The name of the deployment.\\n\\nFormat:\\n`projects/{project}/locations/{location}/deployments/{deployment}`\",\n \"x-google-identifier\": true,\n \"type\": \"string\"\n },\n \"displayName\": {\n \"description\": \"Required. The display name of the deployment.\",\n \"type\": \"string\"\n },\n \"description\": {\n \"description\": \"Optional. The description of the deployment.\",\n \"type\": \"string\"\n },\n \"documentation\": {\n \"description\": \"Optional. The documentation of the deployment.\",\n \"type\": \"object\",\n \"properties\": {\n \"externalUri\": {\n \"description\": \"Optional. The uri of the externally hosted documentation.\",\n \"type\": \"string\"\n }\n }\n },\n \"deploymentType\": {\n \"description\": \"Required. The type of deployment.\\nThis maps to the following system defined attribute:\\n`projects/{project}/locations/{location}/attributes/system-deployment-type`\\nattribute.\\nThe number of values for this attribute will be based on the\\ncardinality of the attribute. The same can be retrieved via GetAttribute\\nAPI. All values should be from the list of allowed values defined for the\\nattribute.\",\n \"type\": \"object\",\n \"properties\": {\n \"enumValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is enum.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is enum.\",\n \"type\": \"array\",\n \"items\": {\n \"description\": \"The value that can be assigned to the attribute when the data type is\\nenum.\",\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"description\": \"Required. The ID of the allowed value.\\n* If provided, the same will be used. The service will throw an error if\\nthe specified id is already used by another allowed value in the same\\nattribute resource.\\n* If not provided, a system generated id derived from the display name\\nwill be used. In this case, the service will handle conflict resolution\\nby adding a system generated suffix in case of duplicates.\\n\\nThis value should be 4-63 characters, and valid characters\\nare /a-z-/.\",\n \"type\": \"string\"\n },\n \"displayName\": {\n \"description\": \"Required. The display name of the allowed value.\",\n \"type\": \"string\"\n },\n \"description\": {\n \"description\": \"Optional. The detailed description of the allowed value.\",\n \"type\": \"string\"\n },\n \"immutable\": {\n \"description\": \"Optional. When set to true, the allowed value cannot be updated or deleted by the\\nuser. It can only be true for System defined attributes.\",\n \"type\": \"boolean\"\n }\n },\n \"required\": [\"id\", \"displayName\"]\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"stringValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is string.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"jsonValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is JSON.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"uriValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is URL, URI or IP, like gs://bucket-name/object-name.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"attribute\": {\n \"description\": \"Output only. The name of the attribute.\\nFormat: projects/{project}/locations/{location}/attributes/{attribute}\",\n \"readOnly\": true,\n \"type\": \"string\"\n }\n }\n },\n \"resourceUri\": {\n \"description\": \"Required. A uri that uniquely identfies the deployment within a particular gateway.\\nFor example, if the runtime resource is of type APIGEE_PROXY, then this\\nfield will be a combination of org, proxy name and environment.\",\n \"type\": \"string\"\n },\n \"endpoints\": {\n \"description\": \"Required. The endpoints at which this deployment resource is listening for API\\nrequests. This could be a list of complete URIs, hostnames or an IP\\naddresses.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"apiVersions\": {\n \"description\": \"Output only. The API versions linked to this deployment.\\nNote: A particular deployment could be linked to multiple different API\\nversions (of same or different APIs).\",\n \"readOnly\": true,\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"createTime\": {\n \"description\": \"Output only. The time at which the deployment was created.\",\n \"readOnly\": true,\n \"type\": \"string\",\n \"format\": \"date-time\"\n },\n \"updateTime\": {\n \"description\": \"Output only. The time at which the deployment was last updated.\",\n \"readOnly\": true,\n \"type\": \"string\",\n \"format\": \"date-time\"\n },\n \"slo\": {\n \"description\": \"Optional. The SLO for this deployment.\\nThis maps to the following system defined attribute:\\n`projects/{project}/locations/{location}/attributes/system-slo`\\nattribute.\\nThe number of values for this attribute will be based on the\\ncardinality of the attribute. The same can be retrieved via GetAttribute\\nAPI. All values should be from the list of allowed values defined for the\\nattribute.\",\n \"type\": \"object\",\n \"properties\": {\n \"enumValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is enum.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is enum.\",\n \"type\": \"array\",\n \"items\": {\n \"description\": \"The value that can be assigned to the attribute when the data type is\\nenum.\",\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"description\": \"Required. The ID of the allowed value.\\n* If provided, the same will be used. The service will throw an error if\\nthe specified id is already used by another allowed value in the same\\nattribute resource.\\n* If not provided, a system generated id derived from the display name\\nwill be used. In this case, the service will handle conflict resolution\\nby adding a system generated suffix in case of duplicates.\\n\\nThis value should be 4-63 characters, and valid characters\\nare /a-z-/.\",\n \"type\": \"string\"\n },\n \"displayName\": {\n \"description\": \"Required. The display name of the allowed value.\",\n \"type\": \"string\"\n },\n \"description\": {\n \"description\": \"Optional. The detailed description of the allowed value.\",\n \"type\": \"string\"\n },\n \"immutable\": {\n \"description\": \"Optional. When set to true, the allowed value cannot be updated or deleted by the\\nuser. It can only be true for System defined attributes.\",\n \"type\": \"boolean\"\n }\n },\n \"required\": [\"id\", \"displayName\"]\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"stringValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is string.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"jsonValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is JSON.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"uriValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is URL, URI or IP, like gs://bucket-name/object-name.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"attribute\": {\n \"description\": \"Output only. The name of the attribute.\\nFormat: projects/{project}/locations/{location}/attributes/{attribute}\",\n \"readOnly\": true,\n \"type\": \"string\"\n }\n }\n },\n \"environment\": {\n \"description\": \"Optional. The environment mapping to this deployment.\\nThis maps to the following system defined attribute:\\n`projects/{project}/locations/{location}/attributes/system-environment`\\nattribute.\\nThe number of values for this attribute will be based on the\\ncardinality of the attribute. The same can be retrieved via GetAttribute\\nAPI. All values should be from the list of allowed values defined for the\\nattribute.\",\n \"type\": \"object\",\n \"properties\": {\n \"enumValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is enum.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is enum.\",\n \"type\": \"array\",\n \"items\": {\n \"description\": \"The value that can be assigned to the attribute when the data type is\\nenum.\",\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"description\": \"Required. The ID of the allowed value.\\n* If provided, the same will be used. The service will throw an error if\\nthe specified id is already used by another allowed value in the same\\nattribute resource.\\n* If not provided, a system generated id derived from the display name\\nwill be used. In this case, the service will handle conflict resolution\\nby adding a system generated suffix in case of duplicates.\\n\\nThis value should be 4-63 characters, and valid characters\\nare /a-z-/.\",\n \"type\": \"string\"\n },\n \"displayName\": {\n \"description\": \"Required. The display name of the allowed value.\",\n \"type\": \"string\"\n },\n \"description\": {\n \"description\": \"Optional. The detailed description of the allowed value.\",\n \"type\": \"string\"\n },\n \"immutable\": {\n \"description\": \"Optional. When set to true, the allowed value cannot be updated or deleted by the\\nuser. It can only be true for System defined attributes.\",\n \"type\": \"boolean\"\n }\n },\n \"required\": [\"id\", \"displayName\"]\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"stringValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is string.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"jsonValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is JSON.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"uriValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is URL, URI or IP, like gs://bucket-name/object-name.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"attribute\": {\n \"description\": \"Output only. The name of the attribute.\\nFormat: projects/{project}/locations/{location}/attributes/{attribute}\",\n \"readOnly\": true,\n \"type\": \"string\"\n }\n }\n },\n \"attributes\": {\n \"description\": \"Optional. The list of user defined attributes associated with the deployment\\nresource.\\nThe key is the attribute name. It will be of the format:\\n`projects/{project}/locations/{location}/attributes/{attribute}`.\\nThe value is the attribute values associated with the resource.\",\n \"type\": \"object\",\n \"additionalProperties\": {\n \"description\": \"The attribute values associated with resource.\",\n \"type\": \"object\",\n \"properties\": {\n \"enumValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is enum.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is enum.\",\n \"type\": \"array\",\n \"items\": {\n \"description\": \"The value that can be assigned to the attribute when the data type is\\nenum.\",\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"description\": \"Required. The ID of the allowed value.\\n* If provided, the same will be used. The service will throw an error if\\nthe specified id is already used by another allowed value in the same\\nattribute resource.\\n* If not provided, a system generated id derived from the display name\\nwill be used. In this case, the service will handle conflict resolution\\nby adding a system generated suffix in case of duplicates.\\n\\nThis value should be 4-63 characters, and valid characters\\nare /a-z-/.\",\n \"type\": \"string\"\n },\n \"displayName\": {\n \"description\": \"Required. The display name of the allowed value.\",\n \"type\": \"string\"\n },\n \"description\": {\n \"description\": \"Optional. The detailed description of the allowed value.\",\n \"type\": \"string\"\n },\n \"immutable\": {\n \"description\": \"Optional. When set to true, the allowed value cannot be updated or deleted by the\\nuser. It can only be true for System defined attributes.\",\n \"type\": \"boolean\"\n }\n },\n \"required\": [\"id\", \"displayName\"]\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"stringValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is string.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"jsonValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is JSON.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"uriValues\": {\n \"description\": \"The attribute values associated with a resource in case attribute data\\ntype is URL, URI or IP, like gs://bucket-name/object-name.\",\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"description\": \"Required. The attribute values in case attribute data type is string or JSON.\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"required\": [\"values\"]\n },\n \"attribute\": {\n \"description\": \"Output only. The name of the attribute.\\nFormat: projects/{project}/locations/{location}/attributes/{attribute}\",\n \"readOnly\": true,\n \"type\": \"string\"\n }\n }\n }\n },\n \"sourceMetadata\": {\n \"description\": \"Output only. The list of sources and metadata from the sources of the deployment.\",\n \"readOnly\": true,\n \"type\": \"array\",\n \"items\": {\n \"description\": \"SourceMetadata represents the metadata for a resource at the source.\",\n \"type\": \"object\",\n \"properties\": {\n \"pluginInstanceActionSource\": {\n \"description\": \"Output only. The source of the resource is a plugin instance action.\",\n \"readOnly\": true,\n \"type\": \"object\",\n \"properties\": {\n \"pluginInstance\": {\n \"description\": \"Output only. The resource name of the source plugin instance.\\nFormat is\\n`projects/{project}/locations/{location}/plugins/{plugin}/instances/{instance}`\",\n \"readOnly\": true,\n \"type\": \"string\"\n },\n \"actionId\": {\n \"description\": \"Output only. The id of the plugin instance action.\",\n \"readOnly\": true,\n \"type\": \"string\"\n }\n }\n },\n \"sourceType\": {\n \"description\": \"Output only. The type of the source.\",\n \"readOnly\": true,\n \"type\": \"string\",\n \"x-google-enum-descriptions\": [\"Source type not specified.\", \"Source type plugin.\"],\n \"enum\": [\"SOURCE_TYPE_UNSPECIFIED\", \"PLUGIN\"]\n },\n \"originalResourceId\": {\n \"description\": \"Output only. The unique identifier of the resource at the source.\",\n \"readOnly\": true,\n \"type\": \"string\"\n },\n \"originalResourceCreateTime\": {\n \"description\": \"Output only. The time at which the resource was created at the source.\",\n \"readOnly\": true,\n \"type\": \"string\",\n \"format\": \"date-time\"\n },\n \"originalResourceUpdateTime\": {\n \"description\": \"Output only. The time at which the resource was last updated at the source.\",\n \"readOnly\": true,\n \"type\": \"string\",\n \"format\": \"date-time\"\n }\n }\n }\n }\n },\n \"required\": [\"displayName\", \"deploymentType\", \"resourceUri\", \"endpoints\"]\n },\n \"originalId\": {\n \"description\": \"Optional. The unique identifier of the deployment in the system where it was\\noriginally created.\",\n \"type\": \"string\"\n },\n \"originalCreateTime\": {\n \"description\": \"Optional. Timestamp indicating when the deployment was created at the source.\",\n \"type\": \"string\",\n \"format\": \"date-time\"\n },\n \"originalUpdateTime\": {\n \"description\": \"Required. Timestamp indicating when the deployment was last updated at the source.\",\n \"type\": \"string\",\n \"format\": \"date-time\"\n }\n },\n \"required\": [\"deployment\", \"originalUpdateTime\"]\n }\n },\n \"originalId\": {\n \"description\": \"Optional. The unique identifier of the version in the system where it was originally\\ncreated.\",\n \"type\": \"string\"\n },\n \"originalCreateTime\": {\n \"description\": \"Optional. Timestamp indicating when the version was created at the source.\",\n \"type\": \"string\",\n \"format\": \"date-time\"\n },\n \"originalUpdateTime\": {\n \"description\": \"Required. Timestamp indicating when the version was last updated at the source.\",\n \"type\": \"string\",\n \"format\": \"date-time\"\n }\n },\n \"required\": [\"version\", \"originalUpdateTime\"]\n }\n },\n \"originalId\": {\n \"description\": \"Optional. The unique identifier of the API in the system where it was originally\\ncreated.\",\n \"type\": \"string\"\n },\n \"originalCreateTime\": {\n \"description\": \"Optional. Timestamp indicating when the API was created at the source.\",\n \"type\": \"string\",\n \"format\": \"date-time\"\n },\n \"originalUpdateTime\": {\n \"description\": \"Required. Timestamp indicating when the API was last updated at the source.\",\n \"type\": \"string\",\n \"format\": \"date-time\"\n }\n },\n \"required\": [\"api\", \"originalUpdateTime\"]\n }\n },\n \"required\": [\"apiMetadata\"]\n }\n }\n }\n}" + }, { + "key": "curatedAPIMetadata", + "dataType": "JSON_VALUE", + "displayName": "curatedAPIMetadata", + "inputOutputType": "OUT" + }, { + "key": "apiMetadata", + "dataType": "JSON_VALUE", + "displayName": "apiMetadata", + "jsonSchema": "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"type\": \"object\",\n \"properties\": {\n \"versions\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"deployments\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"originalCreateTime\": {\n \"type\": \"string\"\n },\n \"originalUpdateTime\": {\n \"type\": \"string\"\n },\n \"originalId\": {\n \"type\": \"string\"\n },\n \"deployment\": {\n \"type\": \"object\",\n \"properties\": {\n \"deploymentType\": {\n \"type\": \"object\",\n \"properties\": {\n \"attribute\": {\n \"type\": \"string\"\n },\n \"enumValues\": {\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n }\n }\n }\n }\n }\n }\n }\n },\n \"endpoints\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"displayName\": {\n \"type\": \"string\"\n },\n \"description\": {\n \"type\": \"string\"\n },\n \"attributes\": {\n \"type\": \"object\",\n \"properties\": {\n \"projects/api-hub-demo-5/locations/us-central1/attributes/plugin-system-apigee-x-and-hybrid-environment\": {\n \"type\": \"object\",\n \"properties\": {\n \"stringValues\": {\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n }\n },\n \"attribute\": {\n \"type\": \"string\"\n }\n }\n },\n \"projects/api-hub-demo-5/locations/us-central1/attributes/plugin-system-apigee-x-and-hybrid-organization\": {\n \"type\": \"object\",\n \"properties\": {\n \"stringValues\": {\n \"type\": \"object\",\n \"properties\": {\n \"values\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n }\n },\n \"attribute\": {\n \"type\": \"string\"\n }\n }\n }\n }\n },\n \"resourceUri\": {\n \"type\": \"string\"\n }\n }\n }\n }\n }\n },\n \"originalCreateTime\": {\n \"type\": \"string\"\n },\n \"originalUpdateTime\": {\n \"type\": \"string\"\n },\n \"originalId\": {\n \"type\": \"string\"\n },\n \"version\": {\n \"type\": \"object\",\n \"properties\": {\n \"displayName\": {\n \"type\": \"string\"\n },\n \"name\": {\n \"type\": \"string\"\n }\n }\n }\n }\n }\n },\n \"originalUpdateTime\": {\n \"type\": \"string\"\n },\n \"api\": {\n \"type\": \"object\",\n \"properties\": {\n \"displayName\": {\n \"type\": \"string\"\n },\n \"name\": {\n \"type\": \"string\"\n },\n \"fingerprint\": {\n \"type\": \"string\"\n }\n }\n },\n \"originalId\": {\n \"type\": \"string\"\n }\n }\n}" + }, { + "key": "`Task_3_connectorInputPayload`", + "dataType": "JSON_VALUE", + "displayName": "`Task_3_connectorInputPayload`", + "producer": "1_3", + "jsonSchema": "{\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"type\": \"object\",\n \"properties\": {\n \"Bucket\": {\n \"type\": \"string\",\n \"description\": \"Bucket name where the object is located.\"\n },\n \"ObjectFilePath\": {\n \"type\": [\"string\", \"null\"],\n \"description\": \"Object name for the object that should be retrieved. If not specified, all the objects from the specified bucket will be retrieved.\"\n },\n \"HasBytes\": {\n \"type\": [\"boolean\", \"null\"],\n \"description\": \"Whether to download content as bytes.\",\n \"default\": false\n },\n \"UpdatedEndDate\": {\n \"type\": [\"string\", \"null\"],\n \"description\": \"The end of the date range to download objects. If not specified, objects will be downloaded from the specified UpdatedStartDate until the present day.\"\n },\n \"UpdatedStartDate\": {\n \"type\": [\"string\", \"null\"],\n \"description\": \"The start of the date range to download objects. If not specified, objects will be downloaded from the beginning of the time until the UpdatedEndDate.\"\n }\n },\n \"required\": [\"Bucket\"]\n}" + }, { + "key": "`Task_3_connectorOutputPayload`", + "dataType": "JSON_VALUE", + "displayName": "`Task_3_connectorOutputPayload`", + "isTransient": true, + "producer": "1_3", + "jsonSchema": "{\n \"type\": \"array\",\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n },\n \"$schema\": \"http://json-schema.org/draft-07/schema#\"\n }\n}" + }], + "databasePersistencePolicy": "DATABASE_PERSISTENCE_ASYNC", + "integrationConfigParameters": [{ + "parameter": { + "key": "`CONFIG_gcsConnectionName`", + "dataType": "STRING_VALUE", + "defaultValue": { + "stringValue": "projects/{project-id}/locations/{location}/connections/{connection-name}" + }, + "displayName": "`CONFIG_gcsConnectionName`" + } + }, { + "parameter": { + "key": "`CONFIG_bucketName`", + "dataType": "STRING_VALUE", + "defaultValue": { + "stringValue": "{bucket-name}" + }, + "displayName": "`CONFIG_bucketName`" + } + }] +} \ No newline at end of file diff --git a/apihub-curation/enrich-with-specs/enrich-with-spec.png b/apihub-curation/enrich-with-specs/enrich-with-spec.png new file mode 100644 index 00000000..b6d34840 Binary files /dev/null and b/apihub-curation/enrich-with-specs/enrich-with-spec.png differ diff --git a/apihub-curation/enrich-with-specs/specs/orders-api.yaml b/apihub-curation/enrich-with-specs/specs/orders-api.yaml new file mode 100644 index 00000000..9bfba60f --- /dev/null +++ b/apihub-curation/enrich-with-specs/specs/orders-api.yaml @@ -0,0 +1,165 @@ +openapi: 3.0.0 +info: + title: Orders API + version: 1.0.0 + description: API for managing customer orders and their associated items. This includes creating new orders and retrieving existing order details. +servers: + - url: https://api.example.com/orders/v1 + description: Order processing production server. +paths: + /orders: + get: + summary: Get all orders + operationId: getAllOrders + responses: + '200': + description: A list of orders successfully retrieved. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Order' + post: + summary: Create a new order + operationId: createOrder + requestBody: + required: true + description: Order data to be created. + content: + application/json: + schema: + $ref: '#/components/schemas/OrderInput' + responses: + '201': + description: Order successfully created. + content: + application/json: + schema: + $ref: '#/components/schemas/Order' + '400': + description: Invalid order data provided. + /orders/{orderId}: + get: + summary: Get an order by ID + operationId: getOrderById + parameters: + - name: orderId + in: path + required: true + description: Unique identifier of the order to retrieve. + schema: + type: string + format: uuid + responses: + '200': + description: Order details successfully retrieved. + content: + application/json: + schema: + $ref: '#/components/schemas/Order' + '404': + description: Order not found with the given ID. + /orders/{orderId}/items: + get: + summary: Get items for a specific order + operationId: getOrderItems + parameters: + - name: orderId + in: path + required: true + description: Unique identifier of the order to retrieve items for. + schema: + type: string + format: uuid + responses: + '200': + description: A list of items in the order successfully retrieved. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/OrderItem' +components: + schemas: + Order: + type: object + required: + - id + - userId + - status + - orderDate + properties: + id: + type: string + format: uuid + description: Unique order identifier. + userId: + type: string + format: uuid + description: ID of the user who placed the order. + orderDate: + type: string + format: date-time + description: Date and time the order was placed. + status: + type: string + enum: [pending, processing, shipped, delivered, cancelled] + description: Current status of the order. + default: pending + totalAmount: + type: number + format: float + description: Total amount of the order. + items: + type: array + items: + $ref: '#/components/schemas/OrderItem' + description: List of items in the order. + OrderItem: + type: object + required: + - productId + - quantity + - priceAtOrder + properties: + productId: + type: string + format: uuid + description: ID of the product ordered. + quantity: + type: integer + minimum: 1 + description: Quantity of the product ordered. + priceAtOrder: + type: number + format: float + description: Price of the product at the time of order. + OrderInput: + type: object + required: + - userId + - items + properties: + userId: + type: string + format: uuid + description: ID of the user placing the order. + items: + type: array + minItems: 1 + items: + type: object + required: + - productId + - quantity + properties: + productId: + type: string + format: uuid + description: ID of the product to add to the order. + quantity: + type: integer + minimum: 1 + description: Quantity of the product. \ No newline at end of file diff --git a/apihub-curation/enrich-with-specs/specs/products-api.yaml b/apihub-curation/enrich-with-specs/specs/products-api.yaml new file mode 100644 index 00000000..c55d7591 --- /dev/null +++ b/apihub-curation/enrich-with-specs/specs/products-api.yaml @@ -0,0 +1,154 @@ +openapi: 3.0.0 +info: + title: Products API + version: 1.0.0 + description: API for managing product inventory. This API allows for the creation, retrieval, update, and deletion of product records. +servers: + - url: https://api.example.com/products/v1 + description: Production server for the Products API. +paths: + /products: + get: + summary: Get all products + operationId: getAllProducts + responses: + '200': + description: A list of products successfully retrieved. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Product' + post: + summary: Add a new product + operationId: addProduct + requestBody: + required: true + description: Product data to be added. + content: + application/json: + schema: + $ref: '#/components/schemas/ProductInput' + responses: + '201': + description: Product successfully created. + content: + application/json: + schema: + $ref: '#/components/schemas/Product' + '400': + description: Invalid input provided for product creation. + /products/{productId}: + get: + summary: Get a product by ID + operationId: getProductById + parameters: + - name: productId + in: path + required: true + description: Unique identifier of the product to retrieve. + schema: + type: string + format: uuid + responses: + '200': + description: Product details successfully retrieved. + content: + application/json: + schema: + $ref: '#/components/schemas/Product' + '404': + description: Product not found with the given ID. + put: + summary: Update an existing product + operationId: updateProduct + parameters: + - name: productId + in: path + required: true + description: Unique identifier of the product to update. + schema: + type: string + format: uuid + requestBody: + required: true + description: Updated product data. + content: + application/json: + schema: + $ref: '#/components/schemas/ProductInput' + responses: + '200': + description: Product successfully updated. + '400': + description: Invalid input provided for product update. + '404': + description: Product not found with the given ID. + delete: + summary: Delete a product + operationId: deleteProduct + parameters: + - name: productId + in: path + required: true + description: Unique identifier of the product to delete. + schema: + type: string + format: uuid + responses: + '204': + description: Product successfully deleted. No content. + '404': + description: Product not found with the given ID. +components: + schemas: + Product: + type: object + required: + - id + - name + - price + properties: + id: + type: string + format: uuid + description: Unique product identifier. + name: + type: string + description: Name of the product. + description: + type: string + nullable: true + description: Detailed description of the product. + price: + type: number + format: float + description: Price of the product. + stock: + type: integer + format: int32 + description: Current stock quantity. + default: 0 + ProductInput: + type: object + required: + - name + - price + properties: + name: + type: string + description: Name of the product. + description: + type: string + nullable: true + description: Detailed description of the product. + price: + type: number + format: float + description: Price of the product. + stock: + type: integer + format: int32 + description: Initial stock quantity. + default: 0 \ No newline at end of file diff --git a/apihub-curation/enrich-with-specs/specs/users-api.yaml b/apihub-curation/enrich-with-specs/specs/users-api.yaml new file mode 100644 index 00000000..2af51017 --- /dev/null +++ b/apihub-curation/enrich-with-specs/specs/users-api.yaml @@ -0,0 +1,138 @@ +openapi: 3.0.0 +info: + title: Users API + version: 2.0.0 + description: API for managing user accounts and profiles within the system. It supports operations like retrieving, creating, and viewing individual users. +servers: + - url: https://api.example.com/users/v2 + description: User management production server. +paths: + /users: + get: + summary: Retrieve all users + operationId: getAllUsers + parameters: + - name: limit + in: query + description: Maximum number of users to return. + required: false + schema: + type: integer + format: int32 + minimum: 1 + maximum: 100 + - name: offset + in: query + description: Number of users to skip for pagination. + required: false + schema: + type: integer + format: int32 + minimum: 0 + responses: + '200': + description: A list of users successfully retrieved. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/User' + post: + summary: Create a new user + operationId: createUser + requestBody: + required: true + description: User data to be created. + content: + application/json: + schema: + $ref: '#/components/schemas/UserInput' + responses: + '201': + description: User successfully created. + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '400': + description: Invalid user data provided for creation. + /users/{userId}: + get: + summary: Retrieve a user by ID + operationId: getUserById + parameters: + - name: userId + in: path + required: true + description: Unique identifier of the user to retrieve. + schema: + type: string + format: uuid + responses: + '200': + description: User details successfully retrieved. + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '404': + description: User not found with the given ID. +components: + schemas: + User: + type: object + required: + - id + - username + - email + properties: + id: + type: string + format: uuid + description: Unique user identifier. + username: + type: string + description: User's chosen username. + email: + type: string + format: email + description: User's email address. + firstName: + type: string + nullable: true + description: User's first name. + lastName: + type: string + nullable: true + description: User's last name. + createdAt: + type: string + format: date-time + description: Timestamp of user creation. + UserInput: + type: object + required: + - username + - email + - password + properties: + username: + type: string + description: User's chosen username. + email: + type: string + format: email + description: User's email address. + password: + type: string + format: password + description: User's password (should be hashed in real systems). + firstName: + type: string + nullable: true + description: User's first name. + lastName: + type: string + nullable: true + description: User's last name. \ No newline at end of file