{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "2ee21f3f-2a40-486f-9721-d8a358a87aa1",
      "metadata": {},
      "source": [
        "---\n",
        "title: Get started with Qiskit Functions\n",
        "description: How to do common tasks, from install and authentication to checking job status and fetching error messages\n",
        "---\n",
        "\n",
        "{/* cspell:ignore Jarman, HIVQE, Cadavid, Chandarana, Leclerc, Sachdeva, HUBO, Filippov, Downfolding, Aharonov, Mundada, Yamauchi, supersymmetric, Paterakis, Gharibyan, Jaffali, Pellow */}\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b7c85b80",
      "metadata": {
        "tags": [
          "version-info"
        ]
      },
      "source": [
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "04b0ccd6-e960-484b-8696-81b2d567cba2",
      "metadata": {},
      "source": [
        "# Get started with Qiskit Functions\n",
        "\n",
        "Premium, Flex, and On-Prem (through the IBM Quantum Platform API) Plan users can get started with IBM Qiskit Functions for free, or can procure a license from one of the partners who have contributed a function to the catalog.\n",
        "\n",
        "## Request a free trial for third-party Qiskit Functions\n",
        "\n",
        "To request a free trial, navigate to the [Qiskit Functions Catalog](/functions), and explore the details panel. Click `Request a free trial` and fill out information required by the Functions partner, including the IBM Cloud `AccessGroupId`:\n",
        "\n",
        "1. Navigate to [IBM Cloud IAM](http://cloud.ibm.com/iam/groups).\n",
        "2. Verify eligibility.\n",
        "   * Switch your account in the menu bar on the header to one with the following format: `XXXXXXX - [Organization Name]`\n",
        "   * Ensure the organization is the same as the one associated with your Premium account.\n",
        "   * If you see \"\\[Your Name]'s Account\", you are using your *personal* account, which is not eligible for premium access.\n",
        "3. Find your access group ID.\n",
        "   * Click a group name.\n",
        "   * Click **Details**.\n",
        "   * Copy the access group ID. It should start with `AccessGroup-`.\n",
        "\n",
        "<span id=\"install-qiskit-functions-catalog-client\" />\n",
        "\n",
        "## Install the Qiskit Functions Catalog client\n",
        "\n",
        "1. To start using Qiskit Functions, install the IBM Qiskit Functions Catalog client:\n",
        "\n",
        "   ```\n",
        "   pip install qiskit-ibm-catalog\n",
        "   ```\n",
        "\n",
        "2. Retrieve your API key from the [IBM Quantum Platform dashboard](/), and activate your Python virtual environment.  See the [installation instructions](/docs/guides/install-qiskit#local) if you do not already have a virtual environment set up.\n",
        "\n",
        "   <span id=\"save-account\" />**If you are working in a trusted Python environment (such as on a personal laptop or workstation),** use the `save_account()` method to save your credentials locally. ([Skip to the next step](#functions-untrusted) if you are not using a trusted environment, such as a shared or public computer, to authenticate to IBM Quantum Platform.)\n",
        "\n",
        "   To use `save_account()`, run `python` in your shell, then enter the following:\n",
        "\n",
        "   ```python\n",
        "   from qiskit_ibm_catalog import QiskitFunctionsCatalog\n",
        "\n",
        "   QiskitFunctionsCatalog.save_account(channel=\"ibm_quantum_platform\", token=\"<your-token>\", instance=\"<instance-crn>\")\n",
        "   ```\n",
        "\n",
        "   Type `exit()`. From now on, whenever you need to authenticate to the service, you can load your credentials with the following:\n",
        "\n",
        "   ```python\n",
        "   from qiskit_ibm_catalog import QiskitFunctionsCatalog\n",
        "   catalog = QiskitFunctionsCatalog()\n",
        "   ```\n",
        "\n",
        "   For example:\n",
        "\n",
        "   <CodeCellPlaceholder tag=\"id-load-credentials\" />\n",
        "\n",
        "3. <span id=\"functions-untrusted\" />**Avoid executing code on an untrusted machine or an external cloud Python environment to minimize security risks.** If you must use an untrusted environment (on, for example, a public computer), change your API key after each use by deleting it on the [IBM Cloud API keys](https://cloud.ibm.com/iam/apikeys) page to reduce risk. Learn more in the [Managing user API keys](https://cloud.ibm.com/docs/account?topic=account-userapikey\\&interface=ui) topic. To initialize the service in this situation, use this code:\n",
        "\n",
        "   ```python\n",
        "   from qiskit_ibm_catalog import QiskitFunctionsCatalog\n",
        "\n",
        "   # After using the following code, delete your API key on the\n",
        "   # IBM Quantum Platform home dashboard\n",
        "   catalog = QiskitFunctionsCatalog(token=\"<YOUR_API_KEY>\") # Use the 44-character\n",
        "   # API_KEY you created and saved from the IBM Quantum Platform Home dashboard\n",
        "   ```\n",
        "\n",
        "   <Admonition type=\"danger\" title=\"Protect your API key\">\n",
        "     **Never include your key in source code, Python scripts, or notebook files.** When sharing code with others, ensure that your API key is not embedded directly within the Python script. Instead, share the script without the key and provide instructions for securely setting it up.\n",
        "\n",
        "     If you accidentally share your key with someone or include it in version control like Git, immediately revoke your key by deleting it on the [IBM Cloud API keys](https://cloud.ibm.com/iam/apikeys) page to reduce risk. Learn more in the [Managing user API keys](https://cloud.ibm.com/docs/account?topic=account-userapikey\\&interface=ui) topic.\n",
        "   </Admonition>\n",
        "\n",
        "## List the functions you can access\n",
        "\n",
        "After you authenticate, you can list the functions from the Qiskit Functions Catalog that you have access to:\n",
        "\n",
        "<CodeCellPlaceholder tag=\"id-list-functions\" />\n",
        "\n",
        "## Check available backends and capacity\n",
        "\n",
        "Before you run a function, check which backends your instance can reach and how much runtime capacity you have left. `run()` performs the same checks before it submits a job, so you can catch capacity and backend problems early.\n",
        "\n",
        "List the backends your instance can reach. Results are cached per catalog. Pass `refresh_cache=True` to refresh them.\n",
        "\n",
        "<CodeCellPlaceholder tag=\"id-catalog\" />\n",
        "\n",
        "Look up a single backend and confirm access:\n",
        "\n",
        "<CodeCellPlaceholder tag=\"id-backend\" />\n",
        "\n",
        "You can also get the backend with the fewest pending jobs:\n",
        "\n",
        "<CodeCellPlaceholder tag=\"id-least-busy\" />\n",
        "\n",
        "Use `usage()` to see your remaining runtime capacity. It returns `usage_remaining_seconds` and `usage_limit_reached` for the active instance.\n",
        "\n",
        "<CodeCellPlaceholder tag=\"id-usage\" />\n",
        "\n",
        "For example, check your remaining capacity before a long batch of jobs, and stop if there is not enough left to finish it:\n",
        "\n",
        "<CodeCellPlaceholder tag=\"id-usage-example\" />\n",
        "\n",
        "## Run enabled functions\n",
        "\n",
        "After a catalog object has been instantiated, you can select a function by using `catalog.load(\"<provider/function-name>\")`:\n",
        "\n",
        "<CodeCellPlaceholder tag=\"id-run-functions\" />\n",
        "\n",
        "Each Qiskit Function has custom inputs, options, and outputs. Check the specific documentation pages for the function you want to run for more information. By default, all users can only run one function job at a time:\n",
        "\n",
        "<CodeCellPlaceholder tag=\"id-one-function\" />\n",
        "\n",
        "<Admonition type=\"tip\">\n",
        "  `run()` checks your remaining capacity and backend access before it submits the job. If your instance is out of capacity, or the backend you named is not accessible, `run()` raises an error right away instead of leaving the job to fail in the queue. When capacity is low, `run()` emits a warning. Pass `suppress_low_usage_warning=True` to silence it.\n",
        "\n",
        "  <CodeCellPlaceholder tag=\"id-low-capacity\" />\n",
        "</Admonition>\n",
        "\n",
        "<span id=\"check-job-status\" />\n",
        "\n",
        "## Check job status\n",
        "\n",
        "With your Qiskit Function `job_id`, you can check the status of running jobs. This includes the following statuses:\n",
        "\n",
        "* **`QUEUED`**: The remote program is in the Qiskit Function queue. The queue priority is based on how much you've used Qiskit Functions.\n",
        "* **`INITIALIZING`**: The remote program is starting; this includes setting up the remote environment and installing dependencies.\n",
        "* **`RUNNING`**: The program is running. This also includes several more detailed statuses if supported by specific functions.\n",
        "  * **`RUNNING: MAPPING`**: The function is currently mapping your classical inputs to quantum inputs.\n",
        "  * **`RUNNING: OPTIMIZING_FOR_HARDWARE`**: The function is optimizing for the selected QPU. This could include circuit transpilation, QPU characterization, observable backpropagation, and so forth.\n",
        "  * **`RUNNING: WAITING_FOR_QPU`**: The function has submitted a job to Qiskit Runtime, and is waiting in the queue.\n",
        "  * **`RUNNING: EXECUTING_QPU`**: The function has an active Qiskit Runtime job.\n",
        "  * **`RUNNING: POST_PROCESSING`**: The function is post-processing results, which can include error mitigation, mapping quantum results to classical, and so forth.\n",
        "* **`DONE`**: The program is complete, and you can retrieve result data with `job.results()`.\n",
        "* **`ERROR`**: The program stopped running because of a problem. Use `job.result()` to get the error message.\n",
        "* **`CANCELED`**: The program was canceled by a user, the service, or the server.\n",
        "\n",
        "  <CodeCellPlaceholder tag=\"id-status\" />\n",
        "\n",
        "<span id=\"retrieve-results\" />\n",
        "\n",
        "## Retrieve results\n",
        "\n",
        "After a program is `DONE`, you can use `job.results()` to fetch the result. This output format varies with each function, so be sure to follow the specific documentation:\n",
        "\n",
        "<CodeCellPlaceholder tag=\"id-retrieve\" />\n",
        "\n",
        "You can also cancel a job at any time:\n",
        "\n",
        "<CodeCellPlaceholder tag=\"id-cancel\" />\n",
        "\n",
        "## List previously run Qiskit Functions jobs\n",
        "\n",
        "You can use `jobs()` to list all jobs submitted to Qiskit Functions:\n",
        "\n",
        "<CodeCellPlaceholder tag=\"id-all-jobs\" />\n",
        "\n",
        "If you already have the job ID for a certain job, you can retrieve the job with `catalog.get_job_by_id()`:\n",
        "\n",
        "<CodeCellPlaceholder tag=\"id-by-id\" />\n",
        "\n",
        "## Fetch error messages\n",
        "\n",
        "If a program status is `ERROR`, use `job.error_message()` to fetch the error message as follows:\n",
        "\n",
        "<CodeCellPlaceholder tag=\"id-fetch-errors\" />\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "6699700c-ae26-4c10-8d09-05ee77a1afb7",
      "metadata": {
        "tags": [
          "id-load-credentials"
        ]
      },
      "outputs": [],
      "source": [
        "# Load saved credentials\n",
        "from qiskit_ibm_catalog import QiskitFunctionsCatalog\n",
        "\n",
        "catalog = QiskitFunctionsCatalog(channel=\"ibm_quantum_platform\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "275b4b94-7656-403e-8997-941c03c7ef55",
      "metadata": {
        "tags": [
          "id-list-functions"
        ]
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "[QiskitFunction(qunova/hivqe-chemistry),\n",
              " QiskitFunction(global-data-quantum/quantum-portfolio-optimizer),\n",
              " QiskitFunction(algorithmiq/tem),\n",
              " QiskitFunction(qedma/qesem),\n",
              " QiskitFunction(multiverse/singularity),\n",
              " QiskitFunction(ibm/circuit-function),\n",
              " QiskitFunction(q-ctrl/optimization-solver),\n",
              " QiskitFunction(colibritd/quick-pde),\n",
              " QiskitFunction(q-ctrl/performance-management),\n",
              " QiskitFunction(kipu-quantum/iskay-quantum-optimizer)]"
            ]
          },
          "execution_count": 2,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "catalog.list()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "6f2167d5-2dbb-4b5a-8639-8d0712a943c6",
      "metadata": {
        "tags": [
          "id-catalog"
        ]
      },
      "outputs": [],
      "source": [
        "catalog.backends()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "fec85827-af64-40db-a4a8-1173d6378e52",
      "metadata": {
        "tags": [
          "id-backend"
        ]
      },
      "outputs": [],
      "source": [
        "catalog.backend(\"ibm_fez\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "aca1a365-bddf-45b9-bd6d-bab893eac30b",
      "metadata": {
        "tags": [
          "id-least-busy"
        ]
      },
      "outputs": [],
      "source": [
        "catalog.least_busy()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "d77a9e2a-a581-43e4-ad49-e5e92bfaf914",
      "metadata": {
        "tags": [
          "id-usage"
        ]
      },
      "outputs": [],
      "source": [
        "catalog.usage()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "9446ba1c-9369-47e2-8274-6cf8166fd4b9",
      "metadata": {
        "tags": [
          "id-usage-example"
        ]
      },
      "outputs": [],
      "source": [
        "usage = catalog.usage()\n",
        "if usage[\"usage_remaining_seconds\"] < 600:\n",
        "    raise SystemExit(\"Not enough capacity remaining to start this batch.\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "7c570541-599a-48c6-b735-c378b3e2ba02",
      "metadata": {
        "tags": [
          "id-low-capacity"
        ]
      },
      "outputs": [],
      "source": [
        "job = ibm_cf.run(\n",
        "    pubs=[(circuit, observable)],\n",
        "    instance=instance,\n",
        "    backend_name=backend_name,  # E.g. \"ibm_fez\"\n",
        "    suppress_low_usage_warning=True,\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "65a26da5-f537-44ed-9cb4-b335518d009d",
      "metadata": {
        "tags": [
          "id-run-functions"
        ]
      },
      "outputs": [],
      "source": [
        "ibm_cf = catalog.load(\"ibm/circuit-function\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "9b9a7a3c-cc98-4c19-93cd-f59793515c70",
      "metadata": {
        "tags": [
          "id-one-function"
        ]
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'7f08c9d5-471b-4da2-92e7-4f2cb94c23a8'"
            ]
          },
          "execution_count": 5,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "job = ibm_cf.run(\n",
        "    pubs=[(circuit, observable)],\n",
        "    instance=instance,\n",
        "    backend_name=backend_name,  # E.g. \"ibm_fez\"\n",
        ")\n",
        "\n",
        "job.job_id"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "d0574d73-0966-4426-b2f5-94df72a07caa",
      "metadata": {
        "tags": [
          "id-status"
        ]
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'QUEUED'"
            ]
          },
          "execution_count": 6,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "job.status()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "45e302d8-f3c2-4868-8b7c-6d451f6119a9",
      "metadata": {
        "tags": [
          "id-retrieve"
        ]
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "PrimitiveResult([PubResult(data=DataBin(evs=np.ndarray(<shape=(), dtype=float64>), stds=np.ndarray(<shape=(), dtype=float64>), ensemble_standard_error=np.ndarray(<shape=(), dtype=float64>)), metadata={'shots': 4096, 'target_precision': 0.015625, 'circuit_metadata': {}, 'resilience': {}, 'num_randomizations': 32})], metadata={'dynamical_decoupling': {'enable': True, 'sequence_type': 'XX', 'extra_slack_distribution': 'middle', 'scheduling_method': 'alap'}, 'twirling': {'enable_gates': False, 'enable_measure': True, 'num_randomizations': 'auto', 'shots_per_randomization': 'auto', 'interleave_randomizations': True, 'strategy': 'active-accum'}, 'resilience': {'measure_mitigation': True, 'zne_mitigation': False, 'pec_mitigation': False}, 'version': 2})\n"
          ]
        }
      ],
      "source": [
        "result = job.result()\n",
        "print(result)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "0e55d4d6-4680-4671-907f-35aac16971ef",
      "metadata": {
        "tags": [
          "id-cancel"
        ]
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'Job has been stopped.'"
            ]
          },
          "execution_count": 8,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "job.stop()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "4becfe13-68dd-481d-bb43-fc502c254623",
      "metadata": {
        "tags": [
          "id-all-jobs"
        ]
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "[<Job | f6c29f49-4d5f-4fff-aca6-2e9a115b9763>,\n",
              " <Job | 7f08c9d5-471b-4da2-92e7-4f2cb94c23a8>,\n",
              " <Job | 62fe9176-d1e5-467e-b2bd-7a3f3c7be4e5>,\n",
              " <Job | af525b2e-16b1-45a1-80bb-dbd94ce30258>,\n",
              " <Job | b95a7a57-c1ad-4958-b7ac-953e4e1ee824>,\n",
              " <Job | 7bfa33da-0f17-4e67-84b6-f556f7eeb436>,\n",
              " <Job | ca46c191-9eb9-4de6-bfa7-b60d7eb29b5e>,\n",
              " <Job | 6ac0ba93-3831-43fb-9fb9-760da2225e06>,\n",
              " <Job | f0e38071-060d-47e8-988d-9cc1f69358e3>,\n",
              " <Job | 629cf110-e490-4675-8a07-f6d298d166b0>]"
            ]
          },
          "execution_count": 9,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "old_jobs = catalog.jobs()\n",
        "old_jobs"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 18,
      "id": "18d87f07-8a8e-4b93-80d0-7c07e49272e2",
      "metadata": {
        "tags": [
          "id-by-id"
        ]
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "f6c29f49-4d5f-4fff-aca6-2e9a115b9763\n"
          ]
        }
      ],
      "source": [
        "# First, get the most recent job that has been executed.\n",
        "latest_job = old_jobs[0]\n",
        "\n",
        "# We can also get that same job with get_job_by_id\n",
        "job_by_id = catalog.get_job_by_id(latest_job.job_id)\n",
        "\n",
        "# Verify that the job is the same using both retrieval methods.\n",
        "assert job_by_id.job_id == latest_job.job_id\n",
        "\n",
        "# Print the job_id for this job.\n",
        "print(job_by_id.job_id)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "68412b66-8022-4dd3-b140-ec33e119693b",
      "metadata": {
        "tags": [
          "id-fetch-errors"
        ]
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "qiskit.exceptions.QiskitError: 'Workflow execution failed -- https://docs.quantum.ibm.com/errors#9999'\n"
          ]
        }
      ],
      "source": [
        "job.error_message()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "709b39ca-5dbd-42c0-830c-1248c2e5d63c",
      "metadata": {},
      "source": [
        "## Next steps\n",
        "\n",
        "<Admonition type=\"info\" title=\"Recommendations\">\n",
        "  * [Explore circuit functions](/docs/guides/algorithmiq-tem) to build new algorithms and applications, without needing to manage transpilation or error handling.\n",
        "  * [Explore application functions](/docs/guides/q-ctrl-optimization-solver) to solve domain-specific tasks, with classical inputs and outputs.\n",
        "  * See the [API reference documentation](/docs/api/functions/index) for Qiskit Functions.\n",
        "  * For hands-on experience, try out some [tutorials](/docs/tutorials/index#leverage-qiskit-capabilities) that demonstrate Qiskit Functions.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "id": "a1b8767d",
      "source": "© IBM Corp., 2017-2026"
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 4
}