experimenter/cirrus
dependabot[bot] 40cc4affff
chore(deps): Bump sentry-sdk from 2.17.0 to 2.18.0 in /cirrus/server (#11690)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from
2.17.0 to 2.18.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/getsentry/sentry-python/releases">sentry-sdk's
releases</a>.</em></p>
<blockquote>
<h2>2.18.0</h2>
<h3>Various fixes &amp; improvements</h3>
<ul>
<li>Add LaunchDarkly and OpenFeature integration (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3648">#3648</a>)
by <a
href="https://github.com/cmanallen"><code>@​cmanallen</code></a></li>
<li>Correct typo in a comment (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3726">#3726</a>)
by <a
href="https://github.com/szokeasaurusrex"><code>@​szokeasaurusrex</code></a></li>
<li>End <code>http.client</code> span on timeout (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3723">#3723</a>)
by <a
href="https://github.com/Zylphrex"><code>@​Zylphrex</code></a></li>
<li>Check for <code>h2</code> existence in HTTP/2 transport (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3690">#3690</a>)
by <a href="https://github.com/BYK"><code>@​BYK</code></a></li>
<li>Use <code>type()</code> instead when extracting frames (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3716">#3716</a>)
by <a
href="https://github.com/Zylphrex"><code>@​Zylphrex</code></a></li>
<li>Prefer <code>python_multipart</code> import over
<code>multipart</code> (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3710">#3710</a>)
by <a
href="https://github.com/musicinmybrain"><code>@​musicinmybrain</code></a></li>
<li>Update active thread for asgi (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3669">#3669</a>)
by <a
href="https://github.com/Zylphrex"><code>@​Zylphrex</code></a></li>
<li>Only enable HTTP2 when DSN is HTTPS (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3678">#3678</a>)
by <a href="https://github.com/BYK"><code>@​BYK</code></a></li>
<li>Prepare for upstream Strawberry extension removal (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3649">#3649</a>)
by <a
href="https://github.com/DoctorJohn"><code>@​DoctorJohn</code></a></li>
<li>Enhance README with improved clarity and developer-friendly examples
(<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3667">#3667</a>)
by <a
href="https://github.com/UTSAVS26"><code>@​UTSAVS26</code></a></li>
<li>Run license compliance action on all PRs (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3699">#3699</a>)
by <a
href="https://github.com/szokeasaurusrex"><code>@​szokeasaurusrex</code></a></li>
<li>Run CodeQL action on all PRs (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3698">#3698</a>)
by <a
href="https://github.com/szokeasaurusrex"><code>@​szokeasaurusrex</code></a></li>
<li>Fix UTC assuming test (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3722">#3722</a>)
by <a href="https://github.com/BYK"><code>@​BYK</code></a></li>
<li>Exclude fakeredis 2.26.0 on py3.6 and 3.7 (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3695">#3695</a>)
by <a
href="https://github.com/szokeasaurusrex"><code>@​szokeasaurusrex</code></a></li>
<li>Unpin <code>pytest</code> for <code>tornado-latest</code> tests (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3714">#3714</a>)
by <a
href="https://github.com/szokeasaurusrex"><code>@​szokeasaurusrex</code></a></li>
<li>Install <code>pytest-asyncio</code> for <code>redis</code> tests
(Python 3.12-13) (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3706">#3706</a>)
by <a
href="https://github.com/szokeasaurusrex"><code>@​szokeasaurusrex</code></a></li>
<li>Clarify that only pinned tests are required (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3713">#3713</a>)
by <a
href="https://github.com/szokeasaurusrex"><code>@​szokeasaurusrex</code></a></li>
<li>Remove accidentally-committed print (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3712">#3712</a>)
by <a
href="https://github.com/szokeasaurusrex"><code>@​szokeasaurusrex</code></a></li>
<li>Disable broken RQ test in newly-released RQ 2.0 (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3708">#3708</a>)
by <a
href="https://github.com/szokeasaurusrex"><code>@​szokeasaurusrex</code></a></li>
<li>Unpin <code>pytest</code> for <code>celery</code> tests (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3701">#3701</a>)
by <a
href="https://github.com/szokeasaurusrex"><code>@​szokeasaurusrex</code></a></li>
<li>Unpin <code>pytest</code> on Python 3.8+ <code>gevent</code> tests
(<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3700">#3700</a>)
by <a
href="https://github.com/szokeasaurusrex"><code>@​szokeasaurusrex</code></a></li>
<li>Unpin <code>pytest</code> for Python 3.8+ <code>common</code> tests
(<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3697">#3697</a>)
by <a
href="https://github.com/szokeasaurusrex"><code>@​szokeasaurusrex</code></a></li>
<li>Remove <code>pytest</code> pin in
<code>requirements-devenv.txt</code> (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3696">#3696</a>)
by <a
href="https://github.com/szokeasaurusrex"><code>@​szokeasaurusrex</code></a></li>
<li>Test with Falcon 4.0 (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3684">#3684</a>)
by <a
href="https://github.com/sentrivana"><code>@​sentrivana</code></a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md">sentry-sdk's
changelog</a>.</em></p>
<blockquote>
<h2>2.18.0</h2>
<h3>Various fixes &amp; improvements</h3>
<ul>
<li>Add LaunchDarkly and OpenFeature integration (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3648">#3648</a>)
by <a
href="https://github.com/cmanallen"><code>@​cmanallen</code></a></li>
<li>Correct typo in a comment (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3726">#3726</a>)
by <a
href="https://github.com/szokeasaurusrex"><code>@​szokeasaurusrex</code></a></li>
<li>End <code>http.client</code> span on timeout (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3723">#3723</a>)
by <a
href="https://github.com/Zylphrex"><code>@​Zylphrex</code></a></li>
<li>Check for <code>h2</code> existence in HTTP/2 transport (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3690">#3690</a>)
by <a href="https://github.com/BYK"><code>@​BYK</code></a></li>
<li>Use <code>type()</code> instead when extracting frames (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3716">#3716</a>)
by <a
href="https://github.com/Zylphrex"><code>@​Zylphrex</code></a></li>
<li>Prefer <code>python_multipart</code> import over
<code>multipart</code> (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3710">#3710</a>)
by <a
href="https://github.com/musicinmybrain"><code>@​musicinmybrain</code></a></li>
<li>Update active thread for asgi (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3669">#3669</a>)
by <a
href="https://github.com/Zylphrex"><code>@​Zylphrex</code></a></li>
<li>Only enable HTTP2 when DSN is HTTPS (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3678">#3678</a>)
by <a href="https://github.com/BYK"><code>@​BYK</code></a></li>
<li>Prepare for upstream Strawberry extension removal (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3649">#3649</a>)
by <a
href="https://github.com/DoctorJohn"><code>@​DoctorJohn</code></a></li>
<li>Enhance README with improved clarity and developer-friendly examples
(<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3667">#3667</a>)
by <a
href="https://github.com/UTSAVS26"><code>@​UTSAVS26</code></a></li>
<li>Run license compliance action on all PRs (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3699">#3699</a>)
by <a
href="https://github.com/szokeasaurusrex"><code>@​szokeasaurusrex</code></a></li>
<li>Run CodeQL action on all PRs (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3698">#3698</a>)
by <a
href="https://github.com/szokeasaurusrex"><code>@​szokeasaurusrex</code></a></li>
<li>Fix UTC assuming test (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3722">#3722</a>)
by <a href="https://github.com/BYK"><code>@​BYK</code></a></li>
<li>Exclude fakeredis 2.26.0 on py3.6 and 3.7 (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3695">#3695</a>)
by <a
href="https://github.com/szokeasaurusrex"><code>@​szokeasaurusrex</code></a></li>
<li>Unpin <code>pytest</code> for <code>tornado-latest</code> tests (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3714">#3714</a>)
by <a
href="https://github.com/szokeasaurusrex"><code>@​szokeasaurusrex</code></a></li>
<li>Install <code>pytest-asyncio</code> for <code>redis</code> tests
(Python 3.12-13) (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3706">#3706</a>)
by <a
href="https://github.com/szokeasaurusrex"><code>@​szokeasaurusrex</code></a></li>
<li>Clarify that only pinned tests are required (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3713">#3713</a>)
by <a
href="https://github.com/szokeasaurusrex"><code>@​szokeasaurusrex</code></a></li>
<li>Remove accidentally-committed print (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3712">#3712</a>)
by <a
href="https://github.com/szokeasaurusrex"><code>@​szokeasaurusrex</code></a></li>
<li>Disable broken RQ test in newly-released RQ 2.0 (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3708">#3708</a>)
by <a
href="https://github.com/szokeasaurusrex"><code>@​szokeasaurusrex</code></a></li>
<li>Unpin <code>pytest</code> for <code>celery</code> tests (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3701">#3701</a>)
by <a
href="https://github.com/szokeasaurusrex"><code>@​szokeasaurusrex</code></a></li>
<li>Unpin <code>pytest</code> on Python 3.8+ <code>gevent</code> tests
(<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3700">#3700</a>)
by <a
href="https://github.com/szokeasaurusrex"><code>@​szokeasaurusrex</code></a></li>
<li>Unpin <code>pytest</code> for Python 3.8+ <code>common</code> tests
(<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3697">#3697</a>)
by <a
href="https://github.com/szokeasaurusrex"><code>@​szokeasaurusrex</code></a></li>
<li>Remove <code>pytest</code> pin in
<code>requirements-devenv.txt</code> (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3696">#3696</a>)
by <a
href="https://github.com/szokeasaurusrex"><code>@​szokeasaurusrex</code></a></li>
<li>Test with Falcon 4.0 (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3684">#3684</a>)
by <a
href="https://github.com/sentrivana"><code>@​sentrivana</code></a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="09946cb624"><code>09946cb</code></a>
Update CHANGELOG.md</li>
<li><a
href="0a8ef922b8"><code>0a8ef92</code></a>
release: 2.18.0</li>
<li><a
href="dd1117d63f"><code>dd1117d</code></a>
Add LaunchDarkly and OpenFeature integration (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3648">#3648</a>)</li>
<li><a
href="d06a1897e5"><code>d06a189</code></a>
docs(hub): Correct typo in a comment (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3726">#3726</a>)</li>
<li><a
href="5e2d2cf7fd"><code>5e2d2cf</code></a>
fix(tracing): End http.client span on timeout (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3723">#3723</a>)</li>
<li><a
href="5c5d98a793"><code>5c5d98a</code></a>
test: Fix UTC assuming test (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3722">#3722</a>)</li>
<li><a
href="ce9986cb19"><code>ce9986c</code></a>
fix(http2): Check for h2 existence (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3690">#3690</a>)</li>
<li><a
href="02d09346e6"><code>02d0934</code></a>
fix(profiling): Use <code>type()</code> instead when extracting frames
(<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3716">#3716</a>)</li>
<li><a
href="bf40090424"><code>bf40090</code></a>
test(tornado): Unpin <code>pytest</code> for <code>tornado-latest</code>
tests (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3714">#3714</a>)</li>
<li><a
href="000c8e6c4e"><code>000c8e6</code></a>
fix(starlette): Prefer python_multipart import over multipart (<a
href="https://redirect.github.com/getsentry/sentry-python/issues/3710">#3710</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/getsentry/sentry-python/compare/2.17.0...2.18.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=sentry-sdk&package-manager=pip&previous-version=2.17.0&new-version=2.18.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-04 23:16:27 +00:00
..
server chore(deps): Bump sentry-sdk from 2.17.0 to 2.18.0 in /cirrus/server (#11690) 2024-11-04 23:16:27 +00:00
README.md feat(cirrus): Nimbus preview flag to return features based on preview experiments (#10998) 2024-07-24 16:48:06 +00:00

README.md

Cirrus

Cirrus is a feature configuration server that allows clients to obtain a set of features based on their provided client_id and context information. This document provides information on setting up the Cirrus environment, including required environment variables and commands for running and testing Cirrus.

Environment Setup

To set up the Cirrus environment, follow these steps:

  1. Create a .env file inside the cirrus/server directory.

  2. Copy the contents of .env.example into .env by running the following command:

    cp .env.example .env
    
  3. Open the .env file and modify the values of the following environment variables:

    CIRRUS_REMOTE_SETTING_URL=https://firefox.settings.services.mozilla.com/v1/buckets/main/collections/nimbus-web-experiments/records
    CIRRUS_REMOTE_SETTING_PREVIEW_URL=https://firefox.settings.services.mozilla.com/v1/buckets/main/collections/nimbus-web-preview/records
    CIRRUS_REMOTE_SETTING_REFRESH_RATE_IN_SECONDS=10
    CIRRUS_APP_ID=test_app_id
    CIRRUS_APP_NAME=test_app_name
    CIRRUS_CHANNEL=developer
    CIRRUS_FML_PATH=./feature_manifest/sample.fml.yaml
    CIRRUS_SENTRY_DSN=dsn_url
    CIRRUS_INSTANCE_NAME=cirrus_pod_app_v1
    CIRRUS_ENV_NAME=test_app_stage
    CIRRUS_GLEAN_MAX_EVENTS_BUFFER=10
    
    

    Here's what each variable represents:

    • CIRRUS_REMOTE_SETTING_URL: The URL of the remote settings where the experiments data is stored. In this case, it points to the collection of nimbus web experiments.
  • CIRRUS_REMOTE_SETTING_PREVIEW_URL: The URL of the remote settings where the preview experiments data is stored. In this case, it points to the collection of nimbus web preview experiments.
  • CIRRUS_REMOTE_SETTING_REFRESH_RATE_IN_SECONDS: The refresh rate in seconds for fetching the experiments recipes from the remote settings. Set it to 10 to retrieve the latest data every 10 seconds.
  • CIRRUS_APP_ID: Replace test_app_id with the actual ID of your application for example firefox-desktop.
  • CIRRUS_APP_NAME: Replace test_app_name with the desired name for your application for example firefox_desktop.
  • CIRRUS_CHANNEL: Replace developer with the channel like beta, release etc.
  • CIRRUS_FML_PATH: The file path to the feature manifest file. Set it to ./feature_manifest/sample.fml.yaml or specify the correct path to your feature manifest file.
  • CIRRUS_SENTRY_DSN: Replace dsn_url with the appropriate DSN value.
  • CIRRUS_INSTANCE_NAME: Replace with the instance name.
  • CIRRUS_ENV_NAME: Replace with the concatenation of project and environment name
  • CIRRUS_GLEAN_MAX_EVENTS_BUFFER: This value represents the max events buffer size for glean. You can set the value from range 1 to 500, by default Cirrus sets it to 10.

Adjust the values of these variables according to your specific configuration requirements.

By following these steps, you will create the .env file and configure the necessary environment variables for the Cirrus application.

Running as Non-Root User

By default, the Cirrus Docker image runs the application as cirrus/1000/1000. However, if you prefer to run the application as a different user for security reasons, you can build the Docker image with additional parameters.

  • Build the Docker image while specifying the desired username, user ID, and group ID. For example:
docker build --build-arg USERNAME=myuser --build-arg USER_UID=1000 --build-arg USER_GID=1000 -t your_image_name:tag .

Replace myuser with the desired username and 1000 with the desired user ID and group ID.

Commands

The following are the available commands for working with Cirrus:

  • cirrus_build: Builds the Cirrus container.

    • Usage: make cirrus_build
  • cirrus_up: Starts the Cirrus container.

    • Usage: make cirrus_up
  • cirrus_down:cirrus_down: Stops the Cirrus container.

    • Usage: make cirrus_down
  • cirrus_test: Runs tests for the Cirrus application.

    • Usage: make cirrus_test
  • cirrus_check: Performs various checks on the Cirrus application including Ruff linting, Black code formatting check, Pyright static type checking, pytest tests, and documentation generation..

    • Usage: make cirrus_check
  • cirrus_code_format: Formats the code in the Cirrus application.

    • Usage: make cirrus_code_format
  • cirrus_typecheck_createstub: Performs static type checking and creates stub files.

    • Usage: make cirrus_typecheck_createstub
  • cirrus_generate_docs: Generates documentation for the Cirrus application such as openapi schema.

    • Usage: make cirrus_generate_docs

OpenAPI Schema

OpenAPI schema for the Cirrus API

Cirrus Server to get Feature configuration API structure

Api Doc

Cirrus Api Doc for the Cirrus API

Endpoint

POST /v1/features/

  • When making a POST request, please make sure to set headers content type as JSON
      headers: {
              "Content-Type": "application/json",
        }
    

Input

The input should be a JSON object with the following properties:

  • client_id (string): Used for bucketing calculation.
  • context (object): Used for context. It can have any key-value pair.
    • any-key (anytype).
    • language (string): Optional field
    • region (string): Optional field

Note: Make sure to provide a key-value pair when making a call, setting the context value as {} will be considered as False value. For testing you can set value such as

 context: { key: "example-key" }

Example input:

{
  "client_id": "4a1d71ab-29a2-4c5f-9e1d-9d9df2e6e449",
  "context": {
    "key1": "value1",
    "key2": {
      "key2.1": "value2",
      "key2.2": "value3"
    }
  }
}
  • To target clients based on languages you can use key as language and it supports list of languages

Example input:

{
  "client_id": "4a1d71ab-29a2-4c5f-9e1d-9d9df2e6e449",
  "context": {
    "language": "en"
  }
}
  • To target clients based on country you can use key as region and it supports list of countries

Example input:

{
  "client_id": "4a1d71ab-29a2-4c5f-9e1d-9d9df2e6e449",
  "context": {
    "region": "US"
  }
}
  • To target client based on both language and country

Example input:

{
  "client_id": "4a1d71ab-29a2-4c5f-9e1d-9d9df2e6e449",
  "context": {
    "language": "en",
    "region": "US"
  }
}
  • You can make your custom field to target too. Prepare what fields you want to be be able to target on, and then work backwards to construct it and populate a targeting context that will satisfy that. Example input:
{
  "client_id": "4a1d71ab-29a2-4c5f-9e1d-9d9df2e6e449",
  "context": {
    "random_key": "random_value",
  }
}

Optional Query Parameter

nimbus_preview (boolean): Pass this as a query parameter to enable preview mode. When set to true, the endpoint will use the preview experiments to compute enrollments.

Example usage with nimbus_preview query parameter:

curl -X POST "http://localhost:8001/v1/features/?nimbus_preview=true" -H 'Content-Type: application/json' -d '{
  "client_id": "4a1d71ab-29a2-4c5f-9e1d-9d9df2e6e449",
  "context": {
    "language": "en",
    "region": "US"
  }
}'

Output

The output will be a JSON object with the following properties:

  • features (object): An object that contains the set of features. Each feature is represented as a sub-object with its own set of variables.

Example output:

{
  "Feature1": {
    "Variable1.1": "valueA",
    "Variable1.2": "valueB"
  },
  "Feature2": {
    "Variable2.1": "valueC",
    "Variable2.2": "valueD"
  },
  "FeatureN": {
    "VariableN.1": "valueX",
    "VariableN.2": "valueY"
  }
}

Notes

  • This API only accepts POST requests.
  • All parameters should be supplied in the body as JSON.