Developers

Put large-file delivery in the workflow.

Automate yasync with the API, MCP, or CLI. These tools require Pro; the browser and desktop app remain available on every tier.

Authentication

  • Create keys under Dashboard → API keys. Pro accounts can create keys; keys look like ysk_ + 40 characters and act as the account that created them.
  • Send the key on every request as Authorization: Bearer ysk_…. Bearer keys are the only auth on /api/v1 and /api/mcp — no cookies, no sessions.
  • The full key is shown once at creation; we store only a keyed hash. Lost it? Revoke and mint a new one — revocation applies immediately.

Every request

curl -s https://yasync.com/api/v1/transfers \
  -H "Authorization: Bearer ysk_a1b2c3d4…"

Remote MCP: the transfer workflow as tools

Connect a Streamable HTTP MCP client to https://yasync.com/api/mcp and send the same Bearer key. The endpoint is stateless and returns JSON. It never accepts file bodies: upload planning tools return presigned URLs, and the client PUTs each part directly to object storage.

Available tools

  • yasync_create_transfer, yasync_list_transfers, yasync_get_transfer
  • yasync_register_file, yasync_plan_upload, yasync_get_upload_status
  • yasync_sign_upload_parts, yasync_complete_upload, yasync_abort_upload
  • yasync_finalize_transfer, yasync_delete_transfer

The tools call the same transfer and upload core as REST, so plan limits, ownership checks, resume state, and API-key rate limits stay consistent.

List the MCP tools

curl -s -X POST https://yasync.com/api/mcp \
  -H "Authorization: Bearer $YASYNC_KEY" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'

Quickstart: send a file in six curls

The whole send pipeline, by hand. Export YASYNC_KEY first, then carry transferId, fileId, and uploadId forward from each response.

  1. 1 — Create a transfer

    Persist one UUID and reuse it on retries. Everything after this hangs off the returned transferId.

    curl -s -X POST https://yasync.com/api/v1/transfers \
      -H "Authorization: Bearer $YASYNC_KEY" \
      -H "Content-Type: application/json" \
      -d "{"creationRequestId":"$TRANSFER_REQUEST_UUID"}"
    # → {"transferId":"cme3k…","slug":"k4q0z7f2m9d1ab","url":"https://yasync.com/t/k4q0z7f2m9d1ab"}
  2. 2 — Register the file

    Name + exact byte size. Persist a key-safe fileId and reuse it on retries. Folder structure travels in the name ("renders/shot_010.mov").

    curl -s -X POST https://yasync.com/api/v1/transfers/$TRANSFER_ID/files \
      -H "Authorization: Bearer $YASYNC_KEY" \
      -H "Content-Type: application/json" \
      -d "{"fileId":"$CLIENT_FILE_ID","name":"big.mov","size":83886080}"
    # → {"fileId":"x7f3…","name":"big.mov","size":"83886080","contentType":"video/quicktime"}
  3. 3 — Plan the upload

    Compute the whole-file CRC32 locally first. Under 100 MiB it is required in the plan because the returned single-PUT URL is checksum-pinned; bigger files switch to per-part CRC32 — see below.

    curl -s -X POST https://yasync.com/api/v1/transfers/$TRANSFER_ID/uploads \
      -H "Authorization: Bearer $YASYNC_KEY" \
      -H "Content-Type: application/json" \
      -d "{"fileId":"x7f3…","fileSize":83886080,"crc32":"$CRC32_HEX"}"
    # → {"uploadId":"u01b…","mode":"s3_single_put","uploadUrl":"https://…","checksumCrc32":"…","requiredHeaders":{"x-amz-checksum-crc32":"…"}, …}
  4. 4 — PUT the bytes

    Straight to object storage — yasync never proxies your file bytes. Send the plan’s Content-Type and every returned requiredHeaders entry.

    curl -s -X PUT "$UPLOAD_URL" \
      -H "Content-Type: video/quicktime" \
      -H "x-amz-checksum-crc32: $CHECKSUM_CRC32_BASE64" \
      --data-binary @big.mov
  5. 5 — Complete the upload

    CRC32 is required again at completion. The server verifies stored size; for multipart it also folds the ordered, R2-validated part checksums and matches the whole-file CRC32.

    curl -s -X POST https://yasync.com/api/v1/transfers/$TRANSFER_ID/uploads/$UPLOAD_ID/complete \
      -H "Authorization: Bearer $YASYNC_KEY" \
      -H "Content-Type: application/json" \
      -d "{"crc32":"$CRC32_HEX"}"
  6. 6 — Finalize → link

    Add an optional title, message, password, and recipient emails. You can also share the returned link yourself.

    curl -s -X POST https://yasync.com/api/v1/transfers/$TRANSFER_ID/finalize \
      -H "Authorization: Bearer $YASYNC_KEY" \
      -H "Content-Type: application/json" \
      -d '{"title":"Rough cut v4","password":"review-secret"}'
    # → {"url":"https://yasync.com/t/k4q0z7f2m9d1ab"}

Big files: multipart

Files of 100 MiB and up plan as mode: "s3_multipart" with a fixed partSize and partCount. Request presigned part URLs in batches, PUT the parts in parallel with each URL’s requiredHeaders (keep each response’s ETag header), then send them all to /complete. Interrupted? Ask /status which parts already landed and resume from there.

# CRC32 each part locally; base64-encode its four big-endian bytes.
# Sign URLs for parts 1-2 (batch up to 100 per call).
curl -s -X POST https://yasync.com/api/v1/transfers/$TRANSFER_ID/uploads/$UPLOAD_ID/parts \
  -H "Authorization: Bearer $YASYNC_KEY" \
  -H "Content-Type: application/json" \
  -d '{"parts":[{"partNumber":1,"checksumCrc32":"y/Q5Jg=="},{"partNumber":2,"checksumCrc32":"QixqFQ=="}]}'

# PUT each part with its returned x-amz-checksum-crc32 header. Then complete
# with every ETag, the same part checksums, and the required whole-file CRC32.
curl -s -X POST https://yasync.com/api/v1/transfers/$TRANSFER_ID/uploads/$UPLOAD_ID/complete \
  -H "Authorization: Bearer $YASYNC_KEY" \
  -H "Content-Type: application/json" \
  -d '{"parts":[{"partNumber":1,"etag":"\"9b2cf5…\"","checksumCrc32":"y/Q5Jg=="},{"partNumber":2,"etag":"\"41ac00…\"","checksumCrc32":"QixqFQ=="}],"crc32":"3f8d2a1c"}'

Endpoint reference

All byte counts are JSON strings (they can exceed 2⁵³). Timestamps are ISO 8601. Base URL: https://yasync.com.

MethodPathWhat it does
POST/api/v1/transfersCreate a draft; creationRequestId makes retries idempotent
GET/api/v1/transfersList your transfers — cursor pagination via ?limit & ?cursor
GET/api/v1/transfers/{id}Transfer details + completed files
DELETE/api/v1/transfers/{id}Delete a transfer and its files
POST/api/v1/transfers/{id}/filesRegister a file; client fileId makes retries idempotent
POST/api/v1/transfers/{id}/uploadsPlan an upload: checksum-pinned single PUT (< 100 MiB) or multipart
POST/api/v1/transfers/{id}/uploads/{uploadId}/partsBatch-sign checksum-pinned multipart part URLs (up to 100 per call)
POST/api/v1/transfers/{id}/uploads/{uploadId}/completeComplete an upload — validates checksums and stored size
GET/api/v1/transfers/{id}/uploads/{uploadId}/statusUpload state + which parts already landed (resume)
DELETE/api/v1/transfers/{id}/uploads/{uploadId}Abort an upload session
POST/api/v1/transfers/{id}/finalizePublish: draft → live share link (title, message, optional password and recipient emails)

Errors

Every non-2xx response has one stable shape. code is machine-matchable and never changes meaning within v1; message is for humans; some errors add a details object (e.g. the exact byte caps).

{
  "error": {
    "code": "FILE_TOO_LARGE",
    "message": "Files on this tier are limited to 50 GB",
    "details": { "maxFileBytes": "53687091200" }
  }
}
CodeMeaning
INVALID_API_KEYMissing, malformed, or revoked key — check the Authorization header
PRO_REQUIREDThe key owner is not currently entitled to Pro automation access
RATE_LIMITEDA rate limit tripped — back off and retry with jitter
NOT_FOUNDThe transfer/upload does not exist or is not yours
BAD_REQUESTMalformed body or parameters (message says what)
TRANSFER_NOT_DRAFTFiles/uploads only work before finalize
FILE_TOO_LARGESingle file exceeds your tier cap
TRANSFER_TOO_LARGEWhole transfer exceeds your tier cap
FILE_SIZE_MISMATCHfileSize differs from the registered file
UPLOAD_ALREADY_ACTIVEA session for this file is live — abort it before re-planning
UPLOAD_NOT_ACTIVESession already completed/cancelled/failed
UPLOAD_SESSION_EXPIREDSession outlived its 48 h window — plan again
UPLOADS_IN_PROGRESSFinish or abort open uploads before finalizing
NO_COMPLETED_FILESFinalize needs at least one completed file
STORAGE_LIMITStorage cap reached with auto-scale off — enable auto-scale or free space

Rate limits

  • 120 requests / minute per key across all v1 endpoints.
  • 60 transfer creations / 10 minutes per key — batch files into one transfer instead of one transfer per file.
  • 120 part-signing calls / minute per upload, each signing up to 100 part URLs — that comfortably feeds thousands of parallel parts.
  • Hitting a limit returns 429 with code: "RATE_LIMITED" — back off and retry. Presigned PUTs to storage are not rate-limited by us.

Command line

The yasync CLI sends and receives files from scripts and servers. It requires Pro. Use --json for machine-readable output.

yasync login                          # link this machine to your account (browser approval)
yasync send big.mov --json            # create → upload → finalize; prints the link
yasync send renders/ --title "Night renders" --password s3cret
yasync receive https://yasync.com/t/k4q0z7f2m9d1ab -o ~/Downloads
yasync ls                             # your transfers
yasync rm cme3k…                      # delete one
Download desktop & CLI

The Apps page lists verified macOS Apple Silicon, Windows x86_64, and Linux x86_64 downloads with installer instructions.

Versioning & stability

  • /api/v1 is stable: fields are only ever added. Anything breaking ships as /api/v2 — v1 keeps working.
  • /api/mcp is a thin adapter over the same v1 transfer core. Tool schemas may gain optional fields, but existing tool names and required inputs remain compatible.
  • Write clients that tolerate unknown JSON fields and match errors by error.code, not message text.
  • An OpenAPI spec is on the roadmap for a later release; this page is the v1 reference for now.