From 4c7a55d759010deaed72bc5a53301341ae461a78 Mon Sep 17 00:00:00 2001 From: roost-io Date: Thu, 4 Dec 2025 14:35:01 +0530 Subject: [PATCH] Add API Tests (Pytest Framework, Open AI) generated by RoostGPT Using AI Model gpt-5 --- Roost-README.md | 25 + requirements-roost.txt | 14 + tests/CIRCLECI_API/api.json | 23564 ++++++++++++++++ tests/CIRCLECI_API/config.yml | 56 + tests/CIRCLECI_API/conftest.py | 298 + .../insights_org-slug_summary.json | 91 + .../insights_pages_project-slug_summary.json | 101 + .../insights_project-slug_branches.json | 45 + .../insights_project-slug_flaky-tests.json | 41 + .../insights_project-slug_workflows.json | 58 + ..._project-slug_workflows_workflow-name.json | 78 + ...ect-slug_workflows_workflow-name_jobs.json | 84 + ...ect-slug_workflows_workflow-name_summ.json | 58 + ...-series_project-slug_workflows_workfl.json | 92 + .../test_insights_org-slug_summary_get.py | 275 + ...insights_pages_project-slug_summary_get.py | 256 + ...test_insights_project-slug_branches_get.py | 261 + ...t_insights_project-slug_flaky-tests_get.py | 136 + ...est_insights_project-slug_workflows_get.py | 272 + ...roject-slug_workflows_workflow-name_get.py | 267 + ...t-slug_workflows_workflow-name_jobs_get.py | 212 + ...lug_workflows_workflow-name_summary_get.py | 214 + ...t-slug_workflows_workflow-name_jobs_get.py | 234 + tests/CIRCLECI_API/validator.py | 226 + 24 files changed, 26958 insertions(+) create mode 100644 Roost-README.md create mode 100644 requirements-roost.txt create mode 100644 tests/CIRCLECI_API/api.json create mode 100644 tests/CIRCLECI_API/config.yml create mode 100644 tests/CIRCLECI_API/conftest.py create mode 100644 tests/CIRCLECI_API/insights_org-slug_summary.json create mode 100644 tests/CIRCLECI_API/insights_pages_project-slug_summary.json create mode 100644 tests/CIRCLECI_API/insights_project-slug_branches.json create mode 100644 tests/CIRCLECI_API/insights_project-slug_flaky-tests.json create mode 100644 tests/CIRCLECI_API/insights_project-slug_workflows.json create mode 100644 tests/CIRCLECI_API/insights_project-slug_workflows_workflow-name.json create mode 100644 tests/CIRCLECI_API/insights_project-slug_workflows_workflow-name_jobs.json create mode 100644 tests/CIRCLECI_API/insights_project-slug_workflows_workflow-name_summ.json create mode 100644 tests/CIRCLECI_API/insights_time-series_project-slug_workflows_workfl.json create mode 100644 tests/CIRCLECI_API/test_insights_org-slug_summary_get.py create mode 100644 tests/CIRCLECI_API/test_insights_pages_project-slug_summary_get.py create mode 100644 tests/CIRCLECI_API/test_insights_project-slug_branches_get.py create mode 100644 tests/CIRCLECI_API/test_insights_project-slug_flaky-tests_get.py create mode 100644 tests/CIRCLECI_API/test_insights_project-slug_workflows_get.py create mode 100644 tests/CIRCLECI_API/test_insights_project-slug_workflows_workflow-name_get.py create mode 100644 tests/CIRCLECI_API/test_insights_project-slug_workflows_workflow-name_jobs_get.py create mode 100644 tests/CIRCLECI_API/test_insights_project-slug_workflows_workflow-name_summary_get.py create mode 100644 tests/CIRCLECI_API/test_insights_time-series_project-slug_workflows_workflow-name_jobs_get.py create mode 100644 tests/CIRCLECI_API/validator.py diff --git a/Roost-README.md b/Roost-README.md new file mode 100644 index 00000000..dd5bcc8d --- /dev/null +++ b/Roost-README.md @@ -0,0 +1,25 @@ + +# RoostGPT generated pytest code for API Testing + +RoostGPT generats code in `tests` folder within given project path. +Dependency file i.e. `requirements-roost.txt` is also created in the given project path + +Below are the sample steps to run the generated tests. Sample commands contains use of package manager i.e. `uv`. Alternatively python and pip can be used directly. +1. ( Optional ) Create virtual Env . +2. Install dependencies +``` +uv venv // Create virtual Env +uv pip install -r requirements-roost.txt // Install all dependencies + +``` + +Test configurations and test_data is loaded from config.yml. e.g. API HOST, auth, common path parameters of endpoint. +Either set defalt value in this config.yml file OR use ENV. e.g. export API_HOST="https://example.com/api/v2" + +Once configuration values are set, use below commands to run the tests. +``` +// Run generated tests +uv run pytest -m smoke // Run only smoke tests +uv run pytest -s tests/generated-test.py // Run specific test file +``` + \ No newline at end of file diff --git a/requirements-roost.txt b/requirements-roost.txt new file mode 100644 index 00000000..bdaa6d20 --- /dev/null +++ b/requirements-roost.txt @@ -0,0 +1,14 @@ + +connexion +Flask +flask_testing +jsonschema +pytest +python_dateutil +PyYAML +referencing +Requests +setuptools +six +urllib3 +xmltodict \ No newline at end of file diff --git a/tests/CIRCLECI_API/api.json b/tests/CIRCLECI_API/api.json new file mode 100644 index 00000000..9fd67119 --- /dev/null +++ b/tests/CIRCLECI_API/api.json @@ -0,0 +1,23564 @@ +{ + "openapi": "3.0.3", + "info": { + "version": "v2", + "title": "CircleCI API", + "description": "This describes the resources that make up the CircleCI API v2.", + "license": { + "name": "MIT", + "url": "https://opensource.org/license/MIT" + } + }, + "servers": [ + { + "url": "https://circleci.com/api/v2" + } + ], + "security": [ + { + "api_key_header": [] + }, + { + "basic_auth": [] + }, + { + "api_key_query": [] + } + ], + "tags": [ + { + "name": "Context", + "description": "Endpoints relating to [contexts](https://circleci.com/docs/contexts/). Use contexts to secure and share environment variables." + }, + { + "name": "Insights", + "description": "Endpoints relating to [Insights](https://circleci.com/docs/insights/). Use Insights to monitor credit and compute usage for your projects." + }, + { + "name": "User", + "description": "A set of endpoints you can use to get information about a specific user." + }, + { + "name": "Pipeline", + "description": "Endpoints relating to [pipelines](https://circleci.com/docs/pipelines/). Get information about your pipelines. Trigger or continue a pipeline." + }, + { + "name": "Job", + "description": "Endpoints relating to [jobs](https://circleci.com/docs/jobs-steps/). Get information about your jobs, retrieve job assets, cancel a job." + }, + { + "name": "Workflow", + "description": "Endpoints relating to [workflows](https://circleci.com/docs/workflows/). Get information about your workflows, or interact with them to rerun, cancel or approve a job." + }, + { + "name": "Webhook", + "description": "Endpoints relating to [outbound webhooks](https://circleci.com/docs/outbound-webhooks/). Use outbound webhooks to integrate your CircleCI builds with external services." + }, + { + "description": "Endpoints related to manage oidc identity tokens", + "name": "OIDC Token Management" + }, + { + "description": "Endpoints related to managing policies and making policy decisions", + "name": "Policy Management" + }, + { + "name": "Deploy", + "description": "Endpoints related to deploy management." + }, + { + "name": "Pipeline Definition", + "description": "Endpoints related to creating and managing pipeline definitions." + }, + { + "name": "Project", + "description": "Endpoints related to creating and managing a project." + }, + { + "name": "Rollback", + "description": "Endpoints related to creating and managing a rollback." + }, + { + "name": "Trigger", + "description": "Endpoints related to creating and managing triggers." + }, + { + "name": "Usage", + "description": "Endpoints related to organization usage exports.\n\nThe Usage API is an API provided by CircleCI to customers to access all of their usage data on CircleCI. It contains all the metadata (org, project, pipeline, workflow, and job dimensions) as well as credit consumption data. It is provided at the near lowest level of granularity (at the job run level).\n\n__Restrictions__\n\n* Max result set size of 100MB\n* Query timeout of 4 hours.\n* Max date window of 32 days\n* 13 months of historical data is available\n* No PII is surfaced in the Usage API (e.g. email address, Github login name)\n* The POST endpoint can only be queried up to (i.e. is rate limited to) 10 times per hour per org\n* The GET endpoint can only be queried up to (i.e. is rate limited to) 10 times per hour per org\n* To increase performance the API can generate multiple CSV files that need to be merged after download\n\n__Requirements__\n\n* organization ID - To get your organization ID go to to Organization Settings tab in the CircleCI app. ie https://app.circleci.com/settings/organization///overview\n* API Personal Access Token - https://circleci.com/docs/managing-api-tokens/\n\n__Report Fields__\n\n| | Field | Description |\n|---------------------------------------|-------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| | organization_id | The org ID |\n| | organization_name | The org name |\n| | organization_created_date | The date (UTC) that the org was created |\n| Project-level attributes | project_id | The project ID / token |\n| | project_name | The project name. For classic orgs, the project name is inherited from Github. For standalone, the org is set by the user. |\n| | project_created_date | The date (UTC) that the project was created. For classic orgs, this is the date that the repo was authorized on CircleCI. For standalone orgs, this is the date that the project was created on CircleCI |\n| | last_build_finished_at | The date (UTC) of the last pipeline run on this project |\n| Pipeline-level attributes | vcs_name | The name of the VCS connected to the project on which the pipeline was run |\n| | vcs_url | The URL of the VCS on which the pipeline was run |\n| | vcs_branch | The branch on which the pipeline was run |\n| | pipeline_id | The ID of the pipeline instance that was triggered. If a pipeline is re-run, it will share the same pipeline ID as the original pipeline instance |\n| | pipeline_created_at | The date (UTC) the pipeline instance was first triggered |\n| | pipeline_number | The pipeline number |\n| | is_unregistered_user | Y/N flag of whether the pipeline was triggered by a CircleCI user or a user not registered on CircleCI. Examples of the latter include users who commit on a connected VCS and consume credits on CircleCI. |\n| | pipeline_trigger_source | The source of the pipeline instance trigger (API, webhook, etc.) |\n| | pipeline_trigger_user_id | The user ID / token of the user who triggered the pipeline |\n| Workflow-level attributes | workflow_id | The ID of the workflow instance that was triggered |\n| | workflow_name | The name of the workflow |\n| | workflow_first_job_queued_at | The timestamp (UTC) of when the workflow instance started to queue |\n| | workflow_first_job_started_at | The timestamp (UTC) of when the workflow instance started to run |\n| | workflow_stopped_at | The timestamp (UTC) of when the workflow instance stopped |\n| | is_workflow_successful | Y/N flag of whether all jobs in the workflow were successfully ran |\n| Job-level attributes | job_name | The name of the job (the name the customer sees in the UI) |\n| | job_id | The ID of the job run instance that was triggered |\n| | job_run_number | The number of the job run instance that was triggered |\n| | job_run_date | The date (UTC) of the job run instance began |\n| | job_run_queued_at | The timestamp (UTC) of when the job started to queue |\n| | job_run_started_at | The timestamp (UTC) of when the job started to run |\n| | job_run_stopped_at | The timestamp (UTC) of when the job stopped |\n| | job_build_status | The status of the job run instance |\n| | resource_class | The resource class of the job run instance |\n| | operating_system | The operating system of the job run instance |\n| | executor | The executor of the job run instance |\n| | parallelism | The parallelism of the job run instance |\n| | job_run_seconds | The duration in seconds of the job run instance |\n| | median_cpu_utilization_pct | The median CPU utilization calculated over the course of the entire job run instance. CPU utilization is logged every 15 seconds. It will not be available for any jobs under 15 seconds and occasionally will not be available for jobs greater than 15 seconds. |\n| | max_cpu_utilization_pct | The max CPU utilization logged over the course of the entire job run instance. CPU utilization is logged every 15 seconds. It will not be available for any jobs under 15 seconds and occasionally will not be available for jobs greater than 15 seconds. |\n| | median_ram_utilization_pct | The median RAM utilization calculated over the course of the entire job run instance. RAM utilization is logged every 15 seconds. It will not be available for any jobs under 15 seconds and occasionally will not be available for jobs greater than 15 seconds. |\n| | max_ram_utilization_pct | The max RAM utilization logged over the course of the entire job run instance. RAM utilization is logged every 15 seconds. It will not be available for any jobs under 15 seconds and occasionally will not be available for jobs greater than 15 seconds. |\n| Credit consumption metrics | compute_credits | The compute credits consumed by this job run instance |\n| | dlc_credits | The docker-layer caching credits consumed by this job run instance |\n| | user_credits | The user credits consumed by this job run instance |\n| | storage_credits | The storage credits consumed by this job run instance. Note: When an organization is below its allocated storage threshold, a job that uses storage will have 0 storage credits applied. The organization's included storage threshold can be found on the [CircleCI web app](https://app.circleci.com/home) by navigating to **Plan > Plan Usage**. |\n| | network_credits | The network credits consumed by this job run instance |\n| | lease_credits | The lease credits consumed by this job run instance |\n| | lease_overage_credits | The lease overage credits consumed by this job run instance |\n| | ipranges_credits | The IP ranges credits consumed by this job run instance |\n| | total_credits | The total credits consumed by this job run instance |\n" + } + ], + "paths": { + "/insights/pages/{project-slug}/summary": { + "get": { + "summary": "Get summary metrics and trends for a project across it's workflows and branches", + "description": "Get summary metrics and trends for a project at workflow and branch level.\n Workflow runs going back at most 90 days are included in the aggregation window.\n Trends are only supported upto last 30 days.\n Please note that Insights is not a financial reporting tool and should not be used for precise credit reporting. Credit reporting from Insights does not use the same source of truth as the billing information that is found in the Plan Overview page in the CircleCI UI, nor does the underlying data have the same data accuracy guarantees as the billing information in the CircleCI UI. This may lead to discrepancies between credits reported from Insights and the billing information in the Plan Overview page of the CircleCI UI. For precise credit reporting, always use the Plan Overview page in the CircleCI UI.", + "tags": [ + "Insights" + ], + "operationId": "getProjectWorkflowsPageData", + "responses": { + "200": { + "description": "Aggregated summary metrics and trends by workflow and branches", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "org_id": { + "description": "The unique ID of the organization" + }, + "project_id": { + "description": "The unique ID of the project" + }, + "project_data": { + "type": "object", + "properties": { + "metrics": { + "type": "object", + "properties": { + "total_runs": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The total number of runs, including runs that are still on-hold or running." + }, + "total_duration_secs": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "Total duration, in seconds." + }, + "total_credits_used": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The total credits consumed over the current timeseries interval." + }, + "success_rate": { + "type": "number", + "format": "float" + }, + "throughput": { + "type": "number", + "format": "float", + "description": "The average number of runs per day." + } + }, + "required": [ + "total_runs", + "total_duration_secs", + "total_credits_used", + "success_rate", + "throughput" + ], + "description": "Metrics aggregated across all workflows and branches for a project." + }, + "trends": { + "type": "object", + "properties": { + "total_runs": { + "type": "number", + "format": "float", + "description": "The trend value for total number of runs." + }, + "total_duration_secs": { + "type": "number", + "format": "float", + "description": "Trend value for total duration." + }, + "total_credits_used": { + "type": "number", + "format": "float", + "description": "The trend value for total credits consumed." + }, + "success_rate": { + "type": "number", + "format": "float", + "description": "The trend value for the success rate." + }, + "throughput": { + "type": "number", + "format": "float", + "description": "Trend value for the average number of runs per day." + } + }, + "required": [ + "total_runs", + "total_duration_secs", + "total_credits_used", + "success_rate", + "throughput" + ], + "description": "Metric trends aggregated across all workflows and branches for a project." + } + }, + "required": [ + "metrics", + "trends" + ], + "description": "Metrics and trends data aggregated for a given project." + }, + "project_workflow_data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "workflow_name": { + "type": "string", + "description": "The name of the workflow.", + "example": "build-and-test" + }, + "metrics": { + "type": "object", + "properties": { + "total_credits_used": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The total credits consumed over the current timeseries interval." + }, + "p95_duration_secs": { + "type": "number", + "format": "float", + "description": "The 95th percentile duration among a group of workflow runs." + }, + "total_runs": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The total number of runs, including runs that are still on-hold or running." + }, + "success_rate": { + "type": "number", + "format": "float" + } + }, + "required": [ + "total_credits_used", + "p95_duration_secs", + "total_runs", + "success_rate" + ], + "description": "Metrics aggregated across a workflow or branchfor a project." + }, + "trends": { + "type": "object", + "properties": { + "total_credits_used": { + "type": "number", + "format": "float", + "description": "The trend value for total credits consumed." + }, + "p95_duration_secs": { + "type": "number", + "format": "float", + "description": "The 95th percentile duration among a group of workflow runs." + }, + "total_runs": { + "type": "number", + "format": "float", + "description": "The trend value for total number of runs." + }, + "success_rate": { + "type": "number", + "format": "float", + "description": "The trend value for the success rate." + } + }, + "required": [ + "total_credits_used", + "p95_duration_secs", + "total_runs", + "success_rate" + ], + "description": "Trends aggregated across a workflow or branch for a project." + } + }, + "required": [ + "workflow_name", + "metrics", + "trends" + ] + }, + "description": "A list of metrics and trends data for workflows for a given project." + }, + "project_workflow_branch_data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "workflow_name": { + "type": "string", + "description": "The name of the workflow.", + "example": "build-and-test" + }, + "branch": { + "type": "string", + "description": "The VCS branch of a workflow's trigger.", + "example": "main" + }, + "metrics": { + "type": "object", + "properties": { + "total_credits_used": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The total credits consumed over the current timeseries interval." + }, + "p95_duration_secs": { + "type": "number", + "format": "float", + "description": "The 95th percentile duration among a group of workflow runs." + }, + "total_runs": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The total number of runs, including runs that are still on-hold or running." + }, + "success_rate": { + "type": "number", + "format": "float" + } + }, + "required": [ + "total_credits_used", + "p95_duration_secs", + "total_runs", + "success_rate" + ], + "description": "Metrics aggregated across a workflow or branchfor a project." + }, + "trends": { + "type": "object", + "properties": { + "total_credits_used": { + "type": "number", + "format": "float", + "description": "The trend value for total credits consumed." + }, + "p95_duration_secs": { + "type": "number", + "format": "float", + "description": "The 95th percentile duration among a group of workflow runs." + }, + "total_runs": { + "type": "number", + "format": "float", + "description": "The trend value for total number of runs." + }, + "success_rate": { + "type": "number", + "format": "float", + "description": "The trend value for the success rate." + } + }, + "required": [ + "total_credits_used", + "p95_duration_secs", + "total_runs", + "success_rate" + ], + "description": "Trends aggregated across a workflow or branch for a project." + } + }, + "required": [ + "workflow_name", + "branch", + "metrics", + "trends" + ] + }, + "description": "A list of metrics and trends data for branches for a given project." + }, + "all_branches": { + "type": "array", + "items": { + "type": "string", + "description": "The VCS branch of a workflow's trigger.", + "example": "main" + }, + "description": "A list of all the branches for a given project." + }, + "all_workflows": { + "type": "array", + "items": { + "type": "string", + "description": "The name of the workflow.", + "example": "build-and-test" + }, + "description": "A list of all the workflows for a given project." + } + } + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "project-slug", + "description": "Project slug in the form `vcs-slug/org-name/repo-name`. The `/` characters may be URL-escaped. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug`, replace `org-name` with the organization ID (found in Organization Settings), and replace `repo-name` with the project ID (found in Project Settings).", + "schema": { + "type": "string" + }, + "required": true, + "example": "gh/CircleCI-Public/api-preview-docs", + "allowReserved": true + }, + { + "in": "query", + "name": "reporting-window", + "description": "The time window used to calculate summary metrics. If not provided, defaults to last-90-days", + "schema": { + "type": "string" + }, + "required": false, + "example": "last-90-days" + }, + { + "in": "query", + "name": "branches", + "description": "The names of VCS branches to include in branch-level workflow metrics.", + "schema": { + "type": "object" + }, + "required": false, + "example": "A single branch: ?branches=main or for multiple branches: ?branches=main&branches=feature&branches=dev" + }, + { + "in": "query", + "name": "workflow-names", + "description": "The names of workflows to include in workflow-level metrics.", + "schema": { + "type": "object" + }, + "required": false, + "example": "A single workflow name: ?workflow-names=build-test-deploy or\n for multiple workflow names: ?workflow-names=build&workflow-names=test-and-deploy." + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url \"https://circleci.com/api/v2/insights/pages/gh/CircleCI-Public/api-preview-docs/summary?reporting-window=last-90-days&branches=A%20single%20branch%3A%20%3Fbranches%3Dmain%20or%20for%20multiple%20branches%3A%20%3Fbranches%3Dmain%26branches%3Dfeature%26branches%3Ddev&workflow-names=A%20single%20workflow%20name%3A%20%3Fworkflow-names%3Dbuild-test-deploy%20or%0A%20%20%20%20for%20multiple%20workflow%20names%3A%20%3Fworkflow-names%3Dbuild%26workflow-names%3Dtest-and-deploy.\" \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/insights/pages/gh/CircleCI-Public/api-preview-docs/summary?reporting-window=last-90-days&branches=A%20single%20branch%3A%20%3Fbranches%3Dmain%20or%20for%20multiple%20branches%3A%20%3Fbranches%3Dmain%26branches%3Dfeature%26branches%3Ddev&workflow-names=A%20single%20workflow%20name%3A%20%3Fworkflow-names%3Dbuild-test-deploy%20or%0A%20%20%20%20for%20multiple%20workflow%20names%3A%20%3Fworkflow-names%3Dbuild%26workflow-names%3Dtest-and-deploy.';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/insights/pages/gh/CircleCI-Public/api-preview-docs/summary?reporting-window=last-90-days&branches=A%20single%20branch%3A%20%3Fbranches%3Dmain%20or%20for%20multiple%20branches%3A%20%3Fbranches%3Dmain%26branches%3Dfeature%26branches%3Ddev&workflow-names=A%20single%20workflow%20name%3A%20%3Fworkflow-names%3Dbuild-test-deploy%20or%0A%20%20%20%20for%20multiple%20workflow%20names%3A%20%3Fworkflow-names%3Dbuild%26workflow-names%3Dtest-and-deploy.\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/insights/pages/gh/CircleCI-Public/api-preview-docs/summary?reporting-window=last-90-days&branches=A%20single%20branch%3A%20%3Fbranches%3Dmain%20or%20for%20multiple%20branches%3A%20%3Fbranches%3Dmain%26branches%3Dfeature%26branches%3Ddev&workflow-names=A%20single%20workflow%20name%3A%20%3Fworkflow-names%3Dbuild-test-deploy%20or%0A%20%20%20%20for%20multiple%20workflow%20names%3A%20%3Fworkflow-names%3Dbuild%26workflow-names%3Dtest-and-deploy.\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/insights/pages/gh/CircleCI-Public/api-preview-docs/summary?reporting-window=last-90-days&branches=A%20single%20branch%3A%20%3Fbranches%3Dmain%20or%20for%20multiple%20branches%3A%20%3Fbranches%3Dmain%26branches%3Dfeature%26branches%3Ddev&workflow-names=A%20single%20workflow%20name%3A%20%3Fworkflow-names%3Dbuild-test-deploy%20or%0A%20%20%20%20for%20multiple%20workflow%20names%3A%20%3Fworkflow-names%3Dbuild%26workflow-names%3Dtest-and-deploy.\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/insights/time-series/{project-slug}/workflows/{workflow-name}/jobs": { + "get": { + "summary": "Job timeseries data", + "description": "Get timeseries data for all jobs within a workflow. Hourly granularity data is only retained for 48 hours while daily granularity data is retained for 90 days.", + "tags": [ + "Insights" + ], + "operationId": "getJobTimeseries", + "responses": { + "200": { + "description": "An array of timeseries data, one entry per job.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "next_page_token": { + "type": "string", + "x-nullable": true, + "description": "A token to pass as a `page-token` query parameter to return the next page of results." + }, + "items": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of the workflow.", + "example": "build-and-test" + }, + "min_started_at": { + "type": "string", + "format": "date-time", + "description": "The start time for the earliest execution included in the metrics." + }, + "max_ended_at": { + "type": "string", + "format": "date-time", + "description": "The end time of the last execution included in the metrics." + }, + "timestamp": { + "type": "string", + "format": "date-time", + "description": "The start of the interval for timeseries metrics." + }, + "metrics": { + "type": "object", + "properties": { + "total_runs": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The total number of runs, including runs that are still on-hold or running." + }, + "failed_runs": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The number of failed runs." + }, + "successful_runs": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The number of successful runs." + }, + "throughput": { + "type": "number", + "format": "float", + "description": "The average number of runs per day." + }, + "median_credits_used": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The median credits consumed over the current timeseries interval." + }, + "total_credits_used": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The total credits consumed over the current timeseries interval." + }, + "duration_metrics": { + "type": "object", + "properties": { + "min": { + "type": "integer", + "format": "int64", + "minimum": 0, + "x-nullable": true, + "description": "The minimum duration, in seconds, among a group of runs." + }, + "median": { + "type": "integer", + "format": "int64", + "minimum": 0, + "x-nullable": true, + "description": "The median duration, in seconds, among a group of runs." + }, + "max": { + "type": "integer", + "format": "int64", + "minimum": 0, + "x-nullable": true, + "description": "The max duration, in seconds, among a group of runs." + }, + "p95": { + "type": "integer", + "format": "int64", + "minimum": 0, + "x-nullable": true, + "description": "The 95th percentile duration, in seconds, among a group of runs." + }, + "total": { + "type": "integer", + "format": "int64", + "minimum": 0, + "x-nullable": true, + "description": "The total duration, in seconds, added across a group of runs." + } + }, + "required": [ + "min", + "median", + "max", + "p95", + "total" + ], + "description": "Metrics relating to the duration of runs for a workflow." + } + }, + "required": [ + "total_runs", + "failed_runs", + "successful_runs", + "throughput", + "median_credits_used", + "total_credits_used", + "duration_metrics" + ], + "description": "Metrics relating to a workflow's runs." + } + }, + "required": [ + "name", + "min_started_at", + "max_ended_at", + "timestamp", + "metrics" + ] + }, + "description": "Aggregate metrics for a workflow at a time granularity" + } + }, + "required": [ + "next_page_token", + "items" + ], + "description": "Project level timeseries metrics response" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "project-slug", + "description": "Project slug in the form `vcs-slug/org-name/repo-name`. The `/` characters may be URL-escaped. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug`, replace `org-name` with the organization ID (found in Organization Settings), and replace `repo-name` with the project ID (found in Project Settings).", + "schema": { + "type": "string" + }, + "required": true, + "example": "gh/CircleCI-Public/api-preview-docs", + "allowReserved": true + }, + { + "in": "path", + "name": "workflow-name", + "description": "The name of the workflow.", + "schema": { + "type": "string" + }, + "required": true, + "example": "build-and-test" + }, + { + "in": "query", + "name": "branch", + "description": "The name of a vcs branch. If not passed we will scope the API call to the default branch.", + "schema": { + "type": "string" + }, + "required": false + }, + { + "in": "query", + "name": "granularity", + "description": "The granularity for which to query timeseries data.", + "schema": { + "type": "string" + }, + "required": false, + "example": "hourly" + }, + { + "in": "query", + "name": "start-date", + "description": "Include only executions that started at or after this date. This must be specified if an end-date is provided.", + "schema": { + "type": "string", + "format": "date-time" + }, + "required": false, + "example": "2020-08-21T13:26:29Z" + }, + { + "in": "query", + "name": "end-date", + "description": "Include only executions that started before this date. This date can be at most 90 days after the start-date.", + "schema": { + "type": "string", + "format": "date-time" + }, + "required": false, + "example": "2020-09-04T13:26:29Z" + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url \"https://circleci.com/api/v2/insights/time-series/gh/CircleCI-Public/api-preview-docs/workflows/build-and-test/jobs?branch=example-value&granularity=hourly&start-date=2020-08-21T13%3A26%3A29Z&end-date=2020-09-04T13%3A26%3A29Z\" \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/insights/time-series/gh/CircleCI-Public/api-preview-docs/workflows/build-and-test/jobs?branch=example-value&granularity=hourly&start-date=2020-08-21T13%3A26%3A29Z&end-date=2020-09-04T13%3A26%3A29Z';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/insights/time-series/gh/CircleCI-Public/api-preview-docs/workflows/build-and-test/jobs?branch=example-value&granularity=hourly&start-date=2020-08-21T13%3A26%3A29Z&end-date=2020-09-04T13%3A26%3A29Z\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/insights/time-series/gh/CircleCI-Public/api-preview-docs/workflows/build-and-test/jobs?branch=example-value&granularity=hourly&start-date=2020-08-21T13%3A26%3A29Z&end-date=2020-09-04T13%3A26%3A29Z\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/insights/time-series/gh/CircleCI-Public/api-preview-docs/workflows/build-and-test/jobs?branch=example-value&granularity=hourly&start-date=2020-08-21T13%3A26%3A29Z&end-date=2020-09-04T13%3A26%3A29Z\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/insights/{org-slug}/summary": { + "get": { + "summary": "Get summary metrics with trends for the entire org, and for each project.", + "description": "Gets aggregated summary metrics with trends for the entire org.\n Also gets aggregated metrics and trends for each project belonging to the org.", + "tags": [ + "Insights" + ], + "operationId": "getOrgSummaryData", + "responses": { + "200": { + "description": "summary metrics with trends for an entire org and it's projects.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "org_data": { + "type": "object", + "properties": { + "metrics": { + "type": "object", + "properties": { + "total_runs": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The total number of runs, including runs that are still on-hold or running." + }, + "total_duration_secs": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "Total duration, in seconds." + }, + "total_credits_used": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The total credits consumed over the current timeseries interval." + }, + "success_rate": { + "type": "number", + "format": "float" + }, + "throughput": { + "type": "number", + "format": "float", + "description": "The average number of runs per day." + } + }, + "required": [ + "total_runs", + "total_duration_secs", + "total_credits_used", + "success_rate", + "throughput" + ], + "description": "Metrics for a single org metrics." + }, + "trends": { + "type": "object", + "properties": { + "total_runs": { + "type": "number", + "format": "float", + "description": "The trend value for total number of runs." + }, + "total_duration_secs": { + "type": "number", + "format": "float", + "description": "Trend value for total duration." + }, + "total_credits_used": { + "type": "number", + "format": "float", + "description": "The trend value for total credits consumed." + }, + "success_rate": { + "type": "number", + "format": "float", + "description": "The trend value for the success rate." + }, + "throughput": { + "type": "number", + "format": "float", + "description": "Trend value for the average number of runs per day." + } + }, + "required": [ + "total_runs", + "total_duration_secs", + "total_credits_used", + "success_rate", + "throughput" + ], + "description": "Trends for a single org." + } + }, + "required": [ + "metrics", + "trends" + ], + "description": "Aggregated metrics for an org, with trends." + }, + "org_project_data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "project_name": { + "type": "string", + "description": "The name of the project.", + "example": "api-preview-docs" + }, + "metrics": { + "type": "object", + "properties": { + "total_credits_used": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The total credits consumed over the current timeseries interval." + }, + "total_duration_secs": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "Total duration, in seconds." + }, + "total_runs": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The total number of runs, including runs that are still on-hold or running." + }, + "success_rate": { + "type": "number", + "format": "float" + } + }, + "required": [ + "total_credits_used", + "total_duration_secs", + "total_runs", + "success_rate" + ], + "description": "Metrics for a single project, across all branches." + }, + "trends": { + "type": "object", + "properties": { + "total_credits_used": { + "type": "number", + "format": "float", + "description": "The trend value for total credits consumed." + }, + "total_duration_secs": { + "type": "number", + "format": "float", + "description": "Trend value for total duration." + }, + "total_runs": { + "type": "number", + "format": "float", + "description": "The trend value for total number of runs." + }, + "success_rate": { + "type": "number", + "format": "float", + "description": "The trend value for the success rate." + } + }, + "required": [ + "total_credits_used", + "total_duration_secs", + "total_runs", + "success_rate" + ], + "description": "Trends for a single project, across all branches." + } + }, + "required": [ + "project_name", + "metrics", + "trends" + ] + }, + "description": "Metrics for a single project, across all branches" + }, + "all_projects": { + "type": "array", + "items": { + "type": "string" + }, + "x-nullable": true, + "description": "A list of all the project names in the organization." + } + }, + "required": [ + "org_data", + "org_project_data", + "all_projects" + ], + "description": "Summary metrics with trends for the entire org, and for each project." + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "org-slug", + "description": "Org slug in the form `vcs-slug/org-name`. The `/` characters may be URL-escaped.", + "schema": { + "type": "string" + }, + "required": true, + "example": "gh/CircleCI-Public" + }, + { + "in": "query", + "name": "reporting-window", + "description": "The time window used to calculate summary metrics. If not provided, defaults to last-90-days", + "schema": { + "type": "string" + }, + "required": false, + "example": "last-90-days" + }, + { + "in": "query", + "name": "project-names", + "description": "List of project names.", + "schema": { + "type": "object" + }, + "required": false, + "example": "For a single project: ?project-names=some-project or for multiple projects: ?project-names=some-project1&project-names=some-project2" + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url \"https://circleci.com/api/v2/insights/gh/CircleCI-Public/summary?reporting-window=last-90-days&project-names=For%20a%20single%20project%3A%20%3Fproject-names%3Dsome-project%20or%20for%20multiple%20projects%3A%20%3Fproject-names%3Dsome-project1%26project-names%3Dsome-project2\" \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/insights/gh/CircleCI-Public/summary?reporting-window=last-90-days&project-names=For%20a%20single%20project%3A%20%3Fproject-names%3Dsome-project%20or%20for%20multiple%20projects%3A%20%3Fproject-names%3Dsome-project1%26project-names%3Dsome-project2';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/insights/gh/CircleCI-Public/summary?reporting-window=last-90-days&project-names=For%20a%20single%20project%3A%20%3Fproject-names%3Dsome-project%20or%20for%20multiple%20projects%3A%20%3Fproject-names%3Dsome-project1%26project-names%3Dsome-project2\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/insights/gh/CircleCI-Public/summary?reporting-window=last-90-days&project-names=For%20a%20single%20project%3A%20%3Fproject-names%3Dsome-project%20or%20for%20multiple%20projects%3A%20%3Fproject-names%3Dsome-project1%26project-names%3Dsome-project2\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/insights/gh/CircleCI-Public/summary?reporting-window=last-90-days&project-names=For%20a%20single%20project%3A%20%3Fproject-names%3Dsome-project%20or%20for%20multiple%20projects%3A%20%3Fproject-names%3Dsome-project1%26project-names%3Dsome-project2\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/insights/{project-slug}/branches": { + "get": { + "summary": "Get all branches for a project", + "description": "Get a list of all branches for a specified project. The list will only contain branches currently available within Insights. The maximum number of branches returned by this endpoint is 5,000.", + "tags": [ + "Insights" + ], + "operationId": "getAllInsightsBranches", + "responses": { + "200": { + "description": "A list of branches for a project", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "org_id": { + "description": "The unique ID of the organization" + }, + "project_id": { + "description": "The unique ID of the project" + }, + "branches": { + "type": "array", + "items": { + "type": "string", + "description": "The VCS branch of a workflow's trigger.", + "example": "main" + }, + "description": "A list of all the branches for a given project." + } + }, + "required": [ + "org_id", + "project_id", + "branches" + ], + "description": "Project branches response." + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "project-slug", + "description": "Project slug in the form `vcs-slug/org-name/repo-name`. The `/` characters may be URL-escaped. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug`, replace `org-name` with the organization ID (found in Organization Settings), and replace `repo-name` with the project ID (found in Project Settings).", + "schema": { + "type": "string" + }, + "required": true, + "example": "gh/CircleCI-Public/api-preview-docs", + "allowReserved": true + }, + { + "in": "query", + "name": "workflow-name", + "description": "The name of a workflow. If not passed we will scope the API call to the project.", + "schema": { + "type": "string" + }, + "required": false, + "example": "build-and-test" + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url \"https://circleci.com/api/v2/insights/gh/CircleCI-Public/api-preview-docs/branches?workflow-name=build-and-test\" \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/insights/gh/CircleCI-Public/api-preview-docs/branches?workflow-name=build-and-test';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/insights/gh/CircleCI-Public/api-preview-docs/branches?workflow-name=build-and-test\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/insights/gh/CircleCI-Public/api-preview-docs/branches?workflow-name=build-and-test\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/insights/gh/CircleCI-Public/api-preview-docs/branches?workflow-name=build-and-test\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/insights/{project-slug}/flaky-tests": { + "get": { + "summary": "Get flaky tests for a project", + "description": "Get a list of flaky tests for a given project. Flaky tests are branch agnostic.\n A flaky test is a test that passed and failed in the same commit.", + "tags": [ + "Insights" + ], + "operationId": "getFlakyTests", + "responses": { + "200": { + "description": "A list of flaky tests for a project", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "flaky-tests": { + "type": "array", + "items": { + "type": "object", + "properties": { + "time-wasted": { + "allOf": [ + { + "type": "integer", + "format": "int64" + }, + { + "type": "integer", + "format": "int64", + "minimum": 0 + } + ] + }, + "workflow-created-at": { + "type": "string", + "description": "The date and time when workflow was created." + }, + "workflow-id": { + "description": "The ID of the workflow associated with the provided test counts" + }, + "classname": { + "type": "string", + "x-nullable": true, + "description": "The class the test belongs to." + }, + "pipeline-number": { + "allOf": [ + { + "type": "integer", + "format": "int64" + }, + { + "type": "integer", + "format": "int64", + "minimum": 0 + } + ], + "description": "The number of the pipeline." + }, + "workflow-name": { + "type": "string", + "description": "The name of the workflow." + }, + "test-name": { + "type": "string", + "description": "The name of the test." + }, + "job-name": { + "type": "string", + "description": "The name of the job." + }, + "job-number": { + "allOf": [ + { + "type": "integer", + "format": "int64" + }, + { + "type": "integer", + "format": "int64", + "minimum": 0 + } + ], + "description": "The number of the job." + }, + "times-flaked": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The number of times the test flaked." + }, + "source": { + "type": "string", + "x-nullable": true, + "description": "The source of the test." + }, + "file": { + "type": "string", + "x-nullable": true, + "description": "The file the test belongs to." + } + }, + "required": [ + "workflow-created-at", + "classname", + "job-number", + "times-flaked", + "source", + "pipeline-number", + "file", + "workflow-name", + "job-name", + "workflow-id", + "test-name" + ] + }, + "description": "A list of all instances of flakes. Note that a test is no longer considered flaky after 2 weeks have passed without a flake. Each flake resets this timer." + }, + "total-flaky-tests": { + "type": "number", + "format": "double", + "description": "A count of unique tests that have failed. If your project has N tests that have flaked multiple times each, this will be equal to N.", + "example": 5 + } + }, + "required": [ + "flaky-tests", + "total-flaky-tests" + ], + "description": "Flaky tests response" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "project-slug", + "description": "Project slug in the form `vcs-slug/org-name/repo-name`. The `/` characters may be URL-escaped. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug`, replace `org-name` with the organization ID (found in Organization Settings), and replace `repo-name` with the project ID (found in Project Settings).", + "schema": { + "type": "string" + }, + "required": true, + "example": "gh/CircleCI-Public/api-preview-docs", + "allowReserved": true + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/insights/gh/CircleCI-Public/api-preview-docs/flaky-tests \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/insights/gh/CircleCI-Public/api-preview-docs/flaky-tests';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/insights/gh/CircleCI-Public/api-preview-docs/flaky-tests\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/insights/gh/CircleCI-Public/api-preview-docs/flaky-tests\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/insights/gh/CircleCI-Public/api-preview-docs/flaky-tests\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/insights/{project-slug}/workflows": { + "get": { + "summary": "Get summary metrics for a project's workflows", + "description": "Get summary metrics for a project's workflows. Workflow runs going back at most 90 days are included in the aggregation window. Metrics are refreshed daily, and thus may not include executions from the last 24 hours. Please note that Insights is not a financial reporting tool and should not be used for precise credit reporting. Credit reporting from Insights does not use the same source of truth as the billing information that is found in the Plan Overview page in the CircleCI UI, nor does the underlying data have the same data accuracy guarantees as the billing information in the CircleCI UI. This may lead to discrepancies between credits reported from Insights and the billing information in the Plan Overview page of the CircleCI UI. For precise credit reporting, always use the Plan Overview page in the CircleCI UI.", + "tags": [ + "Insights" + ], + "operationId": "getProjectWorkflowMetrics", + "responses": { + "200": { + "description": "A paginated list of summary metrics by workflow", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of the workflow.", + "example": "build-and-test" + }, + "metrics": { + "type": "object", + "properties": { + "total_runs": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The total number of runs, including runs that are still on-hold or running." + }, + "successful_runs": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The number of successful runs." + }, + "mttr": { + "type": "integer", + "format": "int64", + "minimum": 0, + "x-nullable": true, + "description": "The mean time to recovery (mean time between failures and their next success) in seconds." + }, + "total_credits_used": { + "type": "integer", + "format": "int64", + "minimum": 0, + "x-nullable": true, + "description": "The total credits consumed by the workflow in the aggregation window. Note that Insights is not a real time financial reporting tool and should not be used for credit reporting." + }, + "failed_runs": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The number of failed runs." + }, + "success_rate": { + "type": "number", + "format": "float" + }, + "duration_metrics": { + "type": "object", + "properties": { + "min": { + "type": "integer", + "format": "int64", + "minimum": 0, + "x-nullable": true, + "description": "The minimum duration, in seconds, among a group of runs." + }, + "mean": { + "type": "integer", + "format": "int64", + "minimum": 0, + "x-nullable": true, + "description": "The mean duration, in seconds, among a group of runs." + }, + "median": { + "type": "integer", + "format": "int64", + "minimum": 0, + "x-nullable": true, + "description": "The median duration, in seconds, among a group of runs." + }, + "p95": { + "type": "integer", + "format": "int64", + "minimum": 0, + "x-nullable": true, + "description": "The 95th percentile duration, in seconds, among a group of runs." + }, + "max": { + "type": "integer", + "format": "int64", + "minimum": 0, + "x-nullable": true, + "description": "The max duration, in seconds, among a group of runs." + }, + "standard_deviation": { + "type": "number", + "format": "float", + "x-nullable": true, + "description": "The standard deviation, in seconds, among a group of runs." + } + }, + "required": [ + "min", + "mean", + "median", + "p95", + "max", + "standard_deviation" + ], + "description": "Metrics relating to the duration of runs for a workflow." + }, + "total_recoveries": { + "type": "integer", + "format": "int64", + "minimum": 0, + "x-nullable": true, + "description": "The number of recovered workflow executions per day." + }, + "throughput": { + "type": "number", + "format": "float", + "description": "The average number of runs per day." + } + }, + "required": [ + "total_runs", + "successful_runs", + "mttr", + "total_credits_used", + "failed_runs", + "success_rate", + "duration_metrics", + "total_recoveries", + "throughput" + ], + "description": "Metrics relating to a workflow's runs." + }, + "window_start": { + "type": "string", + "format": "date-time", + "description": "The timestamp of the first build within the requested reporting window." + }, + "window_end": { + "type": "string", + "format": "date-time", + "description": "The timestamp of the last build within the requested reporting window." + }, + "project_id": { + "description": "The unique ID of the project" + } + }, + "required": [ + "name", + "metrics", + "window_start", + "window_end", + "project_id" + ] + }, + "description": "Workflow summary metrics." + }, + "next_page_token": { + "type": "string", + "x-nullable": true, + "description": "A token to pass as a `page-token` query parameter to return the next page of results." + } + }, + "required": [ + "items", + "next_page_token" + ], + "description": "Paginated workflow summary metrics." + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "project-slug", + "description": "Project slug in the form `vcs-slug/org-name/repo-name`. The `/` characters may be URL-escaped. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug`, replace `org-name` with the organization ID (found in Organization Settings), and replace `repo-name` with the project ID (found in Project Settings).", + "schema": { + "type": "string" + }, + "required": true, + "example": "gh/CircleCI-Public/api-preview-docs", + "allowReserved": true + }, + { + "in": "query", + "name": "page-token", + "description": "A token to retrieve the next page of results.", + "schema": { + "type": "string" + }, + "required": false, + "allowEmptyValue": true + }, + { + "in": "query", + "name": "all-branches", + "description": "Whether to retrieve data for all branches combined. Use either this parameter OR the branch name parameter.", + "schema": { + "type": "boolean" + }, + "required": false + }, + { + "in": "query", + "name": "branch", + "description": "The name of a vcs branch. If not passed we will scope the API call to the default branch.", + "schema": { + "type": "string" + }, + "required": false + }, + { + "in": "query", + "name": "reporting-window", + "description": "The time window used to calculate summary metrics. If not provided, defaults to last-90-days", + "schema": { + "type": "string" + }, + "required": false, + "example": "last-90-days" + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url \"https://circleci.com/api/v2/insights/gh/CircleCI-Public/api-preview-docs/workflows?page-token=example-value&all-branches=true&branch=example-value&reporting-window=last-90-days\" \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/insights/gh/CircleCI-Public/api-preview-docs/workflows?page-token=example-value&all-branches=true&branch=example-value&reporting-window=last-90-days';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/insights/gh/CircleCI-Public/api-preview-docs/workflows?page-token=example-value&all-branches=true&branch=example-value&reporting-window=last-90-days\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/insights/gh/CircleCI-Public/api-preview-docs/workflows?page-token=example-value&all-branches=true&branch=example-value&reporting-window=last-90-days\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/insights/gh/CircleCI-Public/api-preview-docs/workflows?page-token=example-value&all-branches=true&branch=example-value&reporting-window=last-90-days\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/insights/{project-slug}/workflows/{workflow-name}": { + "get": { + "summary": "Get recent runs of a workflow", + "description": "Get recent runs of a workflow. Runs going back at most 90 days are returned. Please note that Insights is not a financial reporting tool and should not be used for precise credit reporting. Credit reporting from Insights does not use the same source of truth as the billing information that is found in the Plan Overview page in the CircleCI UI, nor does the underlying data have the same data accuracy guarantees as the billing information in the CircleCI UI. This may lead to discrepancies between credits reported from Insights and the billing information in the Plan Overview page of the CircleCI UI. For precise credit reporting, always use the Plan Overview page in the CircleCI UI.", + "tags": [ + "Insights" + ], + "operationId": "getProjectWorkflowRuns", + "responses": { + "200": { + "description": "A paginated list of recent workflow runs", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the workflow." + }, + "branch": { + "type": "string", + "description": "The VCS branch of a Workflow's trigger.", + "example": "main" + }, + "duration": { + "type": "integer", + "format": "int64", + "minimum": 0, + "x-nullable": true, + "description": "The duration in seconds of a run." + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the workflow was created." + }, + "stopped_at": { + "type": "string", + "format": "date-time", + "x-nullable": true, + "description": "The date and time the workflow stopped." + }, + "credits_used": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The number of credits used during execution. Note that Insights is not a real time financial reporting tool and should not be used for credit reporting." + }, + "status": { + "type": "string", + "x-nullable": true, + "description": "Workflow status." + }, + "is_approval": { + "type": "boolean", + "description": "Describes if the job is an approval job or not. Approval jobs are intermediary jobs that are created to pause the workflow until approved.", + "example": false + } + }, + "required": [ + "id", + "branch", + "duration", + "created_at", + "stopped_at", + "credits_used", + "status", + "is_approval" + ] + }, + "description": "Recent workflow runs." + }, + "next_page_token": { + "type": "string", + "x-nullable": true, + "description": "A token to pass as a `page-token` query parameter to return the next page of results." + } + }, + "required": [ + "items", + "next_page_token" + ], + "description": "Paginated recent workflow runs." + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "project-slug", + "description": "Project slug in the form `vcs-slug/org-name/repo-name`. The `/` characters may be URL-escaped. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug`, replace `org-name` with the organization ID (found in Organization Settings), and replace `repo-name` with the project ID (found in Project Settings).", + "schema": { + "type": "string" + }, + "required": true, + "example": "gh/CircleCI-Public/api-preview-docs", + "allowReserved": true + }, + { + "in": "path", + "name": "workflow-name", + "description": "The name of the workflow.", + "schema": { + "type": "string" + }, + "required": true, + "example": "build-and-test" + }, + { + "in": "query", + "name": "all-branches", + "description": "Whether to retrieve data for all branches combined. Use either this parameter OR the branch name parameter.", + "schema": { + "type": "boolean" + }, + "required": false + }, + { + "in": "query", + "name": "branch", + "description": "The name of a vcs branch. If not passed we will scope the API call to the default branch.", + "schema": { + "type": "string" + }, + "required": false + }, + { + "in": "query", + "name": "page-token", + "description": "A token to retrieve the next page of results.", + "schema": { + "type": "string" + }, + "required": false, + "allowEmptyValue": true + }, + { + "in": "query", + "name": "start-date", + "description": "Include only executions that started at or after this date. This must be specified if an end-date is provided.", + "schema": { + "type": "string", + "format": "date-time" + }, + "required": false, + "example": "2020-08-21T13:26:29Z" + }, + { + "in": "query", + "name": "end-date", + "description": "Include only executions that started before this date. This date can be at most 90 days after the start-date.", + "schema": { + "type": "string", + "format": "date-time" + }, + "required": false, + "example": "2020-09-04T13:26:29Z" + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url \"https://circleci.com/api/v2/insights/gh/CircleCI-Public/api-preview-docs/workflows/build-and-test?all-branches=true&branch=example-value&page-token=example-value&start-date=2020-08-21T13%3A26%3A29Z&end-date=2020-09-04T13%3A26%3A29Z\" \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/insights/gh/CircleCI-Public/api-preview-docs/workflows/build-and-test?all-branches=true&branch=example-value&page-token=example-value&start-date=2020-08-21T13%3A26%3A29Z&end-date=2020-09-04T13%3A26%3A29Z';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/insights/gh/CircleCI-Public/api-preview-docs/workflows/build-and-test?all-branches=true&branch=example-value&page-token=example-value&start-date=2020-08-21T13%3A26%3A29Z&end-date=2020-09-04T13%3A26%3A29Z\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/insights/gh/CircleCI-Public/api-preview-docs/workflows/build-and-test?all-branches=true&branch=example-value&page-token=example-value&start-date=2020-08-21T13%3A26%3A29Z&end-date=2020-09-04T13%3A26%3A29Z\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/insights/gh/CircleCI-Public/api-preview-docs/workflows/build-and-test?all-branches=true&branch=example-value&page-token=example-value&start-date=2020-08-21T13%3A26%3A29Z&end-date=2020-09-04T13%3A26%3A29Z\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/insights/{project-slug}/workflows/{workflow-name}/jobs": { + "get": { + "summary": "Get summary metrics for a project workflow's jobs.", + "description": "Get summary metrics for a project workflow's jobs. Job runs going back at most 90 days are included in the aggregation window. Metrics are refreshed daily, and thus may not include executions from the last 24 hours. Please note that Insights is not a financial reporting tool and should not be used for precise credit reporting. Credit reporting from Insights does not use the same source of truth as the billing information that is found in the Plan Overview page in the CircleCI UI, nor does the underlying data have the same data accuracy guarantees as the billing information in the CircleCI UI. This may lead to discrepancies between credits reported from Insights and the billing information in the Plan Overview page of the CircleCI UI. For precise credit reporting, always use the Plan Overview page in the CircleCI UI.", + "tags": [ + "Insights" + ], + "operationId": "getProjectWorkflowJobMetrics", + "responses": { + "200": { + "description": "A paginated list of summary metrics by workflow job.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of the job." + }, + "metrics": { + "type": "object", + "properties": { + "total_runs": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The total number of runs, including runs that are still on-hold or running." + }, + "failed_runs": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The number of failed runs." + }, + "successful_runs": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The number of successful runs." + }, + "duration_metrics": { + "type": "object", + "properties": { + "min": { + "type": "integer", + "format": "int64", + "minimum": 0, + "x-nullable": true, + "description": "The minimum duration, in seconds, among a group of runs." + }, + "mean": { + "type": "integer", + "format": "int64", + "minimum": 0, + "x-nullable": true, + "description": "The mean duration, in seconds, among a group of runs." + }, + "median": { + "type": "integer", + "format": "int64", + "minimum": 0, + "x-nullable": true, + "description": "The median duration, in seconds, among a group of runs." + }, + "p95": { + "type": "integer", + "format": "int64", + "minimum": 0, + "x-nullable": true, + "description": "The 95th percentile duration, in seconds, among a group of runs." + }, + "max": { + "type": "integer", + "format": "int64", + "minimum": 0, + "x-nullable": true, + "description": "The max duration, in seconds, among a group of runs." + }, + "standard_deviation": { + "type": "number", + "format": "float", + "x-nullable": true, + "description": "The standard deviation, in seconds, among a group of runs." + } + }, + "required": [ + "min", + "mean", + "median", + "p95", + "max", + "standard_deviation" + ], + "description": "Metrics relating to the duration of runs for a workflow job." + }, + "success_rate": { + "type": "number", + "format": "float" + }, + "total_credits_used": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The total credits consumed by the job in the aggregation window. Note that Insights is not a real time financial reporting tool and should not be used for credit reporting." + }, + "throughput": { + "type": "number", + "format": "float", + "description": "The average number of runs per day." + } + }, + "required": [ + "total_runs", + "failed_runs", + "successful_runs", + "duration_metrics", + "success_rate", + "total_credits_used", + "throughput" + ], + "description": "Metrics relating to a workflow job's runs." + }, + "window_start": { + "type": "string", + "format": "date-time", + "description": "The timestamp of the first build within the requested reporting window." + }, + "window_end": { + "type": "string", + "format": "date-time", + "description": "The timestamp of the last build within the requested reporting window." + } + }, + "required": [ + "name", + "metrics", + "window_start", + "window_end" + ] + }, + "description": "Job summary metrics." + }, + "next_page_token": { + "type": "string", + "x-nullable": true, + "description": "A token to pass as a `page-token` query parameter to return the next page of results." + } + }, + "required": [ + "items", + "next_page_token" + ], + "description": "Paginated workflow job summary metrics." + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "project-slug", + "description": "Project slug in the form `vcs-slug/org-name/repo-name`. The `/` characters may be URL-escaped. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug`, replace `org-name` with the organization ID (found in Organization Settings), and replace `repo-name` with the project ID (found in Project Settings).", + "schema": { + "type": "string" + }, + "required": true, + "example": "gh/CircleCI-Public/api-preview-docs", + "allowReserved": true + }, + { + "in": "path", + "name": "workflow-name", + "description": "The name of the workflow.", + "schema": { + "type": "string" + }, + "required": true, + "example": "build-and-test" + }, + { + "in": "query", + "name": "page-token", + "description": "A token to retrieve the next page of results.", + "schema": { + "type": "string" + }, + "required": false, + "allowEmptyValue": true + }, + { + "in": "query", + "name": "all-branches", + "description": "Whether to retrieve data for all branches combined. Use either this parameter OR the branch name parameter.", + "schema": { + "type": "boolean" + }, + "required": false + }, + { + "in": "query", + "name": "branch", + "description": "The name of a vcs branch. If not passed we will scope the API call to the default branch.", + "schema": { + "type": "string" + }, + "required": false + }, + { + "in": "query", + "name": "reporting-window", + "description": "The time window used to calculate summary metrics. If not provided, defaults to last-90-days", + "schema": { + "type": "string" + }, + "required": false, + "example": "last-90-days" + }, + { + "in": "query", + "name": "job-name", + "description": "The name of the jobs you would like to filter from your workflow. If not specified, all workflow jobs will be returned. The job name can either be the full job name or just a substring of the job name.", + "schema": { + "type": "string" + }, + "required": false, + "example": "lint" + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url \"https://circleci.com/api/v2/insights/gh/CircleCI-Public/api-preview-docs/workflows/build-and-test/jobs?page-token=example-value&all-branches=true&branch=example-value&reporting-window=last-90-days&job-name=lint\" \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/insights/gh/CircleCI-Public/api-preview-docs/workflows/build-and-test/jobs?page-token=example-value&all-branches=true&branch=example-value&reporting-window=last-90-days&job-name=lint';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/insights/gh/CircleCI-Public/api-preview-docs/workflows/build-and-test/jobs?page-token=example-value&all-branches=true&branch=example-value&reporting-window=last-90-days&job-name=lint\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/insights/gh/CircleCI-Public/api-preview-docs/workflows/build-and-test/jobs?page-token=example-value&all-branches=true&branch=example-value&reporting-window=last-90-days&job-name=lint\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/insights/gh/CircleCI-Public/api-preview-docs/workflows/build-and-test/jobs?page-token=example-value&all-branches=true&branch=example-value&reporting-window=last-90-days&job-name=lint\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/insights/{project-slug}/workflows/{workflow-name}/summary": { + "get": { + "summary": "Get metrics and trends for workflows", + "description": "Get the metrics and trends for a particular workflow on a single branch or all branches", + "tags": [ + "Insights" + ], + "operationId": "getWorkflowSummary", + "responses": { + "200": { + "description": "Metrics and trends for a workflow", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "metrics": { + "type": "object", + "properties": { + "total_runs": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The total number of runs, including runs that are still on-hold or running." + }, + "successful_runs": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The number of successful runs." + }, + "mttr": { + "type": "integer", + "format": "int64", + "minimum": 0, + "x-nullable": true, + "description": "The mean time to recovery (mean time between failures and their next success) in seconds." + }, + "total_credits_used": { + "type": "integer", + "format": "int64", + "minimum": 0, + "x-nullable": true, + "description": "The total credits consumed by the workflow in the aggregation window. Note that Insights is not a real time financial reporting tool and should not be used for credit reporting." + }, + "failed_runs": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The number of failed runs." + }, + "success_rate": { + "type": "number", + "format": "float" + }, + "completed_runs": { + "type": "integer", + "format": "int64", + "minimum": 0, + "x-nullable": true, + "description": "The number of runs that ran to completion within the aggregation window" + }, + "window_start": { + "type": "string", + "format": "date-time", + "description": "The timestamp of the first build within the requested reporting window." + }, + "duration_metrics": { + "type": "object", + "properties": { + "min": { + "type": "integer", + "format": "int64", + "minimum": 0, + "x-nullable": true, + "description": "The minimum duration, in seconds, among a group of runs." + }, + "mean": { + "type": "integer", + "format": "int64", + "minimum": 0, + "x-nullable": true, + "description": "The mean duration, in seconds, among a group of runs." + }, + "median": { + "type": "integer", + "format": "int64", + "minimum": 0, + "x-nullable": true, + "description": "The median duration, in seconds, among a group of runs." + }, + "p95": { + "type": "integer", + "format": "int64", + "minimum": 0, + "x-nullable": true, + "description": "The 95th percentile duration, in seconds, among a group of runs." + }, + "max": { + "type": "integer", + "format": "int64", + "minimum": 0, + "x-nullable": true, + "description": "The max duration, in seconds, among a group of runs." + }, + "standard_deviation": { + "type": "number", + "format": "float", + "x-nullable": true, + "description": "The standard deviation, in seconds, among a group of runs." + } + }, + "required": [ + "min", + "mean", + "median", + "p95", + "max", + "standard_deviation" + ], + "description": "Metrics relating to the duration of runs for a workflow." + }, + "window_end": { + "type": "string", + "format": "date-time", + "description": "The timestamp of the last build within the requested reporting window." + }, + "throughput": { + "type": "number", + "format": "float", + "description": "The average number of runs per day." + } + }, + "required": [ + "total_runs", + "successful_runs", + "mttr", + "total_credits_used", + "failed_runs", + "success_rate", + "window_start", + "duration_metrics", + "window_end", + "throughput", + "completed_runs" + ], + "description": "Metrics aggregated across a workflow for a given time window." + }, + "trends": { + "type": "object", + "properties": { + "total_runs": { + "type": "number", + "format": "float", + "description": "The trend value for total number of runs." + }, + "failed_runs": { + "type": "number", + "format": "float", + "description": "The trend value for number of failed runs." + }, + "success_rate": { + "type": "number", + "format": "float", + "description": "The trend value for the success rate." + }, + "p95_duration_secs": { + "type": "number", + "format": "float", + "description": "Trend value for the 95th percentile duration for a workflow for a given time window." + }, + "median_duration_secs": { + "type": "number", + "format": "float", + "description": "Trend value for the 50th percentile duration for a workflow for a given time window." + }, + "total_credits_used": { + "type": "number", + "format": "float", + "description": "The trend value for total credits consumed." + }, + "mttr": { + "type": "number", + "format": "float", + "description": "trend for mean time to recovery (mean time between failures and their next success)." + }, + "throughput": { + "type": "number", + "format": "float", + "description": "Trend value for the average number of runs per day." + } + }, + "required": [ + "total_runs", + "failed_runs", + "success_rate", + "p95_duration_secs", + "median_duration_secs", + "total_credits_used", + "mttr", + "throughput" + ], + "description": "Trends for aggregated metrics across a workflow for a given time window." + }, + "workflow_names": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of all the workflow names for a given project." + } + }, + "required": [ + "metrics", + "trends", + "workflow_names" + ], + "description": "Workflow level aggregated metrics and trends response" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "project-slug", + "description": "Project slug in the form `vcs-slug/org-name/repo-name`. The `/` characters may be URL-escaped. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug`, replace `org-name` with the organization ID (found in Organization Settings), and replace `repo-name` with the project ID (found in Project Settings).", + "schema": { + "type": "string" + }, + "required": true, + "example": "gh/CircleCI-Public/api-preview-docs", + "allowReserved": true + }, + { + "in": "path", + "name": "workflow-name", + "description": "The name of the workflow.", + "schema": { + "type": "string" + }, + "required": true, + "example": "build-and-test" + }, + { + "in": "query", + "name": "all-branches", + "description": "Whether to retrieve data for all branches combined. Use either this parameter OR the branch name parameter.", + "schema": { + "type": "boolean" + }, + "required": false + }, + { + "in": "query", + "name": "branch", + "description": "The name of a vcs branch. If not passed we will scope the API call to the default branch.", + "schema": { + "type": "string" + }, + "required": false + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url \"https://circleci.com/api/v2/insights/gh/CircleCI-Public/api-preview-docs/workflows/build-and-test/summary?all-branches=true&branch=example-value\" \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/insights/gh/CircleCI-Public/api-preview-docs/workflows/build-and-test/summary?all-branches=true&branch=example-value';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/insights/gh/CircleCI-Public/api-preview-docs/workflows/build-and-test/summary?all-branches=true&branch=example-value\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/insights/gh/CircleCI-Public/api-preview-docs/workflows/build-and-test/summary?all-branches=true&branch=example-value\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/insights/gh/CircleCI-Public/api-preview-docs/workflows/build-and-test/summary?all-branches=true&branch=example-value\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/insights/{project-slug}/workflows/{workflow-name}/test-metrics": { + "get": { + "summary": "Get test metrics for a project's workflows", + "description": "Get test metrics for a project's workflows. Currently tests metrics are calculated based on 10 most recent workflow runs.", + "tags": [ + "Insights" + ], + "operationId": "getProjectWorkflowTestMetrics", + "responses": { + "200": { + "description": "A list of test metrics by workflow", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "average_test_count": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The average number of tests executed per run" + }, + "most_failed_tests": { + "type": "array", + "items": { + "type": "object", + "properties": { + "p95_duration": { + "type": "number", + "format": "double", + "x-nullable": true, + "description": "The 95th percentile duration, in seconds, among a group of test runs." + }, + "total_runs": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The total number of times the test was run." + }, + "classname": { + "type": "string", + "x-nullable": true, + "description": "The class the test belongs to." + }, + "failed_runs": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The number of times the test failed" + }, + "flaky": { + "type": "boolean", + "description": "Whether the test is flaky." + }, + "source": { + "type": "string", + "x-nullable": true, + "description": "The source of the test." + }, + "file": { + "type": "string", + "x-nullable": true, + "description": "The file the test belongs to." + }, + "job_name": { + "type": "string", + "description": "The name of the job." + }, + "test_name": { + "type": "string", + "description": "The name of the test." + } + }, + "required": [ + "failed_runs", + "job_name", + "p95_duration", + "test_name", + "file", + "source", + "classname", + "total_runs", + "flaky" + ] + }, + "description": "Metrics for the most frequently failing tests" + }, + "most_failed_tests_extra": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The number of tests with the same success rate being omitted from most_failed_tests" + }, + "slowest_tests": { + "type": "array", + "items": { + "type": "object", + "properties": { + "p95_duration": { + "type": "number", + "format": "double", + "x-nullable": true, + "description": "The 95th percentile duration, in seconds, among a group of test runs." + }, + "total_runs": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The total number of times the test was run." + }, + "classname": { + "type": "string", + "x-nullable": true, + "description": "The class the test belongs to." + }, + "failed_runs": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The number of times the test failed" + }, + "flaky": { + "type": "boolean", + "description": "Whether the test is flaky." + }, + "source": { + "type": "string", + "x-nullable": true, + "description": "The source of the test." + }, + "file": { + "type": "string", + "x-nullable": true, + "description": "The file the test belongs to." + }, + "job_name": { + "type": "string", + "description": "The name of the job." + }, + "test_name": { + "type": "string", + "description": "The name of the test." + } + }, + "required": [ + "failed_runs", + "job_name", + "p95_duration", + "test_name", + "file", + "source", + "classname", + "total_runs", + "flaky" + ] + }, + "description": "Metrics for the slowest running tests" + }, + "slowest_tests_extra": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The number of tests with the same duration rate being omitted from slowest_tests" + }, + "total_test_runs": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The total number of test runs" + }, + "test_runs": { + "type": "array", + "items": { + "type": "object", + "properties": { + "pipeline_number": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The number of the pipeline associated with the provided test counts" + }, + "workflow_id": { + "description": "The ID of the workflow associated with the provided test counts" + }, + "success_rate": { + "type": "number", + "format": "float", + "description": "The success rate calculated from test counts" + }, + "test_counts": { + "type": "object", + "properties": { + "error": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The number of tests with the error status" + }, + "failure": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The number of tests with the failure status" + }, + "skipped": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The number of tests with the skipped status" + }, + "success": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The number of tests with the success status" + }, + "total": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The total number of tests" + } + }, + "required": [ + "error", + "failure", + "skipped", + "success", + "total" + ], + "description": "Test counts for a given pipeline number" + } + }, + "required": [ + "pipeline_number", + "workflow_id", + "success_rate", + "test_counts" + ] + }, + "description": "Test counts grouped by pipeline number and workflow id" + } + }, + "required": [ + "average_test_count", + "most_failed_tests", + "most_failed_tests_extra", + "slowest_tests", + "slowest_tests_extra", + "total_test_runs", + "test_runs" + ], + "description": "Project level test metrics response" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "project-slug", + "description": "Project slug in the form `vcs-slug/org-name/repo-name`. The `/` characters may be URL-escaped. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug`, replace `org-name` with the organization ID (found in Organization Settings), and replace `repo-name` with the project ID (found in Project Settings).", + "schema": { + "type": "string" + }, + "required": true, + "example": "gh/CircleCI-Public/api-preview-docs", + "allowReserved": true + }, + { + "in": "path", + "name": "workflow-name", + "description": "The name of the workflow.", + "schema": { + "type": "string" + }, + "required": true, + "example": "build-and-test" + }, + { + "in": "query", + "name": "branch", + "description": "The name of a vcs branch. If not passed we will scope the API call to the default branch.", + "schema": { + "type": "string" + }, + "required": false + }, + { + "in": "query", + "name": "all-branches", + "description": "Whether to retrieve data for all branches combined. Use either this parameter OR the branch name parameter.", + "schema": { + "type": "boolean" + }, + "required": false + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url \"https://circleci.com/api/v2/insights/gh/CircleCI-Public/api-preview-docs/workflows/build-and-test/test-metrics?branch=example-value&all-branches=true\" \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/insights/gh/CircleCI-Public/api-preview-docs/workflows/build-and-test/test-metrics?branch=example-value&all-branches=true';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/insights/gh/CircleCI-Public/api-preview-docs/workflows/build-and-test/test-metrics?branch=example-value&all-branches=true\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/insights/gh/CircleCI-Public/api-preview-docs/workflows/build-and-test/test-metrics?branch=example-value&all-branches=true\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/insights/gh/CircleCI-Public/api-preview-docs/workflows/build-and-test/test-metrics?branch=example-value&all-branches=true\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/jobs/{job-id}/cancel": { + "post": { + "summary": "Cancel job by job ID", + "description": "Cancel job with a given job ID.", + "tags": [ + "Job" + ], + "operationId": "cancelJobByJobID", + "responses": { + "200": { + "description": "Job cancelled successfully.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "A human-readable message" + } + }, + "required": [ + "message" + ], + "description": "message response", + "title": "MessageResponse" + } + } + } + }, + "400": { + "description": "Bad request error.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "A human-readable message" + } + }, + "required": [ + "message" + ], + "description": "message response", + "title": "MessageResponse" + } + } + } + }, + "401": { + "description": "Unauthorized error.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "A human-readable message" + } + }, + "required": [ + "message" + ], + "description": "message response", + "title": "MessageResponse" + } + } + } + }, + "403": { + "description": "Forbidden error.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "A human-readable message" + } + }, + "required": [ + "message" + ], + "description": "message response", + "title": "MessageResponse" + } + } + } + }, + "404": { + "description": "Job not found error.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "A human-readable message" + } + }, + "required": [ + "message" + ], + "description": "message response", + "title": "MessageResponse" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "job-id", + "description": "The unique ID of the job.", + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request POST \\\n --url https://circleci.com/api/v2/jobs/497f6eca-6276-4993-bfeb-53cbbbba6f08/cancel \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/jobs/497f6eca-6276-4993-bfeb-53cbbbba6f08/cancel';\n const options = {method: 'POST', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"POST\", \"/api/v2/jobs/497f6eca-6276-4993-bfeb-53cbbbba6f08/cancel\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/jobs/497f6eca-6276-4993-bfeb-53cbbbba6f08/cancel\"\n\n\treq, _ := http.NewRequest(\"POST\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/jobs/497f6eca-6276-4993-bfeb-53cbbbba6f08/cancel\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Post.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/me": { + "get": { + "summary": "User Information", + "description": "Provides information about the user that is currently signed in.", + "tags": [ + "User" + ], + "operationId": "getCurrentUser", + "responses": { + "200": { + "description": "User login information.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "avatar_url": { + "type": "string", + "x-nullable": true, + "description": "URL to the user's avatar on the VCS" + }, + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the user." + }, + "login": { + "type": "string", + "description": "The login information for the user on the VCS.", + "title": "Login" + }, + "name": { + "type": "string", + "description": "The name of the user." + } + }, + "required": [ + "avatar_url", + "id", + "login", + "name" + ], + "title": "User" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/me \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/me';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/me\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/me\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/me\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/me/collaborations": { + "get": { + "summary": "Collaborations", + "description": "Provides the set of organizations of which a user is a member or a collaborator.\n\nThe set of organizations that a user can collaborate on is composed of:\n\n* Organizations that the current user belongs to across VCS types (e.g. BitBucket, GitHub)\n* The parent organization of repository that the user can collaborate on, but is not necessarily a member of\n* The organization of the current user's account", + "tags": [ + "User" + ], + "operationId": "getCollaborations", + "responses": { + "200": { + "description": "Collaborations", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "x-nullable": true, + "description": "The UUID of the organization" + }, + "vcs-type": { + "type": "string", + "description": "The VCS provider" + }, + "name": { + "type": "string", + "description": "The name of the organization" + }, + "avatar_url": { + "type": "string", + "description": "URL to the user's avatar on the VCS" + }, + "slug": { + "type": "string", + "description": "The slug of the organization" + } + }, + "required": [ + "id", + "vcs-type", + "name", + "avatar_url", + "slug" + ], + "title": "Collaboration" + } + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/me/collaborations \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/me/collaborations';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/me/collaborations\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/me/collaborations\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/me/collaborations\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/organization": { + "post": { + "summary": "Create a new organization", + "description": "Create a new organization. For VCS providers (GitHub/Bitbucket), this validates access and syncs org data. For standalone orgs, this creates a new CircleCI organization.", + "tags": [ + "Organization" + ], + "operationId": "createOrganization", + "responses": { + "201": { + "description": "The newly created organization", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The unique ID of the organization." + }, + "name": { + "type": "string", + "description": "The name of the organization." + }, + "slug": { + "type": "string", + "description": "Org slug in the form `vcs-slug/org-name`. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug` and replace the `org-name` with the organization ID (found in Organization Settings)." + }, + "vcs_type": { + "type": "string", + "description": "The version control system type for the organization.", + "example": "github" + } + }, + "required": [ + "id", + "name", + "slug", + "vcs_type" + ] + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of the organization." + }, + "vcs_type": { + "type": "string", + "description": "The version control system type for the organization.", + "example": "github" + } + }, + "required": [ + "name", + "vcs_type" + ] + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request POST \\\n --url https://circleci.com/api/v2/organization \\\n --header \"Circle-Token: $CIRCLE_TOKEN\" \\\n --header \"Content-Type: application/json\" \\\n --data \"{\n \\\"name\\\": \\\"example-string\\\",\n \\\"vcs_type\\\": \\\"github\\\"\n}\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/organization';\n const options = {\n method: 'POST',\n headers: {'Circle-Token': '$CIRCLE_TOKEN', 'Content-Type': 'application/json'},\n body: '{\"name\":\"example-string\",\"vcs_type\":\"github\"}'\n };\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\npayload = \"{\\n \\\"name\\\": \\\"example-string\\\",\\n \\\"vcs_type\\\": \\\"github\\\"\\n}\"\n\nheaders = {\n 'Circle-Token': \"$CIRCLE_TOKEN\",\n 'Content-Type': \"application/json\"\n}\n\nconn.request(\"POST\", \"/api/v2/organization\", payload, headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/organization\"\n\n\tpayload := strings.NewReader(\"{\\n \\\"name\\\": \\\"example-string\\\",\\n \\\"vcs_type\\\": \\\"github\\\"\\n}\")\n\n\treq, _ := http.NewRequest(\"POST\", url, payload)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/organization\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Post.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\nrequest[\"Content-Type\"] = 'application/json'\nrequest.body = \"{\\n \\\"name\\\": \\\"example-string\\\",\\n \\\"vcs_type\\\": \\\"github\\\"\\n}\"\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/organization/{org-slug-or-id}": { + "delete": { + "summary": "Delete an organization", + "description": "Delete an organization. This action will delete all projects including all build data for the organization.", + "tags": [ + "Organization" + ], + "operationId": "deleteOrganization", + "responses": { + "202": { + "description": "A confirmation message.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "A human-readable message" + } + }, + "required": [ + "message" + ], + "description": "message response", + "title": "MessageResponse" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "org-slug-or-id", + "description": "Org UUID or slug in the form `vcs-slug/org-name`. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug` and replace the `org-name` with the organization ID (found in Organization Settings).", + "schema": { + "type": "string" + }, + "required": true, + "example": "gh/CircleCI-Public" + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request DELETE \\\n --url https://circleci.com/api/v2/organization/gh/CircleCI-Public \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/organization/gh/CircleCI-Public';\n const options = {method: 'DELETE', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"DELETE\", \"/api/v2/organization/gh/CircleCI-Public\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/organization/gh/CircleCI-Public\"\n\n\treq, _ := http.NewRequest(\"DELETE\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/organization/gh/CircleCI-Public\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Delete.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/organization/{org-slug-or-id}/project": { + "post": { + "summary": "Create a new project", + "description": "Create a new project. Works for all organization types.", + "tags": [ + "Project" + ], + "operationId": "createProject", + "responses": { + "200": { + "description": "The new project", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "slug": { + "type": "string", + "description": "Project slug in the form `vcs-slug/org-name/repo-name`. The `/` characters may be URL-escaped. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug`, replace `org-name` with the organization ID (found in Organization Settings), and replace `repo-name` with the project ID (found in Project Settings).", + "example": "gh/CircleCI-Public/api-preview-docs" + }, + "name": { + "type": "string", + "description": "The name of the project", + "example": "api-preview-docs" + }, + "id": { + "type": "string", + "format": "uuid" + }, + "organization_name": { + "type": "string", + "description": "The name of the organization the project belongs to", + "example": "CircleCI-Public" + }, + "organization_slug": { + "type": "string", + "description": "The slug of the organization the project belongs to", + "example": "gh/CircleCI-Public" + }, + "organization_id": { + "type": "string", + "format": "uuid", + "description": "The id of the organization the project belongs to", + "example": "ec6887ec-7d44-4b31-b468-7e552408ee32" + }, + "vcs_info": { + "type": "object", + "properties": { + "vcs_url": { + "type": "string", + "description": "URL to the repository hosting the project's code", + "example": "https://github.com/CircleCI-Public/api-preview-docs" + }, + "provider": { + "type": "string", + "description": "The VCS provider" + }, + "default_branch": { + "type": "string", + "example": "main" + } + }, + "required": [ + "vcs_url", + "provider", + "default_branch" + ], + "description": "Information about the VCS that hosts the project source code." + } + }, + "required": [ + "slug", + "name", + "id", + "organization_name", + "organization_slug", + "organization_id", + "vcs_info" + ], + "description": "NOTE: The definition of Project is subject to change.", + "title": "Project" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "org-slug-or-id", + "description": "Org UUID or slug in the form `vcs-slug/org-name`. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug` and replace the `org-name` with the organization ID (found in Organization Settings).", + "schema": { + "type": "string" + }, + "required": true, + "example": "gh/CircleCI-Public" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of the project", + "example": "api-preview-docs" + } + }, + "required": [ + "name" + ] + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request POST \\\n --url https://circleci.com/api/v2/organization/gh/CircleCI-Public/project \\\n --header \"Circle-Token: $CIRCLE_TOKEN\" \\\n --header \"Content-Type: application/json\" \\\n --data \"{\n \\\"name\\\": \\\"api-preview-docs\\\"\n}\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/organization/gh/CircleCI-Public/project';\n const options = {\n method: 'POST',\n headers: {'Circle-Token': '$CIRCLE_TOKEN', 'Content-Type': 'application/json'},\n body: '{\"name\":\"api-preview-docs\"}'\n };\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\npayload = \"{\\n \\\"name\\\": \\\"api-preview-docs\\\"\\n}\"\n\nheaders = {\n 'Circle-Token': \"$CIRCLE_TOKEN\",\n 'Content-Type': \"application/json\"\n}\n\nconn.request(\"POST\", \"/api/v2/organization/gh/CircleCI-Public/project\", payload, headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/organization/gh/CircleCI-Public/project\"\n\n\tpayload := strings.NewReader(\"{\\n \\\"name\\\": \\\"api-preview-docs\\\"\\n}\")\n\n\treq, _ := http.NewRequest(\"POST\", url, payload)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/organization/gh/CircleCI-Public/project\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Post.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\nrequest[\"Content-Type\"] = 'application/json'\nrequest.body = \"{\\n \\\"name\\\": \\\"api-preview-docs\\\"\\n}\"\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/organization/{org-slug-or-id}/url-orb-allow-list": { + "post": { + "summary": "Create a new URL Orb allow-list entry", + "description": "Create a new URL Orb allow-list entry", + "tags": [ + "Organization" + ], + "operationId": "createURLOrbAllowListEntry", + "responses": { + "200": { + "description": "The ID of the new URL Orb allow-list entry", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "URL orb allow-list entry UUID.", + "example": "ba98990a-5a00-4cad-b55e-b44117b92e0c" + }, + "message": { + "type": "string", + "description": "Message describing the outcome of an operation", + "example": "Created." + } + }, + "required": [ + "id", + "message" + ] + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "org-slug-or-id", + "description": "Org UUID or slug in the form `vcs-slug/org-name`. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug` and replace the `org-name` with the organization ID (found in Organization Settings).", + "schema": { + "type": "string" + }, + "required": true, + "example": "gh/CircleCI-Public" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of the URL orb allow-list entry.", + "example": "Allow URL orbs from raw.githubusercontent.com/CircleCI-Public" + }, + "prefix": { + "description": "URL prefix. URL orb references that start with this prefix will be allowed by this allow-list entry.", + "example": "https://raw.githubusercontent.com/CircleCI-Public/orbs/refs/heads/main/" + }, + "auth": { + "type": "string", + "description": "An authentication method to use for fetching URL orb references that match this allow-list entry's prefix. Allowed values are \"bitbucket-oauth\", \"github-oauth\", \"github-app\", or \"none\".", + "example": "github-app" + } + }, + "required": [ + "name", + "prefix", + "auth" + ] + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request POST \\\n --url https://circleci.com/api/v2/organization/gh/CircleCI-Public/url-orb-allow-list \\\n --header \"Circle-Token: $CIRCLE_TOKEN\" \\\n --header \"Content-Type: application/json\" \\\n --data \"{\n \\\"name\\\": \\\"Allow URL orbs from raw.githubusercontent.com/CircleCI-Public\\\",\n \\\"prefix\\\": \\\"https://raw.githubusercontent.com/CircleCI-Public/orbs/refs/heads/main/\\\",\n \\\"auth\\\": \\\"github-app\\\"\n}\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/organization/gh/CircleCI-Public/url-orb-allow-list';\n const options = {\n method: 'POST',\n headers: {'Circle-Token': '$CIRCLE_TOKEN', 'Content-Type': 'application/json'},\n body: '{\"name\":\"Allow URL orbs from raw.githubusercontent.com/CircleCI-Public\",\"prefix\":\"https://raw.githubusercontent.com/CircleCI-Public/orbs/refs/heads/main/\",\"auth\":\"github-app\"}'\n };\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\npayload = \"{\\n \\\"name\\\": \\\"Allow URL orbs from raw.githubusercontent.com/CircleCI-Public\\\",\\n \\\"prefix\\\": \\\"https://raw.githubusercontent.com/CircleCI-Public/orbs/refs/heads/main/\\\",\\n \\\"auth\\\": \\\"github-app\\\"\\n}\"\n\nheaders = {\n 'Circle-Token': \"$CIRCLE_TOKEN\",\n 'Content-Type': \"application/json\"\n}\n\nconn.request(\"POST\", \"/api/v2/organization/gh/CircleCI-Public/url-orb-allow-list\", payload, headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/organization/gh/CircleCI-Public/url-orb-allow-list\"\n\n\tpayload := strings.NewReader(\"{\\n \\\"name\\\": \\\"Allow URL orbs from raw.githubusercontent.com/CircleCI-Public\\\",\\n \\\"prefix\\\": \\\"https://raw.githubusercontent.com/CircleCI-Public/orbs/refs/heads/main/\\\",\\n \\\"auth\\\": \\\"github-app\\\"\\n}\")\n\n\treq, _ := http.NewRequest(\"POST\", url, payload)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/organization/gh/CircleCI-Public/url-orb-allow-list\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Post.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\nrequest[\"Content-Type\"] = 'application/json'\nrequest.body = \"{\\n \\\"name\\\": \\\"Allow URL orbs from raw.githubusercontent.com/CircleCI-Public\\\",\\n \\\"prefix\\\": \\\"https://raw.githubusercontent.com/CircleCI-Public/orbs/refs/heads/main/\\\",\\n \\\"auth\\\": \\\"github-app\\\"\\n}\"\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + }, + "get": { + "summary": "List the entries in the org's URL Orb allow-list", + "description": "List the entries in the org's URL Orb allow-list", + "tags": [ + "Organization" + ], + "operationId": "listURLOrbAllowListEntries", + "responses": { + "200": { + "description": "URL Orb allow-list entries", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "URL orb allow-list entry UUID.", + "example": "ba98990a-5a00-4cad-b55e-b44117b92e0c" + }, + "name": { + "type": "string", + "description": "Name of the URL orb allow-list entry.", + "example": "Allow URL orbs from raw.githubusercontent.com/CircleCI-Public" + }, + "prefix": { + "description": "URL prefix. URL orb references that start with this prefix will be allowed by this allow-list entry.", + "example": "https://raw.githubusercontent.com/CircleCI-Public/orbs/refs/heads/main/" + }, + "auth": { + "type": "string", + "description": "An authentication method to use for fetching URL orb references that match this allow-list entry's prefix. Allowed values are \"bitbucket-oauth\", \"github-oauth\", \"github-app\", or \"none\".", + "example": "github-app" + } + }, + "required": [ + "id", + "name", + "prefix", + "auth" + ] + } + } + }, + "required": [ + "items" + ] + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "org-slug-or-id", + "description": "Org UUID or slug in the form `vcs-slug/org-name`. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug` and replace the `org-name` with the organization ID (found in Organization Settings).", + "schema": { + "type": "string" + }, + "required": true, + "example": "gh/CircleCI-Public" + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/organization/gh/CircleCI-Public/url-orb-allow-list \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/organization/gh/CircleCI-Public/url-orb-allow-list';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/organization/gh/CircleCI-Public/url-orb-allow-list\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/organization/gh/CircleCI-Public/url-orb-allow-list\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/organization/gh/CircleCI-Public/url-orb-allow-list\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/organization/{org-slug-or-id}/url-orb-allow-list/{allow-list-entry-id}": { + "delete": { + "summary": "Remove an entry from the org's URL orb allow-list", + "description": "Remove an entry from the org's URL orb allow-list", + "tags": [ + "Organization" + ], + "operationId": "removeURLOrbAllowListEntry", + "responses": { + "200": { + "description": "The ID of the removed URL Orb allow-list entry", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "URL orb allow-list entry UUID.", + "example": "ba98990a-5a00-4cad-b55e-b44117b92e0c" + }, + "message": { + "type": "string", + "description": "Message describing the outcome of an operation", + "example": "Created." + } + }, + "required": [ + "id", + "message" + ] + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "org-slug-or-id", + "description": "Org UUID or slug in the form `vcs-slug/org-name`. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug` and replace the `org-name` with the organization ID (found in Organization Settings).", + "schema": { + "type": "string" + }, + "required": true, + "example": "gh/CircleCI-Public" + }, + { + "in": "path", + "name": "allow-list-entry-id", + "description": "URL orb allow-list entry UUID.", + "schema": { + "type": "string" + }, + "required": true, + "example": "ba98990a-5a00-4cad-b55e-b44117b92e0c" + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request DELETE \\\n --url https://circleci.com/api/v2/organization/gh/CircleCI-Public/url-orb-allow-list/ba98990a-5a00-4cad-b55e-b44117b92e0c \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/organization/gh/CircleCI-Public/url-orb-allow-list/ba98990a-5a00-4cad-b55e-b44117b92e0c';\n const options = {method: 'DELETE', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"DELETE\", \"/api/v2/organization/gh/CircleCI-Public/url-orb-allow-list/ba98990a-5a00-4cad-b55e-b44117b92e0c\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/organization/gh/CircleCI-Public/url-orb-allow-list/ba98990a-5a00-4cad-b55e-b44117b92e0c\"\n\n\treq, _ := http.NewRequest(\"DELETE\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/organization/gh/CircleCI-Public/url-orb-allow-list/ba98990a-5a00-4cad-b55e-b44117b92e0c\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Delete.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/pipeline": { + "get": { + "summary": "Get a list of pipelines", + "description": "Returns all pipelines for the most recently built projects (max 250) you follow in an organization.", + "tags": [ + "Pipeline" + ], + "operationId": "listPipelines", + "responses": { + "200": { + "description": "A sequence of pipelines.", + "links": { + "NextPipelinePage": { + "operationId": "listPipelines", + "parameters": { + "page-token": "$response.body#/next_page_token" + } + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the pipeline.", + "example": "5034460f-c7c4-4c43-9457-de07e2029e7b" + }, + "errors": { + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The type of error." + }, + "message": { + "type": "string", + "description": "A human-readable error message." + } + }, + "required": [ + "type", + "message" + ], + "description": "An error with a type and message." + }, + "description": "A sequence of errors that have occurred within the pipeline." + }, + "project_slug": { + "type": "string", + "description": "The project-slug for the pipeline.", + "example": "gh/CircleCI-Public/api-preview-docs" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the pipeline was last updated." + }, + "number": { + "type": "integer", + "format": "int64", + "description": "The number of the pipeline.", + "example": 25 + }, + "trigger_parameters": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "integer", + "format": "int64" + }, + { + "type": "boolean" + }, + { + "type": "object" + } + ] + } + }, + "state": { + "type": "string", + "description": "The current state of the pipeline." + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the pipeline was created." + }, + "trigger": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The type of trigger." + }, + "received_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the trigger was received." + }, + "actor": { + "type": "object", + "properties": { + "login": { + "type": "string", + "description": "The login information for the user on the VCS.", + "title": "Login" + }, + "avatar_url": { + "type": "string", + "x-nullable": true, + "description": "URL to the user's avatar on the VCS" + } + }, + "required": [ + "login", + "avatar_url" + ], + "description": "The user who triggered the Pipeline." + } + }, + "required": [ + "type", + "received_at", + "actor" + ], + "description": "A summary of the trigger." + }, + "vcs": { + "type": "object", + "properties": { + "provider_name": { + "type": "string", + "description": "Name of the VCS provider (e.g. GitHub, Bitbucket).", + "example": "GitHub" + }, + "target_repository_url": { + "type": "string", + "description": "URL for the repository the trigger targets (i.e. the repository where the PR will be merged). For fork-PR pipelines, this is the URL to the parent repo. For other pipelines, the `origin_` and `target_repository_url`s will be the same.", + "example": "https://github.com/CircleCI-Public/api-preview-docs" + }, + "branch": { + "type": "string", + "description": "The branch where the pipeline ran. The HEAD commit on this branch was used for the pipeline. Note that `branch` and `tag` are mutually exclusive. To trigger a pipeline for a PR by number use `pull//head` for the PR ref or `pull//merge` for the merge ref (GitHub only).", + "example": "feature/design-new-api" + }, + "review_id": { + "type": "string", + "description": "The code review id.", + "example": "123" + }, + "review_url": { + "type": "string", + "description": "The code review URL.", + "example": "https://github.com/CircleCI-Public/api-preview-docs/pull/123" + }, + "revision": { + "type": "string", + "x-nullable": true, + "description": "The code revision the pipeline ran.", + "example": "f454a02b5d10fcccfd7d9dd7608a76d6493a98b4" + }, + "tag": { + "type": "string", + "description": "The tag used by the pipeline. The commit that this tag points to was used for the pipeline. Note that `branch` and `tag` are mutually exclusive.", + "example": "v3.1.4159" + }, + "commit": { + "type": "object", + "properties": { + "subject": { + "type": "string", + "x-nullable": true, + "description": "The subject of the commit message." + }, + "body": { + "type": "string", + "x-nullable": true, + "description": "The body of the commit message." + } + }, + "required": [ + "subject", + "body" + ], + "description": "The latest commit in the pipeline." + }, + "origin_repository_url": { + "type": "string", + "description": "URL for the repository where the trigger originated. For fork-PR pipelines, this is the URL to the fork. For other pipelines the `origin_` and `target_repository_url`s will be the same.", + "example": "https://github.com/CircleCI-Public/api-preview-docs" + } + }, + "required": [ + "provider_name", + "origin_repository_url", + "target_repository_url", + "revision" + ], + "description": "VCS information for the pipeline." + } + }, + "required": [ + "id", + "number", + "project_slug", + "created_at", + "errors", + "state", + "trigger" + ], + "description": "A pipeline response.", + "title": "Pipeline" + } + }, + "next_page_token": { + "type": "string", + "x-nullable": true, + "description": "A token to pass as a `page-token` query parameter to return the next page of results." + } + }, + "required": [ + "items", + "next_page_token" + ], + "description": "List of pipelines", + "title": "PipelineListResponse" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "query", + "name": "org-slug", + "description": "Org slug in the form `vcs-slug/org-name`. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug` and replace the `org-name` with the organization ID (found in Organization Settings).", + "schema": { + "type": "string" + }, + "required": false, + "example": "gh/CircleCI-Public" + }, + { + "in": "query", + "name": "page-token", + "description": "A token to retrieve the next page of results.", + "schema": { + "type": "string" + }, + "required": false, + "allowEmptyValue": true + }, + { + "in": "query", + "name": "mine", + "description": "Only include entries created by your user.", + "schema": { + "type": "boolean" + }, + "required": false + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url \"https://circleci.com/api/v2/pipeline?org-slug=gh%2FCircleCI-Public&page-token=example-value&mine=true\" \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/pipeline?org-slug=gh%2FCircleCI-Public&page-token=example-value&mine=true';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/pipeline?org-slug=gh%2FCircleCI-Public&page-token=example-value&mine=true\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/pipeline?org-slug=gh%2FCircleCI-Public&page-token=example-value&mine=true\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/pipeline?org-slug=gh%2FCircleCI-Public&page-token=example-value&mine=true\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/pipeline/continue": { + "post": { + "summary": "Continue a pipeline", + "description": "Continue a pipeline from the setup phase. For information on using pipeline parameters with dynamic configuration, see the [Pipeline values and parameters](https://circleci.com/docs/pipeline-variables/#pipeline-parameters-and-dynamic-configuration) docs.", + "tags": [ + "Pipeline" + ], + "operationId": "continuePipeline", + "responses": { + "200": { + "description": "A confirmation message.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "A human-readable message" + } + }, + "required": [ + "message" + ], + "description": "message response", + "title": "MessageResponse" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "continuation-key": { + "type": "string", + "description": "A pipeline continuation key.", + "title": "PipelineContinuationKey" + }, + "configuration": { + "type": "string", + "description": "A configuration string for the pipeline." + }, + "parameters": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "boolean" + } + ] + }, + "description": "An object containing pipeline parameters and their values. Pipeline parameters have the following size limits: 100 max entries, 128 maximum key length, 512 maximum value length.", + "example": { + "deploy_prod": true + } + } + }, + "required": [ + "continuation-key", + "configuration" + ] + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request POST \\\n --url https://circleci.com/api/v2/pipeline/continue \\\n --header \"Circle-Token: $CIRCLE_TOKEN\" \\\n --header \"Content-Type: application/json\" \\\n --data \"{\n \\\"continuation-key\\\": \\\"example-string\\\",\n \\\"configuration\\\": \\\"example-string\\\",\n \\\"parameters\\\": {\n \\\"deploy_prod\\\": true\n }\n}\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/pipeline/continue';\n const options = {\n method: 'POST',\n headers: {'Circle-Token': '$CIRCLE_TOKEN', 'Content-Type': 'application/json'},\n body: '{\"continuation-key\":\"example-string\",\"configuration\":\"example-string\",\"parameters\":{\"deploy_prod\":true}}'\n };\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\npayload = \"{\\n \\\"continuation-key\\\": \\\"example-string\\\",\\n \\\"configuration\\\": \\\"example-string\\\",\\n \\\"parameters\\\": {\\n \\\"deploy_prod\\\": true\\n }\\n}\"\n\nheaders = {\n 'Circle-Token': \"$CIRCLE_TOKEN\",\n 'Content-Type': \"application/json\"\n}\n\nconn.request(\"POST\", \"/api/v2/pipeline/continue\", payload, headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/pipeline/continue\"\n\n\tpayload := strings.NewReader(\"{\\n \\\"continuation-key\\\": \\\"example-string\\\",\\n \\\"configuration\\\": \\\"example-string\\\",\\n \\\"parameters\\\": {\\n \\\"deploy_prod\\\": true\\n }\\n}\")\n\n\treq, _ := http.NewRequest(\"POST\", url, payload)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/pipeline/continue\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Post.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\nrequest[\"Content-Type\"] = 'application/json'\nrequest.body = \"{\\n \\\"continuation-key\\\": \\\"example-string\\\",\\n \\\"configuration\\\": \\\"example-string\\\",\\n \\\"parameters\\\": {\\n \\\"deploy_prod\\\": true\\n }\\n}\"\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/pipeline/{pipeline-id}": { + "get": { + "summary": "Get a pipeline by ID", + "description": "Returns a pipeline by the pipeline ID.", + "tags": [ + "Pipeline" + ], + "operationId": "getPipelineById", + "responses": { + "200": { + "description": "A pipeline object.", + "links": { + "ProjectFromPipeline": { + "operationId": "getProjectBySlug", + "parameters": { + "project_slug": "$response.body#/project_slug" + } + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the pipeline.", + "example": "5034460f-c7c4-4c43-9457-de07e2029e7b" + }, + "errors": { + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The type of error." + }, + "message": { + "type": "string", + "description": "A human-readable error message." + } + }, + "required": [ + "type", + "message" + ], + "description": "An error with a type and message." + }, + "description": "A sequence of errors that have occurred within the pipeline." + }, + "project_slug": { + "type": "string", + "description": "The project-slug for the pipeline.", + "example": "gh/CircleCI-Public/api-preview-docs" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the pipeline was last updated." + }, + "number": { + "type": "integer", + "format": "int64", + "description": "The number of the pipeline.", + "example": 25 + }, + "trigger_parameters": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "integer", + "format": "int64" + }, + { + "type": "boolean" + }, + { + "type": "object" + } + ] + } + }, + "state": { + "type": "string", + "description": "The current state of the pipeline." + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the pipeline was created." + }, + "trigger": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The type of trigger." + }, + "received_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the trigger was received." + }, + "actor": { + "type": "object", + "properties": { + "login": { + "type": "string", + "description": "The login information for the user on the VCS.", + "title": "Login" + }, + "avatar_url": { + "type": "string", + "x-nullable": true, + "description": "URL to the user's avatar on the VCS" + } + }, + "required": [ + "login", + "avatar_url" + ], + "description": "The user who triggered the Pipeline." + } + }, + "required": [ + "type", + "received_at", + "actor" + ], + "description": "A summary of the trigger." + }, + "vcs": { + "type": "object", + "properties": { + "provider_name": { + "type": "string", + "description": "Name of the VCS provider (e.g. GitHub, Bitbucket).", + "example": "GitHub" + }, + "target_repository_url": { + "type": "string", + "description": "URL for the repository the trigger targets (i.e. the repository where the PR will be merged). For fork-PR pipelines, this is the URL to the parent repo. For other pipelines, the `origin_` and `target_repository_url`s will be the same.", + "example": "https://github.com/CircleCI-Public/api-preview-docs" + }, + "branch": { + "type": "string", + "description": "The branch where the pipeline ran. The HEAD commit on this branch was used for the pipeline. Note that `branch` and `tag` are mutually exclusive. To trigger a pipeline for a PR by number use `pull//head` for the PR ref or `pull//merge` for the merge ref (GitHub only).", + "example": "feature/design-new-api" + }, + "review_id": { + "type": "string", + "description": "The code review id.", + "example": "123" + }, + "review_url": { + "type": "string", + "description": "The code review URL.", + "example": "https://github.com/CircleCI-Public/api-preview-docs/pull/123" + }, + "revision": { + "type": "string", + "x-nullable": true, + "description": "The code revision the pipeline ran.", + "example": "f454a02b5d10fcccfd7d9dd7608a76d6493a98b4" + }, + "tag": { + "type": "string", + "description": "The tag used by the pipeline. The commit that this tag points to was used for the pipeline. Note that `branch` and `tag` are mutually exclusive.", + "example": "v3.1.4159" + }, + "commit": { + "type": "object", + "properties": { + "subject": { + "type": "string", + "x-nullable": true, + "description": "The subject of the commit message." + }, + "body": { + "type": "string", + "x-nullable": true, + "description": "The body of the commit message." + } + }, + "required": [ + "subject", + "body" + ], + "description": "The latest commit in the pipeline." + }, + "origin_repository_url": { + "type": "string", + "description": "URL for the repository where the trigger originated. For fork-PR pipelines, this is the URL to the fork. For other pipelines the `origin_` and `target_repository_url`s will be the same.", + "example": "https://github.com/CircleCI-Public/api-preview-docs" + } + }, + "required": [ + "provider_name", + "origin_repository_url", + "target_repository_url", + "revision" + ], + "description": "VCS information for the pipeline." + } + }, + "required": [ + "id", + "number", + "project_slug", + "created_at", + "errors", + "state", + "trigger" + ], + "description": "A pipeline response.", + "title": "Pipeline" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "pipeline-id", + "description": "The unique ID of the pipeline.", + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true, + "example": "5034460f-c7c4-4c43-9457-de07e2029e7b" + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/pipeline/5034460f-c7c4-4c43-9457-de07e2029e7b \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/pipeline/5034460f-c7c4-4c43-9457-de07e2029e7b';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/pipeline/5034460f-c7c4-4c43-9457-de07e2029e7b\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/pipeline/5034460f-c7c4-4c43-9457-de07e2029e7b\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/pipeline/5034460f-c7c4-4c43-9457-de07e2029e7b\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/pipeline/{pipeline-id}/config": { + "get": { + "summary": "Get a pipeline's configuration", + "description": "Returns a pipeline's configuration by ID.", + "tags": [ + "Pipeline" + ], + "operationId": "getPipelineConfigById", + "responses": { + "200": { + "description": "The configuration strings for the pipeline.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "source": { + "type": "string", + "description": "The source configuration for the pipeline, before any config compilation has been performed. If there is no config, then this field will be empty." + }, + "compiled": { + "type": "string", + "description": "The compiled configuration for the pipeline, after all orb expansion has been performed. If there were errors processing the pipeline's configuration, then this field may be empty." + }, + "setup-config": { + "type": "string", + "description": "The setup configuration for the pipeline used for Setup Workflows. If there were errors processing the pipeline's configuration or if setup workflows are not enabled, then this field should not exist" + }, + "compiled-setup-config": { + "type": "string", + "description": "The compiled setup configuration for the pipeline, after all orb expansion has been performed. If there were errors processing the pipeline's setup workflows, then this field may be empty." + } + }, + "required": [ + "source", + "compiled" + ], + "description": "The configuration strings for the pipeline.", + "title": "PipelineConfig" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "pipeline-id", + "description": "The unique ID of the pipeline.", + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true, + "example": "5034460f-c7c4-4c43-9457-de07e2029e7b" + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/pipeline/5034460f-c7c4-4c43-9457-de07e2029e7b/config \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/pipeline/5034460f-c7c4-4c43-9457-de07e2029e7b/config';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/pipeline/5034460f-c7c4-4c43-9457-de07e2029e7b/config\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/pipeline/5034460f-c7c4-4c43-9457-de07e2029e7b/config\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/pipeline/5034460f-c7c4-4c43-9457-de07e2029e7b/config\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/pipeline/{pipeline-id}/values": { + "get": { + "summary": "Get pipeline values for a pipeline", + "description": "Returns a map of pipeline values by pipeline ID. For more information see the [pipeline values reference page](https://circleci.com/docs/variables/#pipeline-values).", + "tags": [ + "Pipeline" + ], + "operationId": "getPipelineValuesById", + "responses": { + "200": { + "description": "A JSON object of pipeline values", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "integer", + "format": "int64" + }, + { + "type": "boolean" + } + ] + }, + "description": "The pipeline-values for the pipeline.", + "title": "PipelineValues" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "pipeline-id", + "description": "The unique ID of the pipeline.", + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true, + "example": "5034460f-c7c4-4c43-9457-de07e2029e7b" + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/pipeline/5034460f-c7c4-4c43-9457-de07e2029e7b/values \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/pipeline/5034460f-c7c4-4c43-9457-de07e2029e7b/values';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/pipeline/5034460f-c7c4-4c43-9457-de07e2029e7b/values\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/pipeline/5034460f-c7c4-4c43-9457-de07e2029e7b/values\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/pipeline/5034460f-c7c4-4c43-9457-de07e2029e7b/values\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/pipeline/{pipeline-id}/workflow": { + "get": { + "summary": "Get a pipeline's workflows", + "description": "Returns a paginated list of workflows by pipeline ID.", + "tags": [ + "Pipeline" + ], + "operationId": "listWorkflowsByPipelineId", + "responses": { + "200": { + "description": "A paginated list of workflow objects.", + "links": { + "NextPipelineWorkflowsPage": { + "operationId": "listWorkflowsByPipelineId", + "parameters": { + "pipeline-id": "$request.path.pipeline-id", + "page-token": "$response.body#/next_page_token" + } + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "type": "object", + "properties": { + "pipeline_id": { + "type": "string", + "format": "uuid", + "description": "The ID of the pipeline this workflow belongs to.", + "example": "5034460f-c7c4-4c43-9457-de07e2029e7b" + }, + "canceled_by": { + "type": "string", + "format": "uuid" + }, + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the workflow." + }, + "auto_rerun_number": { + "type": "integer", + "format": "int64", + "minimum": 1, + "description": "Present if this workflow was auto-rerun from a previous workflow. The Nth auto-rerun workflow will have auto_rerun_number N", + "example": 1 + }, + "name": { + "type": "string", + "description": "The name of the workflow.", + "example": "build-and-test" + }, + "project_slug": { + "type": "string", + "description": "The project-slug for the pipeline this workflow belongs to.", + "example": "gh/CircleCI-Public/api-preview-docs" + }, + "errored_by": { + "type": "string", + "format": "uuid" + }, + "tag": { + "type": "string", + "x-nullable": true, + "description": "Tag used for the workflow", + "example": "setup" + }, + "status": { + "type": "string", + "description": "The current status of the workflow." + }, + "started_by": { + "type": "string", + "format": "uuid" + }, + "max_auto_reruns": { + "type": "integer", + "format": "int64", + "minimum": 1, + "description": "The maximum number of auto reruns specified for the workflow.", + "example": 5 + }, + "pipeline_number": { + "type": "integer", + "format": "int64", + "description": "The number of the pipeline this workflow belongs to.", + "example": 25 + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the workflow was created." + }, + "stopped_at": { + "type": "string", + "format": "date-time", + "x-nullable": true, + "description": "The date and time the workflow stopped." + } + }, + "required": [ + "id", + "name", + "status", + "created_at", + "stopped_at", + "pipeline_id", + "pipeline_number", + "project_slug", + "started_by" + ], + "description": "A workflow", + "title": "Workflow" + }, + "description": "A list of workflows.", + "title": "Workflow list" + }, + "next_page_token": { + "type": "string", + "x-nullable": true, + "description": "A token to pass as a `page-token` query parameter to return the next page of results." + } + }, + "required": [ + "items", + "next_page_token" + ], + "description": "A list of workflows and associated pagination token.", + "title": "WorkflowListResponse" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "pipeline-id", + "description": "The unique ID of the pipeline.", + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true, + "example": "5034460f-c7c4-4c43-9457-de07e2029e7b" + }, + { + "in": "query", + "name": "page-token", + "description": "A token to retrieve the next page of results.", + "schema": { + "type": "string" + }, + "required": false, + "allowEmptyValue": true + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url \"https://circleci.com/api/v2/pipeline/5034460f-c7c4-4c43-9457-de07e2029e7b/workflow?page-token=example-value\" \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/pipeline/5034460f-c7c4-4c43-9457-de07e2029e7b/workflow?page-token=example-value';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/pipeline/5034460f-c7c4-4c43-9457-de07e2029e7b/workflow?page-token=example-value\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/pipeline/5034460f-c7c4-4c43-9457-de07e2029e7b/workflow?page-token=example-value\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/pipeline/5034460f-c7c4-4c43-9457-de07e2029e7b/workflow?page-token=example-value\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/project/{project-slug}": { + "get": { + "summary": "Get a project", + "description": "Retrieves a project by project slug.", + "tags": [ + "Project" + ], + "operationId": "getProjectBySlug", + "responses": { + "200": { + "description": "A project object", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "slug": { + "type": "string", + "description": "Project slug in the form `vcs-slug/org-name/repo-name`. The `/` characters may be URL-escaped. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug`, replace `org-name` with the organization ID (found in Organization Settings), and replace `repo-name` with the project ID (found in Project Settings).", + "example": "gh/CircleCI-Public/api-preview-docs" + }, + "name": { + "type": "string", + "description": "The name of the project", + "example": "api-preview-docs" + }, + "id": { + "type": "string", + "format": "uuid" + }, + "organization_name": { + "type": "string", + "description": "The name of the organization the project belongs to", + "example": "CircleCI-Public" + }, + "organization_slug": { + "type": "string", + "description": "The slug of the organization the project belongs to", + "example": "gh/CircleCI-Public" + }, + "organization_id": { + "type": "string", + "format": "uuid", + "description": "The id of the organization the project belongs to", + "example": "ec6887ec-7d44-4b31-b468-7e552408ee32" + }, + "vcs_info": { + "type": "object", + "properties": { + "vcs_url": { + "type": "string", + "description": "URL to the repository hosting the project's code", + "example": "https://github.com/CircleCI-Public/api-preview-docs" + }, + "provider": { + "type": "string", + "description": "The VCS provider" + }, + "default_branch": { + "type": "string", + "example": "main" + } + }, + "required": [ + "vcs_url", + "provider", + "default_branch" + ], + "description": "Information about the VCS that hosts the project source code." + } + }, + "required": [ + "slug", + "name", + "id", + "organization_name", + "organization_slug", + "organization_id", + "vcs_info" + ], + "description": "NOTE: The definition of Project is subject to change.", + "title": "Project" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "project-slug", + "description": "Project slug in the form `vcs-slug/org-name/repo-name`. The `/` characters may be URL-escaped. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug`, replace `org-name` with the organization ID (found in Organization Settings), and replace `repo-name` with the project ID (found in Project Settings).", + "schema": { + "type": "string" + }, + "required": true, + "example": "gh/CircleCI-Public/api-preview-docs", + "allowReserved": true + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/project/gh/CircleCI-Public/api-preview-docs\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + }, + "delete": { + "summary": "Delete a project", + "description": "Deletes a project by project slug", + "tags": [ + "Project" + ], + "operationId": "deleteProjectBySlug", + "responses": { + "200": { + "description": "A confirmation message.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "A human-readable message" + } + }, + "required": [ + "message" + ], + "description": "message response", + "title": "MessageResponse" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "project-slug", + "description": "Project slug in the form `vcs-slug/org-name/repo-name`. The `/` characters may be URL-escaped. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug`, replace `org-name` with the organization ID (found in Organization Settings), and replace `repo-name` with the project ID (found in Project Settings).", + "schema": { + "type": "string" + }, + "required": true, + "example": "gh/CircleCI-Public/api-preview-docs", + "allowReserved": true + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request DELETE \\\n --url https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs';\n const options = {method: 'DELETE', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"DELETE\", \"/api/v2/project/gh/CircleCI-Public/api-preview-docs\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs\"\n\n\treq, _ := http.NewRequest(\"DELETE\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Delete.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/project/{project-slug}/checkout-key": { + "get": { + "summary": "Get all checkout keys", + "description": "Returns a sequence of checkout keys for `:project`.", + "tags": [ + "Project" + ], + "operationId": "listCheckoutKeys", + "responses": { + "200": { + "description": "A sequence of checkout keys.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "type": "object", + "properties": { + "public-key": { + "type": "string", + "description": "A public SSH key.", + "example": "ssh-rsa ..." + }, + "type": { + "type": "string", + "description": "The type of checkout key. This may be either `deploy-key` or `github-user-key`.", + "title": "CheckoutKeyType", + "example": "deploy-key" + }, + "fingerprint": { + "type": "string", + "description": "An SSH key fingerprint.", + "example": "c9:0b:1c:4f:d5:65:56:b9:ad:88:f9:81:2b:37:74:2f" + }, + "preferred": { + "type": "boolean", + "description": "A boolean value that indicates if this key is preferred.", + "example": true + }, + "created-at": { + "type": "string", + "format": "date-time", + "description": "The date and time the checkout key was created.", + "example": "2015-09-21T17:29:21.042Z" + } + }, + "required": [ + "public-key", + "type", + "fingerprint", + "preferred", + "created-at" + ], + "description": "A checkout key", + "title": "CheckoutKey" + } + }, + "next_page_token": { + "type": "string", + "x-nullable": true, + "description": "A token to pass as a `page-token` query parameter to return the next page of results." + } + }, + "required": [ + "items", + "next_page_token" + ], + "title": "CheckoutKeyListResponse" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "project-slug", + "description": "Project slug in the form `vcs-slug/org-name/repo-name`. The `/` characters may be URL-escaped. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug`, replace `org-name` with the organization ID (found in Organization Settings), and replace `repo-name` with the project ID (found in Project Settings).", + "schema": { + "type": "string" + }, + "required": true, + "example": "gh/CircleCI-Public/api-preview-docs", + "allowReserved": true + }, + { + "in": "query", + "name": "digest", + "description": "The fingerprint digest type to return. This may be either `md5` or `sha256`. If not passed, defaults to `md5`.", + "schema": { + "type": "string" + }, + "required": false + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url \"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/checkout-key?digest=sha256\" \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/checkout-key?digest=sha256';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/project/gh/CircleCI-Public/api-preview-docs/checkout-key?digest=sha256\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/checkout-key?digest=sha256\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/checkout-key?digest=sha256\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + }, + "post": { + "summary": "Create a new checkout key", + "description": "Not available to projects that use GitLab or GitHub App. Creates a new checkout key. This API request is only usable with a user API token.\n Please ensure that you have authorized your account with GitHub before creating user keys.\n This is necessary to give CircleCI the permission to create a user key associated with\n your GitHub user account. You can find this page by visiting Project Settings > Checkout SSH Keys", + "tags": [ + "Project" + ], + "operationId": "createCheckoutKey", + "responses": { + "201": { + "description": "The checkout key.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "public-key": { + "type": "string", + "description": "A public SSH key.", + "example": "ssh-rsa ..." + }, + "type": { + "type": "string", + "description": "The type of checkout key. This may be either `deploy-key` or `github-user-key`.", + "title": "CheckoutKeyType", + "example": "deploy-key" + }, + "fingerprint": { + "type": "string", + "description": "An SSH key fingerprint.", + "example": "c9:0b:1c:4f:d5:65:56:b9:ad:88:f9:81:2b:37:74:2f" + }, + "preferred": { + "type": "boolean", + "description": "A boolean value that indicates if this key is preferred.", + "example": true + }, + "created-at": { + "type": "string", + "format": "date-time", + "description": "The date and time the checkout key was created.", + "example": "2015-09-21T17:29:21.042Z" + } + }, + "required": [ + "public-key", + "type", + "fingerprint", + "preferred", + "created-at" + ], + "description": "A checkout key", + "title": "CheckoutKey" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "project-slug", + "description": "Project slug in the form `vcs-slug/org-name/repo-name`. The `/` characters may be URL-escaped. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug`, replace `org-name` with the organization ID (found in Organization Settings), and replace `repo-name` with the project ID (found in Project Settings).", + "schema": { + "type": "string" + }, + "required": true, + "example": "gh/CircleCI-Public/api-preview-docs", + "allowReserved": true + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The type of checkout key to create. This may be either `deploy-key` or `user-key`.", + "title": "CheckoutKeyInputType", + "example": "deploy-key" + } + }, + "required": [ + "type" + ], + "title": "CheckoutKeyInput" + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request POST \\\n --url https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/checkout-key \\\n --header \"Circle-Token: $CIRCLE_TOKEN\" \\\n --header \"Content-Type: application/json\" \\\n --data \"{\n \\\"type\\\": \\\"deploy-key\\\"\n}\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/checkout-key';\n const options = {\n method: 'POST',\n headers: {'Circle-Token': '$CIRCLE_TOKEN', 'Content-Type': 'application/json'},\n body: '{\"type\":\"deploy-key\"}'\n };\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\npayload = \"{\\n \\\"type\\\": \\\"deploy-key\\\"\\n}\"\n\nheaders = {\n 'Circle-Token': \"$CIRCLE_TOKEN\",\n 'Content-Type': \"application/json\"\n}\n\nconn.request(\"POST\", \"/api/v2/project/gh/CircleCI-Public/api-preview-docs/checkout-key\", payload, headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/checkout-key\"\n\n\tpayload := strings.NewReader(\"{\\n \\\"type\\\": \\\"deploy-key\\\"\\n}\")\n\n\treq, _ := http.NewRequest(\"POST\", url, payload)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/checkout-key\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Post.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\nrequest[\"Content-Type\"] = 'application/json'\nrequest.body = \"{\\n \\\"type\\\": \\\"deploy-key\\\"\\n}\"\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/project/{project-slug}/checkout-key/{fingerprint}": { + "get": { + "summary": "Get a checkout key", + "description": "Returns an individual checkout key via md5 or sha256 fingerprint. sha256 keys should be url-encoded.", + "tags": [ + "Project" + ], + "operationId": "getCheckoutKey", + "responses": { + "200": { + "description": "The checkout key.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "public-key": { + "type": "string", + "description": "A public SSH key.", + "example": "ssh-rsa ..." + }, + "type": { + "type": "string", + "description": "The type of checkout key. This may be either `deploy-key` or `github-user-key`.", + "title": "CheckoutKeyType", + "example": "deploy-key" + }, + "fingerprint": { + "type": "string", + "description": "An SSH key fingerprint.", + "example": "c9:0b:1c:4f:d5:65:56:b9:ad:88:f9:81:2b:37:74:2f" + }, + "preferred": { + "type": "boolean", + "description": "A boolean value that indicates if this key is preferred.", + "example": true + }, + "created-at": { + "type": "string", + "format": "date-time", + "description": "The date and time the checkout key was created.", + "example": "2015-09-21T17:29:21.042Z" + } + }, + "required": [ + "public-key", + "type", + "fingerprint", + "preferred", + "created-at" + ], + "description": "A checkout key", + "title": "CheckoutKey" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "project-slug", + "description": "Project slug in the form `vcs-slug/org-name/repo-name`. The `/` characters may be URL-escaped. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug`, replace `org-name` with the organization ID (found in Organization Settings), and replace `repo-name` with the project ID (found in Project Settings).", + "schema": { + "type": "string" + }, + "required": true, + "example": "gh/CircleCI-Public/api-preview-docs", + "allowReserved": true + }, + { + "in": "path", + "name": "fingerprint", + "description": "An SSH key fingerprint.", + "schema": { + "type": "string" + }, + "required": true, + "example": "c9:0b:1c:4f:d5:65:56:b9:ad:88:f9:81:2b:37:74:2f" + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/checkout-key/c9:0b:1c:4f:d5:65:56:b9:ad:88:f9:81:2b:37:74:2f \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/checkout-key/c9:0b:1c:4f:d5:65:56:b9:ad:88:f9:81:2b:37:74:2f';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/project/gh/CircleCI-Public/api-preview-docs/checkout-key/c9:0b:1c:4f:d5:65:56:b9:ad:88:f9:81:2b:37:74:2f\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/checkout-key/c9:0b:1c:4f:d5:65:56:b9:ad:88:f9:81:2b:37:74:2f\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/checkout-key/c9:0b:1c:4f:d5:65:56:b9:ad:88:f9:81:2b:37:74:2f\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + }, + "delete": { + "summary": "Delete a checkout key", + "description": "Deletes the checkout key via md5 or sha256 fingerprint. sha256 keys should be url-encoded.", + "tags": [ + "Project" + ], + "operationId": "deleteCheckoutKey", + "responses": { + "200": { + "description": "A confirmation message.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "A human-readable message" + } + }, + "required": [ + "message" + ], + "description": "message response", + "title": "MessageResponse" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "project-slug", + "description": "Project slug in the form `vcs-slug/org-name/repo-name`. The `/` characters may be URL-escaped. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug`, replace `org-name` with the organization ID (found in Organization Settings), and replace `repo-name` with the project ID (found in Project Settings).", + "schema": { + "type": "string" + }, + "required": true, + "example": "gh/CircleCI-Public/api-preview-docs", + "allowReserved": true + }, + { + "in": "path", + "name": "fingerprint", + "description": "An SSH key fingerprint.", + "schema": { + "type": "string" + }, + "required": true, + "example": "c9:0b:1c:4f:d5:65:56:b9:ad:88:f9:81:2b:37:74:2f" + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request DELETE \\\n --url https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/checkout-key/c9:0b:1c:4f:d5:65:56:b9:ad:88:f9:81:2b:37:74:2f \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/checkout-key/c9:0b:1c:4f:d5:65:56:b9:ad:88:f9:81:2b:37:74:2f';\n const options = {method: 'DELETE', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"DELETE\", \"/api/v2/project/gh/CircleCI-Public/api-preview-docs/checkout-key/c9:0b:1c:4f:d5:65:56:b9:ad:88:f9:81:2b:37:74:2f\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/checkout-key/c9:0b:1c:4f:d5:65:56:b9:ad:88:f9:81:2b:37:74:2f\"\n\n\treq, _ := http.NewRequest(\"DELETE\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/checkout-key/c9:0b:1c:4f:d5:65:56:b9:ad:88:f9:81:2b:37:74:2f\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Delete.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/project/{project-slug}/envvar": { + "get": { + "summary": "List all environment variables", + "description": "Returns four 'x' characters, in addition to the last four ASCII characters of the value, consistent with the display of environment variable values on the CircleCI website.", + "tags": [ + "Project" + ], + "operationId": "listEnvVars", + "responses": { + "200": { + "description": "A sequence of environment variables.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of the environment variable.", + "example": "foo" + }, + "value": { + "type": "string", + "description": "The value of the environment variable.", + "example": "xxxx1234" + }, + "created-at": { + "x-nullable": true, + "description": "The creation timestamp of the environment variable.", + "example": "#joda/inst 2023-04-14T21:20:14+0000" + } + }, + "required": [ + "name", + "value" + ], + "description": "An environment variable is a map containing a value and an optional timestamp.", + "title": "EnvironmentVariable" + } + }, + "next_page_token": { + "type": "string", + "x-nullable": true, + "description": "A token to pass as a `page-token` query parameter to return the next page of results." + } + }, + "required": [ + "items", + "next_page_token" + ], + "title": "EnvironmentVariableListResponse" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "project-slug", + "description": "Project slug in the form `vcs-slug/org-name/repo-name`. The `/` characters may be URL-escaped. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug`, replace `org-name` with the organization ID (found in Organization Settings), and replace `repo-name` with the project ID (found in Project Settings).", + "schema": { + "type": "string" + }, + "required": true, + "example": "gh/CircleCI-Public/api-preview-docs", + "allowReserved": true + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/envvar \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/envvar';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/project/gh/CircleCI-Public/api-preview-docs/envvar\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/envvar\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/envvar\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + }, + "post": { + "summary": "Create an environment variable", + "description": "Creates a new environment variable.", + "tags": [ + "Project" + ], + "operationId": "createEnvVar", + "responses": { + "201": { + "description": "The environment variable.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of the environment variable.", + "example": "foo" + }, + "value": { + "type": "string", + "description": "The value of the environment variable.", + "example": "xxxx1234" + }, + "created-at": { + "x-nullable": true, + "description": "The creation timestamp of the environment variable.", + "example": "#joda/inst 2023-04-14T21:20:14+0000" + } + }, + "required": [ + "name", + "value" + ], + "description": "An environment variable is a map containing a value and an optional timestamp.", + "title": "EnvironmentVariable" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "project-slug", + "description": "Project slug in the form `vcs-slug/org-name/repo-name`. The `/` characters may be URL-escaped. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug`, replace `org-name` with the organization ID (found in Organization Settings), and replace `repo-name` with the project ID (found in Project Settings).", + "schema": { + "type": "string" + }, + "required": true, + "example": "gh/CircleCI-Public/api-preview-docs", + "allowReserved": true + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of the environment variable.", + "example": "foo" + }, + "value": { + "type": "string", + "description": "The value of the environment variable.", + "example": "xxxx1234" + } + }, + "required": [ + "name", + "value" + ], + "description": "An environment variable request requires a name and a value", + "title": "EnvironmentVariable" + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request POST \\\n --url https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/envvar \\\n --header \"Circle-Token: $CIRCLE_TOKEN\" \\\n --header \"Content-Type: application/json\" \\\n --data \"{\n \\\"name\\\": \\\"foo\\\",\n \\\"value\\\": \\\"xxxx1234\\\"\n}\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/envvar';\n const options = {\n method: 'POST',\n headers: {'Circle-Token': '$CIRCLE_TOKEN', 'Content-Type': 'application/json'},\n body: '{\"name\":\"foo\",\"value\":\"xxxx1234\"}'\n };\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\npayload = \"{\\n \\\"name\\\": \\\"foo\\\",\\n \\\"value\\\": \\\"xxxx1234\\\"\\n}\"\n\nheaders = {\n 'Circle-Token': \"$CIRCLE_TOKEN\",\n 'Content-Type': \"application/json\"\n}\n\nconn.request(\"POST\", \"/api/v2/project/gh/CircleCI-Public/api-preview-docs/envvar\", payload, headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/envvar\"\n\n\tpayload := strings.NewReader(\"{\\n \\\"name\\\": \\\"foo\\\",\\n \\\"value\\\": \\\"xxxx1234\\\"\\n}\")\n\n\treq, _ := http.NewRequest(\"POST\", url, payload)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/envvar\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Post.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\nrequest[\"Content-Type\"] = 'application/json'\nrequest.body = \"{\\n \\\"name\\\": \\\"foo\\\",\\n \\\"value\\\": \\\"xxxx1234\\\"\\n}\"\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/project/{project-slug}/envvar/{name}": { + "get": { + "summary": "Get a masked environment variable", + "description": "Returns the masked value of environment variable :name.", + "tags": [ + "Project" + ], + "operationId": "getEnvVar", + "responses": { + "200": { + "description": "The environment variable.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of the environment variable.", + "example": "foo" + }, + "value": { + "type": "string", + "description": "The value of the environment variable.", + "example": "xxxx1234" + }, + "created-at": { + "x-nullable": true, + "description": "The creation timestamp of the environment variable.", + "example": "#joda/inst 2023-04-14T21:20:14+0000" + } + }, + "required": [ + "name", + "value" + ], + "description": "An environment variable is a map containing a value and an optional timestamp.", + "title": "EnvironmentVariable" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "project-slug", + "description": "Project slug in the form `vcs-slug/org-name/repo-name`. The `/` characters may be URL-escaped. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug`, replace `org-name` with the organization ID (found in Organization Settings), and replace `repo-name` with the project ID (found in Project Settings).", + "schema": { + "type": "string" + }, + "required": true, + "example": "gh/CircleCI-Public/api-preview-docs", + "allowReserved": true + }, + { + "in": "path", + "name": "name", + "description": "The name of the environment variable.", + "schema": { + "type": "string" + }, + "required": true, + "example": "foo" + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/envvar/foo \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/envvar/foo';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/project/gh/CircleCI-Public/api-preview-docs/envvar/foo\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/envvar/foo\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/envvar/foo\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + }, + "delete": { + "summary": "Delete an environment variable", + "description": "Deletes the environment variable named :name.", + "tags": [ + "Project" + ], + "operationId": "deleteEnvVar", + "responses": { + "200": { + "description": "A confirmation message.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "A human-readable message" + } + }, + "required": [ + "message" + ], + "description": "message response", + "title": "MessageResponse" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "project-slug", + "description": "Project slug in the form `vcs-slug/org-name/repo-name`. The `/` characters may be URL-escaped. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug`, replace `org-name` with the organization ID (found in Organization Settings), and replace `repo-name` with the project ID (found in Project Settings).", + "schema": { + "type": "string" + }, + "required": true, + "example": "gh/CircleCI-Public/api-preview-docs", + "allowReserved": true + }, + { + "in": "path", + "name": "name", + "description": "The name of the environment variable.", + "schema": { + "type": "string" + }, + "required": true, + "example": "foo" + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request DELETE \\\n --url https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/envvar/foo \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/envvar/foo';\n const options = {method: 'DELETE', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"DELETE\", \"/api/v2/project/gh/CircleCI-Public/api-preview-docs/envvar/foo\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/envvar/foo\"\n\n\treq, _ := http.NewRequest(\"DELETE\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/envvar/foo\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Delete.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/project/{project-slug}/job/{job-number}": { + "get": { + "summary": "Get job details", + "description": "Returns job details.", + "tags": [ + "Job" + ], + "operationId": "getJobDetails", + "responses": { + "200": { + "description": "Job details.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "web_url": { + "type": "string", + "description": "URL of the job in CircleCI Web UI." + }, + "project": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "slug": { + "type": "string", + "description": "Project slug in the form `vcs-slug/org-name/repo-name`. The `/` characters may be URL-escaped. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug`, replace `org-name` with the organization ID (found in Organization Settings), and replace `repo-name` with the project ID (found in Project Settings).", + "example": "gh/CircleCI-Public/api-preview-docs" + }, + "name": { + "type": "string", + "description": "The name of the project", + "example": "api-preview-docs" + }, + "external_url": { + "type": "string", + "description": "URL to the repository hosting the project's code", + "example": "https://github.com/CircleCI-Public/api-preview-docs" + } + }, + "required": [ + "id", + "slug", + "name", + "external_url" + ], + "description": "Information about a project." + }, + "parallel_runs": { + "type": "array", + "items": { + "type": "object", + "properties": { + "index": { + "type": "integer", + "format": "int64", + "description": "Index of the parallel run." + }, + "status": { + "type": "string", + "description": "Status of the parallel run." + } + }, + "required": [ + "index", + "status" + ], + "description": "Info about a status of the parallel run." + }, + "description": "Info about parallels runs and their status." + }, + "started_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the job started." + }, + "latest_workflow": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the workflow." + }, + "name": { + "type": "string", + "description": "The name of the workflow.", + "example": "build-and-test" + } + }, + "required": [ + "id", + "name" + ], + "description": "Info about the latest workflow the job was a part of." + }, + "name": { + "type": "string", + "description": "The name of the job." + }, + "executor": { + "type": "object", + "properties": { + "resource_class": { + "type": "string", + "description": "Resource class name." + }, + "type": { + "type": "string", + "description": "Executor type." + } + }, + "required": [ + "resource_class" + ], + "description": "Information about executor used for a job." + }, + "parallelism": { + "type": "integer", + "format": "int64", + "description": "A number of parallel runs the job has." + }, + "status": { + "type": "string", + "description": "The current status of the job." + }, + "number": { + "type": "integer", + "format": "int64", + "description": "The number of the job.", + "example": 1 + }, + "pipeline": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the pipeline.", + "example": "5034460f-c7c4-4c43-9457-de07e2029e7b" + } + }, + "required": [ + "id" + ], + "description": "Info about a pipeline the job is a part of." + }, + "duration": { + "type": "integer", + "format": "int64", + "x-nullable": true, + "description": "Duration of a job in milliseconds." + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The time when the job was created." + }, + "messages": { + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Message type." + }, + "message": { + "type": "string", + "description": "Information describing message." + }, + "reason": { + "type": "string", + "description": "Value describing the reason for message to be added to the job." + } + }, + "required": [ + "type", + "message" + ], + "description": "Message from CircleCI execution platform." + }, + "description": "Messages from CircleCI execution platform." + }, + "contexts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of the context." + } + }, + "required": [ + "name" + ], + "description": "Information about the context." + }, + "description": "List of contexts used by the job." + }, + "organization": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of the organization." + } + }, + "required": [ + "name" + ], + "description": "Information about an organization." + }, + "queued_at": { + "type": "string", + "format": "date-time", + "description": "The time when the job was placed in a queue." + }, + "stopped_at": { + "type": "string", + "format": "date-time", + "x-nullable": true, + "description": "The time when the job stopped." + } + }, + "required": [ + "number", + "name", + "status", + "started_at", + "created_at", + "queued_at", + "duration", + "executor", + "project", + "organization", + "contexts", + "web_url", + "parallel_runs", + "latest_workflow", + "pipeline", + "parallelism", + "messages" + ], + "description": "Job Details", + "title": "Job Details" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "job-number", + "description": "The number of the job.", + "schema": {}, + "required": true, + "example": "123" + }, + { + "in": "path", + "name": "project-slug", + "description": "Project slug in the form `vcs-slug/org-name/repo-name`. The `/` characters may be URL-escaped. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug`, replace `org-name` with the organization ID (found in Organization Settings), and replace `repo-name` with the project ID (found in Project Settings).", + "schema": { + "type": "string" + }, + "required": true, + "example": "gh/CircleCI-Public/api-preview-docs", + "allowReserved": true + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/job/123 \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/job/123';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/project/gh/CircleCI-Public/api-preview-docs/job/123\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/job/123\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/job/123\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/project/{project-slug}/job/{job-number}/cancel": { + "post": { + "summary": "Cancel job by job number", + "description": "Cancel job with a given job number.", + "tags": [ + "Job" + ], + "operationId": "cancelJobByJobNumber", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "A human-readable message" + } + }, + "required": [ + "message" + ], + "description": "message response", + "title": "MessageResponse" + } + } + }, + "description": "" + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "job-number", + "description": "The number of the job.", + "schema": {}, + "required": true, + "example": "123" + }, + { + "in": "path", + "name": "project-slug", + "description": "Project slug in the form `vcs-slug/org-name/repo-name`. The `/` characters may be URL-escaped. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug`, replace `org-name` with the organization ID (found in Organization Settings), and replace `repo-name` with the project ID (found in Project Settings).", + "schema": { + "type": "string" + }, + "required": true, + "example": "gh/CircleCI-Public/api-preview-docs", + "allowReserved": true + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request POST \\\n --url https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/job/123/cancel \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/job/123/cancel';\n const options = {method: 'POST', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"POST\", \"/api/v2/project/gh/CircleCI-Public/api-preview-docs/job/123/cancel\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/job/123/cancel\"\n\n\treq, _ := http.NewRequest(\"POST\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/job/123/cancel\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Post.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/project/{project-slug}/pipeline": { + "post": { + "summary": "Trigger a new pipeline", + "description": "**[This endpoint is superseded by the [new Trigger Pipeline API](#tag/Pipeline/operation/triggerPipelineRun), which supports all organization and pipeline types except GitLab.]** Triggers a new pipeline on the project. Does not support triggering pipelines integrated with GitLab or GitHub App.", + "tags": [ + "Pipeline" + ], + "operationId": "triggerPipeline", + "responses": { + "201": { + "description": "The created pipeline.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the pipeline.", + "example": "5034460f-c7c4-4c43-9457-de07e2029e7b" + }, + "state": { + "type": "string", + "description": "The current state of the pipeline." + }, + "number": { + "type": "integer", + "format": "int64", + "description": "The number of the pipeline.", + "example": 25 + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the pipeline was created." + } + }, + "required": [ + "id", + "state", + "number", + "created_at" + ], + "description": "A pipeline creation response.", + "title": "PipelineCreation" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "project-slug", + "description": "Project slug in the form `vcs-slug/org-name/repo-name`. The `/` characters may be URL-escaped. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug`, replace `org-name` with the organization ID (found in Organization Settings), and replace `repo-name` with the project ID (found in Project Settings).", + "schema": { + "type": "string" + }, + "required": true, + "example": "gh/CircleCI-Public/api-preview-docs", + "allowReserved": true + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "branch": { + "type": "string", + "description": "The branch where the pipeline ran. The HEAD commit on this branch was used for the pipeline. Note that `branch` and `tag` are mutually exclusive. To trigger a pipeline for a PR by number use `pull//head` for the PR ref or `pull//merge` for the merge ref (GitHub only).", + "example": "feature/design-new-api" + }, + "tag": { + "type": "string", + "description": "The tag used by the pipeline. The commit that this tag points to was used for the pipeline. Note that `branch` and `tag` are mutually exclusive.", + "example": "v3.1.4159" + }, + "parameters": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "boolean" + } + ] + }, + "description": "An object containing pipeline parameters and their values. Pipeline parameters have the following size limits: 100 max entries, 128 maximum key length, 512 maximum value length.", + "example": { + "deploy_prod": true + } + } + }, + "x-nullable": true, + "description": "The information you can supply when triggering a pipeline.", + "title": "TriggerPipelineParameters" + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request POST \\\n --url https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/pipeline \\\n --header \"Circle-Token: $CIRCLE_TOKEN\" \\\n --header \"Content-Type: application/json\" \\\n --data \"{\n \\\"branch\\\": \\\"feature/design-new-api\\\",\n \\\"tag\\\": \\\"v3.1.4159\\\",\n \\\"parameters\\\": {\n \\\"deploy_prod\\\": true\n }\n}\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/pipeline';\n const options = {\n method: 'POST',\n headers: {'Circle-Token': '$CIRCLE_TOKEN', 'Content-Type': 'application/json'},\n body: '{\"branch\":\"feature/design-new-api\",\"tag\":\"v3.1.4159\",\"parameters\":{\"deploy_prod\":true}}'\n };\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\npayload = \"{\\n \\\"branch\\\": \\\"feature/design-new-api\\\",\\n \\\"tag\\\": \\\"v3.1.4159\\\",\\n \\\"parameters\\\": {\\n \\\"deploy_prod\\\": true\\n }\\n}\"\n\nheaders = {\n 'Circle-Token': \"$CIRCLE_TOKEN\",\n 'Content-Type': \"application/json\"\n}\n\nconn.request(\"POST\", \"/api/v2/project/gh/CircleCI-Public/api-preview-docs/pipeline\", payload, headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/pipeline\"\n\n\tpayload := strings.NewReader(\"{\\n \\\"branch\\\": \\\"feature/design-new-api\\\",\\n \\\"tag\\\": \\\"v3.1.4159\\\",\\n \\\"parameters\\\": {\\n \\\"deploy_prod\\\": true\\n }\\n}\")\n\n\treq, _ := http.NewRequest(\"POST\", url, payload)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/pipeline\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Post.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\nrequest[\"Content-Type\"] = 'application/json'\nrequest.body = \"{\\n \\\"branch\\\": \\\"feature/design-new-api\\\",\\n \\\"tag\\\": \\\"v3.1.4159\\\",\\n \\\"parameters\\\": {\\n \\\"deploy_prod\\\": true\\n }\\n}\"\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + }, + "get": { + "summary": "Get all pipelines", + "description": "Returns all pipelines for this project.", + "tags": [ + "Pipeline" + ], + "operationId": "listPipelinesForProject", + "responses": { + "200": { + "description": "A sequence of pipelines.", + "links": { + "NextPipelinePage": { + "operationId": "listPipelinesForProject", + "parameters": { + "project-slug": "$request.path.project-slug", + "page-token": "$response.body#/next_page_token" + } + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the pipeline.", + "example": "5034460f-c7c4-4c43-9457-de07e2029e7b" + }, + "errors": { + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The type of error." + }, + "message": { + "type": "string", + "description": "A human-readable error message." + } + }, + "required": [ + "type", + "message" + ], + "description": "An error with a type and message." + }, + "description": "A sequence of errors that have occurred within the pipeline." + }, + "project_slug": { + "type": "string", + "description": "The project-slug for the pipeline.", + "example": "gh/CircleCI-Public/api-preview-docs" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the pipeline was last updated." + }, + "number": { + "type": "integer", + "format": "int64", + "description": "The number of the pipeline.", + "example": 25 + }, + "trigger_parameters": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "integer", + "format": "int64" + }, + { + "type": "boolean" + }, + { + "type": "object" + } + ] + } + }, + "state": { + "type": "string", + "description": "The current state of the pipeline." + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the pipeline was created." + }, + "trigger": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The type of trigger." + }, + "received_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the trigger was received." + }, + "actor": { + "type": "object", + "properties": { + "login": { + "type": "string", + "description": "The login information for the user on the VCS.", + "title": "Login" + }, + "avatar_url": { + "type": "string", + "x-nullable": true, + "description": "URL to the user's avatar on the VCS" + } + }, + "required": [ + "login", + "avatar_url" + ], + "description": "The user who triggered the Pipeline." + } + }, + "required": [ + "type", + "received_at", + "actor" + ], + "description": "A summary of the trigger." + }, + "vcs": { + "type": "object", + "properties": { + "provider_name": { + "type": "string", + "description": "Name of the VCS provider (e.g. GitHub, Bitbucket).", + "example": "GitHub" + }, + "target_repository_url": { + "type": "string", + "description": "URL for the repository the trigger targets (i.e. the repository where the PR will be merged). For fork-PR pipelines, this is the URL to the parent repo. For other pipelines, the `origin_` and `target_repository_url`s will be the same.", + "example": "https://github.com/CircleCI-Public/api-preview-docs" + }, + "branch": { + "type": "string", + "description": "The branch where the pipeline ran. The HEAD commit on this branch was used for the pipeline. Note that `branch` and `tag` are mutually exclusive. To trigger a pipeline for a PR by number use `pull//head` for the PR ref or `pull//merge` for the merge ref (GitHub only).", + "example": "feature/design-new-api" + }, + "review_id": { + "type": "string", + "description": "The code review id.", + "example": "123" + }, + "review_url": { + "type": "string", + "description": "The code review URL.", + "example": "https://github.com/CircleCI-Public/api-preview-docs/pull/123" + }, + "revision": { + "type": "string", + "x-nullable": true, + "description": "The code revision the pipeline ran.", + "example": "f454a02b5d10fcccfd7d9dd7608a76d6493a98b4" + }, + "tag": { + "type": "string", + "description": "The tag used by the pipeline. The commit that this tag points to was used for the pipeline. Note that `branch` and `tag` are mutually exclusive.", + "example": "v3.1.4159" + }, + "commit": { + "type": "object", + "properties": { + "subject": { + "type": "string", + "x-nullable": true, + "description": "The subject of the commit message." + }, + "body": { + "type": "string", + "x-nullable": true, + "description": "The body of the commit message." + } + }, + "required": [ + "subject", + "body" + ], + "description": "The latest commit in the pipeline." + }, + "origin_repository_url": { + "type": "string", + "description": "URL for the repository where the trigger originated. For fork-PR pipelines, this is the URL to the fork. For other pipelines the `origin_` and `target_repository_url`s will be the same.", + "example": "https://github.com/CircleCI-Public/api-preview-docs" + } + }, + "required": [ + "provider_name", + "origin_repository_url", + "target_repository_url", + "revision" + ], + "description": "VCS information for the pipeline." + } + }, + "required": [ + "id", + "number", + "project_slug", + "created_at", + "errors", + "state", + "trigger" + ], + "description": "A pipeline response.", + "title": "Pipeline" + } + }, + "next_page_token": { + "type": "string", + "x-nullable": true, + "description": "A token to pass as a `page-token` query parameter to return the next page of results." + } + }, + "required": [ + "items", + "next_page_token" + ], + "description": "List of pipelines", + "title": "PipelineListResponse" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "project-slug", + "description": "Project slug in the form `vcs-slug/org-name/repo-name`. The `/` characters may be URL-escaped. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug`, replace `org-name` with the organization ID (found in Organization Settings), and replace `repo-name` with the project ID (found in Project Settings).", + "schema": { + "type": "string" + }, + "required": true, + "example": "gh/CircleCI-Public/api-preview-docs", + "allowReserved": true + }, + { + "in": "query", + "name": "branch", + "description": "The name of a vcs branch.", + "schema": { + "type": "string" + }, + "required": false, + "allowEmptyValue": true + }, + { + "in": "query", + "name": "page-token", + "description": "A token to retrieve the next page of results.", + "schema": { + "type": "string" + }, + "required": false, + "allowEmptyValue": true + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url \"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/pipeline?branch=example-value&page-token=example-value\" \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/pipeline?branch=example-value&page-token=example-value';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/project/gh/CircleCI-Public/api-preview-docs/pipeline?branch=example-value&page-token=example-value\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/pipeline?branch=example-value&page-token=example-value\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/pipeline?branch=example-value&page-token=example-value\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/project/{project-slug}/pipeline/mine": { + "get": { + "summary": "Get your pipelines", + "description": "Returns a sequence of all pipelines for this project triggered by the user.", + "tags": [ + "Pipeline" + ], + "operationId": "listMyPipelines", + "responses": { + "200": { + "description": "A sequence of pipelines.", + "links": { + "NextPipelinePage": { + "operationId": "listMyPipelines", + "parameters": { + "project-slug": "$request.path.project-slug", + "page-token": "$response.body#/next_page_token" + } + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the pipeline.", + "example": "5034460f-c7c4-4c43-9457-de07e2029e7b" + }, + "errors": { + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The type of error." + }, + "message": { + "type": "string", + "description": "A human-readable error message." + } + }, + "required": [ + "type", + "message" + ], + "description": "An error with a type and message." + }, + "description": "A sequence of errors that have occurred within the pipeline." + }, + "project_slug": { + "type": "string", + "description": "The project-slug for the pipeline.", + "example": "gh/CircleCI-Public/api-preview-docs" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the pipeline was last updated." + }, + "number": { + "type": "integer", + "format": "int64", + "description": "The number of the pipeline.", + "example": 25 + }, + "trigger_parameters": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "integer", + "format": "int64" + }, + { + "type": "boolean" + }, + { + "type": "object" + } + ] + } + }, + "state": { + "type": "string", + "description": "The current state of the pipeline." + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the pipeline was created." + }, + "trigger": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The type of trigger." + }, + "received_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the trigger was received." + }, + "actor": { + "type": "object", + "properties": { + "login": { + "type": "string", + "description": "The login information for the user on the VCS.", + "title": "Login" + }, + "avatar_url": { + "type": "string", + "x-nullable": true, + "description": "URL to the user's avatar on the VCS" + } + }, + "required": [ + "login", + "avatar_url" + ], + "description": "The user who triggered the Pipeline." + } + }, + "required": [ + "type", + "received_at", + "actor" + ], + "description": "A summary of the trigger." + }, + "vcs": { + "type": "object", + "properties": { + "provider_name": { + "type": "string", + "description": "Name of the VCS provider (e.g. GitHub, Bitbucket).", + "example": "GitHub" + }, + "target_repository_url": { + "type": "string", + "description": "URL for the repository the trigger targets (i.e. the repository where the PR will be merged). For fork-PR pipelines, this is the URL to the parent repo. For other pipelines, the `origin_` and `target_repository_url`s will be the same.", + "example": "https://github.com/CircleCI-Public/api-preview-docs" + }, + "branch": { + "type": "string", + "description": "The branch where the pipeline ran. The HEAD commit on this branch was used for the pipeline. Note that `branch` and `tag` are mutually exclusive. To trigger a pipeline for a PR by number use `pull//head` for the PR ref or `pull//merge` for the merge ref (GitHub only).", + "example": "feature/design-new-api" + }, + "review_id": { + "type": "string", + "description": "The code review id.", + "example": "123" + }, + "review_url": { + "type": "string", + "description": "The code review URL.", + "example": "https://github.com/CircleCI-Public/api-preview-docs/pull/123" + }, + "revision": { + "type": "string", + "x-nullable": true, + "description": "The code revision the pipeline ran.", + "example": "f454a02b5d10fcccfd7d9dd7608a76d6493a98b4" + }, + "tag": { + "type": "string", + "description": "The tag used by the pipeline. The commit that this tag points to was used for the pipeline. Note that `branch` and `tag` are mutually exclusive.", + "example": "v3.1.4159" + }, + "commit": { + "type": "object", + "properties": { + "subject": { + "type": "string", + "x-nullable": true, + "description": "The subject of the commit message." + }, + "body": { + "type": "string", + "x-nullable": true, + "description": "The body of the commit message." + } + }, + "required": [ + "subject", + "body" + ], + "description": "The latest commit in the pipeline." + }, + "origin_repository_url": { + "type": "string", + "description": "URL for the repository where the trigger originated. For fork-PR pipelines, this is the URL to the fork. For other pipelines the `origin_` and `target_repository_url`s will be the same.", + "example": "https://github.com/CircleCI-Public/api-preview-docs" + } + }, + "required": [ + "provider_name", + "origin_repository_url", + "target_repository_url", + "revision" + ], + "description": "VCS information for the pipeline." + } + }, + "required": [ + "id", + "number", + "project_slug", + "created_at", + "errors", + "state", + "trigger" + ], + "description": "A pipeline response.", + "title": "Pipeline" + } + }, + "next_page_token": { + "type": "string", + "x-nullable": true, + "description": "A token to pass as a `page-token` query parameter to return the next page of results." + } + }, + "required": [ + "items", + "next_page_token" + ], + "description": "List of pipelines", + "title": "PipelineListResponse" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "project-slug", + "description": "Project slug in the form `vcs-slug/org-name/repo-name`. The `/` characters may be URL-escaped. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug`, replace `org-name` with the organization ID (found in Organization Settings), and replace `repo-name` with the project ID (found in Project Settings).", + "schema": { + "type": "string" + }, + "required": true, + "example": "gh/CircleCI-Public/api-preview-docs", + "allowReserved": true + }, + { + "in": "query", + "name": "page-token", + "description": "A token to retrieve the next page of results.", + "schema": { + "type": "string" + }, + "required": false, + "allowEmptyValue": true + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url \"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/pipeline/mine?page-token=example-value\" \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/pipeline/mine?page-token=example-value';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/project/gh/CircleCI-Public/api-preview-docs/pipeline/mine?page-token=example-value\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/pipeline/mine?page-token=example-value\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/pipeline/mine?page-token=example-value\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/project/{project-slug}/pipeline/{pipeline-number}": { + "get": { + "summary": "Get a pipeline by pipeline number", + "description": "Returns a pipeline by the pipeline number.", + "tags": [ + "Pipeline" + ], + "operationId": "getPipelineByNumber", + "responses": { + "200": { + "description": "A pipeline object.", + "links": { + "ProjectFromPipeline": { + "operationId": "getProjectBySlug", + "parameters": { + "project_slug": "$response.body#/project_slug" + } + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the pipeline.", + "example": "5034460f-c7c4-4c43-9457-de07e2029e7b" + }, + "errors": { + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The type of error." + }, + "message": { + "type": "string", + "description": "A human-readable error message." + } + }, + "required": [ + "type", + "message" + ], + "description": "An error with a type and message." + }, + "description": "A sequence of errors that have occurred within the pipeline." + }, + "project_slug": { + "type": "string", + "description": "The project-slug for the pipeline.", + "example": "gh/CircleCI-Public/api-preview-docs" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the pipeline was last updated." + }, + "number": { + "type": "integer", + "format": "int64", + "description": "The number of the pipeline.", + "example": 25 + }, + "trigger_parameters": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "integer", + "format": "int64" + }, + { + "type": "boolean" + }, + { + "type": "object" + } + ] + } + }, + "state": { + "type": "string", + "description": "The current state of the pipeline." + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the pipeline was created." + }, + "trigger": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The type of trigger." + }, + "received_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the trigger was received." + }, + "actor": { + "type": "object", + "properties": { + "login": { + "type": "string", + "description": "The login information for the user on the VCS.", + "title": "Login" + }, + "avatar_url": { + "type": "string", + "x-nullable": true, + "description": "URL to the user's avatar on the VCS" + } + }, + "required": [ + "login", + "avatar_url" + ], + "description": "The user who triggered the Pipeline." + } + }, + "required": [ + "type", + "received_at", + "actor" + ], + "description": "A summary of the trigger." + }, + "vcs": { + "type": "object", + "properties": { + "provider_name": { + "type": "string", + "description": "Name of the VCS provider (e.g. GitHub, Bitbucket).", + "example": "GitHub" + }, + "target_repository_url": { + "type": "string", + "description": "URL for the repository the trigger targets (i.e. the repository where the PR will be merged). For fork-PR pipelines, this is the URL to the parent repo. For other pipelines, the `origin_` and `target_repository_url`s will be the same.", + "example": "https://github.com/CircleCI-Public/api-preview-docs" + }, + "branch": { + "type": "string", + "description": "The branch where the pipeline ran. The HEAD commit on this branch was used for the pipeline. Note that `branch` and `tag` are mutually exclusive. To trigger a pipeline for a PR by number use `pull//head` for the PR ref or `pull//merge` for the merge ref (GitHub only).", + "example": "feature/design-new-api" + }, + "review_id": { + "type": "string", + "description": "The code review id.", + "example": "123" + }, + "review_url": { + "type": "string", + "description": "The code review URL.", + "example": "https://github.com/CircleCI-Public/api-preview-docs/pull/123" + }, + "revision": { + "type": "string", + "x-nullable": true, + "description": "The code revision the pipeline ran.", + "example": "f454a02b5d10fcccfd7d9dd7608a76d6493a98b4" + }, + "tag": { + "type": "string", + "description": "The tag used by the pipeline. The commit that this tag points to was used for the pipeline. Note that `branch` and `tag` are mutually exclusive.", + "example": "v3.1.4159" + }, + "commit": { + "type": "object", + "properties": { + "subject": { + "type": "string", + "x-nullable": true, + "description": "The subject of the commit message." + }, + "body": { + "type": "string", + "x-nullable": true, + "description": "The body of the commit message." + } + }, + "required": [ + "subject", + "body" + ], + "description": "The latest commit in the pipeline." + }, + "origin_repository_url": { + "type": "string", + "description": "URL for the repository where the trigger originated. For fork-PR pipelines, this is the URL to the fork. For other pipelines the `origin_` and `target_repository_url`s will be the same.", + "example": "https://github.com/CircleCI-Public/api-preview-docs" + } + }, + "required": [ + "provider_name", + "origin_repository_url", + "target_repository_url", + "revision" + ], + "description": "VCS information for the pipeline." + } + }, + "required": [ + "id", + "number", + "project_slug", + "created_at", + "errors", + "state", + "trigger" + ], + "description": "A pipeline response.", + "title": "Pipeline" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "project-slug", + "description": "Project slug in the form `vcs-slug/org-name/repo-name`. The `/` characters may be URL-escaped. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug`, replace `org-name` with the organization ID (found in Organization Settings), and replace `repo-name` with the project ID (found in Project Settings).", + "schema": { + "type": "string" + }, + "required": true, + "example": "gh/CircleCI-Public/api-preview-docs", + "allowReserved": true + }, + { + "in": "path", + "name": "pipeline-number", + "description": "The number of the pipeline.", + "schema": {}, + "required": true, + "example": "123" + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/pipeline/123 \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/pipeline/123';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/project/gh/CircleCI-Public/api-preview-docs/pipeline/123\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/pipeline/123\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/pipeline/123\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/project/{project-slug}/schedule": { + "post": { + "summary": "Create a schedule", + "description": "Not yet available to projects that use GitLab or GitHub App. Creates a schedule and returns the created schedule.", + "tags": [ + "Schedule" + ], + "operationId": "createSchedule", + "responses": { + "201": { + "description": "A schedule object.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the schedule." + }, + "timetable": { + "anyOf": [ + { + "type": "object", + "properties": { + "per-hour": { + "type": "integer", + "format": "integer", + "description": "Number of times a schedule triggers per hour, value must be between 1 and 60" + }, + "hours-of-day": { + "type": "array", + "items": { + "type": "integer", + "format": "integer", + "description": "Hour in a day in UTC, value must be between 0 and 24" + }, + "description": "Hours in a day in which the schedule triggers." + }, + "days-of-week": { + "type": "array", + "items": { + "type": "string", + "description": "Day in a week, in three letters format" + }, + "description": "Days in a week in which the schedule triggers." + }, + "days-of-month": { + "type": "array", + "items": { + "type": "integer", + "format": "integer", + "description": "Day in a month, between 1 and 31." + }, + "description": "Days in a month in which the schedule triggers. This is mutually exclusive with days in a week." + }, + "months": { + "type": "array", + "items": { + "type": "string", + "description": "Month, in three letters format." + }, + "description": "Months in which the schedule triggers." + } + }, + "required": [ + "per-hour", + "hours-of-day", + "days-of-week" + ] + }, + { + "type": "object", + "properties": { + "per-hour": { + "type": "integer", + "format": "integer", + "description": "Number of times a schedule triggers per hour, value must be between 1 and 60" + }, + "hours-of-day": { + "type": "array", + "items": { + "type": "integer", + "format": "integer", + "description": "Hour in a day in UTC, value must be between 0 and 24" + }, + "description": "Hours in a day in which the schedule triggers." + }, + "days-of-month": { + "type": "array", + "items": { + "type": "integer", + "format": "integer", + "description": "Day in a month, between 1 and 31." + }, + "description": "Days in a month in which the schedule triggers. This is mutually exclusive with days in a week." + }, + "days-of-week": { + "type": "array", + "items": { + "type": "string", + "description": "Day in a week, in three letters format" + }, + "description": "Days in a week in which the schedule triggers." + }, + "months": { + "type": "array", + "items": { + "type": "string", + "description": "Month, in three letters format." + }, + "description": "Months in which the schedule triggers." + } + }, + "required": [ + "per-hour", + "hours-of-day", + "days-of-month" + ] + } + ], + "description": "Timetable that specifies when a schedule triggers." + }, + "updated-at": { + "type": "string", + "format": "date-time", + "description": "The date and time the pipeline was last updated." + }, + "name": { + "type": "string", + "description": "Name of the schedule." + }, + "created-at": { + "type": "string", + "format": "date-time", + "description": "The date and time the pipeline was created." + }, + "project-slug": { + "type": "string", + "description": "The project-slug for the schedule", + "example": "gh/CircleCI-Public/api-preview-docs" + }, + "parameters": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "boolean" + } + ] + }, + "description": "Pipeline parameters represented as key-value pairs. Must contain branch or tag.", + "example": { + "deploy_prod": true, + "branch": "feature/design-new-api" + } + }, + "actor": { + "type": "object", + "properties": { + "avatar_url": { + "type": "string", + "x-nullable": true, + "description": "URL to the user's avatar on the VCS" + }, + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the user." + }, + "login": { + "type": "string", + "description": "The login information for the user on the VCS.", + "title": "Login" + }, + "name": { + "type": "string", + "description": "The name of the user." + } + }, + "required": [ + "avatar_url", + "id", + "login", + "name" + ], + "title": "User", + "description": "The attribution actor who will run the scheduled pipeline." + }, + "description": { + "type": "string", + "x-nullable": true, + "description": "Description of the schedule." + } + }, + "required": [ + "id", + "name", + "timetable", + "description", + "project-slug", + "actor", + "created-at", + "updated-at", + "parameters" + ], + "description": "A schedule response", + "title": "Schedule" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "project-slug", + "description": "Project slug in the form `vcs-slug/org-name/repo-name`. The `/` characters may be URL-escaped. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug`, replace `org-name` with the organization ID (found in Organization Settings), and replace `repo-name` with the project ID (found in Project Settings).", + "schema": { + "type": "string" + }, + "required": true, + "example": "gh/CircleCI-Public/api-preview-docs", + "allowReserved": true + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of the schedule." + }, + "timetable": { + "anyOf": [ + { + "type": "object", + "properties": { + "per-hour": { + "type": "integer", + "format": "integer", + "description": "Number of times a schedule triggers per hour, value must be between 1 and 60" + }, + "hours-of-day": { + "type": "array", + "items": { + "type": "integer", + "format": "integer", + "description": "Hour in a day in UTC, value must be between 0 and 24" + }, + "description": "Hours in a day in which the schedule triggers." + }, + "days-of-week": { + "type": "array", + "items": { + "type": "string", + "description": "Day in a week, in three letters format" + }, + "description": "Days in a week in which the schedule triggers." + }, + "days-of-month": { + "type": "array", + "items": { + "type": "integer", + "format": "integer", + "description": "Day in a month, between 1 and 31." + }, + "description": "Days in a month in which the schedule triggers. This is mutually exclusive with days in a week." + }, + "months": { + "type": "array", + "items": { + "type": "string", + "description": "Month, in three letters format." + }, + "description": "Months in which the schedule triggers." + } + }, + "required": [ + "per-hour", + "hours-of-day", + "days-of-week" + ] + }, + { + "type": "object", + "properties": { + "per-hour": { + "type": "integer", + "format": "integer", + "description": "Number of times a schedule triggers per hour, value must be between 1 and 60" + }, + "hours-of-day": { + "type": "array", + "items": { + "type": "integer", + "format": "integer", + "description": "Hour in a day in UTC, value must be between 0 and 24" + }, + "description": "Hours in a day in which the schedule triggers." + }, + "days-of-month": { + "type": "array", + "items": { + "type": "integer", + "format": "integer", + "description": "Day in a month, between 1 and 31." + }, + "description": "Days in a month in which the schedule triggers. This is mutually exclusive with days in a week." + }, + "days-of-week": { + "type": "array", + "items": { + "type": "string", + "description": "Day in a week, in three letters format" + }, + "description": "Days in a week in which the schedule triggers." + }, + "months": { + "type": "array", + "items": { + "type": "string", + "description": "Month, in three letters format." + }, + "description": "Months in which the schedule triggers." + } + }, + "required": [ + "per-hour", + "hours-of-day", + "days-of-month" + ] + } + ], + "description": "Timetable that specifies when a schedule triggers." + }, + "attribution-actor": { + "type": "string", + "description": "The attribution-actor of the scheduled pipeline.", + "example": "current" + }, + "parameters": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "boolean" + } + ] + }, + "description": "Pipeline parameters represented as key-value pairs. Must contain branch or tag.", + "example": { + "deploy_prod": true, + "branch": "feature/design-new-api" + } + }, + "description": { + "type": "string", + "x-nullable": true, + "description": "Description of the schedule." + } + }, + "required": [ + "name", + "timetable", + "attribution-actor", + "parameters" + ], + "description": "The parameters for a create schedule request", + "title": "CreateScheduleParameters" + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request POST \\\n --url https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/schedule \\\n --header \"Circle-Token: $CIRCLE_TOKEN\" \\\n --header \"Content-Type: application/json\" \\\n --data \"{\n \\\"name\\\": \\\"example-string\\\",\n \\\"timetable\\\": null,\n \\\"attribution-actor\\\": \\\"current\\\",\n \\\"parameters\\\": {\n \\\"deploy_prod\\\": true,\n \\\"branch\\\": \\\"feature/design-new-api\\\"\n }\n}\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/schedule';\n const options = {\n method: 'POST',\n headers: {'Circle-Token': '$CIRCLE_TOKEN', 'Content-Type': 'application/json'},\n body: '{\"name\":\"example-string\",\"timetable\":null,\"attribution-actor\":\"current\",\"parameters\":{\"deploy_prod\":true,\"branch\":\"feature/design-new-api\"}}'\n };\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\npayload = \"{\\n \\\"name\\\": \\\"example-string\\\",\\n \\\"timetable\\\": null,\\n \\\"attribution-actor\\\": \\\"current\\\",\\n \\\"parameters\\\": {\\n \\\"deploy_prod\\\": true,\\n \\\"branch\\\": \\\"feature/design-new-api\\\"\\n }\\n}\"\n\nheaders = {\n 'Circle-Token': \"$CIRCLE_TOKEN\",\n 'Content-Type': \"application/json\"\n}\n\nconn.request(\"POST\", \"/api/v2/project/gh/CircleCI-Public/api-preview-docs/schedule\", payload, headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/schedule\"\n\n\tpayload := strings.NewReader(\"{\\n \\\"name\\\": \\\"example-string\\\",\\n \\\"timetable\\\": null,\\n \\\"attribution-actor\\\": \\\"current\\\",\\n \\\"parameters\\\": {\\n \\\"deploy_prod\\\": true,\\n \\\"branch\\\": \\\"feature/design-new-api\\\"\\n }\\n}\")\n\n\treq, _ := http.NewRequest(\"POST\", url, payload)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/schedule\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Post.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\nrequest[\"Content-Type\"] = 'application/json'\nrequest.body = \"{\\n \\\"name\\\": \\\"example-string\\\",\\n \\\"timetable\\\": null,\\n \\\"attribution-actor\\\": \\\"current\\\",\\n \\\"parameters\\\": {\\n \\\"deploy_prod\\\": true,\\n \\\"branch\\\": \\\"feature/design-new-api\\\"\\n }\\n}\"\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + }, + "get": { + "summary": "Get all schedules", + "description": "Returns all schedules for this project.", + "tags": [ + "Schedule" + ], + "operationId": "listSchedulesForProject", + "responses": { + "200": { + "description": "A sequence of schedules.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the schedule." + }, + "timetable": { + "anyOf": [ + { + "type": "object", + "properties": { + "per-hour": { + "type": "integer", + "format": "integer", + "description": "Number of times a schedule triggers per hour, value must be between 1 and 60" + }, + "hours-of-day": { + "type": "array", + "items": { + "type": "integer", + "format": "integer", + "description": "Hour in a day in UTC, value must be between 0 and 24" + }, + "description": "Hours in a day in which the schedule triggers." + }, + "days-of-week": { + "type": "array", + "items": { + "type": "string", + "description": "Day in a week, in three letters format" + }, + "description": "Days in a week in which the schedule triggers." + }, + "days-of-month": { + "type": "array", + "items": { + "type": "integer", + "format": "integer", + "description": "Day in a month, between 1 and 31." + }, + "description": "Days in a month in which the schedule triggers. This is mutually exclusive with days in a week." + }, + "months": { + "type": "array", + "items": { + "type": "string", + "description": "Month, in three letters format." + }, + "description": "Months in which the schedule triggers." + } + }, + "required": [ + "per-hour", + "hours-of-day", + "days-of-week" + ] + }, + { + "type": "object", + "properties": { + "per-hour": { + "type": "integer", + "format": "integer", + "description": "Number of times a schedule triggers per hour, value must be between 1 and 60" + }, + "hours-of-day": { + "type": "array", + "items": { + "type": "integer", + "format": "integer", + "description": "Hour in a day in UTC, value must be between 0 and 24" + }, + "description": "Hours in a day in which the schedule triggers." + }, + "days-of-month": { + "type": "array", + "items": { + "type": "integer", + "format": "integer", + "description": "Day in a month, between 1 and 31." + }, + "description": "Days in a month in which the schedule triggers. This is mutually exclusive with days in a week." + }, + "days-of-week": { + "type": "array", + "items": { + "type": "string", + "description": "Day in a week, in three letters format" + }, + "description": "Days in a week in which the schedule triggers." + }, + "months": { + "type": "array", + "items": { + "type": "string", + "description": "Month, in three letters format." + }, + "description": "Months in which the schedule triggers." + } + }, + "required": [ + "per-hour", + "hours-of-day", + "days-of-month" + ] + } + ], + "description": "Timetable that specifies when a schedule triggers." + }, + "updated-at": { + "type": "string", + "format": "date-time", + "description": "The date and time the pipeline was last updated." + }, + "name": { + "type": "string", + "description": "Name of the schedule." + }, + "created-at": { + "type": "string", + "format": "date-time", + "description": "The date and time the pipeline was created." + }, + "project-slug": { + "type": "string", + "description": "The project-slug for the schedule", + "example": "gh/CircleCI-Public/api-preview-docs" + }, + "parameters": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "boolean" + } + ] + }, + "description": "Pipeline parameters represented as key-value pairs. Must contain branch or tag.", + "example": { + "deploy_prod": true, + "branch": "feature/design-new-api" + } + }, + "actor": { + "type": "object", + "properties": { + "avatar_url": { + "type": "string", + "x-nullable": true, + "description": "URL to the user's avatar on the VCS" + }, + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the user." + }, + "login": { + "type": "string", + "description": "The login information for the user on the VCS.", + "title": "Login" + }, + "name": { + "type": "string", + "description": "The name of the user." + } + }, + "required": [ + "avatar_url", + "id", + "login", + "name" + ], + "title": "User", + "description": "The attribution actor who will run the scheduled pipeline." + }, + "description": { + "type": "string", + "x-nullable": true, + "description": "Description of the schedule." + } + }, + "required": [ + "id", + "name", + "timetable", + "description", + "project-slug", + "actor", + "created-at", + "updated-at", + "parameters" + ], + "description": "A schedule response", + "title": "Schedule" + } + }, + "next_page_token": { + "type": "string", + "x-nullable": true, + "description": "A token to pass as a `page-token` query parameter to return the next page of results." + } + }, + "required": [ + "items", + "next_page_token" + ], + "description": "A sequence of schedules" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "project-slug", + "description": "Project slug in the form `vcs-slug/org-name/repo-name`. The `/` characters may be URL-escaped. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug`, replace `org-name` with the organization ID (found in Organization Settings), and replace `repo-name` with the project ID (found in Project Settings).", + "schema": { + "type": "string" + }, + "required": true, + "example": "gh/CircleCI-Public/api-preview-docs", + "allowReserved": true + }, + { + "in": "query", + "name": "page-token", + "description": "A token to retrieve the next page of results.", + "schema": { + "type": "string" + }, + "required": false, + "allowEmptyValue": true + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url \"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/schedule?page-token=example-value\" \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/schedule?page-token=example-value';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/project/gh/CircleCI-Public/api-preview-docs/schedule?page-token=example-value\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/schedule?page-token=example-value\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/schedule?page-token=example-value\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/project/{project-slug}/{job-number}/artifacts": { + "get": { + "summary": "Get a job's artifacts", + "description": "Returns a job's artifacts.", + "tags": [ + "Job" + ], + "operationId": "getJobArtifacts", + "responses": { + "200": { + "description": "A paginated list of the job's artifacts.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "type": "object", + "properties": { + "path": { + "type": "string", + "description": "The artifact path." + }, + "node_index": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "The index of the node that stored the artifact." + }, + "url": { + "type": "string", + "description": "The URL to download the artifact contents." + } + }, + "required": [ + "path", + "node_index", + "url" + ], + "description": "An artifact", + "title": "Artifact" + } + }, + "next_page_token": { + "type": "string", + "x-nullable": true, + "description": "A token to pass as a `page-token` query parameter to return the next page of results." + } + }, + "required": [ + "items", + "next_page_token" + ], + "title": "ArtifactListResponse" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "job-number", + "description": "The number of the job.", + "schema": {}, + "required": true, + "example": "123" + }, + { + "in": "path", + "name": "project-slug", + "description": "Project slug in the form `vcs-slug/org-name/repo-name`. The `/` characters may be URL-escaped. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug`, replace `org-name` with the organization ID (found in Organization Settings), and replace `repo-name` with the project ID (found in Project Settings).", + "schema": { + "type": "string" + }, + "required": true, + "example": "gh/CircleCI-Public/api-preview-docs", + "allowReserved": true + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/123/artifacts \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/123/artifacts';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/project/gh/CircleCI-Public/api-preview-docs/123/artifacts\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/123/artifacts\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/123/artifacts\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/project/{project-slug}/{job-number}/tests": { + "get": { + "summary": "Get test metadata", + "description": "Get test metadata for a build. In the rare case where there is more than 250MB of test data on the job, no results will be returned.", + "tags": [ + "Job" + ], + "operationId": "getTests", + "responses": { + "200": { + "description": "A paginated list of test results.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "type": "object", + "properties": { + "message": { + "type": "string", + "x-nullable": true, + "description": "The failure message associated with the test.", + "example": "" + }, + "source": { + "type": "string", + "description": "The program that generated the test results", + "example": "" + }, + "run_time": { + "type": "number", + "format": "double", + "description": "The time it took to run the test in seconds", + "example": "" + }, + "file": { + "type": "string", + "description": "The file in which the test is defined.", + "example": "" + }, + "result": { + "type": "string", + "description": "Indication of whether the test succeeded.", + "example": "" + }, + "name": { + "type": "string", + "description": "The name of the test.", + "example": "" + }, + "classname": { + "type": "string", + "description": "The programmatic location of the test.", + "example": "" + } + }, + "required": [ + "message", + "source", + "run_time", + "file", + "result", + "name", + "classname" + ] + }, + "title": "TestsResponse" + }, + "next_page_token": { + "type": "string", + "x-nullable": true, + "description": "A token to pass as a `page-token` query parameter to return the next page of results." + } + }, + "required": [ + "items", + "next_page_token" + ], + "title": "TestsResponse" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "job-number", + "description": "The number of the job.", + "schema": {}, + "required": true, + "example": "123" + }, + { + "in": "path", + "name": "project-slug", + "description": "Project slug in the form `vcs-slug/org-name/repo-name`. The `/` characters may be URL-escaped. For projects that use GitLab or GitHub App, use `circleci` as the `vcs-slug`, replace `org-name` with the organization ID (found in Organization Settings), and replace `repo-name` with the project ID (found in Project Settings).", + "schema": { + "type": "string" + }, + "required": true, + "example": "gh/CircleCI-Public/api-preview-docs", + "allowReserved": true + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/123/tests \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/123/tests';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/project/gh/CircleCI-Public/api-preview-docs/123/tests\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/123/tests\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/123/tests\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/schedule/{schedule-id}": { + "patch": { + "summary": "Update a schedule", + "description": "Not yet available to projects that use GitLab or GitHub App. Updates a schedule and returns the updated schedule.", + "tags": [ + "Schedule" + ], + "operationId": "updateSchedule", + "responses": { + "200": { + "description": "A schedule object.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the schedule." + }, + "timetable": { + "anyOf": [ + { + "type": "object", + "properties": { + "per-hour": { + "type": "integer", + "format": "integer", + "description": "Number of times a schedule triggers per hour, value must be between 1 and 60" + }, + "hours-of-day": { + "type": "array", + "items": { + "type": "integer", + "format": "integer", + "description": "Hour in a day in UTC, value must be between 0 and 24" + }, + "description": "Hours in a day in which the schedule triggers." + }, + "days-of-week": { + "type": "array", + "items": { + "type": "string", + "description": "Day in a week, in three letters format" + }, + "description": "Days in a week in which the schedule triggers." + }, + "days-of-month": { + "type": "array", + "items": { + "type": "integer", + "format": "integer", + "description": "Day in a month, between 1 and 31." + }, + "description": "Days in a month in which the schedule triggers. This is mutually exclusive with days in a week." + }, + "months": { + "type": "array", + "items": { + "type": "string", + "description": "Month, in three letters format." + }, + "description": "Months in which the schedule triggers." + } + }, + "required": [ + "per-hour", + "hours-of-day", + "days-of-week" + ] + }, + { + "type": "object", + "properties": { + "per-hour": { + "type": "integer", + "format": "integer", + "description": "Number of times a schedule triggers per hour, value must be between 1 and 60" + }, + "hours-of-day": { + "type": "array", + "items": { + "type": "integer", + "format": "integer", + "description": "Hour in a day in UTC, value must be between 0 and 24" + }, + "description": "Hours in a day in which the schedule triggers." + }, + "days-of-month": { + "type": "array", + "items": { + "type": "integer", + "format": "integer", + "description": "Day in a month, between 1 and 31." + }, + "description": "Days in a month in which the schedule triggers. This is mutually exclusive with days in a week." + }, + "days-of-week": { + "type": "array", + "items": { + "type": "string", + "description": "Day in a week, in three letters format" + }, + "description": "Days in a week in which the schedule triggers." + }, + "months": { + "type": "array", + "items": { + "type": "string", + "description": "Month, in three letters format." + }, + "description": "Months in which the schedule triggers." + } + }, + "required": [ + "per-hour", + "hours-of-day", + "days-of-month" + ] + } + ], + "description": "Timetable that specifies when a schedule triggers." + }, + "updated-at": { + "type": "string", + "format": "date-time", + "description": "The date and time the pipeline was last updated." + }, + "name": { + "type": "string", + "description": "Name of the schedule." + }, + "created-at": { + "type": "string", + "format": "date-time", + "description": "The date and time the pipeline was created." + }, + "project-slug": { + "type": "string", + "description": "The project-slug for the schedule", + "example": "gh/CircleCI-Public/api-preview-docs" + }, + "parameters": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "boolean" + } + ] + }, + "description": "Pipeline parameters represented as key-value pairs. Must contain branch or tag.", + "example": { + "deploy_prod": true, + "branch": "feature/design-new-api" + } + }, + "actor": { + "type": "object", + "properties": { + "avatar_url": { + "type": "string", + "x-nullable": true, + "description": "URL to the user's avatar on the VCS" + }, + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the user." + }, + "login": { + "type": "string", + "description": "The login information for the user on the VCS.", + "title": "Login" + }, + "name": { + "type": "string", + "description": "The name of the user." + } + }, + "required": [ + "avatar_url", + "id", + "login", + "name" + ], + "title": "User", + "description": "The attribution actor who will run the scheduled pipeline." + }, + "description": { + "type": "string", + "x-nullable": true, + "description": "Description of the schedule." + } + }, + "required": [ + "id", + "name", + "timetable", + "description", + "project-slug", + "actor", + "created-at", + "updated-at", + "parameters" + ], + "description": "A schedule response", + "title": "Schedule" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "schedule-id", + "description": "The unique ID of the schedule.", + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "description": { + "type": "string", + "x-nullable": true, + "description": "Description of the schedule." + }, + "name": { + "type": "string", + "description": "Name of the schedule." + }, + "timetable": { + "type": "object", + "properties": { + "per-hour": { + "type": "integer", + "format": "integer", + "description": "Number of times a schedule triggers per hour, value must be between 1 and 60" + }, + "hours-of-day": { + "type": "array", + "items": { + "type": "integer", + "format": "integer", + "description": "Hour in a day in UTC, value must be between 0 and 24" + }, + "description": "Hours in a day in which the schedule triggers." + }, + "days-of-week": { + "type": "array", + "items": { + "type": "string", + "description": "Day in a week, in three letters format" + }, + "description": "Days in a week in which the schedule triggers." + }, + "days-of-month": { + "type": "array", + "items": { + "type": "integer", + "format": "integer", + "description": "Day in a month, between 1 and 31." + }, + "description": "Days in a month in which the schedule triggers. This is mutually exclusive with days in a week." + }, + "months": { + "type": "array", + "items": { + "type": "string", + "description": "Month, in three letters format." + }, + "description": "Months in which the schedule triggers." + } + }, + "description": "Timetable that specifies when a schedule triggers." + }, + "attribution-actor": { + "type": "string", + "description": "The attribution-actor of the scheduled pipeline.", + "example": "current" + }, + "parameters": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "boolean" + } + ] + }, + "description": "Pipeline parameters represented as key-value pairs. Must contain branch or tag.", + "example": { + "deploy_prod": true, + "branch": "feature/design-new-api" + } + } + }, + "description": "The parameters for an update schedule request", + "title": "UpdateScheduleParameters" + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request PATCH \\\n --url https://circleci.com/api/v2/schedule/497f6eca-6276-4993-bfeb-53cbbbba6f08 \\\n --header \"Circle-Token: $CIRCLE_TOKEN\" \\\n --header \"Content-Type: application/json\" \\\n --data \"{\n \\\"description\\\": \\\"example-string\\\",\n \\\"name\\\": \\\"example-string\\\",\n \\\"timetable\\\": {\n \\\"per-hour\\\": 123,\n \\\"hours-of-day\\\": [\n 123\n ],\n \\\"days-of-week\\\": [\n \\\"TUE\\\"\n ]\n }\n}\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/schedule/497f6eca-6276-4993-bfeb-53cbbbba6f08';\n const options = {\n method: 'PATCH',\n headers: {'Circle-Token': '$CIRCLE_TOKEN', 'Content-Type': 'application/json'},\n body: '{\"description\":\"example-string\",\"name\":\"example-string\",\"timetable\":{\"per-hour\":123,\"hours-of-day\":[123],\"days-of-week\":[\"TUE\"]}}'\n };\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\npayload = \"{\\n \\\"description\\\": \\\"example-string\\\",\\n \\\"name\\\": \\\"example-string\\\",\\n \\\"timetable\\\": {\\n \\\"per-hour\\\": 123,\\n \\\"hours-of-day\\\": [\\n 123\\n ],\\n \\\"days-of-week\\\": [\\n \\\"TUE\\\"\\n ]\\n }\\n}\"\n\nheaders = {\n 'Circle-Token': \"$CIRCLE_TOKEN\",\n 'Content-Type': \"application/json\"\n}\n\nconn.request(\"PATCH\", \"/api/v2/schedule/497f6eca-6276-4993-bfeb-53cbbbba6f08\", payload, headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/schedule/497f6eca-6276-4993-bfeb-53cbbbba6f08\"\n\n\tpayload := strings.NewReader(\"{\\n \\\"description\\\": \\\"example-string\\\",\\n \\\"name\\\": \\\"example-string\\\",\\n \\\"timetable\\\": {\\n \\\"per-hour\\\": 123,\\n \\\"hours-of-day\\\": [\\n 123\\n ],\\n \\\"days-of-week\\\": [\\n \\\"TUE\\\"\\n ]\\n }\\n}\")\n\n\treq, _ := http.NewRequest(\"PATCH\", url, payload)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/schedule/497f6eca-6276-4993-bfeb-53cbbbba6f08\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Patch.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\nrequest[\"Content-Type\"] = 'application/json'\nrequest.body = \"{\\n \\\"description\\\": \\\"example-string\\\",\\n \\\"name\\\": \\\"example-string\\\",\\n \\\"timetable\\\": {\\n \\\"per-hour\\\": 123,\\n \\\"hours-of-day\\\": [\\n 123\\n ],\\n \\\"days-of-week\\\": [\\n \\\"TUE\\\"\\n ]\\n }\\n}\"\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + }, + "delete": { + "summary": "Delete a schedule", + "description": "Not yet available to projects that use GitLab or GitHub App. Deletes the schedule by id.", + "tags": [ + "Schedule" + ], + "operationId": "deleteScheduleById", + "responses": { + "200": { + "description": "A confirmation message.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "A human-readable message" + } + }, + "required": [ + "message" + ], + "description": "message response", + "title": "MessageResponse" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "schedule-id", + "description": "The unique ID of the schedule.", + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request DELETE \\\n --url https://circleci.com/api/v2/schedule/497f6eca-6276-4993-bfeb-53cbbbba6f08 \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/schedule/497f6eca-6276-4993-bfeb-53cbbbba6f08';\n const options = {method: 'DELETE', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"DELETE\", \"/api/v2/schedule/497f6eca-6276-4993-bfeb-53cbbbba6f08\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/schedule/497f6eca-6276-4993-bfeb-53cbbbba6f08\"\n\n\treq, _ := http.NewRequest(\"DELETE\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/schedule/497f6eca-6276-4993-bfeb-53cbbbba6f08\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Delete.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + }, + "get": { + "summary": "Get a schedule", + "description": "Get a schedule by id.", + "tags": [ + "Schedule" + ], + "operationId": "getScheduleById", + "responses": { + "200": { + "description": "A schedule object.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the schedule." + }, + "timetable": { + "anyOf": [ + { + "type": "object", + "properties": { + "per-hour": { + "type": "integer", + "format": "integer", + "description": "Number of times a schedule triggers per hour, value must be between 1 and 60" + }, + "hours-of-day": { + "type": "array", + "items": { + "type": "integer", + "format": "integer", + "description": "Hour in a day in UTC, value must be between 0 and 24" + }, + "description": "Hours in a day in which the schedule triggers." + }, + "days-of-week": { + "type": "array", + "items": { + "type": "string", + "description": "Day in a week, in three letters format" + }, + "description": "Days in a week in which the schedule triggers." + }, + "days-of-month": { + "type": "array", + "items": { + "type": "integer", + "format": "integer", + "description": "Day in a month, between 1 and 31." + }, + "description": "Days in a month in which the schedule triggers. This is mutually exclusive with days in a week." + }, + "months": { + "type": "array", + "items": { + "type": "string", + "description": "Month, in three letters format." + }, + "description": "Months in which the schedule triggers." + } + }, + "required": [ + "per-hour", + "hours-of-day", + "days-of-week" + ] + }, + { + "type": "object", + "properties": { + "per-hour": { + "type": "integer", + "format": "integer", + "description": "Number of times a schedule triggers per hour, value must be between 1 and 60" + }, + "hours-of-day": { + "type": "array", + "items": { + "type": "integer", + "format": "integer", + "description": "Hour in a day in UTC, value must be between 0 and 24" + }, + "description": "Hours in a day in which the schedule triggers." + }, + "days-of-month": { + "type": "array", + "items": { + "type": "integer", + "format": "integer", + "description": "Day in a month, between 1 and 31." + }, + "description": "Days in a month in which the schedule triggers. This is mutually exclusive with days in a week." + }, + "days-of-week": { + "type": "array", + "items": { + "type": "string", + "description": "Day in a week, in three letters format" + }, + "description": "Days in a week in which the schedule triggers." + }, + "months": { + "type": "array", + "items": { + "type": "string", + "description": "Month, in three letters format." + }, + "description": "Months in which the schedule triggers." + } + }, + "required": [ + "per-hour", + "hours-of-day", + "days-of-month" + ] + } + ], + "description": "Timetable that specifies when a schedule triggers." + }, + "updated-at": { + "type": "string", + "format": "date-time", + "description": "The date and time the pipeline was last updated." + }, + "name": { + "type": "string", + "description": "Name of the schedule." + }, + "created-at": { + "type": "string", + "format": "date-time", + "description": "The date and time the pipeline was created." + }, + "project-slug": { + "type": "string", + "description": "The project-slug for the schedule", + "example": "gh/CircleCI-Public/api-preview-docs" + }, + "parameters": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "string" + }, + { + "type": "boolean" + } + ] + }, + "description": "Pipeline parameters represented as key-value pairs. Must contain branch or tag.", + "example": { + "deploy_prod": true, + "branch": "feature/design-new-api" + } + }, + "actor": { + "type": "object", + "properties": { + "avatar_url": { + "type": "string", + "x-nullable": true, + "description": "URL to the user's avatar on the VCS" + }, + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the user." + }, + "login": { + "type": "string", + "description": "The login information for the user on the VCS.", + "title": "Login" + }, + "name": { + "type": "string", + "description": "The name of the user." + } + }, + "required": [ + "avatar_url", + "id", + "login", + "name" + ], + "title": "User", + "description": "The attribution actor who will run the scheduled pipeline." + }, + "description": { + "type": "string", + "x-nullable": true, + "description": "Description of the schedule." + } + }, + "required": [ + "id", + "name", + "timetable", + "description", + "project-slug", + "actor", + "created-at", + "updated-at", + "parameters" + ], + "description": "A schedule response", + "title": "Schedule" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "schedule-id", + "description": "The unique ID of the schedule.", + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/schedule/497f6eca-6276-4993-bfeb-53cbbbba6f08 \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/schedule/497f6eca-6276-4993-bfeb-53cbbbba6f08';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/schedule/497f6eca-6276-4993-bfeb-53cbbbba6f08\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/schedule/497f6eca-6276-4993-bfeb-53cbbbba6f08\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/schedule/497f6eca-6276-4993-bfeb-53cbbbba6f08\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/user/{id}": { + "get": { + "summary": "User Information", + "description": "Provides information about the user with the given ID.", + "tags": [ + "User" + ], + "operationId": "getUser", + "responses": { + "200": { + "description": "User login information.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "avatar_url": { + "type": "string", + "x-nullable": true, + "description": "URL to the user's avatar on the VCS" + }, + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the user." + }, + "login": { + "type": "string", + "description": "The login information for the user on the VCS.", + "title": "Login" + }, + "name": { + "type": "string", + "description": "The name of the user." + } + }, + "required": [ + "avatar_url", + "id", + "login", + "name" + ], + "title": "User" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "id", + "description": "The unique ID of the user.", + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/user/497f6eca-6276-4993-bfeb-53cbbbba6f08 \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/user/497f6eca-6276-4993-bfeb-53cbbbba6f08';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/user/497f6eca-6276-4993-bfeb-53cbbbba6f08\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/user/497f6eca-6276-4993-bfeb-53cbbbba6f08\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/user/497f6eca-6276-4993-bfeb-53cbbbba6f08\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/webhook": { + "post": { + "summary": "Create an outbound webhook", + "description": "Creates an outbound webhook.", + "tags": [ + "Webhook" + ], + "operationId": "createWebhook", + "responses": { + "201": { + "description": "A webhook", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "URL to deliver the webhook to. Note: protocol must be included as well (only https is supported)" + }, + "verify-tls": { + "type": "boolean", + "description": "Whether to enforce TLS certificate verification when delivering the webhook" + }, + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the webhook" + }, + "signing-secret": { + "type": "string", + "description": "Masked value of the secret used to build an HMAC hash of the payload and passed as a header in the webhook request" + }, + "updated-at": { + "type": "string", + "format": "date-time", + "description": "The date and time the webhook was last updated.", + "example": "2015-09-21T17:29:21.042Z" + }, + "name": { + "type": "string", + "description": "Name of the webhook" + }, + "created-at": { + "type": "string", + "format": "date-time", + "description": "The date and time the webhook was created.", + "example": "2015-09-21T17:29:21.042Z" + }, + "scope": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "ID of the scope being used (at the moment, only project ID is supported)" + }, + "type": { + "type": "string", + "description": "Type of the scope being used" + } + }, + "required": [ + "id", + "type" + ], + "description": "The scope in which the relevant events that will trigger webhooks" + }, + "events": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Events that will trigger the webhook" + } + }, + "required": [ + "id", + "scope", + "name", + "events", + "url", + "verify-tls", + "signing-secret", + "created-at", + "updated-at" + ], + "title": "Webhook" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of the webhook" + }, + "events": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Events that will trigger the webhook" + }, + "url": { + "type": "string", + "description": "URL to deliver the webhook to. Note: protocol must be included as well (only https is supported)" + }, + "verify-tls": { + "type": "boolean", + "description": "Whether to enforce TLS certificate verification when delivering the webhook" + }, + "signing-secret": { + "type": "string", + "description": "Secret used to build an HMAC hash of the payload and passed as a header in the webhook request" + }, + "scope": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "ID of the scope being used (at the moment, only project ID is supported)" + }, + "type": { + "type": "string", + "description": "Type of the scope being used" + } + }, + "required": [ + "id", + "type" + ], + "description": "The scope in which the relevant events that will trigger webhooks" + } + }, + "required": [ + "name", + "events", + "url", + "verify-tls", + "signing-secret", + "scope" + ], + "description": "The parameters for a create webhook request" + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request POST \\\n --url https://circleci.com/api/v2/webhook \\\n --header \"Circle-Token: $CIRCLE_TOKEN\" \\\n --header \"Content-Type: application/json\" \\\n --data \"{\n \\\"name\\\": \\\"example-string\\\",\n \\\"events\\\": [\n \\\"workflow-completed\\\"\n ],\n \\\"url\\\": \\\"example-string\\\",\n \\\"verify-tls\\\": true,\n \\\"signing-secret\\\": \\\"example-string\\\",\n \\\"scope\\\": {\n \\\"id\\\": \\\"example-string\\\",\n \\\"type\\\": \\\"project\\\"\n }\n}\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/webhook';\n const options = {\n method: 'POST',\n headers: {'Circle-Token': '$CIRCLE_TOKEN', 'Content-Type': 'application/json'},\n body: '{\"name\":\"example-string\",\"events\":[\"workflow-completed\"],\"url\":\"example-string\",\"verify-tls\":true,\"signing-secret\":\"example-string\",\"scope\":{\"id\":\"example-string\",\"type\":\"project\"}}'\n };\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\npayload = \"{\\n \\\"name\\\": \\\"example-string\\\",\\n \\\"events\\\": [\\n \\\"workflow-completed\\\"\\n ],\\n \\\"url\\\": \\\"example-string\\\",\\n \\\"verify-tls\\\": true,\\n \\\"signing-secret\\\": \\\"example-string\\\",\\n \\\"scope\\\": {\\n \\\"id\\\": \\\"example-string\\\",\\n \\\"type\\\": \\\"project\\\"\\n }\\n}\"\n\nheaders = {\n 'Circle-Token': \"$CIRCLE_TOKEN\",\n 'Content-Type': \"application/json\"\n}\n\nconn.request(\"POST\", \"/api/v2/webhook\", payload, headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/webhook\"\n\n\tpayload := strings.NewReader(\"{\\n \\\"name\\\": \\\"example-string\\\",\\n \\\"events\\\": [\\n \\\"workflow-completed\\\"\\n ],\\n \\\"url\\\": \\\"example-string\\\",\\n \\\"verify-tls\\\": true,\\n \\\"signing-secret\\\": \\\"example-string\\\",\\n \\\"scope\\\": {\\n \\\"id\\\": \\\"example-string\\\",\\n \\\"type\\\": \\\"project\\\"\\n }\\n}\")\n\n\treq, _ := http.NewRequest(\"POST\", url, payload)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/webhook\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Post.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\nrequest[\"Content-Type\"] = 'application/json'\nrequest.body = \"{\\n \\\"name\\\": \\\"example-string\\\",\\n \\\"events\\\": [\\n \\\"workflow-completed\\\"\\n ],\\n \\\"url\\\": \\\"example-string\\\",\\n \\\"verify-tls\\\": true,\\n \\\"signing-secret\\\": \\\"example-string\\\",\\n \\\"scope\\\": {\\n \\\"id\\\": \\\"example-string\\\",\\n \\\"type\\\": \\\"project\\\"\\n }\\n}\"\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + }, + "get": { + "summary": "List webhooks", + "description": "Get a list of outbound webhooks that match the given scope-type and scope-id", + "tags": [ + "Webhook" + ], + "operationId": "getWebhooks", + "responses": { + "200": { + "description": "A list of webhooks", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "URL to deliver the webhook to. Note: protocol must be included as well (only https is supported)" + }, + "verify-tls": { + "type": "boolean", + "description": "Whether to enforce TLS certificate verification when delivering the webhook" + }, + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the webhook" + }, + "signing-secret": { + "type": "string", + "description": "Masked value of the secret used to build an HMAC hash of the payload and passed as a header in the webhook request" + }, + "updated-at": { + "type": "string", + "format": "date-time", + "description": "The date and time the webhook was last updated.", + "example": "2015-09-21T17:29:21.042Z" + }, + "name": { + "type": "string", + "description": "Name of the webhook" + }, + "created-at": { + "type": "string", + "format": "date-time", + "description": "The date and time the webhook was created.", + "example": "2015-09-21T17:29:21.042Z" + }, + "scope": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "ID of the scope being used (at the moment, only project ID is supported)" + }, + "type": { + "type": "string", + "description": "Type of the scope being used" + } + }, + "required": [ + "id", + "type" + ], + "description": "The scope in which the relevant events that will trigger webhooks" + }, + "events": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Events that will trigger the webhook" + } + }, + "required": [ + "id", + "scope", + "name", + "events", + "url", + "verify-tls", + "signing-secret", + "created-at", + "updated-at" + ], + "title": "Webhook" + } + }, + "next_page_token": { + "type": "string", + "x-nullable": true, + "description": "A token to pass as a `page-token` query parameter to return the next page of results." + } + }, + "required": [ + "items", + "next_page_token" + ], + "description": "A list of webhooks" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "query", + "name": "scope-id", + "description": "ID of the scope being used (at the moment, only project ID is supported)", + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true + }, + { + "in": "query", + "name": "scope-type", + "description": "Type of the scope being used", + "schema": { + "type": "string" + }, + "required": true + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url \"https://circleci.com/api/v2/webhook?scope-id=497f6eca-6276-4993-bfeb-53cbbbba6f08&scope-type=project\" \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/webhook?scope-id=497f6eca-6276-4993-bfeb-53cbbbba6f08&scope-type=project';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/webhook?scope-id=497f6eca-6276-4993-bfeb-53cbbbba6f08&scope-type=project\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/webhook?scope-id=497f6eca-6276-4993-bfeb-53cbbbba6f08&scope-type=project\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/webhook?scope-id=497f6eca-6276-4993-bfeb-53cbbbba6f08&scope-type=project\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/webhook/{webhook-id}": { + "put": { + "summary": "Update an outbound webhook", + "description": "Updates an outbound webhook.", + "tags": [ + "Webhook" + ], + "operationId": "updateWebhook", + "responses": { + "200": { + "description": "A webhook", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "URL to deliver the webhook to. Note: protocol must be included as well (only https is supported)" + }, + "verify-tls": { + "type": "boolean", + "description": "Whether to enforce TLS certificate verification when delivering the webhook" + }, + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the webhook" + }, + "signing-secret": { + "type": "string", + "description": "Masked value of the secret used to build an HMAC hash of the payload and passed as a header in the webhook request" + }, + "updated-at": { + "type": "string", + "format": "date-time", + "description": "The date and time the webhook was last updated.", + "example": "2015-09-21T17:29:21.042Z" + }, + "name": { + "type": "string", + "description": "Name of the webhook" + }, + "created-at": { + "type": "string", + "format": "date-time", + "description": "The date and time the webhook was created.", + "example": "2015-09-21T17:29:21.042Z" + }, + "scope": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "ID of the scope being used (at the moment, only project ID is supported)" + }, + "type": { + "type": "string", + "description": "Type of the scope being used" + } + }, + "required": [ + "id", + "type" + ], + "description": "The scope in which the relevant events that will trigger webhooks" + }, + "events": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Events that will trigger the webhook" + } + }, + "required": [ + "id", + "scope", + "name", + "events", + "url", + "verify-tls", + "signing-secret", + "created-at", + "updated-at" + ], + "title": "Webhook" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "webhook-id", + "description": "ID of the webhook (UUID)", + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of the webhook" + }, + "events": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Events that will trigger the webhook" + }, + "url": { + "type": "string", + "description": "URL to deliver the webhook to. Note: protocol must be included as well (only https is supported)" + }, + "signing-secret": { + "type": "string", + "description": "Secret used to build an HMAC hash of the payload and passed as a header in the webhook request" + }, + "verify-tls": { + "type": "boolean", + "description": "Whether to enforce TLS certificate verification when delivering the webhook" + } + }, + "description": "The parameters for an update webhook request" + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request PUT \\\n --url https://circleci.com/api/v2/webhook/497f6eca-6276-4993-bfeb-53cbbbba6f08 \\\n --header \"Circle-Token: $CIRCLE_TOKEN\" \\\n --header \"Content-Type: application/json\" \\\n --data \"{\n \\\"name\\\": \\\"example-string\\\",\n \\\"events\\\": [\n \\\"workflow-completed\\\"\n ],\n \\\"url\\\": \\\"example-string\\\"\n}\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/webhook/497f6eca-6276-4993-bfeb-53cbbbba6f08';\n const options = {\n method: 'PUT',\n headers: {'Circle-Token': '$CIRCLE_TOKEN', 'Content-Type': 'application/json'},\n body: '{\"name\":\"example-string\",\"events\":[\"workflow-completed\"],\"url\":\"example-string\"}'\n };\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\npayload = \"{\\n \\\"name\\\": \\\"example-string\\\",\\n \\\"events\\\": [\\n \\\"workflow-completed\\\"\\n ],\\n \\\"url\\\": \\\"example-string\\\"\\n}\"\n\nheaders = {\n 'Circle-Token': \"$CIRCLE_TOKEN\",\n 'Content-Type': \"application/json\"\n}\n\nconn.request(\"PUT\", \"/api/v2/webhook/497f6eca-6276-4993-bfeb-53cbbbba6f08\", payload, headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/webhook/497f6eca-6276-4993-bfeb-53cbbbba6f08\"\n\n\tpayload := strings.NewReader(\"{\\n \\\"name\\\": \\\"example-string\\\",\\n \\\"events\\\": [\\n \\\"workflow-completed\\\"\\n ],\\n \\\"url\\\": \\\"example-string\\\"\\n}\")\n\n\treq, _ := http.NewRequest(\"PUT\", url, payload)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/webhook/497f6eca-6276-4993-bfeb-53cbbbba6f08\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Put.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\nrequest[\"Content-Type\"] = 'application/json'\nrequest.body = \"{\\n \\\"name\\\": \\\"example-string\\\",\\n \\\"events\\\": [\\n \\\"workflow-completed\\\"\\n ],\\n \\\"url\\\": \\\"example-string\\\"\\n}\"\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + }, + "delete": { + "summary": "Delete an outbound webhook", + "description": "Deletes an outbound webhook", + "tags": [ + "Webhook" + ], + "operationId": "deleteWebhook", + "responses": { + "200": { + "description": "A confirmation message", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "A human-readable message" + } + }, + "required": [ + "message" + ], + "description": "message response", + "title": "MessageResponse" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "webhook-id", + "description": "ID of the webhook (UUID)", + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request DELETE \\\n --url https://circleci.com/api/v2/webhook/497f6eca-6276-4993-bfeb-53cbbbba6f08 \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/webhook/497f6eca-6276-4993-bfeb-53cbbbba6f08';\n const options = {method: 'DELETE', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"DELETE\", \"/api/v2/webhook/497f6eca-6276-4993-bfeb-53cbbbba6f08\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/webhook/497f6eca-6276-4993-bfeb-53cbbbba6f08\"\n\n\treq, _ := http.NewRequest(\"DELETE\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/webhook/497f6eca-6276-4993-bfeb-53cbbbba6f08\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Delete.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + }, + "get": { + "summary": "Get a webhook", + "description": "Get an outbound webhook by id.", + "tags": [ + "Webhook" + ], + "operationId": "getWebhookById", + "responses": { + "200": { + "description": "A webhook", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "URL to deliver the webhook to. Note: protocol must be included as well (only https is supported)" + }, + "verify-tls": { + "type": "boolean", + "description": "Whether to enforce TLS certificate verification when delivering the webhook" + }, + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the webhook" + }, + "signing-secret": { + "type": "string", + "description": "Masked value of the secret used to build an HMAC hash of the payload and passed as a header in the webhook request" + }, + "updated-at": { + "type": "string", + "format": "date-time", + "description": "The date and time the webhook was last updated.", + "example": "2015-09-21T17:29:21.042Z" + }, + "name": { + "type": "string", + "description": "Name of the webhook" + }, + "created-at": { + "type": "string", + "format": "date-time", + "description": "The date and time the webhook was created.", + "example": "2015-09-21T17:29:21.042Z" + }, + "scope": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "ID of the scope being used (at the moment, only project ID is supported)" + }, + "type": { + "type": "string", + "description": "Type of the scope being used" + } + }, + "required": [ + "id", + "type" + ], + "description": "The scope in which the relevant events that will trigger webhooks" + }, + "events": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Events that will trigger the webhook" + } + }, + "required": [ + "id", + "scope", + "name", + "events", + "url", + "verify-tls", + "signing-secret", + "created-at", + "updated-at" + ], + "title": "Webhook" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "webhook-id", + "description": "ID of the webhook (UUID)", + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/webhook/497f6eca-6276-4993-bfeb-53cbbbba6f08 \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/webhook/497f6eca-6276-4993-bfeb-53cbbbba6f08';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/webhook/497f6eca-6276-4993-bfeb-53cbbbba6f08\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/webhook/497f6eca-6276-4993-bfeb-53cbbbba6f08\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/webhook/497f6eca-6276-4993-bfeb-53cbbbba6f08\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/workflow/{id}": { + "get": { + "summary": "Get a workflow", + "description": "Returns summary fields of a workflow by ID.", + "tags": [ + "Workflow" + ], + "operationId": "getWorkflowById", + "responses": { + "200": { + "description": "A workflow object.", + "links": { + "ProjectFromGetWorkflow": { + "operationId": "getProjectBySlug", + "parameters": { + "project_slug": "$response.body#/project_slug" + } + }, + "WorkflowJobs": { + "operationId": "listWorkflowJobs", + "parameters": { + "id": "$response.body#/id" + } + }, + "CancelWorkflow": { + "operationId": "cancelWorkflow", + "parameters": { + "id": "$response.body#/id" + } + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "pipeline_id": { + "type": "string", + "format": "uuid", + "description": "The ID of the pipeline this workflow belongs to.", + "example": "5034460f-c7c4-4c43-9457-de07e2029e7b" + }, + "canceled_by": { + "type": "string", + "format": "uuid" + }, + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the workflow." + }, + "auto_rerun_number": { + "type": "integer", + "format": "int64", + "minimum": 1, + "description": "Present if this workflow was auto-rerun from a previous workflow. The Nth auto-rerun workflow will have auto_rerun_number N", + "example": 1 + }, + "name": { + "type": "string", + "description": "The name of the workflow.", + "example": "build-and-test" + }, + "project_slug": { + "type": "string", + "description": "The project-slug for the pipeline this workflow belongs to.", + "example": "gh/CircleCI-Public/api-preview-docs" + }, + "errored_by": { + "type": "string", + "format": "uuid" + }, + "tag": { + "type": "string", + "x-nullable": true, + "description": "Tag used for the workflow", + "example": "setup" + }, + "status": { + "type": "string", + "description": "The current status of the workflow." + }, + "started_by": { + "type": "string", + "format": "uuid" + }, + "max_auto_reruns": { + "type": "integer", + "format": "int64", + "minimum": 1, + "description": "The maximum number of auto reruns specified for the workflow.", + "example": 5 + }, + "pipeline_number": { + "type": "integer", + "format": "int64", + "description": "The number of the pipeline this workflow belongs to.", + "example": 25 + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the workflow was created." + }, + "stopped_at": { + "type": "string", + "format": "date-time", + "x-nullable": true, + "description": "The date and time the workflow stopped." + } + }, + "required": [ + "id", + "name", + "status", + "created_at", + "stopped_at", + "pipeline_id", + "pipeline_number", + "project_slug", + "started_by" + ], + "description": "A workflow", + "title": "Workflow" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "id", + "description": "The unique ID of the workflow.", + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true, + "example": "5034460f-c7c4-4c43-9457-de07e2029e7b" + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/workflow/5034460f-c7c4-4c43-9457-de07e2029e7b \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/workflow/5034460f-c7c4-4c43-9457-de07e2029e7b';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/workflow/5034460f-c7c4-4c43-9457-de07e2029e7b\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/workflow/5034460f-c7c4-4c43-9457-de07e2029e7b\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/workflow/5034460f-c7c4-4c43-9457-de07e2029e7b\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/workflow/{id}/approve/{approval_request_id}": { + "post": { + "summary": "Approve a job", + "description": "Approves a pending approval job in a workflow.", + "tags": [ + "Workflow" + ], + "operationId": "approvePendingApprovalJobById", + "responses": { + "202": { + "description": "A confirmation message.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "A human-readable message" + } + }, + "required": [ + "message" + ], + "description": "message response", + "title": "MessageResponse" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "approval_request_id", + "description": "The ID of the job being approved.", + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true + }, + { + "in": "path", + "name": "id", + "description": "The unique ID of the workflow.", + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true, + "example": "5034460f-c7c4-4c43-9457-de07e2029e7b" + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request POST \\\n --url https://circleci.com/api/v2/workflow/5034460f-c7c4-4c43-9457-de07e2029e7b/approve/497f6eca-6276-4993-bfeb-53cbbbba6f08 \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/workflow/5034460f-c7c4-4c43-9457-de07e2029e7b/approve/497f6eca-6276-4993-bfeb-53cbbbba6f08';\n const options = {method: 'POST', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"POST\", \"/api/v2/workflow/5034460f-c7c4-4c43-9457-de07e2029e7b/approve/497f6eca-6276-4993-bfeb-53cbbbba6f08\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/workflow/5034460f-c7c4-4c43-9457-de07e2029e7b/approve/497f6eca-6276-4993-bfeb-53cbbbba6f08\"\n\n\treq, _ := http.NewRequest(\"POST\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/workflow/5034460f-c7c4-4c43-9457-de07e2029e7b/approve/497f6eca-6276-4993-bfeb-53cbbbba6f08\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Post.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/workflow/{id}/cancel": { + "post": { + "summary": "Cancel a workflow", + "description": "Cancels a running workflow.", + "tags": [ + "Workflow" + ], + "operationId": "cancelWorkflow", + "responses": { + "202": { + "description": "A confirmation message.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "A human-readable message" + } + }, + "required": [ + "message" + ], + "description": "message response", + "title": "MessageResponse" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "id", + "description": "The unique ID of the workflow.", + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true, + "example": "5034460f-c7c4-4c43-9457-de07e2029e7b" + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request POST \\\n --url https://circleci.com/api/v2/workflow/5034460f-c7c4-4c43-9457-de07e2029e7b/cancel \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/workflow/5034460f-c7c4-4c43-9457-de07e2029e7b/cancel';\n const options = {method: 'POST', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"POST\", \"/api/v2/workflow/5034460f-c7c4-4c43-9457-de07e2029e7b/cancel\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/workflow/5034460f-c7c4-4c43-9457-de07e2029e7b/cancel\"\n\n\treq, _ := http.NewRequest(\"POST\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/workflow/5034460f-c7c4-4c43-9457-de07e2029e7b/cancel\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Post.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/workflow/{id}/job": { + "get": { + "summary": "Get a workflow's jobs", + "description": "Returns a sequence of jobs for a workflow.", + "tags": [ + "Workflow" + ], + "operationId": "listWorkflowJobs", + "responses": { + "200": { + "description": "A paginated sequence of jobs.", + "links": { + "NextWorkflowJobPage": { + "operationId": "listWorkflowJobs", + "parameters": { + "id": "$request.path.id", + "page-token": "$response.body#/next_page_token" + } + } + }, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "type": "object", + "properties": { + "canceled_by": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the user." + }, + "dependencies": { + "type": "array", + "items": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the job." + }, + "description": "A sequence of the unique job IDs for the jobs that this job depends upon in the workflow." + }, + "job_number": { + "type": "integer", + "format": "int64", + "description": "The number of the job.", + "example": 1 + }, + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the job." + }, + "started_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the job started." + }, + "name": { + "type": "string", + "description": "The name of the job." + }, + "approved_by": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the user." + }, + "project_slug": { + "type": "string", + "description": "The project-slug for the job.", + "example": "gh/CircleCI-Public/api-preview-docs" + }, + "status": { + "type": "string", + "description": "The current status of the job." + }, + "type": { + "type": "string", + "description": "The type of job." + }, + "requires": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A sequence of statuses that the job must have one of to satisfy a dependency." + }, + "description": "A sequence of the unique jobs and required statuses that this job depends upon in the workflow.", + "example": { + "d212e286-9962-4ed7-92e2-8699622ed720": [ + "success" + ], + "74be7583-44de-42a6-be75-8344de52a6f2": [ + "failed", + "canceled" + ], + "a3349b77-90f7-4a39-b49b-7790f7da3943": [ + "success", + "failed", + "canceled" + ] + } + }, + "stopped_at": { + "type": "string", + "format": "date-time", + "x-nullable": true, + "description": "The time when the job stopped." + }, + "approval_request_id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the job." + } + }, + "required": [ + "id", + "name", + "started_at", + "dependencies", + "project_slug", + "status", + "type" + ], + "description": "Job", + "title": "Job" + } + }, + "next_page_token": { + "type": "string", + "x-nullable": true, + "description": "A token to pass as a `page-token` query parameter to return the next page of results." + } + }, + "required": [ + "items", + "next_page_token" + ], + "title": "WorkflowJobListResponse" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "id", + "description": "The unique ID of the workflow.", + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true, + "example": "5034460f-c7c4-4c43-9457-de07e2029e7b" + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/workflow/5034460f-c7c4-4c43-9457-de07e2029e7b/job \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/workflow/5034460f-c7c4-4c43-9457-de07e2029e7b/job';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/workflow/5034460f-c7c4-4c43-9457-de07e2029e7b/job\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/workflow/5034460f-c7c4-4c43-9457-de07e2029e7b/job\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/workflow/5034460f-c7c4-4c43-9457-de07e2029e7b/job\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/workflow/{id}/rerun": { + "post": { + "summary": "Rerun a workflow", + "description": "Reruns a workflow.", + "tags": [ + "Workflow" + ], + "operationId": "rerunWorkflow", + "responses": { + "202": { + "description": "A confirmation message.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "workflow_id": { + "type": "string", + "format": "uuid", + "description": "The ID of the newly-created workflow.", + "example": "0e53027b-521a-4c40-9042-47e72b3c63a3" + } + }, + "required": [ + "workflow_id" + ], + "description": "A response to rerunning a workflow" + } + } + } + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + } + }, + "description": "Error response." + } + }, + "parameters": [ + { + "in": "path", + "name": "id", + "description": "The unique ID of the workflow.", + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true, + "example": "5034460f-c7c4-4c43-9457-de07e2029e7b" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "enable_ssh": { + "type": "boolean", + "description": "Whether to enable SSH access for the triggering user on the newly-rerun job. Requires the jobs parameter to be used and so is mutually exclusive with the from_failed parameter.", + "example": false + }, + "from_failed": { + "type": "boolean", + "description": "Whether to rerun the workflow from the failed job. Mutually exclusive with the jobs parameter.", + "example": false + }, + "jobs": { + "type": "array", + "items": { + "type": "string", + "format": "uuid" + }, + "description": "A list of job IDs to rerun.", + "example": [ + "c65b68ef-e73b-4bf2-be9a-7a322a9df150", + "5e957edd-5e8c-4985-9178-5d0d69561822" + ] + }, + "sparse_tree": { + "type": "boolean", + "description": "Completes rerun using sparse trees logic, an optimization for workflows that have disconnected subgraphs. Requires jobs parameter and so is mutually exclusive with the from_failed parameter.", + "example": false + } + }, + "x-nullable": true, + "description": "The information you can supply when rerunning a workflow.", + "title": "RerunWorkflowParameters" + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request POST \\\n --url https://circleci.com/api/v2/workflow/5034460f-c7c4-4c43-9457-de07e2029e7b/rerun \\\n --header \"Circle-Token: $CIRCLE_TOKEN\" \\\n --header \"Content-Type: application/json\" \\\n --data \"{\n \\\"enable_ssh\\\": false,\n \\\"from_failed\\\": false,\n \\\"jobs\\\": [\n \\\"c65b68ef-e73b-4bf2-be9a-7a322a9df150\\\",\n \\\"5e957edd-5e8c-4985-9178-5d0d69561822\\\"\n ]\n}\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/workflow/5034460f-c7c4-4c43-9457-de07e2029e7b/rerun';\n const options = {\n method: 'POST',\n headers: {'Circle-Token': '$CIRCLE_TOKEN', 'Content-Type': 'application/json'},\n body: '{\"enable_ssh\":false,\"from_failed\":false,\"jobs\":[\"c65b68ef-e73b-4bf2-be9a-7a322a9df150\",\"5e957edd-5e8c-4985-9178-5d0d69561822\"]}'\n };\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\npayload = \"{\\n \\\"enable_ssh\\\": false,\\n \\\"from_failed\\\": false,\\n \\\"jobs\\\": [\\n \\\"c65b68ef-e73b-4bf2-be9a-7a322a9df150\\\",\\n \\\"5e957edd-5e8c-4985-9178-5d0d69561822\\\"\\n ]\\n}\"\n\nheaders = {\n 'Circle-Token': \"$CIRCLE_TOKEN\",\n 'Content-Type': \"application/json\"\n}\n\nconn.request(\"POST\", \"/api/v2/workflow/5034460f-c7c4-4c43-9457-de07e2029e7b/rerun\", payload, headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/workflow/5034460f-c7c4-4c43-9457-de07e2029e7b/rerun\"\n\n\tpayload := strings.NewReader(\"{\\n \\\"enable_ssh\\\": false,\\n \\\"from_failed\\\": false,\\n \\\"jobs\\\": [\\n \\\"c65b68ef-e73b-4bf2-be9a-7a322a9df150\\\",\\n \\\"5e957edd-5e8c-4985-9178-5d0d69561822\\\"\\n ]\\n}\")\n\n\treq, _ := http.NewRequest(\"POST\", url, payload)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/workflow/5034460f-c7c4-4c43-9457-de07e2029e7b/rerun\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Post.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\nrequest[\"Content-Type\"] = 'application/json'\nrequest.body = \"{\\n \\\"enable_ssh\\\": false,\\n \\\"from_failed\\\": false,\\n \\\"jobs\\\": [\\n \\\"c65b68ef-e73b-4bf2-be9a-7a322a9df150\\\",\\n \\\"5e957edd-5e8c-4985-9178-5d0d69561822\\\"\\n ]\\n}\"\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/org/{orgID}/oidc-custom-claims": { + "delete": { + "description": "Deletes org-level custom claims of OIDC identity tokens", + "operationId": "DeleteOrgClaims", + "parameters": [ + { + "in": "path", + "name": "orgID", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "description": "comma separated list of claims to delete. Valid values are \"audience\" and \"ttl\".", + "in": "query", + "name": "claims", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "audience": { + "items": { + "type": "string" + }, + "type": "array" + }, + "audience_updated_at": { + "format": "date-time", + "type": "string" + }, + "org_id": { + "format": "uuid", + "type": "string" + }, + "project_id": { + "format": "uuid", + "type": "string" + }, + "ttl": { + "pattern": "^([0-9]+(ms|s|m|h|d|w)){1,7}$", + "type": "string" + }, + "ttl_updated_at": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "org_id" + ], + "type": "object" + } + } + }, + "description": "Claims successfully deleted." + }, + "400": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "OwnerID: must be a valid UUID.", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The request is malformed (e.g, a given path parameter is invalid)\n" + }, + "403": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "Forbidden", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The user is forbidden from making this request\n" + }, + "500": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "internal server error", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "Something unexpected happened on the server." + } + }, + "summary": "Delete org-level claims", + "tags": [ + "OIDC Token Management" + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request DELETE \\\n --url \"https://circleci.com/api/v2/org/example-value/oidc-custom-claims?claims=example-value\" \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/org/example-value/oidc-custom-claims?claims=example-value';\n const options = {method: 'DELETE', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"DELETE\", \"/api/v2/org/example-value/oidc-custom-claims?claims=example-value\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/org/example-value/oidc-custom-claims?claims=example-value\"\n\n\treq, _ := http.NewRequest(\"DELETE\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/org/example-value/oidc-custom-claims?claims=example-value\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Delete.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + }, + "get": { + "description": "Fetches org-level custom claims of OIDC identity tokens", + "operationId": "GetOrgClaims", + "parameters": [ + { + "in": "path", + "name": "orgID", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "audience": { + "items": { + "type": "string" + }, + "type": "array" + }, + "audience_updated_at": { + "format": "date-time", + "type": "string" + }, + "org_id": { + "format": "uuid", + "type": "string" + }, + "project_id": { + "format": "uuid", + "type": "string" + }, + "ttl": { + "pattern": "^([0-9]+(ms|s|m|h|d|w)){1,7}$", + "type": "string" + }, + "ttl_updated_at": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "org_id" + ], + "type": "object" + } + } + }, + "description": "Claims successfully fetched." + }, + "400": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "OwnerID: must be a valid UUID.", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The request is malformed (e.g, a given path parameter is invalid)\n" + }, + "403": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "Forbidden", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The user is forbidden from making this request\n" + }, + "500": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "internal server error", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "Something unexpected happened on the server." + } + }, + "summary": "Get org-level claims", + "tags": [ + "OIDC Token Management" + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/org/example-value/oidc-custom-claims \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/org/example-value/oidc-custom-claims';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/org/example-value/oidc-custom-claims\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/org/example-value/oidc-custom-claims\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/org/example-value/oidc-custom-claims\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + }, + "patch": { + "description": "Creates/Updates org-level custom claims of OIDC identity tokens", + "operationId": "PatchOrgClaims", + "parameters": [ + { + "in": "path", + "name": "orgID", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "audience": { + "items": { + "type": "string" + }, + "type": "array" + }, + "ttl": { + "pattern": "^([0-9]+(ms|s|m|h|d|w)){1,7}$", + "type": "string" + } + }, + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "audience": { + "items": { + "type": "string" + }, + "type": "array" + }, + "audience_updated_at": { + "format": "date-time", + "type": "string" + }, + "org_id": { + "format": "uuid", + "type": "string" + }, + "project_id": { + "format": "uuid", + "type": "string" + }, + "ttl": { + "pattern": "^([0-9]+(ms|s|m|h|d|w)){1,7}$", + "type": "string" + }, + "ttl_updated_at": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "org_id" + ], + "type": "object" + } + } + }, + "description": "Claims successfully patched." + }, + "400": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "OwnerID: must be a valid UUID.", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The request is malformed (e.g, a given path parameter is invalid)\n" + }, + "403": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "Forbidden", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The user is forbidden from making this request\n" + }, + "500": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "internal server error", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "Something unexpected happened on the server." + } + }, + "summary": "Patch org-level claims", + "tags": [ + "OIDC Token Management" + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request PATCH \\\n --url https://circleci.com/api/v2/org/example-value/oidc-custom-claims \\\n --header \"Circle-Token: $CIRCLE_TOKEN\" \\\n --header \"Content-Type: application/json\" \\\n --data \"{\n \\\"audience\\\": [\n \\\"example-string\\\"\n ],\n \\\"ttl\\\": \\\"example-string\\\"\n}\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/org/example-value/oidc-custom-claims';\n const options = {\n method: 'PATCH',\n headers: {'Circle-Token': '$CIRCLE_TOKEN', 'Content-Type': 'application/json'},\n body: '{\"audience\":[\"example-string\"],\"ttl\":\"example-string\"}'\n };\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\npayload = \"{\\n \\\"audience\\\": [\\n \\\"example-string\\\"\\n ],\\n \\\"ttl\\\": \\\"example-string\\\"\\n}\"\n\nheaders = {\n 'Circle-Token': \"$CIRCLE_TOKEN\",\n 'Content-Type': \"application/json\"\n}\n\nconn.request(\"PATCH\", \"/api/v2/org/example-value/oidc-custom-claims\", payload, headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/org/example-value/oidc-custom-claims\"\n\n\tpayload := strings.NewReader(\"{\\n \\\"audience\\\": [\\n \\\"example-string\\\"\\n ],\\n \\\"ttl\\\": \\\"example-string\\\"\\n}\")\n\n\treq, _ := http.NewRequest(\"PATCH\", url, payload)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/org/example-value/oidc-custom-claims\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Patch.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\nrequest[\"Content-Type\"] = 'application/json'\nrequest.body = \"{\\n \\\"audience\\\": [\\n \\\"example-string\\\"\\n ],\\n \\\"ttl\\\": \\\"example-string\\\"\\n}\"\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/org/{orgID}/project/{projectID}/oidc-custom-claims": { + "delete": { + "description": "Deletes project-level custom claims of OIDC identity tokens", + "operationId": "DeleteProjectClaims", + "parameters": [ + { + "in": "path", + "name": "orgID", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "projectID", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "description": "comma separated list of claims to delete. Valid values are \"audience\" and \"ttl\".", + "in": "query", + "name": "claims", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "audience": { + "items": { + "type": "string" + }, + "type": "array" + }, + "audience_updated_at": { + "format": "date-time", + "type": "string" + }, + "org_id": { + "format": "uuid", + "type": "string" + }, + "project_id": { + "format": "uuid", + "type": "string" + }, + "ttl": { + "pattern": "^([0-9]+(ms|s|m|h|d|w)){1,7}$", + "type": "string" + }, + "ttl_updated_at": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "org_id" + ], + "type": "object" + } + } + }, + "description": "Claims successfully deleted." + }, + "400": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "OwnerID: must be a valid UUID.", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The request is malformed (e.g, a given path parameter is invalid)\n" + }, + "403": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "Forbidden", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The user is forbidden from making this request\n" + }, + "500": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "internal server error", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "Something unexpected happened on the server." + } + }, + "summary": "Delete project-level claims", + "tags": [ + "OIDC Token Management" + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request DELETE \\\n --url \"https://circleci.com/api/v2/org/example-value/project/example-value/oidc-custom-claims?claims=example-value\" \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/org/example-value/project/example-value/oidc-custom-claims?claims=example-value';\n const options = {method: 'DELETE', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"DELETE\", \"/api/v2/org/example-value/project/example-value/oidc-custom-claims?claims=example-value\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/org/example-value/project/example-value/oidc-custom-claims?claims=example-value\"\n\n\treq, _ := http.NewRequest(\"DELETE\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/org/example-value/project/example-value/oidc-custom-claims?claims=example-value\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Delete.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + }, + "get": { + "description": "Fetches project-level custom claims of OIDC identity tokens", + "operationId": "GetProjectClaims", + "parameters": [ + { + "in": "path", + "name": "orgID", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "projectID", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "audience": { + "items": { + "type": "string" + }, + "type": "array" + }, + "audience_updated_at": { + "format": "date-time", + "type": "string" + }, + "org_id": { + "format": "uuid", + "type": "string" + }, + "project_id": { + "format": "uuid", + "type": "string" + }, + "ttl": { + "pattern": "^([0-9]+(ms|s|m|h|d|w)){1,7}$", + "type": "string" + }, + "ttl_updated_at": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "org_id" + ], + "type": "object" + } + } + }, + "description": "Claims successfully fetched." + }, + "400": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "OwnerID: must be a valid UUID.", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The request is malformed (e.g, a given path parameter is invalid)\n" + }, + "403": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "Forbidden", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The user is forbidden from making this request\n" + }, + "500": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "internal server error", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "Something unexpected happened on the server." + } + }, + "summary": "Get project-level claims", + "tags": [ + "OIDC Token Management" + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/org/example-value/project/example-value/oidc-custom-claims \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/org/example-value/project/example-value/oidc-custom-claims';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/org/example-value/project/example-value/oidc-custom-claims\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/org/example-value/project/example-value/oidc-custom-claims\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/org/example-value/project/example-value/oidc-custom-claims\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + }, + "patch": { + "description": "Creates/Updates project-level custom claims of OIDC identity tokens", + "operationId": "PatchProjectClaims", + "parameters": [ + { + "in": "path", + "name": "orgID", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "in": "path", + "name": "projectID", + "required": true, + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "audience": { + "items": { + "type": "string" + }, + "type": "array" + }, + "ttl": { + "pattern": "^([0-9]+(ms|s|m|h|d|w)){1,7}$", + "type": "string" + } + }, + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "audience": { + "items": { + "type": "string" + }, + "type": "array" + }, + "audience_updated_at": { + "format": "date-time", + "type": "string" + }, + "org_id": { + "format": "uuid", + "type": "string" + }, + "project_id": { + "format": "uuid", + "type": "string" + }, + "ttl": { + "pattern": "^([0-9]+(ms|s|m|h|d|w)){1,7}$", + "type": "string" + }, + "ttl_updated_at": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "org_id" + ], + "type": "object" + } + } + }, + "description": "Claims successfully patched." + }, + "400": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "OwnerID: must be a valid UUID.", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The request is malformed (e.g, a given path parameter is invalid)\n" + }, + "403": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "Forbidden", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The user is forbidden from making this request\n" + }, + "500": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "internal server error", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "Something unexpected happened on the server." + } + }, + "summary": "Patch project-level claims", + "tags": [ + "OIDC Token Management" + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request PATCH \\\n --url https://circleci.com/api/v2/org/example-value/project/example-value/oidc-custom-claims \\\n --header \"Circle-Token: $CIRCLE_TOKEN\" \\\n --header \"Content-Type: application/json\" \\\n --data \"{\n \\\"audience\\\": [\n \\\"example-string\\\"\n ],\n \\\"ttl\\\": \\\"example-string\\\"\n}\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/org/example-value/project/example-value/oidc-custom-claims';\n const options = {\n method: 'PATCH',\n headers: {'Circle-Token': '$CIRCLE_TOKEN', 'Content-Type': 'application/json'},\n body: '{\"audience\":[\"example-string\"],\"ttl\":\"example-string\"}'\n };\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\npayload = \"{\\n \\\"audience\\\": [\\n \\\"example-string\\\"\\n ],\\n \\\"ttl\\\": \\\"example-string\\\"\\n}\"\n\nheaders = {\n 'Circle-Token': \"$CIRCLE_TOKEN\",\n 'Content-Type': \"application/json\"\n}\n\nconn.request(\"PATCH\", \"/api/v2/org/example-value/project/example-value/oidc-custom-claims\", payload, headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/org/example-value/project/example-value/oidc-custom-claims\"\n\n\tpayload := strings.NewReader(\"{\\n \\\"audience\\\": [\\n \\\"example-string\\\"\\n ],\\n \\\"ttl\\\": \\\"example-string\\\"\\n}\")\n\n\treq, _ := http.NewRequest(\"PATCH\", url, payload)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/org/example-value/project/example-value/oidc-custom-claims\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Patch.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\nrequest[\"Content-Type\"] = 'application/json'\nrequest.body = \"{\\n \\\"audience\\\": [\\n \\\"example-string\\\"\\n ],\\n \\\"ttl\\\": \\\"example-string\\\"\\n}\"\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/owner/{ownerID}/context/{context}/decision": { + "get": { + "description": "This endpoint will return a list of decision audit logs that were made using this owner's policies.", + "operationId": "GetDecisionLogs", + "parameters": [ + { + "in": "path", + "name": "ownerID", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "context", + "required": true, + "schema": { + "type": "string" + } + }, + { + "description": "Return decisions matching this decision status.", + "in": "query", + "name": "status", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "Return decisions made after this date.", + "in": "query", + "name": "after", + "required": false, + "schema": { + "format": "date-time", + "type": "string" + } + }, + { + "description": "Return decisions made before this date.", + "in": "query", + "name": "before", + "required": false, + "schema": { + "format": "date-time", + "type": "string" + } + }, + { + "description": "Return decisions made on this branch.", + "in": "query", + "name": "branch", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "Return decisions made for this project.", + "in": "query", + "name": "project_id", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "Return decisions made for this build number.", + "in": "query", + "name": "build_number", + "required": false, + "schema": { + "type": "string" + } + }, + { + "description": "Sets the offset when retrieving the decisions, for paging.", + "in": "query", + "name": "offset", + "required": false, + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "items": { + "properties": { + "created_at": { + "format": "date-time", + "type": "string" + }, + "decision": { + "properties": { + "enabled_rules": { + "items": { + "type": "string" + }, + "type": "array" + }, + "hard_failures": { + "items": { + "properties": { + "reason": { + "type": "string" + }, + "rule": { + "type": "string" + } + }, + "required": [ + "rule", + "reason" + ], + "type": "object" + }, + "type": "array" + }, + "reason": { + "type": "string" + }, + "soft_failures": { + "items": { + "properties": { + "reason": { + "type": "string" + }, + "rule": { + "type": "string" + } + }, + "required": [ + "rule", + "reason" + ], + "type": "object" + }, + "type": "array" + }, + "status": { + "type": "string" + } + }, + "required": [ + "status" + ], + "type": "object" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "metadata": { + "properties": { + "build_number": { + "type": "integer" + }, + "project_id": { + "format": "uuid", + "type": "string" + }, + "ssh_rerun": { + "type": "boolean" + }, + "vcs": { + "properties": { + "branch": { + "type": "string" + }, + "origin_repository_url": { + "type": "string" + }, + "release_tag": { + "type": "string" + }, + "target_repository_url": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "policies": { + "additionalProperties": { + "maxLength": 128, + "minLength": 128, + "type": "string" + }, + "description": "policy-name-to-hash-map", + "example": { + "policy_name1": "1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75", + "policy_name2": "5267768822ee624d48fce15ec5ca79cbd602cb7f4c2157a516556991f22ef8c7b5ef7b18d1ff41c59370efb0858651d44a936c11b7b144c48fe04df3c6a3e8da" + }, + "type": "object" + }, + "time_taken_ms": { + "type": "integer" + } + }, + "type": "object" + }, + "type": "array" + } + } + }, + "description": "Decision logs successfully retrieved." + }, + "400": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "OwnerID: must be a valid UUID.", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The request is malformed (e.g, a given path parameter is invalid)\n" + }, + "401": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "Unauthorized", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The request is unauthorized\n" + }, + "403": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "Forbidden", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The user is forbidden from making this request\n" + }, + "500": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "unexpected server error", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "Something unexpected happened on the server." + } + }, + "summary": "Retrieves the owner's decision audit logs.", + "tags": [ + "Policy Management" + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url \"https://circleci.com/api/v2/owner/example-value/context/example-value/decision?status=example-value&after=example-value&before=example-value&branch=example-value&project_id=497f6eca-6276-4993-bfeb-53cbbbba6f08&build_number=example-value&offset=123\" \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/owner/example-value/context/example-value/decision?status=example-value&after=example-value&before=example-value&branch=example-value&project_id=497f6eca-6276-4993-bfeb-53cbbbba6f08&build_number=example-value&offset=123';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/owner/example-value/context/example-value/decision?status=example-value&after=example-value&before=example-value&branch=example-value&project_id=497f6eca-6276-4993-bfeb-53cbbbba6f08&build_number=example-value&offset=123\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/owner/example-value/context/example-value/decision?status=example-value&after=example-value&before=example-value&branch=example-value&project_id=497f6eca-6276-4993-bfeb-53cbbbba6f08&build_number=example-value&offset=123\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/owner/example-value/context/example-value/decision?status=example-value&after=example-value&before=example-value&branch=example-value&project_id=497f6eca-6276-4993-bfeb-53cbbbba6f08&build_number=example-value&offset=123\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + }, + "post": { + "description": "This endpoint will evaluate input data (config+metadata) against owner's stored policies and return a decision.", + "operationId": "MakeDecision", + "parameters": [ + { + "in": "path", + "name": "ownerID", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "context", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "input": { + "type": "string" + }, + "metadata": { + "type": "object" + } + }, + "required": [ + "input" + ], + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "enabled_rules": { + "items": { + "type": "string" + }, + "type": "array" + }, + "hard_failures": { + "items": { + "properties": { + "reason": { + "type": "string" + }, + "rule": { + "type": "string" + } + }, + "required": [ + "rule", + "reason" + ], + "type": "object" + }, + "type": "array" + }, + "reason": { + "type": "string" + }, + "soft_failures": { + "items": { + "properties": { + "reason": { + "type": "string" + }, + "rule": { + "type": "string" + } + }, + "required": [ + "rule", + "reason" + ], + "type": "object" + }, + "type": "array" + }, + "status": { + "type": "string" + } + }, + "required": [ + "status" + ], + "type": "object" + } + } + }, + "description": "Decision rendered by applying the policy against the provided data. Response will be modeled by the data and rego processed." + }, + "400": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "context: must be a valid value.", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The request is malformed\n" + }, + "401": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "Unauthorized.", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The request is unauthorized\n" + }, + "500": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "There was an error processing your request.", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "Something unexpected happened on the server." + } + }, + "summary": "Makes a decision", + "tags": [ + "Policy Management" + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request POST \\\n --url https://circleci.com/api/v2/owner/example-value/context/example-value/decision \\\n --header \"Circle-Token: $CIRCLE_TOKEN\" \\\n --header \"Content-Type: application/json\" \\\n --data \"{\n \\\"input\\\": \\\"example-string\\\",\n \\\"metadata\\\": {}\n}\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/owner/example-value/context/example-value/decision';\n const options = {\n method: 'POST',\n headers: {'Circle-Token': '$CIRCLE_TOKEN', 'Content-Type': 'application/json'},\n body: '{\"input\":\"example-string\",\"metadata\":{}}'\n };\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\npayload = \"{\\n \\\"input\\\": \\\"example-string\\\",\\n \\\"metadata\\\": {}\\n}\"\n\nheaders = {\n 'Circle-Token': \"$CIRCLE_TOKEN\",\n 'Content-Type': \"application/json\"\n}\n\nconn.request(\"POST\", \"/api/v2/owner/example-value/context/example-value/decision\", payload, headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/owner/example-value/context/example-value/decision\"\n\n\tpayload := strings.NewReader(\"{\\n \\\"input\\\": \\\"example-string\\\",\\n \\\"metadata\\\": {}\\n}\")\n\n\treq, _ := http.NewRequest(\"POST\", url, payload)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/owner/example-value/context/example-value/decision\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Post.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\nrequest[\"Content-Type\"] = 'application/json'\nrequest.body = \"{\\n \\\"input\\\": \\\"example-string\\\",\\n \\\"metadata\\\": {}\\n}\"\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/owner/{ownerID}/context/{context}/decision/settings": { + "get": { + "description": "This endpoint retrieves the current decision settings (eg enable/disable policy evaluation)", + "operationId": "GetDecisionSettings", + "parameters": [ + { + "in": "path", + "name": "ownerID", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "context", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "enabled": { + "type": "boolean" + } + }, + "type": "object" + } + } + }, + "description": "Decision settings successfully retrieved." + }, + "400": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "OwnerID: must be a valid UUID.", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The request is malformed (e.g, a given path parameter is invalid)\n" + }, + "401": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "Unauthorized", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The request is unauthorized\n" + }, + "403": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "Forbidden", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The user is forbidden from making this request\n" + }, + "500": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "unexpected server error", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "Something unexpected happened on the server." + } + }, + "summary": "Get the decision settings", + "tags": [ + "Policy Management" + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/owner/example-value/context/example-value/decision/settings \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/owner/example-value/context/example-value/decision/settings';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/owner/example-value/context/example-value/decision/settings\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/owner/example-value/context/example-value/decision/settings\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/owner/example-value/context/example-value/decision/settings\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + }, + "patch": { + "description": "This endpoint allows modifying decision settings (eg enable/disable policy evaluation)", + "operationId": "SetDecisionSettings", + "parameters": [ + { + "in": "path", + "name": "ownerID", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "context", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "enabled": { + "type": "boolean" + } + }, + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "enabled": { + "type": "boolean" + } + }, + "type": "object" + } + } + }, + "description": "Decision settings successfully set." + }, + "400": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "OwnerID: must be a valid UUID.", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The request is malformed (e.g, a given path parameter is invalid)\n" + }, + "401": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "Unauthorized", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The request is unauthorized\n" + }, + "403": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "Forbidden", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The user is forbidden from making this request\n" + }, + "500": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "unexpected server error", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "Something unexpected happened on the server." + } + }, + "summary": "Set the decision settings", + "tags": [ + "Policy Management" + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request PATCH \\\n --url https://circleci.com/api/v2/owner/example-value/context/example-value/decision/settings \\\n --header \"Circle-Token: $CIRCLE_TOKEN\" \\\n --header \"Content-Type: application/json\" \\\n --data \"{\n \\\"enabled\\\": true\n}\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/owner/example-value/context/example-value/decision/settings';\n const options = {\n method: 'PATCH',\n headers: {'Circle-Token': '$CIRCLE_TOKEN', 'Content-Type': 'application/json'},\n body: '{\"enabled\":true}'\n };\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\npayload = \"{\\n \\\"enabled\\\": true\\n}\"\n\nheaders = {\n 'Circle-Token': \"$CIRCLE_TOKEN\",\n 'Content-Type': \"application/json\"\n}\n\nconn.request(\"PATCH\", \"/api/v2/owner/example-value/context/example-value/decision/settings\", payload, headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/owner/example-value/context/example-value/decision/settings\"\n\n\tpayload := strings.NewReader(\"{\\n \\\"enabled\\\": true\\n}\")\n\n\treq, _ := http.NewRequest(\"PATCH\", url, payload)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/owner/example-value/context/example-value/decision/settings\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Patch.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\nrequest[\"Content-Type\"] = 'application/json'\nrequest.body = \"{\\n \\\"enabled\\\": true\\n}\"\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/owner/{ownerID}/context/{context}/decision/{decisionID}": { + "get": { + "description": "This endpoint will retrieve a decision for a given decision log ID", + "operationId": "GetDecisionLog", + "parameters": [ + { + "in": "path", + "name": "ownerID", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "context", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "decisionID", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "created_at": { + "format": "date-time", + "type": "string" + }, + "decision": { + "properties": { + "enabled_rules": { + "items": { + "type": "string" + }, + "type": "array" + }, + "hard_failures": { + "items": { + "properties": { + "reason": { + "type": "string" + }, + "rule": { + "type": "string" + } + }, + "required": [ + "rule", + "reason" + ], + "type": "object" + }, + "type": "array" + }, + "reason": { + "type": "string" + }, + "soft_failures": { + "items": { + "properties": { + "reason": { + "type": "string" + }, + "rule": { + "type": "string" + } + }, + "required": [ + "rule", + "reason" + ], + "type": "object" + }, + "type": "array" + }, + "status": { + "type": "string" + } + }, + "required": [ + "status" + ], + "type": "object" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "metadata": { + "properties": { + "build_number": { + "type": "integer" + }, + "project_id": { + "format": "uuid", + "type": "string" + }, + "ssh_rerun": { + "type": "boolean" + }, + "vcs": { + "properties": { + "branch": { + "type": "string" + }, + "origin_repository_url": { + "type": "string" + }, + "release_tag": { + "type": "string" + }, + "target_repository_url": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "policies": { + "additionalProperties": { + "maxLength": 128, + "minLength": 128, + "type": "string" + }, + "description": "policy-name-to-hash-map", + "example": { + "policy_name1": "1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75", + "policy_name2": "5267768822ee624d48fce15ec5ca79cbd602cb7f4c2157a516556991f22ef8c7b5ef7b18d1ff41c59370efb0858651d44a936c11b7b144c48fe04df3c6a3e8da" + }, + "type": "object" + }, + "time_taken_ms": { + "type": "integer" + } + }, + "type": "object" + } + } + }, + "description": "Decision log successfully retrieved." + }, + "400": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "OwnerID: must be a valid UUID.", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The request is malformed (e.g, a given path parameter is invalid)\n" + }, + "401": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "Unauthorized", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The request is unauthorized\n" + }, + "403": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "Forbidden", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The user is forbidden from making this request\n" + }, + "404": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "decision log not found", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "There was no decision log found for given decision_id, and owner_id.\n" + }, + "500": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "unexpected server error", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "Something unexpected happened on the server." + } + }, + "summary": "Retrieves the owner's decision audit log by given decisionID", + "tags": [ + "Policy Management" + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/owner/example-value/context/example-value/decision/example-value \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/owner/example-value/context/example-value/decision/example-value';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/owner/example-value/context/example-value/decision/example-value\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/owner/example-value/context/example-value/decision/example-value\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/owner/example-value/context/example-value/decision/example-value\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/owner/{ownerID}/context/{context}/decision/{decisionID}/policy-bundle": { + "get": { + "description": "This endpoint will retrieve a policy bundle for a given decision log ID", + "operationId": "GetDecisionLogPolicyBundle", + "parameters": [ + { + "in": "path", + "name": "ownerID", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "context", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "decisionID", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "additionalProperties": { + "items": { + "properties": { + "content": { + "type": "string" + }, + "created_at": { + "format": "date-time", + "type": "string" + }, + "created_by": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + } + } + }, + "description": "Policy-Bundle retrieved successfully for given decision log ID" + }, + "400": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "OwnerID: must be a valid UUID.", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The request is malformed (e.g, a given path parameter is invalid)\n" + }, + "401": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "Unauthorized", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The request is unauthorized\n" + }, + "403": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "Forbidden", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The user is forbidden from making this request\n" + }, + "404": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "decision log not found", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "There was no decision log found for given decision_id, and owner_id.\n" + }, + "500": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "unexpected server error", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "Something unexpected happened on the server." + } + }, + "summary": "Retrieves Policy Bundle for a given decision log ID", + "tags": [ + "Policy Management" + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/owner/example-value/context/example-value/decision/example-value/policy-bundle \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/owner/example-value/context/example-value/decision/example-value/policy-bundle';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/owner/example-value/context/example-value/decision/example-value/policy-bundle\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/owner/example-value/context/example-value/decision/example-value/policy-bundle\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/owner/example-value/context/example-value/decision/example-value/policy-bundle\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/owner/{ownerID}/context/{context}/policy-bundle": { + "get": { + "description": "This endpoint will retrieve a policy bundle", + "operationId": "GetPolicyBundle", + "parameters": [ + { + "in": "path", + "name": "ownerID", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "context", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "additionalProperties": { + "items": { + "properties": { + "content": { + "type": "string" + }, + "created_at": { + "format": "date-time", + "type": "string" + }, + "created_by": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + } + } + }, + "description": "Policy-Bundle retrieved successfully." + }, + "400": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "OwnerID: must be a valid UUID.", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The request is malformed (e.g, a given path parameter is invalid)\n" + }, + "401": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "Unauthorized", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The request is unauthorized\n" + }, + "403": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "Forbidden", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The user is forbidden from making this request\n" + }, + "500": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "unexpected server error", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "Something unexpected happened on the server." + } + }, + "summary": "Retrieves Policy Bundle", + "tags": [ + "Policy Management" + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/owner/example-value/context/example-value/policy-bundle \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/owner/example-value/context/example-value/policy-bundle';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/owner/example-value/context/example-value/policy-bundle\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/owner/example-value/context/example-value/policy-bundle\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/owner/example-value/context/example-value/policy-bundle\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + }, + "post": { + "description": "This endpoint replaces the current policy bundle with the provided policy bundle", + "operationId": "CreatePolicyBundle", + "parameters": [ + { + "in": "path", + "name": "ownerID", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "context", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "dry", + "schema": { + "type": "boolean" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "policies": { + "additionalProperties": { + "description": "policy content", + "type": "string" + }, + "type": "object" + } + }, + "type": "object" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "created": { + "items": { + "description": "policy names", + "type": "string" + }, + "type": "array" + }, + "deleted": { + "items": { + "description": "policy names", + "type": "string" + }, + "type": "array" + }, + "modified": { + "items": { + "description": "policy names", + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + } + } + }, + "description": "Policy-Bundle diff successfully returned." + }, + "201": { + "content": { + "application/json": { + "schema": { + "properties": { + "created": { + "items": { + "description": "policy names", + "type": "string" + }, + "type": "array" + }, + "deleted": { + "items": { + "description": "policy names", + "type": "string" + }, + "type": "array" + }, + "modified": { + "items": { + "description": "policy names", + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + } + } + }, + "description": "Policy-Bundle successfully created." + }, + "400": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "OwnerID: must be a valid UUID.", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The request is malformed (e.g, a given path parameter is invalid)\n" + }, + "401": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "Unauthorized", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The request is unauthorized\n" + }, + "403": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "Forbidden", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The user is forbidden from making this request\n" + }, + "413": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "http: request payload too large", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The request exceeds the maximum payload size for policy bundles ~2.5Mib\n" + }, + "500": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "unexpected server error", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "Something unexpected happened on the server." + } + }, + "summary": "Creates policy bundle for the context", + "tags": [ + "Policy Management" + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request POST \\\n --url \"https://circleci.com/api/v2/owner/example-value/context/example-value/policy-bundle?dry=true\" \\\n --header \"Circle-Token: $CIRCLE_TOKEN\" \\\n --header \"Content-Type: application/json\" \\\n --data \"{\n \\\"policies\\\": {}\n}\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/owner/example-value/context/example-value/policy-bundle?dry=true';\n const options = {\n method: 'POST',\n headers: {'Circle-Token': '$CIRCLE_TOKEN', 'Content-Type': 'application/json'},\n body: '{\"policies\":{}}'\n };\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\npayload = \"{\\n \\\"policies\\\": {}\\n}\"\n\nheaders = {\n 'Circle-Token': \"$CIRCLE_TOKEN\",\n 'Content-Type': \"application/json\"\n}\n\nconn.request(\"POST\", \"/api/v2/owner/example-value/context/example-value/policy-bundle?dry=true\", payload, headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/owner/example-value/context/example-value/policy-bundle?dry=true\"\n\n\tpayload := strings.NewReader(\"{\\n \\\"policies\\\": {}\\n}\")\n\n\treq, _ := http.NewRequest(\"POST\", url, payload)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/owner/example-value/context/example-value/policy-bundle?dry=true\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Post.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\nrequest[\"Content-Type\"] = 'application/json'\nrequest.body = \"{\\n \\\"policies\\\": {}\\n}\"\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/owner/{ownerID}/context/{context}/policy-bundle/{policyName}": { + "get": { + "description": "This endpoint will retrieve a policy document.", + "operationId": "GetPolicyDocument", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "content": { + "type": "string" + }, + "created_at": { + "format": "date-time", + "type": "string" + }, + "created_by": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "type": "object" + } + } + }, + "description": "Policy retrieved successfully." + }, + "400": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "OwnerID: must be a valid UUID.", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The request is malformed (e.g, a given path parameter is invalid)\n" + }, + "401": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "Unauthorized", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The request is unauthorized\n" + }, + "403": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "Forbidden", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "The user is forbidden from making this request\n" + }, + "404": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "policy not found", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "There was no policy that was found with the given owner_id and policy name.\n" + }, + "500": { + "content": { + "application/json": { + "schema": { + "properties": { + "error": { + "example": "unexpected server error", + "type": "string" + } + }, + "required": [ + "error" + ], + "type": "object" + } + } + }, + "description": "Something unexpected happened on the server." + } + }, + "summary": "Retrieves a policy document", + "tags": [ + "Policy Management" + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/owner/example-value/context/example-value/policy-bundle/example-value \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/owner/example-value/context/example-value/policy-bundle/example-value';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/owner/example-value/context/example-value/policy-bundle/example-value\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/owner/example-value/context/example-value/policy-bundle/example-value\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/owner/example-value/context/example-value/policy-bundle/example-value\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + }, + "parameters": [ + { + "in": "path", + "name": "ownerID", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "context", + "required": true, + "schema": { + "type": "string" + } + }, + { + "description": "the policy name set by the rego policy_name rule", + "in": "path", + "name": "policyName", + "required": true, + "schema": { + "type": "string" + } + } + ] + }, + "/context": { + "post": { + "summary": "Create a new context", + "description": "Creates a new context in the specified organization.", + "tags": [ + "Context" + ], + "operationId": "createContext", + "responses": { + "200": { + "description": "The new context", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the context." + }, + "name": { + "type": "string", + "description": "The user-defined name of the context." + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the context was created.", + "example": "2015-09-21T17:29:21.042Z" + } + }, + "required": [ + "id", + "name", + "created_at" + ], + "title": "Context" + } + } + } + }, + "401": { + "description": "Credentials provided are invalid.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "invalid_token": { + "summary": "Token is invalid.", + "value": { + "message": "Invalid token provided." + } + }, + "old_token": { + "summary": "Token was generated before 2023-06-23.", + "value": { + "message": "New format tokens are needed to authenticate this API endpoint. Create a new API token for access." + } + }, + "query_auth": { + "summary": "Authentication attempted via query parameters.", + "value": { + "message": "Support for query parameter authentication has been deprecated to improve security. Please use a supported authentication method such as header-based, or basic authentication." + } + } + } + } + } + }, + "404": { + "description": "Entity not found.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "context_not_found": { + "summary": "Context not found.", + "value": { + "message": "Context not found." + } + }, + "org_not_found": { + "summary": "Organization not found.", + "value": { + "message": "Organization does not exist." + } + }, + "user_not_found": { + "summary": "User not found.", + "value": { + "message": "User does not exist." + } + }, + "project_not_found": { + "summary": "Project not found.", + "value": { + "message": "Project does not exist." + } + }, + "group_not_found": { + "summary": "Group not found.", + "value": { + "message": "Group does not exist." + } + }, + "orb_not_found": { + "summary": "Orb not found.", + "value": { + "message": "Orb does not exist." + } + } + } + } + } + }, + "429": { + "description": "API rate limits exceeded.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Rate limit exceeded." + } + } + } + } + } + }, + "500": { + "description": "Internal server error.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Internal server error." + } + } + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string", + "description": "The user defined name of the context." + }, + "owner": { + "additionalProperties": false, + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the owner of the context. This is the organization ID. Specify either owner/organization ID or the owner/organization slug. Find the organization ID and slug in the CircleCI web app (Organization Settings > Overview). Owner/organization slug is not supported for CircleCI server." + }, + "type": { + "type": "string", + "description": "The type of the owner. Defaults to \"organization\". Use \"account\" if you are using CircleCI server.", + "example": "organization" + } + }, + "required": [ + "id" + ] + }, + { + "type": "object", + "additionalProperties": false, + "properties": { + "slug": { + "type": "string", + "description": "A string that represents an organization. This is the organization slug. Specify either this or organization/owner ID. Find the organization ID and slug in the CircleCI web app (Organization Settings > Overview). Owner/organization slug is not supported for CircleCI server." + }, + "type": { + "type": "string", + "description": "The type of owner. Defaults to \"organization\". Accounts are only used as context owners in server and must be specified by an id instead of a slug." + } + }, + "required": [ + "slug" + ] + } + ] + } + }, + "required": [ + "name", + "owner" + ] + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request POST \\\n --url https://circleci.com/api/v2/context \\\n --header \"Circle-Token: $CIRCLE_TOKEN\" \\\n --header \"Content-Type: application/json\" \\\n --data \"{\n \\\"name\\\": \\\"example-string\\\",\n \\\"owner\\\": null\n}\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/context';\n const options = {\n method: 'POST',\n headers: {'Circle-Token': '$CIRCLE_TOKEN', 'Content-Type': 'application/json'},\n body: '{\"name\":\"example-string\",\"owner\":null}'\n };\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\npayload = \"{\\n \\\"name\\\": \\\"example-string\\\",\\n \\\"owner\\\": null\\n}\"\n\nheaders = {\n 'Circle-Token': \"$CIRCLE_TOKEN\",\n 'Content-Type': \"application/json\"\n}\n\nconn.request(\"POST\", \"/api/v2/context\", payload, headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/context\"\n\n\tpayload := strings.NewReader(\"{\\n \\\"name\\\": \\\"example-string\\\",\\n \\\"owner\\\": null\\n}\")\n\n\treq, _ := http.NewRequest(\"POST\", url, payload)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/context\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Post.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\nrequest[\"Content-Type\"] = 'application/json'\nrequest.body = \"{\\n \\\"name\\\": \\\"example-string\\\",\\n \\\"owner\\\": null\\n}\"\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + }, + "get": { + "summary": "List contexts", + "description": "List all contexts for an owner.", + "tags": [ + "Context" + ], + "operationId": "listContexts", + "responses": { + "200": { + "description": "A paginated list of contexts", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "items": { + "type": "array", + "additionalProperties": false, + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the context." + }, + "name": { + "type": "string", + "description": "The user defined name of the context." + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the context was created.", + "example": "2015-09-21T17:29:21.042Z" + } + }, + "required": [ + "id", + "name", + "created_at" + ], + "title": "Context" + } + }, + "next_page_token": { + "type": "string", + "nullable": true, + "description": "A token to pass as a `page-token` query parameter to return the next page of results." + } + }, + "required": [ + "items", + "next_page_token" + ] + } + } + } + }, + "401": { + "description": "Credentials provided are invalid.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "invalid_token": { + "summary": "Token is invalid.", + "value": { + "message": "Invalid token provided." + } + }, + "old_token": { + "summary": "Token was generated before 2023-06-23.", + "value": { + "message": "New format tokens are needed to authenticate this API endpoint. Create a new API token for access." + } + }, + "query_auth": { + "summary": "Authentication attempted via query parameters.", + "value": { + "message": "Support for query parameter authentication has been deprecated to improve security. Please use a supported authentication method such as header-based, or basic authentication." + } + } + } + } + } + }, + "404": { + "description": "Entity not found.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "context_not_found": { + "summary": "Context not found.", + "value": { + "message": "Context not found." + } + }, + "org_not_found": { + "summary": "Organization not found.", + "value": { + "message": "Organization does not exist." + } + }, + "user_not_found": { + "summary": "User not found.", + "value": { + "message": "User does not exist." + } + }, + "project_not_found": { + "summary": "Project not found.", + "value": { + "message": "Project does not exist." + } + }, + "group_not_found": { + "summary": "Group not found.", + "value": { + "message": "Group does not exist." + } + }, + "orb_not_found": { + "summary": "Orb not found.", + "value": { + "message": "Orb does not exist." + } + } + } + } + } + }, + "429": { + "description": "API rate limits exceeded.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Rate limit exceeded." + } + } + } + } + } + }, + "500": { + "description": "Internal server error.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Internal server error." + } + } + } + } + } + } + }, + "parameters": [ + { + "in": "query", + "name": "owner-id", + "description": "The unique ID of the owner of the context. This is the organization ID. Specify either owner/organization ID or the owner/organization slug. Find the organization ID and slug in the CircleCI web app (Organization Settings > Overview). Owner/organization slug is not supported for CircleCI server.", + "schema": { + "type": "string", + "format": "uuid" + }, + "required": false + }, + { + "in": "query", + "name": "owner-slug", + "description": "A string that represents an organization. This is the organization slug. Specify either this or organization/owner ID. Find the organization ID and slug in the CircleCI web app (Organization Settings > Overview). Owner/organization slug is not supported for CircleCI server.", + "schema": { + "type": "string" + }, + "required": false + }, + { + "in": "query", + "name": "owner-type", + "description": "The type of the owner. Defaults to \"organization\". Use \"account\" if you are using CircleCI server.", + "schema": { + "type": "string" + }, + "required": false + }, + { + "name": "page-token", + "in": "query", + "description": "A token to specify which page of results to fetch.", + "schema": { + "type": "string" + } + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url \"https://circleci.com/api/v2/context?owner-id=497f6eca-6276-4993-bfeb-53cbbbba6f08&owner-slug=example-value&owner-type=account&page-token=example-value\" \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/context?owner-id=497f6eca-6276-4993-bfeb-53cbbbba6f08&owner-slug=example-value&owner-type=account&page-token=example-value';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/context?owner-id=497f6eca-6276-4993-bfeb-53cbbbba6f08&owner-slug=example-value&owner-type=account&page-token=example-value\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/context?owner-id=497f6eca-6276-4993-bfeb-53cbbbba6f08&owner-slug=example-value&owner-type=account&page-token=example-value\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/context?owner-id=497f6eca-6276-4993-bfeb-53cbbbba6f08&owner-slug=example-value&owner-type=account&page-token=example-value\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/context/{context_id}": { + "get": { + "summary": "Get a context", + "description": "Returns basic information about a context.", + "tags": [ + "Context" + ], + "operationId": "getContext", + "responses": { + "200": { + "description": "The context", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the context." + }, + "name": { + "type": "string", + "description": "The user defined name of the context." + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the context was created.", + "example": "2015-09-21T17:29:21.042Z" + } + }, + "required": [ + "id", + "name", + "created_at" + ], + "title": "Context" + } + } + } + }, + "401": { + "description": "Credentials provided are invalid.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "invalid_token": { + "summary": "Token is invalid.", + "value": { + "message": "Invalid token provided." + } + }, + "old_token": { + "summary": "Token was generated before 2023-06-23.", + "value": { + "message": "New format tokens are needed to authenticate this API endpoint. Create a new API token for access." + } + }, + "query_auth": { + "summary": "Authentication attempted via query parameters.", + "value": { + "message": "Support for query parameter authentication has been deprecated to improve security. Please use a supported authentication method such as header-based, or basic authentication." + } + } + } + } + } + }, + "404": { + "description": "Entity not found.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "context_not_found": { + "summary": "Context not found.", + "value": { + "message": "Context not found." + } + }, + "org_not_found": { + "summary": "Organization not found.", + "value": { + "message": "Organization does not exist." + } + }, + "user_not_found": { + "summary": "User not found.", + "value": { + "message": "User does not exist." + } + }, + "project_not_found": { + "summary": "Project not found.", + "value": { + "message": "Project does not exist." + } + }, + "group_not_found": { + "summary": "Group not found.", + "value": { + "message": "Group does not exist." + } + }, + "orb_not_found": { + "summary": "Orb not found.", + "value": { + "message": "Orb does not exist." + } + } + } + } + } + }, + "429": { + "description": "API rate limits exceeded.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Rate limit exceeded." + } + } + } + } + } + }, + "500": { + "description": "Internal server error.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Internal server error." + } + } + } + } + } + } + }, + "parameters": [ + { + "name": "context_id", + "description": "An opaque identifier of a context.", + "example": "be8bb2e3-c3d6-4098-89f4-572ff976ba9a", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + }, + "delete": { + "summary": "Delete a context", + "description": "Delete a context by its ID. Will also delete all environment variables inside the context.", + "tags": [ + "Context" + ], + "operationId": "deleteContext", + "responses": { + "200": { + "description": "A confirmation message", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "description": "A human-readable message" + } + }, + "required": [ + "message" + ], + "description": "message response", + "title": "MessageResponse" + } + } + } + }, + "401": { + "description": "Credentials provided are invalid.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "invalid_token": { + "summary": "Token is invalid.", + "value": { + "message": "Invalid token provided." + } + }, + "old_token": { + "summary": "Token was generated before 2023-06-23.", + "value": { + "message": "New format tokens are needed to authenticate this API endpoint. Create a new API token for access." + } + }, + "query_auth": { + "summary": "Authentication attempted via query parameters.", + "value": { + "message": "Support for query parameter authentication has been deprecated to improve security. Please use a supported authentication method such as header-based, or basic authentication." + } + } + } + } + } + }, + "404": { + "description": "Entity not found.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "context_not_found": { + "summary": "Context not found.", + "value": { + "message": "Context not found." + } + }, + "org_not_found": { + "summary": "Organization not found.", + "value": { + "message": "Organization does not exist." + } + }, + "user_not_found": { + "summary": "User not found.", + "value": { + "message": "User does not exist." + } + }, + "project_not_found": { + "summary": "Project not found.", + "value": { + "message": "Project does not exist." + } + }, + "group_not_found": { + "summary": "Group not found.", + "value": { + "message": "Group does not exist." + } + }, + "orb_not_found": { + "summary": "Orb not found.", + "value": { + "message": "Orb does not exist." + } + } + } + } + } + }, + "429": { + "description": "API rate limits exceeded.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Rate limit exceeded." + } + } + } + } + } + }, + "500": { + "description": "Internal server error.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Internal server error." + } + } + } + } + } + } + }, + "parameters": [ + { + "name": "context_id", + "description": "An opaque identifier of a context.", + "example": "be8bb2e3-c3d6-4098-89f4-572ff976ba9a", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request DELETE \\\n --url https://circleci.com/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a';\n const options = {method: 'DELETE', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"DELETE\", \"/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a\"\n\n\treq, _ := http.NewRequest(\"DELETE\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Delete.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/context/{context_id}/environment-variable": { + "get": { + "summary": "List environment variables", + "description": "List information about environment variables in a context, not including their values.", + "tags": [ + "Context" + ], + "operationId": "listEnvironmentVariablesFromContext", + "responses": { + "200": { + "description": "A paginated list of environment variables", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "items": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "variable": { + "type": "string", + "description": "The name of the environment variable", + "example": "POSTGRES_USER" + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the environment variable was created.", + "example": "2015-09-21T17:29:21.042Z" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the environment variable was updated", + "example": "2015-09-21T17:29:21.042Z" + }, + "context_id": { + "type": "string", + "format": "uuid", + "description": "ID of the context (UUID)" + } + }, + "required": [ + "variable", + "created_at", + "updated_at", + "context_id" + ] + } + }, + "next_page_token": { + "type": "string", + "nullable": true, + "description": "A token to pass as a `page-token` query parameter to return the next page of results." + } + }, + "required": [ + "items", + "next_page_token" + ] + } + } + } + }, + "401": { + "description": "Credentials provided are invalid.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "invalid_token": { + "summary": "Token is invalid.", + "value": { + "message": "Invalid token provided." + } + }, + "old_token": { + "summary": "Token was generated before 2023-06-23.", + "value": { + "message": "New format tokens are needed to authenticate this API endpoint. Create a new API token for access." + } + }, + "query_auth": { + "summary": "Authentication attempted via query parameters.", + "value": { + "message": "Support for query parameter authentication has been deprecated to improve security. Please use a supported authentication method such as header-based, or basic authentication." + } + } + } + } + } + }, + "404": { + "description": "Entity not found.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "context_not_found": { + "summary": "Context not found.", + "value": { + "message": "Context not found." + } + }, + "org_not_found": { + "summary": "Organization not found.", + "value": { + "message": "Organization does not exist." + } + }, + "user_not_found": { + "summary": "User not found.", + "value": { + "message": "User does not exist." + } + }, + "project_not_found": { + "summary": "Project not found.", + "value": { + "message": "Project does not exist." + } + }, + "group_not_found": { + "summary": "Group not found.", + "value": { + "message": "Group does not exist." + } + }, + "orb_not_found": { + "summary": "Orb not found.", + "value": { + "message": "Orb does not exist." + } + } + } + } + } + }, + "429": { + "description": "API rate limits exceeded.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Rate limit exceeded." + } + } + } + } + } + }, + "500": { + "description": "Internal server error.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Internal server error." + } + } + } + } + } + } + }, + "parameters": [ + { + "name": "context_id", + "description": "An opaque identifier of a context.", + "example": "be8bb2e3-c3d6-4098-89f4-572ff976ba9a", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "page-token", + "in": "query", + "description": "A token to specify which page of results to fetch.", + "schema": { + "type": "string" + } + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url \"https://circleci.com/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a/environment-variable?page-token=example-value\" \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a/environment-variable?page-token=example-value';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a/environment-variable?page-token=example-value\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a/environment-variable?page-token=example-value\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a/environment-variable?page-token=example-value\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/context/{context_id}/environment-variable/{env_var_name}": { + "put": { + "summary": "Add or update an environment variable", + "description": "Create or update an environment variable within a context. Returns information about the environment variable, not including its value.", + "tags": [ + "Context" + ], + "operationId": "addEnvironmentVariableToContext", + "responses": { + "200": { + "description": "The new environment variable", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "anyOf": [ + { + "type": "object", + "additionalProperties": false, + "properties": { + "variable": { + "type": "string", + "description": "The name of the environment variable", + "example": "POSTGRES_USER" + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the environment variable was created.", + "example": "2015-09-21T17:29:21.042Z" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the environment variable was updated", + "example": "2015-09-21T17:29:21.042Z" + }, + "context_id": { + "type": "string", + "format": "uuid", + "description": "ID of the context (UUID)" + } + }, + "required": [ + "variable", + "created_at", + "updated_at", + "context_id" + ] + }, + { + "type": "object", + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "description": "A human-readable message" + } + }, + "required": [ + "message" + ], + "description": "message response", + "title": "MessageResponse" + } + ] + } + } + } + }, + "401": { + "description": "Credentials provided are invalid.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "invalid_token": { + "summary": "Token is invalid.", + "value": { + "message": "Invalid token provided." + } + }, + "old_token": { + "summary": "Token was generated before 2023-06-23.", + "value": { + "message": "New format tokens are needed to authenticate this API endpoint. Create a new API token for access." + } + }, + "query_auth": { + "summary": "Authentication attempted via query parameters.", + "value": { + "message": "Support for query parameter authentication has been deprecated to improve security. Please use a supported authentication method such as header-based, or basic authentication." + } + } + } + } + } + }, + "404": { + "description": "Entity not found.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "context_not_found": { + "summary": "Context not found.", + "value": { + "message": "Context not found." + } + }, + "org_not_found": { + "summary": "Organization not found.", + "value": { + "message": "Organization does not exist." + } + }, + "user_not_found": { + "summary": "User not found.", + "value": { + "message": "User does not exist." + } + }, + "project_not_found": { + "summary": "Project not found.", + "value": { + "message": "Project does not exist." + } + }, + "group_not_found": { + "summary": "Group not found.", + "value": { + "message": "Group does not exist." + } + }, + "orb_not_found": { + "summary": "Orb not found.", + "value": { + "message": "Orb does not exist." + } + } + } + } + } + }, + "429": { + "description": "API rate limits exceeded.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Rate limit exceeded." + } + } + } + } + } + }, + "500": { + "description": "Internal server error.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Internal server error." + } + } + } + } + } + } + }, + "parameters": [ + { + "name": "context_id", + "description": "An opaque identifier of a context.", + "example": "be8bb2e3-c3d6-4098-89f4-572ff976ba9a", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "env_var_name", + "description": "The name of the environment variable.", + "example": "POSTGRES_USER", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "value": { + "type": "string", + "description": "The value of the environment variable", + "example": "some-secret-value" + } + }, + "required": [ + "value" + ] + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request PUT \\\n --url https://circleci.com/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a/environment-variable/POSTGRES_USER \\\n --header \"Circle-Token: $CIRCLE_TOKEN\" \\\n --header \"Content-Type: application/json\" \\\n --data \"{\n \\\"value\\\": \\\"some-secret-value\\\"\n}\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a/environment-variable/POSTGRES_USER';\n const options = {\n method: 'PUT',\n headers: {'Circle-Token': '$CIRCLE_TOKEN', 'Content-Type': 'application/json'},\n body: '{\"value\":\"some-secret-value\"}'\n };\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\npayload = \"{\\n \\\"value\\\": \\\"some-secret-value\\\"\\n}\"\n\nheaders = {\n 'Circle-Token': \"$CIRCLE_TOKEN\",\n 'Content-Type': \"application/json\"\n}\n\nconn.request(\"PUT\", \"/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a/environment-variable/POSTGRES_USER\", payload, headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a/environment-variable/POSTGRES_USER\"\n\n\tpayload := strings.NewReader(\"{\\n \\\"value\\\": \\\"some-secret-value\\\"\\n}\")\n\n\treq, _ := http.NewRequest(\"PUT\", url, payload)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a/environment-variable/POSTGRES_USER\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Put.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\nrequest[\"Content-Type\"] = 'application/json'\nrequest.body = \"{\\n \\\"value\\\": \\\"some-secret-value\\\"\\n}\"\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + }, + "delete": { + "summary": "Remove an environment variable", + "description": "Delete an environment variable from a context.", + "tags": [ + "Context" + ], + "operationId": "deleteEnvironmentVariableFromContext", + "responses": { + "200": { + "description": "A confirmation message", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "description": "A human-readable message" + } + }, + "required": [ + "message" + ], + "description": "message response", + "title": "MessageResponse" + } + } + } + }, + "401": { + "description": "Credentials provided are invalid.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "invalid_token": { + "summary": "Token is invalid.", + "value": { + "message": "Invalid token provided." + } + }, + "old_token": { + "summary": "Token was generated before 2023-06-23.", + "value": { + "message": "New format tokens are needed to authenticate this API endpoint. Create a new API token for access." + } + }, + "query_auth": { + "summary": "Authentication attempted via query parameters.", + "value": { + "message": "Support for query parameter authentication has been deprecated to improve security. Please use a supported authentication method such as header-based, or basic authentication." + } + } + } + } + } + }, + "404": { + "description": "Entity not found.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "context_not_found": { + "summary": "Context not found.", + "value": { + "message": "Context not found." + } + }, + "org_not_found": { + "summary": "Organization not found.", + "value": { + "message": "Organization does not exist." + } + }, + "user_not_found": { + "summary": "User not found.", + "value": { + "message": "User does not exist." + } + }, + "project_not_found": { + "summary": "Project not found.", + "value": { + "message": "Project does not exist." + } + }, + "group_not_found": { + "summary": "Group not found.", + "value": { + "message": "Group does not exist." + } + }, + "orb_not_found": { + "summary": "Orb not found.", + "value": { + "message": "Orb does not exist." + } + } + } + } + } + }, + "429": { + "description": "API rate limits exceeded.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Rate limit exceeded." + } + } + } + } + } + }, + "500": { + "description": "Internal server error.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Internal server error." + } + } + } + } + } + } + }, + "parameters": [ + { + "name": "context_id", + "description": "An opaque identifier of a context.", + "example": "be8bb2e3-c3d6-4098-89f4-572ff976ba9a", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "env_var_name", + "description": "The name of the environment variable.", + "example": "POSTGRES_USER", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request DELETE \\\n --url https://circleci.com/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a/environment-variable/POSTGRES_USER \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a/environment-variable/POSTGRES_USER';\n const options = {method: 'DELETE', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"DELETE\", \"/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a/environment-variable/POSTGRES_USER\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a/environment-variable/POSTGRES_USER\"\n\n\treq, _ := http.NewRequest(\"DELETE\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a/environment-variable/POSTGRES_USER\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Delete.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/context/{context_id}/restrictions": { + "parameters": [ + { + "name": "context_id", + "description": "An opaque identifier of a context.", + "example": "be8bb2e3-c3d6-4098-89f4-572ff976ba9a", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "get": { + "operationId": "getContextRestrictions", + "summary": "Get context restrictions", + "description": "Gets a list of project and expression restrictions associated with a context.", + "tags": [ + "Context" + ], + "responses": { + "200": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "items": { + "type": "array", + "items": { + "additionalProperties": false, + "properties": { + "context_id": { + "type": "string", + "format": "uuid", + "description": "UUID of the context" + }, + "id": { + "type": "string", + "format": "uuid", + "description": "UUID of the restriction" + }, + "project_id": { + "type": "string", + "format": "uuid", + "description": "Deprecated - For \"project\" restrictions read the project ID from\n\"restriction_value\" instead.\n\nUUID of the project used in a project restriction.\n", + "deprecated": true + }, + "name": { + "type": "string", + "description": "Contains a human-readable reference for the restriction. For\n\"project\" restrictions this is the name of the project.\n\nMay be null.\n" + }, + "restriction_type": { + "type": "string", + "description": "Type of the restriction" + }, + "restriction_value": { + "type": "string", + "description": "Value used to evaluate the restriction" + } + } + } + }, + "next_page_token": { + "type": "string", + "nullable": true, + "description": "Token that can be used to retrieve next page of results" + } + } + } + } + } + }, + "400": { + "description": "Context ID provided is invalid.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "context_id is invalid." + } + } + } + } + } + }, + "401": { + "description": "Credentials provided are invalid.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "invalid_token": { + "summary": "Token is invalid.", + "value": { + "message": "Invalid token provided." + } + }, + "old_token": { + "summary": "Token was generated before 2023-06-23.", + "value": { + "message": "New format tokens are needed to authenticate this API endpoint. Create a new API token for access." + } + }, + "query_auth": { + "summary": "Authentication attempted via query parameters.", + "value": { + "message": "Support for query parameter authentication has been deprecated to improve security. Please use a supported authentication method such as header-based, or basic authentication." + } + } + } + } + } + }, + "404": { + "description": "Entity not found.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "context_not_found": { + "summary": "Context not found.", + "value": { + "message": "Context not found." + } + }, + "org_not_found": { + "summary": "Organization not found.", + "value": { + "message": "Organization does not exist." + } + }, + "user_not_found": { + "summary": "User not found.", + "value": { + "message": "User does not exist." + } + }, + "project_not_found": { + "summary": "Project not found.", + "value": { + "message": "Project does not exist." + } + }, + "group_not_found": { + "summary": "Group not found.", + "value": { + "message": "Group does not exist." + } + }, + "orb_not_found": { + "summary": "Orb not found.", + "value": { + "message": "Orb does not exist." + } + } + } + } + } + }, + "429": { + "description": "API rate limits exceeded.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Rate limit exceeded." + } + } + } + } + } + }, + "500": { + "description": "Internal server error.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Internal server error." + } + } + } + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a/restrictions \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a/restrictions';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a/restrictions\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a/restrictions\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a/restrictions\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + }, + "post": { + "operationId": "createContextRestriction", + "summary": "Create context restriction", + "description": "Creates project or expression restriction on a context.", + "tags": [ + "Context" + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "restriction_type": { + "type": "string", + "description": "Type of the restriction." + }, + "restriction_value": { + "type": "string", + "description": "Value used to evaluate the restriction. If the `restriction_type`\nis `project`, this will be the project UUID. If the `restriction_type`\nis `expression`, this will be the expression rule.\n" + } + } + }, + "examples": { + "project_restriction": { + "summary": "project restriction", + "value": { + "restriction_type": "project", + "restriction_value": "405d8375-3514-403b-8c43-83ae74cfe0e9" + } + }, + "expression_restriction": { + "summary": "expression restriction", + "value": { + "restriction_type": "expression", + "restriction_value": "pipeline.git.branch == \"main\"" + } + }, + "group_restriction": { + "summary": "group restriction", + "value": { + "restriction_type": "group", + "restriction_value": "30865957-99e1-4b69-8c9f-d83a91756f89" + } + } + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "UUID of the project restriction" + }, + "project_id": { + "type": "string", + "format": "uuid", + "description": "Deprecated - For \"project\" restrictions read the project ID from\n\"restriction_value\" instead.\n\nUUID of the project used in a project restriction.\n" + }, + "name": { + "type": "string", + "description": "Contains a human-readable reference for the restriction. For\n\"project\" restrictions this is the name of the project.\n\nMay be null.\n" + }, + "restriction_type": { + "type": "string", + "description": "Type of the restriction" + }, + "restriction_value": { + "type": "string", + "description": "Value used to evaluate the restriction" + } + } + }, + "examples": { + "project_restriction": { + "summary": "project restriction", + "value": { + "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", + "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9", + "name": "project-name", + "restriction_type": "project", + "restriction_value": "405d8375-3514-403b-8c43-83ae74cfe0e9" + } + }, + "expression_restriction": { + "summary": "expression restriction", + "value": { + "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", + "name": "", + "restriction_type": "expression", + "restriction_value": "pipeline.git.branch == \"main\"" + } + }, + "group_restriction": { + "summary": "group restriction", + "value": { + "id": "30865957-99e1-4b69-8c9f-d83a91756f89", + "name": "A Group In My Organization", + "restriction_type": "group", + "restriction_value": "30865957-99e1-4b69-8c9f-d83a91756f89" + } + } + } + } + } + }, + "400": { + "description": "Bad request.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "invalid_restriction": { + "summary": "Invalid restriction", + "value": { + "message": "This restriction cannot be applied to this context." + } + }, + "invalid_access": { + "summary": "Project doesn't exist, or insufficient credentials", + "value": { + "message": "Project does not exist, or user does not have access to this project." + } + } + } + } + } + }, + "401": { + "description": "Credentials provided are invalid.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "invalid_token": { + "summary": "Token is invalid.", + "value": { + "message": "Invalid token provided." + } + }, + "old_token": { + "summary": "Token was generated before 2023-06-23.", + "value": { + "message": "New format tokens are needed to authenticate this API endpoint. Create a new API token for access." + } + }, + "query_auth": { + "summary": "Authentication attempted via query parameters.", + "value": { + "message": "Support for query parameter authentication has been deprecated to improve security. Please use a supported authentication method such as header-based, or basic authentication." + } + } + } + } + } + }, + "404": { + "description": "Entity not found.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "context_not_found": { + "summary": "Context not found.", + "value": { + "message": "Context not found." + } + }, + "org_not_found": { + "summary": "Organization not found.", + "value": { + "message": "Organization does not exist." + } + }, + "user_not_found": { + "summary": "User not found.", + "value": { + "message": "User does not exist." + } + }, + "project_not_found": { + "summary": "Project not found.", + "value": { + "message": "Project does not exist." + } + }, + "group_not_found": { + "summary": "Group not found.", + "value": { + "message": "Group does not exist." + } + }, + "orb_not_found": { + "summary": "Orb not found.", + "value": { + "message": "Orb does not exist." + } + } + } + } + } + }, + "409": { + "description": "Request conflict.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "restriction_conflict": { + "summary": "Restriction conflict", + "value": { + "message": "The restriction you're trying to add already exists." + } + } + } + } + } + }, + "429": { + "description": "API rate limits exceeded.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Rate limit exceeded." + } + } + } + } + } + }, + "500": { + "description": "Internal server error.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Internal server error." + } + } + } + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request POST \\\n --url https://circleci.com/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a/restrictions \\\n --header \"Circle-Token: $CIRCLE_TOKEN\" \\\n --header \"Content-Type: application/json\" \\\n --data \"{\n \\\"restriction_type\\\": \\\"project\\\",\n \\\"restriction_value\\\": \\\"example-string\\\"\n}\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a/restrictions';\n const options = {\n method: 'POST',\n headers: {'Circle-Token': '$CIRCLE_TOKEN', 'Content-Type': 'application/json'},\n body: '{\"restriction_type\":\"project\",\"restriction_value\":\"example-string\"}'\n };\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\npayload = \"{\\n \\\"restriction_type\\\": \\\"project\\\",\\n \\\"restriction_value\\\": \\\"example-string\\\"\\n}\"\n\nheaders = {\n 'Circle-Token': \"$CIRCLE_TOKEN\",\n 'Content-Type': \"application/json\"\n}\n\nconn.request(\"POST\", \"/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a/restrictions\", payload, headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a/restrictions\"\n\n\tpayload := strings.NewReader(\"{\\n \\\"restriction_type\\\": \\\"project\\\",\\n \\\"restriction_value\\\": \\\"example-string\\\"\\n}\")\n\n\treq, _ := http.NewRequest(\"POST\", url, payload)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a/restrictions\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Post.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\nrequest[\"Content-Type\"] = 'application/json'\nrequest.body = \"{\\n \\\"restriction_type\\\": \\\"project\\\",\\n \\\"restriction_value\\\": \\\"example-string\\\"\\n}\"\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/context/{context_id}/restrictions/{restriction_id}": { + "parameters": [ + { + "name": "context_id", + "description": "An opaque identifier of a context.", + "example": "be8bb2e3-c3d6-4098-89f4-572ff976ba9a", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "restriction_id", + "description": "An opaque identifier of a context restriction.", + "example": "1c23d2cb-07b1-4a28-8af3-e369732050ed", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "delete": { + "operationId": "deleteContextRestriction", + "summary": "Delete context restriction", + "description": "Deletes a project, expression or group restriction from a context.", + "tags": [ + "Context" + ], + "responses": { + "200": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "description": "Response message" + } + } + }, + "examples": { + "successful_delete": { + "summary": "Successful deletion of restriction", + "value": { + "message": "Context restriction deleted." + } + } + } + } + } + }, + "400": { + "description": "Context restriction ID provided is invalid.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "restriction_id is invalid." + } + } + } + } + } + }, + "401": { + "description": "Credentials provided are invalid.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "invalid_token": { + "summary": "Token is invalid.", + "value": { + "message": "Invalid token provided." + } + }, + "old_token": { + "summary": "Token was generated before 2023-06-23.", + "value": { + "message": "New format tokens are needed to authenticate this API endpoint. Create a new API token for access." + } + }, + "query_auth": { + "summary": "Authentication attempted via query parameters.", + "value": { + "message": "Support for query parameter authentication has been deprecated to improve security. Please use a supported authentication method such as header-based, or basic authentication." + } + } + } + } + } + }, + "404": { + "description": "Entity not found.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "context_not_found": { + "summary": "Context not found.", + "value": { + "message": "Context not found." + } + }, + "org_not_found": { + "summary": "Organization not found.", + "value": { + "message": "Organization does not exist." + } + }, + "user_not_found": { + "summary": "User not found.", + "value": { + "message": "User does not exist." + } + }, + "project_not_found": { + "summary": "Project not found.", + "value": { + "message": "Project does not exist." + } + }, + "group_not_found": { + "summary": "Group not found.", + "value": { + "message": "Group does not exist." + } + }, + "orb_not_found": { + "summary": "Orb not found.", + "value": { + "message": "Orb does not exist." + } + } + } + } + } + }, + "429": { + "description": "API rate limits exceeded.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Rate limit exceeded." + } + } + } + } + } + }, + "500": { + "description": "Internal server error.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Internal server error." + } + } + } + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request DELETE \\\n --url https://circleci.com/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a/restrictions/1c23d2cb-07b1-4a28-8af3-e369732050ed \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a/restrictions/1c23d2cb-07b1-4a28-8af3-e369732050ed';\n const options = {method: 'DELETE', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"DELETE\", \"/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a/restrictions/1c23d2cb-07b1-4a28-8af3-e369732050ed\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a/restrictions/1c23d2cb-07b1-4a28-8af3-e369732050ed\"\n\n\treq, _ := http.NewRequest(\"DELETE\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/context/be8bb2e3-c3d6-4098-89f4-572ff976ba9a/restrictions/1c23d2cb-07b1-4a28-8af3-e369732050ed\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Delete.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/project/{provider}/{organization}/{project}": { + "parameters": [ + { + "name": "provider", + "description": "The first segment of the slash-separated project slug, as shown in Project Settings > Overview.", + "example": "gh", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "organization", + "description": "The second segment of the slash-separated project slug, as shown in Project Settings > Overview. Depending on the organization type, this may be the org name (e.g. `my-org`) or an ID (e.g. `43G3lM5RtfFE7v5sa4nWAU`).", + "example": "CircleCI-Public", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "project", + "description": "The third segment of the slash-separated project slug, as shown in Project Settings > Overview. Depending on the organization type, this may be the project name (e.g. `my-project`) or an ID (e.g. `44n9wujWcTnVZ2b5S8Fnat`).", + "example": "api-preview-docs", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "post": { + "operationId": "createProject1", + "summary": "⚠️ Create a project", + "description": "__[DEPRECATED] This endpoint is replaced by [organization/{org-slug-or-id}/project](https://circleci.com/docs/api/v2/index.html#tag/Project/operation/createProject) and documentation will be removed on August 1st, 2025.__ Creates a new CircleCI project, and returns a list of the default advanced settings. Can only be called on a repo with a main branch and an existing config.yml file. Not yet available to projects that use GitLab or GitHub App.", + "tags": [ + "Project" + ], + "responses": { + "201": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "advanced": { + "type": "object", + "additionalProperties": false, + "properties": { + "autocancel_builds": { + "type": "boolean", + "description": "Except for the default branch, cancel running pipelines on a branch when a new pipeline starts on that branch." + }, + "build_fork_prs": { + "type": "boolean", + "description": "Run builds for pull requests from forks." + }, + "build_prs_only": { + "type": "boolean", + "description": "Once enabled, we will only build branches that have associated pull requests open." + }, + "disable_ssh": { + "type": "boolean", + "description": "When set to true, job re-runs with SSH debugging access will be disabled for the project." + }, + "forks_receive_secret_env_vars": { + "type": "boolean", + "description": "Run builds for forked pull requests with this project's configuration, environment variables, and secrets." + }, + "oss": { + "type": "boolean", + "description": "Free and Open Source. Enabling this grants additional credits, and lets others see your builds, both through the web UI and the API." + }, + "set_github_status": { + "type": "boolean", + "description": "Report the status of every pushed commit to GitHub's status API. Updates reported per job." + }, + "setup_workflows": { + "type": "boolean", + "description": "Enabling allows you to conditionally trigger configurations outside of the primary `.circleci` parent directory." + }, + "write_settings_requires_admin": { + "type": "boolean", + "description": "Whether updating these settings requires a user to be an organization administrator. When disabled, updating settings can be done by any member." + }, + "pr_only_branch_overrides": { + "type": "array", + "items": { + "type": "string" + }, + "description": "This field is used in conjunction with the `build_prs_only`, it allows you to specify a list of branches that will always triger a build. The value passed will overwrite the existing value." + } + } + } + } + } + } + } + }, + "400": { + "description": "Unexpected request body provided.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Unexpected request body provided." + } + } + } + } + } + }, + "401": { + "description": "Credentials provided are invalid.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "invalid_token": { + "summary": "Token is invalid.", + "value": { + "message": "Invalid token provided." + } + }, + "old_token": { + "summary": "Token was generated before 2023-06-23.", + "value": { + "message": "New format tokens are needed to authenticate this API endpoint. Create a new API token for access." + } + }, + "query_auth": { + "summary": "Authentication attempted via query parameters.", + "value": { + "message": "Support for query parameter authentication has been deprecated to improve security. Please use a supported authentication method such as header-based, or basic authentication." + } + } + } + } + } + }, + "403": { + "description": "None or insufficient credentials provided.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Permission denied." + } + } + } + } + } + }, + "404": { + "description": "Either a branch or a project were not found.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "branch_not_found": { + "summary": "Branch not found, unable to trigger pipeline.", + "value": { + "message": "Branch not found." + } + }, + "project_not_found": { + "summary": "Project not found, e.g. GitHub repo.", + "value": { + "message": "Project not found." + } + } + } + } + } + }, + "405": { + "description": "Create projects using the API is currently supported for classic Github OAuth and Bitbucket projects only.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Create projects using the API is currently supported for classic Github OAuth and Bitbucket projects only." + } + } + } + } + } + }, + "429": { + "description": "API rate limits exceeded.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Rate limit exceeded." + } + } + } + } + } + }, + "500": { + "description": "Internal server error.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Internal server error." + } + } + } + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request POST \\\n --url https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs';\n const options = {method: 'POST', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"POST\", \"/api/v2/project/gh/CircleCI-Public/api-preview-docs\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs\"\n\n\treq, _ := http.NewRequest(\"POST\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Post.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/project/{provider}/{organization}/{project}/settings": { + "parameters": [ + { + "name": "provider", + "description": "The first segment of the slash-separated project slug, as shown in Project Settings > Overview.", + "example": "gh", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "organization", + "description": "The second segment of the slash-separated project slug, as shown in Project Settings > Overview. Depending on the organization type, this may be the org name (e.g. `my-org`) or an ID (e.g. `43G3lM5RtfFE7v5sa4nWAU`).", + "example": "CircleCI-Public", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "project", + "description": "The third segment of the slash-separated project slug, as shown in Project Settings > Overview. Depending on the organization type, this may be the project name (e.g. `my-project`) or an ID (e.g. `44n9wujWcTnVZ2b5S8Fnat`).", + "example": "api-preview-docs", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "get": { + "operationId": "getProjectSettings", + "summary": "🧪 Get project settings", + "description": "[__EXPERIMENTAL__] Returns a list of the advanced settings for a CircleCI project, whether enabled (true) or not (false).", + "tags": [ + "Project" + ], + "responses": { + "200": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "advanced": { + "type": "object", + "additionalProperties": false, + "properties": { + "autocancel_builds": { + "type": "boolean", + "description": "Except for the default branch, cancel running pipelines on a branch when a new pipeline starts on that branch." + }, + "build_fork_prs": { + "type": "boolean", + "description": "Run builds for pull requests from forks." + }, + "build_prs_only": { + "type": "boolean", + "description": "Once enabled, we will only build branches that have associated pull requests open." + }, + "disable_ssh": { + "type": "boolean", + "description": "When set to true, job re-runs with SSH debugging access will be disabled for the project." + }, + "forks_receive_secret_env_vars": { + "type": "boolean", + "description": "Run builds for forked pull requests with this project's configuration, environment variables, and secrets." + }, + "oss": { + "type": "boolean", + "description": "Free and Open Source. Enabling this grants additional credits, and lets others see your builds, both through the web UI and the API." + }, + "set_github_status": { + "type": "boolean", + "description": "Report the status of every pushed commit to GitHub's status API. Updates reported per job." + }, + "setup_workflows": { + "type": "boolean", + "description": "Enabling allows you to conditionally trigger configurations outside of the primary `.circleci` parent directory." + }, + "write_settings_requires_admin": { + "type": "boolean", + "description": "Whether updating these settings requires a user to be an organization administrator. When disabled, updating settings can be done by any member." + }, + "pr_only_branch_overrides": { + "type": "array", + "items": { + "type": "string" + }, + "description": "This field is used in conjunction with the `build_prs_only`, it allows you to specify a list of branches that will always triger a build. The value passed will overwrite the existing value." + } + } + } + } + } + } + } + }, + "401": { + "description": "Credentials provided are invalid.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "invalid_token": { + "summary": "Token is invalid.", + "value": { + "message": "Invalid token provided." + } + }, + "old_token": { + "summary": "Token was generated before 2023-06-23.", + "value": { + "message": "New format tokens are needed to authenticate this API endpoint. Create a new API token for access." + } + }, + "query_auth": { + "summary": "Authentication attempted via query parameters.", + "value": { + "message": "Support for query parameter authentication has been deprecated to improve security. Please use a supported authentication method such as header-based, or basic authentication." + } + } + } + } + } + }, + "403": { + "description": "None or insufficient credentials provided.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Permission denied." + } + } + } + } + } + }, + "404": { + "description": "Insufficient credentials for a private project, OR the organization, project, or repository does not exist.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Project not found." + } + } + } + } + } + }, + "429": { + "description": "API rate limits exceeded.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Rate limit exceeded." + } + } + } + } + } + }, + "500": { + "description": "Internal server error.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Internal server error." + } + } + } + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/settings \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/settings';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/project/gh/CircleCI-Public/api-preview-docs/settings\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/settings\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/settings\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + }, + "patch": { + "operationId": "patchProjectSettings", + "summary": "🧪 Update project settings", + "description": "[__EXPERIMENTAL__] Updates one or more of the advanced settings for a CircleCI project.", + "tags": [ + "Project" + ], + "requestBody": { + "description": "The setting(s) to update, including one or more fields in the JSON object. Note that `oss: true` will only be set on projects whose underlying repositories are actually open source.", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "advanced": { + "type": "object", + "additionalProperties": false, + "properties": { + "autocancel_builds": { + "type": "boolean", + "description": "Except for the default branch, cancel running pipelines on a branch when a new pipeline starts on that branch." + }, + "build_fork_prs": { + "type": "boolean", + "description": "Run builds for pull requests from forks." + }, + "build_prs_only": { + "type": "boolean", + "description": "Once enabled, we will only build branches that have associated pull requests open." + }, + "disable_ssh": { + "type": "boolean", + "description": "When set to true, job re-runs with SSH debugging access will be disabled for the project." + }, + "forks_receive_secret_env_vars": { + "type": "boolean", + "description": "Run builds for forked pull requests with this project's configuration, environment variables, and secrets." + }, + "oss": { + "type": "boolean", + "description": "Free and Open Source. Enabling this grants additional credits, and lets others see your builds, both through the web UI and the API." + }, + "set_github_status": { + "type": "boolean", + "description": "Report the status of every pushed commit to GitHub's status API. Updates reported per job." + }, + "setup_workflows": { + "type": "boolean", + "description": "Enabling allows you to conditionally trigger configurations outside of the primary `.circleci` parent directory." + }, + "write_settings_requires_admin": { + "type": "boolean", + "description": "Whether updating these settings requires a user to be an organization administrator. When disabled, updating settings can be done by any member." + }, + "pr_only_branch_overrides": { + "type": "array", + "items": { + "type": "string" + }, + "description": "This field is used in conjunction with the `build_prs_only`, it allows you to specify a list of branches that will always triger a build. The value passed will overwrite the existing value." + } + } + } + } + }, + "example": { + "advanced": { + "autocancel_builds": false, + "build_prs_only": true, + "pr_only_branch_overrides": [ + "main" + ] + } + } + } + } + }, + "responses": { + "200": { + "description": "Successful response. Always includes the full advanced settings object. Returned even when the provided updates match the existing settings, but can also be returned when `oss: true` fails to set.", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "advanced": { + "type": "object", + "additionalProperties": false, + "properties": { + "autocancel_builds": { + "type": "boolean", + "description": "Except for the default branch, cancel running pipelines on a branch when a new pipeline starts on that branch." + }, + "build_fork_prs": { + "type": "boolean", + "description": "Run builds for pull requests from forks." + }, + "build_prs_only": { + "type": "boolean", + "description": "Once enabled, we will only build branches that have associated pull requests open." + }, + "disable_ssh": { + "type": "boolean", + "description": "When set to true, job re-runs with SSH debugging access will be disabled for the project." + }, + "forks_receive_secret_env_vars": { + "type": "boolean", + "description": "Run builds for forked pull requests with this project's configuration, environment variables, and secrets." + }, + "oss": { + "type": "boolean", + "description": "Free and Open Source. Enabling this grants additional credits, and lets others see your builds, both through the web UI and the API." + }, + "set_github_status": { + "type": "boolean", + "description": "Report the status of every pushed commit to GitHub's status API. Updates reported per job." + }, + "setup_workflows": { + "type": "boolean", + "description": "Enabling allows you to conditionally trigger configurations outside of the primary `.circleci` parent directory." + }, + "write_settings_requires_admin": { + "type": "boolean", + "description": "Whether updating these settings requires a user to be an organization administrator. When disabled, updating settings can be done by any member." + }, + "pr_only_branch_overrides": { + "type": "array", + "items": { + "type": "string" + }, + "description": "This field is used in conjunction with the `build_prs_only`, it allows you to specify a list of branches that will always triger a build. The value passed will overwrite the existing value." + } + } + } + } + } + } + } + }, + "400": { + "description": "Request is malformed, e.g. with improperly encoded JSON", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "invalid_json": { + "summary": "Invalid JSON body", + "value": { + "message": "Invalid JSON body." + } + }, + "too_many_branch_overrides": { + "summary": "More than 100 branches sent for `pr_only_branch_overrides`", + "value": { + "message": "Field 'pr_only_branch_overrides' only supports up to 100 branches." + } + }, + "no_json": { + "summary": "Empty JSON request body", + "value": { + "message": "No JSON fields found." + } + }, + "unexpected_field": { + "summary": "Incorrect root field name", + "value": { + "message": "Unexpected JSON field 'incorrect'" + } + }, + "unknown_setting": { + "summary": "Incorrect setting name", + "value": { + "message": "Unknown advanced setting 'incorrect'." + } + }, + "incorrect_type": { + "summary": "Incorrect setting type", + "value": { + "message": "Setting 'autocancel_builds' must be boolean." + } + }, + "oss": { + "summary": "Incorrect OSS value for project", + "value": { + "message": "Feature flag 'oss' is not settable for this project." + } + } + } + } + } + }, + "401": { + "description": "Credentials provided are invalid.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "invalid_token": { + "summary": "Token is invalid.", + "value": { + "message": "Invalid token provided." + } + }, + "old_token": { + "summary": "Token was generated before 2023-06-23.", + "value": { + "message": "New format tokens are needed to authenticate this API endpoint. Create a new API token for access." + } + }, + "query_auth": { + "summary": "Authentication attempted via query parameters.", + "value": { + "message": "Support for query parameter authentication has been deprecated to improve security. Please use a supported authentication method such as header-based, or basic authentication." + } + } + } + } + } + }, + "403": { + "description": "None or insufficient credentials provided.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Permission denied." + } + } + } + } + } + }, + "404": { + "description": "Insufficient credentials for a private project, OR the organization, project, or repository does not exist.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Project not found." + } + } + } + } + } + }, + "429": { + "description": "API rate limits exceeded.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Rate limit exceeded." + } + } + } + } + } + }, + "500": { + "description": "Internal server error.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Internal server error." + } + } + } + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request PATCH \\\n --url https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/settings \\\n --header \"Circle-Token: $CIRCLE_TOKEN\" \\\n --header \"Content-Type: application/json\" \\\n --data \"{\n \\\"advanced\\\": {\n \\\"autocancel_builds\\\": true,\n \\\"build_fork_prs\\\": true,\n \\\"build_prs_only\\\": true\n }\n}\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/settings';\n const options = {\n method: 'PATCH',\n headers: {'Circle-Token': '$CIRCLE_TOKEN', 'Content-Type': 'application/json'},\n body: '{\"advanced\":{\"autocancel_builds\":true,\"build_fork_prs\":true,\"build_prs_only\":true}}'\n };\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\npayload = \"{\\n \\\"advanced\\\": {\\n \\\"autocancel_builds\\\": true,\\n \\\"build_fork_prs\\\": true,\\n \\\"build_prs_only\\\": true\\n }\\n}\"\n\nheaders = {\n 'Circle-Token': \"$CIRCLE_TOKEN\",\n 'Content-Type': \"application/json\"\n}\n\nconn.request(\"PATCH\", \"/api/v2/project/gh/CircleCI-Public/api-preview-docs/settings\", payload, headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/settings\"\n\n\tpayload := strings.NewReader(\"{\\n \\\"advanced\\\": {\\n \\\"autocancel_builds\\\": true,\\n \\\"build_fork_prs\\\": true,\\n \\\"build_prs_only\\\": true\\n }\\n}\")\n\n\treq, _ := http.NewRequest(\"PATCH\", url, payload)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/settings\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Patch.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\nrequest[\"Content-Type\"] = 'application/json'\nrequest.body = \"{\\n \\\"advanced\\\": {\\n \\\"autocancel_builds\\\": true,\\n \\\"build_fork_prs\\\": true,\\n \\\"build_prs_only\\\": true\\n }\\n}\"\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/organizations/{org_id}/groups": { + "parameters": [ + { + "name": "org_id", + "description": "An opaque identifier of an organization.", + "example": "b9291e0d-a11e-41fb-8517-c545388b5953", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "get": { + "operationId": "getOrganizationGroups", + "summary": "Groups in an organization", + "description": "Get all the groups in an organization.", + "tags": [ + "Groups" + ], + "parameters": [ + { + "name": "limit", + "in": "query", + "description": "The number of results per page.", + "schema": { + "type": "integer" + } + }, + { + "name": "page-token", + "in": "query", + "description": "A token to specify which page of results to fetch.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully get all the groups in an organization. Results are paginated.", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "items": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for group" + }, + "name": { + "type": "string", + "description": "Name of group" + }, + "description": { + "type": "string", + "description": "Description field on group" + } + } + } + }, + "next_page_token": { + "type": "string", + "nullable": true + }, + "total_count": { + "type": "integer" + } + } + }, + "examples": { + "groups": { + "summary": "A list of sample groups", + "value": { + "items": [ + { + "id": "bdbe5e8d-50a5-4f73-a917-074592949844", + "name": "Project B Editors", + "description": "This group has the ability to edit settings on Project B." + }, + { + "id": "70dbc16f-a6b9-4c32-b258-4a61a861c24f", + "name": "Project MLOps Editors", + "description": "This group has the ability to edit settings on ML Ops Projects." + } + ], + "next_page_token": "CiRkNjVjY2ZiMy04OGFlLTQ3YjUtYWFjNi0wZDRkNDYwNmQ5ZjYQChoDbmls" + } + } + } + } + } + }, + "403": { + "description": "None or insufficient credentials provided.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Permission denied." + } + } + } + } + } + }, + "404": { + "description": "Entity not found.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "context_not_found": { + "summary": "Context not found.", + "value": { + "message": "Context not found." + } + }, + "org_not_found": { + "summary": "Organization not found.", + "value": { + "message": "Organization does not exist." + } + }, + "user_not_found": { + "summary": "User not found.", + "value": { + "message": "User does not exist." + } + }, + "project_not_found": { + "summary": "Project not found.", + "value": { + "message": "Project does not exist." + } + }, + "group_not_found": { + "summary": "Group not found.", + "value": { + "message": "Group does not exist." + } + }, + "orb_not_found": { + "summary": "Orb not found.", + "value": { + "message": "Orb does not exist." + } + } + } + } + } + }, + "500": { + "description": "Internal server error.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Internal server error." + } + } + } + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url \"https://circleci.com/api/v2/organizations/b9291e0d-a11e-41fb-8517-c545388b5953/groups?limit=123&page-token=example-value\" \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/organizations/b9291e0d-a11e-41fb-8517-c545388b5953/groups?limit=123&page-token=example-value';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/organizations/b9291e0d-a11e-41fb-8517-c545388b5953/groups?limit=123&page-token=example-value\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/organizations/b9291e0d-a11e-41fb-8517-c545388b5953/groups?limit=123&page-token=example-value\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/organizations/b9291e0d-a11e-41fb-8517-c545388b5953/groups?limit=123&page-token=example-value\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + }, + "post": { + "operationId": "createOrganizationGroup", + "summary": "Create Groups", + "description": "Create a new group under the organization.", + "tags": [ + "Groups" + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string", + "description": "Name of the group" + }, + "description": { + "type": "string", + "description": "Description to describe the group" + } + }, + "required": [ + "name" + ] + }, + "examples": { + "group": { + "summary": "Create a new group", + "value": { + "name": "Project A Editors", + "description": "Users in this group have edit access to Project A" + } + } + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "Successful creation of a group.", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for group" + }, + "name": { + "type": "string", + "description": "Name of group" + }, + "description": { + "type": "string", + "description": "Description field on group" + } + } + }, + "examples": { + "group": { + "summary": "A sample group", + "value": { + "id": "9e5e5f87-3e87-47ea-be0f-37265b965d6e", + "name": "Project A Editors", + "description": "Users in this group have edit access to Project A" + } + } + } + } + } + }, + "400": { + "description": "Unexpected request body provided.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Unexpected request body provided." + } + } + } + } + } + }, + "401": { + "description": "Credentials provided are invalid.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "invalid_token": { + "summary": "Token is invalid.", + "value": { + "message": "Invalid token provided." + } + }, + "old_token": { + "summary": "Token was generated before 2023-06-23.", + "value": { + "message": "New format tokens are needed to authenticate this API endpoint. Create a new API token for access." + } + }, + "query_auth": { + "summary": "Authentication attempted via query parameters.", + "value": { + "message": "Support for query parameter authentication has been deprecated to improve security. Please use a supported authentication method such as header-based, or basic authentication." + } + } + } + } + } + }, + "403": { + "description": "None or insufficient credentials provided.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Permission denied." + } + } + } + } + } + }, + "404": { + "description": "Entity not found.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "context_not_found": { + "summary": "Context not found.", + "value": { + "message": "Context not found." + } + }, + "org_not_found": { + "summary": "Organization not found.", + "value": { + "message": "Organization does not exist." + } + }, + "user_not_found": { + "summary": "User not found.", + "value": { + "message": "User does not exist." + } + }, + "project_not_found": { + "summary": "Project not found.", + "value": { + "message": "Project does not exist." + } + }, + "group_not_found": { + "summary": "Group not found.", + "value": { + "message": "Group does not exist." + } + }, + "orb_not_found": { + "summary": "Orb not found.", + "value": { + "message": "Orb does not exist." + } + } + } + } + } + }, + "409": { + "description": "A conflict has occurred while attempting to create the resource.\n", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "max_groups": { + "summary": "Max number of groups reached", + "value": { + "message": "Failed to create group, reached max number of groups for this organization." + } + }, + "name_already_taken": { + "summary": "Group name already taken", + "value": { + "message": "Failed to create group, group already exists." + } + } + } + } + } + }, + "500": { + "description": "Internal server error.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Internal server error." + } + } + } + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request POST \\\n --url https://circleci.com/api/v2/organizations/b9291e0d-a11e-41fb-8517-c545388b5953/groups \\\n --header \"Circle-Token: $CIRCLE_TOKEN\" \\\n --header \"Content-Type: application/json\" \\\n --data \"{\n \\\"name\\\": \\\"example-string\\\",\n \\\"description\\\": \\\"example-string\\\"\n}\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/organizations/b9291e0d-a11e-41fb-8517-c545388b5953/groups';\n const options = {\n method: 'POST',\n headers: {'Circle-Token': '$CIRCLE_TOKEN', 'Content-Type': 'application/json'},\n body: '{\"name\":\"example-string\",\"description\":\"example-string\"}'\n };\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\npayload = \"{\\n \\\"name\\\": \\\"example-string\\\",\\n \\\"description\\\": \\\"example-string\\\"\\n}\"\n\nheaders = {\n 'Circle-Token': \"$CIRCLE_TOKEN\",\n 'Content-Type': \"application/json\"\n}\n\nconn.request(\"POST\", \"/api/v2/organizations/b9291e0d-a11e-41fb-8517-c545388b5953/groups\", payload, headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/organizations/b9291e0d-a11e-41fb-8517-c545388b5953/groups\"\n\n\tpayload := strings.NewReader(\"{\\n \\\"name\\\": \\\"example-string\\\",\\n \\\"description\\\": \\\"example-string\\\"\\n}\")\n\n\treq, _ := http.NewRequest(\"POST\", url, payload)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/organizations/b9291e0d-a11e-41fb-8517-c545388b5953/groups\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Post.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\nrequest[\"Content-Type\"] = 'application/json'\nrequest.body = \"{\\n \\\"name\\\": \\\"example-string\\\",\\n \\\"description\\\": \\\"example-string\\\"\\n}\"\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/organizations/{org_id}/groups/{group_id}": { + "parameters": [ + { + "name": "org_id", + "description": "An opaque identifier of an organization.", + "example": "b9291e0d-a11e-41fb-8517-c545388b5953", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "group_id", + "description": "An opaque identifier of a group.", + "example": "39f660db-f49b-417e-ad79-2769ba29faf7", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "get": { + "operationId": "getGroup", + "summary": "A group in an organization", + "description": "Get details for a group in an organization.", + "tags": [ + "Groups" + ], + "responses": { + "200": { + "description": "Successfully gets a group. Members not included.", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for group" + }, + "name": { + "type": "string", + "description": "Name of group" + }, + "description": { + "type": "string", + "description": "Description field on group" + } + } + }, + "examples": { + "group": { + "summary": "A sample group", + "value": { + "id": "bdbe5e8d-50a5-4f73-a917-074592949844", + "name": "Project A Editors", + "description": "Users can edit Project A settings." + } + } + } + } + } + }, + "403": { + "description": "None or insufficient credentials provided.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Permission denied." + } + } + } + } + } + }, + "404": { + "description": "Entity not found.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "context_not_found": { + "summary": "Context not found.", + "value": { + "message": "Context not found." + } + }, + "org_not_found": { + "summary": "Organization not found.", + "value": { + "message": "Organization does not exist." + } + }, + "user_not_found": { + "summary": "User not found.", + "value": { + "message": "User does not exist." + } + }, + "project_not_found": { + "summary": "Project not found.", + "value": { + "message": "Project does not exist." + } + }, + "group_not_found": { + "summary": "Group not found.", + "value": { + "message": "Group does not exist." + } + }, + "orb_not_found": { + "summary": "Orb not found.", + "value": { + "message": "Orb does not exist." + } + } + } + } + } + }, + "500": { + "description": "Internal server error.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Internal server error." + } + } + } + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/organizations/b9291e0d-a11e-41fb-8517-c545388b5953/groups/39f660db-f49b-417e-ad79-2769ba29faf7 \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/organizations/b9291e0d-a11e-41fb-8517-c545388b5953/groups/39f660db-f49b-417e-ad79-2769ba29faf7';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/organizations/b9291e0d-a11e-41fb-8517-c545388b5953/groups/39f660db-f49b-417e-ad79-2769ba29faf7\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/organizations/b9291e0d-a11e-41fb-8517-c545388b5953/groups/39f660db-f49b-417e-ad79-2769ba29faf7\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/organizations/b9291e0d-a11e-41fb-8517-c545388b5953/groups/39f660db-f49b-417e-ad79-2769ba29faf7\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + }, + "delete": { + "operationId": "deleteGroup", + "summary": "Delete a group", + "description": "Delete a group in an organization. This will remove all members from the group as well, and the subsequent role grants tied to the group.", + "tags": [ + "Groups" + ], + "responses": { + "200": { + "description": "Successful deletion of a group.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Group deleted." + } + } + } + } + } + }, + "401": { + "description": "Credentials provided are invalid.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "invalid_token": { + "summary": "Token is invalid.", + "value": { + "message": "Invalid token provided." + } + }, + "old_token": { + "summary": "Token was generated before 2023-06-23.", + "value": { + "message": "New format tokens are needed to authenticate this API endpoint. Create a new API token for access." + } + }, + "query_auth": { + "summary": "Authentication attempted via query parameters.", + "value": { + "message": "Support for query parameter authentication has been deprecated to improve security. Please use a supported authentication method such as header-based, or basic authentication." + } + } + } + } + } + }, + "403": { + "description": "None or insufficient credentials provided.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Permission denied." + } + } + } + } + } + }, + "404": { + "description": "Entity not found.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "context_not_found": { + "summary": "Context not found.", + "value": { + "message": "Context not found." + } + }, + "org_not_found": { + "summary": "Organization not found.", + "value": { + "message": "Organization does not exist." + } + }, + "user_not_found": { + "summary": "User not found.", + "value": { + "message": "User does not exist." + } + }, + "project_not_found": { + "summary": "Project not found.", + "value": { + "message": "Project does not exist." + } + }, + "group_not_found": { + "summary": "Group not found.", + "value": { + "message": "Group does not exist." + } + }, + "orb_not_found": { + "summary": "Orb not found.", + "value": { + "message": "Orb does not exist." + } + } + } + } + } + }, + "500": { + "description": "Internal server error.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Internal server error." + } + } + } + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request DELETE \\\n --url https://circleci.com/api/v2/organizations/b9291e0d-a11e-41fb-8517-c545388b5953/groups/39f660db-f49b-417e-ad79-2769ba29faf7 \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/organizations/b9291e0d-a11e-41fb-8517-c545388b5953/groups/39f660db-f49b-417e-ad79-2769ba29faf7';\n const options = {method: 'DELETE', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"DELETE\", \"/api/v2/organizations/b9291e0d-a11e-41fb-8517-c545388b5953/groups/39f660db-f49b-417e-ad79-2769ba29faf7\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/organizations/b9291e0d-a11e-41fb-8517-c545388b5953/groups/39f660db-f49b-417e-ad79-2769ba29faf7\"\n\n\treq, _ := http.NewRequest(\"DELETE\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/organizations/b9291e0d-a11e-41fb-8517-c545388b5953/groups/39f660db-f49b-417e-ad79-2769ba29faf7\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Delete.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/organizations/{org_id}/usage_export_job": { + "parameters": [ + { + "name": "org_id", + "description": "An opaque identifier of an organization.", + "example": "b9291e0d-a11e-41fb-8517-c545388b5953", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "post": { + "operationId": "createUsageExport", + "summary": "Create a usage export", + "description": "Submits a request to create a usage export for an organization.", + "tags": [ + "Usage" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "type": "object", + "properties": { + "start": { + "type": "string", + "format": "date-time", + "description": "The start date & time (inclusive) of the range from which data will be pulled. Must be no more than one year ago." + }, + "end": { + "type": "string", + "format": "date-time", + "description": "The end date & time (inclusive) of the range from which data will be pulled. Must be no more than 31 days after `start`." + }, + "shared_org_ids": { + "type": "array", + "items": { + "type": "string", + "format": "uuid", + "description": "Additional shared org IDs to to include data for in the generated usage export." + } + } + }, + "required": [ + "start", + "end" + ] + } + } + } + }, + "responses": { + "201": { + "description": "Usage export created successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "usage_export_job_id": { + "type": "string", + "format": "uuid" + }, + "state": { + "type": "string" + }, + "start": { + "type": "string", + "format": "date-time" + }, + "end": { + "type": "string", + "format": "date-time" + }, + "download_urls": { + "description": "A list of pre signed urls that the client can use to download the results of a Usage Export.", + "type": "array", + "items": { + "additionalProperties": false, + "type": "string", + "format": "uri" + } + } + }, + "required": [ + "usage_export_job_id", + "state", + "start", + "end", + "download_urls" + ] + } + } + } + }, + "400": { + "description": "Unexpected request body provided.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Unexpected request body provided." + } + } + } + } + } + }, + "401": { + "description": "Credentials provided are invalid.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "invalid_token": { + "summary": "Token is invalid.", + "value": { + "message": "Invalid token provided." + } + }, + "old_token": { + "summary": "Token was generated before 2023-06-23.", + "value": { + "message": "New format tokens are needed to authenticate this API endpoint. Create a new API token for access." + } + }, + "query_auth": { + "summary": "Authentication attempted via query parameters.", + "value": { + "message": "Support for query parameter authentication has been deprecated to improve security. Please use a supported authentication method such as header-based, or basic authentication." + } + } + } + } + } + }, + "404": { + "description": "Entity not found.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "context_not_found": { + "summary": "Context not found.", + "value": { + "message": "Context not found." + } + }, + "org_not_found": { + "summary": "Organization not found.", + "value": { + "message": "Organization does not exist." + } + }, + "user_not_found": { + "summary": "User not found.", + "value": { + "message": "User does not exist." + } + }, + "project_not_found": { + "summary": "Project not found.", + "value": { + "message": "Project does not exist." + } + }, + "group_not_found": { + "summary": "Group not found.", + "value": { + "message": "Group does not exist." + } + }, + "orb_not_found": { + "summary": "Orb not found.", + "value": { + "message": "Orb does not exist." + } + } + } + } + } + }, + "429": { + "description": "API rate limits exceeded.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Rate limit exceeded." + } + } + } + } + } + }, + "500": { + "description": "Internal server error.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Internal server error." + } + } + } + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request POST \\\n --url https://circleci.com/api/v2/organizations/b9291e0d-a11e-41fb-8517-c545388b5953/usage_export_job \\\n --header \"Circle-Token: $CIRCLE_TOKEN\" \\\n --header \"Content-Type: application/json\" \\\n --data \"{\n \\\"start\\\": \\\"example-string\\\",\n \\\"end\\\": \\\"example-string\\\",\n \\\"shared_org_ids\\\": [\n \\\"example-string\\\"\n ]\n}\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/organizations/b9291e0d-a11e-41fb-8517-c545388b5953/usage_export_job';\n const options = {\n method: 'POST',\n headers: {'Circle-Token': '$CIRCLE_TOKEN', 'Content-Type': 'application/json'},\n body: '{\"start\":\"example-string\",\"end\":\"example-string\",\"shared_org_ids\":[\"example-string\"]}'\n };\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\npayload = \"{\\n \\\"start\\\": \\\"example-string\\\",\\n \\\"end\\\": \\\"example-string\\\",\\n \\\"shared_org_ids\\\": [\\n \\\"example-string\\\"\\n ]\\n}\"\n\nheaders = {\n 'Circle-Token': \"$CIRCLE_TOKEN\",\n 'Content-Type': \"application/json\"\n}\n\nconn.request(\"POST\", \"/api/v2/organizations/b9291e0d-a11e-41fb-8517-c545388b5953/usage_export_job\", payload, headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/organizations/b9291e0d-a11e-41fb-8517-c545388b5953/usage_export_job\"\n\n\tpayload := strings.NewReader(\"{\\n \\\"start\\\": \\\"example-string\\\",\\n \\\"end\\\": \\\"example-string\\\",\\n \\\"shared_org_ids\\\": [\\n \\\"example-string\\\"\\n ]\\n}\")\n\n\treq, _ := http.NewRequest(\"POST\", url, payload)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/organizations/b9291e0d-a11e-41fb-8517-c545388b5953/usage_export_job\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Post.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\nrequest[\"Content-Type\"] = 'application/json'\nrequest.body = \"{\\n \\\"start\\\": \\\"example-string\\\",\\n \\\"end\\\": \\\"example-string\\\",\\n \\\"shared_org_ids\\\": [\\n \\\"example-string\\\"\\n ]\\n}\"\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/organizations/{org_id}/usage_export_job/{usage_export_job_id}": { + "parameters": [ + { + "name": "org_id", + "description": "An opaque identifier of an organization.", + "example": "b9291e0d-a11e-41fb-8517-c545388b5953", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "usage_export_job_id", + "description": "An opaque identifier of a usage export job.", + "example": "e8235eed-f121-4ae3-9c72-2719d6572818", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "get": { + "operationId": "getUsageExport", + "summary": "Get a usage export", + "description": "Gets a usage export for an organization.", + "tags": [ + "Usage" + ], + "responses": { + "200": { + "description": "Usage export fetched successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "usage_export_job_id": { + "type": "string", + "format": "uuid" + }, + "state": { + "type": "string" + }, + "download_urls": { + "description": "A list of pre signed urls that the client can use to download the results of a Usage Export.", + "type": "array", + "items": { + "additionalProperties": false, + "type": "string", + "format": "uri" + } + }, + "error_reason": { + "type": "string" + } + }, + "required": [ + "usage_export_job_id", + "state", + "download_urls" + ] + } + } + } + }, + "400": { + "description": "Unexpected request body provided.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Unexpected request body provided." + } + } + } + } + } + }, + "401": { + "description": "Credentials provided are invalid.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "invalid_token": { + "summary": "Token is invalid.", + "value": { + "message": "Invalid token provided." + } + }, + "old_token": { + "summary": "Token was generated before 2023-06-23.", + "value": { + "message": "New format tokens are needed to authenticate this API endpoint. Create a new API token for access." + } + }, + "query_auth": { + "summary": "Authentication attempted via query parameters.", + "value": { + "message": "Support for query parameter authentication has been deprecated to improve security. Please use a supported authentication method such as header-based, or basic authentication." + } + } + } + } + } + }, + "404": { + "description": "Entity not found.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "context_not_found": { + "summary": "Context not found.", + "value": { + "message": "Context not found." + } + }, + "org_not_found": { + "summary": "Organization not found.", + "value": { + "message": "Organization does not exist." + } + }, + "user_not_found": { + "summary": "User not found.", + "value": { + "message": "User does not exist." + } + }, + "project_not_found": { + "summary": "Project not found.", + "value": { + "message": "Project does not exist." + } + }, + "group_not_found": { + "summary": "Group not found.", + "value": { + "message": "Group does not exist." + } + }, + "orb_not_found": { + "summary": "Orb not found.", + "value": { + "message": "Orb does not exist." + } + } + } + } + } + }, + "429": { + "description": "API rate limits exceeded.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Rate limit exceeded." + } + } + } + } + } + }, + "500": { + "description": "Internal server error.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Internal server error." + } + } + } + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/organizations/b9291e0d-a11e-41fb-8517-c545388b5953/usage_export_job/e8235eed-f121-4ae3-9c72-2719d6572818 \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/organizations/b9291e0d-a11e-41fb-8517-c545388b5953/usage_export_job/e8235eed-f121-4ae3-9c72-2719d6572818';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/organizations/b9291e0d-a11e-41fb-8517-c545388b5953/usage_export_job/e8235eed-f121-4ae3-9c72-2719d6572818\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/organizations/b9291e0d-a11e-41fb-8517-c545388b5953/usage_export_job/e8235eed-f121-4ae3-9c72-2719d6572818\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/organizations/b9291e0d-a11e-41fb-8517-c545388b5953/usage_export_job/e8235eed-f121-4ae3-9c72-2719d6572818\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/project/{provider}/{organization}/{project}/pipeline/run": { + "post": { + "operationId": "triggerPipelineRun", + "summary": "[Recommended] Trigger a new pipeline", + "description": "Trigger a pipeline given a pipeline definition ID. Supports all integrations except GitLab.\n\nThe slash-separated project slug is shown in Project Settings > Overview.\n\nDepending on the organization type, the project slug may have a human-readable format (`vcs_type/org_name/project_name`)\nor be an opaque string (e.g. `circleci/43G3lM5RtfFE7v5sa4nWAU/44n9wujWcTnVZ2b5S8Fnat`).", + "tags": [ + "Pipeline" + ], + "parameters": [ + { + "name": "provider", + "description": "The first segment of the slash-separated project slug, as shown in Project Settings > Overview.", + "example": "gh", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + }, + { + "name": "organization", + "description": "The second segment of the slash-separated project slug, as shown in Project Settings > Overview. Depending on the organization type, this may be the org name (e.g. `my-org`) or an ID (e.g. `43G3lM5RtfFE7v5sa4nWAU`).", + "example": "CircleCI-Public", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "project", + "description": "The third segment of the slash-separated project slug, as shown in Project Settings > Overview. Depending on the organization type, this may be the project name (e.g. `my-project`) or an ID (e.g. `44n9wujWcTnVZ2b5S8Fnat`).", + "example": "api-preview-docs", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "definition_id": { + "type": "string", + "format": "uuid", + "description": "The unique id for the pipeline definition. This can be found in the page Project Settings > Pipelines.", + "example": "2338d0ae-5541-4bbf-88a2-55e9f7281f80" + }, + "config": { + "type": "object", + "additionalProperties": false, + "example": { + "branch": "main" + }, + "properties": { + "branch": { + "type": "string", + "example": "main", + "description": "The branch that should be used to fetch the config file.\nNote that branch and tag are mutually exclusive.\nTo trigger a pipeline for a PR by number use pull//head for the PR ref or pull//merge for the merge ref (GitHub only)\n" + }, + "tag": { + "type": "string", + "example": "v2", + "description": "The tag that should be used to fetch the config file.\nThe commit that this tag points to is used for the pipeline.\nNote that branch and tag are mutually exclusive.\n" + } + } + }, + "checkout": { + "type": "object", + "additionalProperties": false, + "example": { + "tag": "v2" + }, + "properties": { + "branch": { + "type": "string", + "example": "main", + "description": "The branch that should be used to check out code on a checkout step.\nNote that branch and tag are mutually exclusive.\nTo trigger a pipeline for a PR by number use pull//head for the PR ref or pull//merge for the merge ref (GitHub only)\n" + }, + "tag": { + "type": "string", + "example": "v2", + "description": "The tag that should be used to check out code on a checkout step.\nThe commit that this tag points to is used for the pipeline. Note that branch and tag are mutually exclusive.\n" + } + } + }, + "parameters": { + "type": "object", + "additionalProperties": true, + "description": "An object containing pipeline parameters and their values.\nPipeline parameters have the following size limits: 100 max entries, 128 maximum key length, 512 maximum value length.\n", + "example": { + "example_param": "my value", + "example_param2": true, + "example_param3": 3 + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Successful response with no created pipeline.", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "description": "A message indicating the reason why a pipeline was not triggered", + "example": "Ignoring pipeline due to CI skip in the commit" + } + } + } + } + } + }, + "201": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "state": { + "type": "string" + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "number": { + "type": "integer", + "example": 25 + }, + "id": { + "type": "string", + "format": "uuid" + } + } + } + } + } + }, + "400": { + "description": "Unexpected request body provided.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Unexpected request body provided." + } + } + } + } + } + }, + "401": { + "description": "Credentials provided are invalid.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "invalid_token": { + "summary": "Token is invalid.", + "value": { + "message": "Invalid token provided." + } + }, + "old_token": { + "summary": "Token was generated before 2023-06-23.", + "value": { + "message": "New format tokens are needed to authenticate this API endpoint. Create a new API token for access." + } + }, + "query_auth": { + "summary": "Authentication attempted via query parameters.", + "value": { + "message": "Support for query parameter authentication has been deprecated to improve security. Please use a supported authentication method such as header-based, or basic authentication." + } + } + } + } + } + }, + "404": { + "description": "Entity not found.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "context_not_found": { + "summary": "Context not found.", + "value": { + "message": "Context not found." + } + }, + "org_not_found": { + "summary": "Organization not found.", + "value": { + "message": "Organization does not exist." + } + }, + "user_not_found": { + "summary": "User not found.", + "value": { + "message": "User does not exist." + } + }, + "project_not_found": { + "summary": "Project not found.", + "value": { + "message": "Project does not exist." + } + }, + "group_not_found": { + "summary": "Group not found.", + "value": { + "message": "Group does not exist." + } + }, + "orb_not_found": { + "summary": "Orb not found.", + "value": { + "message": "Orb does not exist." + } + } + } + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request POST \\\n --url https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/pipeline/run \\\n --header \"Circle-Token: $CIRCLE_TOKEN\" \\\n --header \"Content-Type: application/json\" \\\n --data \"{\n \\\"definition_id\\\": \\\"2338d0ae-5541-4bbf-88a2-55e9f7281f80\\\",\n \\\"config\\\": {\n \\\"branch\\\": \\\"main\\\"\n },\n \\\"checkout\\\": {\n \\\"tag\\\": \\\"v2\\\"\n }\n}\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/pipeline/run';\n const options = {\n method: 'POST',\n headers: {'Circle-Token': '$CIRCLE_TOKEN', 'Content-Type': 'application/json'},\n body: '{\"definition_id\":\"2338d0ae-5541-4bbf-88a2-55e9f7281f80\",\"config\":{\"branch\":\"main\"},\"checkout\":{\"tag\":\"v2\"}}'\n };\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\npayload = \"{\\n \\\"definition_id\\\": \\\"2338d0ae-5541-4bbf-88a2-55e9f7281f80\\\",\\n \\\"config\\\": {\\n \\\"branch\\\": \\\"main\\\"\\n },\\n \\\"checkout\\\": {\\n \\\"tag\\\": \\\"v2\\\"\\n }\\n}\"\n\nheaders = {\n 'Circle-Token': \"$CIRCLE_TOKEN\",\n 'Content-Type': \"application/json\"\n}\n\nconn.request(\"POST\", \"/api/v2/project/gh/CircleCI-Public/api-preview-docs/pipeline/run\", payload, headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/pipeline/run\"\n\n\tpayload := strings.NewReader(\"{\\n \\\"definition_id\\\": \\\"2338d0ae-5541-4bbf-88a2-55e9f7281f80\\\",\\n \\\"config\\\": {\\n \\\"branch\\\": \\\"main\\\"\\n },\\n \\\"checkout\\\": {\\n \\\"tag\\\": \\\"v2\\\"\\n }\\n}\")\n\n\treq, _ := http.NewRequest(\"POST\", url, payload)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/project/gh/CircleCI-Public/api-preview-docs/pipeline/run\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Post.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\nrequest[\"Content-Type\"] = 'application/json'\nrequest.body = \"{\\n \\\"definition_id\\\": \\\"2338d0ae-5541-4bbf-88a2-55e9f7281f80\\\",\\n \\\"config\\\": {\\n \\\"branch\\\": \\\"main\\\"\\n },\\n \\\"checkout\\\": {\\n \\\"tag\\\": \\\"v2\\\"\\n }\\n}\"\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/projects/{project_id}/pipeline-definitions": { + "get": { + "operationId": "listPipelineDefinitions", + "summary": "List pipeline definitions", + "description": "List all pipeline definitions for a given project. [Share feedback](https://circleci.canny.io/cloud-feature-requests/p/project-administration-apis) about our Project Administration APIs.", + "tags": [ + "Pipeline Definition" + ], + "parameters": [ + { + "name": "project_id", + "description": "An opaque identifier of a project.", + "example": "39723015-b399-4601-9ff6-bd1bfbed8fa8", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "items": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the pipeline definition." + }, + "name": { + "type": "string", + "example": "some pipeline", + "description": "The name of the pipeline definition." + }, + "description": { + "type": "string", + "example": "some pipeline description", + "description": "The description of the pipeline definition." + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the pipeline definition was created." + }, + "config_source": { + "type": "object", + "additionalProperties": false, + "description": "The resource that stores the CircleCI config YAML used for this pipeline definition.", + "properties": { + "provider": { + "type": "string", + "example": "github_app", + "description": "The integration provider for this resource." + }, + "repo": { + "type": "object", + "additionalProperties": false, + "properties": { + "full_name": { + "type": "string", + "example": "some-org/some-repo-name", + "description": "The fully-qualified name of the repository." + }, + "external_id": { + "type": "string", + "example": "some-repo-id", + "description": "External identifier for the repository, as defined by the respective version control provider." + } + } + }, + "file_path": { + "type": "string", + "example": ".circleci/some-pipeline.yml", + "description": "Path to CircleCI config YAML file to use for this pipeline definition." + } + } + }, + "checkout_source": { + "type": "object", + "additionalProperties": false, + "description": "The resource to be used when running the `checkout` command.", + "properties": { + "provider": { + "type": "string", + "example": "github_app", + "description": "The integration provider for this resource." + }, + "repo": { + "type": "object", + "additionalProperties": false, + "properties": { + "full_name": { + "type": "string", + "example": "some-org/some-repo-name", + "description": "The fully-qualified name of the repository." + }, + "external_id": { + "type": "string", + "example": "some-repo-id", + "description": "External identifier for the repository, as defined by the respective version control provider." + } + } + } + } + } + } + } + } + } + } + } + } + }, + "400": { + "description": "Unexpected request body provided.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Unexpected request body provided." + } + } + } + } + } + }, + "401": { + "description": "Credentials provided are invalid.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "invalid_token": { + "summary": "Token is invalid.", + "value": { + "message": "Invalid token provided." + } + }, + "old_token": { + "summary": "Token was generated before 2023-06-23.", + "value": { + "message": "New format tokens are needed to authenticate this API endpoint. Create a new API token for access." + } + }, + "query_auth": { + "summary": "Authentication attempted via query parameters.", + "value": { + "message": "Support for query parameter authentication has been deprecated to improve security. Please use a supported authentication method such as header-based, or basic authentication." + } + } + } + } + } + }, + "404": { + "description": "Entity not found.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "context_not_found": { + "summary": "Context not found.", + "value": { + "message": "Context not found." + } + }, + "org_not_found": { + "summary": "Organization not found.", + "value": { + "message": "Organization does not exist." + } + }, + "user_not_found": { + "summary": "User not found.", + "value": { + "message": "User does not exist." + } + }, + "project_not_found": { + "summary": "Project not found.", + "value": { + "message": "Project does not exist." + } + }, + "group_not_found": { + "summary": "Group not found.", + "value": { + "message": "Group does not exist." + } + }, + "orb_not_found": { + "summary": "Orb not found.", + "value": { + "message": "Orb does not exist." + } + } + } + } + } + }, + "500": { + "description": "Internal server error.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Internal server error." + } + } + } + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/pipeline-definitions \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/pipeline-definitions';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/pipeline-definitions\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/pipeline-definitions\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/pipeline-definitions\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + }, + "post": { + "operationId": "createPipelineDefinition", + "summary": "Create pipeline definition", + "description": "Create a pipeline definition for a given project. Currently only supported for pipeline definitions where `config_source.provider` is `github_app`. [Share feedback](https://circleci.canny.io/cloud-feature-requests/p/project-administration-apis) about our Project Administration APIs.", + "tags": [ + "Pipeline Definition" + ], + "parameters": [ + { + "name": "project_id", + "description": "An opaque identifier of a project.", + "example": "39723015-b399-4601-9ff6-bd1bfbed8fa8", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string", + "example": "Some pipeline name", + "description": "The name of the pipeline definition." + }, + "description": { + "type": "string", + "example": "Some pipeline description", + "description": "The description of the pipeline definition." + }, + "config_source": { + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "description": "Config source for external providers (repo required)", + "properties": { + "provider": { + "type": "string", + "example": "github_app", + "description": "The integration provider for this resource. Currently `github_app` is the only supported external provider." + }, + "repo": { + "type": "object", + "additionalProperties": false, + "properties": { + "external_id": { + "type": "string", + "example": "some-repo-id", + "description": "External identifier for the repository, as defined by the respective version control provider." + } + }, + "required": [ + "external_id" + ] + }, + "file_path": { + "type": "string", + "example": ".circleci/some-pipeline.yml", + "description": "Path to CircleCI config YAML file to use for this pipeline definition." + } + }, + "required": [ + "provider", + "repo", + "file_path" + ] + }, + { + "type": "object", + "additionalProperties": false, + "description": "Config source for CircleCI provider (no repo required)", + "properties": { + "provider": { + "type": "string", + "description": "The integration provider for this resource." + }, + "file_path": { + "type": "string", + "example": ".circleci/some-pipeline.yml", + "description": "Path to CircleCI config YAML file to use for this pipeline definition." + } + }, + "required": [ + "provider", + "file_path" + ] + } + ] + }, + "checkout_source": { + "type": "object", + "additionalProperties": false, + "description": "The resource to be used when running the `checkout` command.", + "properties": { + "provider": { + "type": "string", + "example": "github_app", + "description": "The integration provider for this resource. Currently `github_app` is the only supported value." + }, + "repo": { + "type": "object", + "additionalProperties": false, + "properties": { + "external_id": { + "type": "string", + "example": "some-repo-id", + "description": "External identifier for the repository, as defined by the respective version control provider." + } + }, + "required": [ + "external_id" + ] + } + }, + "required": [ + "provider", + "repo" + ] + } + }, + "required": [ + "name", + "config_source", + "checkout_source" + ] + } + } + } + }, + "responses": { + "200": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the pipeline definition." + }, + "name": { + "type": "string", + "example": "some pipeline", + "description": "The name of the pipeline definition." + }, + "description": { + "type": "string", + "example": "some pipeline description", + "description": "The description of the pipeline definition." + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the pipeline definition was created." + }, + "config_source": { + "type": "object", + "additionalProperties": false, + "description": "The resource that stores the CircleCI config YAML used for this pipeline definition.", + "properties": { + "provider": { + "type": "string", + "example": "github_app", + "description": "The integration provider for this resource." + }, + "repo": { + "type": "object", + "additionalProperties": false, + "properties": { + "full_name": { + "type": "string", + "example": "some-org/some-repo-name", + "description": "The fully-qualified name of the repository." + }, + "external_id": { + "type": "string", + "example": "some-repo-id", + "description": "External identifier for the repository, as defined by the respective version control provider." + } + } + }, + "file_path": { + "type": "string", + "example": ".circleci/some-pipeline.yml", + "description": "Path to CircleCI config YAML file to use for this pipeline definition." + } + } + }, + "checkout_source": { + "type": "object", + "additionalProperties": false, + "description": "The resource to be used when running the `checkout` command.", + "properties": { + "provider": { + "type": "string", + "example": "github_app", + "description": "The integration provider for this resource." + }, + "repo": { + "type": "object", + "additionalProperties": false, + "properties": { + "full_name": { + "type": "string", + "example": "some-org/some-repo-name", + "description": "The fully-qualified name of the repository." + }, + "external_id": { + "type": "string", + "example": "some-repo-id", + "description": "External identifier for the repository, as defined by the respective version control provider." + } + } + } + } + } + } + } + } + } + }, + "400": { + "description": "Unexpected request body provided.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Unexpected request body provided." + } + } + } + } + } + }, + "401": { + "description": "Credentials provided are invalid.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "invalid_token": { + "summary": "Token is invalid.", + "value": { + "message": "Invalid token provided." + } + }, + "old_token": { + "summary": "Token was generated before 2023-06-23.", + "value": { + "message": "New format tokens are needed to authenticate this API endpoint. Create a new API token for access." + } + }, + "query_auth": { + "summary": "Authentication attempted via query parameters.", + "value": { + "message": "Support for query parameter authentication has been deprecated to improve security. Please use a supported authentication method such as header-based, or basic authentication." + } + } + } + } + } + }, + "404": { + "description": "Entity not found.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "context_not_found": { + "summary": "Context not found.", + "value": { + "message": "Context not found." + } + }, + "org_not_found": { + "summary": "Organization not found.", + "value": { + "message": "Organization does not exist." + } + }, + "user_not_found": { + "summary": "User not found.", + "value": { + "message": "User does not exist." + } + }, + "project_not_found": { + "summary": "Project not found.", + "value": { + "message": "Project does not exist." + } + }, + "group_not_found": { + "summary": "Group not found.", + "value": { + "message": "Group does not exist." + } + }, + "orb_not_found": { + "summary": "Orb not found.", + "value": { + "message": "Orb does not exist." + } + } + } + } + } + }, + "500": { + "description": "Internal server error.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Internal server error." + } + } + } + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request POST \\\n --url https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/pipeline-definitions \\\n --header \"Circle-Token: $CIRCLE_TOKEN\" \\\n --header \"Content-Type: application/json\" \\\n --data \"{\n \\\"name\\\": \\\"Some pipeline name\\\",\n \\\"description\\\": \\\"Some pipeline description\\\",\n \\\"config_source\\\": null,\n \\\"checkout_source\\\": {\n \\\"provider\\\": \\\"github_app\\\",\n \\\"repo\\\": {\n \\\"external_id\\\": \\\"some-repo-id\\\"\n }\n }\n}\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/pipeline-definitions';\n const options = {\n method: 'POST',\n headers: {'Circle-Token': '$CIRCLE_TOKEN', 'Content-Type': 'application/json'},\n body: '{\"name\":\"Some pipeline name\",\"description\":\"Some pipeline description\",\"config_source\":null,\"checkout_source\":{\"provider\":\"github_app\",\"repo\":{\"external_id\":\"some-repo-id\"}}}'\n };\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\npayload = \"{\\n \\\"name\\\": \\\"Some pipeline name\\\",\\n \\\"description\\\": \\\"Some pipeline description\\\",\\n \\\"config_source\\\": null,\\n \\\"checkout_source\\\": {\\n \\\"provider\\\": \\\"github_app\\\",\\n \\\"repo\\\": {\\n \\\"external_id\\\": \\\"some-repo-id\\\"\\n }\\n }\\n}\"\n\nheaders = {\n 'Circle-Token': \"$CIRCLE_TOKEN\",\n 'Content-Type': \"application/json\"\n}\n\nconn.request(\"POST\", \"/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/pipeline-definitions\", payload, headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/pipeline-definitions\"\n\n\tpayload := strings.NewReader(\"{\\n \\\"name\\\": \\\"Some pipeline name\\\",\\n \\\"description\\\": \\\"Some pipeline description\\\",\\n \\\"config_source\\\": null,\\n \\\"checkout_source\\\": {\\n \\\"provider\\\": \\\"github_app\\\",\\n \\\"repo\\\": {\\n \\\"external_id\\\": \\\"some-repo-id\\\"\\n }\\n }\\n}\")\n\n\treq, _ := http.NewRequest(\"POST\", url, payload)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/pipeline-definitions\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Post.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\nrequest[\"Content-Type\"] = 'application/json'\nrequest.body = \"{\\n \\\"name\\\": \\\"Some pipeline name\\\",\\n \\\"description\\\": \\\"Some pipeline description\\\",\\n \\\"config_source\\\": null,\\n \\\"checkout_source\\\": {\\n \\\"provider\\\": \\\"github_app\\\",\\n \\\"repo\\\": {\\n \\\"external_id\\\": \\\"some-repo-id\\\"\\n }\\n }\\n}\"\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/projects/{project_id}/pipeline-definitions/{pipeline_definition_id}": { + "get": { + "operationId": "getPipelineDefinition", + "summary": "Get pipeline definition", + "description": "Get details for a pipeline definition. Currently only supported for pipeline definitions where `config_source.provider` is `github_app`, `github_oauth`, `bitbucket_dc`, `bitbucket_oauth` or `gitlab`. [Share feedback](https://circleci.canny.io/cloud-feature-requests/p/project-administration-apis) about our Project Administration APIs.", + "tags": [ + "Pipeline Definition" + ], + "parameters": [ + { + "name": "project_id", + "description": "An opaque identifier of a project.", + "example": "39723015-b399-4601-9ff6-bd1bfbed8fa8", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "pipeline_definition_id", + "description": "An opaque identifier of a pipeline definition.", + "example": "6cb29b00-8e02-4357-8bc0-313983bf1f46", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the pipeline definition." + }, + "name": { + "type": "string", + "example": "some pipeline", + "description": "The name of the pipeline definition." + }, + "description": { + "type": "string", + "example": "some pipeline description", + "description": "The description of the pipeline definition." + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the pipeline definition was created." + }, + "config_source": { + "type": "object", + "additionalProperties": false, + "description": "The resource that stores the CircleCI config YAML used for this pipeline definition.", + "properties": { + "provider": { + "type": "string", + "example": "github_app", + "description": "The integration provider for this resource." + }, + "repo": { + "type": "object", + "additionalProperties": false, + "properties": { + "full_name": { + "type": "string", + "example": "some-org/some-repo-name", + "description": "The fully-qualified name of the repository." + }, + "external_id": { + "type": "string", + "example": "some-repo-id", + "description": "External identifier for the repository, as defined by the respective version control provider." + } + } + }, + "file_path": { + "type": "string", + "example": ".circleci/some-pipeline.yml", + "description": "Path to CircleCI config YAML file to use for this pipeline definition." + } + } + }, + "checkout_source": { + "type": "object", + "additionalProperties": false, + "description": "The resource to be used when running the `checkout` command.", + "properties": { + "provider": { + "type": "string", + "example": "github_app", + "description": "The integration provider for this resource." + }, + "repo": { + "type": "object", + "additionalProperties": false, + "properties": { + "full_name": { + "type": "string", + "example": "some-org/some-repo-name", + "description": "The fully-qualified name of the repository." + }, + "external_id": { + "type": "string", + "example": "some-repo-id", + "description": "External identifier for the repository, as defined by the respective version control provider." + } + } + } + } + } + } + } + } + } + }, + "400": { + "description": "Unexpected request body provided.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Unexpected request body provided." + } + } + } + } + } + }, + "401": { + "description": "Credentials provided are invalid.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "invalid_token": { + "summary": "Token is invalid.", + "value": { + "message": "Invalid token provided." + } + }, + "old_token": { + "summary": "Token was generated before 2023-06-23.", + "value": { + "message": "New format tokens are needed to authenticate this API endpoint. Create a new API token for access." + } + }, + "query_auth": { + "summary": "Authentication attempted via query parameters.", + "value": { + "message": "Support for query parameter authentication has been deprecated to improve security. Please use a supported authentication method such as header-based, or basic authentication." + } + } + } + } + } + }, + "404": { + "description": "Entity not found.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "context_not_found": { + "summary": "Context not found.", + "value": { + "message": "Context not found." + } + }, + "org_not_found": { + "summary": "Organization not found.", + "value": { + "message": "Organization does not exist." + } + }, + "user_not_found": { + "summary": "User not found.", + "value": { + "message": "User does not exist." + } + }, + "project_not_found": { + "summary": "Project not found.", + "value": { + "message": "Project does not exist." + } + }, + "group_not_found": { + "summary": "Group not found.", + "value": { + "message": "Group does not exist." + } + }, + "orb_not_found": { + "summary": "Orb not found.", + "value": { + "message": "Orb does not exist." + } + } + } + } + } + }, + "500": { + "description": "Internal server error.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Internal server error." + } + } + } + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/pipeline-definitions/6cb29b00-8e02-4357-8bc0-313983bf1f46 \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/pipeline-definitions/6cb29b00-8e02-4357-8bc0-313983bf1f46';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/pipeline-definitions/6cb29b00-8e02-4357-8bc0-313983bf1f46\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/pipeline-definitions/6cb29b00-8e02-4357-8bc0-313983bf1f46\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/pipeline-definitions/6cb29b00-8e02-4357-8bc0-313983bf1f46\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + }, + "patch": { + "operationId": "updatePipelineDefinition", + "summary": "Update pipeline definition", + "description": "Update pipeline definition. Currently only supported for pipeline definitions where `config_source.provider` is `github_app` or `bitbucket_dc`. [Share feedback](https://circleci.canny.io/cloud-feature-requests/p/project-administration-apis) about our Project Administration APIs.", + "tags": [ + "Pipeline Definition" + ], + "parameters": [ + { + "name": "project_id", + "description": "An opaque identifier of a project.", + "example": "39723015-b399-4601-9ff6-bd1bfbed8fa8", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "pipeline_definition_id", + "description": "An opaque identifier of a pipeline definition.", + "example": "6cb29b00-8e02-4357-8bc0-313983bf1f46", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string", + "example": "Some pipeline name", + "description": "The name of the pipeline definition." + }, + "description": { + "type": "string", + "example": "Some pipeline description", + "description": "The description of the pipeline definition." + }, + "config_source": { + "type": "object", + "additionalProperties": false, + "description": "The resource that stores the CircleCI config YAML used for this pipeline definition.", + "properties": { + "file_path": { + "type": "string", + "example": ".circleci/some-pipeline.yml", + "description": "Path to CircleCI config YAML file to use for this pipeline definition." + } + } + }, + "checkout_source": { + "type": "object", + "additionalProperties": false, + "description": "The resource to be used when running the `checkout` command.", + "properties": { + "provider": { + "type": "string", + "example": "github_app", + "description": "The integration provider for this resource. Currently `github_app` is the only supported value." + }, + "repo": { + "type": "object", + "additionalProperties": false, + "properties": { + "external_id": { + "type": "string", + "example": "some-repo-id", + "description": "External identifier for the repository, as defined by the respective version control provider." + } + } + } + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the pipeline definition." + }, + "name": { + "type": "string", + "example": "some pipeline", + "description": "The name of the pipeline definition." + }, + "description": { + "type": "string", + "example": "some pipeline description", + "description": "The description of the pipeline definition." + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the pipeline definition was created." + }, + "config_source": { + "type": "object", + "additionalProperties": false, + "description": "The resource that stores the CircleCI config YAML used for this pipeline definition.", + "properties": { + "provider": { + "type": "string", + "example": "github_app", + "description": "The integration provider for this resource." + }, + "repo": { + "type": "object", + "additionalProperties": false, + "properties": { + "full_name": { + "type": "string", + "example": "some-org/some-repo-name", + "description": "The fully-qualified name of the repository." + }, + "external_id": { + "type": "string", + "example": "some-repo-id", + "description": "External identifier for the repository, as defined by the respective version control provider." + } + } + }, + "file_path": { + "type": "string", + "example": ".circleci/some-pipeline.yml", + "description": "Path to CircleCI config YAML file to use for this pipeline definition." + } + } + }, + "checkout_source": { + "type": "object", + "additionalProperties": false, + "description": "The resource to be used when running the `checkout` command.", + "properties": { + "provider": { + "type": "string", + "example": "github_app", + "description": "The integration provider for this resource." + }, + "repo": { + "type": "object", + "additionalProperties": false, + "properties": { + "full_name": { + "type": "string", + "example": "some-org/some-repo-name", + "description": "The fully-qualified name of the repository." + }, + "external_id": { + "type": "string", + "example": "some-repo-id", + "description": "External identifier for the repository, as defined by the respective version control provider." + } + } + } + } + } + } + } + } + } + }, + "400": { + "description": "Unexpected request body provided.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Unexpected request body provided." + } + } + } + } + } + }, + "401": { + "description": "Credentials provided are invalid.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "invalid_token": { + "summary": "Token is invalid.", + "value": { + "message": "Invalid token provided." + } + }, + "old_token": { + "summary": "Token was generated before 2023-06-23.", + "value": { + "message": "New format tokens are needed to authenticate this API endpoint. Create a new API token for access." + } + }, + "query_auth": { + "summary": "Authentication attempted via query parameters.", + "value": { + "message": "Support for query parameter authentication has been deprecated to improve security. Please use a supported authentication method such as header-based, or basic authentication." + } + } + } + } + } + }, + "404": { + "description": "Entity not found.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "context_not_found": { + "summary": "Context not found.", + "value": { + "message": "Context not found." + } + }, + "org_not_found": { + "summary": "Organization not found.", + "value": { + "message": "Organization does not exist." + } + }, + "user_not_found": { + "summary": "User not found.", + "value": { + "message": "User does not exist." + } + }, + "project_not_found": { + "summary": "Project not found.", + "value": { + "message": "Project does not exist." + } + }, + "group_not_found": { + "summary": "Group not found.", + "value": { + "message": "Group does not exist." + } + }, + "orb_not_found": { + "summary": "Orb not found.", + "value": { + "message": "Orb does not exist." + } + } + } + } + } + }, + "500": { + "description": "Internal server error.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Internal server error." + } + } + } + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request PATCH \\\n --url https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/pipeline-definitions/6cb29b00-8e02-4357-8bc0-313983bf1f46 \\\n --header \"Circle-Token: $CIRCLE_TOKEN\" \\\n --header \"Content-Type: application/json\" \\\n --data \"{\n \\\"name\\\": \\\"Some pipeline name\\\",\n \\\"description\\\": \\\"Some pipeline description\\\",\n \\\"config_source\\\": {\n \\\"file_path\\\": \\\".circleci/some-pipeline.yml\\\"\n }\n}\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/pipeline-definitions/6cb29b00-8e02-4357-8bc0-313983bf1f46';\n const options = {\n method: 'PATCH',\n headers: {'Circle-Token': '$CIRCLE_TOKEN', 'Content-Type': 'application/json'},\n body: '{\"name\":\"Some pipeline name\",\"description\":\"Some pipeline description\",\"config_source\":{\"file_path\":\".circleci/some-pipeline.yml\"}}'\n };\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\npayload = \"{\\n \\\"name\\\": \\\"Some pipeline name\\\",\\n \\\"description\\\": \\\"Some pipeline description\\\",\\n \\\"config_source\\\": {\\n \\\"file_path\\\": \\\".circleci/some-pipeline.yml\\\"\\n }\\n}\"\n\nheaders = {\n 'Circle-Token': \"$CIRCLE_TOKEN\",\n 'Content-Type': \"application/json\"\n}\n\nconn.request(\"PATCH\", \"/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/pipeline-definitions/6cb29b00-8e02-4357-8bc0-313983bf1f46\", payload, headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/pipeline-definitions/6cb29b00-8e02-4357-8bc0-313983bf1f46\"\n\n\tpayload := strings.NewReader(\"{\\n \\\"name\\\": \\\"Some pipeline name\\\",\\n \\\"description\\\": \\\"Some pipeline description\\\",\\n \\\"config_source\\\": {\\n \\\"file_path\\\": \\\".circleci/some-pipeline.yml\\\"\\n }\\n}\")\n\n\treq, _ := http.NewRequest(\"PATCH\", url, payload)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/pipeline-definitions/6cb29b00-8e02-4357-8bc0-313983bf1f46\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Patch.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\nrequest[\"Content-Type\"] = 'application/json'\nrequest.body = \"{\\n \\\"name\\\": \\\"Some pipeline name\\\",\\n \\\"description\\\": \\\"Some pipeline description\\\",\\n \\\"config_source\\\": {\\n \\\"file_path\\\": \\\".circleci/some-pipeline.yml\\\"\\n }\\n}\"\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + }, + "delete": { + "operationId": "deletePipelineDefinition", + "summary": "Delete pipeline definition", + "description": "Delete pipeline definition. Currently only supported for pipeline definitions where `config_source.provider` is `github_app` or `bitbucket_dc`. [Share feedback](https://circleci.canny.io/cloud-feature-requests/p/project-administration-apis) about our Project Administration APIs.", + "tags": [ + "Pipeline Definition" + ], + "parameters": [ + { + "name": "project_id", + "description": "An opaque identifier of a project.", + "example": "39723015-b399-4601-9ff6-bd1bfbed8fa8", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "pipeline_definition_id", + "description": "An opaque identifier of a pipeline definition.", + "example": "6cb29b00-8e02-4357-8bc0-313983bf1f46", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "description": "Response message" + } + } + } + } + } + }, + "400": { + "description": "Unexpected request body provided.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Unexpected request body provided." + } + } + } + } + } + }, + "401": { + "description": "Credentials provided are invalid.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "invalid_token": { + "summary": "Token is invalid.", + "value": { + "message": "Invalid token provided." + } + }, + "old_token": { + "summary": "Token was generated before 2023-06-23.", + "value": { + "message": "New format tokens are needed to authenticate this API endpoint. Create a new API token for access." + } + }, + "query_auth": { + "summary": "Authentication attempted via query parameters.", + "value": { + "message": "Support for query parameter authentication has been deprecated to improve security. Please use a supported authentication method such as header-based, or basic authentication." + } + } + } + } + } + }, + "404": { + "description": "Entity not found.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "context_not_found": { + "summary": "Context not found.", + "value": { + "message": "Context not found." + } + }, + "org_not_found": { + "summary": "Organization not found.", + "value": { + "message": "Organization does not exist." + } + }, + "user_not_found": { + "summary": "User not found.", + "value": { + "message": "User does not exist." + } + }, + "project_not_found": { + "summary": "Project not found.", + "value": { + "message": "Project does not exist." + } + }, + "group_not_found": { + "summary": "Group not found.", + "value": { + "message": "Group does not exist." + } + }, + "orb_not_found": { + "summary": "Orb not found.", + "value": { + "message": "Orb does not exist." + } + } + } + } + } + }, + "500": { + "description": "Internal server error.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Internal server error." + } + } + } + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request DELETE \\\n --url https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/pipeline-definitions/6cb29b00-8e02-4357-8bc0-313983bf1f46 \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/pipeline-definitions/6cb29b00-8e02-4357-8bc0-313983bf1f46';\n const options = {method: 'DELETE', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"DELETE\", \"/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/pipeline-definitions/6cb29b00-8e02-4357-8bc0-313983bf1f46\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/pipeline-definitions/6cb29b00-8e02-4357-8bc0-313983bf1f46\"\n\n\treq, _ := http.NewRequest(\"DELETE\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/pipeline-definitions/6cb29b00-8e02-4357-8bc0-313983bf1f46\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Delete.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/projects/{project_id}/pipeline-definitions/{pipeline_definition_id}/triggers": { + "get": { + "operationId": "listPipelineDefinitionTriggers", + "summary": "List pipeline definition triggers", + "description": "List all triggers for a given pipeline definition. Currently only supported for pipeline definitions where `config_source.provider` is `github_app` or `bitbucket_dc`. [Share feedback](https://circleci.canny.io/cloud-feature-requests/p/project-administration-apis) about our Project Administration APIs.", + "tags": [ + "Trigger" + ], + "parameters": [ + { + "name": "project_id", + "description": "An opaque identifier of a project.", + "example": "39723015-b399-4601-9ff6-bd1bfbed8fa8", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "pipeline_definition_id", + "description": "An opaque identifier of a pipeline definition.", + "example": "6cb29b00-8e02-4357-8bc0-313983bf1f46", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "items": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the trigger." + }, + "event_name": { + "type": "string", + "example": "some event name", + "description": "The name of the event that will trigger the pipeline." + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the trigger was created." + }, + "event_source": { + "type": "object", + "additionalProperties": false, + "description": "The source of events to use for this trigger. Will contain either a `repo` or `webhook` object depending on the `provider`. (The `github_app` and `github_oauth` providers imply a `repo` and `webhook` implies a `webhook`.)", + "properties": { + "provider": { + "type": "string", + "example": "github_app", + "description": "The integration provider for this resource. Currently `github_app`, `github_oauth`, and `webhook` are the only supported values." + }, + "repo": { + "type": "object", + "additionalProperties": false, + "description": "Information pertaining to the repository used as a source of events for this trigger, if applicable.", + "properties": { + "full_name": { + "type": "string", + "example": "some-org/some-repo-name", + "description": "The fully-qualified name of the repository." + }, + "external_id": { + "type": "string", + "example": "some-repo-id", + "description": "External identifier for the repository, as defined by the respective version control provider." + } + } + }, + "webhook": { + "type": "object", + "additionalProperties": false, + "description": "Information pertaining to the custom webhook used as a source of events for this trigger, if applicable.", + "properties": { + "url": { + "type": "string", + "example": "https://some-webhook.invalid/some-endpoint?secret=some-secret", + "description": "The URL to use when triggering this webhook." + }, + "sender": { + "type": "string", + "example": "datadog", + "description": "The name of the webhook sender.." + } + } + } + } + }, + "event_preset": { + "type": "string", + "example": "all-pushes", + "description": "The name of the event preset to use when filtering events for this trigger. Only applicable when `event_source.provider` is `github_app`." + }, + "checkout_ref": { + "type": "string", + "example": "some-checkout-ref", + "description": "The ref to use when checking out code for pipeline runs created from this trigger. If empty, the ref provided in the trigger event is used." + }, + "config_ref": { + "type": "string", + "example": "some-config-ref", + "description": "The ref to use when fetching config for pipeline runs created from this trigger. If empty, the ref provided in the trigger event is used." + }, + "disabled": { + "type": "boolean", + "example": false, + "description": "Whether the trigger is disabled. Not supported for pipeline definitions where `config_source.provider` is `github_oauth`." + } + } + } + } + } + } + } + } + }, + "400": { + "description": "Unexpected request body provided.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Unexpected request body provided." + } + } + } + } + } + }, + "401": { + "description": "Credentials provided are invalid.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "invalid_token": { + "summary": "Token is invalid.", + "value": { + "message": "Invalid token provided." + } + }, + "old_token": { + "summary": "Token was generated before 2023-06-23.", + "value": { + "message": "New format tokens are needed to authenticate this API endpoint. Create a new API token for access." + } + }, + "query_auth": { + "summary": "Authentication attempted via query parameters.", + "value": { + "message": "Support for query parameter authentication has been deprecated to improve security. Please use a supported authentication method such as header-based, or basic authentication." + } + } + } + } + } + }, + "404": { + "description": "Entity not found.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "context_not_found": { + "summary": "Context not found.", + "value": { + "message": "Context not found." + } + }, + "org_not_found": { + "summary": "Organization not found.", + "value": { + "message": "Organization does not exist." + } + }, + "user_not_found": { + "summary": "User not found.", + "value": { + "message": "User does not exist." + } + }, + "project_not_found": { + "summary": "Project not found.", + "value": { + "message": "Project does not exist." + } + }, + "group_not_found": { + "summary": "Group not found.", + "value": { + "message": "Group does not exist." + } + }, + "orb_not_found": { + "summary": "Orb not found.", + "value": { + "message": "Orb does not exist." + } + } + } + } + } + }, + "500": { + "description": "Internal server error.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Internal server error." + } + } + } + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/pipeline-definitions/6cb29b00-8e02-4357-8bc0-313983bf1f46/triggers \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/pipeline-definitions/6cb29b00-8e02-4357-8bc0-313983bf1f46/triggers';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/pipeline-definitions/6cb29b00-8e02-4357-8bc0-313983bf1f46/triggers\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/pipeline-definitions/6cb29b00-8e02-4357-8bc0-313983bf1f46/triggers\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/pipeline-definitions/6cb29b00-8e02-4357-8bc0-313983bf1f46/triggers\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + }, + "post": { + "operationId": "createTrigger", + "summary": "Create trigger", + "description": "Create a trigger for a given pipeline definition. Currently only supported for pipeline definitions where `config_source.provider` is `github_app`. [Share feedback](https://circleci.canny.io/cloud-feature-requests/p/project-administration-apis) about our Project Administration APIs.", + "tags": [ + "Trigger" + ], + "parameters": [ + { + "name": "project_id", + "description": "An opaque identifier of a project.", + "example": "39723015-b399-4601-9ff6-bd1bfbed8fa8", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "pipeline_definition_id", + "description": "An opaque identifier of a pipeline definition.", + "example": "6cb29b00-8e02-4357-8bc0-313983bf1f46", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "event_source": { + "type": "object", + "additionalProperties": false, + "description": "The source of events to use for this trigger. The `repo` object must be specified when `provider` is `github_app`, and the `webhook` object may only be specified when `provider` is `webhook`.", + "properties": { + "provider": { + "type": "string", + "example": "github_app", + "description": "The integration provider for this resource. Currently `github_app`, `github_oauth`, and `webhook` are the only supported values." + }, + "repo": { + "type": "object", + "additionalProperties": false, + "description": "Information pertaining to the repository used as a source of events for this trigger, if applicable.", + "properties": { + "external_id": { + "type": "string", + "example": "some-repo-id", + "description": "External identifier for the repository, as defined by the respective version control provider." + } + }, + "required": [ + "external_id" + ] + }, + "webhook": { + "type": "object", + "additionalProperties": false, + "description": "Information pertaining to the custom webhook being used as a source of events for this trigger, if applicable.", + "properties": { + "sender": { + "type": "string", + "example": "some-webhook-sender", + "description": "The sender of the webhook." + } + } + } + }, + "required": [ + "provider" + ] + }, + "event_preset": { + "type": "string", + "example": "all-pushes", + "description": "The name of the event preset to use when filtering events for this trigger. Only applicable when `event_source.provider` is `github_app`." + }, + "checkout_ref": { + "type": "string", + "example": "some-checkout-ref", + "description": "The ref to use when checking out code for pipeline runs created from this trigger. Always required when `event_source.provider` is `webhook`. When `event_source.provider` is `github_app`, only expected if the event source repository (identified by `event_source.provider.repo.external_id`) is different to the checkout source repository of the associated Pipeline Definition. Otherwise, must be omitted." + }, + "config_ref": { + "type": "string", + "example": "some-config-ref", + "description": "The ref to use when fetching config for pipeline runs created from this trigger. Always required when `event_source.provider` is `webhook`. When `event_source.provider` is `github_app`, only expected if the event source repository (identified by `event_source.provider.repo.external_id`) is different to the config source repository of the associated Pipeline Definition. Otherwise, must be omitted." + }, + "event_name": { + "type": "string", + "example": "some-event-name", + "description": "The name of the triggering event. This should only be set for triggers where `provider` is `webhook`." + }, + "disabled": { + "type": "boolean", + "example": false, + "description": "Whether the trigger should be disabled upon creation. Not supported for pipeline definitions where `config_source.provider` is `github_oauth`." + } + }, + "required": [ + "event_source" + ] + } + } + } + }, + "responses": { + "200": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the trigger." + }, + "event_name": { + "type": "string", + "example": "some event name", + "description": "The name of the event that will trigger the pipeline." + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the trigger was created." + }, + "event_source": { + "type": "object", + "additionalProperties": false, + "description": "The source of events to use for this trigger. Will contain either a `repo` or `webhook` object depending on the `provider`. (The `github_app` and `github_oauth` providers imply a `repo` and `webhook` implies a `webhook`.)", + "properties": { + "provider": { + "type": "string", + "example": "github_app", + "description": "The integration provider for this resource. Currently `github_app`, `github_oauth`, and `webhook` are the only supported values." + }, + "repo": { + "type": "object", + "additionalProperties": false, + "description": "Information pertaining to the repository used as a source of events for this trigger, if applicable.", + "properties": { + "full_name": { + "type": "string", + "example": "some-org/some-repo-name", + "description": "The fully-qualified name of the repository." + }, + "external_id": { + "type": "string", + "example": "some-repo-id", + "description": "External identifier for the repository, as defined by the respective version control provider." + } + } + }, + "webhook": { + "type": "object", + "additionalProperties": false, + "description": "Information pertaining to the custom webhook used as a source of events for this trigger, if applicable.", + "properties": { + "url": { + "type": "string", + "example": "https://some-webhook.invalid/some-endpoint?secret=some-secret", + "description": "The URL to use when triggering this webhook." + }, + "sender": { + "type": "string", + "example": "datadog", + "description": "The name of the webhook sender.." + } + } + } + } + }, + "event_preset": { + "type": "string", + "example": "all-pushes", + "description": "The name of the event preset to use when filtering events for this trigger. Only applicable when `event_source.provider` is `github_app`." + }, + "checkout_ref": { + "type": "string", + "example": "some-checkout-ref", + "description": "The ref to use when checking out code for pipeline runs created from this trigger. If empty, the ref provided in the trigger event is used." + }, + "config_ref": { + "type": "string", + "example": "some-config-ref", + "description": "The ref to use when fetching config for pipeline runs created from this trigger. If empty, the ref provided in the trigger event is used." + }, + "disabled": { + "type": "boolean", + "example": false, + "description": "Whether the trigger is disabled. Not supported for pipeline definitions where `config_source.provider` is `github_oauth`." + } + } + } + } + } + }, + "400": { + "description": "Unexpected request body provided.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Unexpected request body provided." + } + } + } + } + } + }, + "401": { + "description": "Credentials provided are invalid.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "invalid_token": { + "summary": "Token is invalid.", + "value": { + "message": "Invalid token provided." + } + }, + "old_token": { + "summary": "Token was generated before 2023-06-23.", + "value": { + "message": "New format tokens are needed to authenticate this API endpoint. Create a new API token for access." + } + }, + "query_auth": { + "summary": "Authentication attempted via query parameters.", + "value": { + "message": "Support for query parameter authentication has been deprecated to improve security. Please use a supported authentication method such as header-based, or basic authentication." + } + } + } + } + } + }, + "404": { + "description": "Entity not found.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "context_not_found": { + "summary": "Context not found.", + "value": { + "message": "Context not found." + } + }, + "org_not_found": { + "summary": "Organization not found.", + "value": { + "message": "Organization does not exist." + } + }, + "user_not_found": { + "summary": "User not found.", + "value": { + "message": "User does not exist." + } + }, + "project_not_found": { + "summary": "Project not found.", + "value": { + "message": "Project does not exist." + } + }, + "group_not_found": { + "summary": "Group not found.", + "value": { + "message": "Group does not exist." + } + }, + "orb_not_found": { + "summary": "Orb not found.", + "value": { + "message": "Orb does not exist." + } + } + } + } + } + }, + "500": { + "description": "Internal server error.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Internal server error." + } + } + } + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request POST \\\n --url https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/pipeline-definitions/6cb29b00-8e02-4357-8bc0-313983bf1f46/triggers \\\n --header \"Circle-Token: $CIRCLE_TOKEN\" \\\n --header \"Content-Type: application/json\" \\\n --data \"{\n \\\"event_source\\\": {\n \\\"provider\\\": \\\"github_app\\\",\n \\\"repo\\\": {\n \\\"external_id\\\": \\\"some-repo-id\\\"\n },\n \\\"webhook\\\": {\n \\\"sender\\\": \\\"some-webhook-sender\\\"\n }\n },\n \\\"event_preset\\\": \\\"all-pushes\\\",\n \\\"checkout_ref\\\": \\\"some-checkout-ref\\\"\n}\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/pipeline-definitions/6cb29b00-8e02-4357-8bc0-313983bf1f46/triggers';\n const options = {\n method: 'POST',\n headers: {'Circle-Token': '$CIRCLE_TOKEN', 'Content-Type': 'application/json'},\n body: '{\"event_source\":{\"provider\":\"github_app\",\"repo\":{\"external_id\":\"some-repo-id\"},\"webhook\":{\"sender\":\"some-webhook-sender\"}},\"event_preset\":\"all-pushes\",\"checkout_ref\":\"some-checkout-ref\"}'\n };\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\npayload = \"{\\n \\\"event_source\\\": {\\n \\\"provider\\\": \\\"github_app\\\",\\n \\\"repo\\\": {\\n \\\"external_id\\\": \\\"some-repo-id\\\"\\n },\\n \\\"webhook\\\": {\\n \\\"sender\\\": \\\"some-webhook-sender\\\"\\n }\\n },\\n \\\"event_preset\\\": \\\"all-pushes\\\",\\n \\\"checkout_ref\\\": \\\"some-checkout-ref\\\"\\n}\"\n\nheaders = {\n 'Circle-Token': \"$CIRCLE_TOKEN\",\n 'Content-Type': \"application/json\"\n}\n\nconn.request(\"POST\", \"/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/pipeline-definitions/6cb29b00-8e02-4357-8bc0-313983bf1f46/triggers\", payload, headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/pipeline-definitions/6cb29b00-8e02-4357-8bc0-313983bf1f46/triggers\"\n\n\tpayload := strings.NewReader(\"{\\n \\\"event_source\\\": {\\n \\\"provider\\\": \\\"github_app\\\",\\n \\\"repo\\\": {\\n \\\"external_id\\\": \\\"some-repo-id\\\"\\n },\\n \\\"webhook\\\": {\\n \\\"sender\\\": \\\"some-webhook-sender\\\"\\n }\\n },\\n \\\"event_preset\\\": \\\"all-pushes\\\",\\n \\\"checkout_ref\\\": \\\"some-checkout-ref\\\"\\n}\")\n\n\treq, _ := http.NewRequest(\"POST\", url, payload)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/pipeline-definitions/6cb29b00-8e02-4357-8bc0-313983bf1f46/triggers\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Post.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\nrequest[\"Content-Type\"] = 'application/json'\nrequest.body = \"{\\n \\\"event_source\\\": {\\n \\\"provider\\\": \\\"github_app\\\",\\n \\\"repo\\\": {\\n \\\"external_id\\\": \\\"some-repo-id\\\"\\n },\\n \\\"webhook\\\": {\\n \\\"sender\\\": \\\"some-webhook-sender\\\"\\n }\\n },\\n \\\"event_preset\\\": \\\"all-pushes\\\",\\n \\\"checkout_ref\\\": \\\"some-checkout-ref\\\"\\n}\"\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/projects/{project_id}/triggers/{trigger_id}": { + "get": { + "operationId": "getTrigger", + "summary": "Get trigger", + "description": "Get details for a trigger. Currently only supported for triggers where `event_source.provider` is `github_app`, `bitbucket_dc` or `webhook`. [Share feedback](https://circleci.canny.io/cloud-feature-requests/p/project-administration-apis) about our Project Administration APIs. Breaking change [upcoming on May 27, 2025](https://discuss.circleci.com/t/upcoming-changes-1-breaking-to-crud-trigger-v2-apis-may-27-2025/53314).", + "tags": [ + "Trigger" + ], + "parameters": [ + { + "name": "project_id", + "description": "An opaque identifier of a project.", + "example": "39723015-b399-4601-9ff6-bd1bfbed8fa8", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "trigger_id", + "description": "An opaque identifier of a trigger.", + "example": "bbea3a3d-4686-48b6-8d2d-2a14ace3913c", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the trigger." + }, + "event_name": { + "type": "string", + "example": "some event name", + "description": "The name of the event that will trigger the pipeline." + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the trigger was created." + }, + "event_source": { + "type": "object", + "additionalProperties": false, + "description": "The source of events to use for this trigger. Will contain either a `repo` or `webhook` object depending on the `provider`. (The `github_app` and `github_oauth` providers imply a `repo` and `webhook` implies a `webhook`.)", + "properties": { + "provider": { + "type": "string", + "example": "github_app", + "description": "The integration provider for this resource. Currently `github_app`, `github_oauth`, and `webhook` are the only supported values." + }, + "repo": { + "type": "object", + "additionalProperties": false, + "description": "Information pertaining to the repository used as a source of events for this trigger, if applicable.", + "properties": { + "full_name": { + "type": "string", + "example": "some-org/some-repo-name", + "description": "The fully-qualified name of the repository." + }, + "external_id": { + "type": "string", + "example": "some-repo-id", + "description": "External identifier for the repository, as defined by the respective version control provider." + } + } + }, + "webhook": { + "type": "object", + "additionalProperties": false, + "description": "Information pertaining to the custom webhook used as a source of events for this trigger, if applicable.", + "properties": { + "url": { + "type": "string", + "example": "https://some-webhook.invalid/some-endpoint?secret=some-secret", + "description": "The URL to use when triggering this webhook." + }, + "sender": { + "type": "string", + "example": "datadog", + "description": "The name of the webhook sender.." + } + } + } + } + }, + "event_preset": { + "type": "string", + "example": "all-pushes", + "description": "The name of the event preset to use when filtering events for this trigger. Only applicable when `event_source.provider` is `github_app`." + }, + "checkout_ref": { + "type": "string", + "example": "some-checkout-ref", + "description": "The ref to use when checking out code for pipeline runs created from this trigger. If empty, the ref provided in the trigger event is used." + }, + "config_ref": { + "type": "string", + "example": "some-config-ref", + "description": "The ref to use when fetching config for pipeline runs created from this trigger. If empty, the ref provided in the trigger event is used." + }, + "disabled": { + "type": "boolean", + "example": false, + "description": "Whether the trigger is disabled. Not supported for pipeline definitions where `config_source.provider` is `github_oauth`." + } + } + } + } + } + }, + "400": { + "description": "Unexpected request body provided.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Unexpected request body provided." + } + } + } + } + } + }, + "401": { + "description": "Credentials provided are invalid.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "invalid_token": { + "summary": "Token is invalid.", + "value": { + "message": "Invalid token provided." + } + }, + "old_token": { + "summary": "Token was generated before 2023-06-23.", + "value": { + "message": "New format tokens are needed to authenticate this API endpoint. Create a new API token for access." + } + }, + "query_auth": { + "summary": "Authentication attempted via query parameters.", + "value": { + "message": "Support for query parameter authentication has been deprecated to improve security. Please use a supported authentication method such as header-based, or basic authentication." + } + } + } + } + } + }, + "404": { + "description": "Entity not found.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "context_not_found": { + "summary": "Context not found.", + "value": { + "message": "Context not found." + } + }, + "org_not_found": { + "summary": "Organization not found.", + "value": { + "message": "Organization does not exist." + } + }, + "user_not_found": { + "summary": "User not found.", + "value": { + "message": "User does not exist." + } + }, + "project_not_found": { + "summary": "Project not found.", + "value": { + "message": "Project does not exist." + } + }, + "group_not_found": { + "summary": "Group not found.", + "value": { + "message": "Group does not exist." + } + }, + "orb_not_found": { + "summary": "Orb not found.", + "value": { + "message": "Orb does not exist." + } + } + } + } + } + }, + "500": { + "description": "Internal server error.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Internal server error." + } + } + } + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/triggers/bbea3a3d-4686-48b6-8d2d-2a14ace3913c \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/triggers/bbea3a3d-4686-48b6-8d2d-2a14ace3913c';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/triggers/bbea3a3d-4686-48b6-8d2d-2a14ace3913c\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/triggers/bbea3a3d-4686-48b6-8d2d-2a14ace3913c\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/triggers/bbea3a3d-4686-48b6-8d2d-2a14ace3913c\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + }, + "patch": { + "operationId": "updateTrigger", + "summary": "Update trigger", + "description": "Update a trigger. Currently only supported for triggers where `event_source.provider` is `github_app`, `bitbucket_dc` or `webhook`. [Share feedback](https://circleci.canny.io/cloud-feature-requests/p/project-administration-apis) about our Project Administration APIs.", + "tags": [ + "Trigger" + ], + "parameters": [ + { + "name": "project_id", + "description": "An opaque identifier of a project.", + "example": "39723015-b399-4601-9ff6-bd1bfbed8fa8", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "trigger_id", + "description": "An opaque identifier of a trigger.", + "example": "bbea3a3d-4686-48b6-8d2d-2a14ace3913c", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "event_preset": { + "type": "string", + "example": "all-pushes", + "description": "The name of the event preset to use when filtering events for this trigger. Only applicable when `event_source.provider` is `github_app`." + }, + "checkout_ref": { + "type": "string", + "example": "some-checkout-ref", + "description": "The ref to use when checking out code for pipeline runs created from this trigger." + }, + "config_ref": { + "type": "string", + "example": "some-config-ref", + "description": "The ref to use when fetching config for pipeline runs created from this trigger." + }, + "event_name": { + "type": "string", + "example": "some event name", + "description": "The name of the triggering event. This can only be set for triggers where `provider` is `webhook`." + }, + "disabled": { + "type": "boolean", + "example": false, + "description": "A flag indicating whether the trigger is disabled or not. This can only be set for triggers where `provider` is `webhook`." + }, + "event_source": { + "type": "object", + "additionalProperties": false, + "properties": { + "webhook": { + "type": "object", + "additionalProperties": false, + "properties": { + "sender": { + "type": "string", + "example": "some sender", + "description": "The sender of the webhook. This can only be set for triggers where `provider` is `webhook`." + } + } + } + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the trigger." + }, + "event_name": { + "type": "string", + "example": "some event name", + "description": "The name of the event that will trigger the pipeline." + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the trigger was created." + }, + "event_source": { + "type": "object", + "additionalProperties": false, + "description": "The source of events to use for this trigger. Will contain either a `repo` or `webhook` object depending on the `provider`. (The `github_app` and `github_oauth` providers imply a `repo` and `webhook` implies a `webhook`.)", + "properties": { + "provider": { + "type": "string", + "example": "github_app", + "description": "The integration provider for this resource. Currently `github_app`, `github_oauth`, and `webhook` are the only supported values." + }, + "repo": { + "type": "object", + "additionalProperties": false, + "description": "Information pertaining to the repository used as a source of events for this trigger, if applicable.", + "properties": { + "full_name": { + "type": "string", + "example": "some-org/some-repo-name", + "description": "The fully-qualified name of the repository." + }, + "external_id": { + "type": "string", + "example": "some-repo-id", + "description": "External identifier for the repository, as defined by the respective version control provider." + } + } + }, + "webhook": { + "type": "object", + "additionalProperties": false, + "description": "Information pertaining to the custom webhook used as a source of events for this trigger, if applicable.", + "properties": { + "url": { + "type": "string", + "example": "https://some-webhook.invalid/some-endpoint?secret=some-secret", + "description": "The URL to use when triggering this webhook." + }, + "sender": { + "type": "string", + "example": "datadog", + "description": "The name of the webhook sender.." + } + } + } + } + }, + "event_preset": { + "type": "string", + "example": "all-pushes", + "description": "The name of the event preset to use when filtering events for this trigger. Only applicable when `event_source.provider` is `github_app`." + }, + "checkout_ref": { + "type": "string", + "example": "some-checkout-ref", + "description": "The ref to use when checking out code for pipeline runs created from this trigger. If empty, the ref provided in the trigger event is used." + }, + "config_ref": { + "type": "string", + "example": "some-config-ref", + "description": "The ref to use when fetching config for pipeline runs created from this trigger. If empty, the ref provided in the trigger event is used." + }, + "disabled": { + "type": "boolean", + "example": false, + "description": "Whether the trigger is disabled. Not supported for pipeline definitions where `config_source.provider` is `github_oauth`." + } + } + } + } + } + }, + "400": { + "description": "Unexpected request body provided.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Unexpected request body provided." + } + } + } + } + } + }, + "401": { + "description": "Credentials provided are invalid.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "invalid_token": { + "summary": "Token is invalid.", + "value": { + "message": "Invalid token provided." + } + }, + "old_token": { + "summary": "Token was generated before 2023-06-23.", + "value": { + "message": "New format tokens are needed to authenticate this API endpoint. Create a new API token for access." + } + }, + "query_auth": { + "summary": "Authentication attempted via query parameters.", + "value": { + "message": "Support for query parameter authentication has been deprecated to improve security. Please use a supported authentication method such as header-based, or basic authentication." + } + } + } + } + } + }, + "404": { + "description": "Entity not found.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "context_not_found": { + "summary": "Context not found.", + "value": { + "message": "Context not found." + } + }, + "org_not_found": { + "summary": "Organization not found.", + "value": { + "message": "Organization does not exist." + } + }, + "user_not_found": { + "summary": "User not found.", + "value": { + "message": "User does not exist." + } + }, + "project_not_found": { + "summary": "Project not found.", + "value": { + "message": "Project does not exist." + } + }, + "group_not_found": { + "summary": "Group not found.", + "value": { + "message": "Group does not exist." + } + }, + "orb_not_found": { + "summary": "Orb not found.", + "value": { + "message": "Orb does not exist." + } + } + } + } + } + }, + "500": { + "description": "Internal server error.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Internal server error." + } + } + } + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request PATCH \\\n --url https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/triggers/bbea3a3d-4686-48b6-8d2d-2a14ace3913c \\\n --header \"Circle-Token: $CIRCLE_TOKEN\" \\\n --header \"Content-Type: application/json\" \\\n --data \"{\n \\\"event_preset\\\": \\\"all-pushes\\\",\n \\\"checkout_ref\\\": \\\"some-checkout-ref\\\",\n \\\"config_ref\\\": \\\"some-config-ref\\\"\n}\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/triggers/bbea3a3d-4686-48b6-8d2d-2a14ace3913c';\n const options = {\n method: 'PATCH',\n headers: {'Circle-Token': '$CIRCLE_TOKEN', 'Content-Type': 'application/json'},\n body: '{\"event_preset\":\"all-pushes\",\"checkout_ref\":\"some-checkout-ref\",\"config_ref\":\"some-config-ref\"}'\n };\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\npayload = \"{\\n \\\"event_preset\\\": \\\"all-pushes\\\",\\n \\\"checkout_ref\\\": \\\"some-checkout-ref\\\",\\n \\\"config_ref\\\": \\\"some-config-ref\\\"\\n}\"\n\nheaders = {\n 'Circle-Token': \"$CIRCLE_TOKEN\",\n 'Content-Type': \"application/json\"\n}\n\nconn.request(\"PATCH\", \"/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/triggers/bbea3a3d-4686-48b6-8d2d-2a14ace3913c\", payload, headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/triggers/bbea3a3d-4686-48b6-8d2d-2a14ace3913c\"\n\n\tpayload := strings.NewReader(\"{\\n \\\"event_preset\\\": \\\"all-pushes\\\",\\n \\\"checkout_ref\\\": \\\"some-checkout-ref\\\",\\n \\\"config_ref\\\": \\\"some-config-ref\\\"\\n}\")\n\n\treq, _ := http.NewRequest(\"PATCH\", url, payload)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/triggers/bbea3a3d-4686-48b6-8d2d-2a14ace3913c\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Patch.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\nrequest[\"Content-Type\"] = 'application/json'\nrequest.body = \"{\\n \\\"event_preset\\\": \\\"all-pushes\\\",\\n \\\"checkout_ref\\\": \\\"some-checkout-ref\\\",\\n \\\"config_ref\\\": \\\"some-config-ref\\\"\\n}\"\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + }, + "delete": { + "operationId": "deleteTrigger", + "summary": "Delete trigger", + "description": "Delete a trigger. Currently only supported for triggers where `event_source.provider` is `github_app`, `bitbucket_dc` or `webhook`. [Share feedback](https://circleci.canny.io/cloud-feature-requests/p/project-administration-apis) about our Project Administration APIs.", + "tags": [ + "Trigger" + ], + "parameters": [ + { + "name": "project_id", + "description": "An opaque identifier of a project.", + "example": "39723015-b399-4601-9ff6-bd1bfbed8fa8", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "trigger_id", + "description": "An opaque identifier of a trigger.", + "example": "bbea3a3d-4686-48b6-8d2d-2a14ace3913c", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "description": "Response message" + } + } + } + } + } + }, + "400": { + "description": "Unexpected request body provided.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Unexpected request body provided." + } + } + } + } + } + }, + "401": { + "description": "Credentials provided are invalid.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "invalid_token": { + "summary": "Token is invalid.", + "value": { + "message": "Invalid token provided." + } + }, + "old_token": { + "summary": "Token was generated before 2023-06-23.", + "value": { + "message": "New format tokens are needed to authenticate this API endpoint. Create a new API token for access." + } + }, + "query_auth": { + "summary": "Authentication attempted via query parameters.", + "value": { + "message": "Support for query parameter authentication has been deprecated to improve security. Please use a supported authentication method such as header-based, or basic authentication." + } + } + } + } + } + }, + "404": { + "description": "Entity not found.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "context_not_found": { + "summary": "Context not found.", + "value": { + "message": "Context not found." + } + }, + "org_not_found": { + "summary": "Organization not found.", + "value": { + "message": "Organization does not exist." + } + }, + "user_not_found": { + "summary": "User not found.", + "value": { + "message": "User does not exist." + } + }, + "project_not_found": { + "summary": "Project not found.", + "value": { + "message": "Project does not exist." + } + }, + "group_not_found": { + "summary": "Group not found.", + "value": { + "message": "Group does not exist." + } + }, + "orb_not_found": { + "summary": "Orb not found.", + "value": { + "message": "Orb does not exist." + } + } + } + } + } + }, + "500": { + "description": "Internal server error.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Internal server error." + } + } + } + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request DELETE \\\n --url https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/triggers/bbea3a3d-4686-48b6-8d2d-2a14ace3913c \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/triggers/bbea3a3d-4686-48b6-8d2d-2a14ace3913c';\n const options = {method: 'DELETE', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"DELETE\", \"/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/triggers/bbea3a3d-4686-48b6-8d2d-2a14ace3913c\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/triggers/bbea3a3d-4686-48b6-8d2d-2a14ace3913c\"\n\n\treq, _ := http.NewRequest(\"DELETE\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/triggers/bbea3a3d-4686-48b6-8d2d-2a14ace3913c\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Delete.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/projects/{project_id}/rollback": { + "post": { + "operationId": "rollbackProject", + "summary": "Rollback a project", + "description": "Performs a rollback operation by triggering a rollback pipeline.", + "tags": [ + "Rollback" + ], + "parameters": [ + { + "name": "project_id", + "description": "An opaque identifier of a project.", + "example": "39723015-b399-4601-9ff6-bd1bfbed8fa8", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "component_name": { + "description": "The component name", + "example": "frontend", + "type": "string", + "x-go-name": "ComponentName" + }, + "current_version": { + "description": "The current version", + "example": "1.0.0", + "type": "string", + "x-go-name": "CurrentVersion" + }, + "environment_name": { + "description": "The environment name", + "example": "production", + "type": "string", + "x-go-name": "EnvironmentName" + }, + "namespace": { + "description": "The namespace", + "example": "default", + "type": "string", + "x-go-name": "Namespace" + }, + "parameters": { + "additionalProperties": {}, + "description": "The extra parameters for the rollback pipeline", + "example": { + "param1": "value1", + "param2": "value2" + }, + "type": "object", + "x-go-name": "Parameters" + }, + "reason": { + "description": "The reason for the rollback", + "example": "The component is down", + "type": "string", + "x-go-name": "Reason" + }, + "target_version": { + "description": "The target version", + "example": "1.0.1", + "type": "string", + "x-go-name": "TargetVersion" + } + }, + "required": [ + "environment_name", + "component_name", + "current_version", + "target_version" + ] + } + } + }, + "required": true + }, + "responses": { + "202": { + "description": "Rollback request accepted.", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "description": "The ID of the rollback pipeline or the command created to handle the rollback", + "example": "123e4567-e89b-12d3-a456-426614174000", + "format": "uuid", + "type": "string" + }, + "rollback_type": { + "description": "The type of the rollback", + "example": "PIPELINE", + "type": "string" + } + } + } + } + } + }, + "400": { + "description": "Unexpected request body provided.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Unexpected request body provided." + } + } + } + } + } + }, + "404": { + "description": "Entity not found.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "context_not_found": { + "summary": "Context not found.", + "value": { + "message": "Context not found." + } + }, + "org_not_found": { + "summary": "Organization not found.", + "value": { + "message": "Organization does not exist." + } + }, + "user_not_found": { + "summary": "User not found.", + "value": { + "message": "User does not exist." + } + }, + "project_not_found": { + "summary": "Project not found.", + "value": { + "message": "Project does not exist." + } + }, + "group_not_found": { + "summary": "Group not found.", + "value": { + "message": "Group does not exist." + } + }, + "orb_not_found": { + "summary": "Orb not found.", + "value": { + "message": "Orb does not exist." + } + } + } + } + } + }, + "409": { + "description": "A conflict has occurred while attempting to create the resource.\n", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Conflict creating entity." + } + } + } + } + } + }, + "500": { + "description": "Internal server error.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Internal server error." + } + } + } + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request POST \\\n --url https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/rollback \\\n --header \"Circle-Token: $CIRCLE_TOKEN\" \\\n --header \"Content-Type: application/json\" \\\n --data \"{\n \\\"component_name\\\": \\\"frontend\\\",\n \\\"current_version\\\": \\\"1.0.0\\\",\n \\\"environment_name\\\": \\\"production\\\",\n \\\"target_version\\\": \\\"1.0.1\\\"\n}\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/rollback';\n const options = {\n method: 'POST',\n headers: {'Circle-Token': '$CIRCLE_TOKEN', 'Content-Type': 'application/json'},\n body: '{\"component_name\":\"frontend\",\"current_version\":\"1.0.0\",\"environment_name\":\"production\",\"target_version\":\"1.0.1\"}'\n };\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\npayload = \"{\\n \\\"component_name\\\": \\\"frontend\\\",\\n \\\"current_version\\\": \\\"1.0.0\\\",\\n \\\"environment_name\\\": \\\"production\\\",\\n \\\"target_version\\\": \\\"1.0.1\\\"\\n}\"\n\nheaders = {\n 'Circle-Token': \"$CIRCLE_TOKEN\",\n 'Content-Type': \"application/json\"\n}\n\nconn.request(\"POST\", \"/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/rollback\", payload, headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/rollback\"\n\n\tpayload := strings.NewReader(\"{\\n \\\"component_name\\\": \\\"frontend\\\",\\n \\\"current_version\\\": \\\"1.0.0\\\",\\n \\\"environment_name\\\": \\\"production\\\",\\n \\\"target_version\\\": \\\"1.0.1\\\"\\n}\")\n\n\treq, _ := http.NewRequest(\"POST\", url, payload)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\treq.Header.Add(\"Content-Type\", \"application/json\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/projects/39723015-b399-4601-9ff6-bd1bfbed8fa8/rollback\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Post.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\nrequest[\"Content-Type\"] = 'application/json'\nrequest.body = \"{\\n \\\"component_name\\\": \\\"frontend\\\",\\n \\\"current_version\\\": \\\"1.0.0\\\",\\n \\\"environment_name\\\": \\\"production\\\",\\n \\\"target_version\\\": \\\"1.0.1\\\"\\n}\"\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/deploy/environments": { + "get": { + "operationId": "listEnvironments", + "summary": "List Environments", + "description": "Allows listing environments for a given organization ID.", + "tags": [ + "Deploy" + ], + "parameters": [ + { + "name": "org-id", + "description": "An opaque identifier of an organization used in query parameters.", + "example": "b9291e0d-a11e-41fb-8517-c545388b5953", + "in": "query", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "page-size", + "in": "query", + "required": true, + "description": "The number of results per page.", + "schema": { + "type": "integer" + } + }, + { + "name": "page-token", + "in": "query", + "description": "A token to specify which page of results to fetch.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Paginated environments list", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "items": { + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "created_at": { + "description": "The time when the environment was created", + "format": "date-time", + "type": "string", + "x-go-name": "CreatedAt" + }, + "description": { + "description": "Short description given to the environment", + "example": "some description", + "type": "string", + "x-go-name": "Description" + }, + "id": { + "description": "The environment ID", + "example": "123e4127-e89b-12d3-a456-426123417400", + "format": "uuid", + "type": "string", + "x-go-name": "ID" + }, + "labels": { + "description": "The labels associated to the environment", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "key": { + "description": "The key of the label", + "example": "env", + "type": "string", + "x-go-name": "Key" + }, + "value": { + "description": "The value of the label", + "example": "prod", + "type": "string", + "x-go-name": "Value" + } + } + }, + "type": "array", + "x-go-name": "Labels" + }, + "name": { + "description": "The environment name", + "example": "prod-app", + "type": "string", + "x-go-name": "Name" + }, + "updated_at": { + "description": "The time when the environment was updated", + "format": "date-time", + "type": "string", + "x-go-name": "UpdatedAt" + } + } + }, + "type": "array", + "x-go-name": "Items" + }, + "next_page_token": { + "description": "The pagination token to use when fetching the next page in this result set.", + "type": "string", + "nullable": true, + "x-go-name": "NextPageToken" + } + } + } + } + } + }, + "400": { + "description": "Unexpected request body provided.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Unexpected request body provided." + } + } + } + } + } + }, + "404": { + "description": "Entity not found.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "context_not_found": { + "summary": "Context not found.", + "value": { + "message": "Context not found." + } + }, + "org_not_found": { + "summary": "Organization not found.", + "value": { + "message": "Organization does not exist." + } + }, + "user_not_found": { + "summary": "User not found.", + "value": { + "message": "User does not exist." + } + }, + "project_not_found": { + "summary": "Project not found.", + "value": { + "message": "Project does not exist." + } + }, + "group_not_found": { + "summary": "Group not found.", + "value": { + "message": "Group does not exist." + } + }, + "orb_not_found": { + "summary": "Orb not found.", + "value": { + "message": "Orb does not exist." + } + } + } + } + } + }, + "500": { + "description": "Internal server error.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Internal server error." + } + } + } + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url \"https://circleci.com/api/v2/deploy/environments?org-id=b9291e0d-a11e-41fb-8517-c545388b5953&page-size=123&page-token=example-value\" \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/deploy/environments?org-id=b9291e0d-a11e-41fb-8517-c545388b5953&page-size=123&page-token=example-value';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/deploy/environments?org-id=b9291e0d-a11e-41fb-8517-c545388b5953&page-size=123&page-token=example-value\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/deploy/environments?org-id=b9291e0d-a11e-41fb-8517-c545388b5953&page-size=123&page-token=example-value\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/deploy/environments?org-id=b9291e0d-a11e-41fb-8517-c545388b5953&page-size=123&page-token=example-value\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/deploy/environments/{environment_id}": { + "get": { + "operationId": "getEnvironment", + "summary": "Get Environment", + "description": "Allows getting an environment for a given environment ID.", + "tags": [ + "Deploy" + ], + "parameters": [ + { + "name": "environment_id", + "description": "An opaque identifier of an environment.", + "example": "1c23d2cb-07b1-4a28-8af3-e369732050ed", + "in": "path", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Environment", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "created_at": { + "description": "The time when the environment was created", + "format": "date-time", + "type": "string", + "x-go-name": "CreatedAt" + }, + "description": { + "description": "Short description given to the environment", + "example": "some description", + "type": "string", + "x-go-name": "Description" + }, + "id": { + "description": "The environment ID", + "example": "123e4127-e89b-12d3-a456-426123417400", + "format": "uuid", + "type": "string", + "x-go-name": "ID" + }, + "labels": { + "description": "The labels associated to the environment", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "key": { + "description": "The key of the label", + "example": "env", + "type": "string", + "x-go-name": "Key" + }, + "value": { + "description": "The value of the label", + "example": "prod", + "type": "string", + "x-go-name": "Value" + } + } + }, + "type": "array", + "x-go-name": "Labels" + }, + "name": { + "description": "The environment name", + "example": "prod-app", + "type": "string", + "x-go-name": "Name" + }, + "updated_at": { + "description": "The time when the environment was updated", + "format": "date-time", + "type": "string", + "x-go-name": "UpdatedAt" + } + } + } + } + } + }, + "400": { + "description": "Unexpected request body provided.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Unexpected request body provided." + } + } + } + } + } + }, + "404": { + "description": "Entity not found.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "context_not_found": { + "summary": "Context not found.", + "value": { + "message": "Context not found." + } + }, + "org_not_found": { + "summary": "Organization not found.", + "value": { + "message": "Organization does not exist." + } + }, + "user_not_found": { + "summary": "User not found.", + "value": { + "message": "User does not exist." + } + }, + "project_not_found": { + "summary": "Project not found.", + "value": { + "message": "Project does not exist." + } + }, + "group_not_found": { + "summary": "Group not found.", + "value": { + "message": "Group does not exist." + } + }, + "orb_not_found": { + "summary": "Orb not found.", + "value": { + "message": "Orb does not exist." + } + } + } + } + } + }, + "500": { + "description": "Internal server error.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Internal server error." + } + } + } + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/deploy/environments/1c23d2cb-07b1-4a28-8af3-e369732050ed \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/deploy/environments/1c23d2cb-07b1-4a28-8af3-e369732050ed';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/deploy/environments/1c23d2cb-07b1-4a28-8af3-e369732050ed\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/deploy/environments/1c23d2cb-07b1-4a28-8af3-e369732050ed\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/deploy/environments/1c23d2cb-07b1-4a28-8af3-e369732050ed\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/deploy/components": { + "get": { + "operationId": "listComponents", + "summary": "List Components", + "description": "Allows for listing of components for a given organization ID.", + "tags": [ + "Deploy" + ], + "parameters": [ + { + "name": "org-id", + "description": "An opaque identifier of an organization used in query parameters.", + "example": "b9291e0d-a11e-41fb-8517-c545388b5953", + "in": "query", + "required": true, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "project-id", + "description": "An opaque identifier of an project used in query parameters.", + "example": "39723015-b399-4601-9ff6-bd1bfbed8fa8", + "in": "query", + "required": false, + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "page-size", + "in": "query", + "required": true, + "description": "The number of results per page.", + "schema": { + "type": "integer" + } + }, + { + "name": "page-token", + "in": "query", + "description": "A token to specify which page of results to fetch.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Paginated components list", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "items": { + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "description": "The component ID", + "example": "123e4127-e89b-12d3-a456-426123417400", + "format": "uuid", + "type": "string", + "x-go-name": "ID" + }, + "name": { + "description": "The component name", + "example": "service-a", + "type": "string", + "x-go-name": "Name" + }, + "project_id": { + "description": "The project ID of the component", + "example": "123e4127-e89b-12d3-a456-426123417400", + "format": "uuid", + "type": "string", + "x-go-name": "ID" + }, + "labels": { + "description": "The labels associated with the component", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "key": { + "description": "The key of the label", + "example": "env", + "type": "string", + "x-go-name": "Key" + }, + "value": { + "description": "The value of the label", + "example": "prod", + "type": "string", + "x-go-name": "Value" + } + } + }, + "type": "array", + "x-go-name": "Labels" + }, + "release_count": { + "description": "The number of releases for this component", + "example": 1, + "type": "integer", + "x-go-name": "ReleaseCount" + }, + "created_at": { + "description": "The time when the component was created", + "format": "date-time", + "type": "string", + "x-go-name": "CreatedAt" + }, + "updated_at": { + "description": "The time when the component was updated", + "format": "date-time", + "type": "string", + "x-go-name": "UpdatedAt" + } + } + }, + "type": "array", + "x-go-name": "Items" + }, + "next_page_token": { + "description": "The pagination token to use when fetching the next page in this result set.", + "type": "string", + "nullable": true, + "x-go-name": "NextPageToken" + } + } + } + } + } + }, + "400": { + "description": "Unexpected request body provided.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Unexpected request body provided." + } + } + } + } + } + }, + "404": { + "description": "Entity not found.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "context_not_found": { + "summary": "Context not found.", + "value": { + "message": "Context not found." + } + }, + "org_not_found": { + "summary": "Organization not found.", + "value": { + "message": "Organization does not exist." + } + }, + "user_not_found": { + "summary": "User not found.", + "value": { + "message": "User does not exist." + } + }, + "project_not_found": { + "summary": "Project not found.", + "value": { + "message": "Project does not exist." + } + }, + "group_not_found": { + "summary": "Group not found.", + "value": { + "message": "Group does not exist." + } + }, + "orb_not_found": { + "summary": "Orb not found.", + "value": { + "message": "Orb does not exist." + } + } + } + } + } + }, + "500": { + "description": "Internal server error.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Internal server error." + } + } + } + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url \"https://circleci.com/api/v2/deploy/components?org-id=b9291e0d-a11e-41fb-8517-c545388b5953&project-id=39723015-b399-4601-9ff6-bd1bfbed8fa8&page-size=123&page-token=example-value\" \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/deploy/components?org-id=b9291e0d-a11e-41fb-8517-c545388b5953&project-id=39723015-b399-4601-9ff6-bd1bfbed8fa8&page-size=123&page-token=example-value';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/deploy/components?org-id=b9291e0d-a11e-41fb-8517-c545388b5953&project-id=39723015-b399-4601-9ff6-bd1bfbed8fa8&page-size=123&page-token=example-value\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/deploy/components?org-id=b9291e0d-a11e-41fb-8517-c545388b5953&project-id=39723015-b399-4601-9ff6-bd1bfbed8fa8&page-size=123&page-token=example-value\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/deploy/components?org-id=b9291e0d-a11e-41fb-8517-c545388b5953&project-id=39723015-b399-4601-9ff6-bd1bfbed8fa8&page-size=123&page-token=example-value\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/deploy/components/{component_id}": { + "get": { + "operationId": "getComponent", + "summary": "Get Component", + "description": "Get the details of a component by ID.", + "tags": [ + "Deploy" + ], + "parameters": [ + { + "name": "component_id", + "description": "An opaque identifier of a component.", + "example": "b9291e0d-a11e-41fb-8517-c545388b5953", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successful response.", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "description": "The component ID", + "example": "123e4127-e89b-12d3-a456-426123417400", + "format": "uuid", + "type": "string", + "x-go-name": "ID" + }, + "name": { + "description": "The component name", + "example": "service-a", + "type": "string", + "x-go-name": "Name" + }, + "project_id": { + "description": "The project ID of the component", + "example": "123e4127-e89b-12d3-a456-426123417400", + "format": "uuid", + "type": "string", + "x-go-name": "ID" + }, + "labels": { + "description": "The labels associated with the component", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "key": { + "description": "The key of the label", + "example": "env", + "type": "string", + "x-go-name": "Key" + }, + "value": { + "description": "The value of the label", + "example": "prod", + "type": "string", + "x-go-name": "Value" + } + } + }, + "type": "array", + "x-go-name": "Labels" + }, + "release_count": { + "description": "The number of releases for this component", + "example": 1, + "type": "integer", + "x-go-name": "ReleaseCount" + }, + "created_at": { + "description": "The time when the component was created", + "format": "date-time", + "type": "string", + "x-go-name": "CreatedAt" + }, + "updated_at": { + "description": "The time when the component was updated", + "format": "date-time", + "type": "string", + "x-go-name": "UpdatedAt" + } + } + } + } + } + }, + "400": { + "description": "Unexpected request body provided.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Unexpected request body provided." + } + } + } + } + } + }, + "404": { + "description": "Entity not found.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "context_not_found": { + "summary": "Context not found.", + "value": { + "message": "Context not found." + } + }, + "org_not_found": { + "summary": "Organization not found.", + "value": { + "message": "Organization does not exist." + } + }, + "user_not_found": { + "summary": "User not found.", + "value": { + "message": "User does not exist." + } + }, + "project_not_found": { + "summary": "Project not found.", + "value": { + "message": "Project does not exist." + } + }, + "group_not_found": { + "summary": "Group not found.", + "value": { + "message": "Group does not exist." + } + }, + "orb_not_found": { + "summary": "Orb not found.", + "value": { + "message": "Orb does not exist." + } + } + } + } + } + }, + "500": { + "description": "Internal server error.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Internal server error." + } + } + } + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url https://circleci.com/api/v2/deploy/components/b9291e0d-a11e-41fb-8517-c545388b5953 \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/deploy/components/b9291e0d-a11e-41fb-8517-c545388b5953';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/deploy/components/b9291e0d-a11e-41fb-8517-c545388b5953\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/deploy/components/b9291e0d-a11e-41fb-8517-c545388b5953\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/deploy/components/b9291e0d-a11e-41fb-8517-c545388b5953\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + }, + "/deploy/components/{component_id}/versions": { + "get": { + "operationId": "listComponentVersions", + "summary": "List Component Versions", + "description": "List the versions for a component.", + "tags": [ + "Deploy" + ], + "parameters": [ + { + "name": "component_id", + "description": "An opaque identifier of a component.", + "example": "b9291e0d-a11e-41fb-8517-c545388b5953", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "environment-id", + "description": "An opaque identifier of an environment used in query parameters.", + "example": "39723015-b399-4601-9ff6-bd1bfbed8fa8", + "in": "query", + "required": false, + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Paginated component versions list", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": false, + "properties": { + "items": { + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "description": "The version name", + "example": "1.0.0", + "type": "string", + "x-go-name": "Name" + }, + "environment_id": { + "description": "The ID of the environment in which the version has been deployed", + "example": "123e4127-e89b-12d3-a456-426123417400", + "format": "uuid", + "type": "string", + "x-go-name": "ID" + }, + "namespace": { + "description": "The namespace in which the version was deployed", + "example": "default", + "type": "string", + "x-go-name": "Namespace" + }, + "is_live": { + "description": "Whether the version is live or not", + "example": true, + "type": "boolean", + "x-go-name": "IsLive" + }, + "pipeline_id": { + "description": "The ID of the pipeline that deployed the version", + "example": "cc54a110-d03f-4916-96fc-ff36a1221ed7", + "format": "uuid", + "type": "string", + "x-go-name": "ID" + }, + "workflow_id": { + "description": "The ID of the CircleCI workflow that deployed the version", + "example": "5034460f-c7c4-4c43-9457-de07e2029e7b", + "format": "uuid", + "type": "string", + "x-go-name": "WorkflowID" + }, + "job_id": { + "description": "The ID of the CircleCI job that deployed the version", + "example": "f7e18b53-db27-4706-ad77-b16dc1e6fc53", + "format": "uuid", + "type": "string", + "x-go-name": "JobID" + }, + "job_number": { + "description": "The number of the CircleCI job that deployed the version", + "example": 123, + "type": "integer", + "x-go-name": "JobNumber" + }, + "last_deployed_at": { + "description": "The time at which the version was last deployed", + "format": "date-time", + "type": "string", + "x-go-name": "LastDeployedAt" + } + } + }, + "type": "array", + "x-go-name": "Items" + }, + "next_page_token": { + "description": "The pagination token to use when fetching the next page in this result set.", + "type": "string", + "nullable": true, + "x-go-name": "NextPageToken" + } + } + } + } + } + }, + "400": { + "description": "Unexpected request body provided.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Unexpected request body provided." + } + } + } + } + } + }, + "404": { + "description": "Entity not found.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string" + } + } + }, + "examples": { + "context_not_found": { + "summary": "Context not found.", + "value": { + "message": "Context not found." + } + }, + "org_not_found": { + "summary": "Organization not found.", + "value": { + "message": "Organization does not exist." + } + }, + "user_not_found": { + "summary": "User not found.", + "value": { + "message": "User does not exist." + } + }, + "project_not_found": { + "summary": "Project not found.", + "value": { + "message": "Project does not exist." + } + }, + "group_not_found": { + "summary": "Group not found.", + "value": { + "message": "Group does not exist." + } + }, + "orb_not_found": { + "summary": "Orb not found.", + "value": { + "message": "Orb does not exist." + } + } + } + } + } + }, + "500": { + "description": "Internal server error.", + "content": { + "application/json": { + "schema": { + "additionalProperties": false, + "properties": { + "message": { + "type": "string", + "default": "Internal server error." + } + } + } + } + } + } + }, + "x-code-samples": [ + { + "lang": "cURL", + "source": "curl --request GET \\\n --url \"https://circleci.com/api/v2/deploy/components/b9291e0d-a11e-41fb-8517-c545388b5953/versions?environment-id=39723015-b399-4601-9ff6-bd1bfbed8fa8\" \\\n --header \"Circle-Token: $CIRCLE_TOKEN\"" + }, + { + "lang": "Node.js", + "source": "const fetch = require('node-fetch');\n\nasync function run() {\n const url = 'https://circleci.com/api/v2/deploy/components/b9291e0d-a11e-41fb-8517-c545388b5953/versions?environment-id=39723015-b399-4601-9ff6-bd1bfbed8fa8';\n const options = {method: 'GET', headers: {'Circle-Token': '$CIRCLE_TOKEN'}};\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(error);\n }\n}\n\nrun();" + }, + { + "lang": "Python", + "source": "import http.client\n\nconn = http.client.HTTPSConnection(\"circleci.com\")\n\nheaders = { 'Circle-Token': \"$CIRCLE_TOKEN\" }\n\nconn.request(\"GET\", \"/api/v2/deploy/components/b9291e0d-a11e-41fb-8517-c545388b5953/versions?environment-id=39723015-b399-4601-9ff6-bd1bfbed8fa8\", headers=headers)\n\nres = conn.getresponse()\ndata = res.read()\n\nprint(data.decode(\"utf-8\"))" + }, + { + "lang": "Go", + "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"io\"\n)\n\nfunc main() {\n\n\turl := \"https://circleci.com/api/v2/deploy/components/b9291e0d-a11e-41fb-8517-c545388b5953/versions?environment-id=39723015-b399-4601-9ff6-bd1bfbed8fa8\"\n\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\n\treq.Header.Add(\"Circle-Token\", \"$CIRCLE_TOKEN\")\n\n\tres, _ := http.DefaultClient.Do(req)\n\n\tdefer res.Body.Close()\n\tbody, _ := io.ReadAll(res.Body)\n\n\tfmt.Println(res)\n\tfmt.Println(string(body))\n\n}" + }, + { + "lang": "Ruby", + "source": "require 'uri'\nrequire 'net/http'\n\nurl = URI(\"https://circleci.com/api/v2/deploy/components/b9291e0d-a11e-41fb-8517-c545388b5953/versions?environment-id=39723015-b399-4601-9ff6-bd1bfbed8fa8\")\n\nhttp = Net::HTTP.new(url.host, url.port)\nhttp.use_ssl = true\n\nrequest = Net::HTTP::Get.new(url)\nrequest[\"Circle-Token\"] = '$CIRCLE_TOKEN'\n\nresponse = http.request(request)\nputs response.read_body" + } + ] + } + } + }, + "components": { + "securitySchemes": { + "api_key_header": { + "type": "apiKey", + "name": "Circle-Token", + "in": "header", + "description": "Project API tokens are not supported for API v2. Use a personal API token." + }, + "basic_auth": { + "description": "HTTP basic authentication. The username should be set as the circle-token value, and the password should be left blank. Note that project tokens are currently not supported on API v2.", + "type": "http", + "scheme": "basic" + }, + "api_key_query": { + "type": "apiKey", + "name": "circle-token", + "in": "query", + "description": "DEPRECATED - we will remove this option in the future. Project API tokens are not supported for API v2. Use a personal API token." + } + }, + "schemas": { + "ClaimResponse": { + "properties": { + "audience": { + "items": { + "type": "string" + }, + "type": "array" + }, + "audience_updated_at": { + "format": "date-time", + "type": "string" + }, + "org_id": { + "format": "uuid", + "type": "string" + }, + "project_id": { + "format": "uuid", + "type": "string" + }, + "ttl": { + "pattern": "^([0-9]+(ms|s|m|h|d|w)){1,7}$", + "type": "string" + }, + "ttl_updated_at": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "org_id" + ], + "type": "object" + }, + "PatchClaimsRequest": { + "properties": { + "audience": { + "items": { + "type": "string" + }, + "type": "array" + }, + "ttl": { + "pattern": "^([0-9]+(ms|s|m|h|d|w)){1,7}$", + "type": "string" + } + }, + "type": "object" + }, + "Decision": { + "properties": { + "enabled_rules": { + "items": { + "type": "string" + }, + "type": "array" + }, + "hard_failures": { + "items": { + "properties": { + "reason": { + "type": "string" + }, + "rule": { + "type": "string" + } + }, + "required": [ + "rule", + "reason" + ], + "type": "object" + }, + "type": "array" + }, + "reason": { + "type": "string" + }, + "soft_failures": { + "items": { + "properties": { + "reason": { + "type": "string" + }, + "rule": { + "type": "string" + } + }, + "required": [ + "rule", + "reason" + ], + "type": "object" + }, + "type": "array" + }, + "status": { + "type": "string" + } + }, + "required": [ + "status" + ], + "type": "object" + }, + "DecisionLog": { + "properties": { + "created_at": { + "format": "date-time", + "type": "string" + }, + "decision": { + "properties": { + "enabled_rules": { + "items": { + "type": "string" + }, + "type": "array" + }, + "hard_failures": { + "items": { + "properties": { + "reason": { + "type": "string" + }, + "rule": { + "type": "string" + } + }, + "required": [ + "rule", + "reason" + ], + "type": "object" + }, + "type": "array" + }, + "reason": { + "type": "string" + }, + "soft_failures": { + "items": { + "properties": { + "reason": { + "type": "string" + }, + "rule": { + "type": "string" + } + }, + "required": [ + "rule", + "reason" + ], + "type": "object" + }, + "type": "array" + }, + "status": { + "type": "string" + } + }, + "required": [ + "status" + ], + "type": "object" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "metadata": { + "properties": { + "build_number": { + "type": "integer" + }, + "project_id": { + "format": "uuid", + "type": "string" + }, + "ssh_rerun": { + "type": "boolean" + }, + "vcs": { + "properties": { + "branch": { + "type": "string" + }, + "origin_repository_url": { + "type": "string" + }, + "release_tag": { + "type": "string" + }, + "target_repository_url": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "policies": { + "additionalProperties": { + "maxLength": 128, + "minLength": 128, + "type": "string" + }, + "description": "policy-name-to-hash-map", + "example": { + "policy_name1": "1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75", + "policy_name2": "5267768822ee624d48fce15ec5ca79cbd602cb7f4c2157a516556991f22ef8c7b5ef7b18d1ff41c59370efb0858651d44a936c11b7b144c48fe04df3c6a3e8da" + }, + "type": "object" + }, + "time_taken_ms": { + "type": "integer" + } + }, + "type": "object" + }, + "PolicyBundle": { + "additionalProperties": { + "items": { + "properties": { + "content": { + "type": "string" + }, + "created_at": { + "format": "date-time", + "type": "string" + }, + "created_by": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "groups": { + "type": "object", + "additionalProperties": false, + "properties": { + "items": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier for group" + }, + "name": { + "type": "string", + "description": "Name of group" + }, + "description": { + "type": "string", + "description": "Description field on group" + } + } + } + }, + "next_page_token": { + "type": "string", + "nullable": true + }, + "total_count": { + "type": "integer" + } + } + }, + "pipelineDefinition": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the pipeline definition." + }, + "name": { + "type": "string", + "example": "some pipeline", + "description": "The name of the pipeline definition." + }, + "description": { + "type": "string", + "example": "some pipeline description", + "description": "The description of the pipeline definition." + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the pipeline definition was created." + }, + "config_source": { + "type": "object", + "additionalProperties": false, + "description": "The resource that stores the CircleCI config YAML used for this pipeline definition.", + "properties": { + "provider": { + "type": "string", + "example": "github_app", + "description": "The integration provider for this resource." + }, + "repo": { + "type": "object", + "additionalProperties": false, + "properties": { + "full_name": { + "type": "string", + "example": "some-org/some-repo-name", + "description": "The fully-qualified name of the repository." + }, + "external_id": { + "type": "string", + "example": "some-repo-id", + "description": "External identifier for the repository, as defined by the respective version control provider." + } + } + }, + "file_path": { + "type": "string", + "example": ".circleci/some-pipeline.yml", + "description": "Path to CircleCI config YAML file to use for this pipeline definition." + } + } + }, + "checkout_source": { + "type": "object", + "additionalProperties": false, + "description": "The resource to be used when running the `checkout` command.", + "properties": { + "provider": { + "type": "string", + "example": "github_app", + "description": "The integration provider for this resource." + }, + "repo": { + "type": "object", + "additionalProperties": false, + "properties": { + "full_name": { + "type": "string", + "example": "some-org/some-repo-name", + "description": "The fully-qualified name of the repository." + }, + "external_id": { + "type": "string", + "example": "some-repo-id", + "description": "External identifier for the repository, as defined by the respective version control provider." + } + } + } + } + } + } + }, + "pipelineDefinitionList": { + "type": "object", + "additionalProperties": false, + "properties": { + "items": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the pipeline definition." + }, + "name": { + "type": "string", + "example": "some pipeline", + "description": "The name of the pipeline definition." + }, + "description": { + "type": "string", + "example": "some pipeline description", + "description": "The description of the pipeline definition." + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the pipeline definition was created." + }, + "config_source": { + "type": "object", + "additionalProperties": false, + "description": "The resource that stores the CircleCI config YAML used for this pipeline definition.", + "properties": { + "provider": { + "type": "string", + "example": "github_app", + "description": "The integration provider for this resource." + }, + "repo": { + "type": "object", + "additionalProperties": false, + "properties": { + "full_name": { + "type": "string", + "example": "some-org/some-repo-name", + "description": "The fully-qualified name of the repository." + }, + "external_id": { + "type": "string", + "example": "some-repo-id", + "description": "External identifier for the repository, as defined by the respective version control provider." + } + } + }, + "file_path": { + "type": "string", + "example": ".circleci/some-pipeline.yml", + "description": "Path to CircleCI config YAML file to use for this pipeline definition." + } + } + }, + "checkout_source": { + "type": "object", + "additionalProperties": false, + "description": "The resource to be used when running the `checkout` command.", + "properties": { + "provider": { + "type": "string", + "example": "github_app", + "description": "The integration provider for this resource." + }, + "repo": { + "type": "object", + "additionalProperties": false, + "properties": { + "full_name": { + "type": "string", + "example": "some-org/some-repo-name", + "description": "The fully-qualified name of the repository." + }, + "external_id": { + "type": "string", + "example": "some-repo-id", + "description": "External identifier for the repository, as defined by the respective version control provider." + } + } + } + } + } + } + } + } + } + }, + "trigger": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the trigger." + }, + "event_name": { + "type": "string", + "example": "some event name", + "description": "The name of the event that will trigger the pipeline." + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the trigger was created." + }, + "event_source": { + "type": "object", + "additionalProperties": false, + "description": "The source of events to use for this trigger. Will contain either a `repo` or `webhook` object depending on the `provider`. (The `github_app` and `github_oauth` providers imply a `repo` and `webhook` implies a `webhook`.)", + "properties": { + "provider": { + "type": "string", + "example": "github_app", + "description": "The integration provider for this resource. Currently `github_app`, `github_oauth`, and `webhook` are the only supported values." + }, + "repo": { + "type": "object", + "additionalProperties": false, + "description": "Information pertaining to the repository used as a source of events for this trigger, if applicable.", + "properties": { + "full_name": { + "type": "string", + "example": "some-org/some-repo-name", + "description": "The fully-qualified name of the repository." + }, + "external_id": { + "type": "string", + "example": "some-repo-id", + "description": "External identifier for the repository, as defined by the respective version control provider." + } + } + }, + "webhook": { + "type": "object", + "additionalProperties": false, + "description": "Information pertaining to the custom webhook used as a source of events for this trigger, if applicable.", + "properties": { + "url": { + "type": "string", + "example": "https://some-webhook.invalid/some-endpoint?secret=some-secret", + "description": "The URL to use when triggering this webhook." + }, + "sender": { + "type": "string", + "example": "datadog", + "description": "The name of the webhook sender.." + } + } + } + } + }, + "event_preset": { + "type": "string", + "example": "all-pushes", + "description": "The name of the event preset to use when filtering events for this trigger. Only applicable when `event_source.provider` is `github_app`." + }, + "checkout_ref": { + "type": "string", + "example": "some-checkout-ref", + "description": "The ref to use when checking out code for pipeline runs created from this trigger. If empty, the ref provided in the trigger event is used." + }, + "config_ref": { + "type": "string", + "example": "some-config-ref", + "description": "The ref to use when fetching config for pipeline runs created from this trigger. If empty, the ref provided in the trigger event is used." + }, + "disabled": { + "type": "boolean", + "example": false, + "description": "Whether the trigger is disabled. Not supported for pipeline definitions where `config_source.provider` is `github_oauth`." + } + } + }, + "triggerList": { + "type": "object", + "additionalProperties": false, + "properties": { + "items": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The unique ID of the trigger." + }, + "event_name": { + "type": "string", + "example": "some event name", + "description": "The name of the event that will trigger the pipeline." + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "The date and time the trigger was created." + }, + "event_source": { + "type": "object", + "additionalProperties": false, + "description": "The source of events to use for this trigger. Will contain either a `repo` or `webhook` object depending on the `provider`. (The `github_app` and `github_oauth` providers imply a `repo` and `webhook` implies a `webhook`.)", + "properties": { + "provider": { + "type": "string", + "example": "github_app", + "description": "The integration provider for this resource. Currently `github_app`, `github_oauth`, and `webhook` are the only supported values." + }, + "repo": { + "type": "object", + "additionalProperties": false, + "description": "Information pertaining to the repository used as a source of events for this trigger, if applicable.", + "properties": { + "full_name": { + "type": "string", + "example": "some-org/some-repo-name", + "description": "The fully-qualified name of the repository." + }, + "external_id": { + "type": "string", + "example": "some-repo-id", + "description": "External identifier for the repository, as defined by the respective version control provider." + } + } + }, + "webhook": { + "type": "object", + "additionalProperties": false, + "description": "Information pertaining to the custom webhook used as a source of events for this trigger, if applicable.", + "properties": { + "url": { + "type": "string", + "example": "https://some-webhook.invalid/some-endpoint?secret=some-secret", + "description": "The URL to use when triggering this webhook." + }, + "sender": { + "type": "string", + "example": "datadog", + "description": "The name of the webhook sender.." + } + } + } + } + }, + "event_preset": { + "type": "string", + "example": "all-pushes", + "description": "The name of the event preset to use when filtering events for this trigger. Only applicable when `event_source.provider` is `github_app`." + }, + "checkout_ref": { + "type": "string", + "example": "some-checkout-ref", + "description": "The ref to use when checking out code for pipeline runs created from this trigger. If empty, the ref provided in the trigger event is used." + }, + "config_ref": { + "type": "string", + "example": "some-config-ref", + "description": "The ref to use when fetching config for pipeline runs created from this trigger. If empty, the ref provided in the trigger event is used." + }, + "disabled": { + "type": "boolean", + "example": false, + "description": "Whether the trigger is disabled. Not supported for pipeline definitions where `config_source.provider` is `github_oauth`." + } + } + } + } + } + }, + "createTriggerRequest": { + "type": "object", + "additionalProperties": false, + "properties": { + "event_source": { + "type": "object", + "additionalProperties": false, + "description": "The source of events to use for this trigger. The `repo` object must be specified when `provider` is `github_app`, and the `webhook` object may only be specified when `provider` is `webhook`.", + "properties": { + "provider": { + "type": "string", + "example": "github_app", + "description": "The integration provider for this resource. Currently `github_app`, `github_oauth`, and `webhook` are the only supported values." + }, + "repo": { + "type": "object", + "additionalProperties": false, + "description": "Information pertaining to the repository used as a source of events for this trigger, if applicable.", + "properties": { + "external_id": { + "type": "string", + "example": "some-repo-id", + "description": "External identifier for the repository, as defined by the respective version control provider." + } + }, + "required": [ + "external_id" + ] + }, + "webhook": { + "type": "object", + "additionalProperties": false, + "description": "Information pertaining to the custom webhook being used as a source of events for this trigger, if applicable.", + "properties": { + "sender": { + "type": "string", + "example": "some-webhook-sender", + "description": "The sender of the webhook." + } + } + } + }, + "required": [ + "provider" + ] + }, + "event_preset": { + "type": "string", + "example": "all-pushes", + "description": "The name of the event preset to use when filtering events for this trigger. Only applicable when `event_source.provider` is `github_app`." + }, + "checkout_ref": { + "type": "string", + "example": "some-checkout-ref", + "description": "The ref to use when checking out code for pipeline runs created from this trigger. Always required when `event_source.provider` is `webhook`. When `event_source.provider` is `github_app`, only expected if the event source repository (identified by `event_source.provider.repo.external_id`) is different to the checkout source repository of the associated Pipeline Definition. Otherwise, must be omitted." + }, + "config_ref": { + "type": "string", + "example": "some-config-ref", + "description": "The ref to use when fetching config for pipeline runs created from this trigger. Always required when `event_source.provider` is `webhook`. When `event_source.provider` is `github_app`, only expected if the event source repository (identified by `event_source.provider.repo.external_id`) is different to the config source repository of the associated Pipeline Definition. Otherwise, must be omitted." + }, + "event_name": { + "type": "string", + "example": "some-event-name", + "description": "The name of the triggering event. This should only be set for triggers where `provider` is `webhook`." + }, + "disabled": { + "type": "boolean", + "example": false, + "description": "Whether the trigger should be disabled upon creation. Not supported for pipeline definitions where `config_source.provider` is `github_oauth`." + } + }, + "required": [ + "event_source" + ] + }, + "updateTriggerRequest": { + "type": "object", + "additionalProperties": false, + "properties": { + "event_preset": { + "type": "string", + "example": "all-pushes", + "description": "The name of the event preset to use when filtering events for this trigger. Only applicable when `event_source.provider` is `github_app`." + }, + "checkout_ref": { + "type": "string", + "example": "some-checkout-ref", + "description": "The ref to use when checking out code for pipeline runs created from this trigger." + }, + "config_ref": { + "type": "string", + "example": "some-config-ref", + "description": "The ref to use when fetching config for pipeline runs created from this trigger." + }, + "event_name": { + "type": "string", + "example": "some event name", + "description": "The name of the triggering event. This can only be set for triggers where `provider` is `webhook`." + }, + "disabled": { + "type": "boolean", + "example": false, + "description": "A flag indicating whether the trigger is disabled or not. This can only be set for triggers where `provider` is `webhook`." + }, + "event_source": { + "type": "object", + "additionalProperties": false, + "properties": { + "webhook": { + "type": "object", + "additionalProperties": false, + "properties": { + "sender": { + "type": "string", + "example": "some sender", + "description": "The sender of the webhook. This can only be set for triggers where `provider` is `webhook`." + } + } + } + } + } + } + }, + "component": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "description": "The component ID", + "example": "123e4127-e89b-12d3-a456-426123417400", + "format": "uuid", + "type": "string", + "x-go-name": "ID" + }, + "name": { + "description": "The component name", + "example": "service-a", + "type": "string", + "x-go-name": "Name" + }, + "project_id": { + "description": "The project ID of the component", + "example": "123e4127-e89b-12d3-a456-426123417400", + "format": "uuid", + "type": "string", + "x-go-name": "ID" + }, + "labels": { + "description": "The labels associated with the component", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "key": { + "description": "The key of the label", + "example": "env", + "type": "string", + "x-go-name": "Key" + }, + "value": { + "description": "The value of the label", + "example": "prod", + "type": "string", + "x-go-name": "Value" + } + } + }, + "type": "array", + "x-go-name": "Labels" + }, + "release_count": { + "description": "The number of releases for this component", + "example": 1, + "type": "integer", + "x-go-name": "ReleaseCount" + }, + "created_at": { + "description": "The time when the component was created", + "format": "date-time", + "type": "string", + "x-go-name": "CreatedAt" + }, + "updated_at": { + "description": "The time when the component was updated", + "format": "date-time", + "type": "string", + "x-go-name": "UpdatedAt" + } + } + }, + "paginatedComponentList": { + "type": "object", + "additionalProperties": false, + "properties": { + "items": { + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "description": "The component ID", + "example": "123e4127-e89b-12d3-a456-426123417400", + "format": "uuid", + "type": "string", + "x-go-name": "ID" + }, + "name": { + "description": "The component name", + "example": "service-a", + "type": "string", + "x-go-name": "Name" + }, + "project_id": { + "description": "The project ID of the component", + "example": "123e4127-e89b-12d3-a456-426123417400", + "format": "uuid", + "type": "string", + "x-go-name": "ID" + }, + "labels": { + "description": "The labels associated with the component", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "key": { + "description": "The key of the label", + "example": "env", + "type": "string", + "x-go-name": "Key" + }, + "value": { + "description": "The value of the label", + "example": "prod", + "type": "string", + "x-go-name": "Value" + } + } + }, + "type": "array", + "x-go-name": "Labels" + }, + "release_count": { + "description": "The number of releases for this component", + "example": 1, + "type": "integer", + "x-go-name": "ReleaseCount" + }, + "created_at": { + "description": "The time when the component was created", + "format": "date-time", + "type": "string", + "x-go-name": "CreatedAt" + }, + "updated_at": { + "description": "The time when the component was updated", + "format": "date-time", + "type": "string", + "x-go-name": "UpdatedAt" + } + } + }, + "type": "array", + "x-go-name": "Items" + }, + "next_page_token": { + "description": "The pagination token to use when fetching the next page in this result set.", + "type": "string", + "nullable": true, + "x-go-name": "NextPageToken" + } + } + }, + "paginatedComponentVersionList": { + "type": "object", + "additionalProperties": false, + "properties": { + "items": { + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "description": "The version name", + "example": "1.0.0", + "type": "string", + "x-go-name": "Name" + }, + "environment_id": { + "description": "The ID of the environment in which the version has been deployed", + "example": "123e4127-e89b-12d3-a456-426123417400", + "format": "uuid", + "type": "string", + "x-go-name": "ID" + }, + "namespace": { + "description": "The namespace in which the version was deployed", + "example": "default", + "type": "string", + "x-go-name": "Namespace" + }, + "is_live": { + "description": "Whether the version is live or not", + "example": true, + "type": "boolean", + "x-go-name": "IsLive" + }, + "pipeline_id": { + "description": "The ID of the pipeline that deployed the version", + "example": "cc54a110-d03f-4916-96fc-ff36a1221ed7", + "format": "uuid", + "type": "string", + "x-go-name": "ID" + }, + "workflow_id": { + "description": "The ID of the CircleCI workflow that deployed the version", + "example": "5034460f-c7c4-4c43-9457-de07e2029e7b", + "format": "uuid", + "type": "string", + "x-go-name": "WorkflowID" + }, + "job_id": { + "description": "The ID of the CircleCI job that deployed the version", + "example": "f7e18b53-db27-4706-ad77-b16dc1e6fc53", + "format": "uuid", + "type": "string", + "x-go-name": "JobID" + }, + "job_number": { + "description": "The number of the CircleCI job that deployed the version", + "example": 123, + "type": "integer", + "x-go-name": "JobNumber" + }, + "last_deployed_at": { + "description": "The time at which the version was last deployed", + "format": "date-time", + "type": "string", + "x-go-name": "LastDeployedAt" + } + } + }, + "type": "array", + "x-go-name": "Items" + }, + "next_page_token": { + "description": "The pagination token to use when fetching the next page in this result set.", + "type": "string", + "nullable": true, + "x-go-name": "NextPageToken" + } + } + }, + "environment": { + "type": "object", + "additionalProperties": false, + "properties": { + "created_at": { + "description": "The time when the environment was created", + "format": "date-time", + "type": "string", + "x-go-name": "CreatedAt" + }, + "description": { + "description": "Short description given to the environment", + "example": "some description", + "type": "string", + "x-go-name": "Description" + }, + "id": { + "description": "The environment ID", + "example": "123e4127-e89b-12d3-a456-426123417400", + "format": "uuid", + "type": "string", + "x-go-name": "ID" + }, + "labels": { + "description": "The labels associated to the environment", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "key": { + "description": "The key of the label", + "example": "env", + "type": "string", + "x-go-name": "Key" + }, + "value": { + "description": "The value of the label", + "example": "prod", + "type": "string", + "x-go-name": "Value" + } + } + }, + "type": "array", + "x-go-name": "Labels" + }, + "name": { + "description": "The environment name", + "example": "prod-app", + "type": "string", + "x-go-name": "Name" + }, + "updated_at": { + "description": "The time when the environment was updated", + "format": "date-time", + "type": "string", + "x-go-name": "UpdatedAt" + } + } + }, + "paginatedEnvironmentList": { + "type": "object", + "additionalProperties": false, + "properties": { + "items": { + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "created_at": { + "description": "The time when the environment was created", + "format": "date-time", + "type": "string", + "x-go-name": "CreatedAt" + }, + "description": { + "description": "Short description given to the environment", + "example": "some description", + "type": "string", + "x-go-name": "Description" + }, + "id": { + "description": "The environment ID", + "example": "123e4127-e89b-12d3-a456-426123417400", + "format": "uuid", + "type": "string", + "x-go-name": "ID" + }, + "labels": { + "description": "The labels associated to the environment", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "key": { + "description": "The key of the label", + "example": "env", + "type": "string", + "x-go-name": "Key" + }, + "value": { + "description": "The value of the label", + "example": "prod", + "type": "string", + "x-go-name": "Value" + } + } + }, + "type": "array", + "x-go-name": "Labels" + }, + "name": { + "description": "The environment name", + "example": "prod-app", + "type": "string", + "x-go-name": "Name" + }, + "updated_at": { + "description": "The time when the environment was updated", + "format": "date-time", + "type": "string", + "x-go-name": "UpdatedAt" + } + } + }, + "type": "array", + "x-go-name": "Items" + }, + "next_page_token": { + "description": "The pagination token to use when fetching the next page in this result set.", + "type": "string", + "nullable": true, + "x-go-name": "NextPageToken" + } + } + } + } + } +} \ No newline at end of file diff --git a/tests/CIRCLECI_API/config.yml b/tests/CIRCLECI_API/config.yml new file mode 100644 index 00000000..a2787595 --- /dev/null +++ b/tests/CIRCLECI_API/config.yml @@ -0,0 +1,56 @@ + +# This config.yml contains user provided data for api testing. Allows to define values here or use ENV to load values. e.g. ENV[API_HOST] = "https://exampl2.com" +# api: +# host: "${API_HOST:-https://example.com/api/v2}" # includes base path +# auth: +# api_key: "${API_KEY:-}" +# api_key_header: "${KEYNAME:-DefaultValue}" # openapi.spec.security.KEY_NAME +# basic_auth: "${username:-}:${password:-}" +# test_data: +# id: "${TEST_ID:-282739-1238371-219393-2833}" # Any test data key value pair e.g. GET /api/v1/cart/:id +# context-id: "${TEST_context-id:-}" # GET /api/v1/{context-id}/summary + + + +api: + host: "${CIRCLECI_API_BASE_URL:-https://circleci.com/api/v2}" +auth: + api_key_header: "${Circle-Token:-}" + basic_auth: "${CIRCLECI_API_AUTH_USERNAME:-}:${CIRCLECI_API_AUTH_PASSWORD:-}" + api_key_query: "${circle-token:-}" +test_data: + project-slug: "${TEST_project-slug:-}" + workflow-name: "${TEST_workflow-name:-}" + org-slug: "${TEST_org-slug:-}" + job-id: "${TEST_job-id:-}" + org-slug-or-id: "${TEST_org-slug-or-id:-}" + allow-list-entry-id: "${TEST_allow-list-entry-id:-}" + pipeline-id: "${TEST_pipeline-id:-}" + fingerprint: "${TEST_fingerprint:-}" + name: "${TEST_name:-}" + job-number: "${TEST_job-number:-}" + pipeline-number: "${TEST_pipeline-number:-}" + schedule-id: "${TEST_schedule-id:-}" + id: "${TEST_id:-}" + webhook-id: "${TEST_webhook-id:-}" + approval_request_id: "${TEST_approval_request_id:-}" + orgID: "${TEST_orgID:-}" + projectID: "${TEST_projectID:-}" + ownerID: "${TEST_ownerID:-}" + context: "${TEST_context:-}" + decisionID: "${TEST_decisionID:-}" + policyName: "${TEST_policyName:-}" + context_id: "${TEST_context_id:-}" + env_var_name: "${TEST_env_var_name:-}" + restriction_id: "${TEST_restriction_id:-}" + provider: "${TEST_provider:-}" + organization: "${TEST_organization:-}" + project: "${TEST_project:-}" + org_id: "${TEST_org_id:-}" + group_id: "${TEST_group_id:-}" + usage_export_job_id: "${TEST_usage_export_job_id:-}" + project_id: "${TEST_project_id:-}" + pipeline_definition_id: "${TEST_pipeline_definition_id:-}" + trigger_id: "${TEST_trigger_id:-}" + environment_id: "${TEST_environment_id:-}" + component_id: "${TEST_component_id:-}" diff --git a/tests/CIRCLECI_API/conftest.py b/tests/CIRCLECI_API/conftest.py new file mode 100644 index 00000000..705d1fff --- /dev/null +++ b/tests/CIRCLECI_API/conftest.py @@ -0,0 +1,298 @@ +import json +import os +import re +from pathlib import Path +from typing import Any, Callable, Dict, Optional + +import pytest +import requests +import yaml +from requests.adapters import HTTPAdapter +from urllib3.util.retry import Retry + + +# --------------------------- +# Utility: Environment expansion +# --------------------------- + +# Regex similar to r"${([^}:s]+):-([^}]+)}" to support ${ENV_VAR:-default} +_ENV_PATTERN = re.compile(r"\$\{([^}:\s]+):-([^}]+)\}") + + +def _expand_env_vars(value: Any) -> Any: + """ + Recursively expand environment variable placeholders in strings using the + pattern ${ENV_VAR:-default}. If ENV_VAR is unset or empty, 'default' is used. + Non-string inputs are returned unchanged, dicts/lists are processed recursively. + """ + + def _expand_str(s: str) -> str: + def _repl(match: re.Match) -> str: + var_name = match.group(1) + default_val = match.group(2) + env_val = os.environ.get(var_name) + return env_val if env_val not in (None, "") else default_val + + # Expand repeatedly in case a replacement introduces another pattern + previous = None + current = s + # Avoid infinite loops by capping iterations + for _ in range(10): + if previous == current: + break + previous = current + current = _ENV_PATTERN.sub(_repl, current) + return current + + if isinstance(value, str): + return _expand_str(value) + elif isinstance(value, list): + return [_expand_env_vars(item) for item in value] + elif isinstance(value, dict): + return {k: _expand_env_vars(v) for k, v in value.items()} + else: + return value + + +# --------------------------- +# Config loading +# --------------------------- + +def _load_raw_config() -> Dict[str, Any]: + here = Path(__file__).parent + cfg_path = here / "config.yml" + if not cfg_path.exists(): + raise pytest.UsageError(f"Missing configuration file: {cfg_path}") + + try: + with cfg_path.open("r", encoding="utf-8") as f: + data = yaml.safe_load(f) or {} + except yaml.YAMLError as e: + raise pytest.UsageError(f"Invalid YAML in {cfg_path}: {e}") from e + except Exception as e: + raise pytest.UsageError(f"Failed to read {cfg_path}: {e}") from e + + return data + + +@pytest.fixture(scope="session") +def config() -> Dict[str, Any]: + """ + Load config.yml from the same directory as this conftest.py, + expanding environment variables using ${ENV_VAR:-default}. + """ + raw = _load_raw_config() + expanded = _expand_env_vars(raw) + if not isinstance(expanded, dict): + raise pytest.UsageError("Top-level config must be a mapping/dictionary.") + return expanded + + +# --------------------------- +# Dynamic config getter +# --------------------------- + +@pytest.fixture(scope="session") +def get_config(config: Dict[str, Any]) -> Callable[[str, Optional[Any]], Any]: + """ + Returns a callable to fetch config values via dotted keys, e.g.: + get_config("api.host") or get_config("test_data.project-slug"). + """ + + def _getter(dotted_key: str, default: Any = None) -> Any: + parts = dotted_key.split(".") + current: Any = config + for part in parts: + if isinstance(current, dict) and part in current: + current = current[part] + else: + if default is not None: + return default + raise KeyError(f"Config key not found: {dotted_key}") + return current + + return _getter + + +# --------------------------- +# Endpoint test data loading and merge +# --------------------------- + +@pytest.fixture +def load_endpoint_test_data(request) -> Callable[[str], Dict[str, Any]]: + """ + Returns a callable that loads JSON test data from a path. + Resolution order: + - absolute path + - relative to the test file's directory + - relative to current working directory + """ + + def _loader(path: str) -> Dict[str, Any]: + candidate = Path(path) + if not candidate.is_absolute(): + test_dir = Path(getattr(request, "fspath", Path.cwd())).parent + if (test_dir / path).exists(): + candidate = test_dir / path + elif (Path.cwd() / path).exists(): + candidate = Path.cwd() / path + + if not candidate.exists(): + raise FileNotFoundError(f"Endpoint test data file not found: {path}") + + try: + with candidate.open("r", encoding="utf-8") as f: + data = json.load(f) + except json.JSONDecodeError as e: + raise ValueError(f"Invalid JSON in {candidate}: {e}") from e + if not isinstance(data, dict): + raise ValueError(f"Endpoint test data must be a JSON object: {candidate}") + return data + + return _loader + + +@pytest.fixture +def merged_test_data(config: Dict[str, Any], load_endpoint_test_data: Callable[[str], Dict[str, Any]]) -> Callable[[str], Dict[str, Any]]: + """ + Returns a callable that merges config['test_data'] with endpoint JSON data. + Values from endpoint JSON override keys in config.yml.test_data when duplicated. + """ + + def _merger(path: str) -> Dict[str, Any]: + base = config.get("test_data", {}) + if base is None: + base = {} + if not isinstance(base, dict): + raise ValueError("config['test_data'] must be a mapping if present.") + ep = load_endpoint_test_data(path) + merged = dict(base) + merged.update(ep) + return merged + + return _merger + + +# --------------------------- +# API Client +# --------------------------- + +class APIClient: + def __init__( + self, + base_url: str, + default_timeout: Optional[float] = None, + retries_config: Optional[Dict[str, Any]] = None, + verify: Optional[bool] = None, + session: Optional[requests.Session] = None, + ): + if not isinstance(base_url, str) or not base_url.strip(): + raise ValueError("Base URL must be a non-empty string.") + self.base_url = base_url.strip().rstrip("/") + self.default_timeout = default_timeout + self.verify = verify + + self.session = session or requests.Session() + + # Configure retries if provided or use sensible defaults + rc = retries_config or {} + total = int(rc.get("total", 3)) + backoff_factor = float(rc.get("backoff_factor", 0.3)) + status_forcelist = rc.get("status_forcelist", (429, 500, 502, 503, 504)) + allowed_methods = rc.get("allowed_methods", frozenset(["HEAD", "GET", "OPTIONS", "POST", "PUT", "PATCH", "DELETE"])) + + retry = Retry( + total=total, + read=total, + connect=total, + backoff_factor=backoff_factor, + status_forcelist=status_forcelist, + allowed_methods=allowed_methods, + raise_on_status=False, + ) + adapter = HTTPAdapter(max_retries=retry) + self.session.mount("http://", adapter) + self.session.mount("https://", adapter) + + def _full_url(self, endpoint: Optional[str]) -> str: + if not endpoint: + return self.base_url + return f"{self.base_url}/{str(endpoint).lstrip('/')}" + + def make_request(self, endpoint: Optional[str], method: str = "GET", headers: Optional[Dict[str, str]] = None, **kwargs) -> requests.Response: + url = self._full_url(endpoint) + hdrs = {} + if headers: + hdrs.update(headers) + + # Default timeout if not provided + if "timeout" not in kwargs and self.default_timeout is not None: + kwargs["timeout"] = self.default_timeout + + # Allow per-request override of verify; fallback to client default + if "verify" not in kwargs and self.verify is not None: + kwargs["verify"] = self.verify + + response = self.session.request(method=method.upper(), url=url, headers=hdrs, **kwargs) + return response + + def get(self, endpoint: Optional[str], headers: Optional[Dict[str, str]] = None, **kwargs) -> requests.Response: + return self.make_request(endpoint, method="GET", headers=headers, **kwargs) + + def post(self, endpoint: Optional[str], headers: Optional[Dict[str, str]] = None, **kwargs) -> requests.Response: + return self.make_request(endpoint, method="POST", headers=headers, **kwargs) + + def put(self, endpoint: Optional[str], headers: Optional[Dict[str, str]] = None, **kwargs) -> requests.Response: + return self.make_request(endpoint, method="PUT", headers=headers, **kwargs) + + def patch(self, endpoint: Optional[str], headers: Optional[Dict[str, str]] = None, **kwargs) -> requests.Response: + return self.make_request(endpoint, method="PATCH", headers=headers, **kwargs) + + def delete(self, endpoint: Optional[str], headers: Optional[Dict[str, str]] = None, **kwargs) -> requests.Response: + return self.make_request(endpoint, method="DELETE", headers=headers, **kwargs) + + +@pytest.fixture(scope="session") +def api_client(config: Dict[str, Any]) -> APIClient: + # Base URL required + try: + base_url = config["api"]["host"] + except Exception as e: + raise pytest.UsageError("config['api']['host'] is required in config.yml") from e + + # Optional settings + api_cfg = config.get("api", {}) if isinstance(config.get("api", {}), dict) else {} + timeout = api_cfg.get("timeout", None) + if timeout is not None: + try: + timeout = float(timeout) + except Exception: + raise pytest.UsageError("config['api']['timeout'] must be numeric if provided.") + + verify = api_cfg.get("verify", None) + if isinstance(verify, str): + # Interpret common string booleans + v = verify.strip().lower() + if v in ("true", "1", "yes", "y", "on"): + verify = True + elif v in ("false", "0", "no", "n", "off"): + verify = False + + retries_cfg = api_cfg.get("retry") or api_cfg.get("retries") # support common naming if present + if retries_cfg is not None and not isinstance(retries_cfg, dict): + raise pytest.UsageError("config['api']['retry'|'retries'] must be a mapping if provided.") + + return APIClient( + base_url=str(base_url).strip(), + default_timeout=timeout, + retries_config=retries_cfg, + verify=verify if isinstance(verify, bool) else None, + ) + + +# --------------------------- +# Pytest hooks / markers +# --------------------------- + +def pytest_configure(config: pytest.Config) -> None: + config.addinivalue_line("markers", "smoke: mark test as part of the smoke suite") diff --git a/tests/CIRCLECI_API/insights_org-slug_summary.json b/tests/CIRCLECI_API/insights_org-slug_summary.json new file mode 100644 index 00000000..254e35b5 --- /dev/null +++ b/tests/CIRCLECI_API/insights_org-slug_summary.json @@ -0,0 +1,91 @@ +[ + { + "org-slug": "acme-inc", + "statusCode": 200, + "scenario": "Successful responses: OK" + }, + { + "org-slug": "acme-inc", + "reporting-window": "last-30-days", + "project-names": { + "include": [ + "api-preview-docs", + "mobile-app" + ], + "exclude": [ + "legacy-lib" + ] + }, + "statusCode": 200, + "scenario": "Successful responses: OK" + }, + { + "org-slug": "devops-labs", + "reporting-window": "last-7-days", + "project-names": { + "include": [ + "api-service", + "web-frontend" + ] + }, + "statusCode": 200, + "scenario": "Successful responses: OK" + }, + { + "org-slug": "octo-org", + "project-names": { + "include": [ + "cli", + "docs" + ] + }, + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "org-slug": "acme-inc", + "reporting-window": "last-13-days", + "project-names": { + "include": [ + "api-preview-docs" + ] + }, + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "org-slug": "does-not-exist-404", + "reporting-window": "last-30-days", + "project-names": { + "include": [ + "api-service" + ] + }, + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "org-slug": "devops-labs", + "reporting-window": "last-90-days", + "project-names": { + "include": "single-project" + }, + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "org-slug": "data-wizards", + "reporting-window": "last-24-hours", + "project-names": { + "include": [ + "etl-pipeline", + "ml-platform" + ], + "exclude": [ + "deprecated-service" + ] + }, + "statusCode": 200, + "scenario": "Successful responses: OK" + } +] \ No newline at end of file diff --git a/tests/CIRCLECI_API/insights_pages_project-slug_summary.json b/tests/CIRCLECI_API/insights_pages_project-slug_summary.json new file mode 100644 index 00000000..1094474d --- /dev/null +++ b/tests/CIRCLECI_API/insights_pages_project-slug_summary.json @@ -0,0 +1,101 @@ +[ + { + "project-slug": "gh/acme/cool-app", + "statusCode": 200, + "scenario": "Successful responses: OK" + }, + { + "project-slug": "gh/acme/cool-app", + "reporting-window": "last-30-days", + "statusCode": 200, + "scenario": "Successful responses: OK" + }, + { + "project-slug": "gh/example/monorepo", + "reporting-window": "last-90-days", + "branches": { + "include": [ + "main", + "develop", + "release/1.2.0" + ] + }, + "workflow-names": { + "include": [ + "build-and-test", + "deploy", + "lint" + ] + }, + "statusCode": 200, + "scenario": "Successful responses: OK" + }, + { + "project-slug": "bb/contoso/backend-service", + "branches": { + "include": [ + "main", + "release/*" + ] + }, + "statusCode": 200, + "scenario": "Successful responses: OK" + }, + { + "project-slug": "gh/acme/cool-app", + "branches": { + "include": [ + "feature/new-ui" + ] + }, + "workflow-names": { + "include": [ + "integration-tests" + ] + }, + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "gh/example/monorepo", + "reporting-window": "past-13-days", + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "invalid-format-slug", + "reporting-window": "last-30-days", + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "gh/unknown-org/unknown-repo", + "reporting-window": "last-7-days", + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "gh/sample/cli-tool", + "reporting-window": "last-30-days", + "branches": { + "includes": [ + "main", + "hotfix/urgent-123" + ] + }, + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "gh/data/analytics-pipeline", + "reporting-window": "last-90-days", + "workflow-names": { + "include": [ + "non-existent-workflow", + "typoed-workflow" + ] + }, + "statusCode": "default", + "scenario": "Unknown response class" + } +] \ No newline at end of file diff --git a/tests/CIRCLECI_API/insights_project-slug_branches.json b/tests/CIRCLECI_API/insights_project-slug_branches.json new file mode 100644 index 00000000..495d23f8 --- /dev/null +++ b/tests/CIRCLECI_API/insights_project-slug_branches.json @@ -0,0 +1,45 @@ +[ + { + "project-slug": "gh/acme-inc/mobile-app", + "statusCode": 200, + "scenario": "Successful responses: OK" + }, + { + "project-slug": "bb/contoso/api-service", + "workflow-name": "build_and_test", + "statusCode": 200, + "scenario": "Successful responses: OK" + }, + { + "project-slug": "acme-inc/mobile-app", + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "gh/ghost-org/vanished-repo", + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "gh/acme-inc/mobile-app", + "workflow-name": "💥invalid-workflow%%", + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "bb/contoso/api-service", + "workflow-name": "nonexistent_workflow_123", + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "gl/acme-inc/mobile-app", + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "gh/acme-inc", + "statusCode": "default", + "scenario": "Unknown response class" + } +] \ No newline at end of file diff --git a/tests/CIRCLECI_API/insights_project-slug_flaky-tests.json b/tests/CIRCLECI_API/insights_project-slug_flaky-tests.json new file mode 100644 index 00000000..bdb7b122 --- /dev/null +++ b/tests/CIRCLECI_API/insights_project-slug_flaky-tests.json @@ -0,0 +1,41 @@ +[ + { + "project-slug": "gh/acme/widgets-service", + "statusCode": 200, + "scenario": "Successful responses: OK" + }, + { + "project-slug": "bb/space/ansible-role-nginx", + "statusCode": 200, + "scenario": "Successful responses: OK" + }, + { + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "zz/acme/widgets", + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "gh/acme corp/widgets service", + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "gh/ghost-org-9999/ghost-repo-9999", + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "gh/acme/mobile-app", + "statusCode": 200, + "scenario": "Successful responses: OK" + }, + { + "project-slug": "gh/acme-only", + "statusCode": "default", + "scenario": "Unknown response class" + } +] \ No newline at end of file diff --git a/tests/CIRCLECI_API/insights_project-slug_workflows.json b/tests/CIRCLECI_API/insights_project-slug_workflows.json new file mode 100644 index 00000000..8aa81fe9 --- /dev/null +++ b/tests/CIRCLECI_API/insights_project-slug_workflows.json @@ -0,0 +1,58 @@ +[ + { + "project-slug": "gh/acme/api-service", + "statusCode": 200, + "scenario": "Successful responses: OK" + }, + { + "project-slug": "gh/acme/api-service", + "page-token": "cjp.eyJwYWdlIjoxfQ", + "all-branches": true, + "reporting-window": "last-30-days", + "statusCode": 200, + "scenario": "Successful responses: OK" + }, + { + "project-slug": "gh/foocorp/monorepo", + "all-branches": false, + "branch": "develop", + "reporting-window": "last-7-days", + "page-token": "cjp.eyJwYWdlIjoyfQ", + "statusCode": 200, + "scenario": "Successful responses: OK" + }, + { + "project-slug": "gh/foocorp/monorepo", + "all-branches": false, + "reporting-window": "last-24-hours", + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "gh/acme/api-service", + "reporting-window": "last-90-days", + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "gh/unknown-org/nonexistent-repo", + "reporting-window": "last-30-days", + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "gh/acme/api-service", + "page-token": "invalid.token.value", + "reporting-window": "last-7-days", + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "gh/acme/api-service", + "all-branches": true, + "branch": "feature/refactor-ci", + "reporting-window": "since-2020-01-01", + "statusCode": "default", + "scenario": "Unknown response class" + } +] \ No newline at end of file diff --git a/tests/CIRCLECI_API/insights_project-slug_workflows_workflow-name.json b/tests/CIRCLECI_API/insights_project-slug_workflows_workflow-name.json new file mode 100644 index 00000000..74bf78e9 --- /dev/null +++ b/tests/CIRCLECI_API/insights_project-slug_workflows_workflow-name.json @@ -0,0 +1,78 @@ +[ + { + "project-slug": "gh/acme/widget-service", + "workflow-name": "build_and_test", + "statusCode": 200, + "scenario": "Successful responses: OK" + }, + { + "project-slug": "gh/acme/widget-service", + "workflow-name": "build_and_test", + "all-branches": true, + "page-token": "pg_2b7e15", + "start-date": "2025-01-01T00:00:00Z", + "end-date": "2025-01-31T23:59:59Z", + "statusCode": 200, + "scenario": "Successful responses: OK" + }, + { + "project-slug": "gh/acme/mobile-app", + "workflow-name": "deploy_prod", + "all-branches": false, + "branch": "main", + "statusCode": 200, + "scenario": "Successful responses: OK" + }, + { + "project-slug": "gh/open-source/sample-repo", + "workflow-name": "nightly_ci", + "page-token": "eyJwYWdlIjoyfQ", + "statusCode": 200, + "scenario": "Successful responses: OK" + }, + { + "project-slug": "gh/acme/mobile-app", + "workflow-name": "deploy_prod", + "all-branches": false, + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "gh/acme/widget-service", + "workflow-name": "build_and_test", + "all-branches": "yes", + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "gh/open-source/sample-repo", + "workflow-name": "nightly_ci", + "start-date": "2025-13-01", + "end-date": "2025-02-30", + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "gh/unknown-org/unknown-repo", + "workflow-name": "non_existent_workflow", + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "gh/acme/widget-service", + "workflow-name": "build_and_test", + "page-token": "!!invalid-token!!", + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "bb/acme-inc/legacy-service", + "workflow-name": "smoke_tests", + "all-branches": false, + "branch": "release/2025.12", + "start-date": "2025-11-01T00:00:00Z", + "end-date": "2025-12-01T00:00:00Z", + "statusCode": 200, + "scenario": "Successful responses: OK" + } +] \ No newline at end of file diff --git a/tests/CIRCLECI_API/insights_project-slug_workflows_workflow-name_jobs.json b/tests/CIRCLECI_API/insights_project-slug_workflows_workflow-name_jobs.json new file mode 100644 index 00000000..191657a1 --- /dev/null +++ b/tests/CIRCLECI_API/insights_project-slug_workflows_workflow-name_jobs.json @@ -0,0 +1,84 @@ +[ + { + "project-slug": "gh/acme-inc/rocket-app", + "workflow-name": "build_and_test", + "statusCode": 200, + "scenario": "Successful responses: OK" + }, + { + "project-slug": "gh/acme-inc/rocket-app", + "workflow-name": "deploy", + "reporting-window": "last-30-days", + "all-branches": true, + "page-token": "cursor_1_a1b2c3", + "job-name": "deploy", + "statusCode": 200, + "scenario": "Successful responses: OK" + }, + { + "project-slug": "gh/acme-inc/rocket-app", + "workflow-name": "nightly", + "reporting-window": "last-7-days", + "all-branches": false, + "branch": "release/1.2.3", + "page-token": "cursor_rls_987", + "job-name": "package", + "statusCode": 200, + "scenario": "Successful responses: OK" + }, + { + "project-slug": "gh/acme-inc/rocket-app", + "workflow-name": "build_and_test", + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "gh/acme-inc/rocket-app", + "workflow-name": "build_and_test", + "reporting-window": "last-365-days", + "all-branches": true, + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "gh/unknown-org-zzz-404/nope", + "workflow-name": "build_and_test", + "reporting-window": "last-30-days", + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "gh/acme-inc/rocket-app", + "workflow-name": "unknown_workflow_404", + "reporting-window": "last-90-days", + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "gh/acme-inc/rocket-app", + "workflow-name": "build_and_test", + "reporting-window": "last-24-hours", + "page-token": "invalid!token?!", + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "gh/bytecraft/data-pipeline", + "workflow-name": "ingest", + "reporting-window": "last-24-hours", + "all-branches": false, + "branch": "develop", + "job-name": "extract", + "statusCode": 200, + "scenario": "Successful responses: OK" + }, + { + "project-slug": "gh/acme-inc/rocket-app", + "workflow-name": "build_and_test", + "reporting-window": "yesterday", + "all-branches": false, + "branch": "main", + "statusCode": "default", + "scenario": "Unknown response class" + } +] \ No newline at end of file diff --git a/tests/CIRCLECI_API/insights_project-slug_workflows_workflow-name_summ.json b/tests/CIRCLECI_API/insights_project-slug_workflows_workflow-name_summ.json new file mode 100644 index 00000000..032a1408 --- /dev/null +++ b/tests/CIRCLECI_API/insights_project-slug_workflows_workflow-name_summ.json @@ -0,0 +1,58 @@ +[ + { + "project-slug": "gh/ci-samples/sample-node", + "workflow-name": "build_and_test", + "statusCode": 200, + "scenario": "Successful responses: OK" + }, + { + "project-slug": "gh/ci-samples/sample-node", + "workflow-name": "deploy", + "branch": "main", + "statusCode": 200, + "scenario": "Successful responses: OK" + }, + { + "project-slug": "gh/acme-org/monorepo", + "workflow-name": "nightly_pipeline", + "all-branches": true, + "statusCode": 200, + "scenario": "Successful responses: OK" + }, + { + "project-slug": "gh/nonexistent-org/nonexistent-repo", + "workflow-name": "build_and_test", + "branch": "main", + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "gh/acme-org/monorepo", + "workflow-name": "unknown_workflow", + "all-branches": true, + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "bb/acme-inc/legacy-app", + "workflow-name": "deploy", + "branch": "develop", + "all-branches": true, + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "gh/ci-samples/sample-node", + "workflow-name": "build_and_test", + "branch": "feature/invalid space", + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "gh/acme-org/monorepo", + "workflow-name": "nightly_pipeline", + "branch": "feature/very-long-branch-name-for-validation-purposes-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "statusCode": "default", + "scenario": "Unknown response class" + } +] \ No newline at end of file diff --git a/tests/CIRCLECI_API/insights_time-series_project-slug_workflows_workfl.json b/tests/CIRCLECI_API/insights_time-series_project-slug_workflows_workfl.json new file mode 100644 index 00000000..4287a868 --- /dev/null +++ b/tests/CIRCLECI_API/insights_time-series_project-slug_workflows_workfl.json @@ -0,0 +1,92 @@ +[ + { + "project-slug": "gh/acme/widgets-api", + "workflow-name": "build-and-test", + "granularity": "day", + "start-date": "2024-09-01T00:00:00Z", + "end-date": "2024-10-01T00:00:00Z", + "statusCode": 200, + "scenario": "Successful responses: OK" + }, + { + "project-slug": "gh/acme/widgets-api", + "workflow-name": "deploy", + "branch": "main", + "granularity": "hour", + "start-date": "2024-10-01T00:00:00Z", + "end-date": "2024-10-08T00:00:00Z", + "statusCode": 200, + "scenario": "Successful responses: OK" + }, + { + "project-slug": "gh/acme/widgets-api", + "workflow-name": "build-and-test", + "start-date": "2024-10-01T00:00:00Z", + "end-date": "2024-10-08T00:00:00Z", + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "gh/acme/widgets-api", + "workflow-name": "build-and-test", + "granularity": "minute", + "start-date": "2024-10-01T00:00:00Z", + "end-date": "2024-10-08T00:00:00Z", + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "gl/acme/widgets-api", + "workflow-name": "build-and-test", + "granularity": "day", + "start-date": "2024-10-01T00:00:00Z", + "end-date": "2024-10-08T00:00:00Z", + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "gh/acme/widgets-api", + "workflow-name": "build-and-test", + "granularity": "day", + "start-date": "2024/10/01", + "end-date": "2024/10/08", + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "gh/acme/widgets-api", + "workflow-name": "build-and-test", + "granularity": "day", + "start-date": "2024-10-10T00:00:00Z", + "end-date": "2024-10-01T00:00:00Z", + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "gh/acme/mobile-app", + "workflow-name": "release", + "branch": "feature/login", + "granularity": "day", + "start-date": "2024-08-01T00:00:00Z", + "end-date": "2024-09-01T00:00:00Z", + "statusCode": 200, + "scenario": "Successful responses: OK" + }, + { + "project-slug": "gh/acme/mobile-app", + "workflow-name": "release", + "granularity": "hour", + "end-date": "2024-09-01T00:00:00Z", + "statusCode": "default", + "scenario": "Unknown response class" + }, + { + "project-slug": "gh/acme/widgets-api", + "workflow-name": "nonexistent-workflow", + "granularity": "day", + "start-date": "2024-10-01T00:00:00Z", + "end-date": "2024-10-08T00:00:00Z", + "statusCode": "default", + "scenario": "Unknown response class" + } +] \ No newline at end of file diff --git a/tests/CIRCLECI_API/test_insights_org-slug_summary_get.py b/tests/CIRCLECI_API/test_insights_org-slug_summary_get.py new file mode 100644 index 00000000..4a534210 --- /dev/null +++ b/tests/CIRCLECI_API/test_insights_org-slug_summary_get.py @@ -0,0 +1,275 @@ +# ********RoostGPT******** + +# Test generated by RoostGPT for test api-test-pytest-circleci using AI Type Open AI and AI Model gpt-5 +# +# Test file generated for /insights/{org-slug}/summary_get for http method type GET +# RoostTestHash=84690151ce +# +# + +# ********RoostGPT******** +""" +Pytest suite for Insights Summary API. + +How to run: + pytest -q +""" + +from pathlib import Path +from typing import Any, Dict, List, Optional +from urllib.parse import quote +import json + +import pytest + +from validator import SwaggerSchemaValidator + + +# Module-level constants required by test harness +_ENDPOINT = "/insights/{org-slug}/summary" +_METHOD = "get" +_TEST_DATA_FILE = "insights_org-slug_summary.json" +_here = Path(__file__).resolve().parent +_endpoint_data_path = _here / _TEST_DATA_FILE + +# Initialize validator once per module as required +_VALIDATOR = SwaggerSchemaValidator("api.json") + + +def _extract_endpoint_cases(merged: Optional[Dict[str, Any]], fallback_path: Path) -> List[Dict[str, Any]]: + """ + Extracts a list of test-case dictionaries from the merged endpoint data. + Tolerates different container keys and falls back to loading a JSON list + directly if the endpoint file is a list. + """ + if isinstance(merged, dict): + for key in ("cases", "entries", "tests", "items", "data"): + val = merged.get(key) + if isinstance(val, list): + return [x for x in val if isinstance(x, dict)] + + # Fallback: attempt to read a list directly from the file (the prompt's example shows a top-level list) + try: + raw = json.loads(fallback_path.read_text(encoding="utf-8")) + if isinstance(raw, list): + return [x for x in raw if isinstance(x, dict)] + except Exception: + pass + + return [] + + +def _build_headers_valid(get_config) -> Dict[str, str]: + headers: Dict[str, str] = {"Accept": "application/json"} + # Auth header name per spec examples + token = str(get_config("auth.api_key_header", "") or "") + # Always include the header for "valid" path; empty token will behave as missing/invalid in envs without credentials + headers["Circle-Token"] = token + return headers + + +def _build_headers_invalid() -> Dict[str, str]: + return { + "Accept": "application/json", + "Circle-Token": "invalid-token", + } + + +def _build_headers_missing() -> Dict[str, str]: + return { + "Accept": "application/json", + } + + +def _encode_project_names(value: Any) -> Optional[str]: + """ + Since the spec declares 'project-names' as an object in query, pass as JSON string if provided. + """ + if value is None: + return None + try: + return json.dumps(value) + except Exception: + # Fallback to string + return str(value) + + +def _resolve_org_slug(entry: Dict[str, Any], get_config) -> Optional[str]: + # Endpoint JSON values override config.yml + slug = entry.get("org-slug") + if slug: + return str(slug) + # Fallback to config + cfg_slug = get_config("test_data.org-slug", "") + if cfg_slug: + return str(cfg_slug) + return None + + +@pytest.mark.smoke +def test_insights_summary_smoke_success(api_client, get_config, merged_test_data): + """ + Happy-path success cases using only required fields. + - Required: path parameter org-slug + - Optional query params are intentionally omitted + """ + # Load merged data; tolerate top-level list via fallback + merged = None + try: + merged = merged_test_data(_endpoint_data_path) + except Exception: + merged = None + + entries = _extract_endpoint_cases(merged, _endpoint_data_path) + + # Filter smoke cases: those that contain only required inputs + smoke_candidates: List[Dict[str, Any]] = [] + for e in entries: + # Consider optional fields as per spec + has_optional = any(k in e for k in ("reporting-window", "project-names")) + if not has_optional: + smoke_candidates.append(e) + + # If no suitable smoke case present, build a minimal case from config + if not smoke_candidates: + cfg_org = get_config("test_data.org-slug", "") + if not cfg_org: + pytest.skip("No smoke test data available and test_data.org-slug not configured") + smoke_candidates = [{"org-slug": cfg_org, "statusCode": 200, "scenario": "Smoke: only required path params"}] + + for case in smoke_candidates: + org_slug = _resolve_org_slug(case, get_config) + if not org_slug: + pytest.skip("Missing org-slug in data and config fallback") + + # Encode slug: '/' may need escaping per spec + encoded_slug = quote(str(org_slug), safe="") + endpoint_path = _ENDPOINT.replace("{org-slug}", encoded_slug) + + headers = _build_headers_valid(get_config) + + resp = api_client.get(endpoint_path, headers=headers) + + expected_status = int(case.get("statusCode", 200)) + assert resp.status_code == expected_status, f"Expected {expected_status} but got {resp.status_code} for scenario: {case.get('scenario')}" + + # Validate response schema against OpenAPI for 200 + result = _VALIDATOR.validate_schema_by_response(_ENDPOINT, _METHOD, str(expected_status), resp) + assert result.get("valid"), f"Schema validation failed for 200 response: {result}" + + +def test_insights_summary_success_with_optional_params(api_client, get_config, merged_test_data): + """ + Success cases including optional query params 'reporting-window' and/or 'project-names'. + Values from endpoint JSON override config.yml. + """ + merged = None + try: + merged = merged_test_data(_endpoint_data_path) + except Exception: + merged = None + + entries = _extract_endpoint_cases(merged, _endpoint_data_path) + + opt_cases = [e for e in entries if any(k in e for k in ("reporting-window", "project-names"))] + if not opt_cases: + pytest.skip("No optional-parameter test entries present") + + for case in opt_cases: + org_slug = _resolve_org_slug(case, get_config) + if not org_slug: + pytest.skip("Missing org-slug in data and config fallback") + + encoded_slug = quote(str(org_slug), safe="") + endpoint_path = _ENDPOINT.replace("{org-slug}", encoded_slug) + + params: Dict[str, Any] = {} + if "reporting-window" in case: + params["reporting-window"] = str(case["reporting-window"]) + + if "project-names" in case: + pn = _encode_project_names(case.get("project-names")) + if pn is not None: + params["project-names"] = pn + + headers = _build_headers_valid(get_config) + + resp = api_client.get(endpoint_path, headers=headers, params=params) + + expected_status = int(case.get("statusCode", 200)) + assert resp.status_code == expected_status, ( + f"Expected {expected_status} but got {resp.status_code} " + f"for optional-params scenario: {case.get('scenario')}" + ) + + result = _VALIDATOR.validate_schema_by_response(_ENDPOINT, _METHOD, str(expected_status), resp) + assert result.get("valid"), f"Schema validation failed for {expected_status} response: {result}" + + +@pytest.mark.parametrize("auth_mode", ["invalid", "missing"]) +def test_insights_summary_auth_errors(api_client, get_config, merged_test_data, auth_mode: str): + """ + Negative tests for auth: + - invalid token + - missing token + Validate against the 'default' error response schema. + """ + merged = None + try: + merged = merged_test_data(_endpoint_data_path) + except Exception: + merged = None + + entries = _extract_endpoint_cases(merged, _endpoint_data_path) + # Use first available org-slug or fallback to config + base = entries[0] if entries else {} + org_slug = _resolve_org_slug(base, get_config) + if not org_slug: + pytest.skip("No org-slug available for auth negative tests") + + encoded_slug = quote(str(org_slug), safe="") + endpoint_path = _ENDPOINT.replace("{org-slug}", encoded_slug) + + headers = _build_headers_invalid() if auth_mode == "invalid" else _build_headers_missing() + + resp = api_client.get(endpoint_path, headers=headers) + assert not (200 <= resp.status_code < 300), f"Expected non-2xx for {auth_mode} auth, got: {resp.status_code}" + + # Validate against 'default' error schema + result = _VALIDATOR.validate_schema_by_response(_ENDPOINT, _METHOD, "default", resp) + assert result.get("valid"), f"Default error schema validation failed: {result}" + + +def test_insights_summary_negative_params(api_client, get_config, merged_test_data): + """ + Boundary/negative payload scenario: + - empty org-slug (invalid path) + - nonsensical query params + Expect a non-2xx status code and validate against 'default' error schema. + """ + merged = None + try: + merged = merged_test_data(_endpoint_data_path) + except Exception: + merged = None + + # Attempt an empty org-slug to force a path-related error + bad_org_slug = "" + encoded_slug = quote(str(bad_org_slug), safe="") + endpoint_path = _ENDPOINT.replace("{org-slug}", encoded_slug) + + headers = _build_headers_valid(get_config) + + # Intentionally provide malformed/odd query values + params = { + "reporting-window": "", # empty string + "project-names": "{malformed-json", # malformed JSON + } + + resp = api_client.get(endpoint_path, headers=headers, params=params) + assert not (200 <= resp.status_code < 300), f"Expected non-2xx for negative param scenario, got: {resp.status_code}" + + result = _VALIDATOR.validate_schema_by_response(_ENDPOINT, _METHOD, "default", resp) + # If the server does not expose a default schema for such errors, allow pass if validator says no block; + # however, per spec, a 'default' error response exists. + assert result.get("valid") or "No response block" in str(result.get("message", "")), f"Error schema validation failed: {result}" diff --git a/tests/CIRCLECI_API/test_insights_pages_project-slug_summary_get.py b/tests/CIRCLECI_API/test_insights_pages_project-slug_summary_get.py new file mode 100644 index 00000000..55b70c13 --- /dev/null +++ b/tests/CIRCLECI_API/test_insights_pages_project-slug_summary_get.py @@ -0,0 +1,256 @@ +# ********RoostGPT******** + +# Test generated by RoostGPT for test api-test-pytest-circleci using AI Type Open AI and AI Model gpt-5 +# +# Test file generated for /insights/pages/{project-slug}/summary_get for http method type GET +# RoostTestHash=6af3ca7513 +# +# + +# ********RoostGPT******** +""" +Pytest API tests for CircleCI Insights Pages Summary endpoint. + +How to run: + - Ensure config.yml and api.json are present alongside conftest.py + - Place endpoint test data JSON in the test directory + - Execute: pytest -q +""" + +from pathlib import Path +from typing import Dict, Any, List, Optional, Tuple +import pytest + +from validator import SwaggerSchemaValidator + +# Module-level required variables +_ENDPOINT = "/insights/pages/{project-slug}/summary" +_METHOD = "get" # lowercase matching APIClient methods +_TEST_DATA_FILE = "insights_pages_project-slug_summary.json" +_here = Path(__file__).resolve().parent +_endpoint_data_path = _here / _TEST_DATA_FILE + + +def _build_path(project_slug: str) -> str: + """ + Construct concrete path for the endpoint. + """ + slug = (project_slug or "").strip().lstrip("/") + return _ENDPOINT.replace("{project-slug}", slug) + + +def _available_valid_auth_variants(get_config) -> List[Dict[str, Any]]: + """ + Build a list of available valid auth variants from config. + Each variant is a dict with optional 'headers', 'params', and 'auth' (requests auth tuple). + """ + variants: List[Dict[str, Any]] = [] + + # Header API key + api_key_header = get_config("auth.api_key_header", "") or "" + if api_key_header.strip(): + variants.append({"headers": {"Circle-Token": api_key_header.strip()}}) + + # Basic auth: "username:password" + basic = get_config("auth.basic_auth", "") or "" + if basic is not None and isinstance(basic, str) and (basic.strip() or ":" in basic): + user, pw = (basic.split(":", 1) + [""])[:2] + if user or pw: + variants.append({"auth": (user, pw)}) + + # Query API key (deprecated) + api_key_query = get_config("auth.api_key_query", "") or "" + if api_key_query.strip(): + variants.append({"params": {"circle-token": api_key_query.strip()}}) + + return variants + + +def _merge_auth_and_params( + base_headers: Optional[Dict[str, str]], + base_params: Optional[Dict[str, Any]], + variant: Dict[str, Any] +) -> Tuple[Dict[str, str], Dict[str, Any], Optional[Tuple[str, str]]]: + """ + Merge base headers/params with an auth variant. + """ + headers = dict(base_headers or {}) + params = dict(base_params or {}) + auth = variant.get("auth") + if "headers" in variant: + headers.update(variant["headers"]) + if "params" in variant: + params.update(variant["params"]) + return headers, params, auth + + +def _load_cases(merged: Dict[str, Any]) -> List[Dict[str, Any]]: + """ + Extract cases list from merged test data. + Endpoint JSON data must provide 'cases' as a list of entries. + """ + cases = merged.get("cases") + if not isinstance(cases, list): + raise AssertionError("Endpoint test data must provide 'cases' as a list.") + return cases + + +@pytest.mark.smoke +def test_insights_pages_summary_smoke_success(api_client, get_config, merged_test_data): + """ + Happy-path: validate successful responses using only required fields from test data. + """ + data = merged_test_data(_endpoint_data_path) + cases = _load_cases(data) + + # Initialize validator for response schema checks + validator = SwaggerSchemaValidator("api.json") + + # Ensure at least one auth variant is available from config for happy path + auth_variants = _available_valid_auth_variants(get_config) + if not auth_variants: + pytest.skip("No valid authentication credentials configured in config.yml (auth.*).") + + # Use the first available valid auth variant for smoke tests + auth_variant = auth_variants[0] + + for i, entry in enumerate(cases): + # Required path parameter + project_slug = entry.get("project-slug") or get_config("test_data.project-slug", "") + assert project_slug, f"[case {i}] Missing required 'project-slug' in test data or config." + + # Query parameters (optional) + params: Dict[str, Any] = {} + if "reporting-window" in entry and entry.get("reporting-window") not in (None, ""): + params["reporting-window"] = entry["reporting-window"] + + # Merge auth + headers, params, auth = _merge_auth_and_params( + base_headers={"Accept": "application/json"}, + base_params=params, + variant=auth_variant, + ) + + # Build path and execute + path = _build_path(project_slug) + response = api_client.get(path, headers=headers, params=params, auth=auth) + + # Assert expected status code from test data + expected_status = int(entry.get("statusCode", 200)) + assert response.status_code == expected_status, ( + f"[case {i}] Expected status {expected_status}, got {response.status_code}. " + f"URL: {path}, params={params}" + ) + + # Validate schema using the OpenAPI spec + vres = validator.validate_schema_by_response(_ENDPOINT, _METHOD, str(response.status_code), response) + assert vres.get("valid"), f"[case {i}] Response schema validation failed: {vres}" + + +def test_insights_pages_summary_auth_errors(api_client, get_config): + """ + Negative: missing/invalid authentication should not return 2xx. + Validates error schemas when defined. + """ + # Prepare required path param + project_slug = get_config("test_data.project-slug", "") + if not project_slug: + pytest.skip("No 'test_data.project-slug' configured; cannot run auth error tests.") + path = _build_path(project_slug) + + validator = SwaggerSchemaValidator("api.json") + + scenarios = [ + {"name": "missing-auth", "headers": {}, "params": {}, "auth": None}, + {"name": "invalid-header-token", "headers": {"Circle-Token": "invalid-token"}, "params": {}, "auth": None}, + {"name": "invalid-query-token", "headers": {}, "params": {"circle-token": "invalid-token"}, "auth": None}, + {"name": "invalid-basic", "headers": {}, "params": {}, "auth": ("invalid-token", "")}, + ] + + for sc in scenarios: + headers = {"Accept": "application/json"} + headers.update(sc["headers"]) + params = dict(sc["params"]) + + resp = api_client.get(path, headers=headers, params=params, auth=sc["auth"]) + + assert not (200 <= resp.status_code < 300), ( + f"[{sc['name']}] Expected non-2xx for invalid/missing auth, got {resp.status_code}" + ) + + vres = validator.validate_schema_by_response(_ENDPOINT, _METHOD, str(resp.status_code), resp) + # If the spec defines an error schema for this status, it must be valid. + # If not defined, validator returns 'No response block' which is acceptable as schema absence. + if vres.get("valid") is False: + msg = vres.get("message", "") + # Allow when the spec doesn't define the error response; otherwise fail. + assert "No response block" in msg or "Method" in msg, f"Schema validation failed: {vres}" + + +def test_insights_pages_summary_invalid_project_slug(api_client, get_config): + """ + Negative: invalid project-slug should not return 2xx. + """ + validator = SwaggerSchemaValidator("api.json") + + # Acquire a valid auth variant to isolate path param error + auth_variants = _available_valid_auth_variants(get_config) + if not auth_variants: + pytest.skip("No valid authentication configured; cannot run invalid path tests.") + auth_variant = auth_variants[0] + + invalid_slugs = [ + "", # empty + "gh/unknown/definitely-not-a-project", # non-existent + ] + + for slug in invalid_slugs: + headers, params, auth = _merge_auth_and_params( + base_headers={"Accept": "application/json"}, + base_params={}, + variant=auth_variant, + ) + path = _build_path(slug) + resp = api_client.get(path, headers=headers, params=params, auth=auth) + + assert not (200 <= resp.status_code < 300), ( + f"[invalid project-slug '{slug}'] Expected non-2xx status, got {resp.status_code}" + ) + vres = validator.validate_schema_by_response(_ENDPOINT, _METHOD, str(resp.status_code), resp) + if vres.get("valid") is False: + msg = vres.get("message", "") + assert "No response block" in msg or "Method" in msg, f"Schema validation failed: {vres}" + + +def test_insights_pages_summary_invalid_reporting_window(api_client, get_config): + """ + Negative: invalid reporting-window query parameter should not return 2xx. + """ + validator = SwaggerSchemaValidator("api.json") + + # Use configured project slug + project_slug = get_config("test_data.project-slug", "") + if not project_slug: + pytest.skip("No 'test_data.project-slug' configured; cannot run invalid query tests.") + + # Acquire a valid auth variant to isolate query param error + auth_variants = _available_valid_auth_variants(get_config) + if not auth_variants: + pytest.skip("No valid authentication configured; cannot run invalid query tests.") + auth_variant = auth_variants[0] + + headers, params, auth = _merge_auth_and_params( + base_headers={"Accept": "application/json"}, + base_params={"reporting-window": "invalid-window-value"}, + variant=auth_variant, + ) + path = _build_path(project_slug) + resp = api_client.get(path, headers=headers, params=params, auth=auth) + + assert not (200 <= resp.status_code < 300), ( + f"[invalid reporting-window] Expected non-2xx status, got {resp.status_code}" + ) + vres = validator.validate_schema_by_response(_ENDPOINT, _METHOD, str(resp.status_code), resp) + if vres.get("valid") is False: + msg = vres.get("message", "") + assert "No response block" in msg or "Method" in msg, f"Schema validation failed: {vres}" diff --git a/tests/CIRCLECI_API/test_insights_project-slug_branches_get.py b/tests/CIRCLECI_API/test_insights_project-slug_branches_get.py new file mode 100644 index 00000000..81b390a9 --- /dev/null +++ b/tests/CIRCLECI_API/test_insights_project-slug_branches_get.py @@ -0,0 +1,261 @@ +# ********RoostGPT******** + +# Test generated by RoostGPT for test api-test-pytest-circleci using AI Type Open AI and AI Model gpt-5 +# +# Test file generated for /insights/{project-slug}/branches_get for http method type GET +# RoostTestHash=09a8ae2e85 +# +# + +# ********RoostGPT******** +""" +Pytest suite for CircleCI Insights: GET /insights/{project-slug}/branches + +How to run: + - Ensure config.yml and api.json are present alongside conftest.py. + - Provide necessary credentials via environment variables referenced by config.yml. + - Execute: pytest -q +""" + +from pathlib import Path +from typing import Any, Dict, Iterable, List, Optional, Tuple +from urllib.parse import quote + +import json +import pytest + +from validator import SwaggerSchemaValidator + +# Module-level required variables +_ENDPOINT = "/insights/{project-slug}/branches" +_METHOD = "get" +_TEST_DATA_FILE = "insights_project-slug_branches.json" +_here = Path(__file__).resolve().parent +_endpoint_data_path = _here / _TEST_DATA_FILE + +# Initialize schema validator using provided API spec +_validator = SwaggerSchemaValidator("api.json") + + +def _encode_project_slug(slug: str) -> str: + """ + URL-encode the project slug. The '/' characters should be URL-escaped. + """ + return quote(slug, safe="") + + +def _render_endpoint(slug: str) -> str: + """ + Replace path param with encoded value. + """ + return _ENDPOINT.replace("{project-slug}", _encode_project_slug(slug)) + + +def _get_auth_headers_valid(get_config) -> Dict[str, str]: + """ + Build headers for valid API key auth using config values. + """ + token = str(get_config("auth.api_key_header", "") or "") + return {"Circle-Token": token} if token != "" else {"Circle-Token": ""} + + +def _get_auth_headers_invalid() -> Dict[str, str]: + """ + Build headers for invalid API key auth (hardcoded bad token). + """ + return {"Circle-Token": "invalid-or-bogus-token"} + + +def _get_auth_headers_missing() -> Dict[str, str]: + """ + No auth headers for missing auth scenario. + """ + return {} + + +def _extract_cases_from_data(data: Any) -> List[Dict[str, Any]]: + """ + Normalize endpoint test cases into a list from various possible container formats. + This function accepts: + - a list (already the cases), + - an object containing "tests" or "cases" as arrays, + - otherwise returns an empty list. + """ + if isinstance(data, list): + return data + if isinstance(data, dict): + for key in ("tests", "cases", "entries", "data"): + v = data.get(key) + if isinstance(v, list): + return v + return [] + + +def _load_endpoint_cases(merged_test_data) -> List[Dict[str, Any]]: + """ + Load endpoint test cases using the mandated merged_test_data fixture, with a safe fallback + in case the JSON file is an array (per instructions) instead of an object (as required by fixture). + """ + raw = None + try: + # Mandatory: attempt to load via merged_test_data + raw = merged_test_data(_endpoint_data_path) + cases = _extract_cases_from_data(raw) + if cases: + return cases + except Exception: + # Fallback to direct JSON load if merged_test_data cannot handle list-type files + pass + + # Direct file read as fallback to support list-based test data + with _endpoint_data_path.open("r", encoding="utf-8") as f: + raw_fallback = json.load(f) + return _extract_cases_from_data(raw_fallback) + + +def _expected_status_and_validator_target(entry: Dict[str, Any]) -> Tuple[Optional[int], str]: + """ + Determine the expected status code and the target response block to validate against. + If the entry says "default", we validate against the 'default' response and expect non-2xx status. + Otherwise, default expected is 200. + """ + sc = entry.get("statusCode", 200) + if isinstance(sc, str) and sc.lower() == "default": + return None, "default" + try: + code_int = int(sc) + return code_int, str(code_int) + except Exception: + # Fallback: treat unknown as default + return None, "default" + + +@pytest.mark.smoke +def test_get_insights_branches_smoke(api_client, get_config, merged_test_data): + """ + Smoke: Only required parameters for success path. + Iterates only entries that use required fields (no query params). + """ + cases = _load_endpoint_cases(merged_test_data) + + # Filter cases that intend success and include only required inputs (no 'workflow-name') + required_only_cases = [] + for e in cases: + exp, target = _expected_status_and_validator_target(e) + if exp == 200 and "workflow-name" not in e: + required_only_cases.append(e) + + assert required_only_cases, "No smoke cases found with only required fields." + + headers = _get_auth_headers_valid(get_config) + + for idx, entry in enumerate(required_only_cases, start=1): + slug = entry.get("project-slug") or get_config("test_data.project-slug", "") + assert isinstance(slug, str) and slug, f"[smoke case {idx}] project-slug must be a non-empty string." + + endpoint = _render_endpoint(slug) + + # Required-only: no query params + resp = api_client.get(endpoint, headers=headers) + + assert resp.status_code == 200, f"[smoke case {idx}] Expected 200, got {resp.status_code}. Body: {resp.text}" + v = _validator.validate_schema_by_response(_ENDPOINT, _METHOD, "200", resp) + assert v.get("valid"), f"[smoke case {idx}] Response schema validation failed: {v}" + + +def test_get_insights_branches_all_cases(api_client, get_config, merged_test_data): + """ + Data-driven execution over all provided cases. + Optional query params are included when provided. + """ + cases = _load_endpoint_cases(merged_test_data) + assert isinstance(cases, list) and cases, "Endpoint test data must provide a non-empty list of cases." + + for idx, entry in enumerate(cases, start=1): + slug = entry.get("project-slug") or get_config("test_data.project-slug", "") + assert isinstance(slug, str) and slug, f"[case {idx}] project-slug must be a non-empty string." + + wf = entry.get("workflow-name") or None + params = {} + if isinstance(wf, str) and wf.strip(): + params["workflow-name"] = wf.strip() + + expected_status, validator_target = _expected_status_and_validator_target(entry) + + headers = _get_auth_headers_valid(get_config) + endpoint = _render_endpoint(slug) + + resp = api_client.get(endpoint, headers=headers, params=params if params else None) + + if validator_target == "default": + assert not (200 <= resp.status_code < 300), f"[case {idx}] Expected non-2xx for default error, got {resp.status_code}" + else: + assert resp.status_code == expected_status, f"[case {idx}] Expected {expected_status}, got {resp.status_code}. Body: {resp.text}" + + v = _validator.validate_schema_by_response(_ENDPOINT, _METHOD, validator_target, resp) + assert v.get("valid"), f"[case {idx}] Response schema validation failed: {v}" + + +def test_get_insights_branches_auth_scenarios(api_client, get_config, merged_test_data): + """ + Security checks: + - Valid auth (header Circle-Token) + - Invalid auth (bad token) + - Missing auth + """ + # Choose a project-slug from data or config for auth tests + cases = _load_endpoint_cases(merged_test_data) + candidate_slug = None + for e in cases: + if isinstance(e.get("project-slug"), str) and e.get("project-slug").strip(): + candidate_slug = e["project-slug"].strip() + break + slug = candidate_slug or get_config("test_data.project-slug", "") + assert isinstance(slug, str) and slug, "A valid project-slug is required for auth tests." + + endpoint = _render_endpoint(slug) + + # Valid auth + headers_valid = _get_auth_headers_valid(get_config) + resp_valid = api_client.get(endpoint, headers=headers_valid) + if 200 <= resp_valid.status_code < 300: + v_valid = _validator.validate_schema_by_response(_ENDPOINT, _METHOD, "200", resp_valid) + assert v_valid.get("valid"), f"[auth: valid] Schema validation failed: {v_valid}" + else: + # If not successful, still validate against default error + v_default = _validator.validate_schema_by_response(_ENDPOINT, _METHOD, "default", resp_valid) + assert v_default.get("valid"), f"[auth: valid->error] Default schema validation failed: {v_default}" + + # Invalid auth + headers_invalid = _get_auth_headers_invalid() + resp_invalid = api_client.get(endpoint, headers=headers_invalid) + assert not (200 <= resp_invalid.status_code < 300), f"[auth: invalid] Expected non-2xx, got {resp_invalid.status_code}" + v_invalid = _validator.validate_schema_by_response(_ENDPOINT, _METHOD, "default", resp_invalid) + assert v_invalid.get("valid"), f"[auth: invalid] Default schema validation failed: {v_invalid}" + + # Missing auth + headers_missing = _get_auth_headers_missing() + resp_missing = api_client.get(endpoint, headers=headers_missing) + assert not (200 <= resp_missing.status_code < 300), f"[auth: missing] Expected non-2xx, got {resp_missing.status_code}" + v_missing = _validator.validate_schema_by_response(_ENDPOINT, _METHOD, "default", resp_missing) + assert v_missing.get("valid"), f"[auth: missing] Default schema validation failed: {v_missing}" + + +def test_get_insights_branches_invalid_slug_errors(api_client, get_config): + """ + Negative/boundary: malformed project-slug should return an error (default response). + """ + headers = _get_auth_headers_valid(get_config) + + invalid_slugs = [ + "zz/unknownOrg/unknownRepo", # likely non-existent + "not/a/valid slug", # contains space + "###/@@@/!!!", # invalid characters + ] + + for idx, bad in enumerate(invalid_slugs, start=1): + endpoint = _render_endpoint(bad) + resp = api_client.get(endpoint, headers=headers) + assert not (200 <= resp.status_code < 300), f"[invalid slug {idx}] Expected non-2xx, got {resp.status_code}" + v = _validator.validate_schema_by_response(_ENDPOINT, _METHOD, "default", resp) + assert v.get("valid"), f"[invalid slug {idx}] Default schema validation failed: {v}" diff --git a/tests/CIRCLECI_API/test_insights_project-slug_flaky-tests_get.py b/tests/CIRCLECI_API/test_insights_project-slug_flaky-tests_get.py new file mode 100644 index 00000000..444f06c0 --- /dev/null +++ b/tests/CIRCLECI_API/test_insights_project-slug_flaky-tests_get.py @@ -0,0 +1,136 @@ +# ********RoostGPT******** + +# Test generated by RoostGPT for test api-test-pytest-circleci using AI Type Open AI and AI Model gpt-5 +# +# Test file generated for /insights/{project-slug}/flaky-tests_get for http method type GET +# RoostTestHash=abf46592e1 +# +# + +# ********RoostGPT******** +""" +Pytest suite for CircleCI Insights API: GET /insights/{project-slug}/flaky-tests + +How to run: + - Ensure config.yml is configured (see conftest.py for details) + - Place endpoint test data JSON next to this test file + - Run: pytest -q +""" + +from pathlib import Path +from typing import Any, Dict, List + +import pytest + +from validator import SwaggerSchemaValidator + +# Module-level constants required before tests +_ENDPOINT = "/insights/{project-slug}/flaky-tests" +_METHOD = "get" +_TEST_DATA_FILE = "insights_project-slug_flaky-tests.json" +_here = Path(__file__).resolve().parent +_endpoint_data_path = _here / _TEST_DATA_FILE + +# Initialize schema validator with the API specification +_validator = SwaggerSchemaValidator("api.json") + + +def _build_endpoint(project_slug: str) -> str: + """ + Build the endpoint with the provided project slug. + The slug is path-embedded and is expected to include slashes as-is. + """ + return _ENDPOINT.replace("{project-slug}", str(project_slug)) + + +def _extract_cases(data: Dict[str, Any]) -> List[Dict[str, Any]]: + """ + Extracts test cases from merged data. + Supports several common keys; falls back to a single case synthesized from merged data. + """ + for key in ("cases", "entries", "tests", "endpoint_test_data", "ENDPOINT_TEST_DATA", "items", "data"): + v = data.get(key) + if isinstance(v, list): + return [c for c in v if isinstance(c, dict)] + + # Fallback to a single synthesized case using available merged/config data + fallback_slug = str(data.get("project-slug", "")).strip() + return [{"project-slug": fallback_slug, "scenario": "auto-generated from merged config"}] + + +@pytest.mark.smoke +def test_get_flaky_tests_smoke_valid_auth(api_client, get_config, merged_test_data): + """ + Happy path: authenticated request should return 200 and a response matching the schema. + Uses only required path parameter from data/config. + """ + data = merged_test_data(_endpoint_data_path) + token = get_config("auth.api_key_header", "") + if not isinstance(token, str) or token.strip() == "": + pytest.skip("auth.api_key_header is not configured; skipping authenticated smoke test.") + + cases = _extract_cases(data) + assert isinstance(cases, list) and len(cases) >= 1, "No test cases found for smoke test." + + for idx, entry in enumerate(cases, start=1): + slug = (entry.get("project-slug") or data.get("project-slug") or "").strip() + if not slug: + pytest.skip(f"Missing project-slug for case #{idx}; verify endpoint test data or config.yml.test_data.project-slug") + + endpoint = _build_endpoint(slug) + headers = {"Circle-Token": token} + + # No request body for GET; proceed to send the request + response = getattr(api_client, _METHOD)(endpoint, headers=headers) + + assert response.status_code == 200, f"[case #{idx}] Expected 200 OK, got {response.status_code} (scenario={entry.get('scenario','')})" + + validation = _validator.validate_schema_by_response(_ENDPOINT, _METHOD, "200", response) + assert validation.get("valid"), f"[case #{idx}] Response schema invalid: {validation}" + + +def test_get_flaky_tests_invalid_auth_default_error(api_client, merged_test_data): + """ + Negative: invalid API key should yield a non-2xx status and conform to the default error schema. + """ + data = merged_test_data(_endpoint_data_path) + cases = _extract_cases(data) + assert isinstance(cases, list) and len(cases) >= 1, "No test cases found for invalid auth test." + + for idx, entry in enumerate(cases, start=1): + slug = (entry.get("project-slug") or data.get("project-slug") or "").strip() + if not slug: + pytest.skip(f"Missing project-slug for case #{idx}; verify endpoint test data or config.yml.test_data.project-slug") + + endpoint = _build_endpoint(slug) + headers = {"Circle-Token": "invalid-token-for-testing"} + + response = getattr(api_client, _METHOD)(endpoint, headers=headers) + + assert not (200 <= response.status_code < 300), f"[case #{idx}] Expected non-2xx for invalid auth, got {response.status_code}" + # Validate against default error schema as defined by spec + validation = _validator.validate_schema_by_response(_ENDPOINT, _METHOD, "default", response) + assert validation.get("valid"), f"[case #{idx}] Default error schema validation failed: {validation}" + + +def test_get_flaky_tests_missing_auth_default_error(api_client, merged_test_data): + """ + Negative: missing API key should yield a non-2xx status and conform to the default error schema. + """ + data = merged_test_data(_endpoint_data_path) + cases = _extract_cases(data) + assert isinstance(cases, list) and len(cases) >= 1, "No test cases found for missing auth test." + + for idx, entry in enumerate(cases, start=1): + slug = (entry.get("project-slug") or data.get("project-slug") or "").strip() + if not slug: + pytest.skip(f"Missing project-slug for case #{idx}; verify endpoint test data or config.yml.test_data.project-slug") + + endpoint = _build_endpoint(slug) + + response = getattr(api_client, _METHOD)(endpoint) + + assert not (200 <= response.status_code < 300), f"[case #{idx}] Expected non-2xx for missing auth, got {response.status_code}" + # Validate against default error schema as defined by spec + validation = _validator.validate_schema_by_response(_ENDPOINT, _METHOD, "default", response) + assert validation.get("valid"), f"[case #{idx}] Default error schema validation failed: {validation}" diff --git a/tests/CIRCLECI_API/test_insights_project-slug_workflows_get.py b/tests/CIRCLECI_API/test_insights_project-slug_workflows_get.py new file mode 100644 index 00000000..1da41326 --- /dev/null +++ b/tests/CIRCLECI_API/test_insights_project-slug_workflows_get.py @@ -0,0 +1,272 @@ +# ********RoostGPT******** + +# Test generated by RoostGPT for test api-test-pytest-circleci using AI Type Open AI and AI Model gpt-5 +# +# Test file generated for /insights/{project-slug}/workflows_get for http method type GET +# RoostTestHash=a3d95b97e2 +# +# + +# ********RoostGPT******** +""" +Pytest API tests for: GET /insights/{project-slug}/workflows + +How to run: + - Ensure config.yml and api.json are present alongside conftest.py + - Place endpoint test data JSON file next to this test module + - Run: pytest -q +""" + +from pathlib import Path +from functools import lru_cache +from typing import Any, Dict, List, Tuple +from urllib.parse import quote + +import json +import pytest + +from validator import SwaggerSchemaValidator + + +# Module-level constants required before tests (no fixture calls here) +_ENDPOINT = "/insights/{project-slug}/workflows" +_METHOD = "get" # lowercase matching APIClient methods +_TEST_DATA_FILE = "insights_project-slug_workflows.json" +_here = Path(__file__).resolve().parent +_endpoint_data_path = _here / _TEST_DATA_FILE + + +@lru_cache(maxsize=1) +def _validator() -> SwaggerSchemaValidator: + spec_path = _here / "api.json" + return SwaggerSchemaValidator(str(spec_path)) + + +def _resolve_endpoint(project_slug: str) -> str: + # allowReserved for '/', keep slashes + encoded = quote(project_slug, safe="/") + return _ENDPOINT.replace("{project-slug}", encoded) + + +def _extract_cases(merged_data: Dict[str, Any]) -> List[Dict[str, Any]]: + """ + Extract list test cases from merged endpoint data. + Accepts common keys; returns empty list if not found. + """ + for key in ("cases", "tests", "entries", "items", "data"): + v = merged_data.get(key) + if isinstance(v, list): + return v + + # Fallback: if merged_data looks like a single-case dict, normalize to list + candidate_keys = {"project-slug", "page-token", "all-branches", "branch", "reporting-window", "statusCode", "scenario"} + if any(k in merged_data for k in candidate_keys): + return [merged_data] + return [] + + +def _build_query_params(entry: Dict[str, Any]) -> Dict[str, Any]: + qp: Dict[str, Any] = {} + for key in ("page-token", "all-branches", "branch", "reporting-window"): + if key in entry: + qp[key] = entry[key] + return qp + + +def _assert_validated_response(resp, expected_status: int, status_key_for_schema: str) -> None: + assert resp.status_code == expected_status, f"Unexpected status code: {resp.status_code}, body={getattr(resp, 'text', '')}" + result = _validator().validate_schema_by_response(_ENDPOINT, _METHOD, status_key_for_schema, resp) + assert result.get("valid", False), f"Response schema validation failed: {json.dumps(result, indent=2)}" + + +@pytest.mark.smoke +def test_smoke_get_workflow_metrics_success_required_only(api_client, get_config, merged_test_data): + """ + Smoke: Happy-path success using only required parameters (project-slug). + """ + data = merged_test_data(str(_endpoint_data_path)) + cases = _extract_cases(data) + + # Filter to cases with only required fields (project-slug + optional metadata fields) + allowed_non_input_keys = {"statusCode", "scenario"} + filtered = [] + for idx, entry in enumerate(cases): + keys = set(entry.keys()) + input_keys = keys - allowed_non_input_keys + if input_keys == {"project-slug"}: + filtered.append((idx, entry)) + + if not filtered: + pytest.skip("No smoke cases found with only required fields in endpoint test data") + + token = str(get_config("auth.api_key_header", "") or "") + if not token: + pytest.skip("auth.api_key_header is not configured; cannot perform authenticated success test") + + for idx, entry in filtered: + slug = entry.get("project-slug") or get_config("test_data.project-slug", None) + if not slug: + pytest.skip(f"Missing project-slug for smoke case index={idx}") + + endpoint = _resolve_endpoint(slug) + headers = {"Circle-Token": token} + expected_status = int(entry.get("statusCode", 200)) + + resp = api_client.get(endpoint, headers=headers, params={}) + _assert_validated_response(resp, expected_status, str(expected_status)) + + # Minimal content checks for 200 responses as per spec + if expected_status == 200: + try: + body = resp.json() + except Exception as e: + pytest.fail(f"Response is not valid JSON: {e}") + assert "items" in body and isinstance(body["items"], list), "Expected 'items' list in response body" + assert "next_page_token" in body, "Expected 'next_page_token' in response body" + + # Validate required fields for first item when present + if body["items"]: + item = body["items"][0] + for req_key in ("name", "metrics", "window_start", "window_end", "project_id"): + assert req_key in item, f"Missing required field in item: {req_key}" + metrics = item.get("metrics", {}) + assert isinstance(metrics, dict), "metrics must be an object" + dm = metrics.get("duration_metrics", {}) + for req_key in ("min", "mean", "median", "p95", "max", "standard_deviation"): + assert req_key in dm, f"Missing required field in duration_metrics: {req_key}" + + +def test_get_workflow_metrics_all_cases_with_valid_auth(api_client, get_config, merged_test_data): + """ + Iterate over all endpoint test data cases, applying optional query params when provided. + """ + data = merged_test_data(str(_endpoint_data_path)) + cases = _extract_cases(data) + if not cases: + pytest.skip("No endpoint test cases found") + + token = str(get_config("auth.api_key_header", "") or "") + if not token: + pytest.skip("auth.api_key_header is not configured; cannot perform authenticated tests") + + headers = {"Circle-Token": token} + + for idx, entry in enumerate(cases): + slug = entry.get("project-slug") or get_config("test_data.project-slug", None) + if not slug: + pytest.skip(f"Missing project-slug for case index={idx}") + + endpoint = _resolve_endpoint(slug) + params = _build_query_params(entry) + expected_status = int(entry.get("statusCode", 200)) + + resp = api_client.get(endpoint, headers=headers, params=params) + + # Validate against explicit status code if defined in spec; otherwise fallback to 'default' + status_key = str(expected_status) if expected_status == 200 else "default" + if status_key == "default": + assert not (200 <= resp.status_code < 300), f"Expected non-2xx for case {idx}, got {resp.status_code}" + _assert_validated_response(resp, resp.status_code if status_key == "default" else expected_status, status_key) + + +def test_get_workflow_metrics_missing_auth(api_client, get_config, merged_test_data): + """ + Missing authentication should produce a non-2xx 'default' error response. + """ + data = merged_test_data(str(_endpoint_data_path)) + cases = _extract_cases(data) + if not cases: + pytest.skip("No endpoint test cases found") + + entry = cases[0] + slug = entry.get("project-slug") or get_config("test_data.project-slug", None) + if not slug: + pytest.skip("Missing project-slug for missing-auth test") + + endpoint = _resolve_endpoint(slug) + + resp = api_client.get(endpoint, headers={}, params={}) + assert not (200 <= resp.status_code < 300), f"Expected non-2xx for missing auth, got {resp.status_code}" + result = _validator().validate_schema_by_response(_ENDPOINT, _METHOD, "default", resp) + assert result.get("valid", False), f"Default error response schema validation failed: {json.dumps(result, indent=2)}" + + +def test_get_workflow_metrics_invalid_auth(api_client, get_config, merged_test_data): + """ + Invalid token should produce a non-2xx 'default' error response. + """ + data = merged_test_data(str(_endpoint_data_path)) + cases = _extract_cases(data) + if not cases: + pytest.skip("No endpoint test cases found") + + entry = cases[0] + slug = entry.get("project-slug") or get_config("test_data.project-slug", None) + if not slug: + pytest.skip("Missing project-slug for invalid-auth test") + + endpoint = _resolve_endpoint(slug) + headers = {"Circle-Token": "invalid-token"} + + resp = api_client.get(endpoint, headers=headers, params={}) + assert not (200 <= resp.status_code < 300), f"Expected non-2xx for invalid auth, got {resp.status_code}" + result = _validator().validate_schema_by_response(_ENDPOINT, _METHOD, "default", resp) + assert result.get("valid", False), f"Default error response schema validation failed: {json.dumps(result, indent=2)}" + + +def test_get_workflow_metrics_valid_query_token_auth(api_client, get_config, merged_test_data): + """ + Valid auth via query parameter 'circle-token' when configured. + """ + token_q = str(get_config("auth.api_key_query", "") or "") + if not token_q: + pytest.skip("auth.api_key_query is not configured; skipping query token auth test") + + data = merged_test_data(str(_endpoint_data_path)) + cases = _extract_cases(data) + if not cases: + pytest.skip("No endpoint test cases found") + + entry = cases[0] + slug = entry.get("project-slug") or get_config("test_data.project-slug", None) + if not slug: + pytest.skip("Missing project-slug for query-auth test") + + endpoint = _resolve_endpoint(slug) + params = {"circle-token": token_q} + + resp = api_client.get(endpoint, headers={}, params=params) + if 200 <= resp.status_code < 300: + # Happy path validated against 200 response schema + _assert_validated_response(resp, 200, "200") + else: + # Some environments may not accept query token; still validate default error + result = _validator().validate_schema_by_response(_ENDPOINT, _METHOD, "default", resp) + assert result.get("valid", False), f"Default error response schema validation failed: {json.dumps(result, indent=2)}" + + +def test_get_workflow_metrics_invalid_page_token(api_client, get_config, merged_test_data): + """ + Negative test: invalid 'page-token' should return a non-2xx default error response when authenticated. + """ + token = str(get_config("auth.api_key_header", "") or "") + if not token: + pytest.skip("auth.api_key_header is not configured; cannot perform authenticated negative test") + + data = merged_test_data(str(_endpoint_data_path)) + cases = _extract_cases(data) + slug = None + if cases: + slug = cases[0].get("project-slug") + slug = slug or get_config("test_data.project-slug", None) + if not slug: + pytest.skip("Missing project-slug for invalid page-token test") + + endpoint = _resolve_endpoint(slug) + headers = {"Circle-Token": token} + params = {"page-token": "not-a-valid-page-token"} + + resp = api_client.get(endpoint, headers=headers, params=params) + assert not (200 <= resp.status_code < 300), f"Expected non-2xx for invalid page-token, got {resp.status_code}" + result = _validator().validate_schema_by_response(_ENDPOINT, _METHOD, "default", resp) + assert result.get("valid", False), f"Default error response schema validation failed: {json.dumps(result, indent=2)}" diff --git a/tests/CIRCLECI_API/test_insights_project-slug_workflows_workflow-name_get.py b/tests/CIRCLECI_API/test_insights_project-slug_workflows_workflow-name_get.py new file mode 100644 index 00000000..3ff5cfc9 --- /dev/null +++ b/tests/CIRCLECI_API/test_insights_project-slug_workflows_workflow-name_get.py @@ -0,0 +1,267 @@ +# ********RoostGPT******** + +# Test generated by RoostGPT for test api-test-pytest-circleci using AI Type Open AI and AI Model gpt-5 +# +# Test file generated for /insights/{project-slug}/workflows/{workflow-name}_get for http method type GET +# RoostTestHash=e7554c4ea6 +# +# + +# ********RoostGPT******** +""" +Pytest suite for CircleCI Insights API: GET /insights/{project-slug}/workflows/{workflow-name} + +How to run: + - Ensure config.yml and api.json are present next to this test. + - Place endpoint test data JSON at the same directory as this test file. + - Run: pytest -q +""" + +from pathlib import Path +from typing import Any, Dict, Iterable, List, Tuple, Optional + +import pytest + +from validator import SwaggerSchemaValidator + +# Module-level constants (do not call fixtures here) +_ENDPOINT = "/insights/{project-slug}/workflows/{workflow-name}" +_METHOD = "get" # lowercase matching APIClient methods +_TEST_DATA_FILE = "insights_project-slug_workflows_workflow-name.json" +_here = Path(__file__).resolve().parent +_endpoint_data_path = _here / _TEST_DATA_FILE + +# Initialize validator against the local OpenAPI spec file +_validator_spec_path = str(_here / "api.json") +_validator = SwaggerSchemaValidator(_validator_spec_path) + + +# --------------------------- +# Helpers (no fixture definitions) +# --------------------------- + +_OPTIONAL_QUERY_KEYS = ("all-branches", "branch", "page-token", "start-date", "end-date") + + +def _build_endpoint(project_slug: str, workflow_name: str) -> str: + """ + Construct endpoint path by substituting path parameters. + project_slug may contain slashes by design and should remain unescaped + given the API path structure. + """ + return ( + _ENDPOINT + .replace("{project-slug}", project_slug) + .replace("{workflow-name}", workflow_name) + ) + + +def _bool_to_query(v: Any) -> Any: + """ + Convert booleans to lowercase 'true'/'false' strings for query parameters. + """ + if isinstance(v, bool): + return "true" if v else "false" + return v + + +def _extract_cases(merged: Dict[str, Any]) -> List[Dict[str, Any]]: + """ + Obtain a list of test case dicts from merged test data. + The endpoint JSON is expected to provide a list under 'cases'. + If not present, fallback to 'entries' and finally to empty list. + """ + cases = merged.get("cases") + if isinstance(cases, list): + return [c for c in cases if isinstance(c, dict)] + # Fallbacks to be defensive if a different key is used + entries = merged.get("entries") + if isinstance(entries, list): + return [c for c in entries if isinstance(c, dict)] + # Final fallback: if a single case-like mapping is given at root (not recommended) + # do not treat root merged mapping as a case list to avoid mixing config values. + return [] + + +def _required_path_params_for_case( + case: Dict[str, Any], get_config +) -> Tuple[str, str]: + """ + Resolve required path parameters, preferring endpoint case overrides + then falling back to config.yml test_data values. + """ + project_slug = case.get("project-slug") or get_config("test_data.project-slug", "") + workflow_name = case.get("workflow-name") or get_config("test_data.workflow-name", "") + if not project_slug or not workflow_name: + raise pytest.UsageError( + "Missing required path params 'project-slug' and/or 'workflow-name'. " + "Provide them in endpoint test data or config.yml.test_data." + ) + return str(project_slug), str(workflow_name) + + +def _query_from_case(case: Dict[str, Any]) -> Dict[str, Any]: + """ + Extract optional query params from case dict and coerce as needed. + Missing optional fields are simply omitted. + """ + q: Dict[str, Any] = {} + for key in _OPTIONAL_QUERY_KEYS: + if key in case: + val = case[key] + q[key] = _bool_to_query(val) + return q + + +def _valid_token_or_skip(get_config) -> str: + """ + Retrieve a token for header-based auth. Skip if not provided. + """ + token = get_config("auth.api_key_header", "").strip() + if not token: + pytest.skip("No valid API key provided in config.yml under auth.api_key_header") + return token + + +def _is_smoke_case(case: Dict[str, Any]) -> bool: + """ + A smoke (happy-path) case uses only required fields (path params) + and does not specify any optional query parameters. + """ + return not any(k in case for k in _OPTIONAL_QUERY_KEYS) + + +def _assert_200_and_validate(response, message: str = ""): + """ + Assert 200 OK and validate response body against the OpenAPI 200 schema. + """ + assert response.status_code == 200, f"Expected 200 OK. {message} Got: {response.status_code}, Body: {response.text}" + result = _validator.validate_schema_by_response(_ENDPOINT, _METHOD, "200", response) + assert result.get("valid") is True, f"Schema validation failed for 200 response: {result}" + + +def _assert_default_error_and_validate(response, message: str = ""): + """ + Assert non-2xx and validate response body against the OpenAPI 'default' error schema. + """ + assert not (200 <= response.status_code < 300), f"Expected non-2xx error. {message} Got: {response.status_code}, Body: {response.text}" + result = _validator.validate_schema_by_response(_ENDPOINT, _METHOD, "default", response) + assert result.get("valid") is True, f"Schema validation failed for default error response: {result}" + + +# --------------------------- +# Tests +# --------------------------- + +@pytest.mark.smoke +def test_get_project_workflow_runs_smoke(api_client, merged_test_data, get_config): + """ + Smoke: happy-path success using only required parameters (path params). + Iterates over cases that only provide required fields. + """ + data = merged_test_data(str(_endpoint_data_path)) + cases = _extract_cases(data) + + # Filter only smoke cases (no optional query params present) + smoke_cases = [c for c in cases if _is_smoke_case(c)] + + if not smoke_cases: + pytest.skip("No smoke cases found in endpoint test data.") + + token = _valid_token_or_skip(get_config) + + for idx, case in enumerate(smoke_cases): + project_slug, workflow_name = _required_path_params_for_case(case, get_config) + endpoint = _build_endpoint(project_slug, workflow_name) + + headers = {"Circle-Token": token} + params = {} # smoke => only required path params + + # Note: Request has no body schema to validate. Proceed to call. + response = api_client.get(endpoint, headers=headers, params=params) + case_msg = f"(smoke case #{idx+1} - {case.get('scenario','unspecified')}) " + _assert_200_and_validate(response, case_msg) + + +def test_get_project_workflow_runs_success_cases(api_client, merged_test_data, get_config): + """ + Success scenarios including optional query parameters. + Iterates over all provided cases; non-smoke cases will exercise optional query params. + """ + data = merged_test_data(str(_endpoint_data_path)) + cases = _extract_cases(data) + if not cases: + pytest.skip("No endpoint cases found to execute.") + + token = _valid_token_or_skip(get_config) + + for idx, case in enumerate(cases): + # Expected status code from case; fallback to 200 if explicitly specified in data + expected_status = int(case.get("statusCode", 200)) + project_slug, workflow_name = _required_path_params_for_case(case, get_config) + endpoint = _build_endpoint(project_slug, workflow_name) + + headers = {"Circle-Token": token} + params = _query_from_case(case) + + response = api_client.get(endpoint, headers=headers, params=params) + case_msg = f"(case #{idx+1} - {case.get('scenario','unspecified')}) " + + # Validate expected status and schema + assert response.status_code == expected_status, f"Expected {expected_status}. {case_msg} Got: {response.status_code}, Body: {response.text}" + result = _validator.validate_schema_by_response(_ENDPOINT, _METHOD, str(expected_status), response) + assert result.get("valid") is True, f"Schema validation failed for {expected_status} response: {result}" + + +def test_get_project_workflow_runs_auth_errors(api_client, merged_test_data, get_config): + """ + Security tests for invalid and missing authentication. + Uses required path params from data/config and asserts default error schema for non-2xx responses. + """ + data = merged_test_data(str(_endpoint_data_path)) + cases = _extract_cases(data) + # Choose first available case for path params + base_case = cases[0] if cases else {} + project_slug, workflow_name = _required_path_params_for_case(base_case, get_config) + endpoint = _build_endpoint(project_slug, workflow_name) + + # 1) Invalid token + invalid_headers = {"Circle-Token": "invalid_or_malformed_token"} + resp_invalid = api_client.get(endpoint, headers=invalid_headers, params={}) + _assert_default_error_and_validate(resp_invalid, "Invalid auth: ") + + # 2) Missing token + resp_missing = api_client.get(endpoint, headers={}, params={}) + _assert_default_error_and_validate(resp_missing, "Missing auth: ") + + +def test_get_project_workflow_runs_parameter_errors(api_client, merged_test_data, get_config): + """ + Negative and boundary tests for query parameters: + - both all-branches and branch provided (mutually exclusive) + - end-date provided without start-date + Valid auth is required to focus on parameter error handling. + """ + token = _valid_token_or_skip(get_config) + + data = merged_test_data(str(_endpoint_data_path)) + cases = _extract_cases(data) + base_case = cases[0] if cases else {} + project_slug, workflow_name = _required_path_params_for_case(base_case, get_config) + endpoint = _build_endpoint(project_slug, workflow_name) + headers = {"Circle-Token": token} + + # Mutually exclusive parameters provided together + params_conflict = { + "all-branches": "true", + "branch": "main", + } + resp_conflict = api_client.get(endpoint, headers=headers, params=params_conflict) + _assert_default_error_and_validate(resp_conflict, "Conflicting params (all-branches + branch): ") + + # end-date provided without start-date + params_end_only = { + "end-date": "2025-01-15T00:00:00Z", + } + resp_end_only = api_client.get(endpoint, headers=headers, params=params_end_only) + _assert_default_error_and_validate(resp_end_only, "end-date without start-date: ") diff --git a/tests/CIRCLECI_API/test_insights_project-slug_workflows_workflow-name_jobs_get.py b/tests/CIRCLECI_API/test_insights_project-slug_workflows_workflow-name_jobs_get.py new file mode 100644 index 00000000..83a53976 --- /dev/null +++ b/tests/CIRCLECI_API/test_insights_project-slug_workflows_workflow-name_jobs_get.py @@ -0,0 +1,212 @@ +# ********RoostGPT******** + +# Test generated by RoostGPT for test api-test-pytest-circleci using AI Type Open AI and AI Model gpt-5 +# +# Test file generated for /insights/{project-slug}/workflows/{workflow-name}/jobs_get for http method type GET +# RoostTestHash=0b14551fdb +# +# + +# ********RoostGPT******** +""" +pytest tests for CircleCI Insights: project workflow job metrics endpoint. + +How to run: + - Ensure config.yml and api.json are present alongside conftest.py + - Place endpoint test data JSON file next to this test (see _TEST_DATA_FILE) + - Run: pytest -q +""" +from pathlib import Path +from typing import Dict, Any, List, Optional, Tuple +import json +import urllib.parse + +import pytest + +from validator import SwaggerSchemaValidator + + +# Required module-level variables +_ENDPOINT = "/insights/{project-slug}/workflows/{workflow-name}/jobs" +_METHOD = "get" +_TEST_DATA_FILE = "endpoint_test_data.json" +_here = Path(__file__).resolve().parent +_endpoint_data_path = _here / _TEST_DATA_FILE + +# Validator initialized once per module for efficiency +_validator = SwaggerSchemaValidator("api.json") + + +def _fmt_path(project_slug: str, workflow_name: str) -> str: + # Preserve slashes in project slug as per allowReserved while percent-encoding other characters + # Workflow name typically simple, but still encode safely (spaces, etc.) without encoding slashes + ps = urllib.parse.quote(project_slug, safe="/:@-._~") + wn = urllib.parse.quote(workflow_name, safe="-._~") + return _ENDPOINT.replace("{project-slug}", ps).replace("{workflow-name}", wn) + + +def _extract_cases_from_merged(merged: Dict[str, Any]) -> List[Dict[str, Any]]: + # Prefer known keys for case lists; allow flexible integration if merged data nests cases + if isinstance(merged, dict): + for key in ("cases", "test_cases", "entries"): + v = merged.get(key) + if isinstance(v, list) and all(isinstance(i, dict) for i in v): + return v + return [] + + +def _load_endpoint_cases_flex(path: Path, merged_data: Dict[str, Any]) -> List[Dict[str, Any]]: + """ + Flexible case loader: + 1) Try extracting list from merged_data under common keys (cases/test_cases/entries) + 2) If not found, attempt reading the JSON file directly if it contains a list + 3) Otherwise return empty + """ + cases = _extract_cases_from_merged(merged_data) + if cases: + return cases + + # Fallback to reading file when endpoint JSON is an array per instructions + try: + with path.open("r", encoding="utf-8") as f: + raw = json.load(f) + if isinstance(raw, list) and all(isinstance(i, dict) for i in raw): + return raw + except Exception: + pass + + return [] + + +def _build_headers(get_config, use_auth: bool = True, override_token: Optional[str] = None) -> Dict[str, str]: + headers: Dict[str, str] = {} + if use_auth: + token = override_token if override_token is not None else get_config("auth.api_key_header", "") + if token: + headers["Circle-Token"] = str(token) + return headers + + +def _build_query(case: Dict[str, Any]) -> Dict[str, Any]: + # Only include optional query params if present in the case + qp: Dict[str, Any] = {} + for key in ("page-token", "all-branches", "branch", "reporting-window", "job-name"): + if key in case and case[key] not in (None, ""): + qp[key] = case[key] + return qp + + +def _validate_response_schema(resp, expected_status: int) -> None: + status_key = str(expected_status) if 200 <= expected_status < 300 else "default" + result = _validator.validate_schema_by_response(_ENDPOINT, _METHOD, status_key, resp) + assert result.get("valid") is True, f"Schema validation failed: {result}" + + +@pytest.mark.smoke +def test_get_workflow_job_metrics_smoke(api_client, get_config, merged_test_data): + # Load merged data; tolerate JSON array endpoint data by flexible loader + try: + merged = merged_test_data(str(_endpoint_data_path)) + except Exception as e: + pytest.skip(f"Unable to load endpoint test data via merged_test_data: {e}") + + cases = _load_endpoint_cases_flex(_endpoint_data_path, merged) + if not cases: + pytest.skip("No endpoint cases available in merged data or raw file") + + # Choose a minimal (required-only) case for the smoke test + optional_keys = {"page-token", "all-branches", "branch", "reporting-window", "job-name"} + minimal_case = None + for c in cases: + if isinstance(c, dict) and not (optional_keys & set(c.keys())): + minimal_case = c + break + if minimal_case is None: + # Fallback to first case; we will still send only required fields + minimal_case = cases[0] + + project_slug = minimal_case.get("project-slug") or get_config("test_data.project-slug", "") + workflow_name = minimal_case.get("workflow-name") or get_config("test_data.workflow-name", "") + if not project_slug or not workflow_name: + pytest.skip("Required path parameters are not provided in test data or config") + + endpoint = _fmt_path(project_slug, workflow_name) + headers = _build_headers(get_config, use_auth=True) + if "Circle-Token" not in headers or not headers["Circle-Token"]: + pytest.skip("Valid API token not configured in config.yml auth.api_key_header") + + # Only required path params; no query params for smoke + expected_status = int(minimal_case.get("statusCode", 200)) + resp = api_client.get(endpoint, headers=headers, params={}) + assert resp is not None, "No response received from API" + assert resp.status_code == expected_status, f"Expected {expected_status}, got {resp.status_code}. Body: {resp.text}" + + _validate_response_schema(resp, expected_status) + + +def test_get_workflow_job_metrics_cases(api_client, get_config, merged_test_data): + # Load merged data; tolerate JSON array endpoint data by flexible loader + try: + merged = merged_test_data(str(_endpoint_data_path)) + except Exception as e: + pytest.skip(f"Unable to load endpoint test data via merged_test_data: {e}") + + cases = _load_endpoint_cases_flex(_endpoint_data_path, merged) + if not cases: + pytest.skip("No endpoint cases available in merged data or raw file") + + # Use valid auth for all cases in this test + headers = _build_headers(get_config, use_auth=True) + if "Circle-Token" not in headers or not headers["Circle-Token"]: + pytest.skip("Valid API token not configured in config.yml auth.api_key_header") + + for idx, case in enumerate(cases): + project_slug = case.get("project-slug") or get_config("test_data.project-slug", "") + workflow_name = case.get("workflow-name") or get_config("test_data.workflow-name", "") + if not project_slug or not workflow_name: + pytest.skip(f"Missing required path parameters for case index {idx}") + + endpoint = _fmt_path(project_slug, workflow_name) + params = _build_query(case) + expected_status = int(case.get("statusCode", 200)) + + resp = api_client.get(endpoint, headers=headers, params=params) + assert resp is not None, f"[Case {idx}] No response received from API" + assert resp.status_code == expected_status, ( + f"[Case {idx}] Expected {expected_status}, got {resp.status_code}. " + f"Scenario: {case.get('scenario')}; Body: {resp.text}" + ) + _validate_response_schema(resp, expected_status) + + +@pytest.mark.parametrize("auth_mode", ["invalid", "missing"]) +def test_get_workflow_job_metrics_auth_errors(api_client, get_config, merged_test_data, auth_mode): + # Load any case to obtain required path params, falling back to config if needed + try: + merged = merged_test_data(str(_endpoint_data_path)) + except Exception: + merged = {} + + cases = _load_endpoint_cases_flex(_endpoint_data_path, merged) + base_case = cases[0] if cases else {} + + project_slug = base_case.get("project-slug") or get_config("test_data.project-slug", "") + workflow_name = base_case.get("workflow-name") or get_config("test_data.workflow-name", "") + if not project_slug or not workflow_name: + pytest.skip("Required path parameters not found for auth error test") + + endpoint = _fmt_path(project_slug, workflow_name) + + if auth_mode == "invalid": + headers = _build_headers(get_config, use_auth=True, override_token="invalid-token-value") + else: + headers = _build_headers(get_config, use_auth=False) + + resp = api_client.get(endpoint, headers=headers, params={}) + assert resp is not None, "No response received from API" + assert not (200 <= resp.status_code < 300), f"Expected non-2xx for {auth_mode} auth, got {resp.status_code}" + + # Validate against the default error schema block + result = _validator.validate_schema_by_response(_ENDPOINT, _METHOD, "default", resp) + # If content type is not JSON or schema missing, validator may return valid without schema; this is acceptable + assert result.get("valid") is True, f"Default error schema validation failed: {result}" diff --git a/tests/CIRCLECI_API/test_insights_project-slug_workflows_workflow-name_summary_get.py b/tests/CIRCLECI_API/test_insights_project-slug_workflows_workflow-name_summary_get.py new file mode 100644 index 00000000..0ffe136b --- /dev/null +++ b/tests/CIRCLECI_API/test_insights_project-slug_workflows_workflow-name_summary_get.py @@ -0,0 +1,214 @@ +# ********RoostGPT******** + +# Test generated by RoostGPT for test api-test-pytest-circleci using AI Type Open AI and AI Model gpt-5 +# +# Test file generated for /insights/{project-slug}/workflows/{workflow-name}/summary_get for http method type GET +# RoostTestHash=b2014120ff +# +# + +# ********RoostGPT******** +""" +Pytest API tests for CircleCI Insights: Workflow Summary endpoint. + +How to run: + - Ensure config.yml is populated with api.host and credentials under auth.* + - Place api.json (OpenAPI spec) alongside project root or accessible path + - Ensure the endpoint-level test data file exists at _endpoint_data_path + - Run: pytest -q +""" + +from pathlib import Path +import json +from typing import Dict, Any, List, Optional + +import pytest + +from validator import SwaggerSchemaValidator + + +# Module-level constants required before tests (no fixture calls here) +_ENDPOINT = "/insights/{project-slug}/workflows/{workflow-name}/summary" +_METHOD = "get" +_TEST_DATA_FILE = "insights_project-slug_workflows_workflow-name_summ.json" +_here = Path(__file__).resolve().parent +_endpoint_data_path = _here / _TEST_DATA_FILE + + +def _format_path(endpoint_template: str, project_slug: str, workflow_name: str) -> str: + """ + Internal helper to format the OpenAPI templated path with actual values. + """ + return ( + endpoint_template.replace("{project-slug}", project_slug) + .replace("{workflow-name}", workflow_name) + ) + + +def _load_cases_list(path: Path) -> List[Dict[str, Any]]: + """ + Load the endpoint test cases from the JSON file which is expected to be a list. + """ + with path.open("r", encoding="utf-8") as f: + data = json.load(f) + if not isinstance(data, list): + raise AssertionError(f"Endpoint test data must be a list of cases at: {path}") + return data + + +def _build_query_params(entry: Dict[str, Any]) -> Dict[str, Any]: + """ + Build query parameters ensuring mutual exclusivity between 'branch' and 'all-branches'. + """ + params: Dict[str, Any] = {} + branch = entry.get("branch") + all_branches = entry.get("all-branches") + if branch: + params["branch"] = branch + elif all_branches is not None: + params["all-branches"] = all_branches + return params + + +@pytest.mark.smoke +def test_get_workflow_summary_success_smoke(api_client, get_config, merged_test_data): + """ + Happy-path tests using required fields only (path params), driven by ENDPOINT_TEST_DATA. + Endpoint: GET /insights/{project-slug}/workflows/{workflow-name}/summary + """ + # Attempt to merge config test_data with endpoint JSON (as mandated). + # The endpoint JSON may be a list (per provided content). We defensively handle that. + try: + _ = merged_test_data(str(_endpoint_data_path)) + except Exception: + # Proceed even if merging isn't applicable due to list structure. + pass + + # Load list of test cases + cases = _load_cases_list(_endpoint_data_path) + + # Auth header from config; skip if not configured + token: str = get_config("auth.api_key_header", "") + if not token: + pytest.skip("auth.api_key_header is not set in config.yml (Circle-Token).") + + validator = SwaggerSchemaValidator("api.json") + + for idx, entry in enumerate(cases, start=1): + # Resolve required path params with entry taking precedence over config defaults + project_slug: str = entry.get("project-slug") or get_config("test_data.project-slug", "") + workflow_name: str = entry.get("workflow-name") or get_config("test_data.workflow-name", "") + + if not project_slug or not workflow_name: + pytest.skip(f"Missing required path params for case #{idx}: project-slug/workflow-name.") + + path = _format_path(_ENDPOINT, project_slug, workflow_name) + params = _build_query_params(entry) + + # Validate request: no body for GET; path/query types are simple and checked at server + # Send request with valid auth + headers = {"Circle-Token": token} + response = api_client.get(path, headers=headers, params=params) + + expected_status = int(entry.get("statusCode", 200)) + assert response.status_code == expected_status, ( + f"Expected HTTP {expected_status} for case #{idx} ({entry.get('scenario','')}); " + f"got {response.status_code}. URL={path} params={params}" + ) + + # Validate response schema using the concrete status code defined in spec (200) + res = validator.validate_schema_by_response(_ENDPOINT, _METHOD, str(expected_status), response) + assert res.get("valid"), f"Schema validation failed for case #{idx}: {res}" + + +def test_get_workflow_summary_auth_errors(api_client, get_config, merged_test_data): + """ + Auth error scenarios: invalid and missing token. + Validated against the 'default' error response schema. + """ + # Attempt mandated merge call; tolerate list-based endpoint data + try: + _ = merged_test_data(str(_endpoint_data_path)) + except Exception: + pass + + cases = _load_cases_list(_endpoint_data_path) + + token: str = get_config("auth.api_key_header", "") + if not token: + pytest.skip("auth.api_key_header is not set in config.yml (Circle-Token).") + + validator = SwaggerSchemaValidator("api.json") + + for idx, entry in enumerate(cases, start=1): + project_slug: str = entry.get("project-slug") or get_config("test_data.project-slug", "") + workflow_name: str = entry.get("workflow-name") or get_config("test_data.workflow-name", "") + + if not project_slug or not workflow_name: + pytest.skip(f"Missing required path params for case #{idx} (auth error tests).") + + path = _format_path(_ENDPOINT, project_slug, workflow_name) + params = _build_query_params(entry) + + # Invalid token + bad_headers = {"Circle-Token": "invalid-token-value"} + bad_resp = api_client.get(path, headers=bad_headers, params=params) + assert not (200 <= bad_resp.status_code < 300), ( + f"Expected non-2xx for invalid auth in case #{idx}; got {bad_resp.status_code}" + ) + res_bad = validator.validate_schema_by_response(_ENDPOINT, _METHOD, "default", bad_resp) + assert res_bad.get("valid"), f"Default error schema invalid (invalid token) for case #{idx}: {res_bad}" + + # Missing token + noauth_resp = api_client.get(path, headers={}, params=params) + assert not (200 <= noauth_resp.status_code < 300), ( + f"Expected non-2xx for missing auth in case #{idx}; got {noauth_resp.status_code}" + ) + res_noauth = validator.validate_schema_by_response(_ENDPOINT, _METHOD, "default", noauth_resp) + assert res_noauth.get("valid"), f"Default error schema invalid (missing token) for case #{idx}: {res_noauth}" + + +def test_get_workflow_summary_negative_params(api_client, get_config): + """ + Negative parameter scenarios: conflicting query params, invalid types, and nonexistent resources. + Validated against the 'default' error response schema. + """ + token: str = get_config("auth.api_key_header", "") + if not token: + pytest.skip("auth.api_key_header is not set in config.yml (Circle-Token).") + + project_slug: str = get_config("test_data.project-slug", "") + workflow_name: str = get_config("test_data.workflow-name", "") + if not project_slug or not workflow_name: + pytest.skip("Missing required test_data.project-slug or test_data.workflow-name in config.yml") + + validator = SwaggerSchemaValidator("api.json") + path = _format_path(_ENDPOINT, project_slug, workflow_name) + + # 1) Both branch and all-branches provided (mutually exclusive by description) + headers = {"Circle-Token": token} + params_conflict = {"branch": "main", "all-branches": True} + resp_conflict = api_client.get(path, headers=headers, params=params_conflict) + assert not (200 <= resp_conflict.status_code < 300), ( + f"Expected non-2xx for conflicting params; got {resp_conflict.status_code}" + ) + res_conflict = validator.validate_schema_by_response(_ENDPOINT, _METHOD, "default", resp_conflict) + assert res_conflict.get("valid"), f"Default error schema invalid (conflicting params): {res_conflict}" + + # 2) Invalid type for all-branches (expects boolean) + params_bad_type = {"all-branches": "not-a-boolean"} + resp_bad_type = api_client.get(path, headers=headers, params=params_bad_type) + assert not (200 <= resp_bad_type.status_code < 300), ( + f"Expected non-2xx for invalid param type; got {resp_bad_type.status_code}" + ) + res_bad_type = validator.validate_schema_by_response(_ENDPOINT, _METHOD, "default", resp_bad_type) + assert res_bad_type.get("valid"), f"Default error schema invalid (bad type): {res_bad_type}" + + # 3) Nonexistent workflow name to simulate not found or forbidden + invalid_path = _format_path(_ENDPOINT, project_slug, f"{workflow_name}-nonexistent") + resp_not_found = api_client.get(invalid_path, headers=headers, params={}) + assert not (200 <= resp_not_found.status_code < 300), ( + f"Expected non-2xx for nonexistent workflow; got {resp_not_found.status_code}" + ) + res_not_found = validator.validate_schema_by_response(_ENDPOINT, _METHOD, "default", resp_not_found) + assert res_not_found.get("valid"), f"Default error schema invalid (not found): {res_not_found}" diff --git a/tests/CIRCLECI_API/test_insights_time-series_project-slug_workflows_workflow-name_jobs_get.py b/tests/CIRCLECI_API/test_insights_time-series_project-slug_workflows_workflow-name_jobs_get.py new file mode 100644 index 00000000..cd3756e5 --- /dev/null +++ b/tests/CIRCLECI_API/test_insights_time-series_project-slug_workflows_workflow-name_jobs_get.py @@ -0,0 +1,234 @@ +# ********RoostGPT******** + +# Test generated by RoostGPT for test api-test-pytest-circleci using AI Type Open AI and AI Model gpt-5 +# +# Test file generated for /insights/time-series/{project-slug}/workflows/{workflow-name}/jobs_get for http method type GET +# RoostTestHash=3f5fbf9535 +# +# + +# ********RoostGPT******** +""" +Pytest suite for CircleCI Insights Timeseries Jobs endpoint. + +How to run: + - Ensure config.yml and api.json are present alongside conftest.py. + - Place endpoint test data JSON at the same directory with filename set in _TEST_DATA_FILE. + - Run: pytest -q +""" + +from pathlib import Path +from typing import Dict, Any, Iterable, Tuple, Optional +import pytest + +from validator import SwaggerSchemaValidator + +# Module-level required variables +_ENDPOINT = "/insights/time-series/{project-slug}/workflows/{workflow-name}/jobs" +_METHOD = "get" +_TEST_DATA_FILE = "insights_time-series_project-slug_workflows_workfl.json" +_here = Path(__file__).resolve().parent +_endpoint_data_path = _here / _TEST_DATA_FILE + +# Initialize validator for the OpenAPI specification +_validator = SwaggerSchemaValidator(str((_here / "api.json").resolve())) + + +def _build_endpoint(project_slug: str, workflow_name: str) -> str: + """ + Substitute path parameters into the endpoint template. + Note: project-slug may include slashes and is allowed as-is (allowReserved). + """ + return ( + _ENDPOINT + .replace("{project-slug}", str(project_slug)) + .replace("{workflow-name}", str(workflow_name)) + ) + + +def _extract_cases(merged: Dict[str, Any]) -> Iterable[Dict[str, Any]]: + """ + Extract iterable list of test entries from merged test data. + Supports flexible keys: 'cases', 'scenarios', 'tests', 'entries'. + If none found, yield a single empty dict to allow downstream defaults via config.yml. + """ + for key in ("cases", "scenarios", "tests", "entries"): + if isinstance(merged.get(key), list): + return merged[key] + # If endpoint JSON didn't provide list entries, return a single default case + # allowing fallback to config.yml test_data values + return [dict()] + + +def _resolve_path_params(case: Dict[str, Any], merged: Dict[str, Any], get_config) -> Tuple[str, str]: + """ + Resolve required path parameters for the endpoint from: + 1) case overrides (endpoint JSON) + 2) merged top-level values (from config.yml.test_data merged with endpoint JSON) + 3) config.yml.test_data fallback via get_config + """ + pslug = case.get("project-slug") or merged.get("project-slug") or get_config("test_data.project-slug", "") + wname = case.get("workflow-name") or merged.get("workflow-name") or get_config("test_data.workflow-name", "") + return str(pslug), str(wname) + + +def _resolve_query_params(case: Dict[str, Any]) -> Dict[str, Any]: + """ + Build query parameters for optional inputs if present in the test case. + Only include keys when provided by the test entry. + """ + qp: Dict[str, Any] = {} + for key in ("branch", "granularity", "start-date", "end-date"): + if key in case and case.get(key) not in (None, ""): + qp[key] = case[key] + return qp + + +def _auth_header_valid(get_config) -> Optional[Dict[str, str]]: + """ + Construct valid auth header from config. Returns None if token empty. + """ + token = get_config("auth.api_key_header", "") or "" + token = str(token).strip() + if not token: + return None + return {"Circle-Token": token} + + +def _auth_header_invalid() -> Dict[str, str]: + """ + Hardcoded invalid token for negative auth testing. + """ + return {"Circle-Token": "invalid-token-for-testing"} + + +def _validate_response_schema(endpoint: str, method: str, status: int, response) -> None: + """ + Validate response against OpenAPI schema using validator. + Uses "200" for success, "default" for non-2xx error responses as defined by the spec. + """ + status_key = "200" if 200 <= status < 300 else "default" + result = _validator.validate_schema_by_response(endpoint, method, status_key, response) + assert result.get("valid") is True, f"Schema validation failed: {result}" + + +@pytest.mark.smoke +def test_get_job_timeseries_smoke_required_only(api_client, get_config, merged_test_data): + """ + Smoke: required-only parameters using endpoint test data entries. + """ + merged = merged_test_data(_endpoint_data_path) + cases = _extract_cases(merged) + + headers_valid = _auth_header_valid(get_config) + if not headers_valid: + pytest.skip("Valid API token not provided in config.yml (auth.api_key_header)") + + for idx, case in enumerate(cases): + project_slug, workflow_name = _resolve_path_params(case, merged, get_config) + assert project_slug and workflow_name, f"Missing required path params for case index {idx}" + + endpoint = _build_endpoint(project_slug, workflow_name) + + # Validate request payloads: for GET, no JSON body to validate. + + resp = api_client.get(endpoint, headers=headers_valid, params=None) + expected_status = int(case.get("statusCode", 200)) + assert resp.status_code == expected_status, f"Unexpected HTTP {resp.status_code} for case index {idx}; expected {expected_status}" + + _validate_response_schema(_ENDPOINT, _METHOD, resp.status_code, resp) + + +def test_get_job_timeseries_success_with_optional_params(api_client, get_config, merged_test_data): + """ + Success scenarios with optional query params taken from endpoint test data entries. + """ + merged = merged_test_data(_endpoint_data_path) + cases = _extract_cases(merged) + + headers_valid = _auth_header_valid(get_config) + if not headers_valid: + pytest.skip("Valid API token not provided in config.yml (auth.api_key_header)") + + for idx, case in enumerate(cases): + project_slug, workflow_name = _resolve_path_params(case, merged, get_config) + assert project_slug and workflow_name, f"Missing required path params for case index {idx}" + + endpoint = _build_endpoint(project_slug, workflow_name) + params = _resolve_query_params(case) + + resp = api_client.get(endpoint, headers=headers_valid, params=params if params else None) + expected_status = int(case.get("statusCode", 200)) + assert resp.status_code == expected_status, f"Unexpected HTTP {resp.status_code} for case index {idx}; expected {expected_status}" + + _validate_response_schema(_ENDPOINT, _METHOD, resp.status_code, resp) + + +def test_get_job_timeseries_auth_invalid(api_client, get_config, merged_test_data): + """ + Invalid authentication: expect non-2xx and validate against 'default' response schema. + """ + merged = merged_test_data(_endpoint_data_path) + cases = _extract_cases(merged) + + headers_invalid = _auth_header_invalid() + + for idx, case in enumerate(cases): + project_slug, workflow_name = _resolve_path_params(case, merged, get_config) + assert project_slug and workflow_name, f"Missing required path params for case index {idx}" + + endpoint = _build_endpoint(project_slug, workflow_name) + params = _resolve_query_params(case) + + resp = api_client.get(endpoint, headers=headers_invalid, params=params if params else None) + assert not (200 <= resp.status_code < 300), f"Expected auth error (non-2xx) for invalid token; got {resp.status_code} for case index {idx}" + + _validate_response_schema(_ENDPOINT, _METHOD, resp.status_code, resp) + + +def test_get_job_timeseries_auth_missing(api_client, get_config, merged_test_data): + """ + Missing authentication: expect non-2xx and validate against 'default' response schema. + """ + merged = merged_test_data(_endpoint_data_path) + cases = _extract_cases(merged) + + for idx, case in enumerate(cases): + project_slug, workflow_name = _resolve_path_params(case, merged, get_config) + assert project_slug and workflow_name, f"Missing required path params for case index {idx}" + + endpoint = _build_endpoint(project_slug, workflow_name) + params = _resolve_query_params(case) + + resp = api_client.get(endpoint, headers=None, params=params if params else None) + assert not (200 <= resp.status_code < 300), f"Expected auth error (non-2xx) for missing token; got {resp.status_code} for case index {idx}" + + _validate_response_schema(_ENDPOINT, _METHOD, resp.status_code, resp) + + +def test_get_job_timeseries_negative_invalid_granularity(api_client, get_config, merged_test_data): + """ + Negative scenario: invalid granularity value should yield non-2xx (validated against 'default'). + """ + merged = merged_test_data(_endpoint_data_path) + cases = _extract_cases(merged) + + headers_valid = _auth_header_valid(get_config) + if not headers_valid: + pytest.skip("Valid API token not provided in config.yml (auth.api_key_header)") + + for idx, case in enumerate(cases): + project_slug, workflow_name = _resolve_path_params(case, merged, get_config) + assert project_slug and workflow_name, f"Missing required path params for case index {idx}" + + endpoint = _build_endpoint(project_slug, workflow_name) + + # Start with any provided optional params, then override granularity with invalid value + params = _resolve_query_params(case) + params = dict(params) if params else {} + params["granularity"] = "not-a-valid-granularity" + + resp = api_client.get(endpoint, headers=headers_valid, params=params) + assert not (200 <= resp.status_code < 300), f"Expected non-2xx for invalid granularity; got {resp.status_code} for case index {idx}" + + _validate_response_schema(_ENDPOINT, _METHOD, resp.status_code, resp) diff --git a/tests/CIRCLECI_API/validator.py b/tests/CIRCLECI_API/validator.py new file mode 100644 index 00000000..76cf47fb --- /dev/null +++ b/tests/CIRCLECI_API/validator.py @@ -0,0 +1,226 @@ + +import json +import yaml +from jsonschema import ( + Draft202012Validator, + Draft7Validator, + Draft4Validator, + ValidationError, +) +from referencing import Registry, Resource +from pathlib import Path +from typing import Dict, Any +import requests + + +class SwaggerSchemaValidator: + """ + Validates JSON, XML, and text responses + """ + + def __init__(self, swagger_source: str): + self.spec = self._load_spec(swagger_source) + self.is_swagger2 = False + self.schemas = self._extract_schemas() + self.registry = Registry() + + for name, schema in self.schemas.items(): + pointer = ( + f"#/definitions/{name}" if self.is_swagger2 + else f"#/components/schemas/{name}" + ) + + wrapped = { + "$schema": "https://json-schema.org/draft/2020-12/schema", + **schema, + } + self.registry = self.registry.with_resource( + pointer, + Resource.from_contents(wrapped) + ) + + def _load_spec(self, source: str) -> Dict[str, Any]: + # Convert Path to string if needed + if isinstance(source, Path): + source = str(source) + + if source.startswith(("http://", "https://")): + resp = requests.get(source) + resp.raise_for_status() + text = resp.text + + try: + return yaml.safe_load(text) + except yaml.YAMLError: + try: + return json.loads(text) + except json.JSONDecodeError: + raise ValueError("URL does not contain valid YAML or JSON") + + with open(source, "r") as f: + text = f.read() + + if source.endswith((".yaml", ".yml")): + return yaml.safe_load(text) + if source.endswith(".json"): + return json.loads(text) + + raise ValueError("File must be YAML or JSON") + + def _extract_schemas(self): + if "components" in self.spec and "schemas" in self.spec["components"]: + self.is_swagger2 = False + return self.spec["components"]["schemas"] + + if "definitions" in self.spec: + self.is_swagger2 = True + return self.spec["definitions"] + + raise ValueError("No schemas found under components/schemas or definitions") + + def get_version(self): + return self.spec.get("openapi") or self.spec.get("swagger") or "" + + def select_validator(self): + v = self.get_version() + + if v.startswith("2."): + return Draft4Validator + if v.startswith("3.0"): + return Draft7Validator + if v.startswith("3.1"): + return Draft202012Validator + + return Draft202012Validator + + def resolve_ref(self, ref): + if ref.startswith("#/"): + parts = ref.lstrip("#/").split("/") + node = self.spec + for p in parts: + node = node[p] + return node + + raise ValueError(f"External refs not supported: {ref}") + + def deref(self, schema): + if isinstance(schema, dict): + if "$ref" in schema: + resolved = self.resolve_ref(schema["$ref"]) + return self.deref(resolved) + return {k: self.deref(v) for k, v in schema.items()} + + if isinstance(schema, list): + return [self.deref(v) for v in schema] + + return schema + + def detect_format(self, response): + ctype = response.headers.get("Content-Type", "").lower() + if "json" in ctype: + return "json" + if "xml" in ctype: + return "xml" + if "text" in ctype: + return "text" + return "binary" + + def parse_body(self, response, fmt): + if fmt == "json": + return json.loads(response.text) + + if fmt == "xml": + import xmltodict + return xmltodict.parse(response.text) + + if fmt == "text": + return response.text + + return response.content + + def extract_schema_for_media_type(self, response_block, content_type): + content = response_block.get("content", {}) + + if content_type in content: + return content[content_type].get("schema") + + if "json" in content_type: + for k, v in content.items(): + if k == "application/json" or k.endswith("+json"): + return v.get("schema") + + if "xml" in content_type: + for k, v in content.items(): + if "xml" in k: + return v.get("schema") + + if "text/plain" in content: + return content["text/plain"].get("schema") + + return None + + + def validate_json(self, data, schema_name): + if schema_name not in self.schemas: + raise ValueError(f"Schema '{schema_name}' not found") + + schema = self.deref(self.schemas[schema_name]) + validator_cls = self.select_validator() + validator = validator_cls(schema, registry=self.registry) + + try: + validator.validate(data) + return {"valid": True} + except ValidationError as e: + return { + "valid": False, + "message": e.message, + "path": list(e.path), + "schema_path": list(e.schema_path), + } + + def validate_schema_by_response(self, endpoint, method, status_code, response): + fmt = self.detect_format(response) + + paths = self.spec.get("paths", {}) + op = paths.get(endpoint, {}).get(method.lower()) + + if not op: + return {"valid": False, "message": f"Method {method} not found at path {endpoint}"} + + responses = op.get("responses", {}) + response_block = responses.get(status_code) + + if not response_block: + return {"valid": False, "message": f"No response block for {status_code}"} + + ctype = response.headers.get("Content-Type", "").split(";")[0].strip() + + if "content" in response_block: + schema = self.extract_schema_for_media_type(response_block, ctype) + else: + schema = response_block.get("schema") + + if schema is None: + return {"valid": True, "message": "No schema defined for this content type"} + + try: + data = self.parse_body(response, fmt) + except Exception as e: + return {"valid": False, "message": f"Body parsing failed: {e}"} + + schema = self.deref(schema) + + validator_cls = self.select_validator() + validator = validator_cls(schema, registry=self.registry) + + try: + validator.validate(data) + return {"valid": True} + except ValidationError as e: + return { + "valid": False, + "message": e.message, + "path": list(e.path), + "schema_path": list(e.schema_path), + }