{"info":{"title":"Inrō API","description":"This is the documentation for the Inrō API.\nIt allows you to access and update contacts in your account.\n## Base URL\nThe base URL for all API requests is: `api.inro.social/api/v1`\n## Authorization\nThe API is using API keys for authorization.\nYou can find your API key in your organization\nsettings:\n\n![API key location](/images/api_key_screen.png)\n\nCopy the API key and use it in the request's\n`Authorization` header, prefixed by `Bearer `.\nThe header value should look like:\n\n`Bearer 9e983d4479887176bffefe772d1927a8`\n","version":"v1"},"swagger":"2.0","produces":["application/json","application/octet-stream","image/jpeg","image/png","image/gif","image/webp","image/avif","audio/mpeg","audio/mp4","audio/aac","audio/x-wav","video/mp4","video/quicktime","video/webm"],"securityDefinitions":{"api_key":{"type":"apiKey","in":"header","name":"Authorization","description":"Token obtained from your organization settings"}},"security":[{"api_key":[]}],"host":"api.inro.social","tags":[{"name":"Segments","description":"Operations about Segments"},{"name":"Automation executions","description":"Operations about Automation executions"},{"name":"Me","description":"Information about the logged in organization"},{"name":"Contacts","description":"Operations about Instagram contacts"},{"name":"Contact properties","description":"Operations about contact custom properties. These are specific to your organization and are used to store additional information to your contacts."},{"name":"Folders","description":"Operations about contact folders"},{"name":"Scenarios","description":"Operations about scenarios"},{"name":"Scenario Folders","description":"Operations about scenario folders. Priority folders enforce mutual-exclusion execution; normal folders are organisational only."},{"name":"Campaigns","description":"Operations about campaigns"},{"name":"Campaign Folders","description":"Operations about campaign folders (organisational grouping only)"},{"name":"Conversion Links","description":"Operations about conversion links — shareable cards with a title, subtitle, URL, and call-to-action button"},{"name":"Templates","description":"Operations about templates (scenarios \u0026 campaigns)"},{"name":"Messages","description":"Operations for sending messages to contacts"},{"name":"Medias","description":"Read Instagram feed posts and create, schedule, and publish new feed posts (images, reels, carousels)"},{"name":"Stories","description":"Read Instagram stories and create, schedule, and publish new stories"},{"name":"Agent","description":"Operations for configuring the AI agent, including trigger rules, knowledge base items, actions, and tracked contact properties"},{"name":"Batch tasks","description":"Track the progress of long-running batch operations (campaign sends, bulk contact updates)"},{"name":"Partner","description":"For partners managing several client accounts. Authenticate with a partner token to list, create and delete the organizations the partner owns. To act *inside* one of them, use the same token on any other endpoint with the X-Inro-Organization header."},{"name":"Media files","description":"Manage uploaded media files used in scenario and campaign actions"},{"name":"Settings","description":"Organization-level settings. Currently the opt-out group: how contacts opt out of messages — keywords, persistent menu entry, and confirmation message"},{"name":"Icebreakers","description":"Read and update the icebreaker questions shown on the Instagram profile. Stored on Instagram, never on our side, so every call reads them back from the Graph API"},{"name":"Persistent menu","description":"Read and update the always-visible menu in the Instagram conversation. Stored on Instagram, never on our side, so every call reads it back from the Graph API"}],"paths":{"/api/v1/me":{"get":{"summary":"Logged in organization","description":"As you may be managing several organizations from your Inrō account,\nit might be useful to know which organization is currently\nauthenticated.\n\n- If using an `api_key`, this is the organization that owns the\n`api_key` used in the request's `Authorization` header.\n\n- If using an integration (such as Make), this is the organization that\nyou authorized when you first created the connection.\n","produces":["application/json"],"responses":{"200":{"description":"Get information about the logged in organization","schema":{"$ref":"#/definitions/PublicApi_Entities_OrganizationEntity"}}},"tags":["Me"],"operationId":"getApiV1Me"}},"/api/v1/contacts":{"get":{"summary":"List contacts","description":"This endpoint returns a paginated list of Instagram contacts.","produces":["application/json"],"parameters":[{"in":"query","name":"page","description":"Page number","type":"integer","format":"int32","default":1,"required":false},{"in":"query","name":"per_page","description":"Number of items per page (max 1000)","type":"integer","format":"int32","default":20,"minimum":1,"maximum":1000,"required":false},{"in":"query","name":"order_direction","description":"Order direction (asc or desc)","type":"string","default":"asc","enum":["asc","desc"],"required":false},{"in":"query","name":"order_column","description":"Order column. Custom ordering available for: username (case-insensitive), name (case-insensitive), email (case-insensitive), phone, status, updated_at, created_at, last_message_at.","type":"string","default":"username","required":false}],"responses":{"200":{"description":"List contacts","schema":{"type":"object","properties":{"contacts":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_ContactEntity"}}}}}},"tags":["Contacts"],"operationId":"getApiV1Contacts"}},"/api/v1/contacts/search":{"get":{"summary":"Search contacts","description":"This endpoint returns results from a search query on Instagram contacts as a paginated list.","produces":["application/json"],"parameters":[{"in":"query","name":"query","description":"Search query","type":"string","required":false},{"in":"query","name":"page","description":"Page number","type":"integer","format":"int32","default":1,"required":false},{"in":"query","name":"per_page","description":"Number of items per page (max 1000)","type":"integer","format":"int32","default":20,"minimum":1,"maximum":1000,"required":false},{"in":"query","name":"order_direction","description":"Order direction (asc or desc)","type":"string","default":"asc","enum":["asc","desc"],"required":false},{"in":"query","name":"order_column","description":"Order column. Custom ordering available for: username (case-insensitive), name (case-insensitive), email (case-insensitive), phone, status, is_follower, follower_count, last_message_at. Or use any Contact column (e.g., created_at, updated_at, organization_id, instagram_id, etc.)","type":"string","default":"username","required":false}],"responses":{"200":{"description":"Search contacts","schema":{"type":"object","properties":{"contacts":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_ContactEntity"}}}}}},"tags":["Contacts"],"operationId":"getApiV1ContactsSearch"}},"/api/v1/contacts/filter_types":{"get":{"summary":"List contact filter types","description":"Returns the catalog of contact filter types (with their operators, date ranges, value and options) that can be used to build the `filters` array for POST /contacts/filter.","produces":["application/json"],"responses":{"200":{"description":"List contact filter types"}},"tags":["Contacts"],"operationId":"getApiV1ContactsFilterTypes"}},"/api/v1/contacts/filter":{"post":{"summary":"Filter contacts","description":"Returns a paginated list of contacts matching a structured set of contact filters (activity, automation, transaction, and contact-info criteria) combined with AND/OR logic — the same segmentation engine used for Segments. Call GET /contacts/filter_types to discover the available filter types and the fields each accepts.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"name":"postApiV1ContactsFilter","in":"body","required":true,"schema":{"$ref":"#/definitions/postApiV1ContactsFilter"}}],"responses":{"200":{"description":"Filter contacts","schema":{"type":"object","properties":{"contacts":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_ContactEntity"}}}}}},"tags":["Contacts"],"operationId":"postApiV1ContactsFilter"}},"/api/v1/contacts/bulk":{"put":{"summary":"Bulk update contacts","description":"Update up to 1,000 contacts in a single request, each with different values. Each entry must include exactly one identifier (id, username, or email) and a contact attributes hash. Identifiers are resolved immediately and unmatched entries are returned in not_found; the updates themselves are applied asynchronously via a batch task whose progress can be polled at GET /api/batch_tasks/:id. Returns 202 Accepted with the batch_task_id.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"name":"putApiV1ContactsBulk","in":"body","required":true,"schema":{"$ref":"#/definitions/putApiV1ContactsBulk"}}],"responses":{"202":{"description":"Bulk update contacts"}},"tags":["Contacts"],"operationId":"putApiV1ContactsBulk"}},"/api/v1/contacts/{id}/messages":{"get":{"summary":"List a contact's messages","description":"This endpoint returns a paginated list of the messages exchanged with a contact, most recent first by default. Unlike `last_messages` on the contact, it can be paged through the whole conversation history.","produces":["application/json"],"parameters":[{"in":"path","name":"id","description":"Contact ID","type":"integer","format":"int32","required":true},{"in":"query","name":"page","description":"Page number","type":"integer","format":"int32","default":1,"required":false},{"in":"query","name":"per_page","description":"Number of items per page (max 1000)","type":"integer","format":"int32","default":20,"minimum":1,"maximum":1000,"required":false},{"in":"query","name":"order_direction","description":"Order direction on received_at (asc or desc)","type":"string","default":"desc","enum":["asc","desc"],"required":false}],"responses":{"200":{"description":"List a contact's messages","schema":{"type":"object","properties":{"messages":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_MessageEntity"}}}}}},"tags":["Contacts"],"operationId":"getApiV1ContactsIdMessages"}},"/api/v1/contacts/{id}":{"put":{"summary":"Update a contact","description":"This endpoint updates an Instagram contact via its Inrō ID.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"in":"path","name":"id","description":"Contact ID","type":"integer","format":"int32","required":true},{"name":"putApiV1ContactsId","in":"body","required":true,"schema":{"$ref":"#/definitions/putApiV1ContactsId"}}],"responses":{"200":{"description":"Update a contact","schema":{"type":"object","properties":{"contact":{"$ref":"#/definitions/PublicApi_Entities_ExtendedContactEntity"}}}}},"tags":["Contacts"],"operationId":"putApiV1ContactsId"}},"/api/v1/contact":{"put":{"summary":"Update contact(s) (via username, email or ID)","description":"This endpoint updates one Instagram contact or more via their Inrō ID, email or username. Please note that you'll need to provide exactly one of the 6 parameters: `id` (or `ids``), `email` (or `emails``) or `username` (or `usernames`).","produces":["application/json"],"consumes":["application/json"],"parameters":[{"name":"putApiV1Contact","in":"body","required":true,"schema":{"$ref":"#/definitions/putApiV1Contact"}}],"responses":{"200":{"description":"Update contact(s) (via username, email or ID)","schema":{"type":"object","properties":{"contact":{"$ref":"#/definitions/PublicApi_Entities_ExtendedContactEntity"}}}}},"tags":["Contacts"],"operationId":"putApiV1Contact"},"get":{"summary":"Get a contact","description":"This endpoint returns an Instagram contact via its Inrō ID, email or username. Please note that you'll need to provide exactly one of the 3 parameters: `id`, `email` or `username`.","produces":["application/json"],"parameters":[{"in":"query","name":"id","description":"Contact ID","type":"integer","format":"int32","required":false,"x-example":123},{"in":"query","name":"username","description":"Contact username (for identification)","type":"string","required":false,"x-example":"john_doe"},{"in":"query","name":"email","description":"Contact email (for identification)","type":"string","required":false,"x-example":"john.doe@example.com"},{"in":"query","name":"force_picture","description":"Force the contact picture to be updated","type":"boolean","required":false,"x-example":true}],"responses":{"200":{"description":"Get a contact","schema":{"type":"object","properties":{"contact":{"$ref":"#/definitions/PublicApi_Entities_ExtendedContactEntity"}}}}},"tags":["Contacts"],"operationId":"getApiV1Contact"}},"/api/v1/folders":{"get":{"summary":"List all folders","description":"This endpoint returns a paginated list of your folders.","produces":["application/json"],"parameters":[{"in":"query","name":"page","description":"Page offset to fetch.","type":"integer","format":"int32","default":1,"required":false},{"in":"query","name":"per_page","description":"Number of results to return per page.","type":"integer","format":"int32","default":20,"required":false},{"in":"query","name":"offset","description":"Pad a number of results.","type":"integer","format":"int32","default":0,"required":false}],"responses":{"200":{"description":"List all folders","schema":{"type":"object","properties":{"folders":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_FolderEntity"}}}}}},"tags":["Folders"],"operationId":"getApiV1Folders"},"post":{"summary":"Create a new folder","description":"This endpoint creates a new folder. If a folder with the same name already exists, it returns the existing folder with a 200 status code (other parameters like color are ignored in this case).","produces":["application/json"],"consumes":["application/json"],"parameters":[{"name":"postApiV1Folders","in":"body","required":true,"schema":{"$ref":"#/definitions/postApiV1Folders"}}],"responses":{"200":{"description":"Existing folder returned","schema":{"type":"object","properties":{"folder":{"$ref":"#/definitions/PublicApi_Entities_FolderEntity"}}}},"201":{"description":"New folder created","schema":{"type":"object","properties":{"folder":{"$ref":"#/definitions/PublicApi_Entities_FolderEntity"}}}}},"tags":["Folders"],"operationId":"postApiV1Folders"}},"/api/v1/folders/{id}":{"put":{"summary":"Update an existing folder","description":"This endpoint updates an existing folder.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"in":"path","name":"id","type":"integer","format":"int32","required":true},{"name":"putApiV1FoldersId","in":"body","required":true,"schema":{"$ref":"#/definitions/putApiV1FoldersId"}}],"responses":{"200":{"description":"Update a folder","schema":{"$ref":"#/definitions/PublicApi_Entities_FolderEntity"}}},"tags":["Folders"],"operationId":"putApiV1FoldersId"},"delete":{"summary":"Delete a folder","description":"This endpoint deletes a folder. This action is irreversible. Contacts will not be deleted.","produces":["application/json"],"parameters":[{"in":"path","name":"id","description":"Folder ID","type":"integer","format":"int32","required":true}],"responses":{"204":{"description":"Delete a folder"}},"tags":["Folders"],"operationId":"deleteApiV1FoldersId"}},"/api/v1/folders/{id}/contacts":{"get":{"summary":"List folder contacts","description":"This endpoint returns all contacts.","produces":["application/json"],"parameters":[{"in":"path","name":"id","description":"Folder ID","type":"integer","format":"int32","required":true},{"in":"query","name":"page","description":"Page offset to fetch.","type":"integer","format":"int32","default":1,"required":false},{"in":"query","name":"per_page","description":"Number of results to return per page.","type":"integer","format":"int32","default":20,"required":false},{"in":"query","name":"offset","description":"Pad a number of results.","type":"integer","format":"int32","default":0,"required":false}],"responses":{"200":{"description":"List folder contacts","schema":{"type":"object","properties":{"contacts":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_ContactEntity"}}}}}},"tags":["Folders"],"operationId":"getApiV1FoldersIdContacts"}},"/api/v1/folders/{id}/add_contacts":{"post":{"summary":"Add contacts to a folder","description":"This endpoint adds contacts to a folder. If a contact is already in the folder, it will be ignored. Invalid contact IDs will be ignored. The contacts are added asynchronously via a batch task whose progress can be polled at GET /api/batch_tasks/:id. Returns 202 Accepted with the batch_task_id.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"in":"path","name":"id","description":"Folder ID","type":"integer","format":"int32","required":true},{"name":"postApiV1FoldersIdAddContacts","in":"body","required":true,"schema":{"$ref":"#/definitions/postApiV1FoldersIdAddContacts"}}],"responses":{"202":{"description":"Add contacts to a folder"}},"tags":["Folders"],"operationId":"postApiV1FoldersIdAddContacts"}},"/api/v1/folders/{id}/remove_contacts":{"post":{"summary":"Remove contacts from a folder","description":"This endpoint removes contacts from a folder. If a contact is not in the folder, it will be ignored. Invalid contact IDs will be ignored. The contacts are removed asynchronously via a batch task whose progress can be polled at GET /api/batch_tasks/:id. Returns 202 Accepted with the batch_task_id.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"in":"path","name":"id","description":"Folder ID","type":"integer","format":"int32","required":true},{"name":"postApiV1FoldersIdRemoveContacts","in":"body","required":true,"schema":{"$ref":"#/definitions/postApiV1FoldersIdRemoveContacts"}}],"responses":{"202":{"description":"Remove contacts from a folder"}},"tags":["Folders"],"operationId":"postApiV1FoldersIdRemoveContacts"}},"/api/v1/segments":{"get":{"summary":"List segments","description":"Returns a paginated list of segments with their contact filters, ordered by title. Use GET /segments/:id for the contact count.","produces":["application/json"],"parameters":[{"in":"query","name":"page","description":"Page number","type":"integer","format":"int32","default":1,"required":false},{"in":"query","name":"per_page","description":"Number of items per page (max 1000)","type":"integer","format":"int32","default":20,"minimum":1,"maximum":1000,"required":false}],"responses":{"200":{"description":"List segments","schema":{"type":"object","properties":{"segments":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_SegmentEntity"}}}}}},"tags":["Segments"],"operationId":"getApiV1Segments"},"post":{"summary":"Create a segment","description":"Creates a segment from a title and a list of contact filters combined with AND/OR logic. Call GET /contacts/filter_types to discover the available filter types and the fields each accepts.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"name":"postApiV1Segments","in":"body","required":true,"schema":{"$ref":"#/definitions/postApiV1Segments"}}],"responses":{"201":{"description":"Create a segment","schema":{"type":"object","properties":{"segments":{"$ref":"#/definitions/PublicApi_Entities_DetailedSegmentEntity"}}}}},"tags":["Segments"],"operationId":"postApiV1Segments"}},"/api/v1/segments/{id}":{"get":{"summary":"Get a segment","description":"Returns a segment with its contact filters and the number of contacts it matches.","produces":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the segment","type":"integer","format":"int32","required":true}],"responses":{"200":{"description":"Get a segment","schema":{"type":"object","properties":{"segments":{"$ref":"#/definitions/PublicApi_Entities_DetailedSegmentEntity"}}}}},"tags":["Segments"],"operationId":"getApiV1SegmentsId"},"patch":{"summary":"Update a segment","description":"Updates a segment's title, emoji or filter logic. When `contact_filters` is provided it replaces the segment's whole filter list (an empty array removes all filters, matching every contact); omit it to keep the current filters.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the segment","type":"integer","format":"int32","required":true},{"name":"patchApiV1SegmentsId","in":"body","required":true,"schema":{"$ref":"#/definitions/patchApiV1SegmentsId"}}],"responses":{"200":{"description":"Update a segment","schema":{"type":"object","properties":{"segments":{"$ref":"#/definitions/PublicApi_Entities_DetailedSegmentEntity"}}}}},"tags":["Segments"],"operationId":"patchApiV1SegmentsId"},"delete":{"summary":"Delete a segment","description":"Deletes a segment and its contact filters. Contacts are not deleted.","produces":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the segment","type":"integer","format":"int32","required":true}],"responses":{"204":{"description":"Delete a segment"}},"tags":["Segments"],"operationId":"deleteApiV1SegmentsId"}},"/api/v1/contact_properties":{"get":{"summary":"List contact properties","description":"This endpoint returns a paginated list of your contact custom properties.","produces":["application/json"],"parameters":[{"in":"query","name":"page","description":"Page offset to fetch.","type":"integer","format":"int32","default":1,"required":false},{"in":"query","name":"per_page","description":"Number of results to return per page.","type":"integer","format":"int32","default":20,"required":false},{"in":"query","name":"offset","description":"Pad a number of results.","type":"integer","format":"int32","default":0,"required":false}],"responses":{"200":{"description":"List contact properties","schema":{"type":"object","properties":{"contact_properties":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_ContactPropertyEntity"}}}}}},"tags":["Contact properties"],"operationId":"getApiV1ContactProperties"},"post":{"summary":"Create a contact property","description":"This endpoint creates a new custom contact property for your organization.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"name":"postApiV1ContactProperties","in":"body","required":true,"schema":{"$ref":"#/definitions/postApiV1ContactProperties"}}],"responses":{"201":{"description":"Create a contact property","schema":{"type":"object","properties":{"contact_property":{"$ref":"#/definitions/PublicApi_Entities_ContactPropertyEntity"}}}}},"tags":["Contact properties"],"operationId":"postApiV1ContactProperties"}},"/api/v1/contact_properties/{slug}":{"put":{"summary":"Update an existing contact property","description":"This endpoint updates an existing custom contact property.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"in":"path","name":"slug","description":"The slug of the contact property","type":"string","required":true},{"name":"putApiV1ContactPropertiesSlug","in":"body","required":true,"schema":{"$ref":"#/definitions/putApiV1ContactPropertiesSlug"}}],"responses":{"200":{"description":"Update a contact property","schema":{"$ref":"#/definitions/PublicApi_Entities_ContactPropertyEntity"}}},"tags":["Contact properties"],"operationId":"putApiV1ContactPropertiesSlug"},"delete":{"summary":"Delete a contact property","description":"This endpoint deletes a contact property. This action is irreversible. All associated contact property values will also be deleted.","produces":["application/json"],"parameters":[{"in":"path","name":"slug","description":"The slug of the contact property","type":"string","required":true}],"responses":{"204":{"description":"Delete a contact property"}},"tags":["Contact properties"],"operationId":"deleteApiV1ContactPropertiesSlug"}},"/api/v1/contact_properties/{slug}/backfill":{"post":{"summary":"Detect a contact property on existing contacts","description":"Runs automatic detection of this property over the contacts that already exist and have no value for it (they need a bio or at least one message). The property must have auto_detect enabled. Detection runs in the background as a batch task whose progress can be polled at GET /api/v1/batch_tasks/:id, and spends AI credits on accounts that have them, one per contact where a value is found. Returns 202 Accepted with the batch task, or 422 if auto_detect is off, a run is already in progress, or there is nothing to detect.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"in":"path","name":"slug","description":"The slug of the contact property","type":"string","required":true}],"responses":{"202":{"description":"Detect a property on existing contacts","schema":{"$ref":"#/definitions/PublicApi_Entities_BatchTaskEntity"}}},"tags":["Contact properties"],"operationId":"postApiV1ContactPropertiesSlugBackfill"}},"/api/v1/scenarios":{"get":{"summary":"List scenarios","description":"This endpoint returns a paginated list of scenarios. Filter by folder with `scenario_folder_id` (a folder ID or `none` for ungrouped scenarios). Pass `search` to run a fulltext search over the scenario title, its description and the content of its actions. Results come back most relevant first, accents are ignored, and every word of the query matches on a prefix.","produces":["application/json"],"parameters":[{"in":"query","name":"page","description":"Page number","type":"integer","format":"int32","default":1,"required":false},{"in":"query","name":"per_page","description":"Number of items per page (max 1000)","type":"integer","format":"int32","default":20,"minimum":1,"maximum":1000,"required":false},{"in":"query","name":"order_direction","description":"Order direction","type":"string","default":"desc","required":false},{"in":"query","name":"order_column","description":"Order column","type":"string","default":"updated_at","required":false},{"in":"query","name":"search","description":"Fulltext search over the scenario title, description and action content, most relevant first","type":"string","required":false},{"in":"query","name":"scenario_folder_id","description":"Filter by folder ID, or `none` to return only ungrouped scenarios","type":"string","required":false}],"responses":{"200":{"description":"List scenarios","schema":{"type":"object","properties":{"scenarios":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_ScenarioEntity"}}}}}},"tags":["Scenarios"],"operationId":"getApiV1Scenarios"},"post":{"summary":"Create a scenario","description":"Creates a new scenario. Three modes: (1) `template_id` clones an existing template; (2) `prompt` classifies the request and, when it is buildable, triggers asynchronous AI generation of triggers and actions; (3) `triggers` and/or `actions` directly persist a full JSON definition. Modes are mutually exclusive.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"name":"postApiV1Scenarios","in":"body","required":true,"schema":{"$ref":"#/definitions/postApiV1Scenarios"}}],"responses":{"201":{"description":"Create a scenario","schema":{"type":"object","properties":{"scenarios":{"$ref":"#/definitions/PublicApi_Entities_DetailedScenarioEntity"}}}}},"tags":["Scenarios"],"operationId":"postApiV1Scenarios"}},"/api/v1/scenarios/{id}":{"get":{"summary":"Get a scenario","description":"This endpoint returns details of a specific scenario, including its triggers and actions JSON.","produces":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the scenario","type":"string","required":true}],"responses":{"200":{"description":"Get a scenario","schema":{"type":"object","properties":{"scenarios":{"$ref":"#/definitions/PublicApi_Entities_DetailedScenarioEntity"}}}}},"tags":["Scenarios"],"operationId":"getApiV1ScenariosId"},"patch":{"summary":"Update a scenario","description":"Updates a scenario. (1) provide top-level fields (title, active, etc.) for direct updates; (2) provide `prompt` to trigger asynchronous AI re-generation (Poll GET /scenarios/:id and inspect `generation_data`); (3) provide `triggers` and/or `actions`: `actions` is the complete list — any existing action not in it is destroyed; `triggers` replaces all existing triggers only when no item has an `id`, otherwise unlisted triggers are kept. Include existing actions by `id` to keep/update them; new actions (no `id`) must reference a parent in the same list via `parent_key` or `parent_id`. `prompt` is mutually exclusive with `triggers` and `actions`.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the scenario to update","type":"string","required":true},{"name":"patchApiV1ScenariosId","in":"body","required":true,"schema":{"$ref":"#/definitions/patchApiV1ScenariosId"}}],"responses":{"200":{"description":"Update a scenario","schema":{"type":"object","properties":{"scenarios":{"$ref":"#/definitions/PublicApi_Entities_DetailedScenarioEntity"}}}}},"tags":["Scenarios"],"operationId":"patchApiV1ScenariosId"},"delete":{"summary":"Delete a scenario","description":"Permanently deletes a scenario, along with its triggers and actions. Past executions are kept as history but no longer reference the scenario, and any of their actions still pending are interrupted. The scenario is removed from its folder (the folder itself is kept).","produces":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the scenario to delete","type":"string","required":true}],"responses":{"204":{"description":"Delete a scenario"}},"tags":["Scenarios"],"operationId":"deleteApiV1ScenariosId"}},"/api/v1/scenarios/{id}/trigger":{"post":{"summary":"Trigger a scenario","description":"This endpoint triggers a scenario, based on the contact identifier provided.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the scenario to trigger","type":"string","required":true},{"in":"query","name":"contacts[id]","description":"Contact ID","type":"integer","format":"int32","required":false,"x-example":123},{"in":"query","name":"contacts[username]","description":"Contact username (for identification)","type":"string","required":false,"x-example":"john_doe"},{"in":"query","name":"contacts[email]","description":"Contact email (for identification)","type":"string","required":false,"x-example":"john.doe@example.com"},{"name":"postApiV1ScenariosIdTrigger","in":"body","required":true,"schema":{"$ref":"#/definitions/postApiV1ScenariosIdTrigger"}}],"responses":{"200":{"description":"Trigger a scenario","schema":{"type":"object","properties":{"scenarios":{"$ref":"#/definitions/PublicApi_Entities_ScenarioEntity"}}}}},"tags":["Scenarios"],"operationId":"postApiV1ScenariosIdTrigger"}},"/api/v1/scenarios/{id}/test":{"post":{"summary":"Test a scenario with a contact","description":"Runs the scenario once as a test for one contact, even when it is inactive. The scenario's messages are really sent to that contact; the run is excluded from metrics. Any pending run of the scenario for that contact is interrupted.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the scenario to test","type":"string","required":true},{"in":"query","name":"contact[id]","description":"Contact ID","type":"integer","format":"int32","required":false,"x-example":123},{"in":"query","name":"contact[username]","description":"Contact username (for identification)","type":"string","required":false,"x-example":"john_doe"},{"in":"query","name":"contact[email]","description":"Contact email (for identification)","type":"string","required":false,"x-example":"john.doe@example.com"},{"name":"postApiV1ScenariosIdTest","in":"body","required":true,"schema":{"$ref":"#/definitions/postApiV1ScenariosIdTest"}}],"responses":{"201":{"description":"Test a scenario with a contact"}},"tags":["Scenarios"],"operationId":"postApiV1ScenariosIdTest"}},"/api/v1/scenarios/{id}/performance":{"get":{"summary":"Scenario performance","description":"Per-step funnel for one scenario over a window: how many runs reached each step, how many finished it, and the reason codes behind the ones that did not. Read top to bottom, the drop between two steps is where the scenario is breaking — which is what tells you which step to inspect with `GET /v1/automation/executions`. Cached for a minute; `computed_at` says when it was calculated.","produces":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the scenario","type":"integer","format":"int32","required":true},{"in":"query","name":"since","description":"Start of the window (default: 7 days ago, maximum lookback: 90 days)","type":"string","format":"date-time","required":false},{"in":"query","name":"until","description":"End of the window (default: now)","type":"string","format":"date-time","required":false}],"responses":{"200":{"description":"Scenario performance","schema":{"type":"object","properties":{"performance":{"$ref":"#/definitions/PublicApi_Entities_RunnablePerformanceEntity"}}}}},"tags":["Scenarios"],"operationId":"getApiV1ScenariosIdPerformance"}},"/api/v1/scenario_folders":{"get":{"summary":"List scenario folders","description":"Returns all scenario folders for the organization, ordered by name.","produces":["application/json"],"responses":{"200":{"description":"List scenario folders","schema":{"type":"object","properties":{"scenario_folders":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_ScenarioFolderEntity"}}}}}},"tags":["Scenario Folders"],"operationId":"getApiV1ScenarioFolders"},"post":{"summary":"Create a scenario folder","description":"Creates a new scenario folder. Use `folder_type: priority` (default) for mutual-exclusion execution or `folder_type: normal` for organisational grouping only.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"name":"postApiV1ScenarioFolders","in":"body","required":true,"schema":{"$ref":"#/definitions/postApiV1ScenarioFolders"}}],"responses":{"201":{"description":"Create a scenario folder","schema":{"type":"object","properties":{"scenario_folders":{"$ref":"#/definitions/PublicApi_Entities_ScenarioFolderEntity"}}}}},"tags":["Scenario Folders"],"operationId":"postApiV1ScenarioFolders"}},"/api/v1/scenario_folders/{id}":{"get":{"summary":"Get a scenario folder","description":"Returns a specific scenario folder by ID.","produces":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the scenario folder","type":"integer","format":"int32","required":true}],"responses":{"200":{"description":"Get a scenario folder","schema":{"type":"object","properties":{"scenario_folders":{"$ref":"#/definitions/PublicApi_Entities_ScenarioFolderEntity"}}}}},"tags":["Scenario Folders"],"operationId":"getApiV1ScenarioFoldersId"},"patch":{"summary":"Update a scenario folder","description":"Updates a scenario folder's name, description, or type.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the scenario folder","type":"integer","format":"int32","required":true},{"name":"patchApiV1ScenarioFoldersId","in":"body","required":true,"schema":{"$ref":"#/definitions/patchApiV1ScenarioFoldersId"}}],"responses":{"200":{"description":"Update a scenario folder","schema":{"type":"object","properties":{"scenario_folders":{"$ref":"#/definitions/PublicApi_Entities_ScenarioFolderEntity"}}}}},"tags":["Scenario Folders"],"operationId":"patchApiV1ScenarioFoldersId"},"delete":{"summary":"Delete a scenario folder","description":"Deletes a scenario folder. By default, scenarios in the folder are ungrouped (kept but unassigned). Pass `action_type: delete_scenarios` to also delete all scenarios in the folder.","produces":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the scenario folder","type":"integer","format":"int32","required":true},{"in":"query","name":"action_type","description":"`ungroup` (default) keeps scenarios but removes them from the folder; `delete_scenarios` permanently deletes all scenarios in the folder","type":"string","default":"ungroup","enum":["ungroup","delete_scenarios"],"required":false}],"responses":{"204":{"description":"Delete a scenario folder"}},"tags":["Scenario Folders"],"operationId":"deleteApiV1ScenarioFoldersId"}},"/api/v1/scenario_folders/{id}/duplicate":{"post":{"summary":"Duplicate a scenario folder","description":"Duplicates a scenario folder and all of its scenarios. The copies are created as inactive.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the scenario folder to duplicate","type":"integer","format":"int32","required":true}],"responses":{"201":{"description":"Duplicate a scenario folder","schema":{"type":"object","properties":{"scenario_folders":{"$ref":"#/definitions/PublicApi_Entities_ScenarioFolderEntity"}}}}},"tags":["Scenario Folders"],"operationId":"postApiV1ScenarioFoldersIdDuplicate"}},"/api/v1/scenario_folders/{id}/reorder":{"post":{"summary":"Reorder scenarios in a folder","description":"Sets the execution priority order for scenarios in a priority folder. The first scenario ID in the list gets the highest priority (lowest numeric value). Only meaningful for priority folders.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the scenario folder","type":"integer","format":"int32","required":true},{"name":"postApiV1ScenarioFoldersIdReorder","in":"body","required":true,"schema":{"$ref":"#/definitions/postApiV1ScenarioFoldersIdReorder"}}],"responses":{"200":{"description":"Reorder scenarios in a priority folder","schema":{"type":"object","properties":{"scenario_folders":{"$ref":"#/definitions/PublicApi_Entities_ScenarioFolderEntity"}}}}},"tags":["Scenario Folders"],"operationId":"postApiV1ScenarioFoldersIdReorder"}},"/api/v1/scenario_folders/{id}/toggle_active":{"patch":{"summary":"Toggle folder scenarios active/inactive","description":"Activates or deactivates all scenarios in the folder at once.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the scenario folder","type":"integer","format":"int32","required":true},{"name":"patchApiV1ScenarioFoldersIdToggleActive","in":"body","required":true,"schema":{"$ref":"#/definitions/patchApiV1ScenarioFoldersIdToggleActive"}}],"responses":{"200":{"description":"Toggle all scenarios in a folder active or inactive","schema":{"type":"object","properties":{"scenario_folders":{"$ref":"#/definitions/PublicApi_Entities_ScenarioFolderEntity"}}}}},"tags":["Scenario Folders"],"operationId":"patchApiV1ScenarioFoldersIdToggleActive"}},"/api/v1/messages":{"post":{"summary":"Send a message to one or more contacts","description":"This endpoint sends a message to one or more Instagram contacts. Messages are sent asynchronously via a background job. Only active contacts will receive messages. Maximum of 1000 contacts per request.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"name":"postApiV1Messages","in":"body","required":true,"schema":{"$ref":"#/definitions/postApiV1Messages"}}],"responses":{"202":{"description":"Send a message to one or more contacts"}},"tags":["Messages"],"operationId":"postApiV1Messages"}},"/api/v1/campaigns":{"get":{"summary":"List campaigns","description":"This endpoint returns a paginated list of campaigns with optional filters. Filter by folder with `campaign_folder_id` (a folder ID or `none` for ungrouped campaigns).","produces":["application/json"],"parameters":[{"in":"query","name":"page","description":"Page number","type":"integer","format":"int32","default":1,"required":false},{"in":"query","name":"per_page","description":"Number of items per page (max 1000)","type":"integer","format":"int32","default":20,"minimum":1,"maximum":1000,"required":false},{"in":"query","name":"order_direction","description":"Order direction","type":"string","default":"desc","required":false},{"in":"query","name":"order_column","description":"Order column","type":"string","default":"updated_at","required":false},{"in":"query","name":"status","description":"Filter campaigns by status","type":"string","enum":["draft","running","completed","scheduled","limited","canceled"],"required":false},{"in":"query","name":"search","description":"Fulltext search over the campaign title, description and action content, most relevant first","type":"string","required":false},{"in":"query","name":"campaign_folder_id","description":"Filter by folder ID, or `none` to return only ungrouped campaigns","type":"string","required":false},{"in":"query","name":"sort_by","description":"Column to sort by","type":"string","required":false},{"in":"query","name":"sort_direction","description":"Sort direction","type":"string","enum":["asc","desc"],"required":false}],"responses":{"200":{"description":"List campaigns","schema":{"type":"object","properties":{"campaigns":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_CampaignEntity"}}}}}},"tags":["Campaigns"],"operationId":"getApiV1Campaigns"},"post":{"summary":"Create a campaign","description":"Creates a new campaign. Three modes: (1) `template_id` clones an existing template; (2) `actions` and/or `campaign_rules` directly persist a full JSON definition; (3) without either, creates a blank campaign with the provided title and targeting. `template_id` is mutually exclusive with `actions` and `campaign_rules`.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"name":"postApiV1Campaigns","in":"body","required":true,"schema":{"$ref":"#/definitions/postApiV1Campaigns"}}],"responses":{"201":{"description":"Create a campaign","schema":{"type":"object","properties":{"campaigns":{"$ref":"#/definitions/PublicApi_Entities_DetailedCampaignEntity"}}}}},"tags":["Campaigns"],"operationId":"postApiV1Campaigns"}},"/api/v1/campaigns/{id}":{"get":{"summary":"Get a campaign","description":"This endpoint returns details of a specific campaign, including its targeting rules (`campaign_rules`) and the full `actions` flow.","produces":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the campaign","type":"string","required":true}],"responses":{"200":{"description":"Get a campaign","schema":{"type":"object","properties":{"campaigns":{"$ref":"#/definitions/PublicApi_Entities_DetailedCampaignEntity"}}}}},"tags":["Campaigns"],"operationId":"getApiV1CampaignsId"},"patch":{"summary":"Update a campaign","description":"Updates a draft campaign. Accepts targeting (selected contact IDs, campaign rules) and structural fields (title, options, interrupt flags, actions). When `actions` or `campaign_rules` is provided, the campaign is rebuilt from the payload (existing actions are replaced if no action ids are passed). Only draft campaigns can be updated.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the campaign","type":"string","required":true},{"name":"patchApiV1CampaignsId","in":"body","required":true,"schema":{"$ref":"#/definitions/patchApiV1CampaignsId"}}],"responses":{"200":{"description":"Update a campaign","schema":{"type":"object","properties":{"campaigns":{"$ref":"#/definitions/PublicApi_Entities_DetailedCampaignEntity"}}}}},"tags":["Campaigns"],"operationId":"patchApiV1CampaignsId"}},"/api/v1/campaigns/{id}/send":{"post":{"summary":"Send a campaign","description":"This endpoint sends an existing draft campaign by transitioning it to the running state and queuing its executions. Returns the campaign along with the batch_task_id whose progress can be polled at GET /api/v1/batch_tasks/:id.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the campaign","type":"string","required":true}],"responses":{"200":{"description":"Send a campaign","schema":{"type":"object","properties":{"campaigns":{"$ref":"#/definitions/PublicApi_Entities_CampaignEntity"}}}}},"tags":["Campaigns"],"operationId":"postApiV1CampaignsIdSend"}},"/api/v1/campaigns/{id}/test":{"post":{"summary":"Test a campaign with a contact","description":"Runs the campaign once as a test for one contact without starting it; it works on a draft or scheduled campaign. The campaign's messages are really sent to that contact; the run is excluded from metrics. A running or completed campaign cannot be tested.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the campaign to test","type":"string","required":true},{"in":"query","name":"contact[id]","description":"Contact ID","type":"integer","format":"int32","required":false,"x-example":123},{"in":"query","name":"contact[username]","description":"Contact username (for identification)","type":"string","required":false,"x-example":"john_doe"},{"in":"query","name":"contact[email]","description":"Contact email (for identification)","type":"string","required":false,"x-example":"john.doe@example.com"},{"name":"postApiV1CampaignsIdTest","in":"body","required":true,"schema":{"$ref":"#/definitions/postApiV1CampaignsIdTest"}}],"responses":{"201":{"description":"Test a campaign with a contact"}},"tags":["Campaigns"],"operationId":"postApiV1CampaignsIdTest"}},"/api/v1/campaigns/{id}/performance":{"get":{"summary":"Campaign performance","description":"Per-step funnel for one campaign over a window: how many sends reached each step, how many finished it, and the reason codes behind the ones that did not. The run counts name the paused buckets too — `limited` (activation limit) and `disconnected` (broken Instagram connection) — which are the sends `POST /v1/campaigns/:id/resend` can put through once the cause is fixed. Cached for a minute.","produces":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the campaign","type":"integer","format":"int32","required":true},{"in":"query","name":"since","description":"Start of the window (default: 7 days ago, maximum lookback: 90 days)","type":"string","format":"date-time","required":false},{"in":"query","name":"until","description":"End of the window (default: now)","type":"string","format":"date-time","required":false}],"responses":{"200":{"description":"Campaign performance","schema":{"type":"object","properties":{"performance":{"$ref":"#/definitions/PublicApi_Entities_RunnablePerformanceEntity"}}}}},"tags":["Campaigns"],"operationId":"getApiV1CampaignsIdPerformance"}},"/api/v1/campaigns/{id}/resend":{"post":{"summary":"Re-send paused campaign sends","description":"Puts through the sends this campaign parked because the Instagram connection was broken (`scope=disconnected`) or the monthly contact-activation limit was reached (`scope=limited`). Re-sending consumes activations, so it is a two-step call: with `confirm=false` (the default) it returns how many sends it would make and how much activation headroom is left, and sends nothing; with `confirm=true` it sends. Paused sends outside `window` are cancelled, which is what clears the paused-sends warning in one action.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the campaign","type":"integer","format":"int32","required":true},{"name":"postApiV1CampaignsIdResend","in":"body","required":true,"schema":{"$ref":"#/definitions/postApiV1CampaignsIdResend"}}],"responses":{"200":{"description":"Re-send paused campaign sends","schema":{"type":"object","properties":{"campaign":{"$ref":"#/definitions/PublicApi_Entities_CampaignEntity"}}}}},"tags":["Campaigns"],"operationId":"postApiV1CampaignsIdResend"}},"/api/v1/campaign_folders":{"get":{"summary":"List campaign folders","description":"Returns all campaign folders for the organization, ordered by name.","produces":["application/json"],"responses":{"200":{"description":"List campaign folders","schema":{"type":"object","properties":{"campaign_folders":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_CampaignFolderEntity"}}}}}},"tags":["Campaign Folders"],"operationId":"getApiV1CampaignFolders"},"post":{"summary":"Create a campaign folder","description":"Creates a new campaign folder for organisational grouping. Campaign folders are purely organisational — folder membership has no effect on how or when campaigns send.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"name":"postApiV1CampaignFolders","in":"body","required":true,"schema":{"$ref":"#/definitions/postApiV1CampaignFolders"}}],"responses":{"201":{"description":"Create a campaign folder","schema":{"type":"object","properties":{"campaign_folders":{"$ref":"#/definitions/PublicApi_Entities_CampaignFolderEntity"}}}}},"tags":["Campaign Folders"],"operationId":"postApiV1CampaignFolders"}},"/api/v1/campaign_folders/{id}":{"get":{"summary":"Get a campaign folder","description":"Returns a specific campaign folder by ID.","produces":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the campaign folder","type":"integer","format":"int32","required":true}],"responses":{"200":{"description":"Get a campaign folder","schema":{"type":"object","properties":{"campaign_folders":{"$ref":"#/definitions/PublicApi_Entities_CampaignFolderEntity"}}}}},"tags":["Campaign Folders"],"operationId":"getApiV1CampaignFoldersId"},"patch":{"summary":"Update a campaign folder","description":"Updates a campaign folder's name or description.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the campaign folder","type":"integer","format":"int32","required":true},{"name":"patchApiV1CampaignFoldersId","in":"body","required":true,"schema":{"$ref":"#/definitions/patchApiV1CampaignFoldersId"}}],"responses":{"200":{"description":"Update a campaign folder","schema":{"type":"object","properties":{"campaign_folders":{"$ref":"#/definitions/PublicApi_Entities_CampaignFolderEntity"}}}}},"tags":["Campaign Folders"],"operationId":"patchApiV1CampaignFoldersId"},"delete":{"summary":"Delete a campaign folder","description":"Deletes a campaign folder. By default, campaigns in the folder are ungrouped (kept but unassigned). Pass `action_type: delete_campaigns` to also delete all campaigns in the folder.","produces":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the campaign folder","type":"integer","format":"int32","required":true},{"in":"query","name":"action_type","description":"`ungroup` (default) keeps campaigns but removes them from the folder; `delete_campaigns` permanently deletes all campaigns in the folder","type":"string","default":"ungroup","enum":["ungroup","delete_campaigns"],"required":false}],"responses":{"204":{"description":"Delete a campaign folder"}},"tags":["Campaign Folders"],"operationId":"deleteApiV1CampaignFoldersId"}},"/api/v1/campaign_folders/{id}/duplicate":{"post":{"summary":"Duplicate a campaign folder","description":"Duplicates a campaign folder and all of its campaigns. The copies are created as drafts.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the campaign folder to duplicate","type":"integer","format":"int32","required":true}],"responses":{"201":{"description":"Duplicate a campaign folder","schema":{"type":"object","properties":{"campaign_folders":{"$ref":"#/definitions/PublicApi_Entities_CampaignFolderEntity"}}}}},"tags":["Campaign Folders"],"operationId":"postApiV1CampaignFoldersIdDuplicate"}},"/api/v1/conversion_links":{"get":{"summary":"List conversion links","description":"Returns a paginated list of conversion links for the organization.","produces":["application/json"],"parameters":[{"in":"query","name":"page","description":"Page number","type":"integer","format":"int32","default":1,"required":false},{"in":"query","name":"per_page","description":"Number of items per page (max 1000)","type":"integer","format":"int32","default":20,"minimum":1,"maximum":1000,"required":false},{"in":"query","name":"search","description":"Search conversion links by title, subtitle, URL, or button title","type":"string","required":false}],"responses":{"200":{"description":"List conversion links","schema":{"type":"object","properties":{"conversion_links":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_ConversionLinkEntity"}}}}}},"tags":["Conversion Links"],"operationId":"getApiV1ConversionLinks"},"post":{"summary":"Create a conversion link","description":"Creates a new conversion link. Conversion links are shareable cards with a title, subtitle, URL, and call-to-action button. They can be attached to scenario or campaign message actions.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"name":"postApiV1ConversionLinks","in":"body","required":true,"schema":{"$ref":"#/definitions/postApiV1ConversionLinks"}}],"responses":{"201":{"description":"Create a conversion link","schema":{"type":"object","properties":{"conversion_links":{"$ref":"#/definitions/PublicApi_Entities_ConversionLinkEntity"}}}}},"tags":["Conversion Links"],"operationId":"postApiV1ConversionLinks"}},"/api/v1/conversion_links/{id}":{"get":{"summary":"Get a conversion link","description":"Returns a specific conversion link by ID.","produces":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the conversion link","type":"integer","format":"int32","required":true}],"responses":{"200":{"description":"Get a conversion link","schema":{"type":"object","properties":{"conversion_links":{"$ref":"#/definitions/PublicApi_Entities_ConversionLinkEntity"}}}}},"tags":["Conversion Links"],"operationId":"getApiV1ConversionLinksId"},"patch":{"summary":"Update a conversion link","description":"Updates a conversion link. Changing the URL, title, subtitle, or button title triggers an automatic re-embedding for search. The card image can be replaced with image_url (fetched in the background) or media_file_id (immediate), and removed by passing null to either.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the conversion link","type":"integer","format":"int32","required":true},{"name":"patchApiV1ConversionLinksId","in":"body","required":true,"schema":{"$ref":"#/definitions/patchApiV1ConversionLinksId"}}],"responses":{"200":{"description":"Update a conversion link","schema":{"type":"object","properties":{"conversion_links":{"$ref":"#/definitions/PublicApi_Entities_ConversionLinkEntity"}}}}},"tags":["Conversion Links"],"operationId":"patchApiV1ConversionLinksId"},"delete":{"summary":"Delete a conversion link","description":"Deletes a conversion link. Messages that used this link will have their conversion_link reference cleared (not deleted).","produces":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the conversion link","type":"integer","format":"int32","required":true}],"responses":{"204":{"description":"Delete a conversion link"}},"tags":["Conversion Links"],"operationId":"deleteApiV1ConversionLinksId"}},"/api/v1/templates":{"get":{"summary":"Search templates","description":"This endpoint searches for templates using semantic search. Returns scenarios or campaigns marked as templates.","produces":["application/json"],"parameters":[{"in":"query","name":"type","description":"Type of template to search","type":"string","enum":["Scenario","Campaign"],"required":true},{"in":"query","name":"query","description":"Search query for semantic search","type":"string","required":true}],"responses":{"200":{"description":"Search templates","schema":{"type":"object","properties":{"templates":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_TemplateEntity"}}}}}},"tags":["Templates"],"operationId":"getApiV1Templates"}},"/api/v1/medias":{"get":{"summary":"List medias","description":"Returns a paginated list of media posts for the organization, ordered by post date descending.","produces":["application/json"],"parameters":[{"in":"query","name":"page","description":"Page number","type":"integer","format":"int32","default":1,"required":false},{"in":"query","name":"per_page","description":"Number of items per page (max 1000)","type":"integer","format":"int32","default":20,"minimum":1,"maximum":1000,"required":false},{"in":"query","name":"status","description":"Filter by publication status","type":"string","enum":["published","pending","scheduled","draft"],"required":false},{"in":"query","name":"search","description":"Search medias by caption or thumbnail description","type":"string","required":false}],"responses":{"200":{"description":"List medias","schema":{"type":"object","properties":{"medias":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_MediaEntity"}}}}}},"tags":["Medias"],"operationId":"getApiV1Medias"},"post":{"summary":"Create a media post (draft, scheduled, or published)","description":"Creates a feed post from a previously uploaded media file (see\n`POST /media_files`). Supported types: IMAGE (single image), REELS\n(video), CAROUSEL (2–10 images/videos via `children`).\n\n- Omit both `scheduled_at` and `publish_now` to save a **draft**.\n- Set `scheduled_at` (future timestamp) to **schedule** automatic publishing.\n- Set `publish_now: true` to **publish immediately**.\n\nWith `publish_now`, fast posts (images, image carousels, short\nvideos) usually finish inside this request: the response then has\n`status: \"published\"` and a `permalink`, and nothing needs polling.\nA slower upload comes back `status: \"pending\"` — see\n`POST /medias/:id/publish` for how to follow it.\n\nSet `is_ai_generated: true` on AI-generated media — Meta requires\nthe disclosure on photorealistic AI content, and it can only be set\nwhile the post is created. Instagram lets an account owner remove\nthe label from a live post, never add it, so a post published\nwithout the flag stays undisclosed for good.\n\n`is_paid_partnership` and `branded_content_sponsors` add\nInstagram's \"Paid partnership\" label and the brands it names. Like\nthe AI disclosure they are read only while the post is created.\n\n`trial_graduation_strategy` publishes a REEL as a trial reel, shown\nonly to non-followers until it graduates.\n\nScheduling or publishing requires Instagram publishing permission;\nwithout it the request is rejected with 403 (see the `can_publish`\nfield on `GET /me`).\n","produces":["application/json"],"consumes":["application/json"],"parameters":[{"name":"postApiV1Medias","in":"body","required":true,"schema":{"$ref":"#/definitions/postApiV1Medias"}}],"responses":{"201":{"description":"Create a media post","schema":{"type":"object","properties":{"medias":{"$ref":"#/definitions/PublicApi_Entities_MediaEntity"}}}}},"tags":["Medias"],"operationId":"postApiV1Medias"}},"/api/v1/medias/{id}":{"get":{"summary":"Get a media","description":"Returns a specific media post by its Inrō ID.","produces":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the media","type":"integer","format":"int32","required":true}],"responses":{"200":{"description":"Get a media","schema":{"type":"object","properties":{"medias":{"$ref":"#/definitions/PublicApi_Entities_MediaEntity"}}}}},"tags":["Medias"],"operationId":"getApiV1MediasId"},"patch":{"summary":"Update a media draft","description":"Updates a draft or scheduled post. Provide only the fields to\nchange; setting `scheduled_at` (re)schedules and requires publishing\npermission. `is_ai_generated` can still be changed here while the\npost is a draft or scheduled — once it is published the label can\nonly be removed from Instagram, never added.\n\nA published post cannot have its content edited, but it does\naccept a request whose only fields are `comment_to_dm` and/or\n`agent_context` — those don't touch the post itself.\n","produces":["application/json"],"consumes":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the media","type":"integer","format":"int32","required":true},{"name":"patchApiV1MediasId","in":"body","required":true,"schema":{"$ref":"#/definitions/patchApiV1MediasId"}}],"responses":{"200":{"description":"Update a media draft","schema":{"type":"object","properties":{"medias":{"$ref":"#/definitions/PublicApi_Entities_MediaEntity"}}}}},"tags":["Medias"],"operationId":"patchApiV1MediasId"},"delete":{"summary":"Delete a media","description":"Deletes a media. Deleting a published post also removes it from Instagram.","produces":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the media","type":"integer","format":"int32","required":true}],"responses":{"204":{"description":"Delete a media"}},"tags":["Medias"],"operationId":"deleteApiV1MediasId"}},"/api/v1/medias/{id}/publish":{"post":{"summary":"Publish a draft/scheduled media now","description":"Immediately publishes a draft or scheduled post to Instagram.\n\nInstagram processes most containers in under a second, so this\nrequest waits briefly for the post to go live. Read the response\nbefore polling anything:\n\n- `status: \"published\"` (with `instagram_id` and `permalink`) — the\n  post is live and the publish is complete.\n- `status: \"pending\"` / `publish_status: \"PENDING\"` or\n  `\"IN_PROGRESS\"` — Instagram is still processing the upload\n  (typically a large video). Poll `GET /medias/:id` until `status`\n  becomes `\"published\"` or `publish_status` is `\"ERROR\"`.\n- `publish_status: \"ERROR\"` — the publish failed; see\n  `login_error_data`.\n\nRequires publishing permission.\n","produces":["application/json"],"consumes":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the media","type":"integer","format":"int32","required":true}],"responses":{"200":{"description":"Publish a media","schema":{"type":"object","properties":{"medias":{"$ref":"#/definitions/PublicApi_Entities_MediaEntity"}}}}},"tags":["Medias"],"operationId":"postApiV1MediasIdPublish"}},"/api/v1/medias/{id}/comment_to_dm":{"post":{"summary":"Attach or update this post's comment-to-DM automation","description":"Sets up the automation that publicly replies to people who comment\non this post and DMs them a tracked link. Works on a draft, a\nscheduled post, or one that is already published.\n\nSame payload and same behavior as the `comment_to_dm` field on\n`POST /medias` and `PATCH /medias/:id` — this is the direct route\nwhen the post already exists and you are not editing it. Call it\nagain for the same post to change the filter, the link or the\nquestion step; it updates that automation rather than creating a\nsecond one.\n","produces":["application/json"],"consumes":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the media","type":"integer","format":"int32","required":true},{"name":"postApiV1MediasIdCommentToDm","in":"body","required":true,"schema":{"$ref":"#/definitions/postApiV1MediasIdCommentToDm"}}],"responses":{"200":{"description":"Attach a comment-to-DM automation","schema":{"type":"object","properties":{"medias":{"$ref":"#/definitions/PublicApi_Entities_MediaEntity"}}}}},"tags":["Medias"],"operationId":"postApiV1MediasIdCommentToDm"}},"/api/v1/stories":{"get":{"summary":"List stories","description":"Returns a paginated list of stories for the organization, most recent first.","produces":["application/json"],"parameters":[{"in":"query","name":"page","description":"Page number","type":"integer","format":"int32","default":1,"required":false},{"in":"query","name":"per_page","description":"Number of items per page (max 1000)","type":"integer","format":"int32","default":20,"minimum":1,"maximum":1000,"required":false},{"in":"query","name":"status","description":"Filter by publication status","type":"string","enum":["published","pending","scheduled","draft"],"required":false}],"responses":{"200":{"description":"List stories","schema":{"type":"object","properties":{"stories":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_StoryEntity"}}}}}},"tags":["Stories"],"operationId":"getApiV1Stories"},"post":{"summary":"Create a story (draft, scheduled, or published)","description":"Creates a story from a previously uploaded media file (see\n`POST /media_files`). The asset can be an image or a video; the\nstory type is detected automatically.\n\n- Omit both `scheduled_at` and `publish_now` to save a **draft**.\n- Set `scheduled_at` (future timestamp) to **schedule** publishing.\n- Set `publish_now: true` to **publish immediately**.\n\nWith `publish_now`, an image or short video story usually finishes\ninside this request: the response then has `status: \"published\"` and\na `permalink`, and nothing needs polling. A slower upload comes back\n`status: \"pending\"` — see `POST /stories/:id/publish` for how to\nfollow it.\n\nSet `is_ai_generated: true` on AI-generated media — Meta requires\nthe disclosure on photorealistic AI content, and it can only be set\nwhile the story is created. Instagram lets an account owner remove\nthe label from a live story, never add it, so a story published\nwithout the flag stays undisclosed for good.\n\nScheduling or publishing requires Instagram publishing permission\n(see the `can_publish` field on `GET /me`).\n","produces":["application/json"],"consumes":["application/json"],"parameters":[{"name":"postApiV1Stories","in":"body","required":true,"schema":{"$ref":"#/definitions/postApiV1Stories"}}],"responses":{"201":{"description":"Create a story","schema":{"type":"object","properties":{"stories":{"$ref":"#/definitions/PublicApi_Entities_StoryEntity"}}}}},"tags":["Stories"],"operationId":"postApiV1Stories"}},"/api/v1/stories/{id}":{"get":{"summary":"Get a story","description":"Returns a specific story by its Inrō ID.","produces":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the story","type":"integer","format":"int32","required":true}],"responses":{"200":{"description":"Get a story","schema":{"type":"object","properties":{"stories":{"$ref":"#/definitions/PublicApi_Entities_StoryEntity"}}}}},"tags":["Stories"],"operationId":"getApiV1StoriesId"},"patch":{"summary":"Update a story draft","description":"Updates a draft or scheduled story. Provide only the fields to change; setting `scheduled_at` (re)schedules and requires publishing permission. `is_ai_generated` can still be changed while the story is a draft or scheduled — once it is published the label can only be removed from Instagram, never added. A published story cannot have its content edited, but it does accept a request whose only field is `agent_context`.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the story","type":"integer","format":"int32","required":true},{"name":"patchApiV1StoriesId","in":"body","required":true,"schema":{"$ref":"#/definitions/patchApiV1StoriesId"}}],"responses":{"200":{"description":"Update a story draft","schema":{"type":"object","properties":{"stories":{"$ref":"#/definitions/PublicApi_Entities_StoryEntity"}}}}},"tags":["Stories"],"operationId":"patchApiV1StoriesId"},"delete":{"summary":"Delete a story","description":"Deletes a draft/scheduled story from Inrō.","produces":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the story","type":"integer","format":"int32","required":true}],"responses":{"204":{"description":"Delete a story"}},"tags":["Stories"],"operationId":"deleteApiV1StoriesId"}},"/api/v1/stories/{id}/publish":{"post":{"summary":"Publish a draft/scheduled story now","description":"Immediately publishes a draft or scheduled story to Instagram.\n\nInstagram processes most containers in under a second, so this\nrequest waits briefly for the story to go live. Read the response\nbefore polling anything:\n\n- `status: \"published\"` (with `instagram_id` and `permalink`) — the\n  story is live and the publish is complete.\n- `status: \"pending\"` / `publish_status: \"PENDING\"` or\n  `\"IN_PROGRESS\"` — Instagram is still processing the upload\n  (typically a large video). Poll `GET /stories/:id` until `status`\n  becomes `\"published\"` or `publish_status` is `\"ERROR\"`.\n- `publish_status: \"ERROR\"` — the publish failed.\n\nRequires publishing permission.\n","produces":["application/json"],"consumes":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the story","type":"integer","format":"int32","required":true}],"responses":{"200":{"description":"Publish a story","schema":{"type":"object","properties":{"stories":{"$ref":"#/definitions/PublicApi_Entities_StoryEntity"}}}}},"tags":["Stories"],"operationId":"postApiV1StoriesIdPublish"}},"/api/v1/media_files":{"get":{"summary":"List media files","description":"Returns a paginated list of uploaded media files for the organization.","produces":["application/json"],"parameters":[{"in":"query","name":"page","description":"Page number","type":"integer","format":"int32","default":1,"required":false},{"in":"query","name":"per_page","description":"Number of items per page (max 1000)","type":"integer","format":"int32","default":20,"minimum":1,"maximum":1000,"required":false},{"in":"query","name":"media_type","description":"Filter by media type","type":"string","enum":["image","audio","video","application","text"],"required":false}],"responses":{"200":{"description":"List media files","schema":{"type":"object","properties":{"media_files":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_MediaFileEntity"}}}}}},"tags":["Media files"],"operationId":"getApiV1MediaFiles"},"post":{"summary":"Create a media file","description":"Creates a media file using one of these input modes:\n\n- `file_url` — we download the file server-side. Preferred whenever\n  the file is reachable at an address; the record comes back `ready`.\n- `file` (multipart) — direct upload; the record comes back `ready`.\n- **neither** — returns a `pending` record plus a single-use\n  `upload_url` to PUT the raw file bytes to (ideal for large videos),\n  an `upload_page_url` to hand to a person who has the file, and\n  `expires_at`. The record becomes `ready` once the bytes land.\n  Provide `media_type` so the correct size limit applies.\n\nThe upload URL and page are invalidated by the first successful\nupload and by `expires_at`, whichever comes first. Poll\n`GET /media_files/:id` and read `upload_status` to follow a pending\nupload to `ready` or `failed`.\n\nSize limits apply (images/audio 25MB, video 250MB); oversized uploads\nare rejected. The limit follows the file's `media_type`, which is\nauto-detected from the file when you do not name it.\n\nThe file is stored exactly as uploaded, so it is safe to use for\nmedia, reels and stories. DMs and templates send a smaller copy\nmade for them. `purpose` is only a hint: `publishing` skips\npreparing that copy up front, and it never affects quality.\n\nRegardless of the input mode, the resulting media file behaves\nidentically afterwards.\n","produces":["application/json"],"consumes":["application/json"],"parameters":[{"name":"postApiV1MediaFiles","in":"body","required":true,"schema":{"$ref":"#/definitions/postApiV1MediaFiles"}}],"responses":{"201":{"description":"Create a media file","schema":{"type":"object","properties":{"media_files":{"$ref":"#/definitions/PublicApi_Entities_MediaFileEntity"}}}}},"tags":["Media files"],"operationId":"postApiV1MediaFiles"}},"/api/v1/media_files/{id}/upload":{"put":{"summary":"Upload bytes to a pre-authenticated upload URL","description":"Completes the upload_url flow: PUT the raw file bytes as the request\nbody to the single-use URL returned by `POST /media_files` (the URL\nalready carries its `token`, so no Authorization header is needed).\nSet `Content-Type` to the file's MIME type. On success the media file\ntransitions to `ready` and the URL is invalidated — a second PUT\nreturns 404, as does any PUT after `expires_at`. Oversized bodies are\nrejected with 422 and the file is marked `failed` (the URL stays\nvalid, until it expires, so you can retry).\n","produces":["application/json"],"consumes":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the pending media file","type":"integer","format":"int32","required":true},{"name":"putApiV1MediaFilesIdUpload","in":"body","required":true,"schema":{"$ref":"#/definitions/putApiV1MediaFilesIdUpload"}}],"responses":{"200":{"description":"Upload bytes for a pending media file","schema":{"type":"object","properties":{"media_files":{"$ref":"#/definitions/PublicApi_Entities_MediaFileEntity"}}}}},"tags":["Media files"],"operationId":"putApiV1MediaFilesIdUpload"}},"/api/v1/media_files/{id}/refresh_upload":{"post":{"summary":"Mint a new upload URL and upload page for a pending file","description":"Issues a fresh `upload_url`, `upload_page_url` and `expires_at` for a\nmedia file whose upload has not completed. Use this when a file is\nstill `pending` and its `expires_at` has passed, instead of creating\na new media file: the record keeps its ID and any parts already\nuploaded through the upload page, so the person can resume rather\nthan restart.\n\nThe previous URL and page stop working immediately — a refresh never\nleaves two live links for the same file. A `failed` file returns to\n`pending` so the rejected upload can be retried.\n\nReturns `422` if the file is already `ready`, and `404` once it has\nbeen cleaned up (roughly a day after it expired) — create a new media\nfile in that case.\n","produces":["application/json"],"consumes":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the media file","type":"integer","format":"int32","required":true}],"responses":{"200":{"description":"Refresh the upload URL of a pending media file","schema":{"type":"object","properties":{"media_files":{"$ref":"#/definitions/PublicApi_Entities_MediaFileEntity"}}}}},"tags":["Media files"],"operationId":"postApiV1MediaFilesIdRefreshUpload"}},"/api/v1/media_files/{id}":{"get":{"summary":"Get a media file","description":"Returns a specific media file by ID.","produces":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the media file","type":"integer","format":"int32","required":true}],"responses":{"200":{"description":"Get a media file","schema":{"type":"object","properties":{"media_files":{"$ref":"#/definitions/PublicApi_Entities_MediaFileEntity"}}}}},"tags":["Media files"],"operationId":"getApiV1MediaFilesId"}},"/api/v1/agent":{"get":{"summary":"Get agent","description":"Returns the organization's AI agent configuration, including trigger rules, account data, options, actions, knowledge items, and tracked contact properties.","produces":["application/json"],"responses":{"200":{"description":"Get the AI agent configuration","schema":{"type":"object","properties":{"agent":{"$ref":"#/definitions/PublicApi_Entities_AgentEntity"}}}}},"tags":["Agent"],"operationId":"getApiV1Agent"},"patch":{"summary":"Update agent","description":"Updates the organization's AI agent configuration. Only the provided fields are updated.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"name":"patchApiV1Agent","in":"body","required":true,"schema":{"$ref":"#/definitions/patchApiV1Agent"}}],"responses":{"200":{"description":"Update the AI agent configuration","schema":{"type":"object","properties":{"agent":{"$ref":"#/definitions/PublicApi_Entities_AgentEntity"}}}}},"tags":["Agent"],"operationId":"patchApiV1Agent"}},"/api/v1/agent/items":{"get":{"summary":"List agent knowledge items","description":"Returns all knowledge base items for the agent (text, URL, and file items).","produces":["application/json"],"parameters":[{"in":"query","name":"page","description":"Page offset to fetch.","type":"integer","format":"int32","default":1,"required":false},{"in":"query","name":"per_page","description":"Number of results to return per page.","type":"integer","format":"int32","default":25,"required":false},{"in":"query","name":"offset","description":"Pad a number of results.","type":"integer","format":"int32","default":0,"required":false}],"responses":{"200":{"description":"List agent knowledge items","schema":{"type":"object","properties":{"agent_items":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_AgentItemEntity"}}}}}},"tags":["Agent"],"operationId":"getApiV1AgentItems"},"post":{"summary":"Create agent knowledge item","description":"Creates a new knowledge base item. For text items provide `text`. For URL items provide `source_url`. The item is processed asynchronously to generate embeddings.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"name":"postApiV1AgentItems","in":"body","required":true,"schema":{"$ref":"#/definitions/postApiV1AgentItems"}}],"responses":{"201":{"description":"Create an agent knowledge item","schema":{"type":"object","properties":{"agent_item":{"$ref":"#/definitions/PublicApi_Entities_AgentItemEntity"}}}}},"tags":["Agent"],"operationId":"postApiV1AgentItems"}},"/api/v1/agent/items/{id}":{"get":{"summary":"Get agent knowledge item","description":"Returns a specific knowledge base item.","produces":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the knowledge item","type":"integer","format":"int32","required":true}],"responses":{"200":{"description":"Get an agent knowledge item","schema":{"type":"object","properties":{"agent_item":{"$ref":"#/definitions/PublicApi_Entities_AgentItemEntity"}}}}},"tags":["Agent"],"operationId":"getApiV1AgentItemsId"},"patch":{"summary":"Update agent knowledge item","description":"Updates a knowledge base item. Changing text or source_url triggers re-processing of embeddings.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the knowledge item","type":"integer","format":"int32","required":true},{"name":"patchApiV1AgentItemsId","in":"body","required":true,"schema":{"$ref":"#/definitions/patchApiV1AgentItemsId"}}],"responses":{"200":{"description":"Update an agent knowledge item","schema":{"type":"object","properties":{"agent_item":{"$ref":"#/definitions/PublicApi_Entities_AgentItemEntity"}}}}},"tags":["Agent"],"operationId":"patchApiV1AgentItemsId"},"delete":{"summary":"Delete agent knowledge item","description":"Deletes a knowledge base item and all its associated embeddings.","produces":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the knowledge item","type":"integer","format":"int32","required":true}],"responses":{"204":{"description":"Delete an agent knowledge item"}},"tags":["Agent"],"operationId":"deleteApiV1AgentItemsId"}},"/api/v1/agent/actions":{"get":{"summary":"List agent actions","description":"Returns all configured actions for the agent. Actions are triggered when a contact's message matches the action's intent.","produces":["application/json"],"responses":{"200":{"description":"List agent actions","schema":{"type":"object","properties":{"agent_actions":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_AgentActionEntity"}}}}}},"tags":["Agent"],"operationId":"getApiV1AgentActions"},"post":{"summary":"Create agent action","description":"Creates a new agent action. When a contact's message matches the trigger intent, the agent performs the specified action (add to folder, run scenario, send conversion link, or send survey).","produces":["application/json"],"consumes":["application/json"],"parameters":[{"name":"postApiV1AgentActions","in":"body","required":true,"schema":{"$ref":"#/definitions/postApiV1AgentActions"}}],"responses":{"201":{"description":"Create an agent action","schema":{"type":"object","properties":{"agent_action":{"$ref":"#/definitions/PublicApi_Entities_AgentActionEntity"}}}}},"tags":["Agent"],"operationId":"postApiV1AgentActions"}},"/api/v1/agent/actions/{id}":{"patch":{"summary":"Update agent action","description":"Updates an existing agent action.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the agent action","type":"integer","format":"int32","required":true},{"name":"patchApiV1AgentActionsId","in":"body","required":true,"schema":{"$ref":"#/definitions/patchApiV1AgentActionsId"}}],"responses":{"200":{"description":"Update an agent action","schema":{"type":"object","properties":{"agent_action":{"$ref":"#/definitions/PublicApi_Entities_AgentActionEntity"}}}}},"tags":["Agent"],"operationId":"patchApiV1AgentActionsId"},"delete":{"summary":"Delete agent action","description":"Deletes an agent action.","produces":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the agent action","type":"integer","format":"int32","required":true}],"responses":{"204":{"description":"Delete an agent action"}},"tags":["Agent"],"operationId":"deleteApiV1AgentActionsId"}},"/api/v1/agent/contact_properties":{"get":{"summary":"List agent tracked contact properties","description":"Returns all contact properties the agent is configured to detect and extract during conversations.","produces":["application/json"],"responses":{"200":{"description":"List agent tracked contact properties","schema":{"type":"object","properties":{"agent_contact_properties":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_AgentContactPropertyEntity"}}}}}},"tags":["Agent"],"operationId":"getApiV1AgentContactProperties"},"post":{"summary":"Create agent contact property tracking","description":"Configures the agent to detect and extract a contact property during conversations. Use `field_name` for built-in fields (email, phone) or `contact_property_id` for custom properties.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"name":"postApiV1AgentContactProperties","in":"body","required":true,"schema":{"$ref":"#/definitions/postApiV1AgentContactProperties"}}],"responses":{"201":{"description":"Add a contact property for the agent to track","schema":{"type":"object","properties":{"agent_contact_property":{"$ref":"#/definitions/PublicApi_Entities_AgentContactPropertyEntity"}}}}},"tags":["Agent"],"operationId":"postApiV1AgentContactProperties"}},"/api/v1/agent/contact_properties/{id}":{"delete":{"summary":"Delete agent contact property tracking","description":"Removes a contact property from the agent's tracking configuration.","produces":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the agent contact property mapping","type":"integer","format":"int32","required":true}],"responses":{"204":{"description":"Remove a contact property from agent tracking"}},"tags":["Agent"],"operationId":"deleteApiV1AgentContactPropertiesId"}},"/api/v1/batch_tasks":{"get":{"summary":"List batch tasks","description":"Returns a paginated list of batch tasks (e.g. campaign sends and bulk contact updates) for the organization, most recent first. Use this to track the progress of long-running operations.","produces":["application/json"],"parameters":[{"in":"query","name":"page","description":"Page number","type":"integer","format":"int32","default":1,"required":false},{"in":"query","name":"per_page","description":"Number of items per page (max 1000)","type":"integer","format":"int32","default":20,"minimum":1,"maximum":1000,"required":false},{"in":"query","name":"status","description":"Filter by status","type":"string","enum":["pending","processing","completed","failed","canceled","paused"],"required":false},{"in":"query","name":"task_type","description":"Filter by task type","type":"string","enum":["campaign_send","contact_bulk_update","retroactive_automation","contact_property_detection","contact_folder_update"],"required":false}],"responses":{"200":{"description":"List batch tasks","schema":{"type":"object","properties":{"batch_tasks":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_BatchTaskEntity"}}}}}},"tags":["Batch tasks"],"operationId":"getApiV1BatchTasks"}},"/api/v1/batch_tasks/{id}":{"get":{"summary":"Get a batch task","description":"Returns a single batch task by ID, including its current progress.","produces":["application/json"],"parameters":[{"in":"path","name":"id","description":"The ID of the batch task","type":"integer","format":"int32","required":true}],"responses":{"200":{"description":"Get a batch task","schema":{"type":"object","properties":{"batch_task":{"$ref":"#/definitions/PublicApi_Entities_BatchTaskEntity"}}}}},"tags":["Batch tasks"],"operationId":"getApiV1BatchTasksId"}},"/api/v1/automation/health":{"get":{"summary":"Automation health","description":"Start a troubleshooting session here. Returns run totals by status for the window, the failure rate, the automations failing most (ranked by failure rate, not volume), the most common reason codes, and the account-level blockers — a broken Instagram connection or an exhausted activation limit — that stop runs before any step executes. Counts only, never rows. Cached for a minute; `computed_at` says when it was calculated.","produces":["application/json"],"parameters":[{"in":"query","name":"since","description":"Start of the window (default: 7 days ago, maximum lookback: 90 days)","type":"string","format":"date-time","required":false},{"in":"query","name":"until","description":"End of the window (default: now)","type":"string","format":"date-time","required":false}],"responses":{"200":{"description":"Automation health","schema":{"type":"object","properties":{"automation_health":{"$ref":"#/definitions/PublicApi_Entities_AutomationHealthEntity"}}}}},"tags":["Automation executions"],"operationId":"getApiV1AutomationHealth"}},"/api/v1/automation/executions":{"get":{"summary":"List automation runs","description":"Returns scenario and campaign runs together, newest first. Filter by `status` or `reason_code` to see only the failures, or by `contact_id` to answer \"did this automation ever run for this person?\" — an empty result there is itself the answer, and points at the account-level blockers in `GET /v1/automation/health` rather than at the flow. Test runs are excluded unless `include_test` is set. Serves the last 90 days; a single run stays readable by ID at any age.","produces":["application/json"],"parameters":[{"in":"query","name":"page","description":"Page offset to fetch.","type":"integer","format":"int32","default":1,"required":false},{"in":"query","name":"per_page","description":"Number of results to return per page.","type":"integer","format":"int32","default":25,"required":false},{"in":"query","name":"offset","description":"Pad a number of results.","type":"integer","format":"int32","default":0,"required":false},{"in":"query","name":"type","description":"Only runs of this kind of automation","type":"string","enum":["scenario","campaign"],"required":false},{"in":"query","name":"scenario_id","description":"Only runs of this scenario (excludes campaign runs)","type":"integer","format":"int32","required":false},{"in":"query","name":"campaign_id","description":"Only runs of this campaign (excludes scenario runs)","type":"integer","format":"int32","required":false},{"in":"query","name":"contact_id","description":"Only runs for this contact","type":"integer","format":"int32","required":false},{"in":"query","name":"status","description":"Only runs in this status. `limited`, `disconnected` and `restricted` are paused rather than finished.","type":"string","enum":["pending","completed","failed","partially_completed","interrupted","limited","disconnected","restricted"],"required":false},{"in":"query","name":"reason_code","description":"Only runs that ended for this reason. Pair with `GET /v1/automation/health`, which returns the codes actually occurring in the window.","type":"string","enum":["contact_replied","manual_reply","conversation_handled_by_human","contact_in_excluded_folder","contact_matches_exclusion_filter","hate_speech_detected","scenario_not_active","scenario_suspended","plan_limit_reached","instagram_disconnected","account_restricted","dm_held_window","dm_held_private_reply","execution_interrupted","execution_expired_stuck","execution_resolved_stuck","execution_cancelled_by_user","execution_cancelled_manually","execution_cancelled_restriction","interrupted_by_test_run","interrupted_by_user","action_skipped","action_error","unexpected_error"],"required":false},{"in":"query","name":"execution_type","description":"How the run was started (scenario runs only)","type":"string","enum":["automated","manual","agent"],"required":false},{"in":"query","name":"since","description":"Only runs started after this (default: 7 days ago, maximum lookback: 90 days)","type":"string","format":"date-time","required":false},{"in":"query","name":"until","description":"Only runs started before this (default: now)","type":"string","format":"date-time","required":false},{"in":"query","name":"include_test","description":"Include test runs","type":"boolean","default":false,"required":false},{"in":"query","name":"search","description":"Fulltext search over the run's contact","type":"string","required":false}],"responses":{"200":{"description":"List automation runs","schema":{"type":"object","properties":{"executions":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_ExecutionEntity"}}}}}},"tags":["Automation executions"],"operationId":"getApiV1AutomationExecutions"}},"/api/v1/automation/executions/{type}/{id}":{"get":{"summary":"Get an automation run","description":"Returns one run with its ordered step trail: the status of each step, why the failing one failed, how many times it was retried, the attempts that failed before a retry succeeded, and `action_data` — the action's configuration as it was when the step ran, which is what to read when the automation has been edited since. Readable at any age, unlike the list.","produces":["application/json"],"parameters":[{"in":"path","name":"type","description":"Which kind of automation ran","type":"string","enum":["scenario","campaign"],"required":true},{"in":"path","name":"id","description":"The ID of the run","type":"integer","format":"int32","required":true}],"responses":{"200":{"description":"Get an automation run","schema":{"type":"object","properties":{"execution":{"$ref":"#/definitions/PublicApi_Entities_ExecutionEntity"}}}}},"tags":["Automation executions"],"operationId":"getApiV1AutomationExecutionsTypeId"}},"/api/v1/automation/executions/{type}/{id}/retry":{"post":{"summary":"Retry an automation run","description":"Re-runs a run from its first step. Use it on a run paused by a problem that has since been fixed — a reconnected Instagram account (`disconnected`), a lifted restriction (`restricted`), an upgraded plan (`limited`) — or on one that failed for a transient reason. A run that already completed is left alone.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"in":"path","name":"type","description":"Which kind of automation ran","type":"string","enum":["scenario","campaign"],"required":true},{"in":"path","name":"id","description":"The ID of the run","type":"integer","format":"int32","required":true}],"responses":{"200":{"description":"Retry an automation run","schema":{"type":"object","properties":{"execution":{"$ref":"#/definitions/PublicApi_Entities_ExecutionEntity"}}}}},"tags":["Automation executions"],"operationId":"postApiV1AutomationExecutionsTypeIdRetry"}},"/api/v1/automation/executions/{type}/{id}/steps/{step_id}/retry":{"post":{"summary":"Retry one step of a run","description":"Re-runs a single failed step in place, leaving the steps before it alone. Prefer this over retrying the whole run when the earlier steps already did something the contact saw — a comment reply, a DM — and you do not want them repeated.","produces":["application/json"],"consumes":["application/json"],"parameters":[{"in":"path","name":"type","description":"Which kind of automation ran","type":"string","enum":["scenario","campaign"],"required":true},{"in":"path","name":"id","description":"The ID of the run","type":"integer","format":"int32","required":true},{"in":"path","name":"step_id","description":"The ID of the step","type":"integer","format":"int32","required":true}],"responses":{"200":{"description":"Retry one step of a run","schema":{"type":"object","properties":{"step":{"$ref":"#/definitions/PublicApi_Entities_ExecutionStepEntity"}}}}},"tags":["Automation executions"],"operationId":"postApiV1AutomationExecutionsTypeIdStepsStepIdRetry"}},"/api/v1/settings/optout":{"get":{"summary":"Get opt-out settings","description":"Returns the organization's opt-out settings: whether opt-out\nhandling is active, the keywords that opt a contact out, the label\nof the opt-out entry in the Instagram persistent menu, the\nconfirmation message sent afterwards, and whether the AI Agent may\nalso recognize an opt-out request in its own words.\n\nA contact that opts out gets the `optout` status and is skipped by\nevery automation and campaign.\n","produces":["application/json"],"responses":{"200":{"description":"Get the opt-out settings","schema":{"type":"object","properties":{"optout_settings":{"$ref":"#/definitions/PublicApi_Entities_OptoutSettingsEntity"}}}}},"tags":["Settings"],"operationId":"getApiV1SettingsOptout"},"patch":{"summary":"Update opt-out settings","description":"Updates the organization's opt-out settings. Only the provided\nfields are changed; the others keep their current value.\n\nTurning `active` on adds `menu_message` to the Instagram persistent\nmenu (nothing is added when it is blank); turning it off removes\nthe entry. Both take effect on Instagram as part of this call.\n","produces":["application/json"],"consumes":["application/json"],"parameters":[{"name":"patchApiV1SettingsOptout","in":"body","required":true,"schema":{"$ref":"#/definitions/patchApiV1SettingsOptout"}}],"responses":{"200":{"description":"Update the opt-out settings","schema":{"type":"object","properties":{"optout_settings":{"$ref":"#/definitions/PublicApi_Entities_OptoutSettingsEntity"}}}}},"tags":["Settings"],"operationId":"patchApiV1SettingsOptout"}},"/api/v1/icebreakers":{"get":{"summary":"List icebreakers","description":"Returns the icebreakers currently shown on the Instagram profile, in\nthe order Instagram displays them.\n\nIcebreakers are stored on Instagram only — any app connected to the\naccount can change them — so this list is read from the Graph API on\nevery call rather than from a copy on our side.\n\nEach one carries the `automations` that fire when it is tapped: the\nscenarios whose `icebreaker` trigger matches it, plus any referral\nscenario Inrō set the icebreaker up for. An empty `automations`\narray means tapping it starts no conversation.\n","produces":["application/json"],"responses":{"200":{"description":"List icebreakers","schema":{"type":"object","properties":{"icebreakers":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_IcebreakerEntity"}}}}}},"tags":["Icebreakers"],"operationId":"getApiV1Icebreakers"},"post":{"summary":"Create an icebreaker","description":"Adds an icebreaker to the Instagram profile and returns the full\nupdated list. The payload identifying it is generated by Inrō and\nreturned in the response — keep it to update or delete the\nicebreaker later, or to match it from an `icebreaker` scenario\ntrigger.\n\nA new icebreaker has no automation behind it until a scenario\ntriggers on it, so the response carries a `notice` saying so and\nwhat to create.\n\nInstagram allows at most 4 icebreakers per profile; a fifth is\nrejected with **422** rather than sent and dropped.\n","produces":["application/json"],"consumes":["application/json"],"parameters":[{"name":"postApiV1Icebreakers","in":"body","required":true,"schema":{"$ref":"#/definitions/postApiV1Icebreakers"}}],"responses":{"201":{"description":"Create an icebreaker","schema":{"type":"object","properties":{"icebreakers":{"$ref":"#/definitions/PublicApi_Entities_IcebreakerEntity"}}}}},"tags":["Icebreakers"],"operationId":"postApiV1Icebreakers"}},"/api/v1/icebreakers/{payload}":{"patch":{"summary":"Update an icebreaker","description":"Rewrites the question of an existing icebreaker and returns the full\nupdated list. The payload is kept, so a scenario trigger matching on\nit keeps working.\n\nA trigger matching on `icebreaker_title` does not: rewording the\nquestion stops it firing. When that happens the response carries a\n`notice` naming the scenario that no longer matches and how to\nreconnect it.\n","produces":["application/json"],"consumes":["application/json"],"parameters":[{"in":"path","name":"payload","description":"The payload of the icebreaker to update","type":"string","required":true},{"name":"patchApiV1IcebreakersPayload","in":"body","required":true,"schema":{"$ref":"#/definitions/patchApiV1IcebreakersPayload"}}],"responses":{"200":{"description":"Update an icebreaker","schema":{"type":"object","properties":{"icebreakers":{"$ref":"#/definitions/PublicApi_Entities_IcebreakerEntity"}}}}},"tags":["Icebreakers"],"operationId":"patchApiV1IcebreakersPayload"},"delete":{"summary":"Delete an icebreaker","description":"Removes an icebreaker from the Instagram profile and returns the\nremaining ones.\n\nDeleting one that has `automations` leaves those scenarios with\nnothing to fire them; remove the trigger too, or re-save the\nscenario to put the icebreaker back.\n","produces":["application/json"],"parameters":[{"in":"path","name":"payload","description":"The payload of the icebreaker to delete","type":"string","required":true}],"responses":{"200":{"description":"Delete an icebreaker","schema":{"type":"object","properties":{"icebreakers":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_IcebreakerEntity"}}}}}},"tags":["Icebreakers"],"operationId":"deleteApiV1IcebreakersPayload"}},"/api/v1/persistent_menu":{"get":{"summary":"Get the persistent menu","description":"Returns the entries of the always-visible menu in the Instagram\nconversation, in the order Instagram displays them.\n\nLike icebreakers, the menu is stored on Instagram only — any app\nconnected to the account can change it — so it is read from the\nGraph API on every call rather than from a copy on our side. The\nmenu returned is the `default` locale, the one Instagram falls back\nto for every viewer; locale-specific overrides another app set are\npreserved but not listed or edited here.\n\nA `postback` entry sends its payload to Inrō as a message when\ntapped, which an `icebreaker` scenario trigger can match on its\npayload. A `web_url` entry opens a URL and reaches no automation.\n","produces":["application/json"],"responses":{"200":{"description":"Get the persistent menu","schema":{"type":"object","properties":{"persistent_menu":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_PersistentMenuItemEntity"}}}}}},"tags":["Persistent menu"],"operationId":"getApiV1PersistentMenu"},"post":{"summary":"Add a persistent menu entry","description":"Adds an entry to the menu and returns the full updated menu. An\nentry whose id already exists is replaced in place, keeping its\nposition, so adding the same entry twice is safe.\n\nInstagram's guidance is to keep the menu to 5 entries or fewer; more\nare accepted but crowd the menu.\n","produces":["application/json"],"consumes":["application/json"],"parameters":[{"name":"postApiV1PersistentMenu","in":"body","required":true,"schema":{"$ref":"#/definitions/postApiV1PersistentMenu"}}],"responses":{"201":{"description":"Add a persistent menu entry","schema":{"type":"object","properties":{"persistent_menu":{"$ref":"#/definitions/PublicApi_Entities_PersistentMenuItemEntity"}}}}},"tags":["Persistent menu"],"operationId":"postApiV1PersistentMenu"}},"/api/v1/persistent_menu/{id}":{"patch":{"summary":"Update a persistent menu entry","description":"Changes the label or URL of an entry, keeping its position in the\nmenu and, for a postback, its payload — so an `icebreaker` trigger\nmatching on that payload keeps working.\n\nA link is identified by its title, so renaming one changes its `id`.\n\nRenaming the entry the opt-out setting maintains\n(`source: \"optout\"`) also updates that setting's `menu_message`,\nsince otherwise the next opt-out save would undo the rename. The\nresponse says so in a `notice`.\n","produces":["application/json"],"consumes":["application/json"],"parameters":[{"in":"path","name":"id","description":"The entry's id: its payload, or its title for a link","type":"string","required":true},{"name":"patchApiV1PersistentMenuId","in":"body","required":true,"schema":{"$ref":"#/definitions/patchApiV1PersistentMenuId"}}],"responses":{"200":{"description":"Update a persistent menu entry","schema":{"type":"object","properties":{"persistent_menu":{"$ref":"#/definitions/PublicApi_Entities_PersistentMenuItemEntity"}}}}},"tags":["Persistent menu"],"operationId":"patchApiV1PersistentMenuId"},"delete":{"summary":"Delete a persistent menu entry","description":"Removes an entry and returns the remaining menu.\n\nDeleting the entry the opt-out setting maintains\n(`source: \"optout\"`) **turns opt-out off**, rather than leaving a\nsetting that is on with no menu entry and would restore it on its\nnext save. Keywords then stop opting contacts out and no\nconfirmation message is sent; the response says so in a `notice`.\nRe-enable it with `PATCH /v1/settings/optout`.\n","produces":["application/json"],"parameters":[{"in":"path","name":"id","description":"The entry's id: its payload, or its title for a link","type":"string","required":true}],"responses":{"200":{"description":"Delete a persistent menu entry","schema":{"type":"object","properties":{"persistent_menu":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_PersistentMenuItemEntity"}}}}}},"tags":["Persistent menu"],"operationId":"deleteApiV1PersistentMenuId"}},"/api/v1/partner":{"get":{"summary":"Partner account","description":"Identity of the partner the token belongs to, how many\norganizations it owns, and whether Stripe holds a payment method —\nwithout which creating an organization is refused.\n","produces":["application/json"],"responses":{"200":{"description":"Get the authenticated partner account","schema":{"type":"object","properties":{"partner":{"$ref":"#/definitions/PublicApi_Entities_PartnerEntity"}}}}},"tags":["Partner"],"operationId":"getApiV1Partner"}},"/api/v1/partner/organizations":{"get":{"summary":"List organizations","description":"Every organization this partner owns, connected or not. Poll this\nafter creating one to see when the account owner has finished\nconnecting Instagram — `instagram_connected` flips to true and\n`username` is filled in.\n","produces":["application/json"],"parameters":[{"in":"query","name":"connected","description":"Filter by Instagram connection state. Omit for both.","type":"boolean","required":false}],"responses":{"200":{"description":"List the partner's organizations","schema":{"type":"object","properties":{"organizations":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_PartnerOrganizationEntity"}}}}}},"tags":["Partner"],"operationId":"getApiV1PartnerOrganizations"},"post":{"summary":"Create organization","description":"Creates an empty organization owned by this partner and billed\nthrough the partner's Stripe customer. It is not usable until\nsomebody connects an Instagram account to it: send the returned\n`instagram_connect_url` to the account owner, then poll\n`GET /api/v1/partner/organizations` for `instagram_connected`.\n\nPass `partner_link_code` to create it through one of your managed\nlinks, which attributes it to that link and duplicates the link's\ndefault template. `template_id` overrides the template for this\none call.\n\nRefused with `422 no_payment_method` when Stripe holds no usable\npayment method on the partner's customer.\n","produces":["application/json"],"consumes":["application/json"],"parameters":[{"name":"postApiV1PartnerOrganizations","in":"body","required":true,"schema":{"$ref":"#/definitions/postApiV1PartnerOrganizations"}}],"responses":{"201":{"description":"Create an organization","schema":{"type":"object","properties":{"organizations":{"$ref":"#/definitions/PublicApi_Entities_PartnerOrganizationEntity"}}}}},"tags":["Partner"],"operationId":"postApiV1PartnerOrganizations"}},"/api/v1/partner/organizations/{id}":{"get":{"summary":"Get organization","description":"Get one of the partner's organizations","produces":["application/json"],"parameters":[{"in":"path","name":"id","description":"The organization's ID","type":"integer","format":"int32","required":true}],"responses":{"200":{"description":"Get one of the partner's organizations","schema":{"type":"object","properties":{"organizations":{"$ref":"#/definitions/PublicApi_Entities_PartnerOrganizationEntity"}}}}},"tags":["Partner"],"operationId":"getApiV1PartnerOrganizationsId"},"delete":{"summary":"Delete organization","description":"Deletes an organization that never connected Instagram — one\ncreated by mistake, or for a client who never went through with it.\n\nAn organization with Instagram connected is a live account and is\nrefused with `422`. Disconnect it from the account itself first if\nit really is to be deleted.\n","produces":["application/json"],"parameters":[{"in":"path","name":"id","description":"The organization's ID","type":"integer","format":"int32","required":true}],"responses":{"204":{"description":"Delete an unconnected organization"}},"tags":["Partner"],"operationId":"deleteApiV1PartnerOrganizationsId"}},"/api/v1/partner/links":{"get":{"summary":"List partner links","description":"The referral and managed links configured for this partner. A\nmanaged link's `code` is what `POST /api/v1/partner/organizations`\naccepts as `partner_link_code`.\n","produces":["application/json"],"responses":{"200":{"description":"List the partner's links","schema":{"type":"object","properties":{"partner_links":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_PartnerLinkEntity"}}}}}},"tags":["Partner"],"operationId":"getApiV1PartnerLinks"}}},"definitions":{"PublicApi_Entities_OrganizationEntity":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string","example":"jane.doe@example.com","description":"The email of the Instagram organization account"},"name":{"type":"string","example":"ACME","description":"The name of the Instagram organization account"},"created_at":{"type":"string","format":"date-time","description":"When the organization was created"},"updated_at":{"type":"string","format":"date-time","description":"When the organization was last updated"},"username":{"type":"string","example":"acme","description":"The username of the Instagram organization account"},"login_method":{"type":"string","example":"facebook","description":"Method used to connect the account (facebook or instagram)"},"instagram_linked_at":{"type":"string","format":"date-time","description":"When the Instagram account was connected"},"login_error_data":{"type":"object","description":"Error information from login attempts, if any"},"instagram_restrictions":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_InstagramRestrictionEntity"},"description":"Account-wide restrictions Meta currently applies to the connected Instagram account, oldest first. Empty when none"},"can_publish":{"type":"boolean","example":true,"description":"Whether the connected Instagram account has granted the permissions required to publish media and stories. When false, publishing and scheduling requests are rejected. True when the granted scopes are not known, in which case Meta decides the request rather than this field."},"missing_publish_scopes":{"type":"array","items":{"type":"array"},"example":["instagram_content_publish"],"description":"Instagram permission scopes still required before publishing is possible. Empty when `can_publish` is true."},"publishing_reauth_url":{"type":"string","example":"https://app.inro.social/users/auth/instagram","description":"URL the account owner opens in a browser to re-authorize Instagram with the publishing permissions. Present so a headless client can direct the user to grant access."},"subscription_tier":{"type":"string","example":"pro","description":"Current subscription tier (free, trial, or pro)"},"current_billing_period_start":{"type":"string","format":"date-time","description":"Start of current billing period"},"current_billing_period_end":{"type":"string","format":"date-time","description":"End of current billing period"},"free_trial_used":{"type":"boolean","example":true,"description":"Whether the free trial has been used"},"max_contact_activations":{"type":"integer","format":"int32","example":1000,"description":"Maximum number of contact activations allowed"},"optout_options":{"type":"object","description":"Opt-out configuration (active, keywords, messages)"}},"required":["id","email","name","created_at","updated_at","username","login_method","instagram_linked_at","login_error_data","instagram_restrictions","can_publish","missing_publish_scopes","publishing_reauth_url","subscription_tier","current_billing_period_start","current_billing_period_end","free_trial_used","max_contact_activations","optout_options"],"description":"PublicApi_Entities_OrganizationEntity model"},"PublicApi_Entities_InstagramRestrictionEntity":{"type":"object","properties":{"kind":{"type":"string","enum":["sending_blocked","links_blocked","rate_limited"],"example":"sending_blocked","description":"What Meta restricts: sending_blocked (every DM), links_blocked (DMs containing a link) or rate_limited (every DM, usually for minutes). Inrō pauses the affected automations and messages and resumes them on its own once the restriction lifts"},"first_seen_at":{"type":"string","format":"date-time","description":"When the restriction was first seen"},"error_message":{"type":"string","example":"Based on previous use of this feature, your account has been temporarily blocked from taking this action.","description":"Meta's own wording for the restriction, in the account's language"},"help_url":{"type":"string","example":"https://help.inro.social/en/articles/15632344-my-messages-aren-t-sending-rate-limits-what-to-do","description":"Help article explaining the restriction"}},"required":["kind","first_seen_at","error_message","help_url"]},"PublicApi_Entities_ContactEntity":{"type":"object","properties":{"id":{"type":"integer","format":"int32","example":123,"description":"The ID of the contact"},"name":{"type":"string","example":"John Doe","description":"The contact's Instagram display name, fetched via the instagram_manage_messages / instagram_business_manage_messages scope (granted on every connection) once the contact has an Instagram-scoped ID, i.e. after their first message or comment. Meta may withhold this for some private accounts even then (see docs/INSTAGRAM_CONNECTION_SYSTEM.md)."},"username":{"type":"string","example":"john_doe","description":"The username of the contact"},"instagram_url":{"type":"string","example":"https://www.instagram.com/john_doe/","description":"The Instagram URL of the contact"},"profile_picture":{"type":"string","example":"https://www.instagram.com/john_doe/profile_pic.jpg","description":"The profile picture URL of the contact"},"status":{"type":"string","enum":["pending","active","commented","live_commented","requested","optout","deleted","inactive","spam","auto"],"description":"The actionable status of the contact"},"notes":{"type":"string","example":"Shown interest in the product","description":"The notes of the contact"},"is_follower":{"type":"boolean","example":true,"description":"Whether the contact follows the organization on Instagram. Sourced from the same call and scope as `name` (see above), so it shares the same availability constraints."},"is_followed":{"type":"boolean","example":false,"description":"Whether the contact is followed by the organization"},"email":{"type":"string","example":"john.doe@example.com","description":"The email of the contact"},"real_name":{"type":"string","example":"John Doe","description":"The real name of the contact"},"phone":{"type":"string","example":"+33612345678","description":"The phone number of the contact"},"language":{"type":"string","example":"en","description":"The contact's language, as a 2-letter ISO 639-1 code. Not sourced from Instagram at all — it comes from AI text classification of the contact's messages, and is not wired into any automatic trigger today, so it is nil for effectively every contact (see docs/INSTAGRAM_CONNECTION_SYSTEM.md)."},"follower_count":{"type":"integer","format":"int32","example":1000,"description":"The contact's Instagram follower count. Sourced from the same call and scope as `name` (see above), so it shares the same availability constraints."},"bio":{"type":"string","example":"NYC based journalist, photographer and traveler","description":"The contact's Instagram bio. Requires the contact's Instagram account to be a public Business or Creator account (Meta's business_discovery endpoint doesn't cover personal accounts, which is most contacts) and is fetched asynchronously, once per contact, after their first message or comment — so it can be nil for a while after a contact is created even when it will eventually be filled in. See docs/INSTAGRAM_CONNECTION_SYSTEM.md."},"website":{"type":"string","example":"https://john.doe.com","description":"The website the contact has set on their Instagram profile. Same source and constraints as `bio` above."},"created_at":{"type":"string","format":"date-time","description":"The date and time when the contact was created"},"updated_at":{"type":"string","format":"date-time","description":"The date and time when the contact was last updated"},"last_message_at":{"type":"string","format":"date-time","description":"When the organization last exchanged a message with this contact, and the value the `last_message_at` ordering sorts on. Null for a contact that has never exchanged one — those sort last descending, first ascending."},"custom_properties":{"type":"object","example":{"birthdate":"1990-01-01","city":"Paris"},"description":"The custom properties of the contact as a JSON object"},"folders":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_FolderEntity"},"description":"The folders the contact belongs to"},"full_url":{"type":"string","example":"https://app.inro.social/contacts/123","description":"The full URL to this contact in Inrō"}},"required":["id","name","username","instagram_url","profile_picture","status","notes","is_follower","is_followed","email","real_name","phone","language","follower_count","bio","website","created_at","updated_at","last_message_at","custom_properties","folders","full_url"],"description":"PublicApi_Entities_ContactEntity model"},"PublicApi_Entities_FolderEntity":{"type":"object","properties":{"id":{"type":"integer","format":"int32","example":123,"description":"The ID of the folder"},"name":{"type":"string","example":"Potential leads","description":"The name of the folder"},"color":{"type":"string","example":"yellow","description":"The color of the folder"}},"required":["id","name","color"],"description":"PublicApi_Entities_FolderEntity model"},"PublicApi_Entities_ContactPropertyEntity":{"type":"object","properties":{"id":{"type":"integer","format":"int32","example":1,"description":"The ID of the contact property"},"slug":{"type":"string","example":"birthday","description":"The slug of the contact property, used as a variable name in templates (e.g. {{ contact.birthday }})"},"title":{"type":"string","example":"Birthdate","description":"The title of the contact property"},"property_type":{"type":"string","enum":["text","number","date","email","phone","url","boolean","list","single_choice","multiple_choice"],"description":"The type of the contact property"},"choices":{"type":"array","example":["Free","Pro","Enterprise"],"description":"Predefined options for single_choice and multiple_choice properties"},"auto_detect":{"type":"boolean","example":true,"description":"Whether values are detected automatically from contacts' profiles and conversations"}},"required":["id","slug","title","property_type","choices","auto_detect"],"description":"PublicApi_Entities_ContactPropertyEntity model"},"PublicApi_Entities_MessageEntity":{"type":"object","properties":{"id":{"type":"integer","format":"int32","example":12345,"description":"The unique identifier of the message"},"content":{"type":"string","example":"Hello, John!","description":"The content of the message"},"message_type":{"type":"string","example":"text","description":"The type of the message"},"received_at":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00Z","description":"The date and time when the message was received"},"received":{"type":"boolean","example":false,"description":"Whether the message was received (true) or sent (false)"},"sent_from":{"type":"string","example":"api","description":"The source from which the message was sent"},"automated":{"type":"boolean","example":true,"description":"Whether the message was sent automatically"},"instagram_id":{"type":"string","example":"aWdfZD12345","description":"The Instagram message ID"}},"required":["id","content","message_type","received_at","received","sent_from","automated","instagram_id"],"description":"PublicApi_Entities_MessageEntity model"},"PublicApi_Entities_ScenarioEntity":{"type":"object","properties":{"id":{"type":"integer","format":"int32","example":123,"description":"The ID of the scenario"},"title":{"type":"string","example":"Welcome Automation","description":"The title of the scenario"},"active":{"type":"boolean","example":true,"description":"Whether the scenario is active"},"is_template":{"type":"boolean","example":false,"description":"Whether the scenario is a template"},"suspended":{"type":"boolean","example":false,"description":"Whether the scenario has been suspended for abuse (read-only; cannot be run, edited or copied)"},"scenario_type":{"type":"string","enum":["custom","comment_to_dm","comment_moderation"],"example":"custom","description":"The type of the scenario"},"interrupt_on_message":{"type":"boolean","example":false,"description":"Whether the scenario's pending runs for a contact stop when your team messages that contact by hand (Instagram app or Inrō inbox)"},"interrupt_on_reply":{"type":"boolean","example":false,"description":"Whether the scenario's pending runs for a contact stop when the contact sends a message (unless the run is waiting for that reply)"},"last_executed_at":{"type":"string","format":"date-time","description":"The date and time when the scenario was last executed"},"setup_completed_at":{"type":"string","format":"date-time","description":"The date and time when the setup was completed"},"on_reply_scenario_id":{"type":"integer","format":"int32","description":"ID of a scenario to run for a contact whose reply stopped this scenario. Only used with interrupt_on_reply."},"rate_limit_enabled":{"type":"boolean","example":false,"description":"Stop the scenario from running again for the same contact too soon. Needs rate_limit_unit, and rate_limit_value unless the unit is `once`."},"rate_limit_value":{"type":"integer","format":"int32","description":"How many rate_limit_unit must pass after a contact's last run before the scenario runs for them again"},"rate_limit_unit":{"type":"string","description":"`once` runs the scenario only once per contact; any other unit is the unit of rate_limit_value"},"excluded_folder_ids":{"type":"array","items":{"type":"array"},"description":"The IDs of excluded folders"},"scenario_folder_id":{"type":"integer","format":"int32","description":"The ID of the scenario folder"},"scenario_folder_priority":{"type":"integer","format":"int32","description":"The priority within the scenario folder"},"created_at":{"type":"string","format":"date-time","description":"The date and time when the scenario was created"},"updated_at":{"type":"string","format":"date-time","description":"The date and time when the scenario was last updated"},"metrics":{"type":"Object","description":"Scenario metrics. executions counts only executions that ran; ones held back by the contact limit or a disconnected Instagram account are in paused_executions."},"paused_executions":{"type":"Object","example":{"limited":12,"disconnected":0},"description":"Executions waiting to be re-run: limited (monthly contact limit reached) and disconnected (Instagram account disconnected). Comment executions past Instagram's 7-day private-reply window are not included."},"prompt":{"type":"string","example":"Reply to comments with a DM containing a link","description":"The original natural-language prompt used to generate this scenario, if any"},"generation_data":{"type":"Object","description":"Progress of AI generation for scenarios created from a prompt. Contains per-phase (`triggers`, `actions`) `status` values: `pending`, `generating`, `completed`, `failed`, or `not_generated`, plus an optional `error` message. Empty `{}` for scenarios not created from a prompt. `not_generated` on both phases means the prompt was classified rather than built, and `classification` then holds `outcome`, `pattern`, `reason` and, depending on the outcome, `target`, `alternatives`, `question` and `understood`. The generated content itself is available via the scenario's `triggers` and `actions` fields on the detail endpoints."},"full_url":{"type":"string","example":"https://app.inro.social/automation/scenarios/123","description":"The full URL to this scenario in Inrō"}},"required":["id","title","active","is_template","suspended","scenario_type","interrupt_on_message","interrupt_on_reply","last_executed_at","setup_completed_at","on_reply_scenario_id","rate_limit_enabled","rate_limit_value","rate_limit_unit","excluded_folder_ids","scenario_folder_id","scenario_folder_priority","created_at","updated_at","metrics","paused_executions","prompt","generation_data","full_url"],"description":"PublicApi_Entities_ScenarioEntity model"},"PublicApi_Entities_ScenarioFolderEntity":{"type":"object","properties":{"id":{"type":"integer","format":"int32","example":1,"description":"The ID of the scenario folder"},"name":{"type":"string","example":"Welcome flows","description":"The name of the folder"},"description":{"type":"string","description":"Optional description of the folder"},"folder_type":{"type":"string","enum":["normal","priority"],"example":"priority","description":"Folder type: normal (all matching scenarios run) or priority (only the highest-priority matching scenario runs)"},"scenarios_count":{"type":"integer","format":"int32","example":3,"description":"Number of scenarios in this folder"},"created_at":{"type":"string","format":"date-time","description":"The date and time when the folder was created"},"updated_at":{"type":"string","format":"date-time","description":"The date and time when the folder was last updated"}},"required":["id","name","description","folder_type","scenarios_count","created_at","updated_at"],"description":"PublicApi_Entities_ScenarioFolderEntity model"},"PublicApi_Entities_CampaignEntity":{"type":"object","properties":{"id":{"type":"integer","format":"int32","example":123,"description":"The ID of the campaign"},"title":{"type":"string","example":"Welcome Campaign","description":"The title of the campaign"},"status":{"type":"string","enum":["draft","running","completed","scheduled","limited","canceled"],"example":"draft","description":"The status of the campaign"},"sent_at":{"type":"string","format":"date-time","description":"The date and time when the campaign was sent"},"scheduled_at":{"type":"string","format":"date-time","description":"The date and time when the campaign is scheduled to be sent"},"options":{"type":"Object","description":"Additional options for the campaign"},"campaign_folder_id":{"type":"integer","format":"int32","description":"The ID of the campaign folder this campaign belongs to (null if ungrouped)"},"selected_contact_ids":{"type":"array","items":{"type":"array"},"description":"The IDs of selected contacts"},"created_at":{"type":"string","format":"date-time","description":"The date and time when the campaign was created"},"updated_at":{"type":"string","format":"date-time","description":"The date and time when the campaign was last updated"},"metrics":{"type":"Object","description":"Campaign metrics data"},"full_url":{"type":"string","example":"https://app.inro.social/campaigns/123","description":"The full URL to this campaign in Inrō"}},"required":["id","title","status","sent_at","scheduled_at","options","campaign_folder_id","selected_contact_ids","created_at","updated_at","metrics","full_url"],"description":"PublicApi_Entities_CampaignEntity model"},"PublicApi_Entities_CampaignFolderEntity":{"type":"object","properties":{"id":{"type":"integer","format":"int32","example":1,"description":"The ID of the campaign folder"},"name":{"type":"string","example":"Q2 Campaigns","description":"The name of the folder"},"description":{"type":"string","description":"Optional description of the folder"},"campaigns_count":{"type":"integer","format":"int32","example":5,"description":"Number of campaigns in this folder"},"created_at":{"type":"string","format":"date-time","description":"The date and time when the folder was created"},"updated_at":{"type":"string","format":"date-time","description":"The date and time when the folder was last updated"}},"required":["id","name","description","campaigns_count","created_at","updated_at"],"description":"PublicApi_Entities_CampaignFolderEntity model"},"PublicApi_Entities_ConversionLinkEntity":{"type":"object","properties":{"id":{"type":"integer","format":"int32","example":42,"description":"The ID of the conversion link"},"title":{"type":"string","example":"Check out our new collection","description":"Title shown on the link card"},"subtitle":{"type":"string","example":"Limited time offer","description":"Optional subtitle shown on the link card"},"url":{"type":"string","example":"https://example.com/sale","description":"Destination URL"},"button_title":{"type":"string","example":"Shop Now","description":"Call-to-action button label"},"public_image_url":{"type":"string","description":"Public URL of the link card image (expires after 24 hours), or null if no image"},"created_at":{"type":"string","format":"date-time","description":"The date and time when the conversion link was created"},"updated_at":{"type":"string","format":"date-time","description":"The date and time when the conversion link was last updated"}},"required":["id","title","subtitle","url","button_title","public_image_url","created_at","updated_at"],"description":"PublicApi_Entities_ConversionLinkEntity model"},"PublicApi_Entities_TemplateEntity":{"type":"object","properties":{"id":{"type":"integer","format":"int32","example":123,"description":"The ID of the scenario"},"type":{"type":"string","example":"Scenario","description":"The type of the template"},"title":{"type":"string","example":"Customer Onboarding Flow","description":"The title of the template"},"url":{"type":"string","example":"https://app.inro.social/public/scenarios/123","description":"The URL to access the template"},"description":{"type":"string","example":"A template for onboarding new customers","description":"A short description of the template"},"full_description":{"type":"string","example":"Step 1: Greet the customer. Step 2: Ask for their needs...","description":"The full text description of the template (Markdown supported)"},"tags":{"type":"array","items":{"type":"Array[String]"},"example":["onboarding","customer","welcome"],"description":"Tags associated with the template"}},"required":["id","type","title","url","description","full_description","tags"],"description":"PublicApi_Entities_TemplateEntity model"},"PublicApi_Entities_MediaEntity":{"type":"object","properties":{"id":{"type":"integer","format":"int32","example":123,"description":"The ID of the media"},"instagram_id":{"type":"string","example":"17854360229135492","description":"The Instagram post ID (present when published)"},"caption":{"type":"string","description":"The caption of the media post"},"agent_context":{"type":"string","description":"Notes for the AI agent about this post — background the agent needs to answer questions but that shouldn't appear in the caption itself. Settable on any post, including published ones."},"media_url":{"type":"string","description":"The direct URL to the media file on Instagram's CDN"},"thumbnail_url":{"type":"string","description":"The thumbnail URL for the media"},"permalink":{"type":"string","description":"The permanent Instagram permalink for the post"},"media_type":{"type":"string","enum":["IMAGE","REELS","CAROUSEL_ALBUM"],"example":"IMAGE","description":"The Instagram media type"},"media_product_type":{"type":"string","description":"The Instagram media product type (e.g. FEED, REELS, STORY)"},"like_count":{"type":"integer","format":"int32","example":42,"description":"The number of likes on the post"},"status":{"type":"string","enum":["published","pending","scheduled","draft"],"example":"published","description":"The publication status of the media"},"publish_status":{"type":"string","enum":["PENDING","IN_PROGRESS","FINISHED","ERROR","PUBLISHED","EXPIRED"],"description":"The Instagram container publish status (when publishing is in progress)"},"insights":{"type":"object","example":{"reach":1200,"likes":42,"saved":7,"shares":3},"description":"Instagram insights for the post (reach, views, likes, saved, shares, etc.), keyed by metric name. Present only when `insights_status` is \"fresh\"; null while refreshing or unavailable."},"insights_status":{"type":"string","enum":["fresh","refreshing","unavailable"],"example":"fresh","description":"Freshness of `insights`. \"fresh\": present and within its refresh window. \"refreshing\": a refresh is in flight — retry shortly for numbers. \"unavailable\": no insights to serve — the media is not published, or Instagram won't report on it for this account (retrying won't help)."},"insights_synced_at":{"type":"string","format":"date-time","description":"When `insights` were last refreshed from Instagram (null if never fetched)."},"posted_at":{"type":"string","format":"date-time","description":"The date and time when the media was posted on Instagram"},"scheduled_at":{"type":"string","format":"date-time","description":"The date and time when the media is scheduled to be published"},"media_file_id":{"type":"integer","format":"int32","description":"ID of the uploaded MediaFile used as the source asset for a draft/scheduled post (image, reel video, or story asset)."},"publish_media_type":{"type":"string","enum":["IMAGE","REELS","STORIES","CAROUSEL","GRID"],"description":"The publish type of a draft/scheduled post. GRID drafts are created in the app: one picture sliced into a 3, 6 or 9 post profile grid when published."},"publish_caption":{"type":"string","description":"The caption set on a draft/scheduled post before publishing"},"publish_children":{"type":"array","items":{"type":"array"},"description":"Ordered MediaFile IDs composing a CAROUSEL draft (2–10 items)."},"publish_location_id":{"type":"string","description":"Instagram location (page) ID attached to the draft"},"publish_cover_media_id":{"type":"string","description":"MediaFile ID used as the cover image for a REELS draft"},"publish_grid_rows":{"type":"integer","format":"int32","description":"Rows of a GRID draft (3 posts per row): 1, 2 or 3 for a 3, 6 or 9 post grid."},"publish_thumb_offset":{"type":"integer","format":"int32","description":"Frame offset (ms) used as a REELS thumbnail"},"publish_share_to_feed":{"type":"boolean","description":"Whether a REELS draft is also shared to the main feed"},"publish_is_ai_generated":{"type":"boolean","description":"Whether the post carries Meta's AI-generated content disclosure. Applied when the post is published and cannot be added afterwards — only removed, from Instagram."},"publish_is_paid_partnership":{"type":"boolean","description":"Whether the post carries Instagram's \"Paid partnership\" label. Applied when the post is published and cannot be added afterwards."},"publish_branded_content_sponsors":{"type":"array","items":{"type":"array"},"example":[{"id":"17841400000000000","username":"brand"}],"description":"Brand partners tagged on the paid partnership (max 2). Each entry has the sponsor's Instagram user `id`, and its `username` when it was resolved from one."},"publish_trial_graduation_strategy":{"type":"string","enum":["MANUAL","SS_PERFORMANCE"],"description":"Set when the REELS draft is published as a trial reel (shown only to non-followers until it graduates). Null for a normal reel."},"publish_alt_text":{"type":"string","description":"Accessibility alt text for the draft"},"publish_audio_name":{"type":"string","description":"Custom audio name for a REELS draft"},"publish_user_tags":{"type":"array","items":{"type":"array"},"description":"People tagged on the draft. Each entry has a username, plus x/y coordinates (0–1) for feed images."},"publish_collaborators":{"type":"array","items":{"type":"array"},"description":"Usernames invited as collaborators on a feed draft (max 3)."},"login_error_data":{"type":"object","description":"Instagram error details when a publish attempt failed (present when `publish_status` is \"ERROR\")."},"comment_to_dm":{"type":"object","example":{"scenario_id":42,"active":true,"question_type":"button_template","comment_options":{"comment_type":"comment_keywords","comment_keywords":["link"]},"conversion_link":{"id":7,"title":"New collection","url":"https://example.com/shop","button_title":"Shop now"}},"description":"The comment-to-DM automation attached to this post, or null if it has none. Mirrors the `comment_to_dm` field accepted when creating or updating a media, so it can be read back and sent again."},"created_at":{"type":"string","format":"date-time","description":"The date and time when the media record was created in Inrō"},"updated_at":{"type":"string","format":"date-time","description":"The date and time when the media record was last updated"}},"required":["id","instagram_id","caption","agent_context","media_url","thumbnail_url","permalink","media_type","media_product_type","like_count","status","publish_status","insights","insights_status","insights_synced_at","posted_at","scheduled_at","media_file_id","publish_media_type","publish_caption","publish_children","publish_location_id","publish_cover_media_id","publish_grid_rows","publish_thumb_offset","publish_share_to_feed","publish_is_ai_generated","publish_is_paid_partnership","publish_branded_content_sponsors","publish_trial_graduation_strategy","publish_alt_text","publish_audio_name","publish_user_tags","publish_collaborators","login_error_data","comment_to_dm","created_at","updated_at"],"description":"PublicApi_Entities_MediaEntity model"},"PublicApi_Entities_StoryEntity":{"type":"object","properties":{"id":{"type":"integer","format":"int32","example":123,"description":"The ID of the story"},"instagram_id":{"type":"string","description":"The Instagram story ID (present when published)"},"caption":{"type":"string","description":"The caption of the story"},"agent_context":{"type":"string","description":"Notes for the AI agent about this story — background the agent needs to answer questions but that shouldn't appear in the caption itself. Settable on any story, including published ones."},"media_url":{"type":"string","description":"The direct URL to the story media on Instagram's CDN"},"thumbnail_url":{"type":"string","description":"The thumbnail URL for the story"},"permalink":{"type":"string","description":"The permanent Instagram permalink for the story"},"media_type":{"type":"string","enum":["IMAGE","VIDEO"],"example":"IMAGE","description":"The Instagram media type"},"like_count":{"type":"integer","format":"int32","description":"The number of likes on the story"},"insights":{"type":"object","description":"Instagram story insights (reach, replies, etc.), keyed by metric name. Updated via Instagram webhooks."},"status":{"type":"string","enum":["published","pending","scheduled","draft"],"example":"published","description":"The publication status of the story"},"publish_status":{"type":"string","enum":["PENDING","IN_PROGRESS","FINISHED","ERROR","PUBLISHED","EXPIRED"],"description":"The Instagram container publish status (when publishing is in progress)"},"media_file_id":{"type":"integer","format":"int32","description":"ID of the uploaded MediaFile used as the source asset for a draft/scheduled story (image or video)."},"publish_media_type":{"type":"string","enum":["STORIES"],"description":"The publish type of a draft/scheduled story (always STORIES)"},"publish_is_ai_generated":{"type":"boolean","description":"Whether the story carries Meta's AI-generated content disclosure. Applied when the story is published and cannot be added afterwards — only removed, from Instagram."},"publish_user_tags":{"type":"array","items":{"type":"array"},"description":"People tagged on the story draft (username plus x/y)."},"posted_at":{"type":"string","format":"date-time","description":"The date and time when the story was posted on Instagram"},"scheduled_at":{"type":"string","format":"date-time","description":"The date and time when the story is scheduled to be published"},"created_at":{"type":"string","format":"date-time","description":"When the story record was created in Inrō"},"updated_at":{"type":"string","format":"date-time","description":"When the story record was last updated"}},"required":["id","instagram_id","caption","agent_context","media_url","thumbnail_url","permalink","media_type","like_count","insights","status","publish_status","media_file_id","publish_media_type","publish_is_ai_generated","publish_user_tags","posted_at","scheduled_at","created_at","updated_at"],"description":"PublicApi_Entities_StoryEntity model"},"PublicApi_Entities_AgentEntity":{"type":"object","properties":{"id":{"type":"integer","format":"int32","example":1,"description":"The ID of the agent"},"trigger_mode":{"type":"string","enum":["all_messages","specific_messages","never_reply","automation_only"],"example":"specific_messages","description":"When the agent replies to messages"},"trigger_intents":{"type":"Object","example":{"intents":["buy","price"]},"description":"Intent configuration. Contains `intents` array of phrases that trigger the agent in specific_messages mode."},"folder_rules":{"type":"Object","example":{"folder_rule_type":"include","folder_ids":[1,2]},"description":"Folder targeting rules. Contains `folder_rule_type` (include/exclude/null) and `folder_ids` array."},"setup_completed":{"type":"boolean","example":true,"description":"Whether the agent setup is done. When false, the app shows its setup wizard instead of the agent page."},"reasoning":{"type":"string","enum":["low","medium","high"],"example":"medium","description":"The reasoning level chosen for the agent. Only applies while the organization uses its own OpenAI API key; null means the plan default."},"model":{"type":"string","enum":["gpt-6-luna","gpt-6.1-terra","gpt-6.1-sol"],"example":"gpt-6.1-sol","description":"The AI model chosen for the agent. Only applies while the organization uses its own OpenAI API key; null means the plan default."},"context_migrated":{"type":"boolean","example":true,"description":"Whether the agent uses about, goal and rules. Agents set up before rules existed keep their legacy fields until they are migrated."},"about":{"type":"string","description":"Who the account is, what it offers and who it talks to. Included in every reply."},"goal":{"type":"string","description":"What the agent works toward in a conversation it handles on its own. A custom task from an automation replaces it; comment replies don't use it."},"rules":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_AgentRuleEntity"},"description":"Rules the agent follows in every reply, including automations and comment replies"},"account_type":{"type":"string","description":"Type of account/business (e.g. ecommerce, service)"},"description":{"type":"string","description":"Description of the business or account"},"goals":{"type":"array","items":{"type":"array"},"description":"Business goals for the agent"},"audience_type":{"type":"string","description":"Target audience type"},"chat_instructions":{"type":"string","description":"Custom instructions for the agent's chat behavior"},"common_intents":{"type":"array","items":{"type":"array"},"description":"Common contact intents the agent should recognize"},"role":{"type":"string","enum":["community_manager","sales_closer","support_agent","content_promoter","lead_nurturer","brand_concierge"],"description":"The agent's role persona"},"message_length":{"type":"integer","format":"int32","enum":[10,25,50],"description":"Target message length in words"},"auto_like":{"type":"boolean","description":"Whether to automatically like messages"},"style_rules":{"type":"string","description":"Custom style rules for message composition"},"message_examples":{"type":"array","items":{"type":"array"},"description":"Example messages to guide the agent's writing style"},"no_reply_active":{"type":"boolean","description":"\"Limit to instructions\": whether the agent only answers with information from its instructions and knowledge, saying it doesn't know otherwise"},"no_reply_scenario_id":{"type":"string","description":"ID of the scenario run when the agent finds no answer in its instructions and knowledge (only when no_reply_active is true)"},"request_human_scenario_id":{"type":"string","description":"ID of the scenario to run when a human handover is requested"},"human_takeover_active":{"type":"boolean","description":"Whether the agent stands down when a team member replies manually"},"human_takeover_pause":{"type":"integer","format":"int32","description":"Hours the agent stays out of a conversation after a team member replies manually"},"built_in_property_access":{"type":"array","example":["email"],"description":"Built-in contact fields (email, phone) the agent may read when replying"},"actions":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_AgentActionEntity"},"description":"List of configured agent actions"},"items":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_AgentItemEntity"},"description":"List of knowledge base items"},"contact_properties":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_AgentContactPropertyEntity"},"description":"List of contact properties the agent tracks"}},"required":["id","trigger_mode","trigger_intents","folder_rules","setup_completed","reasoning","model","context_migrated","about","goal","rules","account_type","description","goals","audience_type","chat_instructions","common_intents","role","message_length","auto_like","style_rules","message_examples","no_reply_active","no_reply_scenario_id","request_human_scenario_id","human_takeover_active","human_takeover_pause","built_in_property_access","actions","items","contact_properties"],"description":"PublicApi_Entities_AgentEntity model"},"PublicApi_Entities_AgentRuleEntity":{"type":"object","properties":{"id":{"type":"integer","format":"int32","example":1,"description":"The ID of the rule"},"kind":{"type":"string","enum":["voice","instruction"],"example":"instruction","description":"voice: how the agent writes. instruction: what it must or must not say or do."},"text":{"type":"string","example":"Never promise a delivery date","description":"The rule, one sentence"}},"required":["id","kind","text"]},"PublicApi_Entities_AgentActionEntity":{"type":"object","properties":{"id":{"type":"integer","format":"int32","example":1,"description":"The ID of the agent action"},"trigger":{"type":"string","example":"wants to buy","description":"The intent or phrase that triggers this action"},"target_type":{"type":"string","enum":["ConversionLink","Folder","Scenario","Survey"],"example":"Scenario","description":"The type of target for this action"},"target_id":{"type":"integer","format":"int32","example":42,"description":"The ID of the target resource"},"created_at":{"type":"string","format":"date-time","description":"When the action was created"},"updated_at":{"type":"string","format":"date-time","description":"When the action was last updated"}},"required":["id","trigger","target_type","target_id","created_at","updated_at"],"description":"PublicApi_Entities_AgentActionEntity model"},"PublicApi_Entities_AgentItemEntity":{"type":"object","properties":{"id":{"type":"integer","format":"int32","example":1,"description":"The ID of the knowledge item"},"item_type":{"type":"string","enum":["text","url","file"],"example":"text","description":"The type of knowledge item"},"text":{"type":"string","example":"Our pricing starts at $29/month.","description":"The text content (for text-type items)"},"source_url":{"type":"string","example":"https://example.com/faq","description":"The source URL (for url-type items)"},"retrieval":{"type":"boolean","example":true,"description":"Whether this item is used for retrieval (semantic search)"},"status":{"type":"string","enum":["processing","ready","failed"],"example":"ready","description":"The processing status of the item"},"created_at":{"type":"string","format":"date-time","description":"When the item was created"}},"required":["id","item_type","text","source_url","retrieval","status","created_at"],"description":"PublicApi_Entities_AgentItemEntity model"},"PublicApi_Entities_AgentContactPropertyEntity":{"type":"object","properties":{"id":{"type":"integer","format":"int32","example":1,"description":"The ID of the agent contact property mapping"},"field_name":{"type":"string","example":"email","description":"Built-in field name for built-in fields (e.g. email, phone). Null for custom properties."},"contact_property_id":{"type":"integer","format":"int32","example":5,"description":"The ID of the custom contact property. Null for built-in fields."},"created_at":{"type":"string","format":"date-time","description":"When this mapping was created"},"updated_at":{"type":"string","format":"date-time","description":"When this mapping was last updated"}},"required":["id","field_name","contact_property_id","created_at","updated_at"],"description":"PublicApi_Entities_AgentContactPropertyEntity model"},"PublicApi_Entities_BatchTaskEntity":{"type":"object","properties":{"id":{"type":"integer","format":"int32","example":123,"description":"The ID of the batch task"},"task_type":{"type":"string","enum":["campaign_send","contact_bulk_update","retroactive_automation","contact_property_detection","contact_folder_update"],"example":"campaign_send","description":"The type of batch task"},"status":{"type":"string","enum":["pending","processing","completed","failed","canceled","paused"],"example":"processing","description":"The status of the batch task"},"progress":{"type":"integer","format":"int32","example":250,"description":"Number of items processed so far"},"total_count":{"type":"integer","format":"int32","example":1000,"description":"Total number of items to process"},"progress_percentage":{"type":"number","format":"float","example":25.0,"description":"Progress as a percentage (0-100)"},"estimated_completion_time":{"type":"string","format":"date-time","description":"Estimated completion time based on current progress"},"error_message":{"type":"string","description":"Error message if the task failed"},"taskable_type":{"type":"string","example":"Campaign","description":"The type of the resource this task is associated with"},"taskable_id":{"type":"integer","format":"int32","example":456,"description":"The ID of the resource this task is associated with"},"created_at":{"type":"string","format":"date-time","description":"When the batch task was created"},"updated_at":{"type":"string","format":"date-time","description":"When the batch task was last updated"}},"required":["id","task_type","status","progress","total_count","progress_percentage","estimated_completion_time","error_message","taskable_type","taskable_id","created_at","updated_at"],"description":"PublicApi_Entities_BatchTaskEntity model"},"PublicApi_Entities_MediaFileEntity":{"type":"object","properties":{"id":{"type":"integer","format":"int32","example":123,"description":"The ID of the media file"},"media_type":{"type":"string","enum":["image","audio","video","application","text"],"example":"image","description":"The media type"},"purpose":{"type":"string","enum":["messaging","publishing"],"example":"messaging","description":"What the file is for, which decides how hard it was compressed. `messaging` files are shrunk for DM attachments; `publishing` files keep their source resolution for medias, reels and stories."},"upload_status":{"type":"string","enum":["ready","pending","failed"],"example":"ready","description":"Upload lifecycle state. `ready` files are usable immediately; `pending` files are awaiting a PUT to `upload_url`; `failed` means the upload was rejected."},"upload_url":{"type":"string","description":"Single-use URL to PUT the raw file bytes to. Present only while the file is `pending` and its token is still valid; becomes invalid after the first successful upload or at `expires_at`, whichever comes first."},"upload_page_url":{"type":"string","description":"Human-facing upload page for the same pending file. Hand this to the person who has the file when the client cannot perform the PUT itself; it accepts a drag-and-drop or camera-roll upload from any device."},"expires_at":{"type":"string","format":"date-time","description":"When `upload_url` and `upload_page_url` stop working. Once this is in the past both are omitted; call refresh_upload to mint new ones (the file itself survives for about a day longer, along with any parts already uploaded)."},"caption":{"type":"string","description":"AI-generated description of the file (images only)"},"name":{"type":"string","description":"The filename of the attached file"},"file_url":{"type":"string","description":"Direct URL to the attached file"},"media_dimensions":{"type":"Object","description":"Width and height of the media file (images/videos)"},"created_at":{"type":"string","format":"date-time","description":"The date and time when the media file was created"},"updated_at":{"type":"string","format":"date-time","description":"The date and time when the media file was last updated"}},"required":["id","media_type","purpose","upload_status","caption","name","file_url","media_dimensions","created_at","updated_at"],"description":"PublicApi_Entities_MediaFileEntity model"},"PublicApi_Entities_OptoutSettingsEntity":{"type":"object","properties":{"active":{"type":"boolean","example":true,"description":"Whether opt-out handling is on. When on, the menu message is added to the Instagram persistent menu"},"menu_message":{"type":"string","example":"Opt out of messages","description":"Label of the opt-out entry in the Instagram persistent menu. Blank removes the entry (Instagram truncates it to 30 characters)"},"confirmation_message":{"type":"string","example":"You have been successfully unsubscribed.","description":"Message sent to a contact once they have been opted out. Blank sends nothing"},"keywords":{"type":"array","items":{"type":"string"},"example":["stop","unsubscribe"],"description":"Incoming message keywords that opt a contact out. Any message containing one of them as a whole word opts out, ignoring case, accents and surrounding spaces; keywords of 4+ characters also match a plural or one extra letter"},"ai_detection":{"type":"boolean","example":true,"description":"Whether the AI Agent may recognize an opt-out request in its own words, in conversations it replies to, in addition to the keywords and persistent menu. Defaults to true"}},"required":["active","menu_message","confirmation_message","keywords","ai_detection"],"description":"PublicApi_Entities_OptoutSettingsEntity model"},"PublicApi_Entities_IcebreakerEntity":{"type":"object","properties":{"question":{"type":"string","example":"What are your opening hours?","description":"The icebreaker question shown on the Instagram profile"},"payload":{"type":"string","example":"INRO_ICEBREAKERS_A1B2C3","description":"Identifier of the icebreaker on Instagram. Used to update or delete it, and to match it from an `icebreaker` scenario trigger"},"automations":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_IcebreakerAutomationEntity"},"description":"Scenarios whose triggers fire when this icebreaker is tapped. Empty means tapping it starts nothing"}},"required":["question","payload","automations"],"description":"PublicApi_Entities_IcebreakerEntity model"},"PublicApi_Entities_IcebreakerAutomationEntity":{"type":"object","properties":{"scenario_id":{"type":"integer","format":"int32","example":7,"description":"ID of the scenario that runs when the icebreaker is tapped"},"scenario_title":{"type":"string","example":"Send the guide","description":"Title of that scenario"},"active":{"type":"boolean","example":true,"description":"Whether that scenario is running. An inactive scenario matches but never fires"},"trigger_id":{"type":"integer","format":"int32","example":42,"description":"ID of the matching trigger"},"matched_on":{"type":"string","enum":["payload","title"],"example":"payload","description":"How the trigger matches: `payload` (stable across rewrites) or `title` (breaks when the question is reworded)"}},"required":["scenario_id","scenario_title","active","trigger_id","matched_on"]},"PublicApi_Entities_PersistentMenuItemEntity":{"type":"object","properties":{"id":{"type":"string","example":"INRO_MENU_A1B2C3","description":"Identifier used to update or delete the entry: the `payload` for a postback, the `title` for a link (Instagram stores no id of its own)"},"type":{"type":"string","enum":["postback","web_url"],"example":"postback","description":"`postback` sends the payload to Inrō as a message; `web_url` opens the URL"},"title":{"type":"string","example":"Talk to an agent","description":"Label shown in the menu"},"payload":{"type":"string","example":"INRO_MENU_A1B2C3","description":"Postback entries only: the payload Instagram sends when the entry is tapped"},"url":{"type":"string","example":"https://example.com/shop","description":"Link entries only: the URL the entry opens"},"source":{"type":"string","example":"optout","description":"`optout` when the entry is the one the opt-out setting maintains. Null for entries added by hand"}},"required":["id","type","title","payload","url","source"],"description":"PublicApi_Entities_PersistentMenuItemEntity model"},"PublicApi_Entities_PartnerEntity":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string","example":"Acme Partner","description":"The partner's name"},"email":{"type":"string","example":"hello@acme.agency","description":"Contact and billing email for the partner account"},"organizations_count":{"type":"integer","format":"int32","example":12,"description":"How many organizations this partner owns"},"subscribed":{"type":"boolean","example":true,"description":"Whether the partner plan is live. Every organization a partner manages is served by that one plan, so creating one is refused when false and the organizations already created stop being entitled to Pro."},"has_payment_method":{"type":"boolean","example":true,"description":"Whether Stripe holds a usable payment method on the partner's customer. Creating an organization is refused when false, since new organizations are billed to the partner."},"created_at":{"type":"string","format":"date-time","description":"When the partner account was created"}},"required":["id","name","email","organizations_count","subscribed","has_payment_method","created_at"],"description":"PublicApi_Entities_PartnerEntity model"},"PublicApi_Entities_PartnerOrganizationEntity":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string","example":"ACME","description":"The organization's name"},"username":{"type":"string","example":"acme","description":"The connected Instagram username. Null until Instagram is connected."},"instagram_connected":{"type":"boolean","example":false,"description":"Whether Instagram is connected and automations can run. A newly created organization is false until someone completes the connect flow."},"instagram_connect_url":{"type":"string","example":"https://app.inro.social/public/connect/12345","description":"Absolute URL to send the account owner to so they can connect Instagram. Connecting is an interactive authorization, so this link has to be opened by a person — the API cannot complete it."},"subscription_tier":{"type":"string","example":"pro","description":"Current subscription tier (free, trial, or pro)"},"can_be_deleted":{"type":"boolean","example":true,"description":"Whether this organization can be deleted through the API. Only organizations that never connected Instagram can — a connected one is a live account."},"created_at":{"type":"string","format":"date-time","description":"When the organization was created"}},"required":["id","name","username","instagram_connected","instagram_connect_url","subscription_tier","can_be_deleted","created_at"],"description":"PublicApi_Entities_PartnerOrganizationEntity model"},"PublicApi_Entities_PartnerLinkEntity":{"type":"object","properties":{"id":{"type":"string"},"link_type":{"type":"string","example":"managed","description":"`referral` links bring signups in, each billed on its own. `managed` links create an organization billed to the partner and send the visitor straight to Instagram connect."},"code":{"type":"string","example":"a1b2c3d4e5f6","description":"The link's code. For a managed link this is what `partner_link_code` accepts when creating an organization."},"url":{"type":"string","example":"https://app.inro.social/p/a1b2c3d4e5f6/onboard","description":"The shareable URL for this link"},"default_template_id":{"type":"integer","format":"int32","description":"Scenario duplicated into organizations created through this link, if any"},"trial_days":{"type":"integer","format":"int32","description":"Free trial days applied"},"created_at":{"type":"string","format":"date-time"}},"required":["id","link_type","code","url","default_template_id","trial_days","created_at"],"description":"PublicApi_Entities_PartnerLinkEntity model"},"PublicApi_Entities_ExecutionEntity":{"type":"object","properties":{"id":{"type":"integer","format":"int32","example":558123,"description":"The ID of the run"},"type":{"type":"string","enum":["scenario","campaign"],"example":"scenario","description":"Which kind of automation ran"},"scenario_id":{"type":"integer","format":"int32","example":42,"description":"The scenario that ran"},"campaign_id":{"type":"integer","format":"int32","example":17,"description":"The campaign that ran"},"title":{"type":"string","example":"Comment to DM — launch","description":"The title of the automation that ran"},"contact_id":{"type":"integer","format":"int32","example":77120,"description":"The contact the run was for"},"conversation_id":{"type":"integer","format":"int32","example":90211,"description":"The conversation the run acted in"},"status":{"type":"string","enum":["pending","completed","failed","partially_completed","interrupted","limited","disconnected","restricted"],"example":"failed","description":"The run's status. `limited`, `disconnected` and `restricted` are paused rather than finished — they re-run once the underlying problem is fixed. `partially_completed` means a step failed after earlier steps had already run."},"reason_code":{"type":"string","example":"contact_replied","description":"Stable code for why the run ended this way, for branching on in code. Null on a run that completed and on runs that predate the code being recorded; `status_message` carries the same thing as localized prose."},"status_message":{"type":"string","example":"Contact replied","description":"Human-readable reason, localized to the organization"},"notes":{"type":"array","items":{"type":"array"},"example":[{"code":"excluded_folder_bypassed","message":"Excluded folder ignored (VIP): test run","at":"2026-10-26T10:00:00Z"}],"description":"Remarks on the run that never end it: rules that matched but were bypassed because it is a test or manual run. `code` is stable, `message` is localized prose, `at` is when it was recorded."},"execution_type":{"type":"string","enum":["automated","manual","agent"],"example":"automated","description":"How the run was started"},"is_test":{"type":"boolean","example":false,"description":"Whether this was a test run"},"trigger":{"type":"object","description":"What started the run — the comment, story reply or mention the trigger matched"},"created_at":{"type":"string","format":"date-time","description":"When the run started"},"completed_at":{"type":"string","format":"date-time","description":"When the run reached a final status"},"steps":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_ExecutionStepEntity"},"description":"The steps the run executed, in the order they ran"}},"required":["id","type","title","contact_id","conversation_id","status","reason_code","status_message","is_test","created_at","completed_at"],"description":"PublicApi_Entities_ExecutionEntity model"},"PublicApi_Entities_ExecutionStepEntity":{"type":"object","properties":{"id":{"type":"integer","format":"int32","example":8802,"description":"The ID of the step"},"action_id":{"type":"integer","format":"int32","example":902,"description":"The ID of the action this step ran"},"action_type":{"type":"string","example":"message","description":"The type of action this step ran"},"status":{"type":"string","enum":["started","scheduled","waiting","running","completed","interrupted","failed","cancelled","skipped"],"example":"failed","description":"The step's status. `started`, `scheduled`, `waiting` and `running` are in-flight; the rest are final."},"reason_code":{"type":"string","example":"action_error","description":"Stable code for why the step ended this way, for branching on in code. Null while a step is in flight, on a step that completed, and on steps that ran before codes were recorded."},"error_message":{"type":"string","example":"Unsupported get request","description":"Human-readable failure message. Localized when it comes from Inrō, verbatim when it comes from Instagram."},"retry_count":{"type":"integer","format":"int32","example":3,"description":"How many times the step was retried automatically"},"ran_at":{"type":"string","format":"date-time","description":"When the step last ran"},"scheduled_for":{"type":"string","format":"date-time","description":"When a `scheduled` step is due to run. A step waiting on a future timer is waiting legitimately, not stuck."},"expire_at":{"type":"string","format":"date-time","description":"When a `waiting` step stops waiting"},"created_at":{"type":"string","format":"date-time","description":"When the step was created"},"failed_attempts":{"type":"array","description":"The attempts that failed before a retry succeeded. A step that eventually succeeded clears its error_message, so this is the only remaining record of a flaky action."},"action_data":{"type":"object","description":"The action's configuration as it was when the step ran. Read this rather than the action itself when the automation has been edited since the failure."}},"required":["id","action_id","action_type","status","reason_code","error_message","retry_count","ran_at","scheduled_for","expire_at","created_at"],"description":"PublicApi_Entities_ExecutionStepEntity model"},"PublicApi_Entities_AutomationHealthEntity":{"type":"object","properties":{"window":{"type":"object","description":"The `since`/`until` range these numbers cover"},"computed_at":{"type":"string","format":"date-time","description":"When these numbers were computed. Results are cached for a minute, so a value just after a retry may predate it."},"executions":{"type":"object","description":"Run counts by status, plus `total`. Every status is present, so a zero is distinguishable from a missing field."},"failure_rate":{"type":"number","format":"float","example":0.243,"description":"Share of runs that failed or partially completed, 0 to 1"},"account":{"type":"object","description":"Account-level blockers that stop runs before any step executes: `instagram_connected`, `contact_activation_limit_reached`, and the activation usage behind it. These explain the `disconnected`, `restricted` and `limited` run counts above."},"top_failing":{"type":"array","items":{"type":"array"},"description":"The automations to look at first, ranked by failure rate rather than volume. Each entry carries `type`, `id`, `title`, `executions`, `failed`, `failure_rate` and `top_reason_code`."},"top_reason_codes":{"type":"array","items":{"type":"array"},"description":"The most common reason codes in the window, as `reason_code`/`count` pairs"}},"required":["window","computed_at","executions","failure_rate","account","top_failing","top_reason_codes"],"description":"PublicApi_Entities_AutomationHealthEntity model"},"PublicApi_Entities_RunnablePerformanceEntity":{"type":"object","properties":{"id":{"type":"integer","format":"int32","example":42,"description":"The ID of the automation"},"type":{"type":"string","enum":["scenario","campaign"],"example":"scenario","description":"Which kind of automation this is"},"title":{"type":"string","example":"Comment to DM — launch","description":"The title of the automation"},"window":{"type":"object","description":"The `since`/`until` range these numbers cover"},"computed_at":{"type":"string","format":"date-time","description":"When these numbers were computed. Cached for a minute, so a value just after a retry may predate it."},"executions":{"type":"object","description":"Run counts by status for the window, plus `total` and `failure_rate`"},"steps":{"type":"array","items":{"type":"array"},"description":"One entry per step, in flow order. `reached` is how many runs got to the step; `completed`, `failed`, `pending`, `interrupted`, `cancelled` and `skipped` are how they ended there. `metrics` carries the engagement counters (sent, read, clicked, replied, converted) and `top_reason_codes` the reasons behind the failures."}},"required":["id","type","title","window","computed_at","executions","steps"],"description":"PublicApi_Entities_RunnablePerformanceEntity model"},"postApiV1ContactsFilter":{"type":"object","properties":{"filters":{"type":"array","description":"Filter objects to apply. Each has a `filter_type` plus the fields that type accepts (see GET /contacts/filter_types).","items":{"type":"object","properties":{"filter_type":{"type":"string","description":"The filter type","enum":["any_engagement","first_interaction","message","comment","story_reply","story_mention","referral_ad","media_mention","folder","clicked_conversion_link","campaign","scenario","survey","appointment","payment","username","name","email","phone","is_follower","is_followed","status","language","follower_count","contact_created_at","contact_property"]},"operator":{"type":"string","description":"Comparison operator, when the filter type uses one","enum":["is_true","is_false","is_present","is_not_present","contains","does_not_contain","is_equal","is_above","is_below","is_not_equal","is_between"]},"value":{"type":"string","description":"Filter value (meaning depends on filter_type)"},"date_operator":{"type":"string","description":"How the activity date is compared to the day below. A contact matches when at least one of its activities satisfies the condition; is_not_equal and is_not_present match contacts with none. is_equal / is_not_equal use that whole day; is_before and is_after exclude it; is_on_or_before and is_on_or_after include it; is_between includes both days; is_present / is_not_present need no day.","enum":["is_equal","is_not_equal","is_before","is_after","is_on_or_before","is_on_or_after","is_between","is_present","is_not_present"]},"date_mode":{"type":"string","description":"How the day is picked: exact_date (uses date_value), today, yesterday, or days_ago (uses date_days). Defaults to exact_date.","enum":["exact_date","today","yesterday","days_ago"]},"date_days":{"type":"integer","format":"int32","description":"Integer, with date_mode days_ago: 7 means 7 days before today"},"date_value":{"type":"string","format":"date","description":"Date (YYYY-MM-DD), with date_mode exact_date"},"date_value_end":{"type":"string","format":"date","description":"Date (YYYY-MM-DD), the last day when date_operator is is_between"},"date_range":{"type":"string","description":"Deprecated: use date_operator","enum":["today","yesterday","last_7_days","last_30_days","last_90_days","last_365_days","all_time","custom"]},"custom_date_range_start":{"type":"string","format":"date","description":"Deprecated: use date_value"},"custom_date_range_end":{"type":"string","format":"date","description":"Deprecated: use date_value_end"},"media_id":{"type":"string","description":"Instagram media id (comment filter)"},"story_id":{"type":"string","description":"Story id (story_reply / story_mention filters)"},"referral_ad_id":{"type":"string","description":"Referral ad id (referral_ad filter)"},"scenario_id":{"type":"integer","format":"int32","description":"Scenario id (scenario filter)"},"filtered_campaign_id":{"type":"integer","format":"int32","description":"Campaign id (campaign filter)"},"conversion_link_id":{"type":"integer","format":"int32","description":"Conversion link id (clicked_conversion_link filter)"},"options":{"type":"object","description":"Extra options: contact_property, value_end (upper bound for is_between), payment_status, survey_completion_status"}},"required":["filter_type"]}},"filter_logic":{"type":"string","description":"Whether contacts must match all filters (and) or any (or)","enum":["and","or"],"default":"and"},"page":{"type":"integer","format":"int32","description":"Page number","default":1},"per_page":{"type":"integer","format":"int32","description":"Number of items per page (max 1000)","minimum":1,"maximum":1000,"default":20},"order_direction":{"type":"string","description":"Order direction (asc or desc)","enum":["asc","desc"],"default":"asc"},"order_column":{"type":"string","description":"Order column. Custom ordering available for: username (case-insensitive), name (case-insensitive), email (case-insensitive), phone, status, updated_at, created_at, last_message_at.","default":"username"}},"required":["filters"],"description":"Filter contacts"},"putApiV1ContactsBulk":{"type":"object","properties":{"contacts":{"type":"array","description":"Array of contact update objects (max 1,000)","items":{"type":"object","properties":{"id":{"type":"integer","format":"int32","description":"Contact ID"},"username":{"type":"string","description":"Contact username"},"email":{"type":"string","description":"Contact email"},"contact":{"type":"object","description":"Attributes to update for this contact","properties":{"status":{"type":"string","enum":["auto","optout","spam"]},"email":{"type":"string"},"phone":{"type":"string"},"language":{"type":"string"},"folder_ids":{"type":"array","items":{"type":"integer","format":"int32"}},"custom_properties":{"type":"object"}}}},"required":["contact"]}}},"required":["contacts"],"description":"Bulk update contacts"},"putApiV1ContactsId":{"type":"object","properties":{"contact":{"type":"object","description":"The contact attributes to update","properties":{"status":{"type":"string","description":"auto updates the status based on contact history","enum":["auto","optout","spam"]},"email":{"type":"string","description":"Contact email","example":"john.doe@example.com"},"phone":{"type":"string","description":"Contact phone","example":"+33612345678"},"language":{"type":"string","description":"Contact language","example":"en"},"folder_ids":{"type":"array","description":"Contact's folder IDs","example":[1,2,3],"items":{"type":"integer","format":"int32"}},"custom_properties":{"type":"object","description":"Custom properties to update","example":{"property_1":"value"}}}}},"required":["contact"],"description":"Update a contact"},"PublicApi_Entities_ExtendedContactEntity":{"type":"object","properties":{"id":{"type":"integer","format":"int32","example":123,"description":"The ID of the contact"},"name":{"type":"string","example":"John Doe","description":"The contact's Instagram display name, fetched via the instagram_manage_messages / instagram_business_manage_messages scope (granted on every connection) once the contact has an Instagram-scoped ID, i.e. after their first message or comment. Meta may withhold this for some private accounts even then (see docs/INSTAGRAM_CONNECTION_SYSTEM.md)."},"username":{"type":"string","example":"john_doe","description":"The username of the contact"},"instagram_url":{"type":"string","example":"https://www.instagram.com/john_doe/","description":"The Instagram URL of the contact"},"profile_picture":{"type":"string","example":"https://www.instagram.com/john_doe/profile_pic.jpg","description":"The profile picture URL of the contact"},"status":{"type":"string","enum":["pending","active","commented","live_commented","requested","optout","deleted","inactive","spam","auto"],"description":"The actionable status of the contact"},"notes":{"type":"string","example":"Shown interest in the product","description":"The notes of the contact"},"is_follower":{"type":"boolean","example":true,"description":"Whether the contact follows the organization on Instagram. Sourced from the same call and scope as `name` (see above), so it shares the same availability constraints."},"is_followed":{"type":"boolean","example":false,"description":"Whether the contact is followed by the organization"},"email":{"type":"string","example":"john.doe@example.com","description":"The email of the contact"},"real_name":{"type":"string","example":"John Doe","description":"The real name of the contact"},"phone":{"type":"string","example":"+33612345678","description":"The phone number of the contact"},"language":{"type":"string","example":"en","description":"The contact's language, as a 2-letter ISO 639-1 code. Not sourced from Instagram at all — it comes from AI text classification of the contact's messages, and is not wired into any automatic trigger today, so it is nil for effectively every contact (see docs/INSTAGRAM_CONNECTION_SYSTEM.md)."},"follower_count":{"type":"integer","format":"int32","example":1000,"description":"The contact's Instagram follower count. Sourced from the same call and scope as `name` (see above), so it shares the same availability constraints."},"bio":{"type":"string","example":"NYC based journalist, photographer and traveler","description":"The contact's Instagram bio. Requires the contact's Instagram account to be a public Business or Creator account (Meta's business_discovery endpoint doesn't cover personal accounts, which is most contacts) and is fetched asynchronously, once per contact, after their first message or comment — so it can be nil for a while after a contact is created even when it will eventually be filled in. See docs/INSTAGRAM_CONNECTION_SYSTEM.md."},"website":{"type":"string","example":"https://john.doe.com","description":"The website the contact has set on their Instagram profile. Same source and constraints as `bio` above."},"created_at":{"type":"string","format":"date-time","description":"The date and time when the contact was created"},"updated_at":{"type":"string","format":"date-time","description":"The date and time when the contact was last updated"},"custom_properties":{"type":"object","example":{"birthdate":"1990-01-01","city":"Paris"},"description":"The custom properties of the contact as a JSON object"},"folders":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_FolderEntity"},"description":"The folders the contact belongs to"},"last_messages":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_MessageEntity"},"description":"The last messages received from the contact"},"last_comments":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_CommentEntity"},"description":"The last comments received from the contact"},"last_mentions":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_MentionEntity"},"description":"The last mentions received from the contact"}},"required":["id","name","username","instagram_url","profile_picture","status","notes","is_follower","is_followed","email","real_name","phone","language","follower_count","bio","website","created_at","updated_at","custom_properties","folders","last_messages","last_comments","last_mentions"],"description":"PublicApi_Entities_ExtendedContactEntity model"},"PublicApi_Entities_CommentEntity":{"type":"object","properties":{"text":{"type":"string","example":"Nice post!","description":"The text of the comment"},"received_at":{"type":"string","format":"date-time","description":"The date and time when the comment was received"}},"required":["text","received_at"]},"PublicApi_Entities_MentionEntity":{"type":"object","properties":{"text":{"type":"string","example":"Thanks @john_doe!","description":"The text of the mention"},"received_at":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00Z","description":"The date and time when the mention was received"}},"required":["text","received_at"]},"putApiV1Contact":{"type":"object","properties":{"id":{"type":"integer","format":"int32","description":"Contact ID"},"ids":{"type":"array","description":"Contact IDs","items":{"type":"integer","format":"int32"}},"username":{"type":"string","description":"Contact username"},"usernames":{"type":"array","description":"Contact usernames","items":{"type":"string"}},"email":{"type":"string","description":"Contact email"},"emails":{"type":"array","description":"Contact emails","items":{"type":"string"}},"contact":{"type":"object","description":"The contact attributes to update","properties":{"status":{"type":"string","description":"auto updates the status based on contact history","enum":["auto","optout","spam"]},"email":{"type":"string","description":"Contact email","example":"john.doe@example.com"},"phone":{"type":"string","description":"Contact phone","example":"+33612345678"},"language":{"type":"string","description":"Contact language","example":"en"},"folder_ids":{"type":"array","description":"Contact's folder IDs","example":[1,2,3],"items":{"type":"integer","format":"int32"}},"custom_properties":{"type":"object","description":"Custom properties to update","example":{"property_1":"value"}}}}},"required":["contact"],"description":"Update contact(s) (via username, email or ID)"},"postApiV1Folders":{"type":"object","properties":{"folder":{"type":"object","description":"The folder attributes","properties":{"name":{"type":"string","description":"The name of the folder","example":"Potential leads"},"color":{"type":"string","description":"The color of the folder","enum":["yellow","red","green","blue","purple","pink","orange"]}},"required":["name"]}},"required":["folder"],"description":"Create a new folder"},"putApiV1FoldersId":{"type":"object","properties":{"folder":{"type":"object","description":"The folder attributes","properties":{"name":{"type":"string","description":"The name of the folder","example":"Potential leads"},"color":{"type":"string","description":"The color of the folder","enum":["yellow","red","green","blue","purple","pink","orange"]}},"required":["name"]}},"required":["folder"],"description":"Update a folder"},"postApiV1FoldersIdAddContacts":{"type":"object","properties":{"contact_ids":{"type":"array","description":"Contact IDs","example":[1,2,3],"items":{"type":"integer","format":"int32"}}},"required":["contact_ids"],"description":"Add contacts to a folder"},"postApiV1FoldersIdRemoveContacts":{"type":"object","properties":{"contact_ids":{"type":"array","description":"Contact IDs","example":[1,2,3],"items":{"type":"integer","format":"int32"}}},"required":["contact_ids"],"description":"Remove contacts from a folder"},"PublicApi_Entities_SegmentEntity":{"type":"object","properties":{"id":{"type":"integer","format":"int32","example":123,"description":"The ID of the segment"},"title":{"type":"string","example":"VIP buyers","description":"The title of the segment"},"emoji":{"type":"string","description":"Emoji shown next to the title"},"filter_logic":{"type":"string","enum":["and","or"],"description":"Whether contacts must match all filters (and) or any (or)"},"contact_filters":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_ContactFilterEntity"},"description":"The filters defining the segment"},"created_at":{"type":"string","format":"date-time","description":"When the segment was created"},"updated_at":{"type":"string","format":"date-time","description":"When the segment was last updated"}},"required":["id","title","emoji","filter_logic","contact_filters","created_at","updated_at"],"description":"PublicApi_Entities_SegmentEntity model"},"PublicApi_Entities_ContactFilterEntity":{"type":"object","properties":{"id":{"type":"integer","format":"int32","description":"The ID of the contact filter"},"filter_type":{"type":"string","example":"message","description":"The filter type (see GET /contacts/filter_types)"},"operator":{"type":"string","description":"Comparison operator, when the filter type uses one"},"value":{"type":"string","description":"Filter value (meaning depends on filter_type)"},"date_operator":{"type":"string","description":"How the activity date is compared to the day below. A contact matches when at least one of its activities satisfies the condition; is_not_equal and is_not_present match contacts with none. is_equal / is_not_equal use that whole day; is_before and is_after exclude it; is_on_or_before and is_on_or_after include it; is_between includes both days; is_present / is_not_present need no day."},"date_mode":{"type":"string","description":"How the day is picked: exact_date (uses date_value), today, yesterday, or days_ago (uses date_days). Defaults to exact_date."},"date_days":{"type":"integer","format":"int32","description":"Integer, with date_mode days_ago: 7 means 7 days before today"},"date_value":{"type":"string","format":"date","description":"Date (YYYY-MM-DD), with date_mode exact_date"},"date_value_end":{"type":"string","format":"date","description":"Date (YYYY-MM-DD), the last day when date_operator is is_between"},"date_range":{"type":"string","description":"Deprecated: use date_operator"},"custom_date_range_start":{"type":"string","format":"date","description":"Deprecated: use date_value"},"custom_date_range_end":{"type":"string","format":"date","description":"Deprecated: use date_value_end"},"media_id":{"type":"string","description":"Instagram media id (comment filter)"},"story_id":{"type":"string","description":"Story id (story_reply / story_mention filters)"},"referral_ad_id":{"type":"string","description":"Referral ad id (referral_ad filter)"},"scenario_id":{"type":"integer","format":"int32","description":"Scenario id (scenario filter)"},"filtered_campaign_id":{"type":"integer","format":"int32","description":"Campaign id (campaign filter)"},"conversion_link_id":{"type":"integer","format":"int32","description":"Conversion link id (clicked_conversion_link filter)"},"options":{"type":"Object","description":"Extra filter options"}},"required":["id","filter_type","operator","value","date_operator","date_mode","date_days","date_value","date_value_end","date_range","custom_date_range_start","custom_date_range_end","media_id","story_id","referral_ad_id","scenario_id","filtered_campaign_id","conversion_link_id","options"]},"PublicApi_Entities_DetailedSegmentEntity":{"type":"object","properties":{"id":{"type":"integer","format":"int32","example":123,"description":"The ID of the segment"},"title":{"type":"string","example":"VIP buyers","description":"The title of the segment"},"emoji":{"type":"string","description":"Emoji shown next to the title"},"filter_logic":{"type":"string","enum":["and","or"],"description":"Whether contacts must match all filters (and) or any (or)"},"contact_filters":{"type":"array","items":{"$ref":"#/definitions/PublicApi_Entities_ContactFilterEntity"},"description":"The filters defining the segment"},"created_at":{"type":"string","format":"date-time","description":"When the segment was created"},"updated_at":{"type":"string","format":"date-time","description":"When the segment was last updated"},"contacts_count":{"type":"integer","format":"int32","description":"Number of contacts matching the segment (cached for 10 minutes; null if it could not be computed in time)"}},"required":["id","title","emoji","filter_logic","contact_filters","created_at","updated_at","contacts_count"],"description":"PublicApi_Entities_DetailedSegmentEntity model"},"postApiV1Segments":{"type":"object","properties":{"title":{"type":"string","description":"The title of the segment"},"emoji":{"type":"string","description":"Emoji shown next to the title"},"filter_logic":{"type":"string","description":"Whether contacts must match all filters (and) or any (or)","enum":["and","or"],"default":"and"},"contact_filters":{"type":"array","description":"Filters defining the segment (same shape as the `filters` of POST /contacts/filter)","items":{"type":"object","properties":{"id":{"type":"integer","format":"int32","description":"Ignored — filters are replaced as a whole"},"filter_type":{"type":"string","description":"The filter type","enum":["any_engagement","first_interaction","message","comment","story_reply","story_mention","referral_ad","media_mention","folder","clicked_conversion_link","campaign","scenario","survey","appointment","payment","username","name","email","phone","is_follower","is_followed","status","language","follower_count","contact_created_at","contact_property"]},"operator":{"type":"string","description":"Comparison operator, when the filter type uses one","enum":["is_true","is_false","is_present","is_not_present","contains","does_not_contain","is_equal","is_above","is_below","is_not_equal","is_between"]},"value":{"type":"string","description":"Filter value (meaning depends on filter_type)"},"date_operator":{"type":"string","description":"How the activity date is compared to the day below. A contact matches when at least one of its activities satisfies the condition; is_not_equal and is_not_present match contacts with none. is_equal / is_not_equal use that whole day; is_before and is_after exclude it; is_on_or_before and is_on_or_after include it; is_between includes both days; is_present / is_not_present need no day.","enum":["is_equal","is_not_equal","is_before","is_after","is_on_or_before","is_on_or_after","is_between","is_present","is_not_present"]},"date_mode":{"type":"string","description":"How the day is picked: exact_date (uses date_value), today, yesterday, or days_ago (uses date_days). Defaults to exact_date.","enum":["exact_date","today","yesterday","days_ago"]},"date_days":{"type":"integer","format":"int32","description":"Integer, with date_mode days_ago: 7 means 7 days before today"},"date_value":{"type":"string","format":"date","description":"Date (YYYY-MM-DD), with date_mode exact_date"},"date_value_end":{"type":"string","format":"date","description":"Date (YYYY-MM-DD), the last day when date_operator is is_between"},"date_range":{"type":"string","description":"Deprecated: use date_operator","enum":["today","yesterday","last_7_days","last_30_days","last_90_days","last_365_days","all_time","custom"]},"custom_date_range_start":{"type":"string","format":"date","description":"Deprecated: use date_value"},"custom_date_range_end":{"type":"string","format":"date","description":"Deprecated: use date_value_end"},"media_id":{"type":"string","description":"Instagram media id (comment filter)"},"story_id":{"type":"string","description":"Story id (story_reply / story_mention filters)"},"referral_ad_id":{"type":"string","description":"Referral ad id (referral_ad filter)"},"scenario_id":{"type":"integer","format":"int32","description":"Scenario id (scenario filter)"},"filtered_campaign_id":{"type":"integer","format":"int32","description":"Campaign id (campaign filter)"},"conversion_link_id":{"type":"integer","format":"int32","description":"Conversion link id (clicked_conversion_link filter)"},"options":{"type":"object","description":"Extra options: contact_property, value_end (upper bound for is_between), payment_status, survey_completion_status"}},"required":["filter_type"]}}},"required":["title"],"description":"Create a segment"},"patchApiV1SegmentsId":{"type":"object","properties":{"title":{"type":"string","description":"The title of the segment"},"emoji":{"type":"string","description":"Emoji shown next to the title"},"filter_logic":{"type":"string","description":"Whether contacts must match all filters (and) or any (or)","enum":["and","or"]},"contact_filters":{"type":"array","description":"Complete list of filters, replacing the existing ones","items":{"type":"object","properties":{"id":{"type":"integer","format":"int32","description":"Ignored — filters are replaced as a whole"},"filter_type":{"type":"string","description":"The filter type","enum":["any_engagement","first_interaction","message","comment","story_reply","story_mention","referral_ad","media_mention","folder","clicked_conversion_link","campaign","scenario","survey","appointment","payment","username","name","email","phone","is_follower","is_followed","status","language","follower_count","contact_created_at","contact_property"]},"operator":{"type":"string","description":"Comparison operator, when the filter type uses one","enum":["is_true","is_false","is_present","is_not_present","contains","does_not_contain","is_equal","is_above","is_below","is_not_equal","is_between"]},"value":{"type":"string","description":"Filter value (meaning depends on filter_type)"},"date_operator":{"type":"string","description":"How the activity date is compared to the day below. A contact matches when at least one of its activities satisfies the condition; is_not_equal and is_not_present match contacts with none. is_equal / is_not_equal use that whole day; is_before and is_after exclude it; is_on_or_before and is_on_or_after include it; is_between includes both days; is_present / is_not_present need no day.","enum":["is_equal","is_not_equal","is_before","is_after","is_on_or_before","is_on_or_after","is_between","is_present","is_not_present"]},"date_mode":{"type":"string","description":"How the day is picked: exact_date (uses date_value), today, yesterday, or days_ago (uses date_days). Defaults to exact_date.","enum":["exact_date","today","yesterday","days_ago"]},"date_days":{"type":"integer","format":"int32","description":"Integer, with date_mode days_ago: 7 means 7 days before today"},"date_value":{"type":"string","format":"date","description":"Date (YYYY-MM-DD), with date_mode exact_date"},"date_value_end":{"type":"string","format":"date","description":"Date (YYYY-MM-DD), the last day when date_operator is is_between"},"date_range":{"type":"string","description":"Deprecated: use date_operator","enum":["today","yesterday","last_7_days","last_30_days","last_90_days","last_365_days","all_time","custom"]},"custom_date_range_start":{"type":"string","format":"date","description":"Deprecated: use date_value"},"custom_date_range_end":{"type":"string","format":"date","description":"Deprecated: use date_value_end"},"media_id":{"type":"string","description":"Instagram media id (comment filter)"},"story_id":{"type":"string","description":"Story id (story_reply / story_mention filters)"},"referral_ad_id":{"type":"string","description":"Referral ad id (referral_ad filter)"},"scenario_id":{"type":"integer","format":"int32","description":"Scenario id (scenario filter)"},"filtered_campaign_id":{"type":"integer","format":"int32","description":"Campaign id (campaign filter)"},"conversion_link_id":{"type":"integer","format":"int32","description":"Conversion link id (clicked_conversion_link filter)"},"options":{"type":"object","description":"Extra options: contact_property, value_end (upper bound for is_between), payment_status, survey_completion_status"}},"required":["filter_type"]}}},"description":"Update a segment"},"postApiV1ContactProperties":{"type":"object","properties":{"contact_property":{"type":"object","description":"The contact property attributes","properties":{"title":{"type":"string","description":"The title of the contact property","example":"Birthday"},"property_type":{"type":"string","description":"The type of the contact property","enum":["text","number","date","email","phone","url","boolean","list","single_choice","multiple_choice"],"default":"text"},"choices":{"type":"array","description":"Predefined options for single_choice and multiple_choice properties","example":["Free","Pro","Enterprise"],"items":{"type":"string"}},"description":{"type":"string","description":"A description of what this property represents"},"agent_active":{"type":"boolean","description":"Whether this property is active for AI agent detection"},"auto_detect":{"type":"boolean","description":"Whether values for this property are detected automatically from contacts' profiles and conversations. Detection spends AI credits on accounts that have them."}},"required":["title"]}},"required":["contact_property"],"description":"Create a contact property"},"putApiV1ContactPropertiesSlug":{"type":"object","properties":{"contact_property":{"type":"object","description":"The contact property attributes","properties":{"title":{"type":"string","description":"The title of the contact property"},"property_type":{"type":"string","description":"The type of the contact property","enum":["text","number","date","email","phone","url","boolean","list","single_choice","multiple_choice"]},"choices":{"type":"array","description":"Predefined options for single_choice and multiple_choice properties","items":{"type":"string"}},"description":{"type":"string","description":"A description of what this property represents"},"agent_active":{"type":"boolean","description":"Whether this property is active for AI agent detection"},"auto_detect":{"type":"boolean","description":"Whether values for this property are detected automatically from contacts' profiles and conversations. Detection spends AI credits on accounts that have them."}}}},"required":["contact_property"],"description":"Update a contact property"},"PublicApi_Entities_DetailedScenarioEntity":{"type":"object","properties":{"id":{"type":"integer","format":"int32","example":123,"description":"The ID of the scenario"},"title":{"type":"string","example":"Welcome Automation","description":"The title of the scenario"},"active":{"type":"boolean","example":true,"description":"Whether the scenario is active"},"is_template":{"type":"boolean","example":false,"description":"Whether the scenario is a template"},"suspended":{"type":"boolean","example":false,"description":"Whether the scenario has been suspended for abuse (read-only; cannot be run, edited or copied)"},"scenario_type":{"type":"string","enum":["custom","comment_to_dm","comment_moderation"],"example":"custom","description":"The type of the scenario"},"interrupt_on_message":{"type":"boolean","example":false,"description":"Whether the scenario's pending runs for a contact stop when your team messages that contact by hand (Instagram app or Inrō inbox)"},"interrupt_on_reply":{"type":"boolean","example":false,"description":"Whether the scenario's pending runs for a contact stop when the contact sends a message (unless the run is waiting for that reply)"},"last_executed_at":{"type":"string","format":"date-time","description":"The date and time when the scenario was last executed"},"setup_completed_at":{"type":"string","format":"date-time","description":"The date and time when the setup was completed"},"on_reply_scenario_id":{"type":"integer","format":"int32","description":"ID of a scenario to run for a contact whose reply stopped this scenario. Only used with interrupt_on_reply."},"rate_limit_enabled":{"type":"boolean","example":false,"description":"Stop the scenario from running again for the same contact too soon. Needs rate_limit_unit, and rate_limit_value unless the unit is `once`."},"rate_limit_value":{"type":"integer","format":"int32","description":"How many rate_limit_unit must pass after a contact's last run before the scenario runs for them again"},"rate_limit_unit":{"type":"string","description":"`once` runs the scenario only once per contact; any other unit is the unit of rate_limit_value"},"excluded_folder_ids":{"type":"array","items":{"type":"array"},"description":"The IDs of excluded folders"},"scenario_folder_id":{"type":"integer","format":"int32","description":"The ID of the scenario folder"},"scenario_folder_priority":{"type":"integer","format":"int32","description":"The priority within the scenario folder"},"created_at":{"type":"string","format":"date-time","description":"The date and time when the scenario was created"},"updated_at":{"type":"string","format":"date-time","description":"The date and time when the scenario was last updated"},"metrics":{"type":"Object","description":"Scenario metrics. executions counts only executions that ran; ones held back by the contact limit or a disconnected Instagram account are in paused_executions."},"paused_executions":{"type":"Object","example":{"limited":12,"disconnected":0},"description":"Executions waiting to be re-run: limited (monthly contact limit reached) and disconnected (Instagram account disconnected). Comment executions past Instagram's 7-day private-reply window are not included."},"prompt":{"type":"string","example":"Reply to comments with a DM containing a link","description":"The original natural-language prompt used to generate this scenario, if any"},"generation_data":{"type":"Object","description":"Progress of AI generation for scenarios created from a prompt. Contains per-phase (`triggers`, `actions`) `status` values: `pending`, `generating`, `completed`, `failed`, or `not_generated`, plus an optional `error` message. Empty `{}` for scenarios not created from a prompt. `not_generated` on both phases means the prompt was classified rather than built, and `classification` then holds `outcome`, `pattern`, `reason` and, depending on the outcome, `target`, `alternatives`, `question` and `understood`. The generated content itself is available via the scenario's `triggers` and `actions` fields on the detail endpoints."},"full_url":{"type":"string","example":"https://app.inro.social/automation/scenarios/123","description":"The full URL to this scenario in Inrō"},"triggers":{"type":"array","items":{"type":"array"},"description":"Array of scenario triggers. Each trigger has `id`, `trigger_type`, `options`, and `warnings` — the problems detected on the trigger's configuration. Each warning entry has a `message`, a `severity` (`issue` or `suggestion`) and an optional `help_url`."},"actions":{"type":"array","items":{"type":"array"},"description":"Flat array of scenario actions, ordered by position. Each action includes its tree position via `parent_key` / `parent_branch`, and may include nested `conversion_link`, `survey`, `media_file`, or `folder` objects. `warnings` lists the problems detected on the action — each entry has a `message`, a `severity` (`issue` or `suggestion`) and an optional `help_url`. Warnings with a severity of `issue` about the flow structure (a second root action, a `parent_branch` the parent does not have, several actions on one branch) mean the action will not run as drawn; the message states the fix."}},"required":["id","title","active","is_template","suspended","scenario_type","interrupt_on_message","interrupt_on_reply","last_executed_at","setup_completed_at","on_reply_scenario_id","rate_limit_enabled","rate_limit_value","rate_limit_unit","excluded_folder_ids","scenario_folder_id","scenario_folder_priority","created_at","updated_at","metrics","paused_executions","prompt","generation_data","full_url","triggers","actions"],"description":"PublicApi_Entities_DetailedScenarioEntity model"},"postApiV1ScenariosIdTrigger":{"type":"object","properties":{"contacts":{"type":"array","description":"The mandatory contact identifier. Exactly one of the following parameters is required: `id`, `username`, or `email`.","items":{"type":"string"}},"data":{"type":"object","description":"Optional key/value pairs accessible in the scenario as `{{ trigger.key }}`."}},"required":["contacts"],"description":"Trigger a scenario"},"postApiV1ScenariosIdTest":{"type":"object","properties":{"contact":{"type":"object","description":"The contact to test with. Exactly one of the following parameters is required: `id`, `username`, or `email`."}},"required":["contact"],"description":"Test a scenario with a contact"},"postApiV1Scenarios":{"type":"object","properties":{"template_id":{"type":"integer","format":"int32","description":"The ID of the template scenario (optional - if provided, creates from template)"},"prompt":{"type":"string","description":"A natural language description of the scenario to generate. When provided, the prompt is first classified: only a buildable request generates triggers and actions asynchronously via AI. A prompt that Instagram cannot support, that is not an instruction, or that belongs to another feature is classified instead of generated, and the scenario is created with no triggers and no actions. Poll GET /scenarios/:id and inspect `generation_data`: `generation_data.classification` carries the outcome (`clarify`, `route`, `refuse` or `decline`) with its reason, and both phase statuses are `not_generated`."},"title":{"type":"string","description":"The title of the scenario"},"active":{"type":"boolean","description":"Whether the scenario is active"},"scenario_type":{"type":"string","description":"The type of scenario","enum":["custom","comment_to_dm","comment_moderation"]},"interrupt_on_message":{"type":"boolean","description":"Stop the scenario's pending runs for a contact when your team messages that contact by hand, from the Instagram app or the Inrō inbox. Messages sent by scenarios, campaigns, the AI agent or the API don't count."},"interrupt_on_reply":{"type":"boolean","description":"Stop the scenario's pending runs for a contact when the contact sends a message, except a run waiting for that reply at a wait_for_reply, ask_question or collect_property step."},"rate_limit_enabled":{"type":"boolean","description":"Stop the scenario from running again for the same contact too soon. Needs rate_limit_unit, and rate_limit_value unless the unit is `once`."},"rate_limit_value":{"type":"integer","format":"int32","description":"How many rate_limit_unit must pass after a contact's last run before the scenario runs for them again"},"rate_limit_unit":{"type":"string","description":"`once` runs the scenario only once per contact; any other unit is the unit of rate_limit_value","enum":["once","seconds","minutes","hours","days","weeks"]},"scenario_folder_id":{"type":"integer","format":"int32","description":"ID of the scenario folder to assign this scenario to (pass null to remove from folder)"},"scenario_folder_priority":{"type":"integer","format":"int32","description":"Priority within a priority-type folder (1 = highest priority). Only meaningful when the folder's type is `priority`."},"triggers":{"type":"array","description":"Direct JSON definition of the scenario's triggers. On update, a list with no `id` replaces all existing triggers; once any item has an `id`, listed triggers are updated or added and the others are kept. Replacing recreates every trigger with a new id, and a webhook trigger loses its URL.","items":{"type":"object","properties":{"id":{"type":"integer","format":"int32","description":"ID of an existing trigger to update. When any item has an `id`, triggers left out of the list are kept."},"trigger_type":{"type":"string","description":"The trigger type (e.g. messages, comment, story_reply)"},"options":{"type":"object","description":"Trigger-specific options"}}}},"actions":{"type":"array","description":"Complete list of the scenario's actions. Any existing action not in this list will be destroyed. Include existing actions by `id` to keep or update them; omit `id` to create new actions. Each non-root action must specify its parent via `parent_key` (referencing another action's `action_key` in this list) or `parent_id` (the `id` of another action in this list).","items":{"type":"object","properties":{"id":{"type":"integer","format":"int32","description":"Action ID (for partial updates)"},"action_type":{"type":"string","description":"The action type (e.g. message, delay, ask_question)"},"action_key":{"type":"string","description":"Stable key used to reference this action as a parent of others"},"parent_id":{"type":"integer","format":"int32","description":"ID of this action's parent. The parent must also be present in this list. Alternative to `parent_key` when the parent is an existing action."},"parent_key":{"type":"string","description":"`action_key` of this action's parent, if any"},"parent_branch":{"type":"string","description":"Branch label this action lives under in its parent"},"position":{"type":"integer","format":"int32","description":"Position within its branch"},"content":{"type":"string","description":"Action content (for message actions)"},"options":{"type":"object","description":"Action-specific options"},"conversion_link":{"type":"object","description":"Conversion link for this action. To reference an existing link: provide `id`. To create a new link inline: provide `title`, `url`, and `button_title` (all required), plus optional `subtitle` and `media_file`."},"survey":{"type":"object","description":"Associated survey. To reference an existing survey: provide `id`. To create one inline: provide `title`, plus optional `subtitle`, `button_label`, `survey_type`, `limit_replies`, `survey_options` (`title`, `payload`, `folder_id`) and `survey_questions` (`title`). Options and questions keep array order."},"media_file":{"type":"object","description":"Media file for this action. To reference an existing file: provide `id`. To create a new file inline: provide `file_url` (downloaded automatically), plus optional `media_type` (auto-detected if omitted) and `caption`."},"folder":{"type":"object","description":"Inline definition of an associated folder"}}}}},"description":"Create a scenario"},"patchApiV1ScenariosId":{"type":"object","properties":{"prompt":{"type":"string","description":"A new natural language description. When provided, triggers and actions are regenerated asynchronously via AI. Poll GET /scenarios/:id and inspect `generation_data` to track progress."},"title":{"type":"string","description":"The title of the scenario"},"active":{"type":"boolean","description":"Whether the scenario is active"},"scenario_type":{"type":"string","description":"The type of scenario","enum":["custom","comment_to_dm","comment_moderation"]},"interrupt_on_message":{"type":"boolean","description":"Stop the scenario's pending runs for a contact when your team messages that contact by hand, from the Instagram app or the Inrō inbox. Messages sent by scenarios, campaigns, the AI agent or the API don't count."},"interrupt_on_reply":{"type":"boolean","description":"Stop the scenario's pending runs for a contact when the contact sends a message, except a run waiting for that reply at a wait_for_reply, ask_question or collect_property step."},"rate_limit_enabled":{"type":"boolean","description":"Stop the scenario from running again for the same contact too soon. Needs rate_limit_unit, and rate_limit_value unless the unit is `once`."},"rate_limit_value":{"type":"integer","format":"int32","description":"How many rate_limit_unit must pass after a contact's last run before the scenario runs for them again"},"rate_limit_unit":{"type":"string","description":"`once` runs the scenario only once per contact; any other unit is the unit of rate_limit_value","enum":["once","seconds","minutes","hours","days","weeks"]},"scenario_folder_id":{"type":"integer","format":"int32","description":"ID of the scenario folder to assign this scenario to (pass null to remove from folder)"},"scenario_folder_priority":{"type":"integer","format":"int32","description":"Priority within a priority-type folder (1 = highest priority). Only meaningful when the folder's type is `priority`."},"triggers":{"type":"array","description":"Direct JSON definition of the scenario's triggers. On update, a list with no `id` replaces all existing triggers; once any item has an `id`, listed triggers are updated or added and the others are kept. Replacing recreates every trigger with a new id, and a webhook trigger loses its URL.","items":{"type":"object","properties":{"id":{"type":"integer","format":"int32","description":"ID of an existing trigger to update. When any item has an `id`, triggers left out of the list are kept."},"trigger_type":{"type":"string","description":"The trigger type (e.g. messages, comment, story_reply)"},"options":{"type":"object","description":"Trigger-specific options"}}}},"actions":{"type":"array","description":"Complete list of the scenario's actions. Any existing action not in this list will be destroyed. Include existing actions by `id` to keep or update them; omit `id` to create new actions. Each non-root action must specify its parent via `parent_key` (referencing another action's `action_key` in this list) or `parent_id` (the `id` of another action in this list).","items":{"type":"object","properties":{"id":{"type":"integer","format":"int32","description":"Action ID (for partial updates)"},"action_type":{"type":"string","description":"The action type (e.g. message, delay, ask_question)"},"action_key":{"type":"string","description":"Stable key used to reference this action as a parent of others"},"parent_id":{"type":"integer","format":"int32","description":"ID of this action's parent. The parent must also be present in this list. Alternative to `parent_key` when the parent is an existing action."},"parent_key":{"type":"string","description":"`action_key` of this action's parent, if any"},"parent_branch":{"type":"string","description":"Branch label this action lives under in its parent"},"position":{"type":"integer","format":"int32","description":"Position within its branch"},"content":{"type":"string","description":"Action content (for message actions)"},"options":{"type":"object","description":"Action-specific options"},"conversion_link":{"type":"object","description":"Conversion link for this action. To reference an existing link: provide `id`. To create a new link inline: provide `title`, `url`, and `button_title` (all required), plus optional `subtitle` and `media_file`."},"survey":{"type":"object","description":"Associated survey. To reference an existing survey: provide `id`. To create one inline: provide `title`, plus optional `subtitle`, `button_label`, `survey_type`, `limit_replies`, `survey_options` (`title`, `payload`, `folder_id`) and `survey_questions` (`title`). Options and questions keep array order."},"media_file":{"type":"object","description":"Media file for this action. To reference an existing file: provide `id`. To create a new file inline: provide `file_url` (downloaded automatically), plus optional `media_type` (auto-detected if omitted) and `caption`."},"folder":{"type":"object","description":"Inline definition of an associated folder"}}}}},"description":"Update a scenario"},"postApiV1ScenarioFolders":{"type":"object","properties":{"name":{"type":"string","description":"The name of the folder (must be unique within the organization)"},"description":{"type":"string","description":"Optional description of the folder"},"folder_type":{"type":"string","description":"Folder type: `normal` (all matching scenarios run) or `priority` (only the highest-priority scenario runs)","enum":["normal","priority"],"default":"priority"}},"required":["name"],"description":"Create a scenario folder"},"patchApiV1ScenarioFoldersId":{"type":"object","properties":{"name":{"type":"string","description":"New name for the folder"},"description":{"type":"string","description":"New description for the folder"},"folder_type":{"type":"string","description":"Folder type","enum":["normal","priority"]}},"description":"Update a scenario folder"},"postApiV1ScenarioFoldersIdReorder":{"type":"object","properties":{"scenario_ids":{"type":"array","description":"Ordered list of scenario IDs. The first entry has the highest priority.","items":{"type":"integer","format":"int32"}}},"required":["scenario_ids"],"description":"Reorder scenarios in a priority folder"},"patchApiV1ScenarioFoldersIdToggleActive":{"type":"object","properties":{"active":{"type":"boolean","description":"Set to true to activate all scenarios, false to deactivate"}},"required":["active"],"description":"Toggle all scenarios in a folder active or inactive"},"postApiV1Messages":{"type":"object","properties":{"contact_ids":{"type":"array","description":"Array of contact IDs. You can provide contact_ids, contact_usernames, or contact_emails (or mix of single/array versions). Maximum 1000 contacts total.","items":{"type":"integer","format":"int32"}},"contact_id":{"type":"integer","format":"int32","description":"Single contact ID. You can provide contact_id, contact_username, or contact_email (or array versions)."},"contact_usernames":{"type":"array","description":"Array of contact usernames. You can provide contact_ids, contact_usernames, or contact_emails (or mix of single/array versions). Maximum 1000 contacts total.","items":{"type":"string"}},"contact_username":{"type":"string","description":"Single contact username. You can provide contact_id, contact_username, or contact_email (or array versions)."},"contact_emails":{"type":"array","description":"Array of contact emails. You can provide contact_ids, contact_usernames, or contact_emails (or mix of single/array versions). Maximum 1000 contacts total.","items":{"type":"string"}},"contact_email":{"type":"string","description":"Single contact email. You can provide contact_id, contact_username, or contact_email (or array versions)."},"content":{"type":"string","description":"Message content/text (required for text messages, ignored for media/share messages)","example":"Hello! This is a test message."},"message_type":{"type":"string","description":"Message type. Defaults to 'text'. Use 'image', 'video' or 'audio' to send a media file (via the matching parameter), 'share' to share a media post from the library (via media_id), or 'conversion_link' to send a conversion link card (via conversion_link_id).","enum":["text","image","video","audio","share","conversion_link"],"default":"text","example":"text"},"image":{"type":"string","description":"Image file (multipart upload) or publicly accessible URL. Required when message_type is 'image'."},"images":{"type":"array","description":"Several images (files or publicly accessible URLs, max 10) sent together as one message. Only for message_type 'image'; takes precedence over image.","items":{"type":"string"}},"video":{"type":"string","description":"Video file (multipart upload) or publicly accessible URL. Required when message_type is 'video'."},"audio":{"type":"string","description":"Audio file (multipart upload) or publicly accessible URL. Required when message_type is 'audio'."},"media_id":{"type":"integer","format":"int32","description":"Inrō media ID of the post to share. Required when message_type is 'share'."},"conversion_link_id":{"type":"integer","format":"int32","description":"Inrō conversion link ID. Required when message_type is 'conversion_link'."}},"description":"Send a message to one or more contacts"},"PublicApi_Entities_DetailedCampaignEntity":{"type":"object","properties":{"id":{"type":"integer","format":"int32","example":123,"description":"The ID of the campaign"},"title":{"type":"string","example":"Welcome Campaign","description":"The title of the campaign"},"status":{"type":"string","enum":["draft","running","completed","scheduled","limited","canceled"],"example":"draft","description":"The status of the campaign"},"sent_at":{"type":"string","format":"date-time","description":"The date and time when the campaign was sent"},"scheduled_at":{"type":"string","format":"date-time","description":"The date and time when the campaign is scheduled to be sent"},"options":{"type":"Object","description":"Additional options for the campaign"},"campaign_folder_id":{"type":"integer","format":"int32","description":"The ID of the campaign folder this campaign belongs to (null if ungrouped)"},"selected_contact_ids":{"type":"array","items":{"type":"array"},"description":"The IDs of selected contacts"},"created_at":{"type":"string","format":"date-time","description":"The date and time when the campaign was created"},"updated_at":{"type":"string","format":"date-time","description":"The date and time when the campaign was last updated"},"metrics":{"type":"Object","description":"Campaign metrics data"},"full_url":{"type":"string","example":"https://app.inro.social/campaigns/123","description":"The full URL to this campaign in Inrō"},"campaign_rules":{"type":"array","items":{"type":"array"},"description":"Targeting rules (the campaign's destinations). Each has `id`, `list_type` (folder or segment), `rule_type` (inclusion or exclusion) and `destination_id` (the folder or segment ID)."},"actions":{"type":"array","items":{"type":"array"},"description":"Flat array of campaign actions, ordered by position. Each action includes its tree position via `parent_id` / `parent_key` / `parent_branch`, and may include nested `conversion_link`, `survey`, `media_file`, or `folder` objects. `warnings` lists the problems detected on the action — each entry has a `message`, a `severity` (`issue` or `suggestion`) and an optional `help_url`."}},"required":["id","title","status","sent_at","scheduled_at","options","campaign_folder_id","selected_contact_ids","created_at","updated_at","metrics","full_url","campaign_rules","actions"],"description":"PublicApi_Entities_DetailedCampaignEntity model"},"patchApiV1CampaignsId":{"type":"object","properties":{"title":{"type":"string","description":"The title of the campaign"},"interrupt_on_message":{"type":"boolean","description":"Stop the campaign's pending runs for a contact when your team messages that contact by hand, from the Instagram app or the Inrō inbox. Messages sent by scenarios, campaigns, the AI agent or the API don't count."},"interrupt_on_reply":{"type":"boolean","description":"Stop the campaign's pending runs for a contact when the contact sends a message, except a run waiting for that reply at a wait_for_reply, ask_question or collect_property step. on_reply_scenario_id then runs for that contact, if set."},"options":{"type":"object","description":"Additional options (e.g. exclude_time)"},"scheduled_at":{"type":"string","format":"date-time","description":"Date/time when the campaign should be sent"},"on_reply_scenario_id":{"type":"integer","format":"int32","description":"ID of a scenario to run for a contact whose reply stopped the campaign. Only used with interrupt_on_reply."},"campaign_folder_id":{"type":"integer","format":"int32","description":"ID of the campaign folder to assign this campaign to (pass null to remove from folder)"},"selected_contact_ids":{"type":"array","description":"Explicit list of contact IDs to target","items":{"type":"integer","format":"int32"}},"campaign_rules_attributes":{"type":"array","description":"Folder/segment inclusion and exclusion rules (Rails nested attributes form, supports `_destroy`)","items":{"type":"object","properties":{"id":{"type":"integer","format":"int32","description":"Rule ID (required when updating or deleting an existing rule)"},"_destroy":{"type":"boolean","description":"Set to true to delete this rule"},"list_type":{"type":"string","description":"Type of list to target","enum":["folder","segment"]},"rule_type":{"type":"string","description":"Whether this rule includes or excludes contacts","enum":["inclusion","exclusion"]},"destination_id":{"type":"integer","format":"int32","description":"ID of the folder or segment"}}}},"campaign_rules":{"type":"array","description":"Folder/segment inclusion and exclusion rules (replaces existing rules when no ids are provided)","items":{"type":"object","properties":{"id":{"type":"integer","format":"int32","description":"Rule ID (for partial updates)"},"list_type":{"type":"string","description":"Type of list to target","enum":["folder","segment"]},"rule_type":{"type":"string","description":"Whether this rule includes or excludes contacts","enum":["inclusion","exclusion"]},"destination_id":{"type":"integer","format":"int32","description":"ID of the folder or segment"}}}},"actions":{"type":"array","description":"Complete list of the campaign's actions. Any existing action not in this list will be destroyed. Include existing actions by `id` to keep or update them; omit `id` to create new actions. Each non-root action must specify its parent via `parent_key` or `parent_id`.","items":{"type":"object","properties":{"id":{"type":"integer","format":"int32","description":"Action ID (for partial updates)"},"action_type":{"type":"string","description":"The action type (e.g. message, delay, ask_question)"},"action_key":{"type":"string","description":"Stable key used to reference this action as a parent of others"},"parent_id":{"type":"integer","format":"int32","description":"ID of this action's parent. The parent must also be present in this list. Alternative to `parent_key` when the parent is an existing action."},"parent_key":{"type":"string","description":"`action_key` of this action's parent, if any"},"parent_branch":{"type":"string","description":"Branch label this action lives under in its parent"},"position":{"type":"integer","format":"int32","description":"Position within its branch"},"content":{"type":"string","description":"Action content (for message actions)"},"options":{"type":"object","description":"Action-specific options"},"conversion_link":{"type":"object","description":"Conversion link for this action. To reference an existing link: provide `id`. To create a new link inline: provide `title`, `url`, and `button_title` (all required), plus optional `subtitle` and `media_file`."},"survey":{"type":"object","description":"Associated survey. To reference an existing survey: provide `id`. To create one inline: provide `title`, plus optional `subtitle`, `button_label`, `survey_type`, `limit_replies`, `survey_options` (`title`, `payload`, `folder_id`) and `survey_questions` (`title`). Options and questions keep array order."},"media_file":{"type":"object","description":"Media file for this action. To reference an existing file: provide `id`. To create a new file inline: provide `file_url` (downloaded automatically), plus optional `media_type` (auto-detected if omitted) and `caption`."},"folder":{"type":"object","description":"Inline definition of an associated folder"}}}}},"description":"Update a campaign"},"postApiV1CampaignsIdTest":{"type":"object","properties":{"contact":{"type":"object","description":"The contact to test with. Exactly one of the following parameters is required: `id`, `username`, or `email`."}},"required":["contact"],"description":"Test a campaign with a contact"},"postApiV1Campaigns":{"type":"object","properties":{"template_id":{"type":"integer","format":"int32","description":"The ID of the template campaign (optional - if provided, creates from template)"},"title":{"type":"string","description":"The title of the campaign"},"interrupt_on_message":{"type":"boolean","description":"Stop the campaign's pending runs for a contact when your team messages that contact by hand, from the Instagram app or the Inrō inbox. Messages sent by scenarios, campaigns, the AI agent or the API don't count."},"interrupt_on_reply":{"type":"boolean","description":"Stop the campaign's pending runs for a contact when the contact sends a message, except a run waiting for that reply at a wait_for_reply, ask_question or collect_property step. on_reply_scenario_id then runs for that contact, if set."},"options":{"type":"object","description":"Additional options (e.g. exclude_time)"},"scheduled_at":{"type":"string","format":"date-time","description":"Date/time when the campaign should be sent"},"on_reply_scenario_id":{"type":"integer","format":"int32","description":"ID of a scenario to run for a contact whose reply stopped the campaign. Only used with interrupt_on_reply."},"campaign_folder_id":{"type":"integer","format":"int32","description":"ID of the campaign folder to assign this campaign to (pass null to remove from folder)"},"selected_contact_ids":{"type":"array","description":"Explicit list of contact IDs to target","items":{"type":"integer","format":"int32"}},"campaign_rules_attributes":{"type":"array","description":"Folder/segment inclusion and exclusion rules (Rails nested attributes form)","items":{"type":"object","properties":{"list_type":{"type":"string","description":"Type of list to target","enum":["folder","segment"]},"rule_type":{"type":"string","description":"Whether this rule includes or excludes contacts","enum":["inclusion","exclusion"]},"destination_id":{"type":"integer","format":"int32","description":"ID of the folder or segment"}}}},"campaign_rules":{"type":"array","description":"Folder/segment inclusion and exclusion rules (direct definition form)","items":{"type":"object","properties":{"id":{"type":"integer","format":"int32","description":"Rule ID (for partial updates)"},"list_type":{"type":"string","description":"Type of list to target","enum":["folder","segment"]},"rule_type":{"type":"string","description":"Whether this rule includes or excludes contacts","enum":["inclusion","exclusion"]},"destination_id":{"type":"integer","format":"int32","description":"ID of the folder or segment"}}}},"actions":{"type":"array","description":"Direct JSON definition of the campaign's actions as a flat array","items":{"type":"object","properties":{"id":{"type":"integer","format":"int32","description":"Action ID (for partial updates)"},"action_type":{"type":"string","description":"The action type (e.g. message, delay, ask_question)"},"action_key":{"type":"string","description":"Stable key used to reference this action as a parent of others"},"parent_id":{"type":"integer","format":"int32","description":"ID of this action's parent. The parent must also be present in this list. Alternative to `parent_key` when the parent is an existing action."},"parent_key":{"type":"string","description":"`action_key` of this action's parent, if any"},"parent_branch":{"type":"string","description":"Branch label this action lives under in its parent"},"position":{"type":"integer","format":"int32","description":"Position within its branch"},"content":{"type":"string","description":"Action content (for message actions)"},"options":{"type":"object","description":"Action-specific options"},"conversion_link":{"type":"object","description":"Conversion link for this action. To reference an existing link: provide `id`. To create a new link inline: provide `title`, `url`, and `button_title` (all required), plus optional `subtitle` and `media_file`."},"survey":{"type":"object","description":"Associated survey. To reference an existing survey: provide `id`. To create one inline: provide `title`, plus optional `subtitle`, `button_label`, `survey_type`, `limit_replies`, `survey_options` (`title`, `payload`, `folder_id`) and `survey_questions` (`title`). Options and questions keep array order."},"media_file":{"type":"object","description":"Media file for this action. To reference an existing file: provide `id`. To create a new file inline: provide `file_url` (downloaded automatically), plus optional `media_type` (auto-detected if omitted) and `caption`."},"folder":{"type":"object","description":"Inline definition of an associated folder"}}}}},"description":"Create a campaign"},"postApiV1CampaignsIdResend":{"type":"object","properties":{"scope":{"type":"string","description":"Which paused sends to put through: those stopped by the activation limit, or those stopped by a broken connection","enum":["limited","disconnected"]},"window":{"type":"string","description":"Only re-send sends paused within this window; anything older is cancelled","enum":["day","week","all"],"default":"all"},"confirm":{"type":"boolean","description":"`false` previews without sending. Must be `true` to actually re-send.","default":false}},"required":["scope"],"description":"Re-send paused campaign sends"},"postApiV1CampaignFolders":{"type":"object","properties":{"name":{"type":"string","description":"The name of the folder (must be unique within the organization)"},"description":{"type":"string","description":"Optional description of the folder"}},"required":["name"],"description":"Create a campaign folder"},"patchApiV1CampaignFoldersId":{"type":"object","properties":{"name":{"type":"string","description":"New name for the folder"},"description":{"type":"string","description":"New description for the folder"}},"description":"Update a campaign folder"},"postApiV1ConversionLinks":{"type":"object","properties":{"title":{"type":"string","description":"Title shown on the link card"},"url":{"type":"string","description":"Destination URL"},"button_title":{"type":"string","description":"Call-to-action button label (e.g. 'Shop Now', 'Learn More')"},"subtitle":{"type":"string","description":"Optional subtitle shown on the link card"},"image_url":{"type":"string","description":"URL of an image to use as the link card image (downloaded in the background, so it appears shortly after the response)"},"media_file_id":{"type":"integer","format":"int32","description":"ID of an existing media file to use as the link card image. Applied immediately — prefer it over image_url when the image is already in the media library"}},"required":["title","url","button_title"],"description":"Create a conversion link"},"patchApiV1ConversionLinksId":{"type":"object","properties":{"title":{"type":"string","description":"Title shown on the link card"},"subtitle":{"type":"string","description":"Optional subtitle"},"url":{"type":"string","description":"Destination URL"},"button_title":{"type":"string","description":"Call-to-action button label"},"image_url":{"type":"string","description":"URL of a new image for the link card, downloaded in the background and swapped in shortly after the response. Pass null to remove the current image"},"media_file_id":{"type":"integer","format":"int32","description":"ID of an existing media file to use as the link card image. Applied immediately. Pass null to remove the current image"}},"description":"Update a conversion link"},"postApiV1Medias":{"type":"object","properties":{"publish_media_type":{"type":"string","description":"The type of feed post to create","enum":["IMAGE","REELS","CAROUSEL"]},"media_file_id":{"type":"integer","format":"int32","description":"Uploaded MediaFile ID (required for IMAGE and REELS)"},"children":{"type":"array","description":"Ordered MediaFile IDs for a CAROUSEL (2–10 items)","items":{"type":"integer","format":"int32"}},"caption":{"type":"string","description":"Post caption"},"location_id":{"type":"string","description":"Instagram location (page) ID"},"alt_text":{"type":"string","description":"Accessibility alt text"},"audio_name":{"type":"string","description":"Custom audio name (REELS)"},"share_to_feed":{"type":"boolean","description":"Whether a REEL is also shared to the main feed"},"thumb_offset":{"type":"integer","format":"int32","description":"Frame offset in ms used as the REEL thumbnail"},"cover_media_id":{"type":"integer","format":"int32","description":"MediaFile ID used as the REEL cover image"},"collaborators":{"type":"array","description":"Usernames invited as collaborators (max 3)","items":{"type":"string"}},"trial_graduation_strategy":{"type":"string","description":"Publish a REEL as a trial reel, shown only to non-followers until it graduates. `MANUAL`: you graduate it in the Instagram app. `SS_PERFORMANCE`: Instagram graduates it automatically if it performs well. Omit for a normal reel.","enum":["MANUAL","SS_PERFORMANCE"]},"user_tags":{"type":"array","description":"People to tag. Each entry needs a username; feed images also accept x/y coordinates (0–1).","items":{"type":"object","properties":{"username":{"type":"string"},"x":{"type":"number","format":"float"},"y":{"type":"number","format":"float"}},"required":["username"]}},"is_ai_generated":{"type":"boolean","description":"Label the post as AI-generated content. Meta requires this on photorealistic AI-generated media. It is applied when the post is published and cannot be added afterwards — only removed, from Instagram — so set it before publishing or scheduling."},"is_paid_partnership":{"type":"boolean","description":"Show Instagram's \"Paid partnership\" label on the post. Applied when the post is published and cannot be added afterwards, so set it before publishing or scheduling."},"branded_content_sponsors":{"type":"array","description":"Brand partners to tag on the paid partnership (max 2). Each entry is either an Instagram user ID or a username; a username is resolved here and must belong to a public Business or Creator account. Send [] to remove them.","items":{"type":"string"}},"agent_context":{"type":"string","description":"Notes for the AI agent about this post — background it needs to answer questions but that shouldn't appear in the caption. Can be set or changed at any time, including after the post is published."},"scheduled_at":{"type":"string","format":"date-time","description":"Future timestamp to schedule automatic publishing"},"publish_now":{"type":"boolean","description":"Publish to Instagram immediately"},"comment_to_dm":{"type":"object","description":"Reply to people who comment on this post, then DM them a link. Pass the comment filter and the link; every other step (the public comment reply, the DM question, the follow-up, folder tagging, pixel event) is filled in from your most recent comment-to-DM automation. Sending it again for the same post updates that automation rather than creating a second one. Also available on its own at `POST /medias/:id/comment_to_dm`.","properties":{"comment_options":{"type":"object","description":"Which comments trigger it. Optional — defaults to your most recent automation's filter, or every comment. This post is targeted for you, so `post_type` and `post_ids` are ignored if sent.","properties":{"comment_type":{"type":"string","description":"`all_comments`: any comment. `comment_keywords`: comments containing one of `comment_keywords`. `ai_detected`: comments matching `ai_intent`. `hate_spam`: hateful or spam comments. `tag_someone`: comments that @mention an account.","enum":["all_comments","comment_keywords","ai_detected","hate_spam","tag_someone"]},"comment_keywords":{"type":"array","description":"Keywords the comment must contain. Required when `comment_type` is `comment_keywords`.","items":{"type":"string"}},"ai_intent":{"type":"string","description":"Plain-language intent the AI looks for (e.g. \"asking for the price\"). Required when `comment_type` is `ai_detected`."},"allow_replies":{"type":"boolean","description":"Also trigger on replies, not only top-level comments"},"exclude_negative":{"type":"boolean","description":"Skip comments an AI check detects as negative"}}},"conversion_link":{"type":"object","description":"The link the DM sends. Required the first time an automation is attached to a post; omit it later to leave the link as it is. Give either `id` or `url`.","properties":{"id":{"type":"integer","format":"int32","description":"Send an existing conversion link. Every other field here is ignored and the link is left untouched, since other scenarios may send it too."},"url":{"type":"string","description":"Destination URL for a new link. Its title, subtitle and image are read from the page's OpenGraph tags; the fields below override whatever is found."},"title":{"type":"string","description":"Link card title. Defaults to the page's OpenGraph title, then this post's caption, then the URL host."},"subtitle":{"type":"string","description":"Link card subtitle. Defaults to the page's OpenGraph description."},"button_title":{"type":"string","description":"Call-to-action label on the card (e.g. \"Shop now\"). Defaults to a localized \"Visit website\"."},"image_url":{"type":"string","description":"Image for the card. Defaults to the page's OpenGraph image; left empty if it has none."}}},"question_type":{"type":"string","description":"What the commenter must do in the DM before the link is sent. `button_template`: tap a button. `message`: reply to a plain message. `ask_for_follow`: follow the account first (verified). `collect_property`: give their email. Defaults to the one your most recent automation used.","enum":["button_template","message","ask_for_follow","collect_property"]},"active":{"type":"boolean","description":"Whether the automation runs. Defaults to true when it is created, so the post ships working."}}}},"required":["publish_media_type"],"description":"Create a media post"},"patchApiV1MediasId":{"type":"object","properties":{"media_file_id":{"type":"integer","format":"int32"},"children":{"type":"array","items":{"type":"integer","format":"int32"}},"caption":{"type":"string"},"location_id":{"type":"string"},"alt_text":{"type":"string"},"audio_name":{"type":"string"},"share_to_feed":{"type":"boolean"},"thumb_offset":{"type":"integer","format":"int32"},"cover_media_id":{"type":"integer","format":"int32"},"collaborators":{"type":"array","items":{"type":"string"}},"trial_graduation_strategy":{"type":"string","enum":["MANUAL","SS_PERFORMANCE"]},"user_tags":{"type":"array","description":"People to tag. Each entry needs a username; feed images also accept x/y coordinates (0–1).","items":{"type":"object","properties":{"username":{"type":"string"},"x":{"type":"number","format":"float"},"y":{"type":"number","format":"float"}},"required":["username"]}},"is_ai_generated":{"type":"boolean","description":"Label the post as AI-generated content. Meta requires this on photorealistic AI-generated media. It is applied when the post is published and cannot be added afterwards — only removed, from Instagram — so set it before publishing or scheduling."},"is_paid_partnership":{"type":"boolean","description":"Show Instagram's \"Paid partnership\" label on the post. Applied when the post is published and cannot be added afterwards, so set it before publishing or scheduling."},"branded_content_sponsors":{"type":"array","description":"Brand partners to tag on the paid partnership (max 2). Each entry is either an Instagram user ID or a username; a username is resolved here and must belong to a public Business or Creator account. Send [] to remove them.","items":{"type":"string"}},"agent_context":{"type":"string","description":"Notes for the AI agent about this post. Can be set or changed at any time, including on a published post."},"scheduled_at":{"type":"string","format":"date-time"},"comment_to_dm":{"type":"object","description":"Reply to people who comment on this post, then DM them a link. Pass the comment filter and the link; every other step (the public comment reply, the DM question, the follow-up, folder tagging, pixel event) is filled in from your most recent comment-to-DM automation. Sending it again for the same post updates that automation rather than creating a second one. Also available on its own at `POST /medias/:id/comment_to_dm`.","properties":{"comment_options":{"type":"object","description":"Which comments trigger it. Optional — defaults to your most recent automation's filter, or every comment. This post is targeted for you, so `post_type` and `post_ids` are ignored if sent.","properties":{"comment_type":{"type":"string","description":"`all_comments`: any comment. `comment_keywords`: comments containing one of `comment_keywords`. `ai_detected`: comments matching `ai_intent`. `hate_spam`: hateful or spam comments. `tag_someone`: comments that @mention an account.","enum":["all_comments","comment_keywords","ai_detected","hate_spam","tag_someone"]},"comment_keywords":{"type":"array","description":"Keywords the comment must contain. Required when `comment_type` is `comment_keywords`.","items":{"type":"string"}},"ai_intent":{"type":"string","description":"Plain-language intent the AI looks for (e.g. \"asking for the price\"). Required when `comment_type` is `ai_detected`."},"allow_replies":{"type":"boolean","description":"Also trigger on replies, not only top-level comments"},"exclude_negative":{"type":"boolean","description":"Skip comments an AI check detects as negative"}}},"conversion_link":{"type":"object","description":"The link the DM sends. Required the first time an automation is attached to a post; omit it later to leave the link as it is. Give either `id` or `url`.","properties":{"id":{"type":"integer","format":"int32","description":"Send an existing conversion link. Every other field here is ignored and the link is left untouched, since other scenarios may send it too."},"url":{"type":"string","description":"Destination URL for a new link. Its title, subtitle and image are read from the page's OpenGraph tags; the fields below override whatever is found."},"title":{"type":"string","description":"Link card title. Defaults to the page's OpenGraph title, then this post's caption, then the URL host."},"subtitle":{"type":"string","description":"Link card subtitle. Defaults to the page's OpenGraph description."},"button_title":{"type":"string","description":"Call-to-action label on the card (e.g. \"Shop now\"). Defaults to a localized \"Visit website\"."},"image_url":{"type":"string","description":"Image for the card. Defaults to the page's OpenGraph image; left empty if it has none."}}},"question_type":{"type":"string","description":"What the commenter must do in the DM before the link is sent. `button_template`: tap a button. `message`: reply to a plain message. `ask_for_follow`: follow the account first (verified). `collect_property`: give their email. Defaults to the one your most recent automation used.","enum":["button_template","message","ask_for_follow","collect_property"]},"active":{"type":"boolean","description":"Whether the automation runs. Defaults to true when it is created, so the post ships working."}}}},"description":"Update a media draft"},"postApiV1MediasIdCommentToDm":{"type":"object","properties":{"comment_options":{"type":"object","description":"Which comments trigger it. Optional — defaults to your most recent automation's filter, or every comment. This post is targeted for you, so `post_type` and `post_ids` are ignored if sent.","properties":{"comment_type":{"type":"string","description":"`all_comments`: any comment. `comment_keywords`: comments containing one of `comment_keywords`. `ai_detected`: comments matching `ai_intent`. `hate_spam`: hateful or spam comments. `tag_someone`: comments that @mention an account.","enum":["all_comments","comment_keywords","ai_detected","hate_spam","tag_someone"]},"comment_keywords":{"type":"array","description":"Keywords the comment must contain. Required when `comment_type` is `comment_keywords`.","items":{"type":"string"}},"ai_intent":{"type":"string","description":"Plain-language intent the AI looks for (e.g. \"asking for the price\"). Required when `comment_type` is `ai_detected`."},"allow_replies":{"type":"boolean","description":"Also trigger on replies, not only top-level comments"},"exclude_negative":{"type":"boolean","description":"Skip comments an AI check detects as negative"}}},"conversion_link":{"type":"object","description":"The link the DM sends. Required the first time an automation is attached to a post; omit it later to leave the link as it is. Give either `id` or `url`.","properties":{"id":{"type":"integer","format":"int32","description":"Send an existing conversion link. Every other field here is ignored and the link is left untouched, since other scenarios may send it too."},"url":{"type":"string","description":"Destination URL for a new link. Its title, subtitle and image are read from the page's OpenGraph tags; the fields below override whatever is found."},"title":{"type":"string","description":"Link card title. Defaults to the page's OpenGraph title, then this post's caption, then the URL host."},"subtitle":{"type":"string","description":"Link card subtitle. Defaults to the page's OpenGraph description."},"button_title":{"type":"string","description":"Call-to-action label on the card (e.g. \"Shop now\"). Defaults to a localized \"Visit website\"."},"image_url":{"type":"string","description":"Image for the card. Defaults to the page's OpenGraph image; left empty if it has none."}}},"question_type":{"type":"string","description":"What the commenter must do in the DM before the link is sent. `button_template`: tap a button. `message`: reply to a plain message. `ask_for_follow`: follow the account first (verified). `collect_property`: give their email. Defaults to the one your most recent automation used.","enum":["button_template","message","ask_for_follow","collect_property"]},"active":{"type":"boolean","description":"Whether the automation runs. Defaults to true when it is created, so the post ships working."}},"description":"Attach a comment-to-DM automation"},"postApiV1Stories":{"type":"object","properties":{"media_file_id":{"type":"integer","format":"int32","description":"Uploaded MediaFile ID (image or video)"},"user_tags":{"type":"array","description":"People to tag. Each entry needs a username; feed images also accept x/y coordinates (0–1).","items":{"type":"object","properties":{"username":{"type":"string"},"x":{"type":"number","format":"float"},"y":{"type":"number","format":"float"}},"required":["username"]}},"is_ai_generated":{"type":"boolean","description":"Label the post as AI-generated content. Meta requires this on photorealistic AI-generated media. It is applied when the post is published and cannot be added afterwards — only removed, from Instagram — so set it before publishing or scheduling."},"agent_context":{"type":"string","description":"Notes for the AI agent about this story — background it needs to answer questions but that shouldn't appear in the caption. Can be set or changed at any time, including after the story is published."},"scheduled_at":{"type":"string","format":"date-time","description":"Future timestamp to schedule automatic publishing"},"publish_now":{"type":"boolean","description":"Publish to Instagram immediately"}},"required":["media_file_id"],"description":"Create a story"},"patchApiV1StoriesId":{"type":"object","properties":{"media_file_id":{"type":"integer","format":"int32"},"user_tags":{"type":"array","description":"People to tag. Each entry needs a username; feed images also accept x/y coordinates (0–1).","items":{"type":"object","properties":{"username":{"type":"string"},"x":{"type":"number","format":"float"},"y":{"type":"number","format":"float"}},"required":["username"]}},"is_ai_generated":{"type":"boolean","description":"Label the post as AI-generated content. Meta requires this on photorealistic AI-generated media. It is applied when the post is published and cannot be added afterwards — only removed, from Instagram — so set it before publishing or scheduling."},"agent_context":{"type":"string","description":"Notes for the AI agent about this story. Can be set or changed at any time, including on a published story."},"scheduled_at":{"type":"string","format":"date-time"}},"description":"Update a story draft"},"postApiV1MediaFiles":{"type":"object","properties":{"file":{"type":"file","description":"Binary file upload (multipart/form-data)"},"file_url":{"type":"string","description":"URL to download the file from","example":"https://example.com/photo.jpg"},"media_type":{"type":"string","description":"Media type (auto-detected from Content-Type for file_url; required for the upload_url flow)","enum":["image","audio","video","application","text"],"example":"image"},"caption":{"type":"string","description":"Description of the file","example":"Product photo"},"purpose":{"type":"string","description":"Optional hint, never affects quality. `publishing` skips preparing the DM copy up front; `messaging` (default) prepares it in the background.","enum":["messaging","publishing"],"example":"publishing"}},"description":"Create a media file"},"putApiV1MediaFilesIdUpload":{"type":"object","properties":{"token":{"type":"string","description":"Single-use upload token"}},"required":["token"],"description":"Upload bytes for a pending media file"},"patchApiV1Agent":{"type":"object","properties":{"trigger_mode":{"type":"string","description":"When the agent replies","enum":["all_messages","specific_messages","never_reply","automation_only"]},"trigger_intents":{"type":"object","description":"Intent configuration with `intents` array of trigger phrases (for specific_messages mode)"},"folder_rules":{"type":"object","description":"Folder targeting rules with `folder_rule_type` (include/exclude/null) and `folder_ids` array"},"about":{"type":"string","description":"Who the account is, what it offers and who it talks to (max 500 characters). Included in every reply."},"goal":{"type":"string","description":"What the agent works toward in a conversation it handles on its own (max 500 characters). A custom task from an automation (agent handover, AI message) replaces it, and comment replies don't use it."},"rules":{"type":"array","description":"Replaces the whole rule list. Each rule has a kind (voice: how the agent writes; instruction: what it must or must not say or do) and a text (one sentence, max 300 characters, at most 50 rules per kind). Rules apply to every reply, including automations and comment replies. To change one rule, send the list from get with that rule edited.","items":{"type":"object","properties":{"id":{"type":"integer","format":"int32","description":"ID of an existing rule (from get) to keep it; omit to add a rule"},"kind":{"type":"string","enum":["voice","instruction"]},"text":{"type":"string"}},"required":["kind","text"]}},"account_type":{"type":"string","description":"Legacy, replaced by about, goal and rules: only used while context_migrated is false. Type of account/business (e.g. ecommerce, service)"},"description":{"type":"string","description":"Legacy, replaced by about, goal and rules: only used while context_migrated is false. Description of the business or account"},"goals":{"type":"array","description":"Legacy, replaced by about, goal and rules: only used while context_migrated is false. Business goals for the agent","items":{"type":"string"}},"audience_type":{"type":"string","description":"Legacy, replaced by about, goal and rules: only used while context_migrated is false. Target audience type"},"chat_instructions":{"type":"string","description":"Legacy, replaced by about, goal and rules: only used while context_migrated is false. Custom instructions for the agent's chat behavior"},"common_intents":{"type":"array","description":"Common contact intents the agent should recognize","items":{"type":"string"}},"role":{"type":"string","description":"Legacy, replaced by about, goal and rules: only used while context_migrated is false. The agent's role persona","enum":["community_manager","sales_closer","support_agent","content_promoter","lead_nurturer","brand_concierge"]},"message_length":{"type":"integer","format":"int32","description":"Target message length in words","enum":[10,25,50]},"auto_like":{"type":"boolean","description":"Whether to automatically like messages"},"style_rules":{"type":"string","description":"Legacy, replaced by about, goal and rules: only used while context_migrated is false. Custom style rules for message composition"},"message_examples":{"type":"array","description":"Example messages to guide the agent's writing style","items":{"type":"string"}},"no_reply_active":{"type":"boolean","description":"\"Limit to instructions\": when true, the agent only answers with information from its instructions and knowledge and otherwise says it doesn't know, which also runs no_reply_scenario_id if set. When false (\"Always have an answer\"), it also answers from its general model knowledge."},"no_reply_scenario_id":{"type":"string","description":"ID of the scenario to run when the agent finds no answer in its instructions and knowledge. Only used when no_reply_active is true."},"request_human_scenario_id":{"type":"string","description":"ID of the scenario to run when a human handover is requested"},"human_takeover_active":{"type":"boolean","description":"Whether the agent stands down when a team member replies manually"},"human_takeover_pause":{"type":"integer","format":"int32","description":"Hours the agent stays out of a conversation after a team member replies manually","enum":[1,4,12,24]},"built_in_property_access":{"type":"array","description":"Built-in contact fields the agent may read when replying (email and/or phone). Custom properties use `agent_active` on the property itself.","items":{"type":"string","enum":["email","phone"]}},"setup_completed":{"type":"boolean","description":"Whether the agent setup is done. Defaults to true on any update, so the app skips its setup wizard; pass false to show the wizard again."}},"description":"Update the AI agent configuration"},"postApiV1AgentItems":{"type":"object","properties":{"item_type":{"type":"string","description":"The type of item","enum":["text","url"]},"text":{"type":"string","description":"The text content (required for text-type items)"},"source_url":{"type":"string","description":"The source URL (required for url-type items)"},"retrieval":{"type":"boolean","description":"Whether this item is used for semantic retrieval","default":true}},"required":["item_type"],"description":"Create an agent knowledge item"},"patchApiV1AgentItemsId":{"type":"object","properties":{"text":{"type":"string","description":"The text content"},"source_url":{"type":"string","description":"The source URL"},"retrieval":{"type":"boolean","description":"Whether this item is used for semantic retrieval"}},"description":"Update an agent knowledge item"},"postApiV1AgentActions":{"type":"object","properties":{"trigger":{"type":"string","description":"The intent or phrase that triggers this action"},"target_type":{"type":"string","description":"The type of target for this action","enum":["ConversionLink","Folder","Scenario","Survey"]},"target_id":{"type":"integer","format":"int32","description":"The ID of the target resource (Folder, Scenario, ConversionLink, or Survey)"}},"required":["trigger","target_type","target_id"],"description":"Create an agent action"},"patchApiV1AgentActionsId":{"type":"object","properties":{"trigger":{"type":"string","description":"The intent or phrase that triggers this action"},"target_type":{"type":"string","description":"The type of target for this action","enum":["ConversionLink","Folder","Scenario","Survey"]},"target_id":{"type":"integer","format":"int32","description":"The ID of the target resource"}},"description":"Update an agent action"},"postApiV1AgentContactProperties":{"type":"object","properties":{"field_name":{"type":"string","description":"Built-in field to track (email or phone)","enum":["email","phone"]},"contact_property_id":{"type":"integer","format":"int32","description":"The ID of a custom contact property to track"}},"description":"Add a contact property for the agent to track"},"patchApiV1SettingsOptout":{"type":"object","properties":{"active":{"type":"boolean","description":"Whether opt-out handling is on"},"menu_message":{"type":"string","description":"Label of the opt-out entry in the Instagram persistent menu. Blank removes the entry"},"confirmation_message":{"type":"string","description":"Message sent to a contact once they have been opted out. Blank sends nothing"},"keywords":{"type":"array","description":"Incoming message keywords that opt a contact out. Any message containing one of them as a whole word opts out, ignoring case, accents and surrounding spaces; keywords of 4+ characters also match a plural or one extra letter. Replaces the current list","items":{"type":"string"}},"ai_detection":{"type":"boolean","description":"Whether the AI Agent may recognize an opt-out request in its own words, in conversations it replies to, in addition to the keywords and persistent menu. Defaults to true"}},"description":"Update the opt-out settings"},"postApiV1Icebreakers":{"type":"object","properties":{"question":{"type":"string","description":"The icebreaker question shown on the profile"}},"required":["question"],"description":"Create an icebreaker"},"patchApiV1IcebreakersPayload":{"type":"object","properties":{"question":{"type":"string","description":"The new icebreaker question"}},"required":["question"],"description":"Update an icebreaker"},"postApiV1PersistentMenu":{"type":"object","properties":{"title":{"type":"string","description":"Label shown in the menu (truncated to 30 characters)"},"type":{"type":"string","description":"`postback` sends the payload to Inrō; `web_url` opens a URL","enum":["postback","web_url"],"default":"postback"},"url":{"type":"string","description":"Required for a `web_url` entry: the URL to open"},"payload":{"type":"string","description":"Postback entries only: the payload sent when the entry is tapped. Generated when omitted"}},"required":["title"],"description":"Add a persistent menu entry"},"patchApiV1PersistentMenuId":{"type":"object","properties":{"title":{"type":"string","description":"New label"},"url":{"type":"string","description":"New URL, for a link entry"}},"description":"Update a persistent menu entry"},"postApiV1PartnerOrganizations":{"type":"object","properties":{"name":{"type":"string","description":"A name to identify the account before Instagram is connected. Replaced by the Instagram profile name once it is."},"partner_link_code":{"type":"string","description":"Code of one of your managed partner links, to attribute the organization to it and apply its default template."},"template_id":{"type":"integer","format":"int32","description":"A scenario of yours to duplicate into the new organization, activated on creation."}},"description":"Create an organization"}}}