Returning.AIDevelopers
v1

API reference / Chart Analysis

.md

Append drawings

Add drawings to a pending chart analysis, keeping the card and the drawings already on it.

Last updated 26 Sep 2026API v1

Method
POST
Path
https://api.returning.ai/v1/analysis/{analysisId}/drawings
Permission
sendMessage
Retries
A repeat returns 400; nothing is added twice

When to use this

  • Add a stop-loss or target line to an analysis after it was posted.
  • Mark a new zone on the chart as the trade develops.
  • Build up a card in steps, creating it with levels only and adding drawings afterwards.

Authentication#

Header
Authorization: Bearer <API_KEY>
Permission
sendMessageShown in the dashboard as “Send Messages”

Use a Community API key with sendMessage, shown in the dashboard as Send Messages, and keep it on your server. Name the member who created the analysis in sender; only they can add drawings. Only send IDs from your own community's analyses. Personal API keys are not accepted here and return 401.

Behaviour#

Only a Pending analysis accepts new drawings. They are added after the ones already on the card, which stay as they are; the levels and text don't change. Members with the channel open see the new drawings straight away. Nothing is posted in the channel, and no webhook fires.

Drawings use the same shapes as Create analysis: a type, your clientObjectId, points with a UTC time and a price, and an optional style.

Request#

Path parameters#

analysisId#stringREQUIRED
The analysis ID from Create analysis or List analyses.

Rule24 hex characters

Eg"66f000000000000000000b01"

Headers#

Authorization#stringREQUIRED
Community API key with sendMessage.

RuleBearer <API_KEY>

Content-Type#stringREQUIRED
Request body format.

Ruleapplication/json

Body#

sender#stringREQUIRED
Username or email of the member who created the analysis. Required with a Community API key; any other member is refused.

RuleUsername or email

Eg"trader@example.com"

drawings#object[]REQUIRED
The drawings to add. Each clientObjectId must be new, both within the request and on the card.

Rule0-20 items per request

Eg[ ... ]

type#stringREQUIRED
Drawing type. PARALLEL needs exactly 3 points; FIB_RETRACEMENT needs 2 or 3.

RuleHORIZONTAL_LINE, LINE, RECTANGLE, PARALLEL or FIB_RETRACEMENT

Eg"HORIZONTAL_LINE"

clientObjectId#stringREQUIRED
Your own name for the drawing, unique in the request. Use it to find the drawing again in the response.

RuleMin 1 chars

Eg"stop_line"

points#object[]REQUIRED
Chart points for the drawing.

Rule3 for PARALLEL, 2-3 for FIB_RETRACEMENT

Eg[{"time": "2026-09-27T08:00:00.000Z", "price": 1.075}]

time#string | integerREQUIRED
Point time.

RuleISO 8601 date-time in UTC ending in Z, or epoch milliseconds

Eg"2026-09-27T08:00:00.000Z"

price#numberREQUIRED
Point price.

Eg1.075

style#objectOPTIONAL
Optional colours and line style.

Eg{"color": "#C62828"}

color#stringOPTIONAL
Line colour.

Rule#RRGGBB

Eg"#C62828"

lineWidth#integerOPTIONAL
Line width.

Rule1-10

Eg2

lineStyle#stringOPTIONAL
Line style.

RuleSOLID, DASHED or DOTTED

fillColor#stringOPTIONAL
Fill colour. An alpha channel such as #00FF0033 is rejected.

Rule#RRGGBB

Eg"#C8E6C9"

borderColor#stringOPTIONAL
Border colour.

Rule#RRGGBB

Eg"#00FF00"

opacity#numberOPTIONAL
Opacity.

Rule0-1

Eg0.5

startHead#stringOPTIONAL
LINE only: the start decoration.

RuleNONE, ARROW or EXTEND; default NONE

endHead#stringOPTIONAL
LINE only: the end decoration.

RuleNONE, ARROW or EXTEND; default NONE

levels#number[]OPTIONAL
FIB_RETRACEMENT only: the ratios to draw. Omit for the standard set from -0.618 to 1.618.
curl --request POST \
  --url https://api.returning.ai/v1/analysis/66f000000000000000000b01/drawings \
  --header 'Authorization: Bearer <API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{
    "sender": "trader@example.com",
    "drawings": [
      {
        "type": "HORIZONTAL_LINE",
        "clientObjectId": "stop_line",
        "points": [
          {
            "time": "2026-09-27T08:00:00.000Z",
            "price": 1.075
          }
        ],
        "style": {
          "color": "#C62828"
        }
      }
    ]
  }'

Response#

A 200 returns the whole updated analysis in data.analysis and the number added in data.addedCount. There is no map of new IDs: find each new drawing in shapes by your clientObjectId.

status#stringALWAYS
Result of the request.

Rulesuccess

statusCode#integerALWAYS
The HTTP status, repeated.
message#stringALWAYS
Human-readable summary. Do not branch on it.

Eg"Drawings appended successfully"

data#objectALWAYS
The updated analysis and how many drawings were added.

Eg{ ... }

analysis#objectALWAYS
The analysis after the change, with the same fields as data.analysis in Get analysis, without message. New drawings are at the end of shapes, each with your clientObjectId and its saved id.
addedCount#integerALWAYS
Number of drawings added by this request.
{
  "status": "success",
  "statusCode": 200,
  "message": "Drawings appended successfully",
  "data": {
    "analysis": {
      "_id": "66f000000000000000000b01",
      "owner": {
        "id": "3247779"
      },
      "tempId": null,
      "serverId": "66f000000000000000000010",
      "topicId": "66f000000000000000000b11",
      "commentId": "66f000000000000000000b21",
      "timeframe": "H1",
      "users": {
        "up": [],
        "down": []
      },
      "shapes": [
        {
          "key": "analysis",
          "levels": {
            "pivot": {
              "price": 1.1,
              "clientObjectId": "pivot_main",
              "time": "2026-09-27T08:00:00.000Z"
            },
            "resistance": {
              "price": 1.12,
              "clientObjectId": "resistance_main",
              "time": "2026-09-27T08:00:00.000Z"
            },
            "support": {
              "price": 1.08,
              "clientObjectId": "support_main",
              "time": "2026-09-27T08:00:00.000Z"
            }
          },
          "metadata": {
            "direction": "BULLISH",
            "entryPlacement": "BELOW_CURRENT",
            "expiry": {
              "type": "HOURS",
              "hours": 24
            },
            "title": "EURUSD bounce from support",
            "preferenceText": "Holding above [[support_main:support]], targeting [[resistance_main:resistance]].",
            "timeframe": "H1",
            "symbol": "EURUSD"
          },
          "id": "66f000000000000000000b41",
          "isRaw": true,
          "timeRange": [1790496000000, 1790496312431]
        },
        {
          "type": "HORIZONTAL_LINE",
          "clientObjectId": "entry_line",
          "points": [
            {
              "time": "2026-09-27T08:00:00.000Z",
              "price": 1.095
            }
          ],
          "style": {
            "color": "#2E7D32"
          },
          "key": "h-ray",
          "id": "66f000000000000000000b31",
          "isRaw": true,
          "timeRange": [1790035200000, 1790956800000]
        },
        {
          "type": "HORIZONTAL_LINE",
          "clientObjectId": "stop_line",
          "points": [
            {
              "time": "2026-09-27T08:00:00.000Z",
              "price": 1.075
            }
          ],
          "style": {
            "color": "#C62828"
          },
          "key": "h-ray",
          "id": "66f000000000000000000b32",
          "isRaw": true,
          "timeRange": [1790035200000, 1790956800000]
        }
      ],
      "category": "analysis",
      "extra": {
        "happened": "[{\"type\":\"p\",\"children\":[{\"text\":\"Holding above \"},{\"type\":\"linked-text\",\"hoverIds\":[\"66f000000000000000000b41:0\"],\"children\":[{\"text\":\"support\",\"type\":\"text\",\"id\":\"7c1e4f9a-2b6d-4e0a-9f3b-1a2c3d4e5f61\"}],\"id\":\"7c1e4f9a-2b6d-4e0a-9f3b-1a2c3d4e5f71\"},{\"text\":\", targeting \"},{\"type\":\"linked-text\",\"hoverIds\":[\"66f000000000000000000b41:7\"],\"children\":[{\"text\":\"resistance\",\"type\":\"text\",\"id\":\"7c1e4f9a-2b6d-4e0a-9f3b-1a2c3d4e5f62\"}],\"id\":\"7c1e4f9a-2b6d-4e0a-9f3b-1a2c3d4e5f72\"},{\"text\":\".\"}],\"id\":\"7c1e4f9a-2b6d-4e0a-9f3b-1a2c3d4e5f60\"}]",
        "expected": "[{\"type\":\"p\",\"children\":[{\"text\":\"\"}],\"id\":\"7c1e4f9a-2b6d-4e0a-9f3b-1a2c3d4e5f80\"}]",
        "comments": "[{\"type\":\"p\",\"children\":[{\"text\":\"\"}],\"id\":\"7c1e4f9a-2b6d-4e0a-9f3b-1a2c3d4e5f80\"}]",
        "direction": "bullish",
        "currency_pair": "EURUSD",
        "horizon": "SHORT",
        "userId": 3247779,
        "level": [
          {
            "title": "1st Support",
            "value": 1.08
          },
          {
            "title": "2nd Support",
            "value": 0
          },
          {
            "title": "Intermediate Support",
            "value": 0
          },
          {
            "title": "Downside Confirmation",
            "value": 0
          },
          {
            "title": "Upside Confirmation",
            "value": 0
          },
          {
            "title": "Intermediate Resistance",
            "value": 0
          },
          {
            "title": "2nd Resistance",
            "value": 0
          },
          {
            "title": "1st Resistance",
            "value": 1.12
          },
          {
            "title": "Pivot",
            "value": 1.1
          }
        ],
        "timeframe": "H1",
        "analysisType": {
          "expiry": 1,
          "title": "EURUSD bounce from support",
          "type": "bullish_bounce"
        },
        "status": "Pending",
        "intermediate": false
      },
      "roles": [],
      "private": false,
      "timeRange": {
        "x": [1790035200000, 1790956800000],
        "y": [1.078, 1.122]
      },
      "snapshot": null,
      "translationSource": "en",
      "translations": {},
      "createdAt": "2026-09-27T08:05:12.431Z",
      "updatedAt": "2026-09-27T09:20:00.000Z",
      "__v": 0
    },
    "addedCount": 1
  }
}

Errors#

These errors have no machine-readable code; branch on the HTTP status and read message. A sender who isn't the creator gets 500, not 403. The 401 for a missing or unknown key has detail and a meta object; the 401 for a missing permission has only message.

Fix the request03

400Fix the request

Nothing was added. Read message:

  • Append Drawings Request Validation validation error.: a drawing breaks its rule, such as an unknown type, a colour that isn't #RRGGBB, the wrong number of points, or two drawings with the same clientObjectId. detail points to the drawing.
  • clientObjectId must be unique. Duplicate IDs found: ...: the card already has a drawing with this clientObjectId. If you are retrying, the earlier request already added it; otherwise choose a new name.
  • Invalid analysis ID format: send the 24-character analysis ID.
  • Sender field is required: send sender.
  • The Analsys is not possible to update as status changed! (spelled this way): the analysis is no longer Pending.
401Fix the request
The key is missing (Token is require.) or unknown (Token is wrong.), it's a personal key, or it lacks sendMessage (Your API key does not have permission to access this action). Send Authorization: Bearer <API_KEY> with a Community API key, and add Send Messages in Settings > Integration > API Keys.
500Fix the request

Read the body:

  • The analysis was not created by the user: sender isn't the member who created the analysis. Send the creator's username or email; nothing was added.
  • Failed to append drawings: the change failed. Read the analysis with Get analysis, then send only the drawings that are missing.

Fix the data01

404Fix the data
Analysis not found: no analysis has this ID, or it was deleted. User not found: no member of your community has the sender username or email.
{
  "status": "fail",
  "statusCode": 400,
  "message": "clientObjectId must be unique. Duplicate IDs found: stop_line"
}

Next step#

Check the drawings with Get analysisGET/v1/analysis/{analysisId}Read the analysis back and find each new drawing by its clientObjectId.