openapi: 3.2.0 info: title: Nooks Sequencing Calls API version: 0.1.0 description: "The Nooks Sequencing API provides programmatic access to manage sequences, tasks, templates, and prospect engagement workflows created using the Nooks SEP.\n\n## Authentication\n\nSend a bearer token in the `Authorization` header:\n```\nAuthorization: Bearer \n```\n\nTwo token types are accepted on the same header — the API detects which\nformat you sent and validates accordingly. If you already have a token,\npaste it into the Authentication panel and skip the flow setup.\n\n### API keys\n\nLong-lived, workspace-scoped. Best for backend integrations and\nserver-to-server automation. Generate one from **Developer Settings →\nAPI Keys** in your Nooks workspace. API keys are prefixed `nooks-api-`\nand have full read/write access within the owning workspace.\n\n### OAuth 2.0 access tokens\n\nShort-lived (1 hour), user-scoped, scope-limited JWTs issued by\n`https://oauth.nooks.in` via the standard authorization-code + PKCE flow.\nBest for third-party apps acting on behalf of a specific user — the token\ncarries that user's identity and a subset of scopes the user consented\nto. Refresh tokens rotate every 90 days and are invalidated on first\nre-use (refresh-token reuse detection).\n\n**Endpoints:**\n\n- Authorize: `https://oauth.nooks.in/oauth/authorize`\n- Token: `https://oauth.nooks.in/oauth/token`\n- JWKS: `https://oauth.nooks.in/.well-known/jwks.json`\n- Server metadata (RFC 8414): `https://oauth.nooks.in/.well-known/oauth-authorization-server`\n\n**Available scopes:**\n\n| Scope | Grants |\n| --- | --- |\n| `prospects:read` | View your prospects |\n| `prospects:write` | Create and update prospects |\n| `sequences:read` | View your sequences |\n| `sequences:write` | Create and update sequences |\n| `sequence-steps:read` | View sequence steps |\n| `sequence-states:read` | View sequence enrollments |\n| `sequence-states:write` | Enroll prospects and manage enrollments |\n| `tasks:read` | View your tasks |\n| `tasks:write` | Create, update, complete, skip, and delete tasks |\n| `calls:read` | View your calls |\n| `calls:write` | Create and update calls |\n| `call-dispositions:read` | View call dispositions |\n| `emails:read` | View your emails |\n| `emails:write` | Create and update emails |\n| `mailboxes:read` | View connected mailboxes |\n| `users:read` | View users in your workspace |\n| `accounts:read` | View accounts (companies) in your workspace |\n| `notes:write` | Create notes on CRM-backed prospects and accounts |\n| `opportunities:read` | View opportunities (deals) in your workspace |\n| `search:read` | Search across your prospects, accounts, and other records |\n\n## Rate Limiting\nAPI requests are rate limited per workspace and per endpoint in a fixed\none-minute window. Separate endpoint buckets do not share quota, except\nroutes without an explicit limit use the shared default bucket.\n\nEvery response includes these headers:\n- `X-RateLimit-Limit` -- maximum requests allowed in the current per-minute window\n- `X-RateLimit-Remaining` -- requests remaining in the current window\n- `X-RateLimit-Reset` -- seconds until the current window resets\n\nWhen the limit is exceeded the API returns `429 Too Many Requests` with a\n`Retry-After` header indicating how many seconds to wait before retrying.\n\n**Current limits:**\n\n| Endpoint class | Methods | Limit |\n| --- | --- | --- |\n| List reads: `/sequences`, `/emails`, `/users`, `/sequenceStates`, `/prospects`, `/mailboxes`, `/calls`, `/sequenceSteps`, `/callDispositions`, `/tasks`, `/accounts` | `GET` | 300 requests/minute per endpoint |\n| Read by ID: `/sequences/{id}`, `/emails/{id}`, `/users/{id}`, `/sequenceStates/{id}`, `/prospects/{id}`, `/mailboxes/{id}`, `/calls/{id}`, `/sequenceSteps/{id}`, `/callDispositions/{id}`, `/tasks/{id}`, `/accounts/{id}`, `/emailTemplate/{id}` | `GET` | 600 requests/minute per endpoint |\n| Sequence writes: `/sequences`, `/sequences/{id}` | `POST`, `PATCH` | 120 requests/minute per endpoint |\n| Sequence state writes: `/sequenceStates`, `/sequenceStates/{id}`, `/sequenceStates/{id}/actions/finish` | `POST`, `DELETE` | 120 requests/minute per endpoint |\n| Task writes: `/tasks`, `/tasks/{id}`, `/tasks/{id}/complete`, `/tasks/{id}/skip` | `POST`, `PATCH`, `DELETE` | 120 requests/minute per endpoint |\n| CRM note writes: `/prospects/{id}/notes`, `/accounts/{id}/notes` | `POST` | 30 requests/minute per endpoint |\n| `/integrations/prospects/sync` | `POST` | 10 requests/minute |\n| Any other endpoint | Any | 30 requests/minute, shared default bucket |\n\n## Pagination\nList endpoints support cursor-based pagination using the `page[size]` and `page[after]`/`page[before]` query parameters.\n- Maximum page size: 100\n- Default page size: 50\n\n## Include (Inline Expansion)\nMost GET endpoints support an `include` query parameter that expands related `ReferenceObject` fields inline,\neliminating the need for follow-up API calls.\n\n**Format:** `?include=field1,field2` (comma-separated field names)\n\n**Without include:**\n```json\nGET /v1/prospects/123\n\n{\n \"id\": \"123\",\n \"sequenceStates\": [\n { \"id\": \"ss-1\", \"_href\": \"/v1/sequenceStates/ss-1\" }\n ]\n}\n```\n\n**With `include=sequenceStates`:**\n```json\nGET /v1/prospects/123?include=sequenceStates\n\n{\n \"id\": \"123\",\n \"sequenceStates\": [\n {\n \"id\": \"ss-1\",\n \"_href\": \"/v1/sequenceStates/ss-1\",\n \"state\": \"active\",\n \"sequence\": { \"id\": \"seq-1\", \"_href\": \"/v1/sequences/seq-1\" },\n \"prospect\": { \"id\": \"123\", \"_href\": \"/v1/prospects/123\" },\n \"creator\": { \"id\": \"u-1\", \"_href\": \"/v1/users/u-1\" },\n \"sequenceStep\": null,\n \"createdAt\": \"2024-01-01T00:00:00Z\",\n \"updatedAt\": \"2024-01-01T00:00:00Z\"\n }\n ]\n}\n```\n\nThe expanded object is a superset of `ReferenceObject` — it keeps `id` and `_href` and adds all DTO fields.\nThe response shape is unchanged; the field just contains richer data.\n\n**Hard constraints (enforced with 400 errors):**\n- **Max 3 includes per request.** Requesting more than 3 comma-separated values returns `400: \"include accepts at most 3 values\"`.\n- **GET endpoints only.** POST, PATCH, and DELETE endpoints do not accept `include`.\n- **No nested includes.** Only top-level field names are valid (e.g., `sequenceStates`). Dot-notation like `sequenceStates.prospect` returns 400.\n- **`account` on Prospect is not includable.** Requesting `include=account` returns 400.\n\nEach endpoint's `include` parameter lists the valid field names for that resource.\n" contact: name: Nooks API Support email: support@nooks.in url: https://www.nooks.in license: name: Proprietary x-logo: url: ./nooks-logo.svg altText: Nooks Logo href: https://www.nooks.ai servers: - url: https://partner-api.nooks.in/v1 description: Production API security: - BearerAuth: [] tags: - name: Calls description: Access call records paths: /calls: get: operationId: listCalls summary: List calls description: "Returns a paginated list of calls made on the Nooks SEP. Supports filtering by ID and updatedAt range.\n\nThere is no fixed API-enforced historical lookback window for this\nendpoint. You can page through all retained Nooks SEP call records\navailable in the workspace. Historical availability depends on when\nthe workspace started using Nooks SEP and the workspace's retained call\ndata. Use `filter[time]` to fetch by when the call occurred, or\n`filter[createdAt]` / `filter[updatedAt]` for ingestion and sync\nworkflows.\n\nExample:\n```bash\ncurl -X GET 'https://partner-api.nooks.in/v1/calls?page[size]=50' \\\n -H \"Authorization: Bearer nooks-api-...\"\n```\n\nFilter by updatedAt range:\n```bash\ncurl -X GET 'https://partner-api.nooks.in/v1/calls?filter[updatedAt][gte]=2025-01-01T00:00:00Z&filter[updatedAt][lt]=2026-01-01T00:00:00Z' \\\n -H \"Authorization: Bearer nooks-api-...\"\n```\n\nFilter by IDs:\n```bash\ncurl -X GET 'https://partner-api.nooks.in/v1/calls?filter[id]=550e8400-e29b-41d4-a716-446655440000,660e8400-e29b-41d4-a716-446655440001' \\\n -H \"Authorization: Bearer nooks-api-...\"\n```\n\nFilter by account:\n```bash\ncurl -X GET 'https://partner-api.nooks.in/v1/calls?filter[account][id]=990e8400-e29b-41d4-a716-446655440099' \\\n -H \"Authorization: Bearer nooks-api-...\"\n```\n\nFilter by owner (user who placed the call):\n```bash\ncurl -X GET 'https://partner-api.nooks.in/v1/calls?filter[owner][id]=KKLvN5wQoghWFwUvC75CZ12QM7I3' \\\n -H \"Authorization: Bearer nooks-api-...\"\n```\n" tags: - Calls parameters: - $ref: '#/components/parameters/PageSize' - $ref: '#/components/parameters/PageAfter' - $ref: '#/components/parameters/PageBefore' - $ref: '#/components/parameters/FilterId' - $ref: '#/components/parameters/FilterUpdatedAtGte' - $ref: '#/components/parameters/FilterUpdatedAtLt' - name: filter[time][gte] in: query description: Filter calls that occurred at or after this timestamp (ISO 8601). `time` is the actual call time (distinct from `createdAt`, which is the ingestion time). required: false schema: type: string format: date-time example: '2026-04-22T00:00:00Z' - name: filter[time][lte] in: query description: Filter calls that occurred at or before this timestamp (ISO 8601). required: false schema: type: string format: date-time example: '2026-04-22T23:59:59Z' - name: filter[createdAt][gte] in: query description: Filter calls ingested at or after this timestamp (ISO 8601). required: false schema: type: string format: date-time example: '2026-04-22T00:00:00Z' - name: filter[createdAt][lte] in: query description: Filter calls ingested at or before this timestamp (ISO 8601). required: false schema: type: string format: date-time example: '2026-04-22T23:59:59Z' - name: filter[prospect][id] in: query description: Filter calls to a specific prospect. required: false schema: type: string format: uuid example: 770e8400-e29b-41d4-a716-446655440003 - name: filter[account][id] in: query description: 'Filter calls associated with a specific account. Matches the account snapshot stored on the call at ingestion time. ' required: false schema: type: string format: uuid example: 990e8400-e29b-41d4-a716-446655440099 - name: filter[callDisposition][id] in: query description: Filter calls by their recorded disposition. required: false schema: type: string format: uuid example: cc0e8400-e29b-41d4-a716-446655440040 - name: filter[owner][id] in: query description: 'Filter calls placed by a specific user. Matched via the linked caller''s `userId` (the User who owns the caller record). ' required: false schema: type: string example: KKLvN5wQoghWFwUvC75CZ12QM7I3 - name: include in: query description: 'Comma-separated relations to expand inline. Valid values: `prospect`, `sequence`, `sequenceStep`, `callDisposition`, `owner`. Max 3.' required: false schema: type: array items: type: string enum: - prospect - sequence - sequenceStep - callDisposition - owner maxItems: 3 style: form explode: false example: - prospect - callDisposition responses: '200': description: Successful response content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/Call' links: $ref: '#/components/schemas/PaginationLinks' example: data: - id: ff0e8400-e29b-41d4-a716-446655440060 source: nooks duration: 120.5 from: '+14155551234' to: '+14155555678' direction: outgoing recordingUrl: https://example.com/recordings/abc123 prospect: id: 770e8400-e29b-41d4-a716-446655440003 _href: /v1/prospects/770e8400-e29b-41d4-a716-446655440003 sequence: id: 550e8400-e29b-41d4-a716-446655440000 _href: /v1/sequences/550e8400-e29b-41d4-a716-446655440000 sequenceStep: id: aa0e8400-e29b-41d4-a716-446655440030 _href: /v1/sequenceSteps/aa0e8400-e29b-41d4-a716-446655440030 callDisposition: id: dd0e8400-e29b-41d4-a716-446655440070 _href: /v1/callDispositions/dd0e8400-e29b-41d4-a716-446655440070 owner: id: KKLvN5wQoghWFwUvC75CZ12QM7I3 _href: /v1/users/KKLvN5wQoghWFwUvC75CZ12QM7I3 createdAt: '2025-11-01T10:00:00.000Z' updatedAt: '2025-11-01T10:02:00.000Z' - id: ff1e8400-e29b-41d4-a716-446655440061 source: nooks duration: 45.0 from: '+14155551234' to: '+14155559999' direction: outgoing recordingUrl: null prospect: null sequence: null sequenceStep: null callDisposition: null owner: null createdAt: '2025-11-02T14:00:00.000Z' updatedAt: '2025-11-02T14:00:45.000Z' links: first: https://partner-api.nooks.in/v1/calls?page[size]=50 prev: null next: https://partner-api.nooks.in/v1/calls?page[size]=50&page[after]=eyJpZCI6ImZmMWU4NDAwLWUyOWItNDFkNC1hNzE2LTQ0NjY1NTQ0MDA2MSIsInYiOjF9 '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '500': $ref: '#/components/responses/InternalError' /calls/{id}: get: operationId: getCall summary: Get call by ID description: "Returns a single call made on the Nooks SEP by its unique identifier.\n\nExample:\n```bash\ncurl -X GET 'https://partner-api.nooks.in/v1/calls/ff0e8400-e29b-41d4-a716-446655440060' \\\n -H \"Authorization: Bearer nooks-api-...\"\n```\n" tags: - Calls parameters: - name: id in: path required: true description: Unique identifier for the call schema: type: string format: uuid example: ff0e8400-e29b-41d4-a716-446655440060 - name: include in: query description: 'Comma-separated relations to expand inline. Valid values: `prospect`, `sequence`, `sequenceStep`, `callDisposition`, `owner`. Max 3.' required: false schema: type: array items: type: string enum: - prospect - sequence - sequenceStep - callDisposition - owner maxItems: 3 style: form explode: false example: - prospect responses: '200': description: Successful response content: application/json: schema: $ref: '#/components/schemas/Call' example: id: ff0e8400-e29b-41d4-a716-446655440060 source: nooks duration: 120.5 from: '+14155551234' to: '+14155555678' direction: outgoing recordingUrl: https://example.com/recordings/abc123 prospect: id: 770e8400-e29b-41d4-a716-446655440003 _href: /v1/prospects/770e8400-e29b-41d4-a716-446655440003 sequence: id: 550e8400-e29b-41d4-a716-446655440000 _href: /v1/sequences/550e8400-e29b-41d4-a716-446655440000 sequenceStep: id: aa0e8400-e29b-41d4-a716-446655440030 _href: /v1/sequenceSteps/aa0e8400-e29b-41d4-a716-446655440030 callDisposition: id: dd0e8400-e29b-41d4-a716-446655440070 _href: /v1/callDispositions/dd0e8400-e29b-41d4-a716-446655440070 owner: id: KKLvN5wQoghWFwUvC75CZ12QM7I3 _href: /v1/users/KKLvN5wQoghWFwUvC75CZ12QM7I3 createdAt: '2025-11-01T10:00:00.000Z' updatedAt: '2025-11-01T10:02:00.000Z' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalError' components: responses: Unauthorized: description: Unauthorized - invalid or missing API key content: application/json: schema: $ref: '#/components/schemas/Error' example: error: code: UNAUTHORIZED message: Invalid or missing API key NotFound: description: Resource not found content: application/json: schema: $ref: '#/components/schemas/Error' example: error: code: NOT_FOUND message: The requested resource was not found InternalError: description: Internal server error content: application/json: schema: $ref: '#/components/schemas/Error' example: error: code: INTERNAL_ERROR message: An unexpected error occurred BadRequest: description: Bad request - invalid parameters content: application/json: schema: $ref: '#/components/schemas/Error' example: error: code: BAD_REQUEST message: Invalid page[after] cursor parameters: FilterUpdatedAtLt: name: filter[updatedAt][lt] in: query description: Filter by updatedAt before this timestamp, exclusive (ISO 8601 datetime) required: false schema: type: string format: date-time example: '2026-01-01T00:00:00Z' PageSize: name: page[size] in: query description: Number of items per page (max 100) required: false schema: type: integer minimum: 1 maximum: 100 default: 50 example: 50 FilterUpdatedAtGte: name: filter[updatedAt][gte] in: query description: Filter by minimum updatedAt (ISO 8601 datetime) required: false schema: type: string format: date-time example: '2025-01-01T00:00:00Z' PageAfter: name: page[after] in: query description: 'Cursor for fetching the next page. Opaque token returned by the API in `links.next`; callers should treat it as opaque and only pass values they received from a previous response. Malformed cursors return `400 Bad Request`. ' required: false schema: type: string example: eyJpZCI6IjU1MGU4NDAwLWUyOWItNDFkNC1hNzE2LTQ0NjY1NTQ0MDAwMCIsInYiOjF9 FilterId: name: filter[id] in: query description: Filter by IDs (comma-separated UUIDs). An empty value is treated as "no filter". required: false schema: type: string pattern: ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}(,[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})*)?$ example: 550e8400-e29b-41d4-a716-446655440000,660e8400-e29b-41d4-a716-446655440001 PageBefore: name: page[before] in: query description: 'Cursor for fetching the previous page. Opaque token returned by the API in `links.prev`; callers should treat it as opaque and only pass values they received from a previous response. Malformed cursors return `400 Bad Request`. ' required: false schema: type: string example: eyJpZCI6IjU1MGU4NDAwLWUyOWItNDFkNC1hNzE2LTQ0NjY1NTQ0MDAwMCIsInYiOjF9 schemas: Error: type: object description: Standard error response properties: error: type: object properties: code: type: string description: Error code example: NOT_FOUND message: type: string description: Human-readable error message example: The requested resource was not found traceId: type: string description: 'Request trace identifier for correlating this error with server logs and support requests. Present whenever the request carried a trace context (the normal case); omitted otherwise. ' example: abc123def456 PaginationLinks: type: object description: 'Pagination links for navigating through results. Links are returned as relative references (path + query) that should be resolved against the base URL of the request. ' properties: first: type: string format: uri-reference description: URL for the first page example: /v1/sequences?page[size]=50 prev: type: string format: uri-reference nullable: true description: URL for the previous page (null if on first page) example: null next: type: string format: uri-reference nullable: true description: URL for the next page (null if on last page) example: /v1/sequences?page[size]=50&page[after]=eyJpZCI6IjU1MGU4NDAwLWUyOWItNDFkNC1hNzE2LTQ0NjY1NTQ0MDAwMCIsInYiOjF9 Call: type: object description: A call record properties: id: type: string format: uuid description: Unique identifier for the call example: ff0e8400-e29b-41d4-a716-446655440060 source: type: string description: Source/type of the call (e.g., nooks, outreach, salesforce) example: nooks duration: type: number description: Duration of the call in seconds example: 120.5 from: type: string nullable: true description: Phone number of the rep who made/received the call example: '+14155551234' to: type: string nullable: true description: Phone number of the prospect example: '+14155555678' direction: type: string nullable: true description: Direction of the call example: outgoing recordingUrl: type: string nullable: true description: URL to the call recording example: https://example.com/recordings/abc123 time: type: string format: date-time description: 'Wall-clock time the call actually happened. Distinct from `createdAt` (ingestion time) — `time` is what the dialer / telephony layer recorded. Use this for call-time-based queries and filtering. ' example: '2025-11-01T09:57:12.000Z' prospect: nullable: true description: Prospect this call is associated with allOf: - $ref: '#/components/schemas/ReferenceObject' sequence: nullable: true description: 'Sequence associated with this call when matched to a Nooks SEP task. Null when the call is not matched to a Nooks SEP task. ' allOf: - $ref: '#/components/schemas/ReferenceObject' sequenceStep: nullable: true description: 'Sequence step associated with this call when matched to a Nooks SEP task. Null when the call is not matched to a Nooks SEP task. ' allOf: - $ref: '#/components/schemas/ReferenceObject' callDisposition: nullable: true description: 'Call disposition assigned to this call. Null when no disposition has been set. ' allOf: - $ref: '#/components/schemas/ReferenceObject' owner: nullable: true description: 'The user who placed the call. Sourced from the linked caller''s `userId`. Null when the caller has no associated Nooks user. ' allOf: - $ref: '#/components/schemas/ReferenceObject' createdAt: type: string format: date-time description: When the call was created example: '2025-11-01T10:00:00.000Z' updatedAt: type: string format: date-time description: When the call was last updated example: '2025-11-05T14:30:00.000Z' required: - id - source - duration - from - to - direction - recordingUrl - time - prospect - sequence - sequenceStep - callDisposition - owner - createdAt - updatedAt ReferenceObject: type: object description: A reference to a related resource properties: id: type: string description: Unique identifier of the referenced resource example: 550e8400-e29b-41d4-a716-446655440000 _href: type: string description: API path to the referenced resource example: /v1/sequences/550e8400-e29b-41d4-a716-446655440000 required: - id - _href securitySchemes: BearerAuth: type: http scheme: bearer description: 'Bearer token sent in the `Authorization` header. Accepts either a long-lived Nooks API key (`nooks-api-...`, from Developer Settings → API Keys) or an OAuth 2.0 access token issued by `https://oauth.nooks.in`. Use whichever you already have — the API validates both formats on the same header. For full OAuth flow details (authorize/token endpoints, scopes, refresh behavior) see the Authentication section of this spec''s introduction. ' x-tagGroups: - name: API Reference tags: - Sequences - SequenceSteps - Emails - Users - SequenceStates - Prospects - Accounts - Notes - Mailboxes - Calls - CallDispositions - Tasks - EmailTemplates - Introspection