SuperAPI AI Directory

fast-ship

Coding & development

View repository

Updated 10-15 21:52

About this skill

Fast Ship API
What you want to do Actual call
Leave a note/comment/post a completion summary on an issue PUT /api/issues/:iid/collab/summary(posting a comment with an API Key always returns 40301)
Mark as done PUT /api/issues/:iid/internal-meta set workflow_status=done(not state)
Close issue Not possible—JWT only; passing an API Key to state always returns 40301
Started working on it PUT /api/issues/:iid/internal-meta set in_progress
Record consensus/decisions PUT /api/issues/:iid/collab/consensus
By INT-xxx find issue GET /api/projects/:pid/issues?q=INT-56 switch to UUID (path parameters only accept UUIDs)
Attach a PR to an issue POST /api/issues/:iid/pull-requests,body {"url":"<PR链接>"}
Refresh PR status POST /api/issues/:iid/pull-requests/sync(call after merging; for per-line failures see failures[])
Remove a PR DELETE /api/issues/:iid/pull-requests/:lid(:lid is the link row id, i.e. the {id})

Before calling any write endpoint, first read references/api.md the corresponding section; do not construct the request body from memory.

In the table above, :pid in api.md is {id},:iid is {iid};:lid is the PR link row id (in api.md, pull-requests under the path, {id})。

Authentication configuration

Fast Ship uses API Key for programmatic authentication. The key format is a random string starting with fsk_ .

Request method (hard rules)

  • ProhibitedReading the API Key out and writing it into commands, parameters, environment variable assignments, or any output—curl -H "Authorization: Bearer fsk_..." such usage leaves the Key in session logs and process lists.
  • All requests must go through the skill's bundled script. The script reads config itself and attaches the authentication header, so the Key never appears on the command line:
node <技能目录>/scripts/fast-ship-api.mjs <METHOD> <path> [body.json] [--verify [读回路径]]
  • When a request body is required, write the JSON to a UTF-8 file and pass it as the body.json positional parameter.
  • --verify [读回路径]: after a successful write request (2xx), send one more GET and output { "response": …, "verify": … }, for read-back verification after write. By default it GETs the same path; for write endpoints without a corresponding GET route (e.g. internal-meta、recommendation、collab PUT; for batch PUT /api/issues/internal-meta the default read-back will hit GET /issues/:iid and 404) you must explicitly provide the read-back path (e.g. for the Issue itself, GET /api/issues/:iid). For DELETE, a read-back 404 is treated as confirmation of deletion.
  • Fallback when the script is unavailable: write the Authorization: Bearer <api_key> line as a whole into a temporary header file, reference it with curl -H @<header文件> , and after usedelete immediatelythat file.

First use (config persistence)

If ~/.config/fast-ship/config.yaml does not exist,mustask the user for the following information:

  1. Base URL: Fast Ship service address, e.g. http://localhost:8080 or https://fast-ship.example.com
  2. API Key: a key created from the Fast Ship web interface under "Settings → API Key" (fsk_ starting with)

Then write the configuration to the file:

# ~/.config/fast-ship/config.yaml
base_url: "https://fast-ship.example.com"
api_key: "fsk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Note:~/.config the directory usually already exists on macOS/Linux; if it does not, create the directory first.

Subsequent use

The script reads ~/.config/fast-ship/config.yaml from base_url and api_key,no longer asks the user。Agent do notRead the Key out and write it into a command or output.

Request headers

The script automatically carries the following request headers for all requests (no need to add them manually):

Authorization: Bearer <api_key>
Content-Type: application/json; charset=utf-8

Core workflow

When the source is not specified, create source: "internal". Use source: "github"only when the user explicitly requests syncing GitHub. An API Key can only create internal.

For fields, always see references/api.md; only the endpoints are kept here.

  1. GET /api/projects, determine project_id。
  2. before tagging, first GET /api/projects/{id}/issues/repo-labels. When the project has no GitHub repository configured or the labels are empty, change GET /api/projects/{id}/issues/filter-options。
  3. POST /api/projects/{id}/issues to create. For subsequent paths, only use the id(UUID) from the response. The page given to the user is {base_url}/projects/{project_id}/issues/{id}。
  4. To tag, PUT /api/issues/{iid}, and the label name must already exist. Do not rely on the workflow_status in the create request to advance progress.
  5. To advance, use PUT /api/issues/{iid}/internal-meta, with the value being todo、in_progress or done。
  6. To query one, use GET /api/issues/{iid}. For a list, use GET /api/projects/{id}/issues。

Screenshot annotations (AI review loop)

The rectangular box-selection annotations drawn on the canvas of the screenshot page are attached toa specific screenshot versionfor humans/AI to exchange review comments. An API Key can read all annotations, pull cropped images, and mark as resolved; it cannot create/delete annotations (40301), and changing text/linking an Issue/reopening also requires a JWT.

  • List:GET /api/projects/{id}/screenshot-annotations → {items:[...]}, and the query can be filtered by status(open/resolved)、issue_id、screen_id .
  • Issue dimension:GET /api/issues/{iid} 's screenshot_annotations[] embeds the annotations linked to that Issue (omitted if none).
  • Each annotation carries:image_url(the original image of the version it is in),crop_url(a cropped image of the box-selected area, PNG, with margins on all sides), proportional coordinates x/y/width/height(0~1), pixel coordinates pixel_rect(null when the size is unknown),screen_key/screen_title/screen_group、is_latest_version、status。
  • crop_url/image_url is the <img> direct-link path: the script only needs to include the Authorization header when calling; only the Web side's <img> requires ?token=<jwt>。
  • Mark as resolved:PUT /api/screenshot-annotations/{aid}, and the body as a whole passes only {"status":"resolved"}—including other fields or open will result in 40301.
  • When the original image exceeds the decoding pixel limit (about 64MP), crop returns 40004 (尺寸超出可处理范围); in this case, use image_url to pull the original image and scale it yourself.

AI review loop (for field details, see the screenshots chapter of api.md):

  1. GET /api/issues/{iid} Read screenshot_annotations, or filter project annotations by issue_id/status=open .
  2. By crop_url pull the cropped image to see which area the user box-selected and what comment they wrote.
  3. After modifying the UI,POST /api/projects/{id}/screenshots upload a new screenshot withthe same screen_key (it is automatically grouped into the same interface as a new version; old annotations remain attached to the old version, andis_latest_version becomes false).
  4. Mark each PUT {"status":"resolved"} as resolved one by one.

Deleting an Issue only clears the annotation's issue_id(the annotation is retained); deleting a screenshot version/interface cascades to delete annotations.

Issue linked to a PR

One Issue can have multiple PRs attached (cross-repository is also possible).Timing: attach immediately after creating the PR so that implementation progress can be seen on the Issue page; after the PR is merged, call sync once to refresh the status.

  • attach: the body passes only {"url":"https://github.com/<owner>/<repo>/pull/<n>"}, supporting /files, query, and other suffixes. The server fetches the title/status/author from GitHub on its own; if the fetch fails, no record is written (502). Repeated attach is idempotent and does not produce a second row.
  • Read: details GET /api/issues/:iid of pull_requests[] is the full list; list items carry pull_request_summary {total, open, merged}(closed = total - open - merged)。
  • sync: returns {items, failures}, each PR is an independent failure domain—if one cannot be fetched (404/rate limit) it only goes into failures[], and the rest refresh as usual;failures[].id is the associated row id.
  • detach:DELETE /api/issues/:iid/pull-requests/:lid; a nonexistent association returns 40412 (not idempotent; repeated calls will error).
  • PR status and workflow_status are not coupled: all PRs merged does not mean the requirement is complete,internal-meta still has to be advanced on its own.
  • link_origin=manual associations are never mistakenly deleted by the cleanup logic of the GitHub sync projection.

Semantic pitfalls and permission division of labor

multipart

These endpoints are curl -F file=@路径, not JSON. The Issue image response contains markdown; only by pasting this into the body is the attachment actually attached.

  • POST /api/auth/avatar
  • POST /api/projects/{id}/issues/assets(draft, JWT only)
  • POST /api/issues/{iid}/assets
  • POST /api/versions/{vid}/artifacts(optional form field platform)

Field-level permissions

The spec's security often lists both JWT and API Key, but the real rejection happens in the handler.

  • API Key cannot pass state / state_reason, cannot POST /api/issues/{iid}/comments, cannot PUT or DELETE /api/issues/{iid}/ship-hook. Doing so results in 403 (40301).ship_hook only appears in the Issue's GET and list, read-only.
  • PUT /api/issues/{iid}/collab/consensus、PUT /api/issues/{iid}/collab/summary、PUT /api/issues/{iid}/recommendation only accepts API Key. JWT calls return 403 (40303).
  • After a recommendation is deferred by the user,PUT recommendation returns 409 (40911)—do not retry recommending, and do not try to DELETE (also 40911).PUT/DELETE /api/issues/{iid}/recommendation/defer is defer/restore, JWT only (API Key 40301). Completely removing a deferred item can only be done by a JWT user.
  • POST /api/projects/{id}/logs only accepts API Key. JWT calls return 403 (40303).

checklist is a whole-group replacement

PUT /api/issues/{iid}/checklist submitted items is the final list. Old entries not included will be deleted.items=[] will clear the checklist.

q is an in-memory full filter

GET /api/projects/{id}/issues of q is not an index query. It scans the full set, matching title, body, author login,INT-xxx / GH-xxx. Pure digits will also match sequence_number or the GitHub number.

Details come with collab

GET /api/issues/{iid} data contains collab(consensus and summary). List items do not. To see the collaboration area, just read the details; there is no need to call GET /collab。

Batch workflow changes

PUT /api/issues/internal-meta request body is {items:[{issue_id, workflow_status}]}, at most 200 entries. If one entry fails, the whole batch does not become 4xx; HTTP remains 200, see failures[]。

collab read before write

PUT Before consensus or summary, GET first. Do not write back blocks the user has already cleared.DELETE is idempotent; if the target never existed, it also returns 200.

Do not write consensus before the follow-up questions are finished. After the decisions are all asked and the user confirms work can start, then PUT the content that has been decided. If the user says stop asking and just do it, leave the consensus empty; do not make up "implement according to the original Issue text." Do not close the ticket without permission, and do not commit or push code.

Write the completion summary for ordinary people to read; two paragraphs are enough: how it was before, how it is now. Do not list files, do not paste commit SHAs, do not write a test checklist. If the changes have not yet landed on a perceptible result, then do not write "now" yet.

Request encoding

Write the request body as a UTF-8 JSON file, using the script's body.json Passed in. Do not concatenate Chinese in the shell.

Breaking Changes

  • API Key Not allowedvia PUT /api/issues/:issue_id to modify state / state_reason(open/close); the Agent should instead use PUT /api/issues/:issue_id/internal-meta 's workflow_status to mark completion; open/close is operated by the JWT user on the Web side.
  • API Key Not allowedpost comments (POST /api/issues/:issue_id/comments)。
  • API Key Not allowed PUT/DELETE /api/issues/:issue_id/ship-hook。ship_hook only appears in Issue GET/list for read-only. After shipment, closing the order/leaving a message is configured by the JWT user on the Web, and executed by the server after successful shipment.
  • Legacy collaboration endpoint POST/PUT/DELETE /collab/notes、/collab/questions has been removed;suggestions、plan、review and commit_ids are both deprecated. The current GET /collab only returns consensus and summary。