> ## Documentation Index
> Fetch the complete documentation index at: https://www.ayrshare.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 使用 GraphQL API

> 透過 Ayrshare GraphQL API 尋找操作、了解引數型別與列舉、建立貼文及上傳媒體。

<h2 id="finding-an-operation">
  尋找操作
</h2>

對於受支援的 GraphQL 子集，schema 是權威來源：包括操作根、名稱、引數、輸入型別與列舉值。說明文字則提供使用指引，[GraphQL Explorer](https://app.ayrshare.com/graphql-explorer) 會同時呈現這兩者。僅限 REST 的功能請參閱 [REST API 參考](/docs/apis/overview)。

操作名稱依照其對應的 REST 端點命名，並採用 camelCase。`GET /history` 對應 `postHistory`，`GET /analytics/social` 對應 `socialAnalytics`，`POST /post` 對應 `createPost`。

<h2 id="queries-read-mutations-write">
  Query 用於讀取，mutation 用於寫入
</h2>

Query 是讀取與驗證操作，不會在我們這端變更任何東西。Mutation 則會發布或變更狀態、啟動工作或寄送電子郵件。決定根類型的既不是 REST 的 HTTP 動詞，也不是呼叫的成本：

<ul class="custom-bullets">
  <li><code>validatePost</code> 會檢查貼文，但不會發布。</li>
  <li><code>validateMedia</code> 會檢查媒體 URL 是否可存取。</li>
  <li><code>generatePost</code> 是 query，因為它不會在我們這端變更任何東西。但它仍算作一次 API 呼叫，且每次都會傳回不同的文字，因此請確保用戶端快取或自動重新擷取不會在你沒察覺的情況下重複執行它。</li>
  <li><code>mediaUploadUrl</code> 是 mutation，因為它會為你的帳號建立上傳 URL。</li>
  <li><code>linkAnalytics</code> 是 mutation，因為它可以要求以電子郵件寄送報告。</li>
  <li><code>userBatch</code> 是 mutation，因為它會啟動匯出工作。</li>
</ul>

請使用 Explorer 或 schema 確認每個受支援操作的根類型。

<h2 id="creating-a-post">
  建立貼文
</h2>

`createPost` 只接受一個 `input` 引數，因此整篇貼文就是一個物件：

```graphql theme={"system"}
mutation {
  createPost(input: {
    post: "Hello from GraphQL"
    platforms: [LINKEDIN]
    idempotencyKey: "post-2026-09-01-001"
  }) {
    status
    id
  }
}
```

此輸入與文件中的 [REST post 端點](/docs/apis/post/post)一致，包括各社群網路的選項物件，以及接受多種 JSON 結構的 REST 形式：

```graphql theme={"system"}
mutation {
  createPost(input: {
    post: "New video"
    platforms: [YOUTUBE]
    mediaUrls: ["https://example.com/video.mp4"]
    idempotencyKey: "youtube-video-001"
    youTubeOptions: {
      title: "My video"
      visibility: PUBLIC
    }
  }) {
    status
    id
    postIds { platform postUrl }
  }
}
```

一篇貼文可能在某個社群網路上成功，而在另一個社群網路上失敗。這並不是請求失敗，請參閱[錯誤](/docs/apis/graphql/errors#partial-success-on-multi-network-posts)。

<h2 id="argument-types">
  引數型別
</h2>

大多數引數都是一般的字串、數字與布林值。有三種情況值得了解。

<h3 id="enums">
  列舉
</h3>

許多具有固定支援值集合的字串引數都是 GraphQL 列舉，寫法為**不加引號且全部大寫**：

```graphql theme={"system"}
{ socialAnalytics(platforms: [INSTAGRAM, TIKTOK]) }
```

而不是 `"instagram"`。伺服器會將每個接受的列舉對應到底層 REST 控制器所預期的確切值，通常是小寫字串，但並非總是如此。無效的列舉會在操作執行前的 GraphQL 驗證階段被拒絕，因此打錯字不會讓你付出任何代價。

有些引數在不同操作中名稱相同，但接受的值不同，因為這些端點確實有所差異。`reviews(platform:)` 只接受 `GMB` 與 `FACEBOOK`，因為只有這兩個社群網路有評論。你的用戶端自動完成功能會針對每個操作顯示正確的值集合。

<h3 id="the-json-scalar">
  JSON scalar
</h3>

少數引數的型別是 `JSON`，而非特定型別。這種情況發生在某個值確實有多種結構，沒有任何單一 GraphQL 型別能如實描述它時：

<ul class="custom-bullets">
  <li><code>explainError(code:)</code> 接受 <code>215</code> 或 <code>"215"</code>，因為客戶持有的錯誤代碼兩種形式都有。</li>
  <li><code>createPost(input:)</code> 對 <code>post</code> 與 <code>mediaUrls</code> 等欄位使用 JSON，因為這些欄位可以是共用值，也可以是各平台個別的物件。</li>
  <li><code>createAutomation(triggers:, actions:)</code> 接受陣列，其欄位取決於每個項目的 <code>type</code>。</li>
  <li><code>boostFacebookPost(interests:)</code> 接受字串或數字形式的 Meta 興趣 ID。</li>
</ul>

請傳入你在對應 REST body 中會傳送的相同值。`JSON` 引數並不是漏洞：resolver 會在分派前驗證它，因此無效的值會傳回驗證錯誤，且不會消耗任何 API 呼叫。

<h3 id="optional-arguments-and-nulls">
  選用引數與 null
</h3>

對於選用引數以及輸入物件中的選用欄位，明確的 `null` 會被正規化為省略。當清單型別允許時，清單中的 null 成員會被保留。

<h2 id="reading-responses">
  讀取回應
</h2>

大多數操作會傳回包含完整 REST 回應封包的 `JSON` scalar，因此請選取根欄位，不要加上子欄位。`createPost` 目前會傳回型別化的 `PostResult`，因此請選取其欄位：

```graphql theme={"system"}
mutation {
  createPost(input: {
    post: "Hi"
    platforms: [LINKEDIN]
    idempotencyKey: "linkedin-hi-001"
  }) {
    status
    id
    postIds { platform postUrl }
    errors { platform message code }
  }
}
```

`PostResult` 等型別化回應型別也包含 `raw: JSON!`，其中含有完整且未經修改的 REST 回應：

```graphql theme={"system"}
mutation {
  createPost(input: {
    post: "Hi"
    platforms: [LINKEDIN]
    idempotencyKey: "linkedin-hi-001"
  }) {
    status
    raw
  }
}
```

`raw` 會永久保留，目的是讓 REST 回應中新出現的欄位，在我們補上型別定義之前，也永遠能從 GraphQL 取得。如果你需要型別化欄位未提供的資料，請選取 `raw`。

<h2 id="uploading-media">
  上傳媒體
</h2>

**媒體位元組無法透過 GraphQL 請求傳送。** GraphQL 請求是一份大小限制在 64 KB 以內的 JSON 文件，因此沒有任何欄位可以接受檔案；而將圖片以 base64 編碼放進查詢中，除了縮圖以外，任何圖片都會超過此限制。

支援的做法完全避開了這個問題，而且無論如何都比透過 API 上傳更快，因為你的位元組會直接傳送到儲存空間：

1. 取得上傳 URL：

   ```graphql theme={"system"}
   mutation { mediaUploadUrl(contentType: "image/jpeg") }
   ```

2. 從傳回的 JSON 中讀取 `data.mediaUploadUrl.uploadUrl`、`accessUrl` 與 `contentType`。

3. 將你的檔案 `PUT` **直接傳送到 `uploadUrl`**，而不是傳送到 Ayrshare API，並將請求的 `Content-Type` header 設為傳回的 `contentType`。

4. 上傳成功後，在 `createPost.input.mediaUrls` 中傳入 `accessUrl`：

   ```graphql theme={"system"}
   mutation {
     createPost(input: {
       post: "With a photo"
       platforms: [INSTAGRAM]
       mediaUrls: ["https://the-returned-access-url"]
       idempotencyKey: "instagram-photo-001"
     }) {
       status
       postIds { platform postUrl }
     }
   }
   ```

請將 `uploadUrl` 視為短期有效的寫入憑證，不要記錄或公開它。`accessUrl` 則是建立貼文時使用的媒體 URL。

你也可以繼續使用 [REST 上傳端點](/docs/apis/media/upload-media)，並在 GraphQL 中引用產生的 URL。兩種介面共用同一個媒體庫。

<h2 id="read-next">
  延伸閱讀
</h2>

<ul class="custom-bullets">
  <li>[錯誤](/docs/apis/graphql/errors)：HTTP 狀態碼、錯誤結構與部分成功。</li>
  <li>[限制與計費](/docs/apis/graphql/limits)：查詢大小上限與請求的計算方式。</li>
</ul>
