diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 4dedeae..511dd51 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "2.5.0" + ".": "2.6.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 0ac1eb3..33b7080 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 32 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/context-dev/context.dev-242450ea46eb8c3e843fd6c4bf87e73192b5f62f6da697cd091d13c6aa7a991b.yml -openapi_spec_hash: c1c561976de1abcacede71fd5ab9b3d9 -config_hash: 70e7e80b5e87f94981bee396c6cd41e8 +configured_endpoints: 37 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/context-dev/context.dev-960cb623c7ec84bf4dc0f5945cbc19eec9cca48271071f400d96066eaa55dbd6.yml +openapi_spec_hash: 84fd39e3f4dc964bf0c32d4e95da1b34 +config_hash: 2bea1743c84d63bd61f8501a6ea63065 diff --git a/CHANGELOG.md b/CHANGELOG.md index 6617357..9a6d1da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## 2.6.0 (2026-07-31) + +Full Changelog: [v2.5.0...v2.6.0](https://github.com/context-dot-dev/context-go-sdk/compare/v2.5.0...v2.6.0) + +### Features + +* **api:** api update ([406077c](https://github.com/context-dot-dev/context-go-sdk/commit/406077c9710998e29e21bd171d51c68823f3e9d3)) +* **api:** api update ([429179f](https://github.com/context-dot-dev/context-go-sdk/commit/429179f178409b399131e3487bf700fb0437b1d3)) +* **api:** api update ([8d33049](https://github.com/context-dot-dev/context-go-sdk/commit/8d3304944074536b1e602da3d2db89a885a07e0c)) +* **api:** api update ([5b78bbb](https://github.com/context-dot-dev/context-go-sdk/commit/5b78bbb8adb906ed1d8f8134c13d26afa03eafdd)) +* **api:** api update ([c0bdc14](https://github.com/context-dot-dev/context-go-sdk/commit/c0bdc141d92f4211cedf92b143544488569f7db4)) +* **api:** manual updates ([de18f04](https://github.com/context-dot-dev/context-go-sdk/commit/de18f040a005d246145ef25123eb92fe0909f688)) + ## 2.5.0 (2026-07-22) Full Changelog: [v2.4.0...v2.5.0](https://github.com/context-dot-dev/context-go-sdk/compare/v2.4.0...v2.5.0) diff --git a/README.md b/README.md index 27d1523..291ae6f 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Or to pin the version: ```sh -go get -u 'github.com/context-dot-dev/context-go-sdk@v2.5.0' +go get -u 'github.com/context-dot-dev/context-go-sdk@v2.6.0' ``` diff --git a/api.md b/api.md index a249d25..bac920a 100644 --- a/api.md +++ b/api.md @@ -118,3 +118,23 @@ Methods: - client.Monitors.ListRuns(ctx context.Context, monitorID string, query contextdev.MonitorListRunsParams) (\*contextdev.MonitorListRunsResponse, error) - client.Monitors.GetChange(ctx context.Context, changeID string) (\*contextdev.MonitorGetChangeResponse, error) - client.Monitors.Run(ctx context.Context, monitorID string) (\*contextdev.MonitorRunResponse, error) + +# Batch + +Response Types: + +- contextdev.ErrorCount +- contextdev.Error +- contextdev.BatchGetResponse +- contextdev.BatchListResponse +- contextdev.BatchCancelResponse +- contextdev.BatchGetResultsResponse +- contextdev.BatchSubmitResponse + +Methods: + +- client.Batch.Get(ctx context.Context, batchID string) (\*contextdev.BatchGetResponse, error) +- client.Batch.List(ctx context.Context, query contextdev.BatchListParams) (\*contextdev.BatchListResponse, error) +- client.Batch.Cancel(ctx context.Context, batchID string) (\*contextdev.BatchCancelResponse, error) +- client.Batch.GetResults(ctx context.Context, batchID string, query contextdev.BatchGetResultsParams) (\*contextdev.BatchGetResultsResponse, error) +- client.Batch.Submit(ctx context.Context, body contextdev.BatchSubmitParams) (\*contextdev.BatchSubmitResponse, error) diff --git a/batch.go b/batch.go new file mode 100644 index 0000000..e7ccac6 --- /dev/null +++ b/batch.go @@ -0,0 +1,1869 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +package contextdev + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "net/http" + "net/url" + "slices" + + "github.com/context-dot-dev/context-go-sdk/v2/internal/apijson" + "github.com/context-dot-dev/context-go-sdk/v2/internal/apiquery" + "github.com/context-dot-dev/context-go-sdk/v2/internal/requestconfig" + "github.com/context-dot-dev/context-go-sdk/v2/option" + "github.com/context-dot-dev/context-go-sdk/v2/packages/param" + "github.com/context-dot-dev/context-go-sdk/v2/packages/respjson" + "github.com/context-dot-dev/context-go-sdk/v2/shared/constant" +) + +// BatchService contains methods and other services that help with interacting with +// the context.dev API. +// +// Note, unlike clients, this service does not read variables from the environment +// automatically. You should not instantiate this service directly, and instead use +// the [NewBatchService] method instead. +type BatchService struct { + options []option.RequestOption +} + +// NewBatchService generates a new service that applies the given options to each +// request. These options are applied after the parent client's options (if there +// is one), and before any request-specific options. +func NewBatchService(opts ...option.RequestOption) (r BatchService) { + r = BatchService{} + r.options = opts + return +} + +// Check progress and get download links when the batch finishes. Also returns the +// rejected-URL list and webhook signing secret from submission, so nothing is lost +// if the submit response was dropped. +func (r *BatchService) Get(ctx context.Context, batchID string, opts ...option.RequestOption) (res *BatchGetResponse, err error) { + opts = slices.Concat(r.options, opts) + if batchID == "" { + err = errors.New("missing required batch_id parameter") + return nil, err + } + path := fmt.Sprintf("batch/%s", url.PathEscape(batchID)) + err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...) + return res, err +} + +// List your batches from newest to oldest. Filter by status or continue with a +// cursor. +func (r *BatchService) List(ctx context.Context, query BatchListParams, opts ...option.RequestOption) (res *BatchListResponse, err error) { + opts = slices.Concat(r.options, opts) + path := "batch/list" + err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, query, &res, opts...) + return res, err +} + +// Stop a batch from starting new pages. In-progress pages finish, and unused +// credits are refunded. +func (r *BatchService) Cancel(ctx context.Context, batchID string, opts ...option.RequestOption) (res *BatchCancelResponse, err error) { + opts = slices.Concat(r.options, opts) + if batchID == "" { + err = errors.New("missing required batch_id parameter") + return nil, err + } + path := fmt.Sprintf("batch/%s/cancel", url.PathEscape(batchID)) + err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, nil, &res, opts...) + return res, err +} + +// Page through the result records of a finished batch as JSON, in the same order +// as the downloadable result files. Use this instead of downloading and parsing +// the NDJSON files yourself. +func (r *BatchService) GetResults(ctx context.Context, batchID string, query BatchGetResultsParams, opts ...option.RequestOption) (res *BatchGetResultsResponse, err error) { + opts = slices.Concat(r.options, opts) + if batchID == "" { + err = errors.New("missing required batch_id parameter") + return nil, err + } + path := fmt.Sprintf("batch/%s/results", url.PathEscape(batchID)) + err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, query, &res, opts...) + return res, err +} + +// Retrieve and normalize a person profile from identifiers. +func (r *BatchService) Submit(ctx context.Context, body BatchSubmitParams, opts ...option.RequestOption) (res *BatchSubmitResponse, err error) { + opts = slices.Concat(r.options, opts) + path := "people/retrieve" + err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...) + return res, err +} + +// Page failures sharing one error code. +type ErrorCount struct { + // Error code for these failures. + Code string `json:"code" api:"required"` + // Pages that failed with this code. + Count int64 `json:"count" api:"required"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Code respjson.Field + Count respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ErrorCount) RawJSON() string { return r.JSON.raw } +func (r *ErrorCount) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Why the batch failed. +type Error struct { + // Batch error code. + Code string `json:"code" api:"required"` + // Batch error message. + Message string `json:"message" api:"required"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Code respjson.Field + Message respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r Error) RawJSON() string { return r.JSON.raw } +func (r *Error) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +type BatchGetResponse struct { + // Batch ID used to retrieve or cancel the job. + ID string `json:"id" api:"required"` + // Reserved and used credits. + Credits BatchGetResponseCredits `json:"credits" api:"required"` + // Why the batch failed. + Error Error `json:"error" api:"required"` + // Page failures grouped by error code. + Errors []ErrorCount `json:"errors" api:"required"` + // Submission counts. + Input BatchGetResponseInput `json:"input" api:"required"` + // Rejected URLs, up to 100. These are not charged. + InvalidURLs []BatchGetResponseInvalidURL `json:"invalid_urls" api:"required"` + // How pages are selected. + // + // Any of "scrape", "crawl". + Mode BatchGetResponseMode `json:"mode" api:"required"` + // Current processing counts. Use `status` to check completion. + Progress BatchGetResponseProgress `json:"progress" api:"required"` + // Download links available when the batch finishes. GET /batch/{batch_id}/results + // serves the same records as paginated JSON. + Results BatchGetResponseResults `json:"results" api:"required"` + // Current state. `completed`, `cancelled`, and `failed` are final. + // + // Any of "queued", "running", "cancelling", "completed", "cancelled", "failed". + Status BatchGetResponseStatus `json:"status" api:"required"` + // Tags stored on the batch at submission. + Tags []string `json:"tags" api:"required"` + Timing BatchGetResponseTiming `json:"timing" api:"required"` + // Output format. + // + // Any of "markdown", "html". + Type BatchGetResponseType `json:"type" api:"required"` + // API key usage for this request. + KeyMetadata BatchGetResponseKeyMetadata `json:"key_metadata"` + // Webhook signing secret. Also returned by GET /batch/{batch_id}. + WebhookSecret string `json:"webhook_secret"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + ID respjson.Field + Credits respjson.Field + Error respjson.Field + Errors respjson.Field + Input respjson.Field + InvalidURLs respjson.Field + Mode respjson.Field + Progress respjson.Field + Results respjson.Field + Status respjson.Field + Tags respjson.Field + Timing respjson.Field + Type respjson.Field + KeyMetadata respjson.Field + WebhookSecret respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchGetResponse) RawJSON() string { return r.JSON.raw } +func (r *BatchGetResponse) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Reserved and used credits. +type BatchGetResponseCredits struct { + // Credits used by successful pages. + Charged int64 `json:"charged" api:"required"` + // Credits reserved when the batch was accepted. + Estimated int64 `json:"estimated" api:"required"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Charged respjson.Field + Estimated respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchGetResponseCredits) RawJSON() string { return r.JSON.raw } +func (r *BatchGetResponseCredits) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Submission counts. +type BatchGetResponseInput struct { + // Pages accepted, or the crawl page limit. Credits are reserved for this count. + Accepted int64 `json:"accepted" api:"required"` + // Duplicate URL and `itemId` pairs skipped. Always 0 for crawls. + Duplicates int64 `json:"duplicates" api:"required"` + // Pages rejected during validation. + Invalid int64 `json:"invalid" api:"required"` + // Pages submitted before validation. For a crawl, the page limit. + Submitted int64 `json:"submitted" api:"required"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Accepted respjson.Field + Duplicates respjson.Field + Invalid respjson.Field + Submitted respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchGetResponseInput) RawJSON() string { return r.JSON.raw } +func (r *BatchGetResponseInput) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +type BatchGetResponseInvalidURL struct { + // Why it was rejected. + Reason string `json:"reason" api:"required"` + // Rejected URL. + URL string `json:"url" api:"required"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Reason respjson.Field + URL respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchGetResponseInvalidURL) RawJSON() string { return r.JSON.raw } +func (r *BatchGetResponseInvalidURL) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// How pages are selected. +type BatchGetResponseMode string + +const ( + BatchGetResponseModeScrape BatchGetResponseMode = "scrape" + BatchGetResponseModeCrawl BatchGetResponseMode = "crawl" +) + +// Current processing counts. Use `status` to check completion. +type BatchGetResponseProgress struct { + // Pages that could not be scraped. + Failed int64 `json:"failed" api:"required"` + // Accepted pages not yet attempted. Always 0 once the batch completes; a crawl can + // finish under its page limit when the site has no more reachable pages. + Pending int64 `json:"pending" api:"required"` + // Pages scraped successfully. + Succeeded int64 `json:"succeeded" api:"required"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Failed respjson.Field + Pending respjson.Field + Succeeded respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchGetResponseProgress) RawJSON() string { return r.JSON.raw } +func (r *BatchGetResponseProgress) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Download links available when the batch finishes. GET /batch/{batch_id}/results +// serves the same records as paginated JSON. +type BatchGetResponseResults struct { + // When the download URLs expire. + ExpiresAt string `json:"expires_at" api:"required"` + // Result files. Order is not guaranteed. + Files []BatchGetResponseResultsFile `json:"files" api:"required"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + ExpiresAt respjson.Field + Files respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchGetResponseResults) RawJSON() string { return r.JSON.raw } +func (r *BatchGetResponseResults) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +type BatchGetResponseResultsFile struct { + // Compressed file size in bytes. + Bytes int64 `json:"bytes" api:"required"` + // Results in this file. + Items int64 `json:"items" api:"required"` + // Temporary URL for a gzipped NDJSON file. + URL string `json:"url" api:"required"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Bytes respjson.Field + Items respjson.Field + URL respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchGetResponseResultsFile) RawJSON() string { return r.JSON.raw } +func (r *BatchGetResponseResultsFile) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Current state. `completed`, `cancelled`, and `failed` are final. +type BatchGetResponseStatus string + +const ( + BatchGetResponseStatusQueued BatchGetResponseStatus = "queued" + BatchGetResponseStatusRunning BatchGetResponseStatus = "running" + BatchGetResponseStatusCancelling BatchGetResponseStatus = "cancelling" + BatchGetResponseStatusCompleted BatchGetResponseStatus = "completed" + BatchGetResponseStatusCancelled BatchGetResponseStatus = "cancelled" + BatchGetResponseStatusFailed BatchGetResponseStatus = "failed" +) + +type BatchGetResponseTiming struct { + // When processing finished. Null while active. + CompletedAt string `json:"completed_at" api:"required"` + // When the batch was created. + CreatedAt string `json:"created_at" api:"required"` + // When processing started. Null while queued. + StartedAt string `json:"started_at" api:"required"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + CompletedAt respjson.Field + CreatedAt respjson.Field + StartedAt respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchGetResponseTiming) RawJSON() string { return r.JSON.raw } +func (r *BatchGetResponseTiming) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Output format. +type BatchGetResponseType string + +const ( + BatchGetResponseTypeMarkdown BatchGetResponseType = "markdown" + BatchGetResponseTypeHTML BatchGetResponseType = "html" +) + +// API key usage for this request. +type BatchGetResponseKeyMetadata struct { + // The number of credits consumed by this request. + CreditsConsumed int64 `json:"credits_consumed" api:"required"` + // The number of credits remaining for your organization after this request. + CreditsRemaining int64 `json:"credits_remaining" api:"required"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + CreditsConsumed respjson.Field + CreditsRemaining respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchGetResponseKeyMetadata) RawJSON() string { return r.JSON.raw } +func (r *BatchGetResponseKeyMetadata) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +type BatchListResponse struct { + // Batches on this page. + Data []BatchListResponseData `json:"data"` + // Whether another page is available. + HasMore bool `json:"has_more"` + // Metadata about the API key used for the request. Included in every response + // whenever a valid API key is provided, even when the response status is not 200. + KeyMetadata BatchListResponseKeyMetadata `json:"key_metadata"` + // Cursor for the next page. + NextCursor string `json:"next_cursor" api:"nullable"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Data respjson.Field + HasMore respjson.Field + KeyMetadata respjson.Field + NextCursor respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchListResponse) RawJSON() string { return r.JSON.raw } +func (r *BatchListResponse) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// An asynchronous web scraping job. +type BatchListResponseData struct { + // Batch ID used to retrieve or cancel the job. + ID string `json:"id" api:"required"` + // Reserved and used credits. + Credits BatchListResponseDataCredits `json:"credits" api:"required"` + // Why the batch failed. + Error Error `json:"error" api:"required"` + // Page failures grouped by error code. + Errors []ErrorCount `json:"errors" api:"required"` + // Submission counts. + Input BatchListResponseDataInput `json:"input" api:"required"` + // How pages are selected. + // + // Any of "scrape", "crawl". + Mode string `json:"mode" api:"required"` + // Current processing counts. Use `status` to check completion. + Progress BatchListResponseDataProgress `json:"progress" api:"required"` + // Download links available when the batch finishes. GET /batch/{batch_id}/results + // serves the same records as paginated JSON. + Results BatchListResponseDataResults `json:"results" api:"required"` + // Current state. `completed`, `cancelled`, and `failed` are final. + // + // Any of "queued", "running", "cancelling", "completed", "cancelled", "failed". + Status string `json:"status" api:"required"` + // Tags stored on the batch at submission. + Tags []string `json:"tags" api:"required"` + Timing BatchListResponseDataTiming `json:"timing" api:"required"` + // Output format. + // + // Any of "markdown", "html". + Type string `json:"type" api:"required"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + ID respjson.Field + Credits respjson.Field + Error respjson.Field + Errors respjson.Field + Input respjson.Field + Mode respjson.Field + Progress respjson.Field + Results respjson.Field + Status respjson.Field + Tags respjson.Field + Timing respjson.Field + Type respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchListResponseData) RawJSON() string { return r.JSON.raw } +func (r *BatchListResponseData) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Reserved and used credits. +type BatchListResponseDataCredits struct { + // Credits used by successful pages. + Charged int64 `json:"charged" api:"required"` + // Credits reserved when the batch was accepted. + Estimated int64 `json:"estimated" api:"required"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Charged respjson.Field + Estimated respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchListResponseDataCredits) RawJSON() string { return r.JSON.raw } +func (r *BatchListResponseDataCredits) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Submission counts. +type BatchListResponseDataInput struct { + // Pages accepted, or the crawl page limit. Credits are reserved for this count. + Accepted int64 `json:"accepted" api:"required"` + // Duplicate URL and `itemId` pairs skipped. Always 0 for crawls. + Duplicates int64 `json:"duplicates" api:"required"` + // Pages rejected during validation. + Invalid int64 `json:"invalid" api:"required"` + // Pages submitted before validation. For a crawl, the page limit. + Submitted int64 `json:"submitted" api:"required"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Accepted respjson.Field + Duplicates respjson.Field + Invalid respjson.Field + Submitted respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchListResponseDataInput) RawJSON() string { return r.JSON.raw } +func (r *BatchListResponseDataInput) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Current processing counts. Use `status` to check completion. +type BatchListResponseDataProgress struct { + // Pages that could not be scraped. + Failed int64 `json:"failed" api:"required"` + // Accepted pages not yet attempted. Always 0 once the batch completes; a crawl can + // finish under its page limit when the site has no more reachable pages. + Pending int64 `json:"pending" api:"required"` + // Pages scraped successfully. + Succeeded int64 `json:"succeeded" api:"required"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Failed respjson.Field + Pending respjson.Field + Succeeded respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchListResponseDataProgress) RawJSON() string { return r.JSON.raw } +func (r *BatchListResponseDataProgress) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Download links available when the batch finishes. GET /batch/{batch_id}/results +// serves the same records as paginated JSON. +type BatchListResponseDataResults struct { + // When the download URLs expire. + ExpiresAt string `json:"expires_at" api:"required"` + // Result files. Order is not guaranteed. + Files []BatchListResponseDataResultsFile `json:"files" api:"required"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + ExpiresAt respjson.Field + Files respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchListResponseDataResults) RawJSON() string { return r.JSON.raw } +func (r *BatchListResponseDataResults) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +type BatchListResponseDataResultsFile struct { + // Compressed file size in bytes. + Bytes int64 `json:"bytes" api:"required"` + // Results in this file. + Items int64 `json:"items" api:"required"` + // Temporary URL for a gzipped NDJSON file. + URL string `json:"url" api:"required"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Bytes respjson.Field + Items respjson.Field + URL respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchListResponseDataResultsFile) RawJSON() string { return r.JSON.raw } +func (r *BatchListResponseDataResultsFile) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +type BatchListResponseDataTiming struct { + // When processing finished. Null while active. + CompletedAt string `json:"completed_at" api:"required"` + // When the batch was created. + CreatedAt string `json:"created_at" api:"required"` + // When processing started. Null while queued. + StartedAt string `json:"started_at" api:"required"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + CompletedAt respjson.Field + CreatedAt respjson.Field + StartedAt respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchListResponseDataTiming) RawJSON() string { return r.JSON.raw } +func (r *BatchListResponseDataTiming) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Metadata about the API key used for the request. Included in every response +// whenever a valid API key is provided, even when the response status is not 200. +type BatchListResponseKeyMetadata struct { + // The number of credits consumed by this request. + CreditsConsumed int64 `json:"credits_consumed" api:"required"` + // The number of credits remaining for your organization after this request. + CreditsRemaining int64 `json:"credits_remaining" api:"required"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + CreditsConsumed respjson.Field + CreditsRemaining respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchListResponseKeyMetadata) RawJSON() string { return r.JSON.raw } +func (r *BatchListResponseKeyMetadata) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +type BatchCancelResponse struct { + // Batch ID used to retrieve or cancel the job. + ID string `json:"id" api:"required"` + // Reserved and used credits. + Credits BatchCancelResponseCredits `json:"credits" api:"required"` + // Why the batch failed. + Error Error `json:"error" api:"required"` + // Page failures grouped by error code. + Errors []ErrorCount `json:"errors" api:"required"` + // Submission counts. + Input BatchCancelResponseInput `json:"input" api:"required"` + // How pages are selected. + // + // Any of "scrape", "crawl". + Mode BatchCancelResponseMode `json:"mode" api:"required"` + // Current processing counts. Use `status` to check completion. + Progress BatchCancelResponseProgress `json:"progress" api:"required"` + // Download links available when the batch finishes. GET /batch/{batch_id}/results + // serves the same records as paginated JSON. + Results BatchCancelResponseResults `json:"results" api:"required"` + // Current state. `completed`, `cancelled`, and `failed` are final. + // + // Any of "queued", "running", "cancelling", "completed", "cancelled", "failed". + Status BatchCancelResponseStatus `json:"status" api:"required"` + // Tags stored on the batch at submission. + Tags []string `json:"tags" api:"required"` + Timing BatchCancelResponseTiming `json:"timing" api:"required"` + // Output format. + // + // Any of "markdown", "html". + Type BatchCancelResponseType `json:"type" api:"required"` + // API key usage for this request. + KeyMetadata BatchCancelResponseKeyMetadata `json:"key_metadata"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + ID respjson.Field + Credits respjson.Field + Error respjson.Field + Errors respjson.Field + Input respjson.Field + Mode respjson.Field + Progress respjson.Field + Results respjson.Field + Status respjson.Field + Tags respjson.Field + Timing respjson.Field + Type respjson.Field + KeyMetadata respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchCancelResponse) RawJSON() string { return r.JSON.raw } +func (r *BatchCancelResponse) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Reserved and used credits. +type BatchCancelResponseCredits struct { + // Credits used by successful pages. + Charged int64 `json:"charged" api:"required"` + // Credits reserved when the batch was accepted. + Estimated int64 `json:"estimated" api:"required"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Charged respjson.Field + Estimated respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchCancelResponseCredits) RawJSON() string { return r.JSON.raw } +func (r *BatchCancelResponseCredits) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Submission counts. +type BatchCancelResponseInput struct { + // Pages accepted, or the crawl page limit. Credits are reserved for this count. + Accepted int64 `json:"accepted" api:"required"` + // Duplicate URL and `itemId` pairs skipped. Always 0 for crawls. + Duplicates int64 `json:"duplicates" api:"required"` + // Pages rejected during validation. + Invalid int64 `json:"invalid" api:"required"` + // Pages submitted before validation. For a crawl, the page limit. + Submitted int64 `json:"submitted" api:"required"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Accepted respjson.Field + Duplicates respjson.Field + Invalid respjson.Field + Submitted respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchCancelResponseInput) RawJSON() string { return r.JSON.raw } +func (r *BatchCancelResponseInput) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// How pages are selected. +type BatchCancelResponseMode string + +const ( + BatchCancelResponseModeScrape BatchCancelResponseMode = "scrape" + BatchCancelResponseModeCrawl BatchCancelResponseMode = "crawl" +) + +// Current processing counts. Use `status` to check completion. +type BatchCancelResponseProgress struct { + // Pages that could not be scraped. + Failed int64 `json:"failed" api:"required"` + // Accepted pages not yet attempted. Always 0 once the batch completes; a crawl can + // finish under its page limit when the site has no more reachable pages. + Pending int64 `json:"pending" api:"required"` + // Pages scraped successfully. + Succeeded int64 `json:"succeeded" api:"required"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Failed respjson.Field + Pending respjson.Field + Succeeded respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchCancelResponseProgress) RawJSON() string { return r.JSON.raw } +func (r *BatchCancelResponseProgress) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Download links available when the batch finishes. GET /batch/{batch_id}/results +// serves the same records as paginated JSON. +type BatchCancelResponseResults struct { + // When the download URLs expire. + ExpiresAt string `json:"expires_at" api:"required"` + // Result files. Order is not guaranteed. + Files []BatchCancelResponseResultsFile `json:"files" api:"required"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + ExpiresAt respjson.Field + Files respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchCancelResponseResults) RawJSON() string { return r.JSON.raw } +func (r *BatchCancelResponseResults) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +type BatchCancelResponseResultsFile struct { + // Compressed file size in bytes. + Bytes int64 `json:"bytes" api:"required"` + // Results in this file. + Items int64 `json:"items" api:"required"` + // Temporary URL for a gzipped NDJSON file. + URL string `json:"url" api:"required"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Bytes respjson.Field + Items respjson.Field + URL respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchCancelResponseResultsFile) RawJSON() string { return r.JSON.raw } +func (r *BatchCancelResponseResultsFile) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Current state. `completed`, `cancelled`, and `failed` are final. +type BatchCancelResponseStatus string + +const ( + BatchCancelResponseStatusQueued BatchCancelResponseStatus = "queued" + BatchCancelResponseStatusRunning BatchCancelResponseStatus = "running" + BatchCancelResponseStatusCancelling BatchCancelResponseStatus = "cancelling" + BatchCancelResponseStatusCompleted BatchCancelResponseStatus = "completed" + BatchCancelResponseStatusCancelled BatchCancelResponseStatus = "cancelled" + BatchCancelResponseStatusFailed BatchCancelResponseStatus = "failed" +) + +type BatchCancelResponseTiming struct { + // When processing finished. Null while active. + CompletedAt string `json:"completed_at" api:"required"` + // When the batch was created. + CreatedAt string `json:"created_at" api:"required"` + // When processing started. Null while queued. + StartedAt string `json:"started_at" api:"required"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + CompletedAt respjson.Field + CreatedAt respjson.Field + StartedAt respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchCancelResponseTiming) RawJSON() string { return r.JSON.raw } +func (r *BatchCancelResponseTiming) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Output format. +type BatchCancelResponseType string + +const ( + BatchCancelResponseTypeMarkdown BatchCancelResponseType = "markdown" + BatchCancelResponseTypeHTML BatchCancelResponseType = "html" +) + +// API key usage for this request. +type BatchCancelResponseKeyMetadata struct { + // The number of credits consumed by this request. + CreditsConsumed int64 `json:"credits_consumed" api:"required"` + // The number of credits remaining for your organization after this request. + CreditsRemaining int64 `json:"credits_remaining" api:"required"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + CreditsConsumed respjson.Field + CreditsRemaining respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchCancelResponseKeyMetadata) RawJSON() string { return r.JSON.raw } +func (r *BatchCancelResponseKeyMetadata) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +type BatchGetResultsResponse struct { + // Result records on this page. + Data []BatchGetResultsResponseDataUnion `json:"data"` + // Whether another page is available. + HasMore bool `json:"has_more"` + // Metadata about the API key used for the request. Included in every response + // whenever a valid API key is provided, even when the response status is not 200. + KeyMetadata BatchGetResultsResponseKeyMetadata `json:"key_metadata"` + // Cursor for the next page. + NextCursor string `json:"next_cursor" api:"nullable"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Data respjson.Field + HasMore respjson.Field + KeyMetadata respjson.Field + NextCursor respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchGetResultsResponse) RawJSON() string { return r.JSON.raw } +func (r *BatchGetResultsResponse) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// BatchGetResultsResponseDataUnion contains all possible properties and values +// from [BatchGetResultsResponseDataOk], [BatchGetResultsResponseDataError]. +// +// Use the [BatchGetResultsResponseDataUnion.AsAny] method to switch on the +// variant. +// +// Use the methods beginning with 'As' to cast the union to one of its variants. +type BatchGetResultsResponseDataUnion struct { + // This field is from variant [BatchGetResultsResponseDataOk]. + FinalURL string `json:"final_url"` + // This field is from variant [BatchGetResultsResponseDataOk]. + HTTPStatus int64 `json:"http_status"` + // This field is from variant [BatchGetResultsResponseDataOk]. + Metadata BatchGetResultsResponseDataOkMetadata `json:"metadata"` + // Any of "ok", "error". + Status string `json:"status"` + URL string `json:"url"` + // This field is from variant [BatchGetResultsResponseDataOk]. + HTML string `json:"html"` + ItemID string `json:"itemId"` + // This field is from variant [BatchGetResultsResponseDataOk]. + Markdown string `json:"markdown"` + Meta any `json:"meta"` + // This field is from variant [BatchGetResultsResponseDataError]. + ErrorCode string `json:"error_code"` + // This field is from variant [BatchGetResultsResponseDataError]. + Message string `json:"message"` + JSON struct { + FinalURL respjson.Field + HTTPStatus respjson.Field + Metadata respjson.Field + Status respjson.Field + URL respjson.Field + HTML respjson.Field + ItemID respjson.Field + Markdown respjson.Field + Meta respjson.Field + ErrorCode respjson.Field + Message respjson.Field + raw string + } `json:"-"` +} + +// anyBatchGetResultsResponseData is implemented by each variant of +// [BatchGetResultsResponseDataUnion] to add type safety for the return type of +// [BatchGetResultsResponseDataUnion.AsAny] +type anyBatchGetResultsResponseData interface { + implBatchGetResultsResponseDataUnion() +} + +func (BatchGetResultsResponseDataOk) implBatchGetResultsResponseDataUnion() {} +func (BatchGetResultsResponseDataError) implBatchGetResultsResponseDataUnion() {} + +// Use the following switch statement to find the correct variant +// +// switch variant := BatchGetResultsResponseDataUnion.AsAny().(type) { +// case contextdev.BatchGetResultsResponseDataOk: +// case contextdev.BatchGetResultsResponseDataError: +// default: +// fmt.Errorf("no variant present") +// } +func (u BatchGetResultsResponseDataUnion) AsAny() anyBatchGetResultsResponseData { + switch u.Status { + case "ok": + return u.AsOk() + case "error": + return u.AsError() + } + return nil +} + +func (u BatchGetResultsResponseDataUnion) AsOk() (v BatchGetResultsResponseDataOk) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return +} + +func (u BatchGetResultsResponseDataUnion) AsError() (v BatchGetResultsResponseDataError) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return +} + +// Returns the unmodified JSON received from the API +func (u BatchGetResultsResponseDataUnion) RawJSON() string { return u.JSON.raw } + +func (r *BatchGetResultsResponseDataUnion) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// A page the batch fetched successfully. +type BatchGetResultsResponseDataOk struct { + // URL the content was read from, after redirects. + FinalURL string `json:"final_url" api:"required"` + // HTTP status of the final response, when known. + HTTPStatus int64 `json:"http_status" api:"required"` + // Metadata extracted from the scraped page HTML. + Metadata BatchGetResultsResponseDataOkMetadata `json:"metadata" api:"required"` + // The page was scraped. + Status constant.Ok `json:"status" default:"ok"` + // URL as submitted, or as discovered by the crawl. + URL string `json:"url" api:"required"` + // Raw page HTML. Present on html batches. + HTML string `json:"html"` + // Caller-supplied identifier echoed from submission. + ItemID string `json:"itemId"` + // Page content as Markdown. Present on markdown batches. + Markdown string `json:"markdown"` + // Caller-supplied metadata echoed from submission. + Meta map[string]any `json:"meta"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + FinalURL respjson.Field + HTTPStatus respjson.Field + Metadata respjson.Field + Status respjson.Field + URL respjson.Field + HTML respjson.Field + ItemID respjson.Field + Markdown respjson.Field + Meta respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchGetResultsResponseDataOk) RawJSON() string { return r.JSON.raw } +func (r *BatchGetResultsResponseDataOk) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Metadata extracted from the scraped page HTML. +type BatchGetResultsResponseDataOkMetadata struct { + // Final URL scraped after redirects or scraper fallback, when known. Falls back to + // sourceUrl when unavailable. + FinalURL string `json:"finalUrl" api:"required"` + // Original URL requested by the caller. + SourceURL string `json:"sourceUrl" api:"required"` + // Additional non-social meta tags not promoted to top-level metadata fields. + AdditionalMeta map[string]BatchGetResultsResponseDataOkMetadataAdditionalMetaUnion `json:"additionalMeta"` + // Resolved alternate links from link rel=alternate tags. + Alternates []BatchGetResultsResponseDataOkMetadataAlternate `json:"alternates"` + // Author metadata, when present. + Author string `json:"author"` + // Resolved canonical URL, when present. + CanonicalURL string `json:"canonicalUrl"` + // Best description extracted from standard, Open Graph, or Twitter metadata. + Description string `json:"description"` + // Resolved favicon URL, when present. + Favicon string `json:"favicon"` + // Primary resolved preview image from Open Graph, Twitter, or image metadata. + Image string `json:"image"` + // JSON-LD structured data blocks parsed from the page. + JsonLd []map[string]any `json:"jsonLd"` + // Keywords extracted from the page's keywords meta tag. + Keywords []string `json:"keywords"` + // Language extracted from html lang or language meta tags. + Language string `json:"language"` + // Modified timestamp/date from page metadata, when present. + ModifiedTime string `json:"modifiedTime"` + // Open Graph metadata with the og: prefix removed and keys camel-cased. + OpenGraph map[string]BatchGetResultsResponseDataOkMetadataOpenGraphUnion `json:"openGraph"` + // Published timestamp/date from page metadata, when present. + PublishedTime string `json:"publishedTime"` + // Robots meta directive, when present. + Robots string `json:"robots"` + // Site or application name from page metadata. + SiteName string `json:"siteName"` + // Best title extracted from the page. + Title string `json:"title"` + // Twitter card metadata with the twitter: prefix removed and keys camel-cased. + Twitter map[string]BatchGetResultsResponseDataOkMetadataTwitterUnion `json:"twitter"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + FinalURL respjson.Field + SourceURL respjson.Field + AdditionalMeta respjson.Field + Alternates respjson.Field + Author respjson.Field + CanonicalURL respjson.Field + Description respjson.Field + Favicon respjson.Field + Image respjson.Field + JsonLd respjson.Field + Keywords respjson.Field + Language respjson.Field + ModifiedTime respjson.Field + OpenGraph respjson.Field + PublishedTime respjson.Field + Robots respjson.Field + SiteName respjson.Field + Title respjson.Field + Twitter respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchGetResultsResponseDataOkMetadata) RawJSON() string { return r.JSON.raw } +func (r *BatchGetResultsResponseDataOkMetadata) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// BatchGetResultsResponseDataOkMetadataAdditionalMetaUnion contains all possible +// properties and values from [string], [[]string]. +// +// Use the methods beginning with 'As' to cast the union to one of its variants. +// +// If the underlying value is not a json object, one of the following properties +// will be valid: OfString OfStringArray] +type BatchGetResultsResponseDataOkMetadataAdditionalMetaUnion struct { + // This field will be present if the value is a [string] instead of an object. + OfString string `json:",inline"` + // This field will be present if the value is a [[]string] instead of an object. + OfStringArray []string `json:",inline"` + JSON struct { + OfString respjson.Field + OfStringArray respjson.Field + raw string + } `json:"-"` +} + +func (u BatchGetResultsResponseDataOkMetadataAdditionalMetaUnion) AsString() (v string) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return +} + +func (u BatchGetResultsResponseDataOkMetadataAdditionalMetaUnion) AsStringArray() (v []string) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return +} + +// Returns the unmodified JSON received from the API +func (u BatchGetResultsResponseDataOkMetadataAdditionalMetaUnion) RawJSON() string { return u.JSON.raw } + +func (r *BatchGetResultsResponseDataOkMetadataAdditionalMetaUnion) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +type BatchGetResultsResponseDataOkMetadataAlternate struct { + // Resolved alternate URL. + Href string `json:"href" api:"required"` + // Language or locale for the alternate URL, when present. + Hreflang string `json:"hreflang"` + // Alternate resource title, when present. + Title string `json:"title"` + // Alternate resource MIME type, when present. + Type string `json:"type"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Href respjson.Field + Hreflang respjson.Field + Title respjson.Field + Type respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchGetResultsResponseDataOkMetadataAlternate) RawJSON() string { return r.JSON.raw } +func (r *BatchGetResultsResponseDataOkMetadataAlternate) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// BatchGetResultsResponseDataOkMetadataOpenGraphUnion contains all possible +// properties and values from [string], [[]string]. +// +// Use the methods beginning with 'As' to cast the union to one of its variants. +// +// If the underlying value is not a json object, one of the following properties +// will be valid: OfString OfStringArray] +type BatchGetResultsResponseDataOkMetadataOpenGraphUnion struct { + // This field will be present if the value is a [string] instead of an object. + OfString string `json:",inline"` + // This field will be present if the value is a [[]string] instead of an object. + OfStringArray []string `json:",inline"` + JSON struct { + OfString respjson.Field + OfStringArray respjson.Field + raw string + } `json:"-"` +} + +func (u BatchGetResultsResponseDataOkMetadataOpenGraphUnion) AsString() (v string) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return +} + +func (u BatchGetResultsResponseDataOkMetadataOpenGraphUnion) AsStringArray() (v []string) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return +} + +// Returns the unmodified JSON received from the API +func (u BatchGetResultsResponseDataOkMetadataOpenGraphUnion) RawJSON() string { return u.JSON.raw } + +func (r *BatchGetResultsResponseDataOkMetadataOpenGraphUnion) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// BatchGetResultsResponseDataOkMetadataTwitterUnion contains all possible +// properties and values from [string], [[]string]. +// +// Use the methods beginning with 'As' to cast the union to one of its variants. +// +// If the underlying value is not a json object, one of the following properties +// will be valid: OfString OfStringArray] +type BatchGetResultsResponseDataOkMetadataTwitterUnion struct { + // This field will be present if the value is a [string] instead of an object. + OfString string `json:",inline"` + // This field will be present if the value is a [[]string] instead of an object. + OfStringArray []string `json:",inline"` + JSON struct { + OfString respjson.Field + OfStringArray respjson.Field + raw string + } `json:"-"` +} + +func (u BatchGetResultsResponseDataOkMetadataTwitterUnion) AsString() (v string) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return +} + +func (u BatchGetResultsResponseDataOkMetadataTwitterUnion) AsStringArray() (v []string) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return +} + +// Returns the unmodified JSON received from the API +func (u BatchGetResultsResponseDataOkMetadataTwitterUnion) RawJSON() string { return u.JSON.raw } + +func (r *BatchGetResultsResponseDataOkMetadataTwitterUnion) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// A page the batch could not fetch. +type BatchGetResultsResponseDataError struct { + // Why the page failed. + ErrorCode string `json:"error_code" api:"required"` + // Human-readable failure detail. + Message string `json:"message" api:"required"` + // The page could not be scraped. + Status constant.Error `json:"status" default:"error"` + // URL as submitted, or as discovered by the crawl. + URL string `json:"url" api:"required"` + // Caller-supplied identifier echoed from submission. + ItemID string `json:"itemId"` + // Caller-supplied metadata echoed from submission. + Meta map[string]any `json:"meta"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + ErrorCode respjson.Field + Message respjson.Field + Status respjson.Field + URL respjson.Field + ItemID respjson.Field + Meta respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchGetResultsResponseDataError) RawJSON() string { return r.JSON.raw } +func (r *BatchGetResultsResponseDataError) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Metadata about the API key used for the request. Included in every response +// whenever a valid API key is provided, even when the response status is not 200. +type BatchGetResultsResponseKeyMetadata struct { + // The number of credits consumed by this request. + CreditsConsumed int64 `json:"credits_consumed" api:"required"` + // The number of credits remaining for your organization after this request. + CreditsRemaining int64 `json:"credits_remaining" api:"required"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + CreditsConsumed respjson.Field + CreditsRemaining respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchGetResultsResponseKeyMetadata) RawJSON() string { return r.JSON.raw } +func (r *BatchGetResultsResponseKeyMetadata) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +type BatchSubmitResponse struct { + // HTTP status code. + // + // Any of 200. + Code int64 `json:"code" api:"required"` + // Additional response details. + Metadata BatchSubmitResponseMetadata `json:"metadata" api:"required"` + // Retrieved person profile. + Person BatchSubmitResponsePerson `json:"person" api:"required"` + // Response status. + // + // Any of "ok". + Status BatchSubmitResponseStatus `json:"status" api:"required"` + // Metadata about the API key used for the request. Included in every response + // whenever a valid API key is provided, even when the response status is not 200. + KeyMetadata BatchSubmitResponseKeyMetadata `json:"key_metadata"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Code respjson.Field + Metadata respjson.Field + Person respjson.Field + Status respjson.Field + KeyMetadata respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchSubmitResponse) RawJSON() string { return r.JSON.raw } +func (r *BatchSubmitResponse) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Additional response details. +type BatchSubmitResponseMetadata struct { + // Identifiers returned for the person. + Identifiers BatchSubmitResponseMetadataIdentifiers `json:"identifiers" api:"required"` + // Source categories checked. + // + // Any of "linkedin", "cv", "manual", "github", "other". + SourcesAttempted []string `json:"sourcesAttempted" api:"required"` + // Source categories with data. + // + // Any of "linkedin", "cv", "manual", "github", "other". + SourcesSucceeded []string `json:"sourcesSucceeded" api:"required"` + // URLs reviewed for this profile. + URLsAnalyzed []string `json:"urlsAnalyzed" api:"required" format:"uri"` + // Personal website URL, when found. + PersonalWebsiteURL string `json:"personalWebsiteUrl" format:"uri"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Identifiers respjson.Field + SourcesAttempted respjson.Field + SourcesSucceeded respjson.Field + URLsAnalyzed respjson.Field + PersonalWebsiteURL respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchSubmitResponseMetadata) RawJSON() string { return r.JSON.raw } +func (r *BatchSubmitResponseMetadata) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Identifiers returned for the person. +type BatchSubmitResponseMetadataIdentifiers struct { + // LinkedIn profile URL. + LinkedinURL string `json:"linkedinUrl" format:"uri"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + LinkedinURL respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchSubmitResponseMetadataIdentifiers) RawJSON() string { return r.JSON.raw } +func (r *BatchSubmitResponseMetadataIdentifiers) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Retrieved person profile. +type BatchSubmitResponsePerson struct { + // Education history. + Education []BatchSubmitResponsePersonEducation `json:"education" api:"required"` + // Work history. + Experience []BatchSubmitResponsePersonExperience `json:"experience" api:"required"` + // Core profile details. + Profile BatchSubmitResponsePersonProfile `json:"profile" api:"required"` + // Listed skills. + Skills []BatchSubmitResponsePersonSkill `json:"skills" api:"required"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Education respjson.Field + Experience respjson.Field + Profile respjson.Field + Skills respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchSubmitResponsePerson) RawJSON() string { return r.JSON.raw } +func (r *BatchSubmitResponsePerson) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +type BatchSubmitResponsePersonEducation struct { + // School or institution name. + Institution BatchSubmitResponsePersonEducationInstitution `json:"institution" api:"required"` + // Education dates. + Dates BatchSubmitResponsePersonEducationDates `json:"dates"` + // Additional education details. + Description string `json:"description"` + // Area of study. + FieldOfStudy string `json:"fieldOfStudy"` + // Degree, certificate, or credential. + Qualification string `json:"qualification"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Institution respjson.Field + Dates respjson.Field + Description respjson.Field + FieldOfStudy respjson.Field + Qualification respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchSubmitResponsePersonEducation) RawJSON() string { return r.JSON.raw } +func (r *BatchSubmitResponsePersonEducation) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// School or institution name. +type BatchSubmitResponsePersonEducationInstitution struct { + // Display name. + Display string `json:"display" api:"required"` + // Standardized name, when available. + Normalized string `json:"normalized"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Display respjson.Field + Normalized respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchSubmitResponsePersonEducationInstitution) RawJSON() string { return r.JSON.raw } +func (r *BatchSubmitResponsePersonEducationInstitution) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Education dates. +type BatchSubmitResponsePersonEducationDates struct { + // End date, when known. + EndDate BatchSubmitResponsePersonEducationDatesEndDate `json:"endDate"` + // Whether the entry is current. + IsCurrent bool `json:"isCurrent"` + // Start date, when known. + StartDate BatchSubmitResponsePersonEducationDatesStartDate `json:"startDate"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + EndDate respjson.Field + IsCurrent respjson.Field + StartDate respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchSubmitResponsePersonEducationDates) RawJSON() string { return r.JSON.raw } +func (r *BatchSubmitResponsePersonEducationDates) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// End date, when known. +type BatchSubmitResponsePersonEducationDatesEndDate struct { + // Year value. + Year int64 `json:"year" api:"required"` + // Day value, when known. + Day int64 `json:"day"` + // Month value, when known. + Month int64 `json:"month"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Year respjson.Field + Day respjson.Field + Month respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchSubmitResponsePersonEducationDatesEndDate) RawJSON() string { return r.JSON.raw } +func (r *BatchSubmitResponsePersonEducationDatesEndDate) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Start date, when known. +type BatchSubmitResponsePersonEducationDatesStartDate struct { + // Year value. + Year int64 `json:"year" api:"required"` + // Day value, when known. + Day int64 `json:"day"` + // Month value, when known. + Month int64 `json:"month"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Year respjson.Field + Day respjson.Field + Month respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchSubmitResponsePersonEducationDatesStartDate) RawJSON() string { return r.JSON.raw } +func (r *BatchSubmitResponsePersonEducationDatesStartDate) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +type BatchSubmitResponsePersonExperience struct { + // Company or organization name. + Company BatchSubmitResponsePersonExperienceCompany `json:"company" api:"required"` + // Role or job title. + Title string `json:"title" api:"required"` + // Role dates. + Dates BatchSubmitResponsePersonExperienceDates `json:"dates"` + // Role description. + Description string `json:"description"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Company respjson.Field + Title respjson.Field + Dates respjson.Field + Description respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchSubmitResponsePersonExperience) RawJSON() string { return r.JSON.raw } +func (r *BatchSubmitResponsePersonExperience) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Company or organization name. +type BatchSubmitResponsePersonExperienceCompany struct { + // Display name. + Display string `json:"display" api:"required"` + // Standardized name, when available. + Normalized string `json:"normalized"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Display respjson.Field + Normalized respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchSubmitResponsePersonExperienceCompany) RawJSON() string { return r.JSON.raw } +func (r *BatchSubmitResponsePersonExperienceCompany) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Role dates. +type BatchSubmitResponsePersonExperienceDates struct { + // End date, when known. + EndDate BatchSubmitResponsePersonExperienceDatesEndDate `json:"endDate"` + // Whether the entry is current. + IsCurrent bool `json:"isCurrent"` + // Start date, when known. + StartDate BatchSubmitResponsePersonExperienceDatesStartDate `json:"startDate"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + EndDate respjson.Field + IsCurrent respjson.Field + StartDate respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchSubmitResponsePersonExperienceDates) RawJSON() string { return r.JSON.raw } +func (r *BatchSubmitResponsePersonExperienceDates) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// End date, when known. +type BatchSubmitResponsePersonExperienceDatesEndDate struct { + // Year value. + Year int64 `json:"year" api:"required"` + // Day value, when known. + Day int64 `json:"day"` + // Month value, when known. + Month int64 `json:"month"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Year respjson.Field + Day respjson.Field + Month respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchSubmitResponsePersonExperienceDatesEndDate) RawJSON() string { return r.JSON.raw } +func (r *BatchSubmitResponsePersonExperienceDatesEndDate) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Start date, when known. +type BatchSubmitResponsePersonExperienceDatesStartDate struct { + // Year value. + Year int64 `json:"year" api:"required"` + // Day value, when known. + Day int64 `json:"day"` + // Month value, when known. + Month int64 `json:"month"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Year respjson.Field + Day respjson.Field + Month respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchSubmitResponsePersonExperienceDatesStartDate) RawJSON() string { return r.JSON.raw } +func (r *BatchSubmitResponsePersonExperienceDatesStartDate) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Core profile details. +type BatchSubmitResponsePersonProfile struct { + // Person's full name. + FullName string `json:"fullName"` + // Short professional headline. + Headline string `json:"headline"` + // Person's listed location. + Location string `json:"location"` + // Profile image URL. + ProfilePictureURL string `json:"profilePictureUrl" format:"uri"` + // Brief profile summary. + Summary string `json:"summary"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + FullName respjson.Field + Headline respjson.Field + Location respjson.Field + ProfilePictureURL respjson.Field + Summary respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchSubmitResponsePersonProfile) RawJSON() string { return r.JSON.raw } +func (r *BatchSubmitResponsePersonProfile) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +type BatchSubmitResponsePersonSkill struct { + // Skill name. + Name string `json:"name" api:"required"` + // Standardized skill name, when available. + Normalized string `json:"normalized"` + // Skill proficiency, when available. + Proficiency string `json:"proficiency"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Name respjson.Field + Normalized respjson.Field + Proficiency respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchSubmitResponsePersonSkill) RawJSON() string { return r.JSON.raw } +func (r *BatchSubmitResponsePersonSkill) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Response status. +type BatchSubmitResponseStatus string + +const ( + BatchSubmitResponseStatusOk BatchSubmitResponseStatus = "ok" +) + +// Metadata about the API key used for the request. Included in every response +// whenever a valid API key is provided, even when the response status is not 200. +type BatchSubmitResponseKeyMetadata struct { + // The number of credits consumed by this request. + CreditsConsumed int64 `json:"credits_consumed" api:"required"` + // The number of credits remaining for your organization after this request. + CreditsRemaining int64 `json:"credits_remaining" api:"required"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + CreditsConsumed respjson.Field + CreditsRemaining respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BatchSubmitResponseKeyMetadata) RawJSON() string { return r.JSON.raw } +func (r *BatchSubmitResponseKeyMetadata) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +type BatchListParams struct { + // Cursor from the previous page. + Cursor param.Opt[string] `query:"cursor,omitzero" json:"-"` + // Batches per page. Defaults to 25. + Limit param.Opt[int64] `query:"limit,omitzero" json:"-"` + // Free-text search term, matched against the batch id, crawl source (start URL or + // sitemap domain), and tags. + Q param.Opt[string] `query:"q,omitzero" json:"-"` + // Comma-separated list of tags to filter by (matches batches having any of them). + Tags param.Opt[string] `query:"tags,omitzero" json:"-"` + // `prefix` for as-you-type prefix matching (default), `exact` for full-token + // matching. + // + // Any of "exact", "prefix". + SearchType BatchListParamsSearchType `query:"search_type,omitzero" json:"-"` + // Filter by status. + // + // Any of "queued", "running", "cancelling", "completed", "cancelled", "failed". + Status BatchListParamsStatus `query:"status,omitzero" json:"-"` + paramObj +} + +// URLQuery serializes [BatchListParams]'s query parameters as `url.Values`. +func (r BatchListParams) URLQuery() (v url.Values, err error) { + return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{ + ArrayFormat: apiquery.ArrayQueryFormatComma, + NestedFormat: apiquery.NestedQueryFormatBrackets, + }) +} + +// `prefix` for as-you-type prefix matching (default), `exact` for full-token +// matching. +type BatchListParamsSearchType string + +const ( + BatchListParamsSearchTypeExact BatchListParamsSearchType = "exact" + BatchListParamsSearchTypePrefix BatchListParamsSearchType = "prefix" +) + +// Filter by status. +type BatchListParamsStatus string + +const ( + BatchListParamsStatusQueued BatchListParamsStatus = "queued" + BatchListParamsStatusRunning BatchListParamsStatus = "running" + BatchListParamsStatusCancelling BatchListParamsStatus = "cancelling" + BatchListParamsStatusCompleted BatchListParamsStatus = "completed" + BatchListParamsStatusCancelled BatchListParamsStatus = "cancelled" + BatchListParamsStatusFailed BatchListParamsStatus = "failed" +) + +type BatchGetResultsParams struct { + // next_cursor from the previous page. + Cursor param.Opt[string] `query:"cursor,omitzero" json:"-"` + // Records per page. Defaults to 25. A page can close early so its payload stays + // under ~8 MB; rely on next_cursor rather than counting records. + Limit param.Opt[int64] `query:"limit,omitzero" json:"-"` + paramObj +} + +// URLQuery serializes [BatchGetResultsParams]'s query parameters as `url.Values`. +func (r BatchGetResultsParams) URLQuery() (v url.Values, err error) { + return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{ + ArrayFormat: apiquery.ArrayQueryFormatComma, + NestedFormat: apiquery.NestedQueryFormatBrackets, + }) +} + +type BatchSubmitParams struct { + // Known identifiers for the person. At least one identifier is required. + Identifiers BatchSubmitParamsIdentifiers `json:"identifiers,omitzero" api:"required"` + // Optional timeout in milliseconds for the request. If the request takes longer + // than this value, it will be aborted with a 408 status code. Maximum allowed + // value is 300000ms (5 minutes). + TimeoutMs param.Opt[int64] `json:"timeoutMS,omitzero"` + // Optional tags for tracking usage. Up to 20 tags, each 1 to 50 characters. + Tags []string `json:"tags,omitzero"` + paramObj +} + +func (r BatchSubmitParams) MarshalJSON() (data []byte, err error) { + type shadow BatchSubmitParams + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *BatchSubmitParams) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Known identifiers for the person. At least one identifier is required. +type BatchSubmitParamsIdentifiers struct { + // LinkedIn profile URL, e.g. https://www.linkedin.com/in/yahia-bakour/. + LinkedinURL param.Opt[string] `json:"linkedinUrl,omitzero" format:"uri"` + paramObj +} + +func (r BatchSubmitParamsIdentifiers) MarshalJSON() (data []byte, err error) { + type shadow BatchSubmitParamsIdentifiers + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *BatchSubmitParamsIdentifiers) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} diff --git a/batch_test.go b/batch_test.go new file mode 100644 index 0000000..cdb86d8 --- /dev/null +++ b/batch_test.go @@ -0,0 +1,149 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +package contextdev_test + +import ( + "context" + "errors" + "os" + "testing" + + "github.com/context-dot-dev/context-go-sdk/v2" + "github.com/context-dot-dev/context-go-sdk/v2/internal/testutil" + "github.com/context-dot-dev/context-go-sdk/v2/option" +) + +func TestBatchGet(t *testing.T) { + t.Skip("Mock server tests are disabled") + baseURL := "http://localhost:4010" + if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { + baseURL = envURL + } + if !testutil.CheckTestServer(t, baseURL) { + return + } + client := contextdev.NewClient( + option.WithBaseURL(baseURL), + option.WithAPIKey("My API Key"), + ) + _, err := client.Batch.Get(context.TODO(), "batch_9f2c8a") + if err != nil { + var apierr *contextdev.Error + if errors.As(err, &apierr) { + t.Log(string(apierr.DumpRequest(true))) + } + t.Fatalf("err should be nil: %s", err.Error()) + } +} + +func TestBatchListWithOptionalParams(t *testing.T) { + t.Skip("Mock server tests are disabled") + baseURL := "http://localhost:4010" + if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { + baseURL = envURL + } + if !testutil.CheckTestServer(t, baseURL) { + return + } + client := contextdev.NewClient( + option.WithBaseURL(baseURL), + option.WithAPIKey("My API Key"), + ) + _, err := client.Batch.List(context.TODO(), contextdev.BatchListParams{ + Cursor: contextdev.String("cursor"), + Limit: contextdev.Int(1), + Q: contextdev.String("batch_1a2b"), + SearchType: contextdev.BatchListParamsSearchTypeExact, + Status: contextdev.BatchListParamsStatusQueued, + Tags: contextdev.String("docs,competitor"), + }) + if err != nil { + var apierr *contextdev.Error + if errors.As(err, &apierr) { + t.Log(string(apierr.DumpRequest(true))) + } + t.Fatalf("err should be nil: %s", err.Error()) + } +} + +func TestBatchCancel(t *testing.T) { + t.Skip("Mock server tests are disabled") + baseURL := "http://localhost:4010" + if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { + baseURL = envURL + } + if !testutil.CheckTestServer(t, baseURL) { + return + } + client := contextdev.NewClient( + option.WithBaseURL(baseURL), + option.WithAPIKey("My API Key"), + ) + _, err := client.Batch.Cancel(context.TODO(), "batch_9f2c8a") + if err != nil { + var apierr *contextdev.Error + if errors.As(err, &apierr) { + t.Log(string(apierr.DumpRequest(true))) + } + t.Fatalf("err should be nil: %s", err.Error()) + } +} + +func TestBatchGetResultsWithOptionalParams(t *testing.T) { + t.Skip("Mock server tests are disabled") + baseURL := "http://localhost:4010" + if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { + baseURL = envURL + } + if !testutil.CheckTestServer(t, baseURL) { + return + } + client := contextdev.NewClient( + option.WithBaseURL(baseURL), + option.WithAPIKey("My API Key"), + ) + _, err := client.Batch.GetResults( + context.TODO(), + "batch_9f2c8a", + contextdev.BatchGetResultsParams{ + Cursor: contextdev.String("cursor"), + Limit: contextdev.Int(1), + }, + ) + if err != nil { + var apierr *contextdev.Error + if errors.As(err, &apierr) { + t.Log(string(apierr.DumpRequest(true))) + } + t.Fatalf("err should be nil: %s", err.Error()) + } +} + +func TestBatchSubmitWithOptionalParams(t *testing.T) { + t.Skip("Mock server tests are disabled") + baseURL := "http://localhost:4010" + if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { + baseURL = envURL + } + if !testutil.CheckTestServer(t, baseURL) { + return + } + client := contextdev.NewClient( + option.WithBaseURL(baseURL), + option.WithAPIKey("My API Key"), + ) + _, err := client.Batch.Submit(context.TODO(), contextdev.BatchSubmitParams{ + Identifiers: contextdev.BatchSubmitParamsIdentifiers{ + LinkedinURL: contextdev.String("https://www.linkedin.com/in/yahia-bakour/"), + }, + Tags: []string{"production", "team-alpha"}, + TimeoutMs: contextdev.Int(1000), + }) + if err != nil { + var apierr *contextdev.Error + if errors.As(err, &apierr) { + t.Log(string(apierr.DumpRequest(true))) + } + t.Fatalf("err should be nil: %s", err.Error()) + } +} diff --git a/client.go b/client.go index edee3e9..b445caf 100644 --- a/client.go +++ b/client.go @@ -29,6 +29,7 @@ type Client struct { // MonitorsChangeDetectedWebhookPayload and MonitorsRunCompletedWebhookPayload // schemas. Monitors MonitorService + Batch BatchService } // DefaultClientOptions read from the environment (CONTEXT_DEV_API_KEY, @@ -68,6 +69,7 @@ func NewClient(opts ...option.RequestOption) (r Client) { r.Industry = NewIndustryService(opts...) r.Utility = NewUtilityService(opts...) r.Monitors = NewMonitorService(opts...) + r.Batch = NewBatchService(opts...) return } diff --git a/internal/version.go b/internal/version.go index 0d6e599..e0668d4 100644 --- a/internal/version.go +++ b/internal/version.go @@ -2,4 +2,4 @@ package internal -const PackageVersion = "2.5.0" // x-release-please-version +const PackageVersion = "2.6.0" // x-release-please-version diff --git a/monitor.go b/monitor.go index 30e4f69..59a3763 100644 --- a/monitor.go +++ b/monitor.go @@ -262,13 +262,17 @@ const ( WebhookDeliveryStatusSkippedUnsafeURL WebhookDeliveryStatus = "skipped_unsafe_url" ) -// A web monitor. `mode` is the constant `web`; behavior is described by `target` -// (page/sitemap/extract) and `change_detection` (exact/semantic). +// A newly created monitor plus `initial_run_id`, the id of the baseline run queued +// at creation. type MonitorNewResponse struct { ID string `json:"id" api:"required"` // Discriminated union describing how changes are detected. ChangeDetection MonitorNewResponseChangeDetectionUnion `json:"change_detection" api:"required"` CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"` + // The baseline run queued by this create call, or null if it could not be queued + // immediately (in which case the baseline runs on the next scheduled tick). Poll + // GET /monitors/{monitor_id}/runs/{run_id}. + InitialRunID string `json:"initial_run_id" api:"required"` // Top-level monitor category. Always `web` today; the concrete behavior is // described by `target` and `change_detection`. // @@ -314,6 +318,7 @@ type MonitorNewResponse struct { ID respjson.Field ChangeDetection respjson.Field CreatedAt respjson.Field + InitialRunID respjson.Field Mode respjson.Field Name respjson.Field Schedule respjson.Field @@ -422,9 +427,10 @@ func (r *MonitorNewResponseChangeDetectionExact) UnmarshalJSON(data []byte) erro return apijson.UnmarshalRoot(data, r) } -// Detect meaning-level changes to tracked page content, ignoring cosmetic or -// paraphrase-only differences. Which changes are meaningful is judged against the -// extract target's `instructions` (and `schema`, when provided). +// Detect meaning-level changes to page content, ignoring cosmetic or +// instruction-irrelevant differences. Which changes are meaningful is judged +// against the page or extract target's `instructions` (and an extract target's +// `schema`, when provided). type MonitorNewResponseChangeDetectionSemantic struct { Type constant.Semantic `json:"type" default:"semantic"` ConfidenceThreshold float64 `json:"confidence_threshold"` @@ -501,8 +507,9 @@ const ( // Use the methods beginning with 'As' to cast the union to one of its variants. type MonitorNewResponseTargetUnion struct { // Any of "page", "sitemap", "extract". - Type string `json:"type"` - URL string `json:"url"` + Type string `json:"type"` + URL string `json:"url"` + Instructions string `json:"instructions"` // This field is from variant [MonitorNewResponseTargetPage]. NormalizeWhitespace bool `json:"normalize_whitespace"` // This field is from variant [MonitorNewResponseTargetSitemap]. @@ -512,8 +519,6 @@ type MonitorNewResponseTargetUnion struct { // This field is from variant [MonitorNewResponseTargetSitemap]. MaxURLs int64 `json:"max_urls"` // This field is from variant [MonitorNewResponseTargetExtract]. - Instructions string `json:"instructions"` - // This field is from variant [MonitorNewResponseTargetExtract]. FollowSubdomains bool `json:"follow_subdomains"` // This field is from variant [MonitorNewResponseTargetExtract]. MaxDepth int64 `json:"max_depth"` @@ -524,11 +529,11 @@ type MonitorNewResponseTargetUnion struct { JSON struct { Type respjson.Field URL respjson.Field + Instructions respjson.Field NormalizeWhitespace respjson.Field Exclude respjson.Field Include respjson.Field MaxURLs respjson.Field - Instructions respjson.Field FollowSubdomains respjson.Field MaxDepth respjson.Field MaxPages respjson.Field @@ -591,16 +596,21 @@ func (r *MonitorNewResponseTargetUnion) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -// Watch a single web page. +// Watch a single web page. Exact detection reports visible-text diffs; semantic +// detection judges confirmed stable diffs against `instructions`. type MonitorNewResponseTargetPage struct { Type constant.Page `json:"type" default:"page"` URL string `json:"url" api:"required" format:"uri"` + // Plain-language goal describing which page changes matter. When provided without + // change_detection, semantic detection is inferred. + Instructions string `json:"instructions"` // Normalize whitespace before comparing or analyzing text. NormalizeWhitespace bool `json:"normalize_whitespace"` // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. JSON struct { Type respjson.Field URL respjson.Field + Instructions respjson.Field NormalizeWhitespace respjson.Field ExtraFields map[string]respjson.Field raw string @@ -1060,9 +1070,10 @@ func (r *MonitorGetResponseChangeDetectionExact) UnmarshalJSON(data []byte) erro return apijson.UnmarshalRoot(data, r) } -// Detect meaning-level changes to tracked page content, ignoring cosmetic or -// paraphrase-only differences. Which changes are meaningful is judged against the -// extract target's `instructions` (and `schema`, when provided). +// Detect meaning-level changes to page content, ignoring cosmetic or +// instruction-irrelevant differences. Which changes are meaningful is judged +// against the page or extract target's `instructions` (and an extract target's +// `schema`, when provided). type MonitorGetResponseChangeDetectionSemantic struct { Type constant.Semantic `json:"type" default:"semantic"` ConfidenceThreshold float64 `json:"confidence_threshold"` @@ -1139,8 +1150,9 @@ const ( // Use the methods beginning with 'As' to cast the union to one of its variants. type MonitorGetResponseTargetUnion struct { // Any of "page", "sitemap", "extract". - Type string `json:"type"` - URL string `json:"url"` + Type string `json:"type"` + URL string `json:"url"` + Instructions string `json:"instructions"` // This field is from variant [MonitorGetResponseTargetPage]. NormalizeWhitespace bool `json:"normalize_whitespace"` // This field is from variant [MonitorGetResponseTargetSitemap]. @@ -1150,8 +1162,6 @@ type MonitorGetResponseTargetUnion struct { // This field is from variant [MonitorGetResponseTargetSitemap]. MaxURLs int64 `json:"max_urls"` // This field is from variant [MonitorGetResponseTargetExtract]. - Instructions string `json:"instructions"` - // This field is from variant [MonitorGetResponseTargetExtract]. FollowSubdomains bool `json:"follow_subdomains"` // This field is from variant [MonitorGetResponseTargetExtract]. MaxDepth int64 `json:"max_depth"` @@ -1162,11 +1172,11 @@ type MonitorGetResponseTargetUnion struct { JSON struct { Type respjson.Field URL respjson.Field + Instructions respjson.Field NormalizeWhitespace respjson.Field Exclude respjson.Field Include respjson.Field MaxURLs respjson.Field - Instructions respjson.Field FollowSubdomains respjson.Field MaxDepth respjson.Field MaxPages respjson.Field @@ -1229,16 +1239,21 @@ func (r *MonitorGetResponseTargetUnion) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -// Watch a single web page. +// Watch a single web page. Exact detection reports visible-text diffs; semantic +// detection judges confirmed stable diffs against `instructions`. type MonitorGetResponseTargetPage struct { Type constant.Page `json:"type" default:"page"` URL string `json:"url" api:"required" format:"uri"` + // Plain-language goal describing which page changes matter. When provided without + // change_detection, semantic detection is inferred. + Instructions string `json:"instructions"` // Normalize whitespace before comparing or analyzing text. NormalizeWhitespace bool `json:"normalize_whitespace"` // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. JSON struct { Type respjson.Field URL respjson.Field + Instructions respjson.Field NormalizeWhitespace respjson.Field ExtraFields map[string]respjson.Field raw string @@ -1698,9 +1713,10 @@ func (r *MonitorUpdateResponseChangeDetectionExact) UnmarshalJSON(data []byte) e return apijson.UnmarshalRoot(data, r) } -// Detect meaning-level changes to tracked page content, ignoring cosmetic or -// paraphrase-only differences. Which changes are meaningful is judged against the -// extract target's `instructions` (and `schema`, when provided). +// Detect meaning-level changes to page content, ignoring cosmetic or +// instruction-irrelevant differences. Which changes are meaningful is judged +// against the page or extract target's `instructions` (and an extract target's +// `schema`, when provided). type MonitorUpdateResponseChangeDetectionSemantic struct { Type constant.Semantic `json:"type" default:"semantic"` ConfidenceThreshold float64 `json:"confidence_threshold"` @@ -1778,8 +1794,9 @@ const ( // Use the methods beginning with 'As' to cast the union to one of its variants. type MonitorUpdateResponseTargetUnion struct { // Any of "page", "sitemap", "extract". - Type string `json:"type"` - URL string `json:"url"` + Type string `json:"type"` + URL string `json:"url"` + Instructions string `json:"instructions"` // This field is from variant [MonitorUpdateResponseTargetPage]. NormalizeWhitespace bool `json:"normalize_whitespace"` // This field is from variant [MonitorUpdateResponseTargetSitemap]. @@ -1789,8 +1806,6 @@ type MonitorUpdateResponseTargetUnion struct { // This field is from variant [MonitorUpdateResponseTargetSitemap]. MaxURLs int64 `json:"max_urls"` // This field is from variant [MonitorUpdateResponseTargetExtract]. - Instructions string `json:"instructions"` - // This field is from variant [MonitorUpdateResponseTargetExtract]. FollowSubdomains bool `json:"follow_subdomains"` // This field is from variant [MonitorUpdateResponseTargetExtract]. MaxDepth int64 `json:"max_depth"` @@ -1801,11 +1816,11 @@ type MonitorUpdateResponseTargetUnion struct { JSON struct { Type respjson.Field URL respjson.Field + Instructions respjson.Field NormalizeWhitespace respjson.Field Exclude respjson.Field Include respjson.Field MaxURLs respjson.Field - Instructions respjson.Field FollowSubdomains respjson.Field MaxDepth respjson.Field MaxPages respjson.Field @@ -1868,16 +1883,21 @@ func (r *MonitorUpdateResponseTargetUnion) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -// Watch a single web page. +// Watch a single web page. Exact detection reports visible-text diffs; semantic +// detection judges confirmed stable diffs against `instructions`. type MonitorUpdateResponseTargetPage struct { Type constant.Page `json:"type" default:"page"` URL string `json:"url" api:"required" format:"uri"` + // Plain-language goal describing which page changes matter. When provided without + // change_detection, semantic detection is inferred. + Instructions string `json:"instructions"` // Normalize whitespace before comparing or analyzing text. NormalizeWhitespace bool `json:"normalize_whitespace"` // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. JSON struct { Type respjson.Field URL respjson.Field + Instructions respjson.Field NormalizeWhitespace respjson.Field ExtraFields map[string]respjson.Field raw string @@ -2359,9 +2379,10 @@ func (r *MonitorListResponseDataChangeDetectionExact) UnmarshalJSON(data []byte) return apijson.UnmarshalRoot(data, r) } -// Detect meaning-level changes to tracked page content, ignoring cosmetic or -// paraphrase-only differences. Which changes are meaningful is judged against the -// extract target's `instructions` (and `schema`, when provided). +// Detect meaning-level changes to page content, ignoring cosmetic or +// instruction-irrelevant differences. Which changes are meaningful is judged +// against the page or extract target's `instructions` (and an extract target's +// `schema`, when provided). type MonitorListResponseDataChangeDetectionSemantic struct { Type constant.Semantic `json:"type" default:"semantic"` ConfidenceThreshold float64 `json:"confidence_threshold"` @@ -2418,8 +2439,9 @@ func (r *MonitorListResponseDataSchedule) UnmarshalJSON(data []byte) error { // Use the methods beginning with 'As' to cast the union to one of its variants. type MonitorListResponseDataTargetUnion struct { // Any of "page", "sitemap", "extract". - Type string `json:"type"` - URL string `json:"url"` + Type string `json:"type"` + URL string `json:"url"` + Instructions string `json:"instructions"` // This field is from variant [MonitorListResponseDataTargetPage]. NormalizeWhitespace bool `json:"normalize_whitespace"` // This field is from variant [MonitorListResponseDataTargetSitemap]. @@ -2429,8 +2451,6 @@ type MonitorListResponseDataTargetUnion struct { // This field is from variant [MonitorListResponseDataTargetSitemap]. MaxURLs int64 `json:"max_urls"` // This field is from variant [MonitorListResponseDataTargetExtract]. - Instructions string `json:"instructions"` - // This field is from variant [MonitorListResponseDataTargetExtract]. FollowSubdomains bool `json:"follow_subdomains"` // This field is from variant [MonitorListResponseDataTargetExtract]. MaxDepth int64 `json:"max_depth"` @@ -2441,11 +2461,11 @@ type MonitorListResponseDataTargetUnion struct { JSON struct { Type respjson.Field URL respjson.Field + Instructions respjson.Field NormalizeWhitespace respjson.Field Exclude respjson.Field Include respjson.Field MaxURLs respjson.Field - Instructions respjson.Field FollowSubdomains respjson.Field MaxDepth respjson.Field MaxPages respjson.Field @@ -2508,16 +2528,21 @@ func (r *MonitorListResponseDataTargetUnion) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -// Watch a single web page. +// Watch a single web page. Exact detection reports visible-text diffs; semantic +// detection judges confirmed stable diffs against `instructions`. type MonitorListResponseDataTargetPage struct { Type constant.Page `json:"type" default:"page"` URL string `json:"url" api:"required" format:"uri"` + // Plain-language goal describing which page changes matter. When provided without + // change_detection, semantic detection is inferred. + Instructions string `json:"instructions"` // Normalize whitespace before comparing or analyzing text. NormalizeWhitespace bool `json:"normalize_whitespace"` // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. JSON struct { Type respjson.Field URL respjson.Field + Instructions respjson.Field NormalizeWhitespace respjson.Field ExtraFields map[string]respjson.Field raw string @@ -3441,21 +3466,21 @@ func (r *MonitorRunResponse) UnmarshalJSON(data []byte) error { } type MonitorNewParams struct { - // Discriminated union describing how changes are detected. - ChangeDetection MonitorNewParamsChangeDetectionUnion `json:"change_detection,omitzero" api:"required"` - Name string `json:"name" api:"required"` - // Run the monitor on a fixed interval defined by a frequency and a unit, e.g. - // every 6 hours or every 2 days. The total interval (frequency × unit) must be - // between 10 minutes and 1 year. - Schedule MonitorNewParamsSchedule `json:"schedule,omitzero" api:"required"` + Name string `json:"name" api:"required"` // Discriminated union describing what the monitor watches. Target MonitorNewParamsTargetUnion `json:"target,omitzero" api:"required"` Webhook MonitorNewParamsWebhook `json:"webhook,omitzero"` + // Discriminated union describing how changes are detected. + ChangeDetection MonitorNewParamsChangeDetectionUnion `json:"change_detection,omitzero"` // Top-level monitor category. Always `web` today; the concrete behavior is // described by `target` and `change_detection`. // // Any of "web". Mode MonitorNewParamsMode `json:"mode,omitzero"` + // Run the monitor on a fixed interval defined by a frequency and a unit, e.g. + // every 6 hours or every 2 days. The total interval (frequency × unit) must be + // between 10 minutes and 1 year. + Schedule MonitorNewParamsSchedule `json:"schedule,omitzero"` // User-defined tags for grouping and filtering monitors and their changes. // Duplicates are removed. Tags []string `json:"tags,omitzero"` @@ -3470,108 +3495,6 @@ func (r *MonitorNewParams) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -// Only one field can be non-zero. -// -// Use [param.IsOmitted] to confirm if a field is set. -type MonitorNewParamsChangeDetectionUnion struct { - OfExact *MonitorNewParamsChangeDetectionExact `json:",omitzero,inline"` - OfSemantic *MonitorNewParamsChangeDetectionSemantic `json:",omitzero,inline"` - paramUnion -} - -func (u MonitorNewParamsChangeDetectionUnion) MarshalJSON() ([]byte, error) { - return param.MarshalUnion(u, u.OfExact, u.OfSemantic) -} -func (u *MonitorNewParamsChangeDetectionUnion) UnmarshalJSON(data []byte) error { - return apijson.UnmarshalRoot(data, u) -} - -func init() { - apijson.RegisterUnion[MonitorNewParamsChangeDetectionUnion]( - "type", - apijson.Discriminator[MonitorNewParamsChangeDetectionExact]("exact"), - apijson.Discriminator[MonitorNewParamsChangeDetectionSemantic]("semantic"), - ) -} - -func NewMonitorNewParamsChangeDetectionExact() MonitorNewParamsChangeDetectionExact { - return MonitorNewParamsChangeDetectionExact{ - Type: "exact", - } -} - -// Detect exact changes. For page targets, this means visible text diffs. For -// sitemap targets, this means URL additions and removals. -// -// This struct has a constant value, construct it with -// [NewMonitorNewParamsChangeDetectionExact]. -type MonitorNewParamsChangeDetectionExact struct { - Type constant.Exact `json:"type" default:"exact"` - paramObj -} - -func (r MonitorNewParamsChangeDetectionExact) MarshalJSON() (data []byte, err error) { - type shadow MonitorNewParamsChangeDetectionExact - return param.MarshalObject(r, (*shadow)(&r)) -} -func (r *MonitorNewParamsChangeDetectionExact) UnmarshalJSON(data []byte) error { - return apijson.UnmarshalRoot(data, r) -} - -// Detect meaning-level changes to tracked page content, ignoring cosmetic or -// paraphrase-only differences. Which changes are meaningful is judged against the -// extract target's `instructions` (and `schema`, when provided). -// -// The property Type is required. -type MonitorNewParamsChangeDetectionSemantic struct { - ConfidenceThreshold param.Opt[float64] `json:"confidence_threshold,omitzero"` - // This field can be elided, and will marshal its zero value as "semantic". - Type constant.Semantic `json:"type" default:"semantic"` - paramObj -} - -func (r MonitorNewParamsChangeDetectionSemantic) MarshalJSON() (data []byte, err error) { - type shadow MonitorNewParamsChangeDetectionSemantic - return param.MarshalObject(r, (*shadow)(&r)) -} -func (r *MonitorNewParamsChangeDetectionSemantic) UnmarshalJSON(data []byte) error { - return apijson.UnmarshalRoot(data, r) -} - -// Run the monitor on a fixed interval defined by a frequency and a unit, e.g. -// every 6 hours or every 2 days. The total interval (frequency × unit) must be -// between 10 minutes and 1 year. -// -// The properties Frequency, Type, Unit are required. -type MonitorNewParamsSchedule struct { - // Number of units between runs. The resulting interval (frequency × unit) must be - // at least 10 minutes and at most 1 year (e.g. minimum 10 when unit is minutes; - // maximum 365 when unit is days). - Frequency int64 `json:"frequency" api:"required"` - // Any of "interval". - Type string `json:"type,omitzero" api:"required"` - // Any of "minutes", "hours", "days". - Unit string `json:"unit,omitzero" api:"required"` - paramObj -} - -func (r MonitorNewParamsSchedule) MarshalJSON() (data []byte, err error) { - type shadow MonitorNewParamsSchedule - return param.MarshalObject(r, (*shadow)(&r)) -} -func (r *MonitorNewParamsSchedule) UnmarshalJSON(data []byte) error { - return apijson.UnmarshalRoot(data, r) -} - -func init() { - apijson.RegisterFieldValidator[MonitorNewParamsSchedule]( - "type", "interval", - ) - apijson.RegisterFieldValidator[MonitorNewParamsSchedule]( - "unit", "minutes", "hours", "days", - ) -} - // Only one field can be non-zero. // // Use [param.IsOmitted] to confirm if a field is set. @@ -3598,11 +3521,15 @@ func init() { ) } -// Watch a single web page. +// Watch a single web page. Exact detection reports visible-text diffs; semantic +// detection judges confirmed stable diffs against `instructions`. // // The properties Type, URL are required. type MonitorNewParamsTargetPage struct { URL string `json:"url" api:"required" format:"uri"` + // Plain-language goal describing which page changes matter. When provided without + // change_detection, semantic detection is inferred. + Instructions param.Opt[string] `json:"instructions,omitzero"` // Normalize whitespace before comparing or analyzing text. NormalizeWhitespace param.Opt[bool] `json:"normalize_whitespace,omitzero"` // This field can be elided, and will marshal its zero value as "page". @@ -3687,6 +3614,75 @@ func (r *MonitorNewParamsTargetExtract) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } +// Only one field can be non-zero. +// +// Use [param.IsOmitted] to confirm if a field is set. +type MonitorNewParamsChangeDetectionUnion struct { + OfExact *MonitorNewParamsChangeDetectionExact `json:",omitzero,inline"` + OfSemantic *MonitorNewParamsChangeDetectionSemantic `json:",omitzero,inline"` + paramUnion +} + +func (u MonitorNewParamsChangeDetectionUnion) MarshalJSON() ([]byte, error) { + return param.MarshalUnion(u, u.OfExact, u.OfSemantic) +} +func (u *MonitorNewParamsChangeDetectionUnion) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, u) +} + +func init() { + apijson.RegisterUnion[MonitorNewParamsChangeDetectionUnion]( + "type", + apijson.Discriminator[MonitorNewParamsChangeDetectionExact]("exact"), + apijson.Discriminator[MonitorNewParamsChangeDetectionSemantic]("semantic"), + ) +} + +func NewMonitorNewParamsChangeDetectionExact() MonitorNewParamsChangeDetectionExact { + return MonitorNewParamsChangeDetectionExact{ + Type: "exact", + } +} + +// Detect exact changes. For page targets, this means visible text diffs. For +// sitemap targets, this means URL additions and removals. +// +// This struct has a constant value, construct it with +// [NewMonitorNewParamsChangeDetectionExact]. +type MonitorNewParamsChangeDetectionExact struct { + Type constant.Exact `json:"type" default:"exact"` + paramObj +} + +func (r MonitorNewParamsChangeDetectionExact) MarshalJSON() (data []byte, err error) { + type shadow MonitorNewParamsChangeDetectionExact + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *MonitorNewParamsChangeDetectionExact) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Detect meaning-level changes to page content, ignoring cosmetic or +// instruction-irrelevant differences. Which changes are meaningful is judged +// against the page or extract target's `instructions` (and an extract target's +// `schema`, when provided). +// +// The property Type is required. +type MonitorNewParamsChangeDetectionSemantic struct { + ConfidenceThreshold param.Opt[float64] `json:"confidence_threshold,omitzero"` + // This field can be elided, and will marshal its zero value as "semantic". + Type constant.Semantic `json:"type" default:"semantic"` + paramObj +} + +func (r MonitorNewParamsChangeDetectionSemantic) MarshalJSON() (data []byte, err error) { + type shadow MonitorNewParamsChangeDetectionSemantic + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *MonitorNewParamsChangeDetectionSemantic) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + // Top-level monitor category. Always `web` today; the concrete behavior is // described by `target` and `change_detection`. type MonitorNewParamsMode string @@ -3695,6 +3691,40 @@ const ( MonitorNewParamsModeWeb MonitorNewParamsMode = "web" ) +// Run the monitor on a fixed interval defined by a frequency and a unit, e.g. +// every 6 hours or every 2 days. The total interval (frequency × unit) must be +// between 10 minutes and 1 year. +// +// The properties Frequency, Type, Unit are required. +type MonitorNewParamsSchedule struct { + // Number of units between runs. The resulting interval (frequency × unit) must be + // at least 10 minutes and at most 1 year (e.g. minimum 10 when unit is minutes; + // maximum 365 when unit is days). + Frequency int64 `json:"frequency" api:"required"` + // Any of "interval". + Type string `json:"type,omitzero" api:"required"` + // Any of "minutes", "hours", "days". + Unit string `json:"unit,omitzero" api:"required"` + paramObj +} + +func (r MonitorNewParamsSchedule) MarshalJSON() (data []byte, err error) { + type shadow MonitorNewParamsSchedule + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *MonitorNewParamsSchedule) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +func init() { + apijson.RegisterFieldValidator[MonitorNewParamsSchedule]( + "type", "interval", + ) + apijson.RegisterFieldValidator[MonitorNewParamsSchedule]( + "unit", "minutes", "hours", "days", + ) +} + // The property URL is required. type MonitorNewParamsWebhook struct { // Webhook URL events are delivered to. @@ -3793,9 +3823,10 @@ func (r *MonitorUpdateParamsChangeDetectionExact) UnmarshalJSON(data []byte) err return apijson.UnmarshalRoot(data, r) } -// Detect meaning-level changes to tracked page content, ignoring cosmetic or -// paraphrase-only differences. Which changes are meaningful is judged against the -// extract target's `instructions` (and `schema`, when provided). +// Detect meaning-level changes to page content, ignoring cosmetic or +// instruction-irrelevant differences. Which changes are meaningful is judged +// against the page or extract target's `instructions` (and an extract target's +// `schema`, when provided). // // The property Type is required. type MonitorUpdateParamsChangeDetectionSemantic struct { @@ -3880,11 +3911,15 @@ func init() { ) } -// Watch a single web page. +// Watch a single web page. Exact detection reports visible-text diffs; semantic +// detection judges confirmed stable diffs against `instructions`. // // The properties Type, URL are required. type MonitorUpdateParamsTargetPage struct { URL string `json:"url" api:"required" format:"uri"` + // Plain-language goal describing which page changes matter. When provided without + // change_detection, semantic detection is inferred. + Instructions param.Opt[string] `json:"instructions,omitzero"` // Normalize whitespace before comparing or analyzing text. NormalizeWhitespace param.Opt[bool] `json:"normalize_whitespace,omitzero"` // This field can be elided, and will marshal its zero value as "page". diff --git a/monitor_test.go b/monitor_test.go index a3815bb..32720ba 100644 --- a/monitor_test.go +++ b/monitor_test.go @@ -28,22 +28,23 @@ func TestMonitorNewWithOptionalParams(t *testing.T) { option.WithAPIKey("My API Key"), ) _, err := client.Monitors.New(context.TODO(), contextdev.MonitorNewParams{ - ChangeDetection: contextdev.MonitorNewParamsChangeDetectionUnion{ - OfExact: &contextdev.MonitorNewParamsChangeDetectionExact{}, - }, Name: "Acme pricing page", - Schedule: contextdev.MonitorNewParamsSchedule{ - Frequency: 6, - Type: "interval", - Unit: "hours", - }, Target: contextdev.MonitorNewParamsTargetUnion{ OfPage: &contextdev.MonitorNewParamsTargetPage{ URL: "https://acme.com/pricing", + Instructions: contextdev.String("Report pricing or plan availability changes. Ignore counters, timestamps, testimonials, and navigation."), NormalizeWhitespace: contextdev.Bool(true), }, }, + ChangeDetection: contextdev.MonitorNewParamsChangeDetectionUnion{ + OfExact: &contextdev.MonitorNewParamsChangeDetectionExact{}, + }, Mode: contextdev.MonitorNewParamsModeWeb, + Schedule: contextdev.MonitorNewParamsSchedule{ + Frequency: 6, + Type: "interval", + Unit: "hours", + }, Tags: []string{"pricing", "competitor"}, Webhook: contextdev.MonitorNewParamsWebhook{ URL: "https://example.com/webhook", @@ -113,6 +114,7 @@ func TestMonitorUpdateWithOptionalParams(t *testing.T) { Target: contextdev.MonitorUpdateParamsTargetUnion{ OfPage: &contextdev.MonitorUpdateParamsTargetPage{ URL: "https://acme.com/pricing", + Instructions: contextdev.String("Report pricing or plan availability changes. Ignore counters, timestamps, testimonials, and navigation."), NormalizeWhitespace: contextdev.Bool(true), }, }, diff --git a/shared/constant/constants.go b/shared/constant/constants.go index 25a8648..816f4a0 100644 --- a/shared/constant/constants.go +++ b/shared/constant/constants.go @@ -24,8 +24,10 @@ type ByEmail string // Always "by_email" type ByName string // Always "by_name" type ByTicker string // Always "by_ticker" type ByTransaction string // Always "by_transaction" +type Error string // Always "error" type Exact string // Always "exact" type Extract string // Always "extract" +type Ok string // Always "ok" type Page string // Always "page" type Perform string // Always "perform" type Semantic string // Always "semantic" @@ -38,8 +40,10 @@ func (c ByEmail) Default() ByEmail { return "by_email" } func (c ByName) Default() ByName { return "by_name" } func (c ByTicker) Default() ByTicker { return "by_ticker" } func (c ByTransaction) Default() ByTransaction { return "by_transaction" } +func (c Error) Default() Error { return "error" } func (c Exact) Default() Exact { return "exact" } func (c Extract) Default() Extract { return "extract" } +func (c Ok) Default() Ok { return "ok" } func (c Page) Default() Page { return "page" } func (c Perform) Default() Perform { return "perform" } func (c Semantic) Default() Semantic { return "semantic" } @@ -52,8 +56,10 @@ func (c ByEmail) MarshalJSON() ([]byte, error) { return marshalString(c) } func (c ByName) MarshalJSON() ([]byte, error) { return marshalString(c) } func (c ByTicker) MarshalJSON() ([]byte, error) { return marshalString(c) } func (c ByTransaction) MarshalJSON() ([]byte, error) { return marshalString(c) } +func (c Error) MarshalJSON() ([]byte, error) { return marshalString(c) } func (c Exact) MarshalJSON() ([]byte, error) { return marshalString(c) } func (c Extract) MarshalJSON() ([]byte, error) { return marshalString(c) } +func (c Ok) MarshalJSON() ([]byte, error) { return marshalString(c) } func (c Page) MarshalJSON() ([]byte, error) { return marshalString(c) } func (c Perform) MarshalJSON() ([]byte, error) { return marshalString(c) } func (c Semantic) MarshalJSON() ([]byte, error) { return marshalString(c) } diff --git a/web.go b/web.go index 6a67bd1..6a6a9b6 100644 --- a/web.go +++ b/web.go @@ -1622,19 +1622,26 @@ type WebWebScrapeHTMLResponse struct { Type WebWebScrapeHTMLResponseType `json:"type" api:"required"` // The URL that was scraped URL string `json:"url" api:"required"` + // One verified outcome per requested browser action, in request order. + ActionsApplied []WebWebScrapeHTMLResponseActionsApplied `json:"actionsApplied"` + // True when an action was applied but the returned content could not be refreshed + // afterward. + ActionsHTMLStale bool `json:"actionsHtmlStale"` // Metadata about the API key used for the request. Included in every response // whenever a valid API key is provided, even when the response status is not 200. KeyMetadata WebWebScrapeHTMLResponseKeyMetadata `json:"key_metadata"` // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. JSON struct { - HTML respjson.Field - Metadata respjson.Field - Success respjson.Field - Type respjson.Field - URL respjson.Field - KeyMetadata respjson.Field - ExtraFields map[string]respjson.Field - raw string + HTML respjson.Field + Metadata respjson.Field + Success respjson.Field + Type respjson.Field + URL respjson.Field + ActionsApplied respjson.Field + ActionsHTMLStale respjson.Field + KeyMetadata respjson.Field + ExtraFields map[string]respjson.Field + raw string } `json:"-"` } @@ -1874,6 +1881,39 @@ const ( WebWebScrapeHTMLResponseTypePpt WebWebScrapeHTMLResponseType = "ppt" ) +type WebWebScrapeHTMLResponseActionsApplied struct { + Instruction string `json:"instruction" api:"required"` + // Applied means the requested page state was visibly verified. Failed means it was + // not verified. Skipped means it was not attempted. + // + // Any of "applied", "failed", "skipped". + Status string `json:"status" api:"required"` + // Visible page evidence used to verify an applied action. + CompletionEvidence string `json:"completionEvidence"` + DurationMs float64 `json:"durationMs"` + Error string `json:"error"` + Method string `json:"method"` + TargetDescription string `json:"targetDescription"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Instruction respjson.Field + Status respjson.Field + CompletionEvidence respjson.Field + DurationMs respjson.Field + Error respjson.Field + Method respjson.Field + TargetDescription respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r WebWebScrapeHTMLResponseActionsApplied) RawJSON() string { return r.JSON.raw } +func (r *WebWebScrapeHTMLResponseActionsApplied) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + // Metadata about the API key used for the request. Included in every response // whenever a valid API key is provided, even when the response status is not 200. type WebWebScrapeHTMLResponseKeyMetadata struct { @@ -2029,19 +2069,26 @@ type WebWebScrapeMdResponse struct { Success bool `json:"success" api:"required"` // The URL that was scraped URL string `json:"url" api:"required"` + // One verified outcome per requested browser action, in request order. + ActionsApplied []WebWebScrapeMdResponseActionsApplied `json:"actionsApplied"` + // True when an action was applied but the returned content could not be refreshed + // afterward. + ActionsHTMLStale bool `json:"actionsHtmlStale"` // Metadata about the API key used for the request. Included in every response // whenever a valid API key is provided, even when the response status is not 200. KeyMetadata WebWebScrapeMdResponseKeyMetadata `json:"key_metadata"` // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. JSON struct { - ContentLength respjson.Field - Markdown respjson.Field - Metadata respjson.Field - Success respjson.Field - URL respjson.Field - KeyMetadata respjson.Field - ExtraFields map[string]respjson.Field - raw string + ContentLength respjson.Field + Markdown respjson.Field + Metadata respjson.Field + Success respjson.Field + URL respjson.Field + ActionsApplied respjson.Field + ActionsHTMLStale respjson.Field + KeyMetadata respjson.Field + ExtraFields map[string]respjson.Field + raw string } `json:"-"` } @@ -2258,6 +2305,39 @@ func (r *WebWebScrapeMdResponseMetadataTwitterUnion) UnmarshalJSON(data []byte) return apijson.UnmarshalRoot(data, r) } +type WebWebScrapeMdResponseActionsApplied struct { + Instruction string `json:"instruction" api:"required"` + // Applied means the requested page state was visibly verified. Failed means it was + // not verified. Skipped means it was not attempted. + // + // Any of "applied", "failed", "skipped". + Status string `json:"status" api:"required"` + // Visible page evidence used to verify an applied action. + CompletionEvidence string `json:"completionEvidence"` + DurationMs float64 `json:"durationMs"` + Error string `json:"error"` + Method string `json:"method"` + TargetDescription string `json:"targetDescription"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Instruction respjson.Field + Status respjson.Field + CompletionEvidence respjson.Field + DurationMs respjson.Field + Error respjson.Field + Method respjson.Field + TargetDescription respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r WebWebScrapeMdResponseActionsApplied) RawJSON() string { return r.JSON.raw } +func (r *WebWebScrapeMdResponseActionsApplied) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + // Metadata about the API key used for the request. Included in every response // whenever a valid API key is provided, even when the response status is not 200. type WebWebScrapeMdResponseKeyMetadata struct {