Skip to content

Instantly share code, notes, and snippets.

@troykelly
Created March 8, 2026 06:45
Show Gist options
  • Select an option

  • Save troykelly/0e0ba09c15d73cd0037c345e40a555d0 to your computer and use it in GitHub Desktop.

Select an option

Save troykelly/0e0ba09c15d73cd0037c345e40a555d0 to your computer and use it in GitHub Desktop.
openapi: 3.1.0
info:
title: Pexels API
version: "2026-03-08"
summary: Unofficial OpenAPI 3.1 specification generated from the current Pexels documentation.
description: |-
This OpenAPI document was generated from the current public Pexels API documentation.
Notes:
- Authentication is via the `Authorization` header with a Pexels API key.
- The public docs state that video endpoints are available under `/v1/videos/` and that the older `/videos/` paths are deprecated.
- The current docs also show the "Get a Video" operation at `/v1/videos/videos/{id}`. That looks inconsistent with the other video routes, but this spec preserves the documented path instead of guessing.
- Error response bodies are not documented in detail, so this spec models them conservatively.
contact:
name: Pexels
url: https://www.pexels.com/api/documentation/
servers:
- url: https://api.pexels.com
description: Production API
security:
- ApiKeyAuth: []
tags:
- name: Photos
- name: Videos
- name: Collections
paths:
/v1/search:
get:
tags: [Photos]
operationId: searchPhotos
summary: Search for photos
description: Search Pexels photos by query and optional filters.
parameters:
- $ref: "#/components/parameters/Query"
- $ref: "#/components/parameters/PhotoOrientation"
- $ref: "#/components/parameters/PhotoSize"
- $ref: "#/components/parameters/Color"
- $ref: "#/components/parameters/Locale"
- $ref: "#/components/parameters/Page"
- $ref: "#/components/parameters/PerPage"
responses:
"200":
description: Photo search results.
headers:
X-Ratelimit-Limit:
$ref: "#/components/headers/XRateLimitLimit"
X-Ratelimit-Remaining:
$ref: "#/components/headers/XRateLimitRemaining"
X-Ratelimit-Reset:
$ref: "#/components/headers/XRateLimitReset"
content:
application/json:
schema:
$ref: "#/components/schemas/PhotoSearchResponse"
"400":
$ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
/v1/curated:
get:
tags: [Photos]
operationId: getCuratedPhotos
summary: Curated photos
description: Get real-time curated photos from the Pexels team.
parameters:
- $ref: "#/components/parameters/Page"
- $ref: "#/components/parameters/PerPage"
responses:
"200":
description: Curated photo results.
headers:
X-Ratelimit-Limit:
$ref: "#/components/headers/XRateLimitLimit"
X-Ratelimit-Remaining:
$ref: "#/components/headers/XRateLimitRemaining"
X-Ratelimit-Reset:
$ref: "#/components/headers/XRateLimitReset"
content:
application/json:
schema:
$ref: "#/components/schemas/PhotoPageResponse"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
/v1/photos/{id}:
get:
tags: [Photos]
operationId: getPhoto
summary: Get a photo
description: Retrieve a specific photo by ID.
parameters:
- $ref: "#/components/parameters/PhotoId"
responses:
"200":
description: Photo resource.
headers:
X-Ratelimit-Limit:
$ref: "#/components/headers/XRateLimitLimit"
X-Ratelimit-Remaining:
$ref: "#/components/headers/XRateLimitRemaining"
X-Ratelimit-Reset:
$ref: "#/components/headers/XRateLimitReset"
content:
application/json:
schema:
$ref: "#/components/schemas/Photo"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
/v1/videos/search:
get:
tags: [Videos]
operationId: searchVideos
summary: Search for videos
description: Search Pexels videos by query and optional filters.
parameters:
- $ref: "#/components/parameters/Query"
- $ref: "#/components/parameters/VideoOrientation"
- $ref: "#/components/parameters/VideoSize"
- $ref: "#/components/parameters/Locale"
- $ref: "#/components/parameters/Page"
- $ref: "#/components/parameters/PerPage"
responses:
"200":
description: Video search results.
headers:
X-Ratelimit-Limit:
$ref: "#/components/headers/XRateLimitLimit"
X-Ratelimit-Remaining:
$ref: "#/components/headers/XRateLimitRemaining"
X-Ratelimit-Reset:
$ref: "#/components/headers/XRateLimitReset"
content:
application/json:
schema:
$ref: "#/components/schemas/VideoSearchResponse"
"400":
$ref: "#/components/responses/BadRequest"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
/v1/videos/popular:
get:
tags: [Videos]
operationId: getPopularVideos
summary: Popular videos
description: Get the current popular Pexels videos.
parameters:
- $ref: "#/components/parameters/MinWidth"
- $ref: "#/components/parameters/MinHeight"
- $ref: "#/components/parameters/MinDuration"
- $ref: "#/components/parameters/MaxDuration"
- $ref: "#/components/parameters/Page"
- $ref: "#/components/parameters/PerPage"
responses:
"200":
description: Popular video results.
headers:
X-Ratelimit-Limit:
$ref: "#/components/headers/XRateLimitLimit"
X-Ratelimit-Remaining:
$ref: "#/components/headers/XRateLimitRemaining"
X-Ratelimit-Reset:
$ref: "#/components/headers/XRateLimitReset"
content:
application/json:
schema:
$ref: "#/components/schemas/VideoPageResponse"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
/v1/videos/videos/{id}:
get:
tags: [Videos]
operationId: getVideo
summary: Get a video
description: |-
Retrieve a specific video by ID.
This path is preserved exactly as shown in the current Pexels documentation.
parameters:
- $ref: "#/components/parameters/VideoId"
responses:
"200":
description: Video resource.
headers:
X-Ratelimit-Limit:
$ref: "#/components/headers/XRateLimitLimit"
X-Ratelimit-Remaining:
$ref: "#/components/headers/XRateLimitRemaining"
X-Ratelimit-Reset:
$ref: "#/components/headers/XRateLimitReset"
content:
application/json:
schema:
$ref: "#/components/schemas/Video"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
/v1/collections/featured:
get:
tags: [Collections]
operationId: getFeaturedCollections
summary: Featured collections
description: Returns featured collections on Pexels.
parameters:
- $ref: "#/components/parameters/Page"
- $ref: "#/components/parameters/PerPage"
responses:
"200":
description: Featured collection results.
headers:
X-Ratelimit-Limit:
$ref: "#/components/headers/XRateLimitLimit"
X-Ratelimit-Remaining:
$ref: "#/components/headers/XRateLimitRemaining"
X-Ratelimit-Reset:
$ref: "#/components/headers/XRateLimitReset"
content:
application/json:
schema:
$ref: "#/components/schemas/CollectionPageResponse"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
/v1/collections:
get:
tags: [Collections]
operationId: getMyCollections
summary: My collections
description: Returns all collections belonging to the authenticated user.
parameters:
- $ref: "#/components/parameters/Page"
- $ref: "#/components/parameters/PerPage"
responses:
"200":
description: Authenticated user's collections.
headers:
X-Ratelimit-Limit:
$ref: "#/components/headers/XRateLimitLimit"
X-Ratelimit-Remaining:
$ref: "#/components/headers/XRateLimitRemaining"
X-Ratelimit-Reset:
$ref: "#/components/headers/XRateLimitReset"
content:
application/json:
schema:
$ref: "#/components/schemas/CollectionPageResponse"
"401":
$ref: "#/components/responses/Unauthorized"
"429":
$ref: "#/components/responses/TooManyRequests"
/v1/collections/{id}:
get:
tags: [Collections]
operationId: getCollectionMedia
summary: Collection media
description: |-
Returns media within a single collection. You can filter to only receive photos or videos using `type`.
Per the docs, this endpoint returns a collection if it is featured or belongs to the authenticated user.
parameters:
- $ref: "#/components/parameters/CollectionId"
- $ref: "#/components/parameters/CollectionMediaType"
- $ref: "#/components/parameters/Sort"
- $ref: "#/components/parameters/Page"
- $ref: "#/components/parameters/PerPage"
responses:
"200":
description: Collection media results.
headers:
X-Ratelimit-Limit:
$ref: "#/components/headers/XRateLimitLimit"
X-Ratelimit-Remaining:
$ref: "#/components/headers/XRateLimitRemaining"
X-Ratelimit-Reset:
$ref: "#/components/headers/XRateLimitReset"
content:
application/json:
schema:
$ref: "#/components/schemas/CollectionMediaResponse"
"401":
$ref: "#/components/responses/Unauthorized"
"404":
$ref: "#/components/responses/NotFound"
"429":
$ref: "#/components/responses/TooManyRequests"
components:
securitySchemes:
ApiKeyAuth:
type: apiKey
in: header
name: Authorization
description: Pexels API key.
headers:
XRateLimitLimit:
description: Total request limit for the monthly period.
schema:
type: integer
XRateLimitRemaining:
description: Remaining requests in the current monthly period.
schema:
type: integer
XRateLimitReset:
description: UNIX timestamp for when the monthly period rolls over.
schema:
type: integer
format: int64
parameters:
Query:
name: query
in: query
required: true
schema:
type: string
description: Search query.
PhotoOrientation:
name: orientation
in: query
required: false
schema:
$ref: "#/components/schemas/Orientation"
description: Desired photo orientation.
VideoOrientation:
name: orientation
in: query
required: false
schema:
$ref: "#/components/schemas/Orientation"
description: Desired video orientation.
PhotoSize:
name: size
in: query
required: false
schema:
type: string
enum: [large, medium, small]
description: Minimum photo size. `large` = 24MP, `medium` = 12MP, `small` = 4MP.
VideoSize:
name: size
in: query
required: false
schema:
type: string
enum: [large, medium, small]
description: Minimum video size. `large` = 4K, `medium` = Full HD, `small` = HD.
Color:
name: color
in: query
required: false
schema:
oneOf:
- type: string
enum:
- red
- orange
- yellow
- green
- turquoise
- blue
- violet
- pink
- brown
- black
- gray
- white
- type: string
pattern: "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$"
description: Desired photo color, as a named color or hex code.
Locale:
name: locale
in: query
required: false
schema:
$ref: "#/components/schemas/Locale"
description: Locale of the search being performed.
Page:
name: page
in: query
required: false
schema:
type: integer
minimum: 1
default: 1
description: Page number to request.
PerPage:
name: per_page
in: query
required: false
schema:
type: integer
minimum: 1
maximum: 80
default: 15
description: Number of results to return per page.
PhotoId:
name: id
in: path
required: true
schema:
type: integer
description: Photo ID.
VideoId:
name: id
in: path
required: true
schema:
type: integer
description: Video ID.
CollectionId:
name: id
in: path
required: true
schema:
type: string
description: Collection ID.
MinWidth:
name: min_width
in: query
required: false
schema:
type: integer
minimum: 1
description: Minimum width in pixels of returned videos.
MinHeight:
name: min_height
in: query
required: false
schema:
type: integer
minimum: 1
description: Minimum height in pixels of returned videos.
MinDuration:
name: min_duration
in: query
required: false
schema:
type: integer
minimum: 1
description: Minimum duration in seconds of returned videos.
MaxDuration:
name: max_duration
in: query
required: false
schema:
type: integer
minimum: 1
description: Maximum duration in seconds of returned videos.
CollectionMediaType:
name: type
in: query
required: false
schema:
type: string
enum: [photos, videos]
description: Media type filter. If omitted or invalid, all media may be returned.
Sort:
name: sort
in: query
required: false
schema:
type: string
enum: [asc, desc]
default: asc
description: Order of items in the collection media response.
responses:
BadRequest:
description: Bad request.
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
Unauthorized:
description: Missing or invalid API key.
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
NotFound:
description: Resource not found.
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
TooManyRequests:
description: Rate limit exceeded.
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
schemas:
Orientation:
type: string
enum: [landscape, portrait, square]
Locale:
type: string
enum:
- en-US
- pt-BR
- es-ES
- ca-ES
- de-DE
- it-IT
- fr-FR
- sv-SE
- id-ID
- pl-PL
- ja-JP
- zh-TW
- zh-CN
- ko-KR
- th-TH
- nl-NL
- hu-HU
- vi-VN
- cs-CZ
- da-DK
- fi-FI
- uk-UA
- el-GR
- ro-RO
- nb-NO
- sk-SK
- tr-TR
- ru-RU
Error:
type: object
description: Error payload is not documented in detail by Pexels.
additionalProperties: true
Pagination:
type: object
properties:
page:
type: integer
per_page:
type: integer
total_results:
type: integer
prev_page:
type: string
format: uri
next_page:
type: string
format: uri
required:
- page
- per_page
- total_results
PhotoSource:
type: object
properties:
original:
type: string
format: uri
large2x:
type: string
format: uri
large:
type: string
format: uri
medium:
type: string
format: uri
small:
type: string
format: uri
portrait:
type: string
format: uri
landscape:
type: string
format: uri
tiny:
type: string
format: uri
required:
- original
- large2x
- large
- medium
- small
- portrait
- landscape
- tiny
Photo:
type: object
properties:
id:
type: integer
width:
type: integer
height:
type: integer
url:
type: string
format: uri
photographer:
type: string
photographer_url:
type: string
format: uri
photographer_id:
type: integer
avg_color:
type: string
description: Average color of the photo.
src:
$ref: "#/components/schemas/PhotoSource"
liked:
type: boolean
description: Exposed in current examples and changelog.
alt:
type: string
required:
- id
- width
- height
- url
- photographer
- photographer_url
- photographer_id
- src
PhotoPageResponse:
allOf:
- $ref: "#/components/schemas/Pagination"
- type: object
properties:
photos:
type: array
items:
$ref: "#/components/schemas/Photo"
required:
- photos
PhotoSearchResponse:
allOf:
- $ref: "#/components/schemas/PhotoPageResponse"
VideoUser:
type: object
properties:
id:
type: integer
name:
type: string
url:
type: string
format: uri
required:
- id
- name
- url
VideoFile:
type: object
properties:
id:
type: integer
quality:
type: string
enum: [hd, sd]
file_type:
type: string
width:
type: integer
height:
type: integer
fps:
type: number
link:
type: string
format: uri
required:
- id
- quality
- file_type
- width
- height
- link
VideoPicture:
type: object
properties:
id:
type: integer
picture:
type: string
format: uri
nr:
type: integer
required:
- id
- picture
- nr
Video:
type: object
properties:
id:
type: integer
width:
type: integer
height:
type: integer
url:
type: string
format: uri
image:
type: string
format: uri
duration:
type: integer
user:
$ref: "#/components/schemas/VideoUser"
video_files:
type: array
items:
$ref: "#/components/schemas/VideoFile"
video_pictures:
type: array
items:
$ref: "#/components/schemas/VideoPicture"
required:
- id
- width
- height
- url
- image
- duration
- user
- video_files
- video_pictures
VideoPageResponse:
allOf:
- $ref: "#/components/schemas/Pagination"
- type: object
properties:
url:
type: string
format: uri
videos:
type: array
items:
$ref: "#/components/schemas/Video"
required:
- url
- videos
VideoSearchResponse:
allOf:
- $ref: "#/components/schemas/VideoPageResponse"
Collection:
type: object
properties:
id:
type: string
title:
type: string
description:
type: string
private:
type: boolean
media_count:
type: integer
photos_count:
type: integer
videos_count:
type: integer
required:
- id
- title
- description
- private
- media_count
- photos_count
- videos_count
CollectionPageResponse:
allOf:
- $ref: "#/components/schemas/Pagination"
- type: object
properties:
collections:
type: array
items:
$ref: "#/components/schemas/Collection"
required:
- collections
CollectionMediaPhoto:
allOf:
- $ref: "#/components/schemas/Photo"
- type: object
properties:
type:
type: string
const: Photo
required:
- type
CollectionMediaVideo:
allOf:
- $ref: "#/components/schemas/Video"
- type: object
properties:
type:
type: string
const: Video
required:
- type
CollectionMediaItem:
oneOf:
- $ref: "#/components/schemas/CollectionMediaPhoto"
- $ref: "#/components/schemas/CollectionMediaVideo"
CollectionMediaResponse:
allOf:
- $ref: "#/components/schemas/Pagination"
- type: object
properties:
id:
type: string
media:
type: array
items:
$ref: "#/components/schemas/CollectionMediaItem"
required:
- id
- media
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment