Returning.AIDevelopers
v1

API reference / Chart Analysis

.md

Update analysis

Change a pending chart analysis's title, scenarios, expiry, timeframe, direction with new levels, or its drawings.

Last updated 26 Sep 2026API v1

Method
PATCH
Path
https://api.returning.ai/v1/analysis/{analysisId}
Permission
sendMessage
Retries
No Idempotency-Key; read back before retrying

When to use this

  • Correct a typo in an analysis title or scenario after it was posted.
  • Extend or shorten how long an idea stands by changing its expiry.
  • Flip an idea from bullish to bearish, with a new set of levels.

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 update it. Only send IDs from your own community's analyses. Personal API keys are not accepted here and return 401.

Behaviour#

Only a Pending analysis can be updated. Send at least one of metadata, levels or drawings. Fields you leave out, or send empty, keep their values, and metadata.symbol is ignored.

The card type comes from direction and entryPlacement. Levels move with the type: if a change to either field gives a new type, send a full levels set in the same request, and levels is refused in any other request. Changing direction or entryPlacement without changing the type, for example sending the current value again, counts as no type change.

drawings replaces the whole drawing set, and is saved only alongside a metadata or levels change. To add drawings on their own, use Append drawings.

Any request with metadata or levels rewrites the channel post and fires your message webhooks. When the title, a scenario, the type or the levels change, a bot message about the edit is also added to the card's discussion. Members with the channel open see the change straight away.

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"

metadata#objectOPTIONAL
The fields to change. Leave a field out, or send it empty, to keep its value. The symbol can't be changed.

Eg{"title": "EURUSD bounce holds above support"}

title#stringOPTIONAL
New card title.

Rule1-200 characters

Eg"EURUSD bounce holds above support"

preferenceText#stringOPTIONAL
New main scenario. [[clientObjectId:text]] links must name a level or drawing on the card.

Rule1-5000 characters

alternativeText#stringOPTIONAL
New alternative scenario. Same links.

RuleUp to 5000 characters

comments#stringOPTIONAL
New comments. Same links.

RuleUp to 5000 characters

expiry#objectOPTIONAL
New expiry: {"type": "GTC"}, or {"type": "HOURS", "hours": 1-8760}.

Eg{"type": "GTC"}

type#stringREQUIRED
Good Till Cancelled

RuleGTC

hours#integerOPTIONAL
Hours the idea stands. Required when type is HOURS.

Rule1-8760

Eg48

timeframe#stringOPTIONAL
New chart timeframe.

RuleM1, M5, M15, M30, H1, H2, H4, D, W or M

Eg"H4"

direction#stringOPTIONAL
New market bias. If this changes the card type, levels is required in the same request.

RuleBULLISH or BEARISH

Eg"BEARISH"

entryPlacement#stringOPTIONAL
New entry placement. If this changes the card type, levels is required in the same request.

RuleABOVE_CURRENT or BELOW_CURRENT

Eg"ABOVE_CURRENT"

levels#objectOPTIONAL
A full new set of levels, in the same shape as Create analysis (pivot, resistance and support required, in price order). Accepted only in a request whose direction or entryPlacement changes the card type; otherwise it returns 400 Pivot value can not be changed.
pivot#objectREQUIRED
The centre level.
price#numberREQUIRED
Price of the level.

Eg1.1

clientObjectId#stringREQUIRED
Your own name for the level, unique among the levels. Use it in text links.

RuleMin 1 chars

Eg"pivot_main"

time#stringOPTIONAL
Optional chart time for the level.

RuleISO 8601 date-time

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

resistance#objectREQUIRED
Main resistance, above the pivot.
price#numberREQUIRED
Price of the level.

Eg1.12

clientObjectId#stringREQUIRED
Your own name for the level, unique among the levels. Use it in text links.

RuleMin 1 chars

Eg"resistance_main"

time#stringOPTIONAL
Optional chart time for the level.

RuleISO 8601 date-time

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

support#objectREQUIRED
Main support, below the pivot.
price#numberREQUIRED
Price of the level.

Eg1.08

clientObjectId#stringREQUIRED
Your own name for the level, unique among the levels. Use it in text links.

RuleMin 1 chars

Eg"support_main"

time#stringOPTIONAL
Optional chart time for the level.

RuleISO 8601 date-time

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

intermediateResistance#objectOPTIONAL
Optional level between the pivot and resistance.
price#numberREQUIRED
Price of the level.

Eg1.11

clientObjectId#stringREQUIRED
Your own name for the level, unique among the levels. Use it in text links.

RuleMin 1 chars

Eg"resistance_inner"

time#stringOPTIONAL
Optional chart time for the level.

RuleISO 8601 date-time

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

intermediateSupport#objectOPTIONAL
Optional level between support and the pivot.
price#numberREQUIRED
Price of the level.

Eg1.09

clientObjectId#stringREQUIRED
Your own name for the level, unique among the levels. Use it in text links.

RuleMin 1 chars

Eg"support_inner"

time#stringOPTIONAL
Optional chart time for the level.

RuleISO 8601 date-time

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

drawings#object[]OPTIONAL
Replaces every drawing on the card; [] removes them all. Saved only when the same request also sends metadata or levels: a request with only drawings returns 200 and changes nothing.

Rule0-20 items

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

RuleHORIZONTAL_LINE, LINE, RECTANGLE, PARALLEL or FIB_RETRACEMENT

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

time#string | integerREQUIRED
Point time.

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

price#numberREQUIRED
Point price.

Eg1.09

style#objectOPTIONAL
Optional colours and line style.
color#stringOPTIONAL
Line colour.

Rule#RRGGBB

Eg"#FF0000"

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 PATCH \
  --url https://api.returning.ai/v1/analysis/66f000000000000000000b01 \
  --header 'Authorization: Bearer <API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{
    "sender": "trader@example.com",
    "metadata": {
      "title": "EURUSD bounce holds above support"
    }
  }'

Response#

A 200 returns the updated analysis in data.analysis, not a list of changed fields. Replaced drawings get new saved IDs, so match them on 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"Analysis updated successfully"

data#objectALWAYS
Holds the updated analysis.

Eg{ ... }

analysis#objectALWAYS
The analysis after the update, with the same fields as data.analysis in Get analysis, without message.
{
  "status": "success",
  "statusCode": 200,
  "message": "Analysis updated 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 holds above 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]
        }
      ],
      "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 holds above 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:10:00.000Z",
      "__v": 0
    }
  }
}

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 changed. Read message:

  • Update Analysis Request Validation validation error.: a field breaks its rule, such as an unknown timeframe or levels out of order. detail names the field.
  • 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 and can't be changed.
  • When updating direction or entryPlacement, levels must be provided: the card type changes, so send the new levels too.
  • Pivot value can not be changed: levels was sent without a change of card type. Leave levels out, or change direction or entryPlacement as well.
  • Text links reference non-existent objectIds: a link names an ID that isn't on the card; invalidObjectIds lists them.
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 changed.
  • An HTML error page: the body has none of metadata, levels or drawings, or it sends levels or drawings together with a text link to an ID that isn't in them. Fix the body; nothing was changed.
  • Failed to update analysis: the update failed, and detail has the reason. Read the analysis back with Get analysis before you retry.

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. Check the value and send again.
{
  "status": "fail",
  "statusCode": 400,
  "message": "The Analsys is not possible to update as status changed!"
}

Next step#

Check the result with Get analysisGET/v1/analysis/{analysisId}Read the analysis back to confirm the change, or after a timeout before you retry.