Loading...
Loading...
Builds, versions, publishes, tests, and executes Google Cloud Application Integration workflows through the REST API and Python discovery client, and promotes versions across environments. Use when listing integrations, downloading or uploading integration versions as JSON, configuring API triggers or config variables, publishing drafts, invoking integrations, or automating CI/CD promotion. Do not use for initial region provisioning and IAM setup (use application-integration-basics) or diagnosing failed runs and logs (use application-integration-troubleshooting).
npx skill4agent add google/skills application-integration-authoringhttps://integrations.googleapis.com/v1/...googleapiclient.discovery.build("integrations", "v1")gcloud integrationsgcloudgoogle_integrations_clientgoogle_integrations_auth_configgoogle_integration_connectors_connectionapplication-integration-basicsapplication-integration-troubleshootingintegrations.listintegrations:searchversions.listversions.getversions:downloadauthConfigs.listexecutions.listpip installgcloud config set auth/impersonate_service_accountCONFIG_*projects.locations.authConfigsgcloudgcloud config set project PROJECT_IDgcloud services enable integrations.googleapis.com connectors.googleapis.com secretmanager.googleapis.comus-central1LOCATIONgcloudLOCATIONPOST .../clients:provisionapplication-integration-basicscurlgcloud auth login-H "Authorization: Bearer $(gcloud auth print-access-token)"pip install "google-api-python-client>=2.100.0,<3" "google-auth>=2.20.0,<3"gcloud auth application-default loginGOOGLE_APPLICATION_CREDENTIALSgcloud config set auth/impersonate_service_account SA_EMAILroles/iam.serviceAccountTokenCreatorroles/integrations.integrationEditorversions:uploadintegrations.integrationVersions.createversions:publishroles/integrations.integrationDeployerroles/integrations.integrationEditorroles/integrations.integrationDeployerversions:uploadroles/integrations.serviceAgentservice-PROJECT_NUMBER@gcp-sa-integrations.iam.gserviceaccount.comroles/integrations.integrationInvokerrunAsServiceAccountrunAsServiceAccountrunAsServiceAccountroles/iam.serviceAccountUserroles/iam.serviceAccountUser| Goal | Action | Endpoint / Method |
|---|---|---|
| Inspect existing integrations in a region | List integrations, then list versions | |
| Export an integration version to source control | Download version JSON | |
Create an integration or add a new | Upload version JSON (creates the integration if it does not exist, or adds a new | |
| Create a brand-new integration and fail on a name clash | Create first | |
Edit an existing | Check | |
Edit an | Upload or create a new | |
| Externalize environment-specific URLs or IDs | Define | |
| Store API keys, OAuth credentials, or certs | Create an authentication profile | |
| Test an integration before production | Publish to a non-production project and invoke | |
Deploy a | Publish version with | |
| Invoke a published integration synchronously | Call | |
| Invoke a published integration asynchronously | Call | |
| Promote a version across projects (CI/CD) | Download JSON -> Upload to target -> Publish | |
LOCATIONINTEGRATION_NAMETOKEN="$(gcloud auth print-access-token)"
# List integrations in the region
curl -sS -H "Authorization: Bearer ${TOKEN}" \
"https://integrations.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/integrations?pageSize=50"
# List versions (ordered by most recently modified)
curl -sS -H "Authorization: Bearer ${TOKEN}" \
"https://integrations.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/integrations/INTEGRATION_NAME/versions?orderBy=last_modified_time%20desc"VERSION_IDnamecurl -sS -H "Authorization: Bearer ${TOKEN}" \
"https://integrations.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/integrations/INTEGRATION_NAME/versions/VERSION_ID:download?fileFormat=JSON" \
| jq -r '.content' > integration-version.jsonIntegrationVersionIntegrationVersiontriggerConfigstriggerNumbertriggerTypeAPIPRIVATE_TRIGGERtriggerIdpropertiesapi_trigger/TRIGGER_NAMEstartTaskstaskIdtaskConfigstaskEmailTaskFieldMappingTasktaskIdparametersnextTasksfailurePolicyerrorCatcherIdintegrationParameterskeydataTypeSTRING_VALUEJSON_VALUEinputOutputTypeINOUTIN_OUTIN_OUT_TYPE_UNSPECIFIEDdefaultValueintegrationConfigParametersparameter`CONFIG_<NAME>`parameter.defaultValuevalueconfigParametersrunAsServiceAccountauthConfigConnectorsCall REST EndpointrunAsServiceAccounttriggerConfigstaskConfigsintegrationParameterstriggerConfigsInternaltaskConfigsInternalintegrationParametersInternalValueTypeIntegrationVersionDRAFTINTEGRATION_NAMEversions:uploadDRAFTINTEGRATION_NAMEDRAFTDRAFTversions:publishPOST .../versions?newIntegration=trueIntegrationVersionALREADY_EXISTSINTEGRATION_NAME# Upload integration-version.json as a new DRAFT version
PAYLOAD="$(jq -n --rawfile content integration-version.json '{content: $content, fileFormat: "JSON"}')"
curl -sS --fail-with-body -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
-d "${PAYLOAD}" \
"https://integrations.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/integrations/INTEGRATION_NAME/versions:upload"VERSION_ID.integrationVersion.nameprojects/PROJECT_ID/locations/LOCATION/integrations/INTEGRATION_NAME/versions/VERSION_ID| State | Meaning | Editable? | Can Serve Triggers? |
|---|---|---|---|
| Version actively being edited; its edit lock is held by its author ( | Yes (only by | No |
| Published version serving live traffic | No | Yes |
| Prior draft (when another author takes over in the console) or unpublished version ( | No | No |
| Soft-deleted via | No | No |
DRAFTlockHolderversions:publishversions.deleteDRAFTlockHolderversions:publishversions.deletetakeoverEditLockprojects.locations.integrations.versionsversions.testCasesDRAFTupdateTimeSNAPSHOTDRAFTCONFIG_<NAME>integrationConfigParametersparameter.defaultValuevalueconfigParametersversions:publishconfigParametersintegrationConfigParameters"`CONFIG_target_url`"versions:publishauthConfigsprojects/PROJECT_ID/locations/LOCATION/authConfigs/AUTH_CONFIG_IDPOST .../authConfigsgoogle_integrations_auth_configversions:publishintegrations:executeintegrations:testPOST .../integrations/INTEGRATION_NAME:testDRAFTTestIntegrationsRequest.clientIdclientId:executeApprovalSuspendTimerversions:publishACTIVEACTIVEARCHIVEDDRAFTlockHolderACTIVEversions:unpublishACTIVESNAPSHOTPREVIOUSLY_PUBLISHEDACTIVE# Publish VERSION_ID and supply config variable values (keys must exactly match integrationConfigParameters keys, backticks included; unknown keys are silently ignored)
curl -sS --fail-with-body -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
-d '{"configParameters": {"`CONFIG_backend_url`": "https://api.example.com"}}' \
"https://integrations.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/integrations/INTEGRATION_NAME/versions/VERSION_ID:publish"ACTIVEexecutescheduletriggerIdapi_trigger/TRIGGER_NAMETRIGGER_NAME-INTEGRATION_NAMEexecutetriggerId| Method | Mode | Max Timeout | Max API Input | Key Request Fields | Key Response Fields |
|---|---|---|---|---|---|
| Sync | 2 minutes | 8 MB | | |
| Async | 10 minutes | Not documented | | |
outputParametersexecutionIdExecuteIntegrationsResponseexecutionIdoutputParameters`ExecutionId`doNotPropagateErrortrueIGNORENONE200 OKexecutions.list?filter=execution_id="EXECUTION_ID"executionDetails.statetaskExecutionStateErrorInfoExecution.responseParametersdoNotPropagateErrortruePostWithTriggerIdExecutionExceptionexecutionFailedValueTypeIntegrationVersionEmailTasktaskConfigs[].parameters"To"stringArray"Subject"stringValue"BodyFormat"stringValue"PLAIN_TEXT""TextBody"stringValue"runAsServiceAccount": "RUN_AS_SA"RUN_AS_SAorder-workflow-sa@PROJECT_ID.iam.gserviceaccount.comroles/iam.serviceAccountUserEmailTaskRECIPIENT_EMAILcurlIntegrationVersionversions:uploadINTEGRATION_NAMEDRAFT:executeroles/iam.serviceAccountUserRUN_AS_SAEmailTaskRECIPIENT_EMAILset -euo pipefail
export PROJECT_ID="my-project"
export LOCATION="us-central1"
export INTEGRATION_NAME="order-webhook"
export TRIGGER_NAME="order_api"
TOKEN="$(gcloud auth print-access-token)"
BASE_URL="https://integrations.googleapis.com/v1/projects/${PROJECT_ID}/locations/${LOCATION}"
# 1. Write an IntegrationVersion JSON file (set RUN_AS_SA and confirm RECIPIENT_EMAIL with user first; caller needs roles/iam.serviceAccountUser on RUN_AS_SA)
cat <<'EOF' > /tmp/version.json
{
"description": "API-triggered order notification integration",
"runAsServiceAccount": "RUN_AS_SA",
"triggerConfigs": [
{
"label": "API Trigger",
"triggerType": "API",
"triggerNumber": "1",
"triggerId": "api_trigger/order_api",
"properties": {"Trigger name": "order_api"},
"startTasks": [{"taskId": "1"}]
}
],
"taskConfigs": [
{
"task": "EmailTask",
"taskId": "1",
"displayName": "Send Email",
"taskExecutionStrategy": "WHEN_ALL_SUCCEED",
"parameters": {
"To": {"key": "To", "value": {"stringArray": {"stringValues": ["RECIPIENT_EMAIL"]}}},
"Subject": {"key": "Subject", "value": {"stringValue": "Order notification for $orderId$"}},
"BodyFormat": {"key": "BodyFormat", "value": {"stringValue": "PLAIN_TEXT"}},
"TextBody": {"key": "TextBody", "value": {"stringValue": "Processing order $orderId$."}}
}
}
],
"integrationParameters": [
{
"key": "orderId",
"dataType": "STRING_VALUE",
"inputOutputType": "IN_OUT",
"defaultValue": {"stringValue": "ORD-0000"}
}
]
}
EOF
# 2. Upload as a new DRAFT version — creates INTEGRATION_NAME if it does not exist yet (confirm with user first)
UPLOAD_BODY="$(jq -n --rawfile content /tmp/version.json '{content: $content, fileFormat: "JSON"}')"
VERSION_NAME="$(curl -sS --fail-with-body -X POST \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d "${UPLOAD_BODY}" \
"${BASE_URL}/integrations/${INTEGRATION_NAME}/versions:upload" \
| jq -r '.integrationVersion.name')"
VERSION_ID="${VERSION_NAME##*/}"
[[ -n "${VERSION_ID}" && "${VERSION_ID}" != "null" ]] || { echo "upload failed: ${VERSION_NAME}" >&2; exit 1; }
# 3. Publish the DRAFT version (confirm with user first)
curl -sS --fail-with-body -X POST \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{}' \
"${BASE_URL}/integrations/${INTEGRATION_NAME}/versions/${VERSION_ID}:publish"
# 4. Invoke the published version synchronously — sends a real email to RECIPIENT_EMAIL (confirm with user first)
curl -sS --fail-with-body -X POST \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-H "X-Server-Timeout: 120" \
-d "{
\"triggerId\": \"api_trigger/${TRIGGER_NAME}\",
\"inputParameters\": {
\"orderId\": {\"stringValue\": \"ORD-1001\"}
}
}" \
"${BASE_URL}/integrations/${INTEGRATION_NAME}:execute" \
| jq '{executionId, outputParameters}'docs.cloud.google.comgoogle-api-python-clientroles/iam.serviceAccountUserRUN_AS_SAEmailTaskRECIPIENT_EMAILuploadpublishexecutepip install "google-api-python-client>=2.100.0,<3" "google-auth>=2.20.0,<3"import json
from googleapiclient.discovery import build
PROJECT_ID = "PROJECT_ID"
LOCATION = "LOCATION"
INTEGRATION_NAME = "INTEGRATION_NAME"
TRIGGER_NAME = "TRIGGER_NAME"
RECIPIENT_EMAIL = "RECIPIENT_EMAIL"
parent = f"projects/{PROJECT_ID}/locations/{LOCATION}"
integration_path = f"{parent}/integrations/{INTEGRATION_NAME}"
service = build("integrations", "v1")
integrations_api = service.projects().locations().integrations()
versions_api = integrations_api.versions()
# 1. List existing integrations (read-only)
listed = integrations_api.list(parent=parent, pageSize=20).execute()
for item in listed.get("integrations", []):
print(item["name"], "active=", item.get("active"))
# 2. Upload a DRAFT version — creates INTEGRATION_NAME if it does not exist yet (set RUN_AS_SA and confirm RECIPIENT_EMAIL and action with user before running; caller needs roles/iam.serviceAccountUser on RUN_AS_SA)
version_dict = {
"description": "API-triggered order notification integration",
"runAsServiceAccount": "RUN_AS_SA",
"triggerConfigs": [{
"label": "API Trigger",
"triggerType": "API",
"triggerNumber": "1",
"triggerId": f"api_trigger/{TRIGGER_NAME}",
"properties": {"Trigger name": TRIGGER_NAME},
"startTasks": [{"taskId": "1"}],
}],
"taskConfigs": [{
"task": "EmailTask",
"taskId": "1",
"displayName": "Send Email",
"taskExecutionStrategy": "WHEN_ALL_SUCCEED",
"parameters": {
"To": {"key": "To", "value": {"stringArray": {"stringValues": [RECIPIENT_EMAIL]}}},
"Subject": {"key": "Subject", "value": {"stringValue": "Order notification for $orderId$"}},
"BodyFormat": {"key": "BodyFormat", "value": {"stringValue": "PLAIN_TEXT"}},
"TextBody": {"key": "TextBody", "value": {"stringValue": "Processing order $orderId$."}},
},
}],
"integrationParameters": [{
"key": "orderId",
"dataType": "STRING_VALUE",
"inputOutputType": "IN_OUT",
"defaultValue": {"stringValue": "ORD-0000"},
}],
}
upload_resp = versions_api.upload(
parent=integration_path,
body={"content": json.dumps(version_dict), "fileFormat": "JSON"},
).execute()
version_name = upload_resp["integrationVersion"]["name"]
# 3. Publish the DRAFT version (confirm with user before running)
versions_api.publish(
name=version_name,
body={"configParameters": {}},
).execute()
# 4. Invoke the published version synchronously — sends a real email to RECIPIENT_EMAIL (confirm with user before running)
exec_resp = integrations_api.execute(
name=integration_path,
body={
"triggerId": f"api_trigger/{TRIGGER_NAME}",
"inputParameters": {"orderId": {"stringValue": "ORD-1001"}},
},
).execute()
print("executionId:", exec_resp.get("executionId"))
print("outputParameters:", exec_resp.get("outputParameters"))TO_STRINGTO_INTexecutesScript(event)POST .../executions/EXECUTION_ID/suspensions/SUSPENSION_ID:resolve{"suspension": {"eventExecutionInfoId": "EXECUTION_ID", "integration": "INTEGRATION_NAME", "taskId": "TASK_ID", "state": "LIFTED"}}"REJECTED"integrations.suspensions.resolvePOST .../integrations/INTEGRATION_NAME/executions/EXECUTION_ID/suspensions/SUSPENSION_ID:lift-INTEGRATION_NAMEEXECUTION_IDSUSPENSION_IDEXECUTION_IDSUSPENSION_IDsuspensionResultResolvedintegrations.suspensions.liftsuspensions.listintegrations.suspensions.listroles/integrations.suspensionResolverroles/integrations.integrationAdminroles/iam.serviceAccountUserCall IntegrationFor Each LoopFor Each ParallelSYNCASYNCSYNCCONFIG_<NAME>authConfigsversions:download?fileFormat=JSON.runAsServiceAccountjq --arg sa "$RUN_AS_SA" '.runAsServiceAccount = $sa' integration.json > integration.env.jsonversions:uploadversions:publishversions:uploadDRAFT:publishPOST .../versions/VERSION_ID:unpublishDELETE .../versions/VERSION_IDDELETE .../integrations/INTEGRATION_NAMEhttps://console.cloud.google.com/connectors/connectionstriggerConfigstaskConfigsintegrationParametersValueTypetriggerId:execute:schedule