Returning.AIDevelopers
v1

API reference / Chart Analysis

.md

Create analysis

Post a chart analysis card, with direction, price levels and optional drawings, into a chart-enabled channel on behalf of a member.

Last updated 26 Sep 2026API v1

Method
POST
Path
https://api.returning.ai/v1/analysis/{communityId}/channels/{channelId}
Permission
sendMessage
Retries
Not idempotent; list the channel before retrying

When to use this

  • Your analysts write trade ideas in your own tools, and you want each one to appear as a chart card in your community.
  • You publish a daily outlook for a symbol, with pivot, support and resistance levels drawn on the chart.
  • You want a member's analysis to count toward their XP and appear in every member's activity feed.

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. The analysis is saved in the community that owns the key, whatever communityId you put in the path, so only post to your own channels. With a Community API key you must name the member in sender; the card appears as their post. Personal API keys are not accepted here and return 401.

Behaviour#

The channel must have Enable Charts turned on, and metadata.symbol must be the chart symbol chosen in that channel's settings. The sender must be a member of your community with permission to post in the channel. After the body is validated, the checks run in this order: the channel exists, sender is given and found, Enable Charts is on, the sender may post, and the symbol matches. Nothing is posted when one fails.

A successful create does all of this at once: it posts the card in the channel as the sender, shows it live to members who have the channel open, adds a trade idea to every member's activity feed, may award the sender XP and coins under your community's rules, and fires your message webhooks.

Every new analysis starts as Pending. You can update it, or add drawings to it, only while it stays Pending.

Request#

Path parameters#

communityId#stringREQUIRED
Your community's ID. The analysis is always saved in the community that owns your API key.

Rule24 hex characters

Eg"66f000000000000000000010"

channelId#stringREQUIRED
The channel to post in. It must have Enable Charts turned on in its channel settings.

Rule24 hex characters

Eg"66f000000000000000000b11"

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 the card is posted as. They must belong to your community and be allowed to post in the channel.

RuleUsername or email

Eg"trader@example.com"

metadata#objectREQUIRED
What the analysis says.

Eg{ ... }

direction#stringREQUIRED
Market bias.

RuleBULLISH or BEARISH

Eg"BULLISH"

entryPlacement#stringREQUIRED
Where the entry sits against the current price. With direction it sets the card type: bullish and ABOVE_CURRENT is a bullish breakout, bullish and BELOW_CURRENT a bullish bounce, bearish and ABOVE_CURRENT a bearish bounce, bearish and BELOW_CURRENT a bearish breakout.

RuleABOVE_CURRENT or BELOW_CURRENT

Eg"BELOW_CURRENT"

expiry#objectREQUIRED
How long the idea stands.

Eg{"type": "HOURS", "hours": 24}

type#stringREQUIRED
GTC (good till cancelled) or HOURS.

RuleGTC or HOURS

Eg"HOURS"

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

Rule1-8760

Eg24

title#stringREQUIRED
Card title.

Rule1-200 characters

Eg"EURUSD bounce from support"

preferenceText#stringREQUIRED
Your main scenario. [[clientObjectId:text]] links a phrase to a level or drawing, which is highlighted on hover.

Rule1-5000 characters

Eg"Price is holding above [[support_main:support]]. Look for longs toward [[resistance_main:resistance]]."

alternativeText#stringOPTIONAL
The alternative scenario. Supports the same links.

RuleUp to 5000 characters

comments#stringOPTIONAL
Extra comments. Supports the same links.

RuleUp to 5000 characters

timeframe#stringREQUIRED
Chart timeframe.

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

Eg"H1"

symbol#stringREQUIRED
The channel's chart symbol, set in its channel settings. Not case-sensitive; saved in upper case.

Eg"EURUSD"

levels#objectREQUIRED
Price levels on the card. Each level has a price, a clientObjectId unique among the levels, and an optional ISO 8601 time. Order must be support, intermediate support, pivot, intermediate resistance, resistance, from lowest to highest price.

Eg{ ... }

pivot#objectREQUIRED
The centre level.

Eg{ ... }

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.

Eg{ ... }

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.

Eg{ ... }

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
Optional chart drawings, up to 20. Each clientObjectId must be unique among the drawings.

Rule0-20 items

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. Use it in text links, and to find the drawing again in the response.

RuleMin 1 chars

Eg"entry_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.095}]

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.095

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.
style#objectOPTIONAL
Optional colours and line style.

Eg{"color": "#2E7D32"}

color#stringOPTIONAL
Line colour.

Rule#RRGGBB

Eg"#2E7D32"

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

idempotencyKey#stringOPTIONAL
Accepted but not used. It does not prevent a duplicate card, so list the channel before you retry.

Eg"analysis_20250109_001"

curl --request POST \
  --url https://api.returning.ai/v1/analysis/66f000000000000000000010/channels/66f000000000000000000b11 \
  --header 'Authorization: Bearer <API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{
    "sender": "trader@example.com",
    "metadata": {
      "direction": "BULLISH",
      "entryPlacement": "BELOW_CURRENT",
      "expiry": {
        "type": "HOURS",
        "hours": 24
      },
      "title": "EURUSD bounce from support",
      "preferenceText": "Price is holding above [[support_main:support]]. Look for longs toward [[resistance_main:resistance]].",
      "timeframe": "H1",
      "symbol": "EURUSD"
    },
    "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"
      }
    },
    "drawings": [
      {
        "type": "HORIZONTAL_LINE",
        "clientObjectId": "entry_line",
        "points": [
          {
            "time": "2026-09-27T08:00:00.000Z",
            "price": 1.095
          }
        ],
        "style": {
          "color": "#2E7D32"
        }
      }
    ]
  }'

Response#

A 200 (not 201) means the card is posted. Save data.analysisId. data.objectIdMap tells you the saved ID behind each clientObjectId you sent; you need your own clientObjectId values again when you add drawings, because they must not repeat.

status#stringALWAYS
Result of the request.

Rulesuccess

message#stringALWAYS
Human-readable summary. Do not branch on it.

Eg"Analysis created successfully"

data#objectALWAYS
The new analysis.

Eg{ ... }

analysisId#stringALWAYS
The analysis ID. Use it to read, update, extend or delete the analysis.

Eg"66f000000000000000000b01"

objectIdMap#objectALWAYS
Each clientObjectId you sent, mapped to its saved ID. Levels map to the card ID plus a position, such as <cardId>:8 for the pivot; drawings map to their own IDs.

Eg{ ... }

{
  "status": "success",
  "message": "Analysis created successfully",
  "data": {
    "analysisId": "66f000000000000000000b01",
    "objectIdMap": {
      "pivot_main": "66f000000000000000000b41:8",
      "support_main": "66f000000000000000000b41:0",
      "resistance_main": "66f000000000000000000b41:7",
      "entry_line": "66f000000000000000000b31"
    }
  }
}

Errors#

These errors have no machine-readable code; branch on the HTTP status and read message. The 401 for a missing or unknown key has detail and a meta object; the 401 for a missing permission has only message. A validation 400 names each field in detail. Other errors carry status and message.

Fix the request02

400Fix the request

The request was rejected before anything was posted. Read the body:

  • Create Analysis Request Validation validation error.: a field is missing or breaks its rule, such as a lower-case direction, levels out of order or repeated clientObjectId values. detail names each field.
  • Sender field is required: send sender.
  • Channel does not support analysis posts (chartsEnabled is false): turn on Enable Charts in the channel's settings, or use a chart channel.
  • Symbol <SYMBOL> is not supported by this channel. Allowed symbols: ...: send the channel's chart symbol.
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.

Fix the data02

403Fix the data
The sender isn't allowed to post in this channel. Give the member, or one of their roles, permission to post there, or send as another member.
404Fix the data
User not found: no member of your community has this username or email. Channel not found: no channel has this ID. Check the value and send again.

Retry with backoff01

500Retry with backoff
Error creating analysis: the create failed part way, and detail has the reason. List the channel before you retry, because the card may already be posted. A 500 with an HTML error page means a [[clientObjectId:text]] link names an ID that is not in levels or drawings; fix the link, since nothing was posted.
{
  "status": "error",
  "message": "Channel does not support analysis posts (chartsEnabled is false)"
}

Next step#

Read the new card back with Get analysisGET/v1/analysis/{analysisId}Use data.analysisId to read the saved levels, drawings and status.