# info.description
Anonymous access to published portfolio data and opt-in blog notification subscriptions.

# paths./api/v1/resume.get.responses.200.description
Structured resume with the canonical PDF URL.

# paths./api/v1/resume.get.responses.404.description
No published resume source is available.

# paths./api/v1/blogs/{slug}.get.responses.200.description
One published blog post including its Markdown body.

# paths./api/v1/blogs/{slug}.get.responses.404.description
No published blog post has the requested slug.

# paths./api/notifications/email/subscribe.post.responses.202.description
The privacy-preserving subscription request was accepted.

# paths./api/notifications/email/subscribe.post.responses.429.description
The subscription rate limit was exceeded.

# paths./api/notifications/email/subscribe.post.responses.503.description
Email validation is temporarily unavailable.

# paths./api/notifications/email/subscribe.post.summary
Request a double-opt-in email subscription

# paths./api/notifications/email/confirm.get.parameters[].description
Single-use confirmation token from the confirmation email.

# paths./api/notifications/email/confirm.get.responses.303.description
Redirect to the blog list with confirmation status.

# paths./api/notifications/email/unsubscribe.post.parameters[].description
Signed unsubscribe token from a blog email.

# paths./api/notifications/push/config.get.responses.200.description
Public Web Push configuration and feature availability.

# paths./api/notifications/push/subscribe.post.responses.429.description
The subscription rate limit was exceeded.

# paths./api/notifications/push/subscribe.post.responses.502.description
The push service could not complete the request.

# paths./api/notifications/push/subscribe.post.responses.503.description
Web Push notifications are not configured.