generated: '2026-09-12' method: searched source: https://developer.gettyimages.com/docs/ sources: - https://developer.gettyimages.com/docs/ - https://developer.gettyimages.com/docs/authorization/ - https://developer.gettyimages.com/asset-change/ - https://developer.gettyimages.com/ai-generation/ - openapi/_original/getty-images-swagger-v3-openapi.json description: >- Cross-cutting runtime semantics for the Getty Images API v3, read from the provider's own technical documentation and its live OpenAPI 3.0.4 contract. base_url: https://api.gettyimages.com/v3/ transport: https_only: true tls_minimum: '1.2' tls_supported: ['1.2', '1.3'] cors: supported: true exceptions: [/v4/oauth2/token, /v4/oauth2/auth] redirects: note: Any request may redirect; clients must follow Location. 302 Found and 303 See Other are used. media_type: application/json datetime_format: ISO 8601 UTC (YYYY-MM-DDTHH:MM:SSZ) authentication: api_key: required: true location: header name: Api-Key note: Every request must carry the key; omitting it returns 401 {"message":"Unauthorized"}. bearer_token: required_for: elevated privileges (downloads, download_sizes, boards, purchase history, Gen AI) location: header name: Authorization scheme: Bearer challenge: 'WWW-Authenticate: Bearer realm="Download",error="invalid_token",error_description="The access token is missing"' oauth2: grants: [client_credentials, authorization_code, refresh_token] token_endpoint: https://authentication.gettyimages.com/oauth2/token authorization_endpoint: https://authentication.gettyimages.com/oauth2/auth pkce: S256 and plain supported access_token_lifetime_seconds: 1800 guidance: >- Reuse an access token until it expires. Token calls count against the customer's rate limit, so re-minting early is self-harming. docs: https://developer.gettyimages.com/docs/authorization/ detail: authentication/getty-images-authentication.yml idempotency: supported: false coverage: none mechanism: null header: null scope: [] evidence: >- No Idempotency-Key header, no client-supplied request identifier and no replay-protection language appears anywhere in the Getty Images technical documentation or in the live OpenAPI 3.0.4 contract (searched for "idempoten" across all 29 docs pages and the spec; zero matches). The mutating surface is real — 27 write operations including POST /v3/downloads/images/{id}, which licenses an asset and may consume a credit — and none of it carries replay protection. A retried download POST is a second license event. The one partial mitigation Getty documents is the Asset Changes confirm/ack loop: new changes are not returned from PUT /v3/asset-changes/change-sets until the current change set is confirmed via DELETE, so a dropped response re-delivers the SAME batch rather than skipping one. That is at-least-once delivery with a client-side ack, not idempotency, and Getty explicitly tells clients to treat New/Update messages as upserts for that reason. reversibility: grade: documented applies: true note: >- Getty documents no API-level reversal for its two consequential write classes. Nothing in the contract or the docs states a refund, void, cancel or undo window for a download licence or a generation credit; remediation is a support conversation, not an operation. Graded `documented` rather than `verified` because reversal paths exist for the collaborative surface but NO window is stated for any of them, and no window is asserted here that the provider does not publish. reversible: - surface: boards write: POST /v3/boards reversal: DELETE /v3/boards/{board_id} window: null window_source: null note: Full delete; no stated retention or restore window, and no restore operation exists. - surface: board assets write: PUT /v3/boards/{board_id}/assets/{asset_id} reversal: DELETE /v3/boards/{board_id}/assets/{asset_id} window: null window_source: null - surface: board comments write: POST /v3/boards/{board_id}/comments reversal: DELETE /v3/boards/{board_id}/comments/{comment_id} window: null window_source: null - surface: asset comments write: POST /v3/boards/{board_id}/assets/{asset_id}/comments reversal: DELETE /v3/boards/{board_id}/assets/{asset_id}/comments/{comment_id} window: null window_source: null - surface: gen-ai file registrations write: POST /v3/ai/file-registrations reversal: DELETE /v3/ai/file-registrations/{fileRegistrationId} window: null window_source: null - surface: asset-changes change sets write: PUT /v3/asset-changes/change-sets reversal: DELETE /v3/asset-changes/change-sets/{change-set-id} window: null window_source: null note: >- DELETE here is an ACK ("I processed this batch"), not an undo. Withholding the DELETE is what re-delivers the batch. Recorded for completeness, not as a reversal path. irreversible: - surface: downloads write: ['POST /v3/downloads/images/{id}', 'POST /v3/downloads/videos/{id}'] note: >- Licenses the asset against the customer's agreement and returns a delivery URI. No refund, void or release operation exists in the contract. GET /v3/downloads and GET /v3/{images,videos}/{id}/downloadhistory let an agent CHECK whether an asset was already licensed before licensing it again — the closest thing to a pre-flight the API offers. - surface: generative-ai write: POST /v3/ai/image-generations and the eight sibling generation endpoints note: >- Getty's docs state that use of these endpoints "may result in the deduction of a credit depending on the terms of your license". No credit-reversal operation exists. GET /v3/ai/generation-history is the audit trail, not an undo. - surface: usage reporting write: PUT /v3/usage-batches/{id} note: Usage batch submission; no documented retraction. dry_run_mode: supported: false note: >- No sandbox flag, no simulate/preview parameter and no test-mode key prefix is documented. The nearest pre-flight signals are read-only: fields=download_sizes / largest_downloads tells an agent what a download WOULD return, and GET /v3/downloads tells it what has already been licensed. pagination: style: page-number params: {page: 'page (default 1)', page_size: 'page_size (default 30 for search)'} page_size_allowed_values: [1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 25, 30, 50, 60, 75, 100] response_field: result_count note: >- There is no total_pages field; clients compute page count from result_count. Requesting a page beyond the last returns 400 with ErrorCode InvalidPage and an ErrorMessage that names the real maximum. field_expansion: param: fields default: summary_set presets: [summary_set, detail_set] explicit_only: - download_sizes - largest_downloads - downloads - display_set - high_res_comp - mid_res_comp - comp - preview - thumb note: >- Sparse fieldsets are also supported as a comma-delimited list (fields=id,title). Fields that authorize a download (downloads, download_sizes, largest_downloads) additionally require a Bearer access token, not just the Api-Key. request_headers: - name: Api-Key required: true - name: Authorization required: conditional - name: Accept-Language description: Localizes result strings; supported values are enumerated per operation in the spec. - name: GI-Country-Code description: >- Overrides automatic end-user geolocation for country-tailored results. Gated — not all API customers are permitted to send it; requires a conversation with Getty API support. caching: server_driven: true example_max_age_seconds: 86400 example_surface: Creative Image Search (24 hours) headers: [cache-control, vary, age, x-cache] vary: [Accept-Encoding, Authorization, Api-Key, Accept, GI-Country-Code, Accept-Language] note: >- max-age doubles as the maximum time the API itself caches the result, so a client cannot force freshness by bypassing its own cache. request_id_tracing: client_correlation_header: null note: >- No client-supplied request-id or correlation header is documented. Responses from the AWS API Gateway edge carry x-amzn-requestid / x-amz-apigw-id and CloudFront carries x-amz-cf-id; those are infrastructure identifiers, not a documented support handle. versioning: scheme: uri-path current: v3 base: https://api.gettyimages.com/v3/ detail: lifecycle/getty-images-lifecycle.yml error_envelope: primary: media_type: application/vnd.getty.error+json fields: [ErrorCode, ErrorMessage] note: ErrorCode is the stable machine value; ErrorMessage wording must not be matched in code. gateway: media_type: application/json fields: [message] note: >- Edge/authorizer failures (401 Unauthorized, 403 Forbidden, 429 Too Many Requests) return the terse {"message": "..."} shape instead, with no ErrorCode. rfc9457: false detail: errors/getty-images-problem-types.yml rate_limit_signaling: status: 429 headers_returned: [X-Error-Detail] standard_headers: [] retry_after: false note: >- No RateLimit-* / X-RateLimit-* headers and no Retry-After are returned. The only runtime signal is the 429 plus, on the calls-per-second path, the X-Error-Detail header carrying "Account Over Queries Per Second Limit". An agent therefore cannot read its remaining budget; it can only observe rejection. Getty's documented guidance is a fault-handling library (Polly / Tenacity) and, for Gen AI, a fixed 1-second wait before retrying. detail: rate-limits/getty-images-rate-limits.yml hypermedia: present: true note: >- Responses embed absolute URIs to related resources (largest_downloads[].downloads[].uri points at the download endpoint for that asset), so clients should follow the link rather than construct the URI. Delivery URIs returned by the download endpoint are explicitly opaque and must be introspected via content-disposition / content-length / content-type. event_surface: webhooks: false style: client-pull change sets note: >- Getty publishes no webhooks and no push events. "Asset Changes" is a pull loop: read channels from GET /v3/asset-changes/channels, request a batch with PUT /v3/asset-changes/change-sets, then confirm with DELETE /v3/asset-changes/change-sets/{change-set-id}. Messages are ordered within a channel but may arrive out of lifecycle order, so clients must treat New/Update as upsert and ignore Delete for unknown assets.